widget/windows/nsBidiKeyboard.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include <stdio.h>
michael@0 8 #include "nsBidiKeyboard.h"
michael@0 9 #include "prmem.h"
michael@0 10 #include <tchar.h>
michael@0 11
michael@0 12 NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
michael@0 13
michael@0 14 nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
michael@0 15 {
michael@0 16 Reset();
michael@0 17 }
michael@0 18
michael@0 19 nsBidiKeyboard::~nsBidiKeyboard()
michael@0 20 {
michael@0 21 }
michael@0 22
michael@0 23 NS_IMETHODIMP nsBidiKeyboard::Reset()
michael@0 24 {
michael@0 25 mInitialized = false;
michael@0 26 mHaveBidiKeyboards = false;
michael@0 27 mLTRKeyboard[0] = '\0';
michael@0 28 mRTLKeyboard[0] = '\0';
michael@0 29 mCurrentLocaleName[0] = '\0';
michael@0 30 return NS_OK;
michael@0 31 }
michael@0 32
michael@0 33 NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool *aIsRTL)
michael@0 34 {
michael@0 35 *aIsRTL = false;
michael@0 36
michael@0 37 nsresult result = SetupBidiKeyboards();
michael@0 38 if (NS_FAILED(result))
michael@0 39 return result;
michael@0 40
michael@0 41 HKL currentLocale;
michael@0 42
michael@0 43 currentLocale = ::GetKeyboardLayout(0);
michael@0 44 *aIsRTL = IsRTLLanguage(currentLocale);
michael@0 45
michael@0 46 if (!::GetKeyboardLayoutNameW(mCurrentLocaleName))
michael@0 47 return NS_ERROR_FAILURE;
michael@0 48
michael@0 49 NS_ASSERTION(*mCurrentLocaleName,
michael@0 50 "GetKeyboardLayoutName return string length == 0");
michael@0 51 NS_ASSERTION((wcslen(mCurrentLocaleName) < KL_NAMELENGTH),
michael@0 52 "GetKeyboardLayoutName return string length >= KL_NAMELENGTH");
michael@0 53
michael@0 54 // The language set by the user overrides the default language for that direction
michael@0 55 if (*aIsRTL) {
michael@0 56 wcsncpy(mRTLKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
michael@0 57 mRTLKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
michael@0 58 } else {
michael@0 59 wcsncpy(mLTRKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
michael@0 60 mLTRKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
michael@0 61 }
michael@0 62
michael@0 63 NS_ASSERTION((wcslen(mRTLKeyboard) < KL_NAMELENGTH),
michael@0 64 "mLTRKeyboard has string length >= KL_NAMELENGTH");
michael@0 65 NS_ASSERTION((wcslen(mLTRKeyboard) < KL_NAMELENGTH),
michael@0 66 "mRTLKeyboard has string length >= KL_NAMELENGTH");
michael@0 67 return NS_OK;
michael@0 68 }
michael@0 69
michael@0 70 NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
michael@0 71 {
michael@0 72 NS_ENSURE_ARG_POINTER(aResult);
michael@0 73
michael@0 74 nsresult result = SetupBidiKeyboards();
michael@0 75 if (NS_FAILED(result))
michael@0 76 return result;
michael@0 77
michael@0 78 *aResult = mHaveBidiKeyboards;
michael@0 79 return NS_OK;
michael@0 80 }
michael@0 81
michael@0 82
michael@0 83 // Get the list of keyboard layouts available in the system
michael@0 84 // Set mLTRKeyboard to the first LTR keyboard in the list and mRTLKeyboard to the first RTL keyboard in the list
michael@0 85 // These defaults will be used unless the user explicitly sets something else.
michael@0 86 nsresult nsBidiKeyboard::SetupBidiKeyboards()
michael@0 87 {
michael@0 88 if (mInitialized)
michael@0 89 return mHaveBidiKeyboards ? NS_OK : NS_ERROR_FAILURE;
michael@0 90
michael@0 91 int keyboards;
michael@0 92 HKL far* buf;
michael@0 93 HKL locale;
michael@0 94 wchar_t localeName[KL_NAMELENGTH];
michael@0 95 bool isLTRKeyboardSet = false;
michael@0 96 bool isRTLKeyboardSet = false;
michael@0 97
michael@0 98 // GetKeyboardLayoutList with 0 as first parameter returns the number of keyboard layouts available
michael@0 99 keyboards = ::GetKeyboardLayoutList(0, nullptr);
michael@0 100 if (!keyboards)
michael@0 101 return NS_ERROR_FAILURE;
michael@0 102
michael@0 103 // allocate a buffer to hold the list
michael@0 104 buf = (HKL far*) PR_Malloc(keyboards * sizeof(HKL));
michael@0 105 if (!buf)
michael@0 106 return NS_ERROR_OUT_OF_MEMORY;
michael@0 107
michael@0 108 // Call again to fill the buffer
michael@0 109 if (::GetKeyboardLayoutList(keyboards, buf) != keyboards) {
michael@0 110 PR_Free(buf);
michael@0 111 return NS_ERROR_UNEXPECTED;
michael@0 112 }
michael@0 113
michael@0 114 // Go through the list and pick a default LTR and RTL keyboard layout
michael@0 115 while (keyboards--) {
michael@0 116 locale = buf[keyboards];
michael@0 117 if (IsRTLLanguage(locale)) {
michael@0 118 _snwprintf(mRTLKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
michael@0 119 LANGIDFROMLCID((DWORD_PTR)locale));
michael@0 120 isRTLKeyboardSet = true;
michael@0 121 }
michael@0 122 else {
michael@0 123 _snwprintf(mLTRKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
michael@0 124 LANGIDFROMLCID((DWORD_PTR)locale));
michael@0 125 isLTRKeyboardSet = true;
michael@0 126 }
michael@0 127 }
michael@0 128 PR_Free(buf);
michael@0 129 mInitialized = true;
michael@0 130
michael@0 131 // If there is not at least one keyboard of each directionality, Bidi
michael@0 132 // keyboard functionality will be disabled.
michael@0 133 mHaveBidiKeyboards = (isRTLKeyboardSet && isLTRKeyboardSet);
michael@0 134 if (!mHaveBidiKeyboards)
michael@0 135 return NS_ERROR_FAILURE;
michael@0 136
michael@0 137 // Get the current keyboard layout and use it for either mRTLKeyboard or
michael@0 138 // mLTRKeyboard as appropriate. If the user has many keyboard layouts
michael@0 139 // installed this prevents us from arbitrarily resetting the current
michael@0 140 // layout (bug 80274)
michael@0 141 locale = ::GetKeyboardLayout(0);
michael@0 142 if (!::GetKeyboardLayoutNameW(localeName))
michael@0 143 return NS_ERROR_FAILURE;
michael@0 144
michael@0 145 NS_ASSERTION(*localeName,
michael@0 146 "GetKeyboardLayoutName return string length == 0");
michael@0 147 NS_ASSERTION((wcslen(localeName) < KL_NAMELENGTH),
michael@0 148 "GetKeyboardLayout return string length >= KL_NAMELENGTH");
michael@0 149
michael@0 150 if (IsRTLLanguage(locale)) {
michael@0 151 wcsncpy(mRTLKeyboard, localeName, KL_NAMELENGTH);
michael@0 152 mRTLKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
michael@0 153 }
michael@0 154 else {
michael@0 155 wcsncpy(mLTRKeyboard, localeName, KL_NAMELENGTH);
michael@0 156 mLTRKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
michael@0 157 }
michael@0 158
michael@0 159 NS_ASSERTION(*mRTLKeyboard,
michael@0 160 "mLTRKeyboard has string length == 0");
michael@0 161 NS_ASSERTION(*mLTRKeyboard,
michael@0 162 "mLTRKeyboard has string length == 0");
michael@0 163
michael@0 164 return NS_OK;
michael@0 165 }
michael@0 166
michael@0 167 // Test whether the language represented by this locale identifier is a
michael@0 168 // right-to-left language, using bit 123 of the Unicode subset bitfield in
michael@0 169 // the LOCALESIGNATURE
michael@0 170 // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_63ub.asp
michael@0 171 bool nsBidiKeyboard::IsRTLLanguage(HKL aLocale)
michael@0 172 {
michael@0 173 LOCALESIGNATURE localesig;
michael@0 174 return (::GetLocaleInfoW(PRIMARYLANGID((DWORD_PTR)aLocale),
michael@0 175 LOCALE_FONTSIGNATURE,
michael@0 176 (LPWSTR)&localesig,
michael@0 177 (sizeof(localesig)/sizeof(WCHAR))) &&
michael@0 178 (localesig.lsUsb[3] & 0x08000000));
michael@0 179 }

mercurial