Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

ctxtinfo.c

Go to the documentation of this file.
00001 /**************************************************************************\ 00002 * Module Name: ctxtinfo.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Get/set routines of various Input context information for imm32.dll 00007 * 00008 * History: 00009 * 26-Feb-1996 wkwok 00010 \**************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 // Helper function: 00016 // Converts RECONVERTSTRING structure between ANSI and UNICODE. 00017 extern DWORD ImmReconversionWorker(LPRECONVERTSTRING lpRecTo, LPRECONVERTSTRING lpRecFrom, BOOL bToAnsi, DWORD dwCodePage); 00018 00019 00020 int UnicodeToMultiByteSize(DWORD dwCodePage, LPCWSTR pwstr) 00021 { 00022 char dummy[2], *lpszDummy = dummy; 00023 return WCSToMBEx((WORD)dwCodePage, pwstr, 1, &lpszDummy, sizeof(WCHAR), FALSE); 00024 } 00025 00026 00027 /***************************************************************************\ 00028 * ImmGetCompositionStringA 00029 * 00030 * Query composition string information specified by dwIndex. 00031 * 00032 * History: 00033 * 28-Feb-1995 wkwok Created 00034 \***************************************************************************/ 00035 00036 LONG WINAPI ImmGetCompositionStringA( 00037 HIMC hImc, 00038 DWORD dwIndex, 00039 LPVOID lpBuf, 00040 DWORD dwBufLen) 00041 { 00042 PCLIENTIMC pClientImc; 00043 PINPUTCONTEXT pInputContext; 00044 PCOMPOSITIONSTRING pCompStr; 00045 BOOL fAnsi; 00046 LONG lRet = 0; 00047 DWORD dwCodePage; 00048 00049 if (dwBufLen != 0 && lpBuf == NULL) { 00050 RIPMSG0(RIP_WARNING, "ImmGetCompositionStringW: NULL lpBuf."); 00051 return lRet; 00052 } 00053 00054 pClientImc = ImmLockClientImc(hImc); 00055 if (pClientImc == NULL) { 00056 RIPMSG1(RIP_WARNING, 00057 "ImmGetCompositionStringA: Invalid hImc %lx.", hImc); 00058 return lRet; 00059 } 00060 00061 fAnsi = !TestICF(pClientImc, IMCF_UNICODE); 00062 dwCodePage = CImcCodePage(pClientImc); 00063 00064 ImmUnlockClientImc(pClientImc); 00065 00066 pInputContext = ImmLockIMC(hImc); 00067 if (pInputContext == NULL) { 00068 RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hImc %lx failed.", hImc); 00069 return lRet; 00070 } 00071 00072 pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr); 00073 if (pCompStr == NULL) { 00074 RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hCompStr %x failed", 00075 pInputContext->hCompStr); 00076 ImmUnlockIMC(hImc); 00077 return lRet; 00078 } 00079 00080 lRet = InternalGetCompositionStringA(pCompStr, dwIndex, 00081 lpBuf, dwBufLen, fAnsi, dwCodePage); 00082 00083 ImmUnlockIMCC(pInputContext->hCompStr); 00084 ImmUnlockIMC(hImc); 00085 00086 return lRet; 00087 } 00088 00089 00090 /***************************************************************************\ 00091 * ImmGetCompositionStringA 00092 * 00093 * Query composition string information specified by dwIndex. 00094 * 00095 * History: 00096 * 28-Feb-1995 wkwok Created 00097 \***************************************************************************/ 00098 00099 LONG WINAPI ImmGetCompositionStringW( 00100 HIMC hImc, 00101 DWORD dwIndex, 00102 LPVOID lpBuf, 00103 DWORD dwBufLen) 00104 { 00105 PCLIENTIMC pClientImc; 00106 PINPUTCONTEXT pInputContext; 00107 PCOMPOSITIONSTRING pCompStr; 00108 BOOL fAnsi; 00109 LONG lRet = 0; 00110 DWORD dwCodePage; 00111 00112 if (dwBufLen != 0 && lpBuf == NULL) { 00113 RIPMSG0(RIP_WARNING, "ImmGetCompositionStringW: NULL lpBuf."); 00114 return lRet; 00115 } 00116 00117 pClientImc = ImmLockClientImc(hImc); 00118 if (pClientImc == NULL) { 00119 RIPMSG1(RIP_WARNING, 00120 "ImmGetCompositionStringW: Invalid hImc %lx.", hImc); 00121 return lRet; 00122 } 00123 00124 fAnsi = !TestICF(pClientImc, IMCF_UNICODE); 00125 dwCodePage = CImcCodePage(pClientImc); 00126 00127 ImmUnlockClientImc(pClientImc); 00128 00129 pInputContext = ImmLockIMC(hImc); 00130 if (pInputContext == NULL) { 00131 RIPMSG1(RIP_WARNING, "ImmGetCompositionStringW: Lock hImc %lx failed.", hImc); 00132 return lRet; 00133 } 00134 00135 pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr); 00136 if (pCompStr == NULL) { 00137 RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hCompStr %x failed", 00138 pInputContext->hCompStr); 00139 ImmUnlockIMC(hImc); 00140 return lRet; 00141 } 00142 00143 lRet = InternalGetCompositionStringW(pCompStr, dwIndex, 00144 lpBuf, dwBufLen, fAnsi, dwCodePage); 00145 00146 ImmUnlockIMCC(pInputContext->hCompStr); 00147 ImmUnlockIMC(hImc); 00148 00149 return lRet; 00150 } 00151 00152 00153 /***************************************************************************\ 00154 * ImmSetCompositionStringA 00155 * 00156 * Set composition string information specified by dwIndex. 00157 * 00158 * History: 00159 * 28-Feb-1995 wkwok Created 00160 \***************************************************************************/ 00161 00162 BOOL WINAPI ImmSetCompositionStringA( 00163 HIMC hImc, 00164 DWORD dwIndex, 00165 LPVOID lpComp, 00166 DWORD dwCompLen, 00167 LPVOID lpRead, 00168 DWORD dwReadLen) 00169 { 00170 return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp, 00171 dwCompLen, lpRead, dwReadLen, TRUE); 00172 } 00173 00174 00175 /***************************************************************************\ 00176 * ImmSetCompositionStringW 00177 * 00178 * Set composition string information specified by dwIndex. 00179 * 00180 * History: 00181 * 28-Feb-1995 wkwok Created 00182 \***************************************************************************/ 00183 00184 BOOL WINAPI ImmSetCompositionStringW( 00185 HIMC hImc, 00186 DWORD dwIndex, 00187 LPVOID lpComp, 00188 DWORD dwCompLen, 00189 LPVOID lpRead, 00190 DWORD dwReadLen) 00191 { 00192 return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp, 00193 dwCompLen, lpRead, dwReadLen, FALSE); 00194 } 00195 00196 00197 LONG CompositionString( 00198 HIMC hImc, 00199 PINPUTCONTEXT *ppInputContext, 00200 PCOMPOSITIONSTRING *ppCompStr, 00201 BOOL fCheckSize) 00202 { 00203 PINPUTCONTEXT pInputContext; 00204 PCOMPOSITIONSTRING pCompStr; 00205 00206 pInputContext = ImmLockIMC(hImc); 00207 if (!pInputContext) { 00208 RIPMSG1(RIP_WARNING, "CompositionString: Lock hImc %lx failed.", hImc); 00209 return (LONG)IMM_ERROR_GENERAL; 00210 } 00211 00212 if (!pInputContext->hCompStr) { 00213 ImmUnlockIMC(hImc); 00214 return (LONG)IMM_ERROR_NODATA; 00215 } 00216 00217 pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr); 00218 if (!pCompStr) { 00219 RIPMSG1(RIP_WARNING, 00220 "CompositionString: Lock hCompStr %lx failed.", pInputContext->hCompStr); 00221 ImmUnlockIMC(hImc); 00222 return (LONG)IMM_ERROR_GENERAL; 00223 } 00224 00225 if (fCheckSize && pCompStr->dwSize < sizeof(COMPOSITIONSTRING)) { 00226 RIPMSG0(RIP_WARNING, "CompositionString: no composition string."); 00227 ImmUnlockIMCC(pInputContext->hCompStr); 00228 ImmUnlockIMC(hImc); 00229 return (LONG)IMM_ERROR_NODATA; 00230 } 00231 00232 *ppInputContext = pInputContext; 00233 *ppCompStr = pCompStr; 00234 00235 return (1); 00236 } 00237 00238 00239 BOOL CheckAttribute( 00240 LPBYTE lpComp, // the attr from apps 00241 DWORD dwCompLen, // the attr length from apps 00242 LPBYTE lpAttr, // the attr from IMC 00243 DWORD dwAttrLen, // the attr length from IMC 00244 LPDWORD lpClause, // the clause from IMC 00245 DWORD dwClauseLen) // the clause length from IMC 00246 { 00247 DWORD dwCnt; 00248 DWORD dwBound; 00249 BYTE bAttr; 00250 00251 UNREFERENCED_PARAMETER(dwClauseLen); 00252 00253 if (!lpClause) { 00254 RIPMSG0(RIP_WARNING, "CheckAttribute: no Clause. Pass it to IME."); 00255 return (TRUE); 00256 } 00257 00258 if (!lpAttr) { 00259 RIPMSG0(RIP_WARNING, "CheckAttribute: no Attr. Not pass it to IME."); 00260 return (FALSE); 00261 } 00262 00263 if (dwCompLen != dwAttrLen) { 00264 RIPMSG0(RIP_WARNING, "CheckAttribute: wrong length. Not pass it to IME."); 00265 return (FALSE); 00266 } 00267 00268 /* 00269 * The attr. of chars of one clause have to be same. 00270 */ 00271 while (*lpClause < dwCompLen) { 00272 dwBound = *(lpClause+1) - *lpClause; 00273 bAttr = *lpComp++; 00274 for (dwCnt = 1; dwCnt < dwBound; dwCnt++) 00275 if (bAttr != *lpComp++) { 00276 RIPMSG0(RIP_WARNING, 00277 "CheckAttribute: mismatch clause att. Not Pass it to IME"); 00278 return (FALSE); 00279 } 00280 lpClause++; 00281 } 00282 00283 return (TRUE); 00284 } 00285 00286 00287 BOOL CheckClause( 00288 LPDWORD lpComp, // the clause from apps 00289 DWORD dwCompLen, // the clause length from apps 00290 LPDWORD lpClause, // the clause from IMC 00291 DWORD dwClauseLen) // the clause length from IMC 00292 { 00293 UINT nCnt; 00294 INT diff = 0; 00295 00296 if (!dwClauseLen || !dwCompLen) { 00297 RIPMSG0(RIP_WARNING, "CheckClause: no Clause. Not Pass it to IME."); 00298 return (FALSE); 00299 } 00300 00301 if (*lpComp || *lpClause) { 00302 RIPMSG0(RIP_WARNING, "CheckClause: lpClause[0] have to be ZERO."); 00303 return (FALSE); 00304 } 00305 00306 for (nCnt = 0; nCnt < (UINT)(dwClauseLen/4); nCnt++) 00307 { 00308 if (*lpComp++ != *lpClause++) 00309 { 00310 diff++; 00311 if (dwCompLen > dwClauseLen) 00312 lpClause--; 00313 if (dwCompLen < dwClauseLen) 00314 lpComp--; 00315 } 00316 if (diff > 1) 00317 return (FALSE); 00318 } 00319 00320 return (TRUE); 00321 } 00322 00323 00324 LPBYTE InternalSCS_SETSTR( 00325 LPCVOID lpCompRead, 00326 DWORD dwCompReadLen, 00327 LPVOID *lplpNewCompRead, 00328 DWORD *lpdwNewCompReadLen, 00329 BOOL fAnsi, 00330 DWORD dwCodePage) 00331 { 00332 LPBYTE lpBufRet; 00333 DWORD dwBufSize; 00334 LPSTR lpBufA; 00335 LPWSTR lpBufW; 00336 INT i; 00337 BOOL bUDC; 00338 00339 if (lpCompRead == NULL || dwCompReadLen == 0) 00340 return NULL; 00341 00342 dwBufSize = dwCompReadLen * sizeof(WCHAR) * 2; 00343 00344 lpBufRet = ImmLocalAlloc(0, dwBufSize); 00345 if (lpBufRet == NULL) { 00346 RIPMSG0(RIP_WARNING, "InternalSCS_SETSTR: memory failure."); 00347 return NULL; 00348 } 00349 00350 lpBufW = (LPWSTR)lpBufRet; 00351 lpBufA = (LPSTR)(lpBufW + dwCompReadLen); 00352 00353 if (fAnsi) { 00354 00355 RtlCopyMemory(lpBufA, lpCompRead, dwCompReadLen); 00356 00357 i = MultiByteToWideChar(dwCodePage, 00358 (DWORD)MB_PRECOMPOSED, 00359 (LPSTR)lpBufA, // src 00360 (INT)dwCompReadLen, 00361 (LPWSTR)lpBufW, // dest 00362 (INT)dwCompReadLen); 00363 00364 *lplpNewCompRead = lpBufW; 00365 *lpdwNewCompReadLen = (DWORD)(i * sizeof(WCHAR)); 00366 } 00367 else { 00368 00369 RtlCopyMemory(lpBufW, lpCompRead, dwCompReadLen); 00370 00371 i = WideCharToMultiByte(dwCodePage, 00372 (DWORD)0, 00373 lpBufW, // src 00374 (INT)dwCompReadLen/sizeof(WCHAR), 00375 (LPSTR)lpBufA, // dest 00376 (INT)dwCompReadLen, 00377 (LPSTR)NULL, 00378 (LPBOOL)&bUDC); 00379 00380 *lplpNewCompRead = lpBufA; 00381 *lpdwNewCompReadLen = (DWORD)(i * sizeof(CHAR)); 00382 } 00383 00384 return lpBufRet; 00385 } 00386 00387 00388 LPBYTE InternalSCS_CHANGEATTR( 00389 HIMC hImc, 00390 LPCVOID lpCompRead, 00391 DWORD dwCompReadLen, 00392 DWORD dwIndex, 00393 LPVOID *lplpNewCompRead, 00394 DWORD *lpdwNewCompReadLen, 00395 BOOL fAnsi, 00396 DWORD dwCodePage) 00397 { 00398 LPBYTE lpBufRet; 00399 LPBYTE lpAttr, lpAttrA, lpAttrW; 00400 DWORD dwBufLenA, dwBufLenW; 00401 LPSTR lpStrBufA, lpBufA; 00402 LPWSTR lpStrBufW, lpBufW; 00403 CHAR c; 00404 WCHAR wc; 00405 ULONG MultiByteSize; 00406 00407 if (lpCompRead == NULL || dwCompReadLen == 0) 00408 return NULL; 00409 00410 if (fAnsi) { 00411 00412 dwBufLenA = ImmGetCompositionStringA(hImc, dwIndex, NULL, 0); 00413 00414 lpStrBufA = ImmLocalAlloc(0, dwBufLenA); 00415 if (lpStrBufA == NULL) { 00416 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure."); 00417 return NULL; 00418 } 00419 00420 ImmGetCompositionStringA(hImc, dwIndex, lpStrBufA, dwBufLenA); 00421 00422 lpBufRet = ImmLocalAlloc(0, dwBufLenA); 00423 if (lpBufRet == NULL) { 00424 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure."); 00425 ImmLocalFree(lpStrBufA); 00426 return NULL; 00427 } 00428 00429 lpBufA = lpStrBufA; 00430 lpAttrA = (LPBYTE)lpCompRead; 00431 lpAttr = lpBufRet; 00432 00433 while (dwBufLenA != 0 && (c=*lpBufA++) != 0) { 00434 if (IsDBCSLeadByteEx(dwCodePage, c)) { 00435 if (dwBufLenA >= 2) { 00436 *lpAttr++ = *lpAttrA++; 00437 dwBufLenA--; 00438 } else { 00439 *lpAttr++ = *lpAttrA; 00440 } 00441 lpBufA++; 00442 } else { 00443 *lpAttr++ = *lpAttrA; 00444 } 00445 lpAttrA++; 00446 dwBufLenA--; 00447 } 00448 00449 ImmLocalFree(lpStrBufA); 00450 } 00451 else { 00452 00453 dwBufLenW = ImmGetCompositionStringW(hImc, dwIndex, NULL, 0); 00454 00455 lpStrBufW = ImmLocalAlloc(0, dwBufLenW); 00456 if (lpStrBufW == NULL) { 00457 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure."); 00458 return NULL; 00459 } 00460 00461 ImmGetCompositionStringW(hImc, dwIndex, lpStrBufW, dwBufLenW); 00462 00463 lpBufRet = ImmLocalAlloc(0, dwBufLenW); 00464 if (lpBufRet == NULL) { 00465 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure."); 00466 ImmLocalFree(lpStrBufW); 00467 return NULL; 00468 } 00469 00470 lpBufW = lpStrBufW; 00471 lpAttrW = (LPBYTE)lpCompRead; 00472 lpAttr = lpBufRet; 00473 00474 while (dwBufLenW != 0 && (wc=*lpBufW++) != L'\0') { 00475 MultiByteSize = UnicodeToMultiByteSize(dwCodePage, &wc); 00476 if (MultiByteSize == 2) { 00477 *lpAttr++ = *lpAttrW; 00478 } 00479 *lpAttr++ = *lpAttrW++; 00480 dwBufLenW -= sizeof(WCHAR); 00481 } 00482 00483 ImmLocalFree(lpStrBufW); 00484 } 00485 00486 *lplpNewCompRead = lpBufRet; 00487 *lpdwNewCompReadLen = (DWORD)(lpAttr - (PBYTE)lpBufRet); 00488 00489 return lpBufRet; 00490 } 00491 00492 00493 LPBYTE InternalSCS_CHANGECLAUSE( 00494 HIMC hImc, 00495 LPCVOID lpCompRead, 00496 DWORD dwCompReadLen, 00497 DWORD dwIndex, 00498 LPDWORD *lplpNewCompRead, 00499 DWORD *lpdwNewCompReadLen, 00500 BOOL fAnsi, 00501 DWORD dwCodePage) 00502 { 00503 LPDWORD lpdw, lpNewdw, lpBufRet; 00504 DWORD dwBufLenA, dwBufLenW; 00505 LPSTR lpStrBufA; 00506 LPWSTR lpStrBufW; 00507 INT i; 00508 00509 if (lpCompRead == NULL || dwCompReadLen == 0) 00510 return NULL; 00511 00512 lpdw = (LPDWORD)lpCompRead; 00513 00514 lpBufRet = ImmLocalAlloc(0, dwCompReadLen); 00515 if (lpBufRet == NULL) { 00516 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure."); 00517 return NULL; 00518 } 00519 00520 if (fAnsi) { 00521 00522 dwBufLenA = ImmGetCompositionStringA(hImc, dwIndex, NULL, 0); 00523 00524 lpStrBufA = ImmLocalAlloc(0, dwBufLenA); 00525 if (lpStrBufA == NULL) { 00526 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure."); 00527 ImmLocalFree(lpBufRet); 00528 return NULL; 00529 } 00530 00531 ImmGetCompositionStringA(hImc, dwIndex, lpStrBufA, dwBufLenA); 00532 } 00533 else { 00534 00535 dwBufLenW = ImmGetCompositionStringW(hImc, dwIndex, NULL, 0); 00536 00537 lpStrBufW = ImmLocalAlloc(0, dwBufLenW); 00538 if (lpStrBufW == NULL) { 00539 RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure."); 00540 ImmLocalFree(lpBufRet); 00541 return NULL; 00542 } 00543 00544 ImmGetCompositionStringW(hImc, dwIndex, lpStrBufW, dwBufLenW); 00545 } 00546 00547 *lplpNewCompRead = lpNewdw = lpBufRet; 00548 *lpdwNewCompReadLen = dwCompReadLen; 00549 00550 for (i = 0; i < (INT)(dwCompReadLen / sizeof(DWORD)); i++) { 00551 *lpNewdw++ = fAnsi ? CalcCharacterPositionAtoW(*lpdw++, lpStrBufA, dwCodePage) 00552 : CalcCharacterPositionWtoA(*lpdw++, lpStrBufW, dwCodePage); 00553 } 00554 00555 return (LPBYTE)lpBufRet; 00556 } 00557 00558 00559 LPBYTE InternalSCS_RECONVERTSTRING( 00560 LPRECONVERTSTRING lpReconv, 00561 DWORD dwReconvLen, 00562 LPRECONVERTSTRING *lplpNewReconv, 00563 DWORD *lpdwNewReconvLen, 00564 BOOL fAnsi, 00565 DWORD dwCodePage) 00566 { 00567 LPRECONVERTSTRING lpNewReconv; 00568 DWORD dwBufSize; 00569 00570 if (lpReconv == NULL || dwReconvLen == 0) 00571 return NULL; 00572 00573 if (fAnsi) { 00574 // AtoW 00575 dwBufSize = (lpReconv->dwSize - sizeof *lpReconv + 1) * sizeof(WCHAR) + sizeof *lpReconv; 00576 } 00577 else { 00578 dwBufSize = lpReconv->dwSize + sizeof(BYTE); 00579 } 00580 lpNewReconv = ImmLocalAlloc(0, dwBufSize); 00581 if (lpNewReconv == NULL) { 00582 RIPMSG0(RIP_WARNING, "InternalSCS_RECONVERTSTRING: memory failure."); 00583 return NULL; 00584 } 00585 00586 lpNewReconv->dwVersion = 0; 00587 lpNewReconv->dwSize= dwBufSize; 00588 00589 lpNewReconv->dwSize = ImmReconversionWorker(lpNewReconv, lpReconv, !fAnsi, dwCodePage); 00590 if (lpNewReconv->dwSize == 0) { 00591 ImmLocalFree(lpNewReconv); 00592 return NULL;; 00593 } 00594 *lpdwNewReconvLen = lpNewReconv->dwSize; 00595 *lplpNewReconv = lpNewReconv; 00596 00597 return (LPBYTE)lpNewReconv; 00598 } 00599 00600 00601 /***************************************************************************\ 00602 * ImmSetCompositionStringWorker 00603 * 00604 * Worker function of ImmSetCompositionStringA/ImmSetCompositionStringW 00605 * 00606 * History: 00607 * 28-Feb-1995 wkwok Created 00608 \***************************************************************************/ 00609 00610 BOOL ImmSetCompositionStringWorker( 00611 HIMC hImc, 00612 DWORD dwIndex, 00613 LPVOID lpComp, 00614 DWORD dwCompLen, 00615 LPVOID lpRead, 00616 DWORD dwReadLen, 00617 BOOL fAnsi) 00618 { 00619 PINPUTCONTEXT pInputContext; 00620 PCOMPOSITIONSTRING pCompStr; 00621 DWORD dwThreadId; 00622 PIMEDPI pImeDpi; 00623 LPBYTE lpCompBuf, lpReadBuf; 00624 LPBYTE lpNewComp = NULL, lpNewRead = NULL; 00625 DWORD dwNewCompLen, dwNewReadLen; 00626 BOOL fRet = FALSE; 00627 BOOL fCheckSize = TRUE; 00628 BOOL fNeedAWConversion; 00629 LPBYTE lpOrgComp, lpOrgRead; 00630 DWORD dwOrgCompLen, dwOrgReadLen; 00631 00632 dwThreadId = GetInputContextThread(hImc); 00633 if (dwThreadId != GetCurrentThreadId()) { 00634 RIPMSG1(RIP_WARNING, 00635 "ImmSetCompositionString: Invalid input context access %lx.", hImc); 00636 return FALSE; 00637 } 00638 00639 pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId)); 00640 if (pImeDpi == NULL) 00641 return FALSE; 00642 00643 lpCompBuf = lpReadBuf = NULL; 00644 00645 // Backup original pointers to copyback for QUERY. 00646 lpOrgComp = lpComp; 00647 lpOrgRead = lpRead; 00648 dwOrgCompLen = dwCompLen; 00649 dwOrgReadLen = dwReadLen; 00650 00651 /* 00652 * Check if we need ANSI/Unicode conversion 00653 */ 00654 if (( fAnsi && !(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) || 00655 (!fAnsi && (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))) { 00656 /* 00657 * No A/W conversion needed. 00658 */ 00659 fNeedAWConversion = FALSE; 00660 goto start_scs; 00661 } 00662 fNeedAWConversion = TRUE; 00663 00664 switch (dwIndex) { 00665 case SCS_SETSTR: 00666 if ( lpComp && 00667 (lpCompBuf = InternalSCS_SETSTR(lpComp, dwCompLen, 00668 &lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL) 00669 goto callime_scs; 00670 if ( lpRead && 00671 (lpReadBuf = InternalSCS_SETSTR(lpRead, dwReadLen, 00672 &lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL) 00673 goto callime_scs; 00674 00675 fCheckSize = FALSE; 00676 break; 00677 00678 case SCS_CHANGEATTR: 00679 if ( lpComp && 00680 (lpCompBuf = InternalSCS_CHANGEATTR( 00681 hImc, lpComp, dwCompLen, GCS_COMPSTR, 00682 &lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL) 00683 goto callime_scs; 00684 if ( lpRead && 00685 (lpReadBuf = InternalSCS_CHANGEATTR( 00686 hImc, lpRead, dwReadLen, GCS_COMPREADSTR, 00687 &lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL) 00688 goto callime_scs; 00689 break; 00690 00691 case SCS_CHANGECLAUSE: 00692 if ( lpComp && 00693 (lpCompBuf = InternalSCS_CHANGECLAUSE( 00694 hImc, lpComp, dwCompLen, GCS_COMPSTR, 00695 (LPDWORD *)&lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL) 00696 goto callime_scs; 00697 if ( lpRead && 00698 (lpReadBuf = InternalSCS_CHANGECLAUSE( 00699 hImc, lpRead, dwReadLen, GCS_COMPREADSTR, 00700 (LPDWORD *)&lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL) 00701 goto callime_scs; 00702 break; 00703 00704 case SCS_SETRECONVERTSTRING: 00705 case SCS_QUERYRECONVERTSTRING: 00706 if (lpComp && 00707 (lpCompBuf = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpComp, dwCompLen, 00708 (LPRECONVERTSTRING *)&lpNewComp, &dwNewCompLen, 00709 fAnsi, IMECodePage(pImeDpi))) == NULL) 00710 goto callime_scs; 00711 if (lpRead && 00712 (lpReadBuf = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpRead, dwReadLen, 00713 (LPRECONVERTSTRING *)&lpNewRead, &dwNewReadLen, 00714 fAnsi, IMECodePage(pImeDpi))) == NULL) 00715 goto callime_scs; 00716 00717 fCheckSize = FALSE; 00718 break; 00719 00720 default: 00721 goto callime_scs; 00722 } 00723 00724 if (lpCompBuf != NULL) { 00725 lpComp = lpNewComp; 00726 dwCompLen = dwNewCompLen; 00727 } 00728 00729 if (lpReadBuf != NULL) { 00730 lpRead = lpNewRead; 00731 dwReadLen = dwNewReadLen; 00732 } 00733 00734 start_scs: 00735 00736 if (CompositionString(hImc, &pInputContext, &pCompStr, fCheckSize) <= 0) 00737 goto callime_scs; 00738 00739 switch (dwIndex) 00740 { 00741 case SCS_SETSTR: 00742 fRet = TRUE; 00743 break; 00744 00745 case SCS_CHANGEATTR: 00746 if ( lpComp && 00747 !CheckAttribute((LPBYTE)lpComp, dwCompLen, 00748 (LPBYTE)((LPBYTE)pCompStr + pCompStr->dwCompAttrOffset), 00749 pCompStr->dwCompAttrLen, 00750 (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompClauseOffset), 00751 pCompStr->dwCompClauseLen)) break; 00752 00753 if ( lpRead && 00754 !CheckAttribute((LPBYTE)lpRead, dwReadLen, 00755 (LPBYTE)((LPBYTE)pCompStr + pCompStr->dwCompReadAttrOffset), 00756 pCompStr->dwCompReadAttrLen, 00757 (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompReadClauseOffset), 00758 pCompStr->dwCompReadClauseLen)) break; 00759 fRet = TRUE; 00760 break; 00761 00762 case SCS_CHANGECLAUSE: 00763 if ( lpComp && 00764 !CheckClause((LPDWORD)lpComp, dwCompLen, 00765 (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompClauseOffset), 00766 pCompStr->dwCompClauseLen)) break; 00767 if ( lpRead && 00768 !CheckClause((LPDWORD)lpRead, dwReadLen, 00769 (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompReadClauseOffset), 00770 pCompStr->dwCompReadClauseLen)) break; 00771 fRet = TRUE; 00772 break; 00773 00774 case SCS_SETRECONVERTSTRING: 00775 case SCS_QUERYRECONVERTSTRING: 00776 if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING) { 00777 fRet = TRUE; 00778 } 00779 break; 00780 00781 default: 00782 break; 00783 } 00784 00785 ImmUnlockIMCC(pInputContext->hCompStr); 00786 ImmUnlockIMC(hImc); 00787 00788 callime_scs: 00789 00790 if (fRet) { 00791 fRet = (*pImeDpi->pfn.ImeSetCompositionString)(hImc, dwIndex, 00792 lpComp, dwCompLen, lpRead, dwReadLen); 00793 } 00794 00795 /* 00796 * Check if we need ANSI/Unicode back conversion 00797 */ 00798 if (fNeedAWConversion) { 00799 LPBYTE lpCompBufBack = NULL, lpReadBufBack = NULL; 00800 /* 00801 * A/W back conversion needed. 00802 */ 00803 switch (dwIndex) { 00804 case SCS_QUERYRECONVERTSTRING: 00805 if (lpOrgComp && 00806 (lpCompBufBack = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpComp, dwCompLen, 00807 (LPRECONVERTSTRING *)&lpNewComp, &dwNewCompLen, 00808 !fAnsi, IMECodePage(pImeDpi)))) { 00809 RtlCopyMemory(lpOrgComp, lpNewComp, dwNewCompLen); 00810 } 00811 if (lpOrgRead && 00812 (lpReadBufBack = InternalSCS_RECONVERTSTRING( 00813 (LPRECONVERTSTRING)lpRead, dwReadLen, 00814 (LPRECONVERTSTRING *)&lpNewRead, &dwNewReadLen, 00815 !fAnsi, IMECodePage(pImeDpi)))) { 00816 RtlCopyMemory(lpOrgRead, lpNewRead, dwNewReadLen); 00817 } 00818 } 00819 if (lpCompBufBack != NULL) 00820 LocalFree(lpCompBufBack); 00821 if (lpReadBufBack != NULL) 00822 LocalFree(lpReadBufBack); 00823 } 00824 00825 if (lpCompBuf != NULL) 00826 ImmLocalFree(lpCompBuf); 00827 if (lpReadBuf != NULL) 00828 ImmLocalFree(lpReadBuf); 00829 00830 ImmUnlockImeDpi(pImeDpi); 00831 00832 return fRet; 00833 } 00834 00835 00836 /***************************************************************************\ 00837 * ImmGetCandidateListCountA 00838 * 00839 * Query the byte count and list count to receive all candidate list. 00840 * 00841 * History: 00842 * 27-Feb-1995 wkwok Created 00843 \***************************************************************************/ 00844 00845 DWORD WINAPI ImmGetCandidateListCountA( 00846 HIMC hImc, 00847 LPDWORD lpdwListCount) // the buffer pointer for list count 00848 { 00849 return ImmGetCandidateListCountWorker(hImc, lpdwListCount, TRUE); 00850 } 00851 00852 00853 /***************************************************************************\ 00854 * ImmGetCandidateListCountW 00855 * 00856 * Query the byte count and list count to receive all candidate list. 00857 * 00858 * History: 00859 * 27-Feb-1995 wkwok Created 00860 \***************************************************************************/ 00861 00862 DWORD WINAPI ImmGetCandidateListCountW( 00863 HIMC hImc, 00864 LPDWORD lpdwListCount) // the buffer pointer for list count 00865 { 00866 return ImmGetCandidateListCountWorker(hImc, lpdwListCount, FALSE); 00867 } 00868 00869 00870 /***************************************************************************\ 00871 * ImmGetCandidateListCountWorker 00872 * 00873 * Worker function of ImmGetCandidateListCountA/ImmGetCandidateListCountW. 00874 * 00875 * History: 00876 * 27-Feb-1995 wkwok Created 00877 \***************************************************************************/ 00878 00879 DWORD ImmGetCandidateListCountWorker( 00880 HIMC hImc, 00881 LPDWORD lpdwListCount, 00882 BOOL fAnsi) 00883 { 00884 PCLIENTIMC pClientImc; 00885 PINPUTCONTEXT pInputContext; 00886 LPCANDIDATEINFO lpCandInfo; 00887 DWORD dwRet = 0; 00888 INT i; 00889 DWORD dwCodePage; 00890 00891 if (lpdwListCount) { 00892 *lpdwListCount = 0; 00893 } else { 00894 RIPMSG0(RIP_WARNING, "ImmGetCandidateListCount: NULL lpdwListCount."); 00895 return dwRet; 00896 } 00897 00898 pClientImc = ImmLockClientImc(hImc); 00899 if (pClientImc == NULL) { 00900 RIPMSG1(RIP_WARNING, "ImmGetCandidateListCount: Invalid hImc %lx.", hImc); 00901 goto GetCandListCntExit; 00902 } 00903 dwCodePage = CImcCodePage(pClientImc); 00904 00905 pInputContext = ImmLockIMC(hImc); 00906 if (pInputContext == NULL) { 00907 RIPMSG1(RIP_WARNING, "ImmGetCandidateListCount: Lock hImc %lx failed.", hImc); 00908 goto GetCandListCntUnlockClientImc; 00909 } 00910 00911 lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo); 00912 if (!lpCandInfo) { 00913 RIPMSG1(RIP_WARNING, 00914 "ImmGetCandidateListCount: Lock hCandInfo %x failed.", 00915 pInputContext->hCandInfo); 00916 goto GetCandListCntUnlockIMC; 00917 } 00918 00919 if (lpCandInfo->dwSize < sizeof(CANDIDATEINFO)) { 00920 RIPMSG0(RIP_WARNING, "ImmGetCandidateListCount: no candidate list."); 00921 goto GetCandListCntUnlockIMC; 00922 } 00923 00924 *lpdwListCount = lpCandInfo->dwCount; 00925 00926 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) { 00927 LPCANDIDATELIST lpCandListW; 00928 00929 dwRet = DWORD_ALIGN(sizeof(CANDIDATEINFO)) 00930 + DWORD_ALIGN(lpCandInfo->dwPrivateSize); 00931 00932 for (i = 0; i < (INT)lpCandInfo->dwCount; i++) { 00933 lpCandListW = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[i]); 00934 dwRet += InternalGetCandidateListWtoA(lpCandListW, NULL, 0, dwCodePage); 00935 } 00936 } 00937 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) { 00938 LPCANDIDATELIST lpCandListA; 00939 00940 dwRet = DWORD_ALIGN(sizeof(CANDIDATEINFO)) 00941 + DWORD_ALIGN(lpCandInfo->dwPrivateSize); 00942 00943 for (i = 0; i < (INT)lpCandInfo->dwCount; i++) { 00944 lpCandListA = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[i]); 00945 dwRet += InternalGetCandidateListAtoW(lpCandListA, NULL, 0, dwCodePage); 00946 } 00947 } 00948 else { 00949 dwRet = lpCandInfo->dwSize; 00950 } 00951 00952 ImmUnlockIMCC(pInputContext->hCandInfo); 00953 00954 GetCandListCntUnlockIMC: 00955 ImmUnlockIMC(hImc); 00956 00957 GetCandListCntUnlockClientImc: 00958 ImmUnlockClientImc(pClientImc); 00959 00960 GetCandListCntExit: 00961 return dwRet; 00962 } 00963 00964 00965 /***************************************************************************\ 00966 * ImmGetCandidateListA 00967 * 00968 * Gets the candidate list information specified by dwIndex. 00969 * 00970 * History: 00971 * 27-Feb-1995 wkwok Created 00972 \***************************************************************************/ 00973 00974 DWORD WINAPI ImmGetCandidateListA( 00975 HIMC hImc, 00976 DWORD dwIndex, 00977 LPCANDIDATELIST lpCandList, 00978 DWORD dwBufLen) 00979 { 00980 return ImmGetCandidateListWorker(hImc, dwIndex, 00981 lpCandList, dwBufLen, TRUE); 00982 } 00983 00984 00985 /***************************************************************************\ 00986 * ImmGetCandidateListW 00987 * 00988 * Gets the candidate list information specified by dwIndex. 00989 * 00990 * History: 00991 * 27-Feb-1995 wkwok Created 00992 \***************************************************************************/ 00993 00994 DWORD WINAPI ImmGetCandidateListW( 00995 HIMC hImc, 00996 DWORD dwIndex, 00997 LPCANDIDATELIST lpCandList, 00998 DWORD dwBufLen) 00999 { 01000 return ImmGetCandidateListWorker(hImc, dwIndex, 01001 lpCandList, dwBufLen, FALSE); 01002 } 01003 01004 01005 /***************************************************************************\ 01006 * ImmGetCandidateListWorker 01007 * 01008 * Worker function of ImmGetCandidateListA/ImmGetCandidateListW. 01009 * 01010 * History: 01011 * 27-Feb-1995 wkwok Created 01012 \***************************************************************************/ 01013 01014 DWORD ImmGetCandidateListWorker( 01015 HIMC hImc, 01016 DWORD dwIndex, 01017 LPCANDIDATELIST lpCandList, 01018 DWORD dwBufLen, 01019 BOOL fAnsi) 01020 { 01021 PCLIENTIMC pClientImc; 01022 PINPUTCONTEXT pInputContext; 01023 LPCANDIDATEINFO lpCandInfo; 01024 LPCANDIDATELIST lpCandListTemp; 01025 DWORD dwBufLenTemp; 01026 DWORD dwRet = 0; 01027 DWORD dwCodePage; 01028 01029 pClientImc = ImmLockClientImc(hImc); 01030 if (pClientImc == NULL) { 01031 RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Invalid hImc %lx.", hImc); 01032 goto GetCandListExit; 01033 01034 } 01035 01036 dwCodePage = CImcCodePage(pClientImc); 01037 01038 pInputContext = ImmLockIMC(hImc); 01039 if (pInputContext == NULL) { 01040 RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Lock hImc %lx failed.", hImc); 01041 goto GetCandListUnlockClientImc; 01042 } 01043 01044 lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo); 01045 if (!lpCandInfo) { 01046 RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Lock hCandInfo %x failed", 01047 pInputContext->hCandInfo); 01048 goto GetCandListUnlockIMC; 01049 } 01050 01051 if (lpCandInfo->dwSize < sizeof(CANDIDATEINFO)) { 01052 RIPMSG0(RIP_WARNING, "ImmGetCandidateList: no candidate list."); 01053 goto GetCandListUnlockIMCC; 01054 } 01055 01056 /* 01057 * invalid access 01058 */ 01059 if (dwIndex >= lpCandInfo->dwCount) { 01060 RIPMSG0(RIP_WARNING, "ImmGetCandidateList: dwIndex >= lpCandInfo->dwCount."); 01061 goto GetCandListUnlockIMCC; 01062 } 01063 01064 lpCandListTemp = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[dwIndex]); 01065 01066 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) { 01067 /* 01068 * ANSI Caller with an Unicode hImc. 01069 */ 01070 dwBufLenTemp = InternalGetCandidateListWtoA(lpCandListTemp, NULL, 0, dwCodePage); 01071 } 01072 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) { 01073 /* 01074 * Unicode Caller with an ANSI hImc. 01075 */ 01076 dwBufLenTemp = InternalGetCandidateListAtoW(lpCandListTemp, NULL, 0, dwCodePage); 01077 } 01078 else { 01079 /* 01080 * No conversion required. 01081 */ 01082 dwBufLenTemp = lpCandListTemp->dwSize; 01083 } 01084 01085 /* 01086 * Query buffer size or early exit on error 01087 */ 01088 if (dwBufLen == 0 || dwBufLenTemp == 0) { 01089 dwRet = dwBufLenTemp; 01090 } 01091 else if (!lpCandList) { 01092 RIPMSG0(RIP_WARNING, "ImmGetCandidateList: Null lpCandList."); 01093 } 01094 else if (dwBufLen < dwBufLenTemp) { 01095 RIPMSG2(RIP_WARNING, "ImmGetCandidateList: dwBufLen = %d too small, require = %d.", 01096 dwBufLen, dwBufLenTemp); 01097 } else { 01098 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) { 01099 dwRet = InternalGetCandidateListWtoA(lpCandListTemp, lpCandList, dwBufLenTemp, dwCodePage); 01100 } 01101 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) { 01102 dwRet = InternalGetCandidateListAtoW(lpCandListTemp, lpCandList, dwBufLenTemp, dwCodePage); 01103 } 01104 else { 01105 RtlCopyMemory((LPBYTE)lpCandList, (LPBYTE)lpCandListTemp, dwBufLenTemp); 01106 dwRet = dwBufLenTemp; 01107 } 01108 } 01109 01110 GetCandListUnlockIMCC: 01111 ImmUnlockIMCC(pInputContext->hCandInfo); 01112 01113 GetCandListUnlockIMC: 01114 ImmUnlockIMC(hImc); 01115 01116 GetCandListUnlockClientImc: 01117 ImmUnlockClientImc(pClientImc); 01118 01119 GetCandListExit: 01120 return dwRet; 01121 } 01122 01123 01124 /***************************************************************************\ 01125 * ImmGetGuideLineA 01126 * 01127 * Gets the guide line information reported by the IME. 01128 * 01129 * History: 01130 * 26-Feb-1995 wkwok Created 01131 \***************************************************************************/ 01132 01133 DWORD WINAPI ImmGetGuideLineA( 01134 HIMC hImc, 01135 DWORD dwIndex, 01136 LPSTR lpszBuf, 01137 DWORD dwBufLen) 01138 { 01139 return ImmGetGuideLineWorker(hImc, dwIndex, 01140 (LPBYTE)lpszBuf, dwBufLen, TRUE); 01141 } 01142 01143 01144 /***************************************************************************\ 01145 * ImmGetGuideLineW 01146 * 01147 * Gets the guide line information reported by the IME. 01148 * 01149 * History: 01150 * 26-Feb-1995 wkwok Created 01151 \***************************************************************************/ 01152 01153 DWORD WINAPI ImmGetGuideLineW( 01154 HIMC hImc, 01155 DWORD dwIndex, 01156 LPWSTR lpwszBuf, 01157 DWORD dwBufLen) 01158 { 01159 return ImmGetGuideLineWorker(hImc, dwIndex, 01160 (LPBYTE)lpwszBuf, dwBufLen, FALSE); 01161 } 01162 01163 01164 /***************************************************************************\ 01165 * ImmGetGuideLineWorker 01166 * 01167 * Worker function of ImmGetGuideLineA/ImmGetGuideLineW. 01168 * 01169 * History: 01170 * 26-Feb-1995 wkwok Created 01171 \***************************************************************************/ 01172 01173 DWORD ImmGetGuideLineWorker( 01174 HIMC hImc, 01175 DWORD dwIndex, 01176 LPBYTE lpBuf, 01177 DWORD dwBufLen, 01178 BOOL fAnsi) 01179 { 01180 PCLIENTIMC pClientImc; 01181 PINPUTCONTEXT pInputContext; 01182 LPGUIDELINE lpGuideLine; 01183 LPBYTE lpBufTemp; 01184 DWORD dwRet = 0; 01185 DWORD dwBufLenNeeded; 01186 BOOL bUDC; 01187 DWORD dwCodePage; 01188 01189 pClientImc = ImmLockClientImc(hImc); 01190 if (pClientImc == NULL) { 01191 RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Invalid hImc %lx.", hImc); 01192 goto GetGuideLineExit; 01193 } 01194 dwCodePage = CImcCodePage(pClientImc); 01195 01196 pInputContext = ImmLockIMC(hImc); 01197 if (pInputContext == NULL) { 01198 RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Lock hImc %lx failed.", hImc); 01199 goto GetGuideLineUnlockClientImc; 01200 } 01201 01202 lpGuideLine = (LPGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine); 01203 if (!lpGuideLine) { 01204 RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Lock hGuideLine %lx failed.", 01205 pInputContext->hGuideLine); 01206 goto GetGuideLineUnlockIMC; 01207 } 01208 01209 switch (dwIndex) { 01210 case GGL_LEVEL: 01211 dwRet = lpGuideLine->dwLevel; 01212 break; 01213 01214 case GGL_INDEX: 01215 dwRet = lpGuideLine->dwIndex; 01216 break; 01217 01218 case GGL_STRING: 01219 01220 lpBufTemp = (LPBYTE)lpGuideLine + lpGuideLine->dwStrOffset; 01221 01222 /* 01223 * Calculate the required buffer length. 01224 */ 01225 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) { 01226 dwBufLenNeeded = WideCharToMultiByte(dwCodePage, 01227 (DWORD)0, 01228 (LPWSTR)lpBufTemp, 01229 (INT)lpGuideLine->dwStrLen, 01230 (LPSTR)NULL, 01231 (INT)0, 01232 (LPSTR)NULL, 01233 (LPBOOL)&bUDC); 01234 } 01235 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) { 01236 dwBufLenNeeded = MultiByteToWideChar(dwCodePage, 01237 (DWORD)MB_PRECOMPOSED, 01238 (LPSTR)lpBufTemp, 01239 (INT)lpGuideLine->dwStrLen, 01240 (LPWSTR)NULL, 01241 (INT)0); 01242 dwBufLenNeeded *= sizeof(WCHAR); 01243 } 01244 else { 01245 dwBufLenNeeded = lpGuideLine->dwStrLen; 01246 /* 01247 * The dwStrLen records the strlen and not the byte count. 01248 */ 01249 if (TestICF(pClientImc, IMCF_UNICODE)) 01250 dwBufLenNeeded *= sizeof(WCHAR); 01251 } 01252 01253 /* 01254 * Query GuideLine string size only or early exit on error 01255 */ 01256 if (dwBufLen == 0 || dwBufLenNeeded == 0) { 01257 dwRet = dwBufLenNeeded; 01258 goto GetGuideLineUnlockIMCC; 01259 } 01260 01261 if (lpBuf == NULL || dwBufLen < dwBufLenNeeded) 01262 goto GetGuideLineUnlockIMCC; 01263 01264 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) { 01265 dwRet = WideCharToMultiByte(dwCodePage, 01266 (DWORD)0, 01267 (LPWSTR)lpBufTemp, 01268 (INT)lpGuideLine->dwStrLen, 01269 (LPSTR)lpBuf, 01270 (INT)dwBufLen, 01271 (LPSTR)NULL, 01272 (LPBOOL)&bUDC); 01273 } 01274 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) { 01275 dwRet = MultiByteToWideChar(dwCodePage, 01276 (DWORD)MB_PRECOMPOSED, 01277 (LPSTR)lpBufTemp, 01278 (INT)lpGuideLine->dwStrLen, 01279 (LPWSTR)lpBuf, 01280 (INT)dwBufLen/sizeof(WCHAR)); 01281 dwRet *= sizeof(WCHAR); 01282 } 01283 else { 01284 RtlCopyMemory(lpBuf, lpBufTemp, dwBufLenNeeded); 01285 dwRet = dwBufLenNeeded; 01286 } 01287 01288 break; 01289 01290 case GGL_PRIVATE: 01291 01292 lpBufTemp = (LPBYTE)lpGuideLine + lpGuideLine->dwPrivateOffset; 01293 01294 /* 01295 * The dwPrivateOffset is an offset to a CANDIDATELIST when 01296 * lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION. Do conversion 01297 * for this case only. 01298 */ 01299 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE) && 01300 lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) { 01301 dwBufLenNeeded = InternalGetCandidateListWtoA( 01302 (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0, dwCodePage); 01303 } 01304 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) && 01305 lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) { 01306 dwBufLenNeeded = InternalGetCandidateListAtoW( 01307 (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0, dwCodePage); 01308 } 01309 else { 01310 dwBufLenNeeded = lpGuideLine->dwPrivateSize; 01311 } 01312 01313 /* 01314 * Query dwPrivateSize size only or early exit on error 01315 */ 01316 if (dwBufLen == 0 || dwBufLenNeeded == 0) { 01317 dwRet = dwBufLenNeeded; 01318 goto GetGuideLineUnlockIMCC; 01319 } 01320 01321 if (lpBuf == NULL || dwBufLen < dwBufLenNeeded) 01322 goto GetGuideLineUnlockIMCC; 01323 01324 if (fAnsi && TestICF(pClientImc, IMCF_UNICODE) && 01325 lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) { 01326 dwRet = InternalGetCandidateListWtoA( 01327 (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded, dwCodePage); 01328 } 01329 else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) && 01330 lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) { 01331 dwRet = InternalGetCandidateListAtoW( 01332 (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded, dwCodePage); 01333 } 01334 else { 01335 RtlCopyMemory(lpBuf, lpBufTemp, dwBufLenNeeded); 01336 dwRet = dwBufLenNeeded; 01337 } 01338 01339 break; 01340 01341 default: 01342 break; 01343 } 01344 01345 GetGuideLineUnlockIMCC: 01346 ImmUnlockIMCC(pInputContext->hGuideLine); 01347 01348 GetGuideLineUnlockIMC: 01349 ImmUnlockIMC(hImc); 01350 01351 GetGuideLineUnlockClientImc: 01352 ImmUnlockClientImc(pClientImc); 01353 01354 GetGuideLineExit: 01355 return dwRet; 01356 } 01357 01358 01359 /***************************************************************************\ 01360 * ImmGetConversionStatus 01361 * 01362 * Gets current conversion status. 01363 * 01364 * History: 01365 * 26-Feb-1995 wkwok Created 01366 \***************************************************************************/ 01367 01368 BOOL WINAPI ImmGetConversionStatus( // Get the conversion status 01369 HIMC hImc, 01370 LPDWORD lpfdwConversion, 01371 LPDWORD lpfdwSentence) 01372 { 01373 PINPUTCONTEXT pInputContext; 01374 01375 pInputContext = ImmLockIMC(hImc); 01376 if (pInputContext == NULL) { 01377 RIPMSG1(RIP_WARNING, "ImmGetConversionStatus: Lock hImc %lx failed", hImc); 01378 return FALSE; 01379 } 01380 01381 if (lpfdwConversion != NULL) 01382 *lpfdwConversion = pInputContext->fdwConversion; 01383 01384 if (lpfdwSentence != NULL) 01385 *lpfdwSentence = pInputContext->fdwSentence; 01386 01387 ImmUnlockIMC(hImc); 01388 01389 return TRUE; 01390 } 01391 01392 01393 /***************************************************************************\ 01394 * ImmSetConversionStatus 01395 * 01396 * Sets current conversion status. 01397 * 01398 * History: 01399 * 26-Feb-1995 wkwok Created 01400 \***************************************************************************/ 01401 01402 BOOL WINAPI ImmSetConversionStatus( 01403 HIMC hImc, 01404 DWORD fdwConversion, 01405 DWORD fdwSentence) 01406 { 01407 PINPUTCONTEXT pInputContext; 01408 DWORD fdwOldConversion; 01409 DWORD fdwOldSentence; 01410 BOOL fConvModeChg; 01411 BOOL fSentenceChg; 01412 HWND hWnd; 01413 DWORD dwOpenStatus; 01414 DWORD dwConversion; 01415 01416 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 01417 RIPMSG1(RIP_WARNING, 01418 "ImmSetConversionStatus: Invalid input context access %lx.", hImc); 01419 return FALSE; 01420 } 01421 01422 pInputContext = ImmLockIMC(hImc); 01423 if (pInputContext == NULL) { 01424 RIPMSG1(RIP_WARNING, 01425 "ImmSetConversionStatus: Lock hImc %lx failed", hImc); 01426 return FALSE; 01427 } 01428 01429 fConvModeChg = FALSE; 01430 fSentenceChg = FALSE; 01431 01432 if (pInputContext->fdwConversion != fdwConversion) { 01433 if ((fdwConversion & IME_CMODE_LANGUAGE) == IME_CMODE_KATAKANA) { 01434 RIPMSG0(RIP_WARNING, "ImmSetConversionStatus: wrong fdwConversion"); 01435 } 01436 fdwOldConversion = pInputContext->fdwConversion; 01437 pInputContext->fdwConversion = fdwConversion; 01438 fConvModeChg = TRUE; 01439 } 01440 01441 if (pInputContext->fdwSentence != fdwSentence) { 01442 fdwOldSentence = pInputContext->fdwSentence; 01443 pInputContext->fdwSentence = fdwSentence; 01444 fSentenceChg = TRUE; 01445 } 01446 01447 hWnd = pInputContext->hWnd; 01448 if ( fConvModeChg ) { 01449 01450 dwOpenStatus = (DWORD)pInputContext->fOpen; 01451 dwConversion = pInputContext->fdwConversion; 01452 } 01453 01454 ImmUnlockIMC(hImc); 01455 01456 #ifdef LATER 01457 // Do uNumLangVKey and uNumVKey checking later. 01458 #endif 01459 01460 /* 01461 * inform IME and UI about the conversion mode changes. 01462 */ 01463 if (fConvModeChg) { 01464 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldConversion, 01465 IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0L); 01466 01467 /* 01468 * notify shell and keyboard the conversion mode change 01469 */ 01470 NtUserNotifyIMEStatus( hWnd, dwOpenStatus, dwConversion ); 01471 } 01472 01473 /* 01474 * inform IME and UI about the sentence mode changes. 01475 */ 01476 if (fSentenceChg) { 01477 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldSentence, 01478 IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0L); 01479 } 01480 01481 return TRUE; 01482 } 01483 01484 01485 /***************************************************************************\ 01486 * ImmGetOpenStatus 01487 * 01488 * Gets the open or close status of the IME. 01489 * 01490 * History: 01491 * 26-Feb-1995 wkwok Created 01492 \***************************************************************************/ 01493 01494 BOOL WINAPI ImmGetOpenStatus( 01495 HIMC hImc) 01496 { 01497 PINPUTCONTEXT pInputContext; 01498 BOOL fOpen; 01499 01500 if (hImc == NULL_HIMC) 01501 return FALSE; 01502 01503 pInputContext = ImmLockIMC(hImc); 01504 if (!pInputContext) { 01505 RIPMSG1(RIP_WARNING, "ImmGetOpenStatus: Lock hImc %lx failed", hImc); 01506 return FALSE; 01507 } 01508 01509 fOpen = pInputContext->fOpen; 01510 ImmUnlockIMC(hImc); 01511 01512 return (fOpen); 01513 } 01514 01515 01516 /***************************************************************************\ 01517 * ImmSetOpenStatus 01518 * 01519 * Opens or closes the IME. 01520 * 01521 * History: 01522 * 26-Feb-1995 wkwok Created 01523 \***************************************************************************/ 01524 01525 BOOL WINAPI ImmSetOpenStatus( 01526 HIMC hImc, 01527 BOOL fOpen) 01528 { 01529 PINPUTCONTEXT pInputContext; 01530 HWND hWnd; 01531 DWORD dwOpenStatus; 01532 DWORD dwConversion; 01533 BOOL fOpenChg = FALSE; 01534 01535 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 01536 RIPMSG1(RIP_WARNING, 01537 "ImmSetOpenStatus: Invalid input context access %lx.", hImc); 01538 return FALSE; 01539 } 01540 01541 pInputContext = ImmLockIMC(hImc); 01542 if (!pInputContext) { 01543 RIPMSG1(RIP_WARNING, "ImmSetOpenStatus: Lock hImc %lx failed", hImc); 01544 return FALSE; 01545 } 01546 01547 if (pInputContext->fOpen != fOpen) { 01548 fOpenChg = TRUE; 01549 pInputContext->fOpen = fOpen; 01550 } 01551 01552 if ( fOpenChg ) { 01553 hWnd = (HWND)pInputContext->hWnd; 01554 dwOpenStatus = (DWORD)pInputContext->fOpen; 01555 dwConversion = (DWORD)pInputContext->fdwConversion; 01556 } 01557 01558 ImmUnlockIMC(hImc); 01559 01560 /* 01561 * inform IME and UI about the conversion mode changes. 01562 */ 01563 if (fOpenChg) { 01564 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, (DWORD)0, 01565 IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0L); 01566 01567 NtUserNotifyIMEStatus( hWnd, dwOpenStatus, dwConversion ); 01568 } 01569 01570 return TRUE; 01571 } 01572 01573 01574 /***************************************************************************\ 01575 * ImmGetCompositionFontA 01576 * 01577 * Opens or closes the IME. 01578 * 01579 * History: 01580 * 27-Feb-1995 wkwok Created 01581 \***************************************************************************/ 01582 01583 BOOL WINAPI ImmGetCompositionFontA( 01584 HIMC hImc, 01585 LPLOGFONTA lpLogFontA) 01586 { 01587 PCLIENTIMC pClientImc; 01588 PINPUTCONTEXT pInputContext; 01589 LOGFONTW LogFontW; 01590 BOOL fUnicode, fRet; 01591 01592 pClientImc = ImmLockClientImc(hImc); 01593 if (pClientImc == NULL) { 01594 RIPMSG1(RIP_WARNING, "ImmGetCompositionFontA: Invalid hImc %lx.", hImc); 01595 return FALSE; 01596 } 01597 01598 fUnicode = TestICF(pClientImc, IMCF_UNICODE); 01599 01600 ImmUnlockClientImc(pClientImc); 01601 01602 pInputContext = ImmLockIMC(hImc); 01603 if (pInputContext == NULL) { 01604 RIPMSG1(RIP_WARNING, "ImmGetCompositionFontA: Lock hImc %lx failed.", hImc); 01605 return FALSE; 01606 } 01607 01608 if (fUnicode) { 01609 01610 ImmUnlockIMC(hImc); 01611 01612 if (ImmGetCompositionFontW(hImc, &LogFontW)) { 01613 LFontWtoLFontA(&LogFontW, lpLogFontA); 01614 return (TRUE); 01615 } 01616 01617 return FALSE; 01618 } 01619 01620 if ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) { 01621 *lpLogFontA = pInputContext->lfFont.A; 01622 fRet = TRUE; 01623 } 01624 else { 01625 fRet = FALSE; 01626 } 01627 01628 ImmUnlockIMC(hImc); 01629 01630 return fRet; 01631 } 01632 01633 01634 /***************************************************************************\ 01635 * ImmGetCompositionFontW 01636 * 01637 * Opens or closes the IME. 01638 * 01639 * History: 01640 * 27-Feb-1995 wkwok Created 01641 \***************************************************************************/ 01642 01643 BOOL WINAPI ImmGetCompositionFontW( 01644 HIMC hImc, 01645 LPLOGFONTW lpLogFontW) 01646 { 01647 PCLIENTIMC pClientImc; 01648 PINPUTCONTEXT pInputContext; 01649 LOGFONTA LogFontA; 01650 BOOL fUnicode, fRet; 01651 01652 pClientImc = ImmLockClientImc(hImc); 01653 if (pClientImc == NULL) { 01654 RIPMSG1(RIP_WARNING, "ImmGetCompositionFontW: Invalid hImc %lx.", hImc); 01655 return FALSE; 01656 } 01657 01658 fUnicode = TestICF(pClientImc, IMCF_UNICODE); 01659 01660 ImmUnlockClientImc(pClientImc); 01661 01662 pInputContext = ImmLockIMC(hImc); 01663 if (!pInputContext) { 01664 RIPMSG1(RIP_WARNING, "ImmGetCompositionFontW: Lock hImc %lx failed.", hImc); 01665 return (FALSE); 01666 } 01667 01668 if (!fUnicode) { 01669 01670 ImmUnlockIMC(hImc); 01671 01672 if (ImmGetCompositionFontA(hImc, &LogFontA)) { 01673 LFontAtoLFontW(&LogFontA, lpLogFontW); 01674 return (TRUE); 01675 } 01676 01677 return FALSE; 01678 } 01679 01680 if ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) { 01681 *lpLogFontW = pInputContext->lfFont.W; 01682 fRet = TRUE; 01683 } 01684 else { 01685 fRet = FALSE; 01686 } 01687 01688 ImmUnlockIMC(hImc); 01689 01690 return fRet; 01691 } 01692 01693 01694 BOOL WINAPI ImmSetCompositionFontA( 01695 HIMC hImc, 01696 LPLOGFONTA lpLogFontA) 01697 { 01698 PCLIENTIMC pClientImc; 01699 PINPUTCONTEXT pInputContext; 01700 LOGFONTW LogFontW; 01701 HWND hWnd; 01702 BOOL fUnicode; 01703 01704 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 01705 RIPMSG1(RIP_WARNING, 01706 "ImmSetCompositionFontA: Invalid input context access %lx.", hImc); 01707 return FALSE; 01708 } 01709 01710 pClientImc = ImmLockClientImc(hImc); 01711 if (pClientImc == NULL) { 01712 RIPMSG1(RIP_WARNING, "ImmSetCompositionFontA: Invalid hImc %lx.", hImc); 01713 return FALSE; 01714 } 01715 01716 fUnicode = TestICF(pClientImc, IMCF_UNICODE); 01717 01718 ImmUnlockClientImc(pClientImc); 01719 01720 pInputContext = ImmLockIMC(hImc); 01721 if (!pInputContext) { 01722 RIPMSG1(RIP_WARNING, "ImmSetCompositionFontA: Lock hImc %lx failed.", hImc); 01723 return (FALSE); 01724 } 01725 01726 if (fUnicode) { 01727 01728 ImmUnlockIMC(hImc); 01729 01730 LFontAtoLFontW(lpLogFontA, &LogFontW); 01731 01732 return ImmSetCompositionFontW(hImc, &LogFontW); 01733 } 01734 01735 /* 01736 * Japanese 3.x applications need to receive 3.x compatible notification message. 01737 * 01738 */ 01739 if ( (GetClientInfo()->dwExpWinVer < VER40) && 01740 (PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_JAPANESE) && 01741 ! (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) && 01742 (pInputContext->cfCompForm.dwStyle != CFS_DEFAULT) ) { 01743 01744 PostMessageA( pInputContext->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, (LPARAM)NULL); 01745 } 01746 01747 pInputContext->lfFont.A = *lpLogFontA; 01748 pInputContext->fdwInit |= INIT_LOGFONT; 01749 hWnd = pInputContext->hWnd; 01750 01751 ImmUnlockIMC(hImc); 01752 01753 /* 01754 * inform IME and UI about the change of composition font. 01755 */ 01756 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, 01757 IMC_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONFONT, 0L); 01758 01759 01760 return TRUE; 01761 } 01762 01763 01764 BOOL WINAPI ImmSetCompositionFontW( 01765 HIMC hImc, 01766 LPLOGFONTW lpLogFontW) 01767 { 01768 PCLIENTIMC pClientImc; 01769 PINPUTCONTEXT pInputContext; 01770 LOGFONTA LogFontA; 01771 HWND hWnd; 01772 BOOL fUnicode; 01773 01774 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 01775 RIPMSG1(RIP_WARNING, 01776 "ImmSetCompositionFontW: Invalid input context access %lx.", hImc); 01777 return FALSE; 01778 } 01779 01780 pClientImc = ImmLockClientImc(hImc); 01781 if (pClientImc == NULL) { 01782 RIPMSG1(RIP_WARNING, "ImmSetCompositionFontW: Invalid hImc %lx.", hImc); 01783 return (FALSE); 01784 } 01785 01786 fUnicode = TestICF(pClientImc, IMCF_UNICODE); 01787 01788 ImmUnlockClientImc(pClientImc); 01789 01790 pInputContext = ImmLockIMC(hImc); 01791 if (!pInputContext) { 01792 RIPMSG1(RIP_WARNING, "ImmSetCompositionFontW: Lock hImc %lx failed.", hImc); 01793 return (FALSE); 01794 } 01795 01796 if (!fUnicode) { 01797 01798 ImmUnlockIMC(hImc); 01799 01800 LFontWtoLFontA(lpLogFontW, &LogFontA); 01801 01802 return ImmSetCompositionFontA(hImc, &LogFontA); 01803 } 01804 01805 /* 01806 * Japanese 3.x applications need to receive 3.x compatible notification message. 01807 * 01808 */ 01809 if ( (GetClientInfo()->dwExpWinVer < VER40) && 01810 (PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_JAPANESE) && 01811 ! (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) && 01812 (pInputContext->cfCompForm.dwStyle != CFS_DEFAULT) ) { 01813 01814 PostMessageW( pInputContext->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, (LPARAM)NULL); 01815 } 01816 pInputContext->lfFont.W = *lpLogFontW; 01817 pInputContext->fdwInit |= INIT_LOGFONT; 01818 hWnd = pInputContext->hWnd; 01819 01820 ImmUnlockIMC(hImc); 01821 01822 /* 01823 * inform IME and UI about the change of composition font. 01824 */ 01825 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, 01826 IMC_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONFONT, 0L); 01827 01828 return TRUE; 01829 } 01830 01831 01832 /***************************************************************************\ 01833 * ImmGetConversionListA 01834 * 01835 * Obtains the list of FE character or word from one character or word. 01836 * 01837 * History: 01838 * 27-Feb-1995 wkwok Created 01839 \***************************************************************************/ 01840 01841 DWORD WINAPI ImmGetConversionListA( 01842 HKL hKL, 01843 HIMC hImc, 01844 LPCSTR lpszSrc, 01845 LPCANDIDATELIST lpCandListA, 01846 DWORD dwBufLen, 01847 UINT uFlag) 01848 { 01849 PIMEDPI pImeDpi; 01850 DWORD dwRet; 01851 LPWSTR lpwszSrc; 01852 DWORD dwBufTemp; 01853 LPCANDIDATELIST lpCandListW; 01854 INT i; 01855 DWORD dwCodePage; 01856 01857 pImeDpi = FindOrLoadImeDpi(hKL); 01858 01859 if (pImeDpi == NULL) { 01860 RIPMSG1(RIP_WARNING, 01861 "ImmGetConversionListA: cannot find DPI entry for hkl=%lx", hKL); 01862 return (0); 01863 } 01864 01865 dwCodePage = IMECodePage(pImeDpi); 01866 01867 if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) { 01868 /* 01869 * This is an ANSI call to an ANSI IME. 01870 */ 01871 dwRet = (*pImeDpi->pfn.ImeConversionList.a)(hImc, lpszSrc, 01872 lpCandListA, dwBufLen, uFlag); 01873 ImmUnlockImeDpi(pImeDpi); 01874 return dwRet; 01875 } 01876 01877 ImmUnlockImeDpi(pImeDpi); 01878 01879 /* 01880 * This is an ANSI call to an Unicode IME. 01881 */ 01882 if (lpszSrc != NULL) { 01883 01884 dwBufTemp = (strlen(lpszSrc) + 1) * sizeof(WCHAR); 01885 01886 lpwszSrc = ImmLocalAlloc(0, dwBufTemp); 01887 if (lpwszSrc == NULL) 01888 return (0); 01889 01890 i = MultiByteToWideChar(dwCodePage, 01891 (DWORD)MB_PRECOMPOSED, 01892 (LPSTR)lpszSrc, // src 01893 (INT)strlen(lpszSrc), 01894 (LPWSTR)lpwszSrc, // dest 01895 (INT)dwBufTemp/sizeof(WCHAR)); 01896 01897 lpwszSrc[i] = '\0'; 01898 } 01899 else { 01900 lpwszSrc = NULL; 01901 } 01902 01903 /* 01904 * Query the CandidateListW size required. 01905 */ 01906 dwBufTemp = ImmGetConversionListW(hKL, hImc, lpwszSrc, NULL, 0, uFlag); 01907 01908 if (dwBufTemp == 0 || (lpCandListW = ImmLocalAlloc(0, dwBufTemp)) == NULL) { 01909 if (lpwszSrc) 01910 ImmLocalFree(lpwszSrc); 01911 return (0); 01912 } 01913 01914 /* 01915 * Now get the actual CandidateListW. 01916 */ 01917 dwBufTemp = ImmGetConversionListW(hKL, hImc, lpwszSrc, 01918 lpCandListW, dwBufTemp, uFlag); 01919 01920 /* 01921 * Query the CandidateListA size required. 01922 */ 01923 if (dwBufTemp != 0) { 01924 dwBufTemp = InternalGetCandidateListWtoA(lpCandListW, NULL, 0, dwCodePage); 01925 } 01926 01927 if (dwBufLen == 0 || dwBufTemp == 0) { 01928 /* 01929 * Query required buffer size or error has happened. 01930 */ 01931 dwRet = dwBufTemp; 01932 } 01933 else if (dwBufLen < dwBufTemp) { 01934 /* 01935 * Not enough buffer area. 01936 */ 01937 dwRet = 0; 01938 } 01939 else { 01940 /* 01941 * Get the actual CandidateListA 01942 */ 01943 dwRet = InternalGetCandidateListWtoA(lpCandListW, lpCandListA, dwBufLen, dwCodePage); 01944 } 01945 01946 if (lpwszSrc) 01947 ImmLocalFree(lpwszSrc); 01948 ImmLocalFree(lpCandListW); 01949 01950 return dwRet; 01951 01952 } 01953 01954 01955 /***************************************************************************\ 01956 * ImmGetConversionListW 01957 * 01958 * Obtains the list of FE character or word from one character or word. 01959 * 01960 * History: 01961 * 27-Feb-1995 wkwok Created 01962 \***************************************************************************/ 01963 01964 DWORD WINAPI ImmGetConversionListW( 01965 HKL hKL, 01966 HIMC hImc, 01967 LPCWSTR lpwszSrc, 01968 LPCANDIDATELIST lpCandListW, 01969 DWORD dwBufLen, 01970 UINT uFlag) 01971 { 01972 PIMEDPI pImeDpi; 01973 DWORD dwRet; 01974 LPSTR lpszSrc; 01975 DWORD dwBufTemp; 01976 LPCANDIDATELIST lpCandListA; 01977 BOOL bUDC; 01978 INT i; 01979 DWORD dwCodePage; 01980 01981 pImeDpi = FindOrLoadImeDpi(hKL); 01982 01983 if (pImeDpi == NULL) { 01984 RIPMSG1(RIP_WARNING, 01985 "ImmGetConversionListW: cannot find DPI entry for hkl=%lx", hKL); 01986 return (0); 01987 } 01988 01989 dwCodePage = IMECodePage(pImeDpi); 01990 01991 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) { 01992 /* 01993 * This is an Unicode call to an Unicode IME. 01994 */ 01995 dwRet = (*pImeDpi->pfn.ImeConversionList.w)(hImc, lpwszSrc, 01996 lpCandListW, dwBufLen, uFlag); 01997 ImmUnlockImeDpi(pImeDpi); 01998 return dwRet; 01999 } 02000 02001 ImmUnlockImeDpi(pImeDpi); 02002 02003 /* 02004 * This is an Unicode call to an ANSI IME. 02005 */ 02006 if (lpwszSrc != NULL) { 02007 02008 dwBufTemp = (wcslen(lpwszSrc) + 1) * sizeof(WCHAR); 02009 02010 lpszSrc = ImmLocalAlloc(0, dwBufTemp); 02011 if (lpszSrc == NULL) 02012 return (0); 02013 02014 i = WideCharToMultiByte(dwCodePage, 02015 (DWORD)0, 02016 lpwszSrc, 02017 (INT)wcslen(lpwszSrc), 02018 (LPSTR)lpszSrc, 02019 (INT)dwBufTemp, 02020 (LPSTR)NULL, 02021 (LPBOOL)&bUDC); 02022 02023 lpszSrc[i] = '\0'; 02024 } 02025 else { 02026 lpszSrc = NULL; 02027 } 02028 02029 /* 02030 * Query the CandidateListA size required. 02031 */ 02032 dwBufTemp = ImmGetConversionListA(hKL, hImc, lpszSrc, NULL, 0, uFlag); 02033 02034 if (dwBufTemp == 0 || (lpCandListA = ImmLocalAlloc(0, dwBufTemp)) == NULL) { 02035 if (lpszSrc) 02036 ImmLocalFree(lpszSrc); 02037 02038 return (0); 02039 } 02040 02041 /* 02042 * Now get the actual CandidateListA. 02043 */ 02044 dwBufTemp = ImmGetConversionListA(hKL, hImc, lpszSrc, 02045 lpCandListA, dwBufTemp, uFlag); 02046 02047 /* 02048 * Query the CandidateListW size required. 02049 */ 02050 if (dwBufTemp != 0) { 02051 dwBufTemp = InternalGetCandidateListAtoW(lpCandListA, NULL, 0, dwCodePage); 02052 } 02053 02054 if (dwBufLen == 0 || dwBufTemp == 0) { 02055 /* 02056 * Query required buffer size or error has happened. 02057 */ 02058 dwRet = dwBufTemp; 02059 } 02060 else if (dwBufLen < dwBufTemp) { 02061 /* 02062 * Not enough buffer area. 02063 */ 02064 dwRet = 0; 02065 } 02066 else { 02067 /* 02068 * Get the actual CandidateListW 02069 */ 02070 dwRet = InternalGetCandidateListAtoW(lpCandListA, lpCandListW, dwBufLen, dwCodePage); 02071 } 02072 02073 if (lpszSrc) 02074 ImmLocalFree(lpszSrc); 02075 ImmLocalFree(lpCandListA); 02076 02077 return dwRet; 02078 } 02079 02080 02081 /***************************************************************************\ 02082 * ImmGetStatusWindowPos 02083 * 02084 * Gets the position, in screen coordinates, of the status window. 02085 * 02086 * History: 02087 * 27-Feb-1995 wkwok Created 02088 \***************************************************************************/ 02089 02090 BOOL WINAPI ImmGetStatusWindowPos( 02091 HIMC hImc, 02092 LPPOINT lpptPos) 02093 { 02094 PINPUTCONTEXT pInputContext; 02095 BOOL fStatusWndPosInited; 02096 02097 pInputContext = ImmLockIMC(hImc); 02098 if (!pInputContext) { 02099 RIPMSG1(RIP_WARNING, "ImmGetStatusWindowPos: Lock hImc %lx failed", hImc); 02100 return FALSE; 02101 } 02102 02103 fStatusWndPosInited = ((pInputContext->fdwInit & INIT_STATUSWNDPOS) == INIT_STATUSWNDPOS); 02104 ImmUnlockIMC(hImc); 02105 02106 if (fStatusWndPosInited) { 02107 *lpptPos = pInputContext->ptStatusWndPos; 02108 return TRUE; 02109 } 02110 02111 return FALSE; 02112 } 02113 02114 02115 BOOL WINAPI ImmSetStatusWindowPos( 02116 HIMC hImc, 02117 LPPOINT lpptPos) 02118 { 02119 PINPUTCONTEXT pInputContext; 02120 HWND hWnd; 02121 02122 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 02123 RIPMSG1(RIP_WARNING, 02124 "ImmSetStatusWindowPos: Invalid input context access %lx.", hImc); 02125 return FALSE; 02126 } 02127 02128 pInputContext = ImmLockIMC(hImc); 02129 if (!pInputContext) { 02130 RIPMSG1(RIP_WARNING, "ImmSetStatusWindowPos: Lock hImc %lx failed", hImc); 02131 return (FALSE); 02132 } 02133 02134 pInputContext->ptStatusWndPos = *lpptPos; 02135 pInputContext->fdwInit |= INIT_STATUSWNDPOS; 02136 02137 hWnd = pInputContext->hWnd; 02138 02139 ImmUnlockIMC(hImc); 02140 02141 /* 02142 * inform IME and UI about the change of composition font. 02143 */ 02144 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, 02145 IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0L); 02146 02147 return TRUE; 02148 } 02149 02150 02151 /***************************************************************************\ 02152 * ImmGetCompositionWindow 02153 * 02154 * Gets the information of the composition window. 02155 * 02156 * History: 02157 * 27-Feb-1995 wkwok Created 02158 \***************************************************************************/ 02159 02160 BOOL WINAPI ImmGetCompositionWindow( 02161 HIMC hImc, 02162 LPCOMPOSITIONFORM lpCompForm) 02163 { 02164 PINPUTCONTEXT pInputContext; 02165 BOOL fCompFormInited; 02166 02167 pInputContext = ImmLockIMC(hImc); 02168 if (!pInputContext) { 02169 RIPMSG1(RIP_WARNING, "ImmGetCompositionWindow: Lock hImc %lx failed", hImc); 02170 return FALSE; 02171 } 02172 02173 fCompFormInited = ((pInputContext->fdwInit & INIT_COMPFORM) == INIT_COMPFORM); 02174 ImmUnlockIMC(hImc); 02175 02176 if (fCompFormInited) { 02177 *lpCompForm = pInputContext->cfCompForm; 02178 return TRUE; 02179 } 02180 02181 return FALSE; 02182 } 02183 02184 02185 BOOL WINAPI ImmSetCompositionWindow( 02186 HIMC hImc, 02187 LPCOMPOSITIONFORM lpCompForm) 02188 { 02189 PINPUTCONTEXT pInputContext; 02190 HWND hWnd; 02191 02192 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 02193 RIPMSG1(RIP_WARNING, 02194 "ImmSetCompositionWindow: Invalid input context access %lx.", hImc); 02195 return FALSE; 02196 } 02197 02198 pInputContext = ImmLockIMC(hImc); 02199 if (!pInputContext) { 02200 RIPMSG1(RIP_WARNING, "ImmSetCompositionWindow: Lock hImc %lx failed", hImc); 02201 return FALSE; 02202 } 02203 02204 pInputContext->cfCompForm = *lpCompForm; 02205 pInputContext->fdwInit |= INIT_COMPFORM; 02206 02207 /* 02208 * Only WINNLS.DLL set F31COMPAT_MCWHIDDEN. 02209 * When the apps or edit control calls this API, we need to remove 02210 * F31COMPAT_MCWHIDDEN. 02211 */ 02212 if (pInputContext->fdw31Compat & F31COMPAT_CALLFROMWINNLS) 02213 pInputContext->fdw31Compat &= ~F31COMPAT_CALLFROMWINNLS; 02214 else 02215 pInputContext->fdw31Compat &= ~F31COMPAT_MCWHIDDEN; 02216 02217 hWnd = pInputContext->hWnd; 02218 02219 ImmUnlockIMC(hImc); 02220 02221 /* 02222 * inform IME and UI about the change of composition window. 02223 */ 02224 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, 02225 IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0L); 02226 02227 return TRUE; 02228 } 02229 02230 02231 /***************************************************************************\ 02232 * ImmGetCandidateWindow 02233 * 02234 * Gets the information of the candidate window specified by dwIndex. 02235 * 02236 * History: 02237 * 27-Feb-1995 wkwok Created 02238 \***************************************************************************/ 02239 02240 BOOL WINAPI ImmGetCandidateWindow( 02241 HIMC hImc, 02242 DWORD dwIndex, 02243 LPCANDIDATEFORM lpCandForm) 02244 { 02245 PINPUTCONTEXT pInputContext; 02246 02247 pInputContext = ImmLockIMC(hImc); 02248 if (!pInputContext) { 02249 RIPMSG1(RIP_WARNING, "ImmGetCandidateWindow: Lock hImc %lx failed", hImc); 02250 return FALSE; 02251 } 02252 02253 ImmUnlockIMC(hImc); 02254 02255 if (pInputContext->cfCandForm[dwIndex].dwIndex == -1) { 02256 ImmUnlockIMC(hImc); 02257 return (FALSE); 02258 } 02259 02260 *lpCandForm = pInputContext->cfCandForm[dwIndex]; 02261 ImmUnlockIMC(hImc); 02262 return TRUE; 02263 } 02264 02265 02266 BOOL WINAPI ImmSetCandidateWindow( 02267 HIMC hImc, 02268 LPCANDIDATEFORM lpCandForm) 02269 { 02270 PINPUTCONTEXT pInputContext; 02271 HWND hWnd; 02272 02273 if (lpCandForm->dwIndex >= 4) // over flow candidate index 02274 return (FALSE); 02275 02276 if (GetInputContextThread(hImc) != GetCurrentThreadId()) { 02277 RIPMSG1(RIP_WARNING, 02278 "ImmSetCandidateWindow: Invalid input context access %lx.", hImc); 02279 return FALSE; 02280 } 02281 02282 pInputContext = ImmLockIMC(hImc); 02283 if (!pInputContext) { 02284 RIPMSG1(RIP_WARNING, "ImmSetCandidateWindow: Lock hImc %lx failed", hImc); 02285 return FALSE; 02286 } 02287 02288 pInputContext->cfCandForm[lpCandForm->dwIndex] = *lpCandForm; 02289 02290 hWnd = pInputContext->hWnd; 02291 02292 ImmUnlockIMC(hImc); 02293 02294 /* 02295 * inform IME and UI about the change of composition window. 02296 */ 02297 MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, IMC_SETCANDIDATEPOS, 02298 IMN_SETCANDIDATEPOS, (LPARAM)(0x01 << lpCandForm->dwIndex)); 02299 02300 return TRUE; 02301 } 02302 02303 02304 #define GetCompInfoA(Component) \ 02305 if (!dwBufLen) { /* query required buffer size */ \ 02306 /* not include \0 */ \ 02307 dwBufLen = pCompStr->dw ## Component ## Len * sizeof(CHAR); \ 02308 } else { \ 02309 if (dwBufLen > pCompStr->dw ## Component ## Len * sizeof(CHAR)) { \ 02310 dwBufLen = pCompStr->dw ## Component ## Len * sizeof(CHAR); \ 02311 } \ 02312 /* don't copy \0, maybe there is actually none */ \ 02313 RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE)pCompStr + \ 02314 pCompStr->dw ## Component ## Offset, dwBufLen); \ 02315 } 02316 02317 #define GetCompInfoW(Component) \ 02318 if (!dwBufLen) { /* query required buffer size */ \ 02319 /* not include \0 */ \ 02320 dwBufLen = pCompStr->dw ## Component ## Len * sizeof(WCHAR); \ 02321 } else { \ 02322 if (dwBufLen > pCompStr->dw ## Component ## Len * sizeof(WCHAR)) { \ 02323 dwBufLen = pCompStr->dw ## Component ## Len * sizeof(WCHAR); \ 02324 } \ 02325 /* don't copy \0, maybe there is actually none */ \ 02326 RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE)pCompStr + \ 02327 pCompStr->dw ## Component ## Offset, dwBufLen); \ 02328 } 02329 02330 /***************************************************************************\ 02331 * InternalGetCompositionStringA 02332 * 02333 * Internal version of ImmGetCompositionStringA. 02334 * 02335 * History: 02336 * 28-Feb-1995 wkwok Created 02337 \***************************************************************************/ 02338 02339 LONG InternalGetCompositionStringA( 02340 PCOMPOSITIONSTRING pCompStr, 02341 DWORD dwIndex, 02342 LPVOID lpBuf, 02343 DWORD dwBufLen, 02344 BOOL fAnsiImc, 02345 DWORD dwCodePage) 02346 { 02347 if (fAnsiImc) { 02348 /* 02349 * Composition string in input context is of ANSI style. 02350 */ 02351 switch (dwIndex) { 02352 case GCS_COMPSTR: 02353 GetCompInfoA(CompStr); 02354 break; 02355 case GCS_COMPATTR: 02356 GetCompInfoA(CompAttr); 02357 break; 02358 case GCS_COMPREADSTR: 02359 GetCompInfoA(CompReadStr); 02360 break; 02361 case GCS_COMPREADATTR: 02362 GetCompInfoA(CompReadAttr); 02363 break; 02364 case GCS_COMPREADCLAUSE: 02365 GetCompInfoA(CompReadClause); 02366 break; 02367 case GCS_CURSORPOS: 02368 dwBufLen = (LONG)pCompStr->dwCursorPos; 02369 break; 02370 case GCS_DELTASTART: 02371 dwBufLen = (LONG)pCompStr->dwDeltaStart; 02372 break; 02373 case GCS_RESULTSTR: 02374 GetCompInfoA(ResultStr); 02375 break; 02376 case GCS_RESULTCLAUSE: 02377 GetCompInfoA(ResultClause); 02378 break; 02379 case GCS_RESULTREADSTR: 02380 GetCompInfoA(ResultReadStr); 02381 break; 02382 case GCS_RESULTREADCLAUSE: 02383 GetCompInfoA(ResultReadClause); 02384 break; 02385 case GCS_COMPCLAUSE: 02386 GetCompInfoA(CompClause); 02387 break; 02388 default: 02389 dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL; 02390 break; 02391 } 02392 02393 return (LONG)dwBufLen; 02394 } 02395 02396 /* 02397 * ANSI caller, Unicode input context/composition string. 02398 */ 02399 switch (dwIndex) { 02400 case GCS_COMPSTR: 02401 case GCS_COMPREADSTR: 02402 case GCS_RESULTSTR: 02403 case GCS_RESULTREADSTR: 02404 { 02405 DWORD dwStrSize; 02406 LPWSTR lpStrW; 02407 BOOL bUDC; 02408 02409 /* 02410 * Get ANSI string from Unicode composition string. 02411 */ 02412 dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex, 02413 NULL, 0, fAnsiImc, dwCodePage); 02414 02415 lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR)); 02416 if (lpStrW == NULL) { 02417 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure."); 02418 return (LONG)IMM_ERROR_GENERAL; 02419 } 02420 02421 dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex, 02422 lpStrW, dwStrSize, fAnsiImc, dwCodePage); 02423 02424 dwBufLen = WideCharToMultiByte(dwCodePage, 02425 (DWORD)0, 02426 lpStrW, // src 02427 wcslen(lpStrW), 02428 (LPSTR)lpBuf, // dest 02429 dwBufLen, 02430 (LPSTR)NULL, 02431 (LPBOOL)&bUDC); 02432 02433 ImmLocalFree(lpStrW); 02434 break; 02435 } 02436 02437 case GCS_COMPATTR: 02438 case GCS_COMPREADATTR: 02439 { 02440 DWORD dwAttrLenW, dwIndexStr, dwStrSize; 02441 PBYTE lpAttrA, lpAttrW; 02442 LPSTR lpStrA, lpStrT; 02443 CHAR c; 02444 02445 /* 02446 * Get ANSI attribute from Unicode composition attribute. 02447 */ 02448 switch (dwIndex) { 02449 case GCS_COMPATTR: 02450 lpAttrW = (PBYTE)pCompStr + pCompStr->dwCompAttrOffset; 02451 dwAttrLenW = pCompStr->dwCompAttrLen; 02452 dwIndexStr = GCS_COMPSTR; 02453 break; 02454 case GCS_COMPREADATTR: 02455 lpAttrW = (PBYTE)pCompStr + pCompStr->dwCompReadAttrOffset; 02456 dwAttrLenW = pCompStr->dwCompReadAttrLen; 02457 dwIndexStr = GCS_COMPREADSTR; 02458 break; 02459 } 02460 02461 if (dwAttrLenW == 0) { 02462 /* 02463 * No CompAttr or CompReadAttr exists, do nothing. 02464 */ 02465 return 0; 02466 } 02467 02468 dwStrSize = InternalGetCompositionStringA(pCompStr, 02469 dwIndexStr, NULL, 0, fAnsiImc, dwCodePage); 02470 02471 if (dwStrSize == (DWORD)(LONG)IMM_ERROR_GENERAL) { 02472 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL."); 02473 return (LONG)IMM_ERROR_GENERAL; 02474 } 02475 02476 /* 02477 * Query required size or early exit on error. 02478 */ 02479 if (dwBufLen == 0 || dwStrSize == 0) 02480 return dwStrSize; 02481 02482 lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR)); 02483 if (lpStrA == NULL) { 02484 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure."); 02485 return (LONG)IMM_ERROR_GENERAL; 02486 } 02487 02488 dwStrSize = InternalGetCompositionStringA(pCompStr, 02489 dwIndexStr, lpStrA, dwStrSize, fAnsiImc, dwCodePage); 02490 02491 if (dwStrSize == (LONG)IMM_ERROR_GENERAL) { 02492 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL."); 02493 ImmLocalFree(lpStrA); 02494 return (LONG)IMM_ERROR_GENERAL; 02495 } 02496 02497 lpStrT = lpStrA; 02498 lpAttrA = (PBYTE)lpBuf; 02499 02500 while ((c=*lpStrT++) != '\0' && dwBufLen != 0 && dwAttrLenW-- != 0) { 02501 if (IsDBCSLeadByteEx(dwCodePage, c)) { 02502 if (dwBufLen >= 2) { 02503 *lpAttrA++ = *lpAttrW; 02504 *lpAttrA++ = *lpAttrW; 02505 dwBufLen--; 02506 } 02507 else { 02508 *lpAttrA++ = *lpAttrW; 02509 } 02510 lpStrT++; 02511 } 02512 else { 02513 *lpAttrA++ = *lpAttrW; 02514 } 02515 lpAttrW++; 02516 dwBufLen--; 02517 } 02518 02519 dwBufLen = (DWORD)(lpAttrA - (PBYTE)lpBuf); 02520 02521 ImmLocalFree(lpStrA); 02522 break; 02523 } 02524 02525 case GCS_COMPCLAUSE: 02526 case GCS_COMPREADCLAUSE: 02527 case GCS_RESULTCLAUSE: 02528 case GCS_RESULTREADCLAUSE: 02529 { 02530 LPWSTR lpStrW; 02531 DWORD dwClauseLen, dwBufLenA; 02532 LPDWORD lpdwSrc, lpdwDst; 02533 UINT i; 02534 02535 /* 02536 * Get ANSI clause from Unicode composition clause. 02537 */ 02538 switch (dwIndex) { 02539 case GCS_COMPCLAUSE: 02540 lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset); 02541 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompClauseOffset); 02542 dwClauseLen = pCompStr->dwCompClauseLen; 02543 break; 02544 case GCS_COMPREADCLAUSE: 02545 lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompReadStrOffset); 02546 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompReadClauseOffset); 02547 dwClauseLen = pCompStr->dwCompReadClauseLen; 02548 break; 02549 case GCS_RESULTCLAUSE: 02550 lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwResultStrOffset); 02551 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultClauseOffset); 02552 dwClauseLen = pCompStr->dwResultClauseLen; 02553 break; 02554 case GCS_RESULTREADCLAUSE: 02555 lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwResultReadStrOffset); 02556 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultReadClauseOffset); 02557 dwClauseLen = pCompStr->dwResultReadClauseLen; 02558 break; 02559 } 02560 02561 /* 02562 * Query clause length or early exit on error. 02563 */ 02564 if (dwBufLen == 0 || (LONG)dwClauseLen < 0) { 02565 dwBufLen = dwClauseLen; 02566 break; 02567 } 02568 02569 lpdwDst = (LPDWORD)lpBuf; 02570 dwBufLenA = dwBufLen / sizeof(DWORD); 02571 02572 for (i = 0; i < dwClauseLen / sizeof(DWORD) && dwBufLenA != 0; i++) { 02573 *lpdwDst++ = CalcCharacterPositionWtoA(*lpdwSrc++, lpStrW, dwCodePage); 02574 dwBufLenA--; 02575 } 02576 02577 dwBufLen = i * sizeof(DWORD); 02578 break; 02579 } 02580 02581 case GCS_CURSORPOS: 02582 case GCS_DELTASTART: 02583 /* 02584 * Get ANSI cursor/delta start position from Unicode composition string. 02585 */ 02586 switch (dwIndex) { 02587 case GCS_CURSORPOS: 02588 dwBufLen = pCompStr->dwCursorPos; 02589 break; 02590 case GCS_DELTASTART: 02591 dwBufLen = pCompStr->dwDeltaStart; 02592 break; 02593 } 02594 02595 if ((LONG)dwBufLen > 0) { 02596 dwBufLen = CalcCharacterPositionWtoA(dwBufLen, 02597 (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset), 02598 dwCodePage); 02599 } 02600 break; 02601 02602 default: 02603 dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL; 02604 } 02605 02606 return (LONG)dwBufLen; 02607 } 02608 02609 02610 /***************************************************************************\ 02611 * InternalGetCompositionStringW 02612 * 02613 * Internal version of ImmGetCompositionStringW. 02614 * 02615 * History: 02616 * 28-Feb-1995 wkwok Created 02617 \***************************************************************************/ 02618 02619 LONG InternalGetCompositionStringW( 02620 PCOMPOSITIONSTRING pCompStr, 02621 DWORD dwIndex, 02622 LPVOID lpBuf, 02623 DWORD dwBufLen, 02624 BOOL fAnsiImc, 02625 DWORD dwCodePage) 02626 { 02627 if (!fAnsiImc) { 02628 /* 02629 * Composition string in input context is of Unicode style. 02630 */ 02631 switch (dwIndex) { 02632 case GCS_COMPSTR: 02633 GetCompInfoW(CompStr); 02634 break; 02635 case GCS_COMPATTR: // ANSI-only 02636 GetCompInfoA(CompAttr); 02637 break; 02638 case GCS_COMPREADSTR: 02639 GetCompInfoW(CompReadStr); 02640 break; 02641 case GCS_COMPREADATTR: // ANSI-only 02642 GetCompInfoA(CompReadAttr); 02643 break; 02644 case GCS_COMPREADCLAUSE: // ANSI-only 02645 GetCompInfoA(CompReadClause); 02646 break; 02647 case GCS_CURSORPOS: 02648 dwBufLen = (LONG)pCompStr->dwCursorPos; 02649 break; 02650 case GCS_DELTASTART: 02651 dwBufLen = (LONG)pCompStr->dwDeltaStart; 02652 break; 02653 case GCS_RESULTSTR: 02654 GetCompInfoW(ResultStr); 02655 break; 02656 case GCS_RESULTCLAUSE: // ANSI-only 02657 GetCompInfoA(ResultClause); 02658 break; 02659 case GCS_RESULTREADSTR: 02660 GetCompInfoW(ResultReadStr); 02661 break; 02662 case GCS_RESULTREADCLAUSE: // ANSI-only 02663 GetCompInfoA(ResultReadClause); 02664 break; 02665 case GCS_COMPCLAUSE: // ANSI-only 02666 GetCompInfoA(CompClause); 02667 break; 02668 default: 02669 dwBufLen = (DWORD)IMM_ERROR_GENERAL; 02670 break; 02671 } 02672 02673 return (LONG)dwBufLen; 02674 } 02675 02676 /* 02677 * Unicode caller, ANSI input context/composition string. 02678 */ 02679 switch (dwIndex) { 02680 case GCS_COMPSTR: 02681 case GCS_COMPREADSTR: 02682 case GCS_RESULTSTR: 02683 case GCS_RESULTREADSTR: 02684 { 02685 DWORD dwStrSize; 02686 LPSTR lpStrA; 02687 02688 /* 02689 * Get Unicode string from ANSI composition string. 02690 */ 02691 dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex, 02692 NULL, 0, fAnsiImc, dwCodePage); 02693 02694 lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR)); 02695 if (lpStrA == NULL) { 02696 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure."); 02697 return (LONG)IMM_ERROR_GENERAL; 02698 } 02699 02700 dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex, 02701 lpStrA, dwStrSize, fAnsiImc, dwCodePage); 02702 02703 dwBufLen = MultiByteToWideChar(dwCodePage, 02704 (DWORD)MB_PRECOMPOSED, 02705 lpStrA, // src 02706 strlen(lpStrA), 02707 (LPWSTR)lpBuf, // dest 02708 (INT)dwBufLen); 02709 02710 dwBufLen *= sizeof(WCHAR); // return number of bytes required. 02711 02712 ImmLocalFree(lpStrA); 02713 break; 02714 } 02715 02716 case GCS_COMPATTR: 02717 case GCS_COMPREADATTR: 02718 { 02719 DWORD dwAttrLenA, dwIndexStr, dwStrSize; 02720 PBYTE lpAttrA, lpAttrW; 02721 LPWSTR lpStrW, lpStrT; 02722 ULONG MultiByteSize; 02723 WCHAR wc; 02724 02725 /* 02726 * Get Unicode attribute from ANSI composition attribute. 02727 */ 02728 switch (dwIndex) { 02729 case GCS_COMPATTR: 02730 lpAttrA = (PBYTE)pCompStr + pCompStr->dwCompAttrOffset; 02731 dwAttrLenA = pCompStr->dwCompAttrLen; 02732 dwIndexStr = GCS_COMPSTR; 02733 break; 02734 case GCS_COMPREADATTR: 02735 lpAttrA = (PBYTE)pCompStr + pCompStr->dwCompReadAttrOffset; 02736 dwAttrLenA = pCompStr->dwCompReadAttrLen; 02737 dwIndexStr = GCS_COMPREADSTR; 02738 break; 02739 } 02740 02741 if (dwAttrLenA == 0) { 02742 /* 02743 * No CompAttr or CompReadAttr exists, do nothing. 02744 */ 02745 return 0; 02746 } 02747 02748 dwStrSize = InternalGetCompositionStringW(pCompStr, 02749 dwIndexStr, NULL, 0, fAnsiImc, dwCodePage); 02750 02751 if (dwStrSize == (DWORD)(LONG)IMM_ERROR_GENERAL) { 02752 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL."); 02753 return (LONG)IMM_ERROR_GENERAL; 02754 } 02755 02756 /* 02757 * Query required size or early exit on error. 02758 */ 02759 if (dwBufLen == 0 || dwStrSize == 0) 02760 return dwStrSize / sizeof(WCHAR); 02761 02762 lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR)); 02763 if (lpStrW == NULL) { 02764 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure."); 02765 return (LONG)IMM_ERROR_GENERAL; 02766 } 02767 02768 dwStrSize = InternalGetCompositionStringW(pCompStr, 02769 dwIndexStr, lpStrW, dwStrSize, fAnsiImc, dwCodePage); 02770 02771 if (dwStrSize == (LONG)IMM_ERROR_GENERAL) { 02772 RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL."); 02773 ImmLocalFree(lpStrW); 02774 return (LONG)IMM_ERROR_GENERAL; 02775 } 02776 02777 lpStrT = lpStrW; 02778 lpAttrW = (PBYTE)lpBuf; 02779 02780 while ((wc=*lpStrT++) != L'\0' && dwBufLen != 0 && dwAttrLenA-- != 0) { 02781 MultiByteSize = UnicodeToMultiByteSize(dwCodePage, &wc); 02782 if (MultiByteSize == 2 && dwAttrLenA != 0) { 02783 *lpAttrW++ = *lpAttrA++; 02784 dwAttrLenA--; 02785 } 02786 else { 02787 *lpAttrW++ = *lpAttrA; 02788 } 02789 lpAttrA++; 02790 dwBufLen--; 02791 } 02792 02793 dwBufLen = (DWORD)(lpAttrW - (PBYTE)lpBuf); 02794 02795 ImmLocalFree(lpStrW); 02796 break; 02797 } 02798 02799 case GCS_COMPCLAUSE: 02800 case GCS_COMPREADCLAUSE: 02801 case GCS_RESULTCLAUSE: 02802 case GCS_RESULTREADCLAUSE: 02803 { 02804 LPSTR lpStrA; 02805 DWORD dwClauseLen, dwBufLenW; 02806 LPDWORD lpdwSrc, lpdwDst; 02807 UINT i; 02808 02809 /* 02810 * Get Unicode clause from ANSI composition clause. 02811 */ 02812 switch (dwIndex) { 02813 case GCS_COMPCLAUSE: 02814 lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset); 02815 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompClauseOffset); 02816 dwClauseLen = pCompStr->dwCompClauseLen; 02817 break; 02818 case GCS_COMPREADCLAUSE: 02819 lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompReadStrOffset); 02820 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompReadClauseOffset); 02821 dwClauseLen = pCompStr->dwCompReadClauseLen; 02822 break; 02823 case GCS_RESULTCLAUSE: 02824 lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwResultStrOffset); 02825 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultClauseOffset); 02826 dwClauseLen = pCompStr->dwResultClauseLen; 02827 break; 02828 case GCS_RESULTREADCLAUSE: 02829 lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwResultReadStrOffset); 02830 lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultReadClauseOffset); 02831 dwClauseLen = pCompStr->dwResultReadClauseLen; 02832 break; 02833 } 02834 02835 02836 /* 02837 * Query clause length or early exit on error. 02838 */ 02839 if (dwBufLen == 0 || (LONG)dwClauseLen < 0) { 02840 dwBufLen = dwClauseLen; 02841 break; 02842 } 02843 02844 lpdwDst = (LPDWORD)lpBuf; 02845 dwBufLenW = dwBufLen / sizeof(DWORD); 02846 02847 for (i = 0; i < dwClauseLen / sizeof(DWORD) && dwBufLenW != 0; i++) { 02848 *lpdwDst++ = CalcCharacterPositionAtoW(*lpdwSrc++, lpStrA, dwCodePage); 02849 dwBufLenW--; 02850 } 02851 02852 dwBufLen = i * sizeof(DWORD); 02853 break; 02854 } 02855 02856 case GCS_CURSORPOS: 02857 case GCS_DELTASTART: 02858 /* 02859 * Get Unicode cursor/delta start position from ANSI composition string. 02860 */ 02861 switch (dwIndex) { 02862 case GCS_CURSORPOS: 02863 dwBufLen = pCompStr->dwCursorPos; 02864 break; 02865 case GCS_DELTASTART: 02866 dwBufLen = pCompStr->dwDeltaStart; 02867 break; 02868 } 02869 02870 if ((LONG)dwBufLen > 0) { 02871 dwBufLen = CalcCharacterPositionAtoW(dwBufLen, 02872 (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset), 02873 dwCodePage); 02874 } 02875 break; 02876 02877 default: 02878 dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL; 02879 } 02880 02881 return (LONG)dwBufLen; 02882 } 02883 02884 02885 DWORD InternalGetCandidateListAtoW( 02886 LPCANDIDATELIST lpCandListA, 02887 LPCANDIDATELIST lpCandListW, 02888 DWORD dwBufLen, 02889 DWORD dwCodePage) 02890 { 02891 LPWSTR lpCandStrW; 02892 LPSTR lpCandStrA; 02893 INT i, j; 02894 DWORD dwCandListLen; 02895 02896 dwCandListLen = sizeof(CANDIDATELIST); 02897 02898 /* 02899 * CANDIDATELIST has already contained the dwOffset[0] 02900 */ 02901 if (lpCandListA->dwCount > 0) 02902 dwCandListLen += sizeof(DWORD) * (lpCandListA->dwCount - 1); 02903 02904 for (i = 0; i < (INT)lpCandListA->dwCount; i++) { 02905 02906 lpCandStrA = (LPSTR)((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]); 02907 02908 j = MultiByteToWideChar(dwCodePage, 02909 (DWORD)MB_PRECOMPOSED, 02910 lpCandStrA, 02911 -1, 02912 (LPWSTR)NULL, 02913 0); 02914 02915 dwCandListLen += (j * sizeof(WCHAR)); 02916 } 02917 02918 dwCandListLen = DWORD_ALIGN(dwCandListLen); 02919 02920 if (dwBufLen == 0) 02921 return dwCandListLen; 02922 02923 if (dwBufLen < dwCandListLen) { 02924 RIPMSG0(RIP_WARNING, "InternalGetCandidateListAtoW: dwBufLen too small."); 02925 return 0; 02926 } 02927 02928 lpCandListW->dwSize = dwBufLen; 02929 lpCandListW->dwStyle = lpCandListA->dwStyle; 02930 lpCandListW->dwCount = lpCandListA->dwCount; 02931 lpCandListW->dwSelection = lpCandListA->dwSelection; 02932 lpCandListW->dwPageStart = lpCandListA->dwPageStart; 02933 lpCandListW->dwPageSize = lpCandListA->dwPageSize; 02934 lpCandListW->dwOffset[0] = sizeof(CANDIDATELIST); 02935 if (lpCandListW->dwCount > 0) 02936 lpCandListW->dwOffset[0] += sizeof(DWORD) * (lpCandListW->dwCount - 1); 02937 02938 dwCandListLen = dwBufLen - lpCandListW->dwOffset[0]; 02939 02940 for (i = 0; i < (INT)lpCandListW->dwCount; i++) { 02941 02942 lpCandStrA = (LPSTR) ((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]); 02943 lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]); 02944 02945 j = MultiByteToWideChar(dwCodePage, 02946 (DWORD)MB_PRECOMPOSED, 02947 lpCandStrA, 02948 -1, 02949 lpCandStrW, 02950 (INT)dwCandListLen/sizeof(WCHAR)); 02951 02952 dwCandListLen -= (j * sizeof(WCHAR)); 02953 02954 if (i < (INT)lpCandListW->dwCount - 1) 02955 lpCandListW->dwOffset[i+1] = lpCandListW->dwOffset[i] + j * sizeof(WCHAR); 02956 } 02957 02958 return dwBufLen; 02959 } 02960 02961 02962 DWORD InternalGetCandidateListWtoA( 02963 LPCANDIDATELIST lpCandListW, 02964 LPCANDIDATELIST lpCandListA, 02965 DWORD dwBufLen, 02966 DWORD dwCodePage) 02967 { 02968 LPWSTR lpCandStrW; 02969 LPSTR lpCandStrA; 02970 INT i, j; 02971 DWORD dwCandListLen; 02972 BOOL bUDC; 02973 02974 dwCandListLen = sizeof(CANDIDATELIST); 02975 02976 /* 02977 * CANDIDATELIST has already contained the dwOffset[0] 02978 */ 02979 if (lpCandListW->dwCount > 0) 02980 dwCandListLen += sizeof(DWORD) * (lpCandListW->dwCount - 1); 02981 02982 for (i = 0; i < (INT)lpCandListW->dwCount; i++) { 02983 02984 lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]); 02985 02986 j = WideCharToMultiByte(dwCodePage, 02987 (DWORD)0, 02988 lpCandStrW, 02989 -1, 02990 (LPSTR)NULL, 02991 (INT)0, 02992 (LPSTR)NULL, 02993 (LPBOOL)&bUDC); 02994 02995 dwCandListLen += (j * sizeof(CHAR)); 02996 } 02997 02998 dwCandListLen = DWORD_ALIGN(dwCandListLen); 02999 03000 if (dwBufLen == 0) 03001 return dwCandListLen; 03002 03003 if (dwBufLen < dwCandListLen) { 03004 RIPMSG0(RIP_WARNING, "InternalGetCandidateListWtoA: dwBufLen too small."); 03005 return 0; 03006 } 03007 03008 lpCandListA->dwSize = dwBufLen; 03009 lpCandListA->dwStyle = lpCandListW->dwStyle; 03010 lpCandListA->dwCount = lpCandListW->dwCount; 03011 lpCandListA->dwSelection = lpCandListW->dwSelection; 03012 lpCandListA->dwPageStart = lpCandListW->dwPageStart; 03013 lpCandListA->dwPageSize = lpCandListW->dwPageSize; 03014 lpCandListA->dwOffset[0] = sizeof(CANDIDATELIST); 03015 if (lpCandListA->dwCount > 0) 03016 lpCandListA->dwOffset[0] += sizeof(DWORD) * (lpCandListA->dwCount - 1); 03017 03018 dwCandListLen = dwBufLen - lpCandListA->dwOffset[0]; 03019 03020 for (i = 0; i < (INT)lpCandListA->dwCount; i++) { 03021 03022 lpCandStrA = (LPSTR) ((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]); 03023 lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]); 03024 03025 j = WideCharToMultiByte(dwCodePage, 03026 (DWORD)0, 03027 lpCandStrW, 03028 -1, 03029 (LPSTR)lpCandStrA, 03030 (INT)dwCandListLen, 03031 (LPSTR)NULL, 03032 (LPBOOL)&bUDC); 03033 03034 dwCandListLen -= (j * sizeof(CHAR)); 03035 03036 if (i < (INT)lpCandListA->dwCount - 1) 03037 lpCandListA->dwOffset[i+1] = lpCandListA->dwOffset[i] + j * sizeof(CHAR); 03038 } 03039 03040 return dwBufLen; 03041 } 03042 03043 /***************************************************************************\ 03044 * CalcCharacterPositionAtoW 03045 * 03046 * Calculate Unicode character position to ANSI character position. 03047 * 03048 * History: 03049 * 28-Feb-1995 wkwok Created 03050 \***************************************************************************/ 03051 03052 DWORD CalcCharacterPositionAtoW( 03053 DWORD dwCharPosA, 03054 LPSTR lpszCharStr, 03055 DWORD dwCodePage) 03056 { 03057 DWORD dwCharPosW = 0; 03058 03059 while (dwCharPosA != 0) { 03060 if (IsDBCSLeadByteEx(dwCodePage, *lpszCharStr)) { 03061 if (dwCharPosA >= 2) { 03062 dwCharPosA -= 2; 03063 } 03064 else { 03065 dwCharPosA--; 03066 } 03067 lpszCharStr += 2; 03068 } 03069 else { 03070 dwCharPosA--; 03071 lpszCharStr++; 03072 } 03073 dwCharPosW++; 03074 } 03075 03076 return dwCharPosW; 03077 } 03078 03079 03080 /***************************************************************************\ 03081 * CalcCharacterPositionWtoA 03082 * 03083 * Calculate ANSI character position to Unicode character position. 03084 * 03085 * History: 03086 * 28-Feb-1995 wkwok Created 03087 \***************************************************************************/ 03088 03089 DWORD CalcCharacterPositionWtoA( 03090 DWORD dwCharPosW, 03091 LPWSTR lpwszCharStr, 03092 DWORD dwCodePage) 03093 { 03094 DWORD dwCharPosA = 0; 03095 ULONG MultiByteSize; 03096 03097 while (dwCharPosW != 0) { 03098 MultiByteSize = UnicodeToMultiByteSize(dwCodePage, lpwszCharStr); 03099 if (MultiByteSize == 2) { 03100 dwCharPosA += 2; 03101 } 03102 else { 03103 dwCharPosA++; 03104 } 03105 dwCharPosW--; 03106 lpwszCharStr++; 03107 } 03108 03109 return dwCharPosA; 03110 } 03111 03112 03113 VOID LFontAtoLFontW( 03114 LPLOGFONTA lpLogFontA, 03115 LPLOGFONTW lpLogFontW) 03116 { 03117 INT i; 03118 03119 RtlCopyMemory(lpLogFontW, lpLogFontA, sizeof(LOGFONTA)-LF_FACESIZE); 03120 03121 i = MultiByteToWideChar(CP_ACP, // Note: font face name should use ACP for A/W conversion. 03122 MB_PRECOMPOSED, 03123 lpLogFontA->lfFaceName, 03124 strlen(lpLogFontA->lfFaceName), 03125 lpLogFontW->lfFaceName, 03126 LF_FACESIZE); 03127 03128 lpLogFontW->lfFaceName[i] = L'\0'; 03129 03130 return; 03131 } 03132 03133 03134 VOID LFontWtoLFontA( 03135 LPLOGFONTW lpLogFontW, 03136 LPLOGFONTA lpLogFontA) 03137 { 03138 INT i; 03139 BOOL bUDC; 03140 03141 RtlCopyMemory(lpLogFontA, lpLogFontW, sizeof(LOGFONTA)-LF_FACESIZE); 03142 03143 i = WideCharToMultiByte(CP_ACP, // Note: font face name should use ACP for A/W conversion. 03144 0, 03145 lpLogFontW->lfFaceName, 03146 wcslen(lpLogFontW->lfFaceName), 03147 lpLogFontA->lfFaceName, 03148 LF_FACESIZE, 03149 (LPSTR)NULL, 03150 &bUDC); 03151 03152 lpLogFontA->lfFaceName[i] = '\0'; 03153 03154 return; 03155 } 03156 03157 03158 BOOL MakeIMENotify( 03159 HIMC hImc, 03160 HWND hWnd, 03161 DWORD dwAction, 03162 DWORD dwIndex, 03163 DWORD dwValue, 03164 WPARAM wParam, 03165 LPARAM lParam) 03166 { 03167 PIMEDPI pImeDpi; 03168 DWORD dwThreadId; 03169 03170 #ifdef LATER 03171 // implement MakeIMENotifyEvent() later 03172 #endif 03173 03174 if (dwAction != 0 && (dwThreadId = GetInputContextThread(hImc)) != 0) { 03175 03176 pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId)); 03177 03178 if (pImeDpi != NULL) { 03179 (*pImeDpi->pfn.NotifyIME)(hImc, dwAction, dwIndex, dwValue); 03180 ImmUnlockImeDpi(pImeDpi); 03181 } 03182 } 03183 03184 if (hWnd != NULL && wParam != 0) 03185 SendMessage(hWnd, WM_IME_NOTIFY, wParam, lParam); 03186 03187 return TRUE; 03188 } 03189 03190 03191 03193 // Reconversion support 03195 03196 typedef enum {FROM_IME, FROM_APP} REQ_CALLER; 03197 03199 // ImmGetReconvertTotalSize 03200 // 03201 // calculate the appropriate size of the buffer, based on caller/ansi information 03202 // 03203 // History: 03204 // 28-Feb-1997 hiroyama Created 03206 03207 DWORD ImmGetReconvertTotalSize(DWORD dwSize, REQ_CALLER eCaller, BOOL bAnsiTarget) 03208 { 03209 if (dwSize < sizeof(RECONVERTSTRING)) { 03210 return 0; 03211 } 03212 if (bAnsiTarget) { 03213 dwSize -= sizeof(RECONVERTSTRING); 03214 if (eCaller == FROM_IME) { 03215 dwSize /= 2; 03216 } else { 03217 dwSize *= 2; 03218 } 03219 dwSize += sizeof(RECONVERTSTRING); 03220 } 03221 return dwSize; 03222 } 03223 03224 DWORD ImmReconversionWorker( 03225 LPRECONVERTSTRING lpRecTo, 03226 LPRECONVERTSTRING lpRecFrom, 03227 BOOL bToAnsi, 03228 DWORD dwCodePage) 03229 { 03230 INT i; 03231 DWORD dwSize = 0; 03232 03233 UserAssert(lpRecTo); 03234 UserAssert(lpRecFrom); 03235 03236 if (lpRecFrom->dwVersion != 0 || lpRecTo->dwVersion != 0) { 03237 RIPMSG0(RIP_WARNING, "ImmReconversionWorker: dwVersion in lpRecTo or lpRecFrom is incorrect."); 03238 return 0; 03239 } 03240 // Note: 03241 // In any IME related structures, use the following principal. 03242 // 1) xxxStrOffset is an actual offset, i.e. byte count. 03243 // 2) xxxStrLen is a number of characters, i.e. TCHAR count. 03244 // 03245 // CalcCharacterPositionXtoY() takes TCHAR count so that we 03246 // need to adjust xxxStrOffset if it's being converted. But you 03247 // should be careful, because the actual position of the string 03248 // is always at something like (LPBYTE)lpStruc + lpStruc->dwStrOffset. 03249 // 03250 if (bToAnsi) { 03251 // Convert W to A 03252 lpRecTo->dwStrOffset = sizeof *lpRecTo; 03253 i = WideCharToMultiByte(dwCodePage, 03254 (DWORD)0, 03255 (LPWSTR)((LPSTR)lpRecFrom + lpRecFrom->dwStrOffset), // src 03256 (INT)lpRecFrom->dwStrLen, 03257 (LPSTR)lpRecTo + lpRecTo->dwStrOffset, // dest 03258 (INT)lpRecFrom->dwStrLen * DBCS_CHARSIZE, 03259 (LPSTR)NULL, 03260 (LPBOOL)NULL); 03261 lpRecTo->dwCompStrOffset = 03262 CalcCharacterPositionWtoA(lpRecFrom->dwCompStrOffset / sizeof(WCHAR), 03263 (LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset), 03264 dwCodePage) 03265 * sizeof(CHAR); 03266 03267 lpRecTo->dwCompStrLen = 03268 (CalcCharacterPositionWtoA(lpRecFrom->dwCompStrOffset / sizeof(WCHAR) + 03269 lpRecFrom->dwCompStrLen, 03270 (LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset), 03271 dwCodePage) 03272 * sizeof(CHAR)) 03273 - lpRecTo->dwCompStrOffset; 03274 03275 lpRecTo->dwTargetStrOffset = 03276 CalcCharacterPositionWtoA(lpRecFrom->dwTargetStrOffset / sizeof(WCHAR), 03277 (LPWSTR)((LPBYTE)lpRecFrom + 03278 lpRecFrom->dwStrOffset), 03279 dwCodePage) 03280 * sizeof(CHAR); 03281 03282 lpRecTo->dwTargetStrLen = 03283 (CalcCharacterPositionWtoA(lpRecFrom->dwTargetStrOffset / sizeof(WCHAR) + 03284 lpRecFrom->dwTargetStrLen, 03285 (LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset), 03286 dwCodePage) 03287 * sizeof(CHAR)) 03288 - lpRecTo->dwTargetStrOffset; 03289 03290 ((LPSTR)lpRecTo)[lpRecTo->dwStrOffset + i] = '\0'; 03291 lpRecTo->dwStrLen = i * sizeof(CHAR); 03292 03293 dwSize = sizeof(RECONVERTSTRING) + ((i + 1) * sizeof(CHAR)); 03294 03295 } else { 03296 03297 // AtoW 03298 lpRecTo->dwStrOffset = sizeof *lpRecTo; 03299 i = MultiByteToWideChar(dwCodePage, 03300 (DWORD)MB_PRECOMPOSED, 03301 (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, // src 03302 (INT)lpRecFrom->dwStrLen, 03303 (LPWSTR)((LPSTR)lpRecTo + lpRecTo->dwStrOffset), // dest 03304 (INT)lpRecFrom->dwStrLen); 03305 03306 lpRecTo->dwCompStrOffset = 03307 CalcCharacterPositionAtoW(lpRecFrom->dwCompStrOffset, 03308 (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, 03309 dwCodePage) * sizeof(WCHAR); 03310 03311 lpRecTo->dwCompStrLen = 03312 ((CalcCharacterPositionAtoW(lpRecFrom->dwCompStrOffset + 03313 lpRecFrom->dwCompStrLen, 03314 (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, 03315 dwCodePage) * sizeof(WCHAR)) 03316 - lpRecTo->dwCompStrOffset) / sizeof(WCHAR); 03317 03318 lpRecTo->dwTargetStrOffset = 03319 CalcCharacterPositionAtoW(lpRecFrom->dwTargetStrOffset, 03320 (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, 03321 dwCodePage) * sizeof(WCHAR); 03322 03323 lpRecTo->dwTargetStrLen = 03324 ((CalcCharacterPositionAtoW(lpRecFrom->dwTargetStrOffset + 03325 lpRecFrom->dwTargetStrLen, 03326 (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, 03327 dwCodePage) * sizeof(WCHAR)) 03328 - lpRecTo->dwTargetStrOffset) / sizeof(WCHAR); 03329 03330 lpRecTo->dwStrLen = i; // Length is TCHAR count. 03331 if (lpRecTo->dwSize >= (DWORD)(lpRecTo->dwStrOffset + (i + 1)* sizeof(WCHAR))) { 03332 LPWSTR lpW = (LPWSTR)((LPSTR)lpRecTo + lpRecTo->dwStrOffset); 03333 lpW[i] = L'\0'; 03334 } 03335 dwSize = sizeof(RECONVERTSTRING) + ((i + 1) * sizeof(WCHAR)); 03336 } 03337 return dwSize; 03338 } 03339 03341 // ImmRequestMessageWorker 03342 // 03343 // worker function for WM_IME_REQUEST message 03344 // 03345 // History: 03346 // 30-Mar-1997 hiroyama Created 03348 03349 LRESULT ImmRequestMessageWorker(HIMC hIMC, PWND pwnd, WPARAM wParam, LPARAM lParam, BOOL bAnsiOrigin) 03350 { 03351 // the (least) size of the structure given in lParam: for valid pointer checking 03352 static CONST int nReqBufSize[][7] = { 03353 { // sizes if IME is UNICODE 03354 sizeof(COMPOSITIONFORM), // IMR_COMPOSITIONWINDOW 03355 sizeof(CANDIDATEFORM), // IMR_CANDIDATEWINDOW 03356 sizeof(LOGFONTW), // IMR_COMPOSITIONFONT 03357 sizeof(RECONVERTSTRING), // IMR_RECONVERTSTRING 03358 sizeof(RECONVERTSTRING), // IMR_CONFIRMRECONVERTSTRING 03359 sizeof(IMECHARPOSITION), // IMR_QUERYCHARPOSITION 03360 sizeof(RECONVERTSTRING), // IMR_DOCUMENTFEED 03361 }, 03362 { // sizes if IME is ANSI 03363 sizeof(COMPOSITIONFORM), // IMR_COMPOSITIONWINDOW 03364 sizeof(CANDIDATEFORM), // IMR_CANDIDATEWINDOW 03365 sizeof(LOGFONTA), // IMR_COMPOSITIONFONT 03366 sizeof(RECONVERTSTRING), // IMR_RECONVERTSTRING 03367 sizeof(RECONVERTSTRING), // IMR_CONFIRMRECONVERTSTRING 03368 sizeof(IMECHARPOSITION), // IMR_QUERYCHARPOSITION 03369 sizeof(RECONVERTSTRING), // IMR_DOCUMENTFEED 03370 } 03371 }; 03372 LRESULT lRet = 0L; 03373 CONST BOOLEAN bAnsiTarget = !!TestWF(pwnd, WFANSIPROC); // TRUE if the target Window Proc is ANSI 03374 LPBYTE lpReq = (LPBYTE)lParam; // return buffer (maybe allocated buffer) 03375 LPBYTE lpNew = NULL; // buffer allocated within this function 03376 DWORD dwSaveCharPos; 03377 PCLIENTIMC pClientImc; 03378 DWORD dwCodePage; 03379 03380 #define SEND_MESSAGE(bAnsi) ((bAnsi) ? SendMessageA : SendMessageW) 03381 03383 // Parameter checking 03384 03385 // check wParam as sub messages 03386 if (wParam == 0 || wParam > IMR_DOCUMENTFEED) { // wParam is not a proper sub message 03387 RIPMSG1(RIP_WARNING, "ImmRequestMessageWorker: wParam(%lx) out of range.", wParam); 03388 return 0L; 03389 } 03390 03391 // Check if the pointer which is given through lParam points the proper memory block. 03392 UserAssert(bAnsiOrigin == 0 || bAnsiOrigin == 1); // we'll use bAnsiOrigin as an index 03393 03394 // The first sub message IMR_COMPOSITIONWINDOW is 1, so substract 1 from wParam 03395 if (lpReq && IsBadWritePtr(lpReq, nReqBufSize[bAnsiOrigin][wParam - 1])) { 03396 RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: Bad pointer passed from IME to write"); 03397 return 0L; 03398 } 03399 03400 // check the lpReq(==lParam): the spec does not allow lParam as NULL 03401 // except IMR_RECONVERTSTRING and IMR_DOCUMENTFEED 03402 if (wParam == IMR_RECONVERTSTRING || wParam == IMR_DOCUMENTFEED) { 03403 // 03404 // check version number 03405 // 03406 if (lpReq != NULL) { 03407 LPRECONVERTSTRING lpReconv = (LPRECONVERTSTRING)lParam; 03408 if (lpReconv->dwVersion != 0) { 03409 RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid version number: %d", 03410 lpReconv->dwVersion); 03411 return 0L; 03412 } 03413 if (lpReconv->dwSize < sizeof(RECONVERTSTRING)) { 03414 RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid dwSize: %d", 03415 lpReconv->dwSize); 03416 return 0L; 03417 } 03418 } 03419 } else if (wParam == IMR_CONFIRMRECONVERTSTRING) { 03420 // check if lParam is not NULL, and version of the structure is correct. 03421 if (lpReq == NULL || ((LPRECONVERTSTRING)lpReq)->dwVersion != 0) { 03422 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid argument or invalid version number"); 03423 return 0L; 03424 } 03425 } else if (lpReq == NULL) { 03426 RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, 03427 "ImmRequestMessageWorker: lParam should not be NULL with this wParam(%lx).", 03428 wParam); 03429 return 0L; 03430 } 03431 // end parameter checking 03433 03434 pClientImc = ImmLockClientImc(hIMC); 03435 if (pClientImc != NULL) { 03436 dwCodePage = CImcCodePage(pClientImc); 03437 ImmUnlockClientImc(pClientImc); 03438 } 03439 else { 03440 dwCodePage = CP_ACP; 03441 } 03442 03443 // allocate and prepare required buffer if we need A/W conversion 03444 switch (wParam) { 03445 case IMR_CONFIRMRECONVERTSTRING: 03446 case IMR_RECONVERTSTRING: 03447 case IMR_DOCUMENTFEED: 03448 if (bAnsiOrigin != bAnsiTarget) { 03449 if (lpReq != NULL) { 03450 // IME wants not only the buffer size but the real reconversion information 03451 DWORD dwSize = ImmGetReconvertTotalSize(((LPRECONVERTSTRING)lpReq)->dwSize, FROM_IME, bAnsiTarget); 03452 LPRECONVERTSTRING lpReconv; 03453 03454 lpNew = ImmLocalAlloc(0, dwSize + sizeof(WCHAR)); 03455 if (lpNew == NULL) { 03456 RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: failed to allocate a buffer for reconversion."); 03457 return 0L; 03458 } 03459 lpReconv = (LPRECONVERTSTRING)lpNew; 03460 // setup the information in the allocated structure 03461 lpReconv->dwVersion = 0; 03462 lpReconv->dwSize = dwSize; 03463 03464 // 03465 // if it's confirmation message, we need to translate the contents 03466 // 03467 if (wParam == IMR_CONFIRMRECONVERTSTRING) { 03468 ImmReconversionWorker(lpReconv, (LPRECONVERTSTRING)lParam, bAnsiTarget, dwCodePage); 03469 } 03470 } 03471 } 03472 break; 03473 03474 case IMR_COMPOSITIONFONT: 03475 UserAssert(lpReq != NULL); // has been checked so far 03476 if (bAnsiOrigin != bAnsiTarget) { 03477 if (bAnsiTarget) { 03478 lpNew = ImmLocalAlloc(0, sizeof(LOGFONTA)); 03479 } else { 03480 lpNew = ImmLocalAlloc(0, sizeof(LOGFONTW)); 03481 } 03482 if (lpNew == NULL) { 03483 RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_COMPOSITIONFONT: failed to allocate memory for A/W conversion."); 03484 return 0L; 03485 } 03486 } 03487 break; 03488 03489 case IMR_QUERYCHARPOSITION: 03490 UserAssert(lpReq != NULL); 03491 if (bAnsiOrigin != bAnsiTarget) { 03492 #define lpIMEPOS ((LPIMECHARPOSITION)lParam) 03493 LPVOID lpstr; 03494 DWORD dwLen; 03495 03496 dwSaveCharPos = lpIMEPOS->dwCharPos; 03497 03498 dwLen = (!bAnsiOrigin ? ImmGetCompositionStringW : ImmGetCompositionStringA)(hIMC, GCS_COMPSTR, 0, 0); 03499 if (dwLen == 0) { 03500 RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_QUERYCHARPOSITION no compositiong string."); 03501 return 0L; 03502 } 03503 03504 lpstr = ImmLocalAlloc(0, (dwLen + 1) * (!bAnsiOrigin ? sizeof(WCHAR) : sizeof(CHAR))); 03505 if (lpstr == NULL) { 03506 RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_QUERYCHARPOSITION: failed to allocate memory for A/W conversion."); 03507 return 0L; 03508 } 03509 03510 (!bAnsiOrigin ? ImmGetCompositionStringW : ImmGetCompositionStringA)(hIMC, GCS_COMPSTR, lpstr, dwLen); 03511 if (bAnsiTarget) { 03512 lpIMEPOS->dwCharPos = CalcCharacterPositionWtoA(lpIMEPOS->dwCharPos, lpstr, dwCodePage); 03513 } else { 03514 lpIMEPOS->dwCharPos = CalcCharacterPositionAtoW(lpIMEPOS->dwCharPos, lpstr, dwCodePage); 03515 } 03516 03517 ImmLocalFree(lpstr); 03518 } 03519 break; 03520 03521 default: 03522 UserAssert(lpReq != NULL); // has been checked so far 03523 break; 03524 } 03525 03526 if (lpNew) { 03527 // if we allocated the buffer, let lpReq point it; lpNew is used later to free memory 03528 lpReq = lpNew; 03529 } 03530 03532 lRet = SEND_MESSAGE(bAnsiTarget)(HW(pwnd), WM_IME_REQUEST, wParam, (LPARAM)lpReq); 03534 03535 // copy back the results from WinProc to IME's buffer (only if conversion is needed) 03536 if (bAnsiOrigin != bAnsiTarget) { 03537 switch (wParam) { 03538 case IMR_RECONVERTSTRING: 03539 case IMR_DOCUMENTFEED: 03540 // Note: by definition, we don't have to do back-conversion for IMR_CONFIRMRECONVERTSTRING 03541 if (lRet != 0) { 03542 // IME wants the buffer size 03543 lRet = ImmGetReconvertTotalSize((DWORD)lRet, FROM_APP, bAnsiTarget); 03544 if (lRet < sizeof(RECONVERTSTRING)) { 03545 RIPMSG1(RIP_WARNING, "ImmRequestMessageWorker: return value from application %d is invalid.", lRet); 03546 lRet = 0; 03547 } else if (lpReq) { 03548 // We need to perform the A/W conversion of the contents 03549 if (!ImmReconversionWorker((LPRECONVERTSTRING)lParam, (LPRECONVERTSTRING)lpReq, bAnsiOrigin, dwCodePage)) { 03550 lRet = 0; // Error ! 03551 } 03552 } 03553 } 03554 break; 03555 case IMR_COMPOSITIONFONT: 03556 if (bAnsiOrigin) { 03557 LFontWtoLFontA((LPLOGFONTW)lpNew, (LPLOGFONTA)lParam); 03558 } else { 03559 LFontAtoLFontW((LPLOGFONTA)lpNew, (LPLOGFONTW)lParam); 03560 } 03561 break; 03562 case IMR_QUERYCHARPOSITION: 03563 UserAssert((LPVOID)lParam != NULL); 03564 lpIMEPOS->dwCharPos = dwSaveCharPos; 03565 #undef lpIMEPOS 03566 break; 03567 default: 03568 break; 03569 } 03570 03571 } 03572 if (lpNew) { 03573 // buffer has been allocated, free it before returning 03574 ImmLocalFree(lpNew); 03575 } 03576 return lRet; 03577 } 03578 03579 /**************************************************************************\ 03580 * ImmRequestMessage: Send WM_IME_REQUEST message to the given HIMC window 03581 * 03582 * IME function 03583 * 03584 * 27-Feb-1997 hiroyama Created 03585 \**************************************************************************/ 03586 LRESULT ImmRequestMessageAorW(HIMC hIMC, WPARAM wParam, LPARAM lParam, BOOL bAnsiOrigin) 03587 { 03588 LPINPUTCONTEXT lpInputContext; 03589 PWND pwnd; 03590 LRESULT lRet = 0L; 03591 DWORD dwThreadId = GetInputContextThread(hIMC); 03592 03593 if (dwThreadId != GetCurrentThreadId()) { 03594 RIPMSG1(RIP_WARNING, 03595 "ImmRequestMessageAorW:: Invalid input context access %lx.", hIMC); 03596 return lRet; 03597 } 03598 03599 if (hIMC == NULL || (lpInputContext = ImmLockIMC(hIMC)) == NULL) { 03600 RIPMSG1(RIP_WARNING, "ImmRequestMessage: Invalid hImc %lx.", hIMC); 03601 return 0L; 03602 } 03603 03604 // check if the window of the input context is valid 03605 if ((pwnd = ValidateHwnd(lpInputContext->hWnd)) == NULL) { 03606 RIPMSG1(RIP_WARNING, "ImmRequestMessage: Invalid hWnd %lx.", lpInputContext->hWnd); 03607 } else { 03608 // check if the message is being sent inter thread 03609 if (PtiCurrent() != GETPTI(pwnd)) { 03610 RIPMSG0(RIP_WARNING, "ImmRequestMessage: IME Attempt to send IMR_ message to different thread."); 03611 } else { 03612 lRet = ImmRequestMessageWorker(hIMC, pwnd, wParam, lParam, bAnsiOrigin); 03613 } 03614 } 03615 03616 ImmUnlockIMC(hIMC); 03617 03618 return lRet; 03619 } 03620 03621 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam) 03622 { 03623 return ImmRequestMessageAorW(hIMC, wParam, lParam, TRUE /* ANSI */); 03624 } 03625 03626 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam) 03627 { 03628 return ImmRequestMessageAorW(hIMC, wParam, lParam, FALSE /* not ANSI */); 03629 }

Generated on Sat May 15 19:39:38 2004 for test by doxygen 1.3.7