forked from mirrors/gecko-dev
		
	 265e672179
			
		
	
	
		265e672179
		
	
	
	
	
		
			
			# ignore-this-changeset --HG-- extra : amend_source : 4d301d3b0b8711c4692392aa76088ba7fd7d1022
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 | |
|  *
 | |
|  * This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include "nsBidiKeyboard.h"
 | |
| #include "WidgetUtils.h"
 | |
| #include "nsIWidget.h"
 | |
| #include <tchar.h>
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
 | |
| 
 | |
| nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard() { Reset(); }
 | |
| 
 | |
| nsBidiKeyboard::~nsBidiKeyboard() {}
 | |
| 
 | |
| NS_IMETHODIMP nsBidiKeyboard::Reset() {
 | |
|   mInitialized = false;
 | |
|   mHaveBidiKeyboards = false;
 | |
|   mLTRKeyboard[0] = '\0';
 | |
|   mRTLKeyboard[0] = '\0';
 | |
|   mCurrentLocaleName[0] = '\0';
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool* aIsRTL) {
 | |
|   *aIsRTL = false;
 | |
| 
 | |
|   nsresult result = SetupBidiKeyboards();
 | |
|   if (NS_FAILED(result)) return result;
 | |
| 
 | |
|   HKL currentLocale;
 | |
| 
 | |
|   currentLocale = ::GetKeyboardLayout(0);
 | |
|   *aIsRTL = IsRTLLanguage(currentLocale);
 | |
| 
 | |
|   if (!::GetKeyboardLayoutNameW(mCurrentLocaleName)) return NS_ERROR_FAILURE;
 | |
| 
 | |
|   NS_ASSERTION(*mCurrentLocaleName,
 | |
|                "GetKeyboardLayoutName return string length == 0");
 | |
|   NS_ASSERTION((wcslen(mCurrentLocaleName) < KL_NAMELENGTH),
 | |
|                "GetKeyboardLayoutName return string length >= KL_NAMELENGTH");
 | |
| 
 | |
|   // The language set by the user overrides the default language for that
 | |
|   // direction
 | |
|   if (*aIsRTL) {
 | |
|     wcsncpy(mRTLKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
 | |
|     mRTLKeyboard[KL_NAMELENGTH - 1] = '\0';  // null terminate
 | |
|   } else {
 | |
|     wcsncpy(mLTRKeyboard, mCurrentLocaleName, KL_NAMELENGTH);
 | |
|     mLTRKeyboard[KL_NAMELENGTH - 1] = '\0';  // null terminate
 | |
|   }
 | |
| 
 | |
|   NS_ASSERTION((wcslen(mRTLKeyboard) < KL_NAMELENGTH),
 | |
|                "mLTRKeyboard has string length >= KL_NAMELENGTH");
 | |
|   NS_ASSERTION((wcslen(mLTRKeyboard) < KL_NAMELENGTH),
 | |
|                "mRTLKeyboard has string length >= KL_NAMELENGTH");
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult) {
 | |
|   NS_ENSURE_ARG_POINTER(aResult);
 | |
| 
 | |
|   nsresult result = SetupBidiKeyboards();
 | |
|   if (NS_FAILED(result)) return result;
 | |
| 
 | |
|   *aResult = mHaveBidiKeyboards;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| // Get the list of keyboard layouts available in the system
 | |
| // Set mLTRKeyboard to the first LTR keyboard in the list and mRTLKeyboard to
 | |
| // the first RTL keyboard in the list These defaults will be used unless the
 | |
| // user explicitly sets something else.
 | |
| nsresult nsBidiKeyboard::SetupBidiKeyboards() {
 | |
|   if (mInitialized) return mHaveBidiKeyboards ? NS_OK : NS_ERROR_FAILURE;
 | |
| 
 | |
|   int keyboards;
 | |
|   HKL far* buf;
 | |
|   HKL locale;
 | |
|   wchar_t localeName[KL_NAMELENGTH];
 | |
|   bool isLTRKeyboardSet = false;
 | |
|   bool isRTLKeyboardSet = false;
 | |
| 
 | |
|   // GetKeyboardLayoutList with 0 as first parameter returns the number of
 | |
|   // keyboard layouts available
 | |
|   keyboards = ::GetKeyboardLayoutList(0, nullptr);
 | |
|   if (!keyboards) return NS_ERROR_FAILURE;
 | |
| 
 | |
|   // allocate a buffer to hold the list
 | |
|   buf = (HKL far*)malloc(keyboards * sizeof(HKL));
 | |
|   if (!buf) return NS_ERROR_OUT_OF_MEMORY;
 | |
| 
 | |
|   // Call again to fill the buffer
 | |
|   if (::GetKeyboardLayoutList(keyboards, buf) != keyboards) {
 | |
|     free(buf);
 | |
|     return NS_ERROR_UNEXPECTED;
 | |
|   }
 | |
| 
 | |
|   // Go through the list and pick a default LTR and RTL keyboard layout
 | |
|   while (keyboards--) {
 | |
|     locale = buf[keyboards];
 | |
|     if (IsRTLLanguage(locale)) {
 | |
|       _snwprintf(mRTLKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
 | |
|                  LANGIDFROMLCID((DWORD_PTR)locale));
 | |
|       isRTLKeyboardSet = true;
 | |
|     } else {
 | |
|       _snwprintf(mLTRKeyboard, KL_NAMELENGTH, L"%.*x", KL_NAMELENGTH - 1,
 | |
|                  LANGIDFROMLCID((DWORD_PTR)locale));
 | |
|       isLTRKeyboardSet = true;
 | |
|     }
 | |
|   }
 | |
|   free(buf);
 | |
|   mInitialized = true;
 | |
| 
 | |
|   // If there is not at least one keyboard of each directionality, Bidi
 | |
|   // keyboard functionality will be disabled.
 | |
|   mHaveBidiKeyboards = (isRTLKeyboardSet && isLTRKeyboardSet);
 | |
|   if (!mHaveBidiKeyboards) return NS_ERROR_FAILURE;
 | |
| 
 | |
|   // Get the current keyboard layout and use it for either mRTLKeyboard or
 | |
|   // mLTRKeyboard as appropriate. If the user has many keyboard layouts
 | |
|   // installed this prevents us from arbitrarily resetting the current
 | |
|   // layout (bug 80274)
 | |
|   locale = ::GetKeyboardLayout(0);
 | |
|   if (!::GetKeyboardLayoutNameW(localeName)) return NS_ERROR_FAILURE;
 | |
| 
 | |
|   NS_ASSERTION(*localeName, "GetKeyboardLayoutName return string length == 0");
 | |
|   NS_ASSERTION((wcslen(localeName) < KL_NAMELENGTH),
 | |
|                "GetKeyboardLayout return string length >= KL_NAMELENGTH");
 | |
| 
 | |
|   if (IsRTLLanguage(locale)) {
 | |
|     wcsncpy(mRTLKeyboard, localeName, KL_NAMELENGTH);
 | |
|     mRTLKeyboard[KL_NAMELENGTH - 1] = '\0';  // null terminate
 | |
|   } else {
 | |
|     wcsncpy(mLTRKeyboard, localeName, KL_NAMELENGTH);
 | |
|     mLTRKeyboard[KL_NAMELENGTH - 1] = '\0';  // null terminate
 | |
|   }
 | |
| 
 | |
|   NS_ASSERTION(*mRTLKeyboard, "mLTRKeyboard has string length == 0");
 | |
|   NS_ASSERTION(*mLTRKeyboard, "mLTRKeyboard has string length == 0");
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| // Test whether the language represented by this locale identifier is a
 | |
| //  right-to-left language, using bit 123 of the Unicode subset bitfield in
 | |
| //  the LOCALESIGNATURE
 | |
| // See
 | |
| // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_63ub.asp
 | |
| bool nsBidiKeyboard::IsRTLLanguage(HKL aLocale) {
 | |
|   LOCALESIGNATURE localesig;
 | |
|   return (::GetLocaleInfoW(PRIMARYLANGID((DWORD_PTR)aLocale),
 | |
|                            LOCALE_FONTSIGNATURE, (LPWSTR)&localesig,
 | |
|                            (sizeof(localesig) / sizeof(WCHAR))) &&
 | |
|           (localesig.lsUsb[3] & 0x08000000));
 | |
| }
 | |
| 
 | |
| // static
 | |
| void nsBidiKeyboard::OnLayoutChange() {
 | |
|   mozilla::widget::WidgetUtils::SendBidiKeyboardInfoToContent();
 | |
| }
 | |
| 
 | |
| // static
 | |
| already_AddRefed<nsIBidiKeyboard> nsIWidget::CreateBidiKeyboardInner() {
 | |
|   return do_AddRef(new nsBidiKeyboard());
 | |
| }
 |