1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "nsBidiKeyboard.h"
12 NS_IMPL_ISUPPORTS(nsBidiKeyboard
, nsIBidiKeyboard
)
14 nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
19 nsBidiKeyboard::~nsBidiKeyboard()
23 NS_IMETHODIMP
nsBidiKeyboard::Reset()
26 mHaveBidiKeyboards
= false;
27 mLTRKeyboard
[0] = '\0';
28 mRTLKeyboard
[0] = '\0';
29 mCurrentLocaleName
[0] = '\0';
33 NS_IMETHODIMP
nsBidiKeyboard::IsLangRTL(bool *aIsRTL
)
37 nsresult result
= SetupBidiKeyboards();
38 if (NS_FAILED(result
))
43 currentLocale
= ::GetKeyboardLayout(0);
44 *aIsRTL
= IsRTLLanguage(currentLocale
);
46 if (!::GetKeyboardLayoutNameW(mCurrentLocaleName
))
47 return NS_ERROR_FAILURE
;
49 NS_ASSERTION(*mCurrentLocaleName
,
50 "GetKeyboardLayoutName return string length == 0");
51 NS_ASSERTION((wcslen(mCurrentLocaleName
) < KL_NAMELENGTH
),
52 "GetKeyboardLayoutName return string length >= KL_NAMELENGTH");
54 // The language set by the user overrides the default language for that direction
56 wcsncpy(mRTLKeyboard
, mCurrentLocaleName
, KL_NAMELENGTH
);
57 mRTLKeyboard
[KL_NAMELENGTH
-1] = '\0'; // null terminate
59 wcsncpy(mLTRKeyboard
, mCurrentLocaleName
, KL_NAMELENGTH
);
60 mLTRKeyboard
[KL_NAMELENGTH
-1] = '\0'; // null terminate
63 NS_ASSERTION((wcslen(mRTLKeyboard
) < KL_NAMELENGTH
),
64 "mLTRKeyboard has string length >= KL_NAMELENGTH");
65 NS_ASSERTION((wcslen(mLTRKeyboard
) < KL_NAMELENGTH
),
66 "mRTLKeyboard has string length >= KL_NAMELENGTH");
70 NS_IMETHODIMP
nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult
)
72 NS_ENSURE_ARG_POINTER(aResult
);
74 nsresult result
= SetupBidiKeyboards();
75 if (NS_FAILED(result
))
78 *aResult
= mHaveBidiKeyboards
;
83 // Get the list of keyboard layouts available in the system
84 // Set mLTRKeyboard to the first LTR keyboard in the list and mRTLKeyboard to the first RTL keyboard in the list
85 // These defaults will be used unless the user explicitly sets something else.
86 nsresult
nsBidiKeyboard::SetupBidiKeyboards()
89 return mHaveBidiKeyboards
? NS_OK
: NS_ERROR_FAILURE
;
94 wchar_t localeName
[KL_NAMELENGTH
];
95 bool isLTRKeyboardSet
= false;
96 bool isRTLKeyboardSet
= false;
98 // GetKeyboardLayoutList with 0 as first parameter returns the number of keyboard layouts available
99 keyboards
= ::GetKeyboardLayoutList(0, nullptr);
101 return NS_ERROR_FAILURE
;
103 // allocate a buffer to hold the list
104 buf
= (HKL far
*) PR_Malloc(keyboards
* sizeof(HKL
));
106 return NS_ERROR_OUT_OF_MEMORY
;
108 // Call again to fill the buffer
109 if (::GetKeyboardLayoutList(keyboards
, buf
) != keyboards
) {
111 return NS_ERROR_UNEXPECTED
;
114 // Go through the list and pick a default LTR and RTL keyboard layout
115 while (keyboards
--) {
116 locale
= buf
[keyboards
];
117 if (IsRTLLanguage(locale
)) {
118 _snwprintf(mRTLKeyboard
, KL_NAMELENGTH
, L
"%.*x", KL_NAMELENGTH
- 1,
119 LANGIDFROMLCID((DWORD_PTR
)locale
));
120 isRTLKeyboardSet
= true;
123 _snwprintf(mLTRKeyboard
, KL_NAMELENGTH
, L
"%.*x", KL_NAMELENGTH
- 1,
124 LANGIDFROMLCID((DWORD_PTR
)locale
));
125 isLTRKeyboardSet
= true;
131 // If there is not at least one keyboard of each directionality, Bidi
132 // keyboard functionality will be disabled.
133 mHaveBidiKeyboards
= (isRTLKeyboardSet
&& isLTRKeyboardSet
);
134 if (!mHaveBidiKeyboards
)
135 return NS_ERROR_FAILURE
;
137 // Get the current keyboard layout and use it for either mRTLKeyboard or
138 // mLTRKeyboard as appropriate. If the user has many keyboard layouts
139 // installed this prevents us from arbitrarily resetting the current
140 // layout (bug 80274)
141 locale
= ::GetKeyboardLayout(0);
142 if (!::GetKeyboardLayoutNameW(localeName
))
143 return NS_ERROR_FAILURE
;
145 NS_ASSERTION(*localeName
,
146 "GetKeyboardLayoutName return string length == 0");
147 NS_ASSERTION((wcslen(localeName
) < KL_NAMELENGTH
),
148 "GetKeyboardLayout return string length >= KL_NAMELENGTH");
150 if (IsRTLLanguage(locale
)) {
151 wcsncpy(mRTLKeyboard
, localeName
, KL_NAMELENGTH
);
152 mRTLKeyboard
[KL_NAMELENGTH
-1] = '\0'; // null terminate
155 wcsncpy(mLTRKeyboard
, localeName
, KL_NAMELENGTH
);
156 mLTRKeyboard
[KL_NAMELENGTH
-1] = '\0'; // null terminate
159 NS_ASSERTION(*mRTLKeyboard
,
160 "mLTRKeyboard has string length == 0");
161 NS_ASSERTION(*mLTRKeyboard
,
162 "mLTRKeyboard has string length == 0");
167 // Test whether the language represented by this locale identifier is a
168 // right-to-left language, using bit 123 of the Unicode subset bitfield in
169 // the LOCALESIGNATURE
170 // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_63ub.asp
171 bool nsBidiKeyboard::IsRTLLanguage(HKL aLocale
)
173 LOCALESIGNATURE localesig
;
174 return (::GetLocaleInfoW(PRIMARYLANGID((DWORD_PTR
)aLocale
),
175 LOCALE_FONTSIGNATURE
,
177 (sizeof(localesig
)/sizeof(WCHAR
))) &&
178 (localesig
.lsUsb
[3] & 0x08000000));