widget/windows/nsBidiKeyboard.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/windows/nsBidiKeyboard.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,179 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + *
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include <stdio.h>
    1.11 +#include "nsBidiKeyboard.h"
    1.12 +#include "prmem.h"
    1.13 +#include <tchar.h>
    1.14 +
    1.15 +NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
    1.16 +
    1.17 +nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
    1.18 +{
    1.19 +  Reset();
    1.20 +}
    1.21 +
    1.22 +nsBidiKeyboard::~nsBidiKeyboard()
    1.23 +{
    1.24 +}
    1.25 +
    1.26 +NS_IMETHODIMP nsBidiKeyboard::Reset()
    1.27 +{
    1.28 +  mInitialized = false;
    1.29 +  mHaveBidiKeyboards = false;
    1.30 +  mLTRKeyboard[0] = '\0';
    1.31 +  mRTLKeyboard[0] = '\0';
    1.32 +  mCurrentLocaleName[0] = '\0';
    1.33 +  return NS_OK;
    1.34 +}
    1.35 +
    1.36 +NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool *aIsRTL)
    1.37 +{
    1.38 +  *aIsRTL = false;
    1.39 +
    1.40 +  nsresult result = SetupBidiKeyboards();
    1.41 +  if (NS_FAILED(result))
    1.42 +    return result;
    1.43 +
    1.44 +  HKL  currentLocale;
    1.45 + 
    1.46 +  currentLocale = ::GetKeyboardLayout(0);
    1.47 +  *aIsRTL = IsRTLLanguage(currentLocale);
    1.48 +  
    1.49 +  if (!::GetKeyboardLayoutNameW(mCurrentLocaleName))
    1.50 +    return NS_ERROR_FAILURE;
    1.51 +
    1.52 +  NS_ASSERTION(*mCurrentLocaleName, 
    1.53 +    "GetKeyboardLayoutName return string length == 0");
    1.54 +  NS_ASSERTION((wcslen(mCurrentLocaleName) < KL_NAMELENGTH), 
    1.55 +    "GetKeyboardLayoutName return string length >= KL_NAMELENGTH");
    1.56 +
    1.57 +  // The language set by the user overrides the default language for that direction
    1.58 +  if (*aIsRTL) {
    1.59 +    wcsncpy(mRTLKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
    1.60 +    mRTLKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
    1.61 +  } else {
    1.62 +    wcsncpy(mLTRKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
    1.63 +    mLTRKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
    1.64 +  }
    1.65 +
    1.66 +  NS_ASSERTION((wcslen(mRTLKeyboard) < KL_NAMELENGTH), 
    1.67 +    "mLTRKeyboard has string length >= KL_NAMELENGTH");
    1.68 +  NS_ASSERTION((wcslen(mLTRKeyboard) < KL_NAMELENGTH), 
    1.69 +    "mRTLKeyboard has string length >= KL_NAMELENGTH");
    1.70 +  return NS_OK;
    1.71 +}
    1.72 +
    1.73 +NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
    1.74 +{
    1.75 +  NS_ENSURE_ARG_POINTER(aResult);
    1.76 +
    1.77 +  nsresult result = SetupBidiKeyboards();
    1.78 +  if (NS_FAILED(result))
    1.79 +    return result;
    1.80 +
    1.81 +  *aResult = mHaveBidiKeyboards;
    1.82 +  return NS_OK;
    1.83 +}
    1.84 +
    1.85 +
    1.86 +// Get the list of keyboard layouts available in the system
    1.87 +// Set mLTRKeyboard to the first LTR keyboard in the list and mRTLKeyboard to the first RTL keyboard in the list
    1.88 +// These defaults will be used unless the user explicitly sets something else.
    1.89 +nsresult nsBidiKeyboard::SetupBidiKeyboards()
    1.90 +{
    1.91 +  if (mInitialized)
    1.92 +    return mHaveBidiKeyboards ? NS_OK : NS_ERROR_FAILURE;
    1.93 +
    1.94 +  int keyboards;
    1.95 +  HKL far* buf;
    1.96 +  HKL locale;
    1.97 +  wchar_t localeName[KL_NAMELENGTH];
    1.98 +  bool isLTRKeyboardSet = false;
    1.99 +  bool isRTLKeyboardSet = false;
   1.100 +  
   1.101 +  // GetKeyboardLayoutList with 0 as first parameter returns the number of keyboard layouts available
   1.102 +  keyboards = ::GetKeyboardLayoutList(0, nullptr);
   1.103 +  if (!keyboards)
   1.104 +    return NS_ERROR_FAILURE;
   1.105 +
   1.106 +  // allocate a buffer to hold the list
   1.107 +  buf = (HKL far*) PR_Malloc(keyboards * sizeof(HKL));
   1.108 +  if (!buf)
   1.109 +    return NS_ERROR_OUT_OF_MEMORY;
   1.110 +
   1.111 +  // Call again to fill the buffer
   1.112 +  if (::GetKeyboardLayoutList(keyboards, buf) != keyboards) {
   1.113 +    PR_Free(buf);
   1.114 +    return NS_ERROR_UNEXPECTED;
   1.115 +  }
   1.116 +
   1.117 +  // Go through the list and pick a default LTR and RTL keyboard layout
   1.118 +  while (keyboards--) {
   1.119 +    locale = buf[keyboards];
   1.120 +    if (IsRTLLanguage(locale)) {
   1.121 +      _snwprintf(mRTLKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
   1.122 +                 LANGIDFROMLCID((DWORD_PTR)locale));
   1.123 +      isRTLKeyboardSet = true;
   1.124 +    }
   1.125 +    else {
   1.126 +      _snwprintf(mLTRKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
   1.127 +                 LANGIDFROMLCID((DWORD_PTR)locale));
   1.128 +      isLTRKeyboardSet = true;
   1.129 +    }
   1.130 +  }
   1.131 +  PR_Free(buf);
   1.132 +  mInitialized = true;
   1.133 +
   1.134 +  // If there is not at least one keyboard of each directionality, Bidi
   1.135 +  // keyboard functionality will be disabled.
   1.136 +  mHaveBidiKeyboards = (isRTLKeyboardSet && isLTRKeyboardSet);
   1.137 +  if (!mHaveBidiKeyboards)
   1.138 +    return NS_ERROR_FAILURE;
   1.139 +
   1.140 +  // Get the current keyboard layout and use it for either mRTLKeyboard or
   1.141 +  // mLTRKeyboard as appropriate. If the user has many keyboard layouts
   1.142 +  // installed this prevents us from arbitrarily resetting the current
   1.143 +  // layout (bug 80274)
   1.144 +  locale = ::GetKeyboardLayout(0);
   1.145 +  if (!::GetKeyboardLayoutNameW(localeName))
   1.146 +    return NS_ERROR_FAILURE;
   1.147 +
   1.148 +  NS_ASSERTION(*localeName, 
   1.149 +    "GetKeyboardLayoutName return string length == 0");
   1.150 +  NS_ASSERTION((wcslen(localeName) < KL_NAMELENGTH), 
   1.151 +    "GetKeyboardLayout return string length >= KL_NAMELENGTH");
   1.152 +
   1.153 +  if (IsRTLLanguage(locale)) {
   1.154 +    wcsncpy(mRTLKeyboard, localeName, KL_NAMELENGTH);
   1.155 +    mRTLKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
   1.156 +  }
   1.157 +  else {
   1.158 +    wcsncpy(mLTRKeyboard, localeName, KL_NAMELENGTH);
   1.159 +    mLTRKeyboard[KL_NAMELENGTH-1] = '\0'; // null terminate
   1.160 +  }
   1.161 +
   1.162 +  NS_ASSERTION(*mRTLKeyboard, 
   1.163 +    "mLTRKeyboard has string length == 0");
   1.164 +  NS_ASSERTION(*mLTRKeyboard, 
   1.165 +    "mLTRKeyboard has string length == 0");
   1.166 +
   1.167 +  return NS_OK;
   1.168 +}
   1.169 +
   1.170 +// Test whether the language represented by this locale identifier is a
   1.171 +//  right-to-left language, using bit 123 of the Unicode subset bitfield in
   1.172 +//  the LOCALESIGNATURE
   1.173 +// See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_63ub.asp
   1.174 +bool nsBidiKeyboard::IsRTLLanguage(HKL aLocale)
   1.175 +{
   1.176 +  LOCALESIGNATURE localesig;
   1.177 +  return (::GetLocaleInfoW(PRIMARYLANGID((DWORD_PTR)aLocale),
   1.178 +                           LOCALE_FONTSIGNATURE,
   1.179 +                           (LPWSTR)&localesig,
   1.180 +                           (sizeof(localesig)/sizeof(WCHAR))) &&
   1.181 +          (localesig.lsUsb[3] & 0x08000000));
   1.182 +}

mercurial