/*----------------------------------------------------------------------------*/ BOOL TImm::UnlockIMC(HIMC hImc) { if(_ImmUnlockIMC == NULL) { return FALSE; } else { return _ImmUnlockIMC(hImc); } }
// Obtain the reading string upon WM_IME_NOTIFY/INM_PRIVATE notification. void CIME::GetPrivateReadingString() { DWORD dwId = GetImeId(); if(!dwId) { s_bShowReadingWindow = false; return; } HIMC hImc; hImc = ImmGetContext(UIGetHWND()); if(!hImc) { s_bShowReadingWindow = false; return; } DWORD dwReadingStrLen = 0; DWORD dwErr = 0; WCHAR *pwszReadingStringBuffer = NULL; // Buffer for when the IME supports GetReadingString() WCHAR *wstr = 0; bool bUnicodeIme = false; // Whether the IME context component is Unicode. INPUTCONTEXT *lpIC = NULL; if(_GetReadingString) { UINT uMaxUiLen; BOOL bVertical; // Obtain the reading string size dwReadingStrLen = _GetReadingString(hImc, 0, NULL, (PINT)&dwErr, &bVertical, &uMaxUiLen); if(dwReadingStrLen) { wstr = pwszReadingStringBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * dwReadingStrLen); if(!pwszReadingStringBuffer) { // Out of memory. Exit. _ImmReleaseContext(UIGetHWND(), hImc); return; } // Obtain the reading string dwReadingStrLen = _GetReadingString(hImc, dwReadingStrLen, wstr, (PINT)&dwErr, &bVertical, &uMaxUiLen); } s_bHorizontalReading = !bVertical; bUnicodeIme = true; } else { // IMEs that doesn't implement Reading String API lpIC = _ImmLockIMC(hImc); LPBYTE p = 0; switch(dwId) { case IMEID_CHT_VER42: // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98 case IMEID_CHT_VER43: // New(Phonetic/ChanJie)IME98a : 4.3.x.x // WinMe, Win2k case IMEID_CHT_VER44: // New ChanJie IME98b : 4.4.x.x // WinXP p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 24); if(!p) break; dwReadingStrLen = *(DWORD *)(p + 7 * 4 + 32 * 4); dwErr = *(DWORD *)(p + 8 * 4 + 32 * 4); wstr = (WCHAR *)(p + 56); bUnicodeIme = true; break; case IMEID_CHT_VER50: // 5.0.x.x // WinME p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 3 * 4); if(!p) break; p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4 + 4*2); if(!p) break; dwReadingStrLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16); dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 + 1*4); wstr = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4); bUnicodeIme = false; break; case IMEID_CHT_VER51: // 5.1.x.x // IME2002(w/OfficeXP) case IMEID_CHT_VER52: // 5.2.x.x // (w/whistler) case IMEID_CHS_VER53: // 5.3.x.x // SCIME2k or MSPY3 (w/OfficeXP and Whistler) p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 4); if(!p) break; p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4); if(!p) break; dwReadingStrLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2); dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2 + 1*4); wstr = (WCHAR *) (p + 1*4 + (16*2+2*4) + 5*4); bUnicodeIme = true; break; // the code tested only with Win 98 SE (MSPY 1.5/ ver 4.1.0.21) case IMEID_CHS_VER41: { int nOffset; nOffset = (GetImeId(1) >= 0x00000002) ? 8 : 7; p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + nOffset * 4); if(!p) break; dwReadingStrLen = *(DWORD *)(p + 7*4 + 16*2*4); dwErr = *(DWORD *)(p + 8*4 + 16*2*4); dwErr = __min(dwErr, dwReadingStrLen); wstr = (WCHAR *)(p + 6*4 + 16*2*1); bUnicodeIme = true; break; } case IMEID_CHS_VER42: // 4.2.x.x // SCIME98 or MSPY2 (w/Office2k, Win2k, WinME, etc) { OSVERSIONINFOW osi; osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); GetVersionExW(&osi); int nTcharSize = (osi.dwPlatformId == VER_PLATFORM_WIN32_NT) ? sizeof(WCHAR) : sizeof(char); p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 1*4 + 1*4 + 6*4); if(!p) break; dwReadingStrLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize); dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize + 1*4); wstr = (WCHAR *) (p + 1*4 + (16*2+2*4) + 5*4); bUnicodeIme = (osi.dwPlatformId == VER_PLATFORM_WIN32_NT) ? true : false; } } // switch } // Copy the reading string to the candidate list first s_CandList.awszCandidate[0][0] = 0; s_CandList.awszCandidate[1][0] = 0; s_CandList.awszCandidate[2][0] = 0; s_CandList.awszCandidate[3][0] = 0; s_CandList.dwCount = dwReadingStrLen; s_CandList.dwSelection = (DWORD)-1; // do not select any char if(bUnicodeIme) { UINT i; for(i = 0; i < dwReadingStrLen; ++i) // dwlen > 0, if known IME { if(dwErr <= i && s_CandList.dwSelection == (DWORD)-1) { // select error char s_CandList.dwSelection = i; } s_CandList.awszCandidate[i][0] = wstr[i]; s_CandList.awszCandidate[i][1] = 0; } s_CandList.awszCandidate[i][0] = 0; } else { char *p = (char *)wstr; DWORD i, j; for(i = 0, j = 0; i < dwReadingStrLen; ++i, ++j) // dwlen > 0, if known IME { if(dwErr <= i && s_CandList.dwSelection == (DWORD)-1) { s_CandList.dwSelection = j; } // Obtain the current code page WCHAR wszCodePage[8]; UINT uCodePage = CP_ACP; // Default code page if(GetLocaleInfoW(MAKELCID(GetLanguage(), SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, wszCodePage, sizeof(wszCodePage)/sizeof(wszCodePage[0]))) { uCodePage = wcstoul(wszCodePage, NULL, 0); } MultiByteToWideChar(uCodePage, 0, p + i, IsDBCSLeadByteEx(uCodePage, p[i]) ? 2 : 1, s_CandList.awszCandidate[j], 1); if(IsDBCSLeadByteEx(uCodePage, p[i])) ++i; } s_CandList.awszCandidate[j][0] = 0; s_CandList.dwCount = j; } if(!_GetReadingString) { _ImmUnlockIMCC(lpIC->hPrivate); _ImmUnlockIMC(hImc); GetReadingWindowOrientation(dwId); } _ImmReleaseContext(UIGetHWND(), hImc); if(pwszReadingStringBuffer) HeapFree(GetProcessHeap(), 0, pwszReadingStringBuffer); // Copy the string to the reading string buffer if(s_CandList.dwCount > 0) s_bShowReadingWindow = true; else s_bShowReadingWindow = false; if(s_bHorizontalReading) { s_CandList.nReadingError = -1; s_wstrReadingString.clear(); for(UINT i = 0; i < s_CandList.dwCount; ++i) { if(s_CandList.dwSelection == i) s_CandList.nReadingError = s_wstrReadingString.length(); s_wstrReadingString+=s_CandList.awszCandidate[i]; } } s_CandList.dwPageSize = MAX_CANDLIST; }