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

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     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/. */
     7 #include <stdio.h>
     8 #include "nsBidiKeyboard.h"
     9 #include "prmem.h"
    10 #include <tchar.h>
    12 NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
    14 nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
    15 {
    16   Reset();
    17 }
    19 nsBidiKeyboard::~nsBidiKeyboard()
    20 {
    21 }
    23 NS_IMETHODIMP nsBidiKeyboard::Reset()
    24 {
    25   mInitialized = false;
    26   mHaveBidiKeyboards = false;
    27   mLTRKeyboard[0] = '\0';
    28   mRTLKeyboard[0] = '\0';
    29   mCurrentLocaleName[0] = '\0';
    30   return NS_OK;
    31 }
    33 NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool *aIsRTL)
    34 {
    35   *aIsRTL = false;
    37   nsresult result = SetupBidiKeyboards();
    38   if (NS_FAILED(result))
    39     return result;
    41   HKL  currentLocale;
    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
    55   if (*aIsRTL) {
    56     wcsncpy(mRTLKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
    57     mRTLKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
    58   } else {
    59     wcsncpy(mLTRKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
    60     mLTRKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
    61   }
    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");
    67   return NS_OK;
    68 }
    70 NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
    71 {
    72   NS_ENSURE_ARG_POINTER(aResult);
    74   nsresult result = SetupBidiKeyboards();
    75   if (NS_FAILED(result))
    76     return result;
    78   *aResult = mHaveBidiKeyboards;
    79   return NS_OK;
    80 }
    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()
    87 {
    88   if (mInitialized)
    89     return mHaveBidiKeyboards ? NS_OK : NS_ERROR_FAILURE;
    91   int keyboards;
    92   HKL far* buf;
    93   HKL locale;
    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);
   100   if (!keyboards)
   101     return NS_ERROR_FAILURE;
   103   // allocate a buffer to hold the list
   104   buf = (HKL far*) PR_Malloc(keyboards * sizeof(HKL));
   105   if (!buf)
   106     return NS_ERROR_OUT_OF_MEMORY;
   108   // Call again to fill the buffer
   109   if (::GetKeyboardLayoutList(keyboards, buf) != keyboards) {
   110     PR_Free(buf);
   111     return NS_ERROR_UNEXPECTED;
   112   }
   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;
   121     }
   122     else {
   123       _snwprintf(mLTRKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
   124                  LANGIDFROMLCID((DWORD_PTR)locale));
   125       isLTRKeyboardSet = true;
   126     }
   127   }
   128   PR_Free(buf);
   129   mInitialized = 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
   153   }
   154   else {
   155     wcsncpy(mLTRKeyboard, localeName, KL_NAMELENGTH);
   156     mLTRKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
   157   }
   159   NS_ASSERTION(*mRTLKeyboard, 
   160     "mLTRKeyboard has string length == 0");
   161   NS_ASSERTION(*mLTRKeyboard, 
   162     "mLTRKeyboard has string length == 0");
   164   return NS_OK;
   165 }
   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)
   172 {
   173   LOCALESIGNATURE localesig;
   174   return (::GetLocaleInfoW(PRIMARYLANGID((DWORD_PTR)aLocale),
   175                            LOCALE_FONTSIGNATURE,
   176                            (LPWSTR)&localesig,
   177                            (sizeof(localesig)/sizeof(WCHAR))) &&
   178           (localesig.lsUsb[3] & 0x08000000));
   179 }

mercurial