Bug 424663 crashes [@ CalcCharacterPositionAtoW][@ imm32.dll@0x3e24] involving Chinese IME r=VYV03354+ere,sr=roc,a1906=dveditz
git-svn-id: svn://10.0.0.236/trunk@255763 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
5ab4df3384
commit
c99efa61bf
@ -209,7 +209,8 @@ PRUint32 VirtualKey::GetNativeUniChars (PRUint8 aShiftState, PRUint16* aUniChars
|
||||
|
||||
|
||||
|
||||
KeyboardLayout::KeyboardLayout ()
|
||||
KeyboardLayout::KeyboardLayout () :
|
||||
mKeyboardLayout(0), mCodePage(0)
|
||||
{
|
||||
#ifndef WINCE
|
||||
mDeadKeyTableListHead = nsnull;
|
||||
@ -361,7 +362,18 @@ KeyboardLayout::GetUniCharsWithShiftState(PRUint8 aVirtualKey,
|
||||
|
||||
void KeyboardLayout::LoadLayout (HKL aLayout)
|
||||
{
|
||||
if (mKeyboardLayout == aLayout)
|
||||
return;
|
||||
|
||||
mKeyboardLayout = aLayout;
|
||||
mIMEProperty = ::ImmGetProperty(aLayout, IGP_PROPERTY);
|
||||
|
||||
#ifndef WINCE
|
||||
WORD langID = LOWORD(aLayout);
|
||||
::GetLocaleInfoA(MAKELCID(langID, SORT_DEFAULT),
|
||||
LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(PSTR)&mCodePage, sizeof(mCodePage));
|
||||
|
||||
PRUint32 shiftState;
|
||||
BYTE kbdState [256];
|
||||
BYTE originalKbdState [256];
|
||||
@ -372,7 +384,6 @@ void KeyboardLayout::LoadLayout (HKL aLayout)
|
||||
|
||||
mActiveDeadKey = -1;
|
||||
mNumOfChars = 0;
|
||||
mKeyboardLayout = aLayout;
|
||||
|
||||
ReleaseDeadKeyTables ();
|
||||
|
||||
@ -452,6 +463,8 @@ void KeyboardLayout::LoadLayout (HKL aLayout)
|
||||
}
|
||||
|
||||
::SetKeyboardState (originalKbdState);
|
||||
#else
|
||||
mCodePage = ::GetACP();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -137,6 +137,8 @@ class KeyboardLayout
|
||||
#define NUM_OF_KEYS 50
|
||||
|
||||
HKL mKeyboardLayout;
|
||||
UINT mCodePage;
|
||||
DWORD mIMEProperty;
|
||||
|
||||
VirtualKey mVirtualKeys [NUM_OF_KEYS];
|
||||
DeadKeyTableListEntry* mDeadKeyTableListHead;
|
||||
@ -183,6 +185,10 @@ public:
|
||||
PRUint32 GetUniCharsWithShiftState(PRUint8 aVirtualKey, PRUint8 aShiftStates,
|
||||
PRUint16* aUniChars,
|
||||
PRUint32 aMaxChars) const;
|
||||
|
||||
HKL GetLayout() { return mKeyboardLayout; }
|
||||
UINT GetCodePage() { return mCodePage; }
|
||||
DWORD GetIMEProperty() { return mIMEProperty; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -312,7 +312,6 @@ PRUint32 nsWindow::sInstanceCount = 0;
|
||||
PRBool nsWindow::sIMEIsComposing = PR_FALSE;
|
||||
PRBool nsWindow::sIMEIsStatusChanged = PR_FALSE;
|
||||
|
||||
DWORD nsWindow::sIMEProperty = 0;
|
||||
nsString* nsWindow::sIMECompUnicode = NULL;
|
||||
PRUint8* nsWindow::sIMEAttributeArray = NULL;
|
||||
PRInt32 nsWindow::sIMEAttributeArrayLength = 0;
|
||||
@ -326,6 +325,10 @@ PRUnichar* nsWindow::sIMEReconvertUnicode = NULL;
|
||||
RECT* nsWindow::sIMECompCharPos = nsnull;
|
||||
PRInt32 nsWindow::sIMECaretHeight = 0;
|
||||
|
||||
PRBool nsWindow::gSwitchKeyboardLayout = PR_FALSE;
|
||||
|
||||
static KeyboardLayout gKbdLayout;
|
||||
|
||||
PRBool nsWindow::sIsInEndSession = PR_FALSE;
|
||||
|
||||
BOOL nsWindow::sIsRegistered = FALSE;
|
||||
@ -708,7 +711,7 @@ nsWindow::nsWindow() : nsBaseWidget()
|
||||
static BOOL gbInitGlobalValue = FALSE;
|
||||
if (! gbInitGlobalValue) {
|
||||
gbInitGlobalValue = TRUE;
|
||||
gKeyboardLayout = GetKeyboardLayout(0);
|
||||
gKbdLayout.LoadLayout(GetKeyboardLayout(0));
|
||||
|
||||
// mouse message of MSIME98/2000
|
||||
nsWindow::uWM_MSIME_MOUSE = ::RegisterWindowMessage(RWM_MOUSE);
|
||||
@ -735,10 +738,6 @@ nsWindow::nsWindow() : nsBaseWidget()
|
||||
}
|
||||
|
||||
|
||||
HKL nsWindow::gKeyboardLayout = 0;
|
||||
PRBool nsWindow::gSwitchKeyboardLayout = PR_FALSE;
|
||||
static KeyboardLayout gKbdLayout;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsWindow destructor
|
||||
@ -3509,10 +3508,12 @@ BOOL nsWindow::OnChar(UINT charCode, UINT aScanCode, PRUint32 aFlags)
|
||||
// Keep the characters unshifted for shortcuts and accesskeys and make sure
|
||||
// that numbers are always passed as such (among others: bugs 50255 and 351310)
|
||||
if (uniChar && (mIsControlDown || mIsAltDown)) {
|
||||
UINT virtualKeyCode = ::MapVirtualKeyEx(aScanCode, MAPVK_VSC_TO_VK, gKeyboardLayout);
|
||||
UINT virtualKeyCode = ::MapVirtualKeyEx(aScanCode, MAPVK_VSC_TO_VK,
|
||||
gKbdLayout.GetLayout());
|
||||
UINT unshiftedCharCode =
|
||||
virtualKeyCode >= '0' && virtualKeyCode <= '9' ? virtualKeyCode :
|
||||
mIsShiftDown ? ::MapVirtualKeyEx(virtualKeyCode, MAPVK_VK_TO_CHAR, gKeyboardLayout) : 0;
|
||||
mIsShiftDown ? ::MapVirtualKeyEx(virtualKeyCode, MAPVK_VK_TO_CHAR,
|
||||
gKbdLayout.GetLayout()) : 0;
|
||||
// ignore diacritics (top bit set) and key mapping errors (char code 0)
|
||||
if ((INT)unshiftedCharCode > 0)
|
||||
uniChar = unshiftedCharCode;
|
||||
@ -3581,9 +3582,8 @@ nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
||||
// This changes the state of the keyboard for the current thread only,
|
||||
// and we'll restore it soon, so this should be OK.
|
||||
::SetKeyboardState(kbdState);
|
||||
HKL oldLayout = gKeyboardLayout;
|
||||
gKeyboardLayout = loadedLayout;
|
||||
gKbdLayout.LoadLayout(gKeyboardLayout);
|
||||
HKL oldLayout = gKbdLayout.GetLayout();
|
||||
gKbdLayout.LoadLayout(loadedLayout);
|
||||
|
||||
nsAutoTArray<KeyPair,10> keySequence;
|
||||
SetupKeyModifiersSequence(&keySequence, aModifierFlags);
|
||||
@ -3602,7 +3602,8 @@ nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
||||
::SetKeyboardState(kbdState);
|
||||
SetupModKeyState();
|
||||
if (i == keySequence.Length() - 1 && aCharacters.Length() > 0) {
|
||||
UINT scanCode = ::MapVirtualKeyEx(aNativeKeyCode, MAPVK_VK_TO_VSC, gKeyboardLayout);
|
||||
UINT scanCode = ::MapVirtualKeyEx(aNativeKeyCode, MAPVK_VK_TO_VSC,
|
||||
gKbdLayout.GetLayout());
|
||||
nsFakeCharMessage msg = { aCharacters.CharAt(0), scanCode };
|
||||
OnKeyDown(key, 0, &msg);
|
||||
} else {
|
||||
@ -3623,8 +3624,7 @@ nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
||||
|
||||
// Restore old key state and layout
|
||||
::SetKeyboardState(originalKbdState);
|
||||
gKeyboardLayout = oldLayout;
|
||||
gKbdLayout.LoadLayout(gKeyboardLayout);
|
||||
gKbdLayout.LoadLayout(oldLayout);
|
||||
SetupModKeyState();
|
||||
|
||||
UnloadKeyboardLayout(loadedLayout);
|
||||
@ -4708,7 +4708,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
||||
if (WA_INACTIVE == fActive) {
|
||||
gJustGotDeactivate = PR_TRUE;
|
||||
if (mIsTopWidgetWindow)
|
||||
mLastKeyboardLayout = gKeyboardLayout;
|
||||
mLastKeyboardLayout = gKbdLayout.GetLayout();
|
||||
} else {
|
||||
gJustGotActivate = PR_TRUE;
|
||||
nsMouseEvent event(PR_TRUE, NS_MOUSE_ACTIVATE, this,
|
||||
@ -5000,7 +5000,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
||||
break;
|
||||
|
||||
case WM_INPUTLANGCHANGE:
|
||||
result = OnInputLangChange((HKL)lParam, aRetValue);
|
||||
result = OnInputLangChange((HKL)lParam);
|
||||
break;
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
@ -6432,6 +6432,8 @@ NS_METHOD nsWindow::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX itABC v5.30 on Vista is E0210804. Probably, we should not use these
|
||||
// values for checking the current IME.
|
||||
#define ZH_CN_INTELLEGENT_ABC_IME ((HKL)0xe0040804L)
|
||||
#define ZH_CN_MS_PINYIN_IME_3_0 ((HKL)0xe00e0804L)
|
||||
#define ZH_CN_NEIMA_IME ((HKL)0xe0050804L)
|
||||
@ -6495,10 +6497,10 @@ nsWindow::HandleTextEvent(HIMC hIMEContext,PRBool aCheckAttr)
|
||||
|
||||
::ImmSetCandidateWindow(hIMEContext, &candForm);
|
||||
|
||||
// somehow the "Intellegent ABC IME" in Simplified Chinese
|
||||
// somehow the "Intelligent ABC IME" in Simplified Chinese
|
||||
// window listen to the caret position to decide where to put the
|
||||
// candidate window
|
||||
if (gKeyboardLayout == ZH_CN_INTELLEGENT_ABC_IME)
|
||||
if (gKbdLayout.GetLayout() == ZH_CN_INTELLEGENT_ABC_IME)
|
||||
{
|
||||
CreateCaret(mWnd, nsnull, 1, 1);
|
||||
SetCaretPos(candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
|
||||
@ -6572,7 +6574,7 @@ nsWindow::HandleStartComposition(HIMC hIMEContext)
|
||||
printf("Candidate window position: x=%d, y=%d\n", candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
|
||||
#endif
|
||||
|
||||
if (!gPinYinIMECaretCreated && PINYIN_IME_ON_XP(gKeyboardLayout))
|
||||
if (!gPinYinIMECaretCreated && PINYIN_IME_ON_XP(gKbdLayout.GetLayout()))
|
||||
{
|
||||
gPinYinIMECaretCreated = CreateCaret(mWnd, nsnull, 1, 1);
|
||||
SetCaretPos(candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
|
||||
@ -6709,17 +6711,12 @@ nsWindow::GetTextRangeList(PRUint32* textRangeListLengthResult,nsTextRangeArray*
|
||||
|
||||
|
||||
//==========================================================================
|
||||
BOOL nsWindow::OnInputLangChange(HKL aHKL, LRESULT *oRetValue)
|
||||
BOOL nsWindow::OnInputLangChange(HKL aHKL)
|
||||
{
|
||||
#ifdef KE_DEBUG
|
||||
printf("OnInputLanguageChange\n");
|
||||
#endif
|
||||
|
||||
if (gKeyboardLayout != aHKL)
|
||||
{
|
||||
gKeyboardLayout = aHKL;
|
||||
gKbdLayout.LoadLayout(gKeyboardLayout);
|
||||
}
|
||||
gKbdLayout.LoadLayout(aHKL);
|
||||
|
||||
ResetInputState();
|
||||
|
||||
@ -6787,6 +6784,21 @@ void nsWindow::GetCompositionString(HIMC aHIMC, DWORD aIndex, nsString* aStrUnic
|
||||
aStrUnicode->SetLength(lRtn);
|
||||
}
|
||||
|
||||
PRBool nsWindow::ConvertToANSIString(const nsAFlatString& aStr, UINT aCodePage,
|
||||
nsACString& aANSIStr)
|
||||
{
|
||||
int len = ::WideCharToMultiByte(aCodePage, 0,
|
||||
(LPCWSTR)aStr.get(), aStr.Length(),
|
||||
NULL, 0, NULL, NULL);
|
||||
NS_ENSURE_TRUE(len >= 0, PR_FALSE);
|
||||
|
||||
if (!EnsureStringLength(aANSIStr, len))
|
||||
return PR_FALSE;
|
||||
::WideCharToMultiByte(aCodePage, 0, (LPCWSTR)aStr.get(), aStr.Length(),
|
||||
(LPSTR)aANSIStr.BeginWriting(), len, NULL, NULL);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
BOOL nsWindow::OnIMEComposition(LPARAM aGCS)
|
||||
{
|
||||
@ -6874,29 +6886,61 @@ BOOL nsWindow::OnIMEComposition(LPARAM aGCS)
|
||||
//--------------------------------------------------------
|
||||
// 2. Get GCS_COMPCLAUSE
|
||||
//--------------------------------------------------------
|
||||
long compClauseLen, compClauseLen2;
|
||||
compClauseLen = ::ImmGetCompositionStringW(hIMEContext, GCS_COMPCLAUSE, NULL, 0);
|
||||
long compClauseArrayByteCount =
|
||||
::ImmGetCompositionStringW(hIMEContext, GCS_COMPCLAUSE, NULL, 0);
|
||||
#ifdef DEBUG_IME
|
||||
printf("GCS_COMPCLAUSE compClauseLen = %d\n", compClauseLen);
|
||||
printf("GCS_COMPCLAUSE compClauseArrayByteCount = %d\n",
|
||||
compClauseArrayByteCount);
|
||||
#endif
|
||||
compClauseLen = compClauseLen / sizeof(PRUint32);
|
||||
|
||||
if (compClauseLen > sIMECompClauseArraySize) {
|
||||
long compClauseArrayLength = compClauseArrayByteCount / sizeof(PRUint32);
|
||||
if (compClauseArrayLength > 0) {
|
||||
if (compClauseArrayByteCount > sIMECompClauseArraySize) {
|
||||
if (sIMECompClauseArray)
|
||||
delete [] sIMECompClauseArray;
|
||||
// Allocate some extra space to avoid reallocations.
|
||||
sIMECompClauseArray = new PRUint32[compClauseLen + 32];
|
||||
sIMECompClauseArraySize = compClauseLen + 32;
|
||||
PRInt32 arrayLength = compClauseArrayLength + 32;
|
||||
sIMECompClauseArray = new PRUint32[arrayLength];
|
||||
sIMECompClauseArraySize = arrayLength * sizeof(PRUint32);
|
||||
}
|
||||
|
||||
compClauseLen2 = ::ImmGetCompositionStringW(hIMEContext, GCS_COMPCLAUSE, sIMECompClauseArray,
|
||||
sIMECompClauseArraySize * sizeof(PRUint32));
|
||||
// Intelligent ABC IME (Simplified Chinese IME, the code page is 936)
|
||||
// will crash in ImmGetCompositionStringW for GCS_COMPCLAUSE (bug 424663).
|
||||
// See comment 35 of the bug for the detail. Therefore, we should use A
|
||||
// API for it, however, we should not kill Unicode support on all IMEs.
|
||||
PRBool useA_API = !(gKbdLayout.GetIMEProperty() & IME_PROP_UNICODE);
|
||||
|
||||
compClauseLen2 = compClauseLen2 / sizeof(PRUint32);
|
||||
NS_ASSERTION(compClauseLen2 == compClauseLen, "strange result");
|
||||
if (compClauseLen > compClauseLen2)
|
||||
compClauseLen = compClauseLen2;
|
||||
sIMECompClauseArrayLength = compClauseLen;
|
||||
long compClauseArrayByteCount2 = useA_API ?
|
||||
::ImmGetCompositionStringA(hIMEContext, GCS_COMPCLAUSE,
|
||||
sIMECompClauseArray,
|
||||
sIMECompClauseArraySize) :
|
||||
::ImmGetCompositionStringW(hIMEContext, GCS_COMPCLAUSE,
|
||||
sIMECompClauseArray,
|
||||
sIMECompClauseArraySize);
|
||||
NS_ASSERTION(compClauseArrayByteCount2 == compClauseArrayByteCount,
|
||||
"strange result");
|
||||
if (compClauseArrayByteCount > compClauseArrayByteCount2)
|
||||
compClauseArrayLength = compClauseArrayByteCount2 / sizeof(PRUint32);
|
||||
|
||||
if (useA_API) {
|
||||
// Convert each values of sIMECompClauseArray. The values mean offset of
|
||||
// the clauses in ANSI string. But we need the values in Unicode string.
|
||||
nsCAutoString compANSIStr;
|
||||
if (ConvertToANSIString(*sIMECompUnicode,
|
||||
gKbdLayout.GetCodePage(), compANSIStr)) {
|
||||
PRUint32 maxlen = compANSIStr.Length();
|
||||
sIMECompClauseArray[0] = 0; // first value must be 0
|
||||
for (PRInt32 i = 1; i < compClauseArrayLength; i++) {
|
||||
PRUint32 len = PR_MIN(sIMECompClauseArray[i], maxlen);
|
||||
sIMECompClauseArray[i] =
|
||||
::MultiByteToWideChar(gKbdLayout.GetCodePage(), MB_PRECOMPOSED,
|
||||
(LPCSTR)compANSIStr.get(), len, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// compClauseArrayLength may be negative. I.e., ImmGetCompositionStringW
|
||||
// may return an error code.
|
||||
sIMECompClauseArrayLength = PR_MAX(0, compClauseArrayLength);
|
||||
|
||||
//--------------------------------------------------------
|
||||
// 3. Get GCS_COMPATTR
|
||||
@ -6912,12 +6956,15 @@ BOOL nsWindow::OnIMEComposition(LPARAM aGCS)
|
||||
if (sIMEAttributeArray)
|
||||
delete [] sIMEAttributeArray;
|
||||
// Allocate some extra space to avoid reallocations.
|
||||
sIMEAttributeArray = new PRUint8[attrStrLen + 64];
|
||||
sIMEAttributeArraySize = attrStrLen + 64;
|
||||
PRInt32 arrayLength = attrStrLen + 64;
|
||||
sIMEAttributeArray = new PRUint8[arrayLength];
|
||||
sIMEAttributeArraySize = arrayLength * sizeof(PRUint8);
|
||||
}
|
||||
attrStrLen = ::ImmGetCompositionStringW(hIMEContext, GCS_COMPATTR, sIMEAttributeArray, sIMEAttributeArraySize);
|
||||
|
||||
sIMEAttributeArrayLength = attrStrLen;
|
||||
// attrStrLen may be negative. I.e., ImmGetCompositionStringW may return an
|
||||
// error code.
|
||||
sIMEAttributeArrayLength = PR_MAX(0, attrStrLen);
|
||||
|
||||
//--------------------------------------------------------
|
||||
// 4. Get GCS_CURSOPOS
|
||||
@ -6967,12 +7014,7 @@ BOOL nsWindow::OnIMEEndComposition()
|
||||
printf("OnIMEEndComposition\n");
|
||||
#endif
|
||||
if (sIMEIsComposing) {
|
||||
HIMC hIMEContext;
|
||||
|
||||
if (sIMEProperty & (IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET))
|
||||
return PR_FALSE;
|
||||
|
||||
hIMEContext = ::ImmGetContext(mWnd);
|
||||
HIMC hIMEContext = ::ImmGetContext(mWnd);
|
||||
if (hIMEContext==NULL)
|
||||
return PR_TRUE;
|
||||
|
||||
@ -7278,12 +7320,7 @@ BOOL nsWindow::OnIMEStartComposition()
|
||||
#ifdef DEBUG_IME
|
||||
printf("OnIMEStartComposition\n");
|
||||
#endif
|
||||
HIMC hIMEContext;
|
||||
|
||||
if (sIMEProperty & (IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET))
|
||||
return PR_FALSE;
|
||||
|
||||
hIMEContext = ::ImmGetContext(mWnd);
|
||||
HIMC hIMEContext = ::ImmGetContext(mWnd);
|
||||
if (hIMEContext == NULL)
|
||||
return PR_TRUE;
|
||||
|
||||
|
||||
@ -323,7 +323,7 @@ protected:
|
||||
UINT MapFromNativeToDOM(UINT aNativeKeyCode);
|
||||
|
||||
|
||||
BOOL OnInputLangChange(HKL aHKL, LRESULT *oResult);
|
||||
BOOL OnInputLangChange(HKL aHKL);
|
||||
BOOL OnIMEChar(BYTE aByte1, BYTE aByte2, LPARAM aKeyState);
|
||||
BOOL OnIMEComposition(LPARAM aGCS);
|
||||
BOOL OnIMECompositionFull();
|
||||
@ -340,6 +340,9 @@ protected:
|
||||
void ResolveIMECaretPos(nsWindow* aClient,
|
||||
nsRect& aEventResult,
|
||||
nsRect& aResult);
|
||||
PRBool ConvertToANSIString(const nsAFlatString& aStr,
|
||||
UINT aCodePage,
|
||||
nsACString& aANSIStr);
|
||||
|
||||
virtual PRBool DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode,
|
||||
const nsTArray<nsAlternativeCharCode>* aAlternativeChars,
|
||||
@ -396,7 +399,6 @@ protected:
|
||||
static PRBool sIMEIsComposing;
|
||||
static PRBool sIMEIsStatusChanged;
|
||||
|
||||
static DWORD sIMEProperty;
|
||||
static nsString* sIMECompUnicode;
|
||||
static PRUint8* sIMEAttributeArray;
|
||||
static PRInt32 sIMEAttributeArrayLength;
|
||||
@ -466,7 +468,6 @@ protected:
|
||||
HIMC mOldIMC;
|
||||
PRUint32 mIMEEnabled;
|
||||
|
||||
static HKL gKeyboardLayout;
|
||||
static PRBool gSwitchKeyboardLayout;
|
||||
|
||||
HKL mLastKeyboardLayout;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user