1 /* 2 * IMM32 library 3 * 4 * Copyright 1998 Patrik Stridvall 5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <stdio.h> 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "wingdi.h" 28 #include "winuser.h" 29 #include "winerror.h" 30 #include "wine/debug.h" 31 #include "imm.h" 32 #include "ddk/imm.h" 33 #include "winnls.h" 34 #include "winreg.h" 35 #include "wine/list.h" 36 #include "wine/unicode.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(imm); 39 40 #define IMM_INIT_MAGIC 0x19650412 41 BOOL WINAPI User32InitializeImmEntryTable(DWORD); 42 43 typedef struct _tagImmHkl{ 44 struct list entry; 45 HKL hkl; 46 HMODULE hIME; 47 IMEINFO imeInfo; 48 WCHAR imeClassName[17]; /* 16 character max */ 49 ULONG uSelected; 50 HWND UIWnd; 51 52 /* Function Pointers */ 53 BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *); 54 BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *); 55 BOOL (WINAPI *pImeDestroy)(UINT); 56 LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *); 57 BOOL (WINAPI *pImeSelect)(HIMC, BOOL); 58 BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL); 59 UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC); 60 BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD); 61 BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *); 62 BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *); 63 UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *); 64 BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD); 65 DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT); 66 BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *); 67 UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *); 68 DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD); 69 } ImmHkl; 70 71 typedef struct tagInputContextData 72 { 73 DWORD dwLock; 74 INPUTCONTEXT IMC; 75 DWORD threadID; 76 77 ImmHkl *immKbd; 78 UINT lastVK; 79 BOOL threadDefault; 80 DWORD magic; 81 } InputContextData; 82 83 #define WINE_IMC_VALID_MAGIC 0x56434D49 84 85 typedef struct _tagTRANSMSG { 86 UINT message; 87 WPARAM wParam; 88 LPARAM lParam; 89 } TRANSMSG, *LPTRANSMSG; 90 91 typedef struct _tagIMMThreadData { 92 struct list entry; 93 DWORD threadID; 94 HIMC defaultContext; 95 HWND hwndDefault; 96 BOOL disableIME; 97 DWORD windowRefs; 98 } IMMThreadData; 99 100 static struct list ImmHklList = LIST_INIT(ImmHklList); 101 static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList); 102 103 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0}; 104 105 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0}; 106 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0}; 107 static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0}; 108 109 static const WCHAR szwIME[] = {'I','M','E',0}; 110 static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' ','I','M','E',0}; 111 112 static CRITICAL_SECTION threaddata_cs; 113 static CRITICAL_SECTION_DEBUG critsect_debug = 114 { 115 0, 0, &threaddata_cs, 116 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 117 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") } 118 }; 119 static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; 120 static BOOL disable_ime; 121 122 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE) 123 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE) 124 125 static BOOL IMM_DestroyContext(HIMC hIMC); 126 static InputContextData* get_imc_data(HIMC hIMC); 127 128 static inline WCHAR *strdupAtoW( const char *str ) 129 { 130 WCHAR *ret = NULL; 131 if (str) 132 { 133 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); 134 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 135 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); 136 } 137 return ret; 138 } 139 140 static inline CHAR *strdupWtoA( const WCHAR *str ) 141 { 142 CHAR *ret = NULL; 143 if (str) 144 { 145 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); 146 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) 147 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); 148 } 149 return ret; 150 } 151 152 static DWORD convert_candidatelist_WtoA( 153 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen) 154 { 155 DWORD ret, i, len; 156 157 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] ); 158 if ( lpDst && dwBufLen > 0 ) 159 { 160 *lpDst = *lpSrc; 161 lpDst->dwOffset[0] = ret; 162 } 163 164 for ( i = 0; i < lpSrc->dwCount; i++) 165 { 166 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i]; 167 168 if ( lpDst && dwBufLen > 0 ) 169 { 170 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i]; 171 172 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 173 (LPSTR)dest, dwBufLen, NULL, NULL); 174 175 if ( i + 1 < lpSrc->dwCount ) 176 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char); 177 dwBufLen -= len * sizeof(char); 178 } 179 else 180 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL); 181 182 ret += len * sizeof(char); 183 } 184 185 if ( lpDst ) 186 lpDst->dwSize = ret; 187 188 return ret; 189 } 190 191 static DWORD convert_candidatelist_AtoW( 192 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen) 193 { 194 DWORD ret, i, len; 195 196 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] ); 197 if ( lpDst && dwBufLen > 0 ) 198 { 199 *lpDst = *lpSrc; 200 lpDst->dwOffset[0] = ret; 201 } 202 203 for ( i = 0; i < lpSrc->dwCount; i++) 204 { 205 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i]; 206 207 if ( lpDst && dwBufLen > 0 ) 208 { 209 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i]; 210 211 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, 212 (LPWSTR)dest, dwBufLen); 213 214 if ( i + 1 < lpSrc->dwCount ) 215 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR); 216 dwBufLen -= len * sizeof(WCHAR); 217 } 218 else 219 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0); 220 221 ret += len * sizeof(WCHAR); 222 } 223 224 if ( lpDst ) 225 lpDst->dwSize = ret; 226 227 return ret; 228 } 229 230 static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread) 231 { 232 IMMThreadData *data; 233 DWORD process; 234 235 if (hwnd) 236 { 237 if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL; 238 if (process != GetCurrentProcessId()) return NULL; 239 } 240 else if (thread) 241 { 242 HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, thread); 243 if (!h) return NULL; 244 process = GetProcessIdOfThread(h); 245 CloseHandle(h); 246 if (process != GetCurrentProcessId()) return NULL; 247 } 248 else 249 thread = GetCurrentThreadId(); 250 251 EnterCriticalSection(&threaddata_cs); 252 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry) 253 if (data->threadID == thread) return data; 254 255 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data)); 256 data->threadID = thread; 257 list_add_head(&ImmThreadDataList,&data->entry); 258 TRACE("Thread Data Created (%x)\n",thread); 259 return data; 260 } 261 262 static BOOL IMM_IsDefaultContext(HIMC imc) 263 { 264 InputContextData *data = get_imc_data(imc); 265 266 if (!data) 267 return FALSE; 268 269 return data->threadDefault; 270 } 271 272 static void IMM_FreeThreadData(void) 273 { 274 IMMThreadData *data; 275 276 EnterCriticalSection(&threaddata_cs); 277 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry) 278 { 279 if (data->threadID == GetCurrentThreadId()) 280 { 281 list_remove(&data->entry); 282 LeaveCriticalSection(&threaddata_cs); 283 IMM_DestroyContext(data->defaultContext); 284 HeapFree(GetProcessHeap(),0,data); 285 TRACE("Thread Data Destroyed\n"); 286 return; 287 } 288 } 289 LeaveCriticalSection(&threaddata_cs); 290 } 291 292 static HMODULE load_graphics_driver(void) 293 { 294 static const WCHAR display_device_guid_propW[] = { 295 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_', 296 'd','e','v','i','c','e','_','g','u','i','d',0 }; 297 static const WCHAR key_pathW[] = { 298 'S','y','s','t','e','m','\\', 299 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 300 'C','o','n','t','r','o','l','\\', 301 'V','i','d','e','o','\\','{',0}; 302 static const WCHAR displayW[] = {'}','\\','0','0','0','0',0}; 303 static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0}; 304 305 HMODULE ret = 0; 306 HKEY hkey; 307 DWORD size; 308 WCHAR path[MAX_PATH]; 309 WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40]; 310 UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW )); 311 312 if (!guid_atom) return 0; 313 memcpy( key, key_pathW, sizeof(key_pathW) ); 314 if (!GlobalGetAtomNameW( guid_atom, key + strlenW(key), 40 )) return 0; 315 strcatW( key, displayW ); 316 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0; 317 size = sizeof(path); 318 if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path ); 319 RegCloseKey( hkey ); 320 TRACE( "%s %p\n", debugstr_w(path), ret ); 321 return ret; 322 } 323 324 /* ImmHkl loading and freeing */ 325 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);} 326 static ImmHkl *IMM_GetImmHkl(HKL hkl) 327 { 328 ImmHkl *ptr; 329 WCHAR filename[MAX_PATH]; 330 331 TRACE("Seeking ime for keyboard %p\n",hkl); 332 333 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry) 334 { 335 if (ptr->hkl == hkl) 336 return ptr; 337 } 338 /* not found... create it */ 339 340 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl)); 341 342 ptr->hkl = hkl; 343 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename); 344 if (!ptr->hIME) ptr->hIME = load_graphics_driver(); 345 if (ptr->hIME) 346 { 347 LOAD_FUNCPTR(ImeInquire); 348 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL)) 349 { 350 FreeLibrary(ptr->hIME); 351 ptr->hIME = NULL; 352 } 353 else 354 { 355 LOAD_FUNCPTR(ImeDestroy); 356 LOAD_FUNCPTR(ImeSelect); 357 if (!ptr->pImeSelect || !ptr->pImeDestroy) 358 { 359 FreeLibrary(ptr->hIME); 360 ptr->hIME = NULL; 361 } 362 else 363 { 364 LOAD_FUNCPTR(ImeConfigure); 365 LOAD_FUNCPTR(ImeEscape); 366 LOAD_FUNCPTR(ImeSetActiveContext); 367 LOAD_FUNCPTR(ImeToAsciiEx); 368 LOAD_FUNCPTR(NotifyIME); 369 LOAD_FUNCPTR(ImeRegisterWord); 370 LOAD_FUNCPTR(ImeUnregisterWord); 371 LOAD_FUNCPTR(ImeEnumRegisterWord); 372 LOAD_FUNCPTR(ImeSetCompositionString); 373 LOAD_FUNCPTR(ImeConversionList); 374 LOAD_FUNCPTR(ImeProcessKey); 375 LOAD_FUNCPTR(ImeGetRegisterWordStyle); 376 LOAD_FUNCPTR(ImeGetImeMenuItems); 377 /* make sure our classname is WCHAR */ 378 if (!is_kbd_ime_unicode(ptr)) 379 { 380 WCHAR bufW[17]; 381 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName, 382 -1, bufW, 17); 383 lstrcpyW(ptr->imeClassName, bufW); 384 } 385 } 386 } 387 } 388 list_add_head(&ImmHklList,&ptr->entry); 389 390 return ptr; 391 } 392 #undef LOAD_FUNCPTR 393 394 HWND WINAPI __wine_get_ui_window(HKL hkl) 395 { 396 ImmHkl *immHkl = IMM_GetImmHkl(hkl); 397 return immHkl->UIWnd; 398 } 399 400 static void IMM_FreeAllImmHkl(void) 401 { 402 ImmHkl *ptr,*cursor2; 403 404 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry) 405 { 406 list_remove(&ptr->entry); 407 if (ptr->hIME) 408 { 409 ptr->pImeDestroy(1); 410 FreeLibrary(ptr->hIME); 411 } 412 if (ptr->UIWnd) 413 DestroyWindow(ptr->UIWnd); 414 HeapFree(GetProcessHeap(),0,ptr); 415 } 416 } 417 418 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) 419 { 420 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved); 421 switch (fdwReason) 422 { 423 case DLL_PROCESS_ATTACH: 424 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC)) 425 { 426 return FALSE; 427 } 428 break; 429 case DLL_THREAD_ATTACH: 430 break; 431 case DLL_THREAD_DETACH: 432 IMM_FreeThreadData(); 433 break; 434 case DLL_PROCESS_DETACH: 435 if (lpReserved) break; 436 IMM_FreeThreadData(); 437 IMM_FreeAllImmHkl(); 438 break; 439 } 440 return TRUE; 441 } 442 443 /* for posting messages as the IME */ 444 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam) 445 { 446 HWND target = GetFocus(); 447 if (!target) 448 PostMessageW(data->IMC.hWnd,msg,wParam,lParam); 449 else 450 PostMessageW(target, msg, wParam, lParam); 451 } 452 453 /* for sending messages as the IME */ 454 static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam) 455 { 456 HWND target = GetFocus(); 457 if (!target) 458 SendMessageW(data->IMC.hWnd,msg,wParam,lParam); 459 else 460 SendMessageW(target, msg, wParam, lParam); 461 } 462 463 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam) 464 { 465 HWND target; 466 467 target = data->IMC.hWnd; 468 if (!target) target = GetFocus(); 469 470 if (target) 471 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam); 472 473 return 0; 474 } 475 476 static HIMCC ImmCreateBlankCompStr(void) 477 { 478 HIMCC rc; 479 LPCOMPOSITIONSTRING ptr; 480 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING)); 481 ptr = ImmLockIMCC(rc); 482 memset(ptr,0,sizeof(COMPOSITIONSTRING)); 483 ptr->dwSize = sizeof(COMPOSITIONSTRING); 484 ImmUnlockIMCC(rc); 485 return rc; 486 } 487 488 static InputContextData* get_imc_data(HIMC hIMC) 489 { 490 InputContextData *data = hIMC; 491 492 if (hIMC == NULL) 493 return NULL; 494 495 if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC) 496 { 497 SetLastError(ERROR_INVALID_HANDLE); 498 return NULL; 499 } 500 return data; 501 } 502 503 static HIMC get_default_context( HWND hwnd ) 504 { 505 HIMC ret; 506 IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 ); 507 508 if (!thread_data) return 0; 509 510 if (thread_data->defaultContext) 511 { 512 ret = thread_data->defaultContext; 513 LeaveCriticalSection(&threaddata_cs); 514 return ret; 515 } 516 517 /* can't create a default context in another thread */ 518 if (thread_data->threadID != GetCurrentThreadId()) 519 { 520 LeaveCriticalSection(&threaddata_cs); 521 return 0; 522 } 523 524 LeaveCriticalSection(&threaddata_cs); 525 526 ret = ImmCreateContext(); 527 if (!ret) return 0; 528 ((InputContextData*)ret)->threadDefault = TRUE; 529 530 /* thread_data is in the current thread so we can assume it's still valid */ 531 EnterCriticalSection(&threaddata_cs); 532 533 if (thread_data->defaultContext) /* someone beat us */ 534 { 535 IMM_DestroyContext( ret ); 536 ret = thread_data->defaultContext; 537 } 538 else thread_data->defaultContext = ret; 539 540 LeaveCriticalSection(&threaddata_cs); 541 return ret; 542 } 543 544 static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC) 545 { 546 InputContextData *data; 547 548 if (hWnd) 549 { 550 DWORD thread = GetWindowThreadProcessId(hWnd, NULL); 551 if (thread != GetCurrentThreadId()) return TRUE; 552 } 553 data = get_imc_data(hIMC); 554 if (data && data->threadID != GetCurrentThreadId()) 555 return TRUE; 556 557 return FALSE; 558 } 559 560 /*********************************************************************** 561 * ImmAssociateContext (IMM32.@) 562 */ 563 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) 564 { 565 HIMC old = NULL; 566 InputContextData *data = get_imc_data(hIMC); 567 568 TRACE("(%p, %p):\n", hWnd, hIMC); 569 570 if(hIMC && !data) 571 return NULL; 572 573 /* 574 * If already associated just return 575 */ 576 if (hIMC && data->IMC.hWnd == hWnd) 577 return hIMC; 578 579 if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC)) 580 return NULL; 581 582 if (hWnd) 583 { 584 HIMC defaultContext = get_default_context( hWnd ); 585 old = RemovePropW(hWnd,szwWineIMCProperty); 586 587 if (old == NULL) 588 old = defaultContext; 589 else if (old == (HIMC)-1) 590 old = NULL; 591 592 if (hIMC != defaultContext) 593 { 594 if (hIMC == NULL) /* Meaning disable imm for that window*/ 595 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1); 596 else 597 SetPropW(hWnd,szwWineIMCProperty,hIMC); 598 } 599 600 if (old) 601 { 602 InputContextData *old_data = old; 603 if (old_data->IMC.hWnd == hWnd) 604 old_data->IMC.hWnd = NULL; 605 } 606 } 607 608 if (!hIMC) 609 return old; 610 611 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL); 612 data->IMC.hWnd = hWnd; 613 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL); 614 615 return old; 616 } 617 618 619 /* 620 * Helper function for ImmAssociateContextEx 621 */ 622 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam) 623 { 624 HIMC hImc = (HIMC)lParam; 625 ImmAssociateContext(hwnd,hImc); 626 return TRUE; 627 } 628 629 /*********************************************************************** 630 * ImmAssociateContextEx (IMM32.@) 631 */ 632 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) 633 { 634 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags); 635 636 if (!hWnd) 637 return FALSE; 638 639 switch (dwFlags) 640 { 641 case 0: 642 ImmAssociateContext(hWnd,hIMC); 643 return TRUE; 644 case IACE_DEFAULT: 645 { 646 HIMC defaultContext = get_default_context( hWnd ); 647 if (!defaultContext) return FALSE; 648 ImmAssociateContext(hWnd,defaultContext); 649 return TRUE; 650 } 651 case IACE_IGNORENOCONTEXT: 652 if (GetPropW(hWnd,szwWineIMCProperty)) 653 ImmAssociateContext(hWnd,hIMC); 654 return TRUE; 655 case IACE_CHILDREN: 656 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC); 657 return TRUE; 658 default: 659 FIXME("Unknown dwFlags 0x%x\n",dwFlags); 660 return FALSE; 661 } 662 } 663 664 /*********************************************************************** 665 * ImmConfigureIMEA (IMM32.@) 666 */ 667 BOOL WINAPI ImmConfigureIMEA( 668 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 669 { 670 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 671 672 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); 673 674 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData) 675 return FALSE; 676 677 if (immHkl->hIME && immHkl->pImeConfigure) 678 { 679 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl)) 680 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData); 681 else 682 { 683 REGISTERWORDW rww; 684 REGISTERWORDA *rwa = lpData; 685 BOOL rc; 686 687 rww.lpReading = strdupAtoW(rwa->lpReading); 688 rww.lpWord = strdupAtoW(rwa->lpWord); 689 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww); 690 HeapFree(GetProcessHeap(),0,rww.lpReading); 691 HeapFree(GetProcessHeap(),0,rww.lpWord); 692 return rc; 693 } 694 } 695 else 696 return FALSE; 697 } 698 699 /*********************************************************************** 700 * ImmConfigureIMEW (IMM32.@) 701 */ 702 BOOL WINAPI ImmConfigureIMEW( 703 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 704 { 705 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 706 707 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); 708 709 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData) 710 return FALSE; 711 712 if (immHkl->hIME && immHkl->pImeConfigure) 713 { 714 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl)) 715 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData); 716 else 717 { 718 REGISTERWORDW *rww = lpData; 719 REGISTERWORDA rwa; 720 BOOL rc; 721 722 rwa.lpReading = strdupWtoA(rww->lpReading); 723 rwa.lpWord = strdupWtoA(rww->lpWord); 724 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa); 725 HeapFree(GetProcessHeap(),0,rwa.lpReading); 726 HeapFree(GetProcessHeap(),0,rwa.lpWord); 727 return rc; 728 } 729 } 730 else 731 return FALSE; 732 } 733 734 /*********************************************************************** 735 * ImmCreateContext (IMM32.@) 736 */ 737 HIMC WINAPI ImmCreateContext(void) 738 { 739 InputContextData *new_context; 740 LPGUIDELINE gl; 741 LPCANDIDATEINFO ci; 742 int i; 743 744 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData)); 745 746 /* Load the IME */ 747 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0)); 748 749 if (!new_context->immKbd->hIME) 750 { 751 TRACE("IME dll could not be loaded\n"); 752 HeapFree(GetProcessHeap(),0,new_context); 753 return 0; 754 } 755 756 /* the HIMCCs are never NULL */ 757 new_context->IMC.hCompStr = ImmCreateBlankCompStr(); 758 new_context->IMC.hMsgBuf = ImmCreateIMCC(0); 759 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO)); 760 ci = ImmLockIMCC(new_context->IMC.hCandInfo); 761 memset(ci,0,sizeof(CANDIDATEINFO)); 762 ci->dwSize = sizeof(CANDIDATEINFO); 763 ImmUnlockIMCC(new_context->IMC.hCandInfo); 764 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE)); 765 gl = ImmLockIMCC(new_context->IMC.hGuideLine); 766 memset(gl,0,sizeof(GUIDELINE)); 767 gl->dwSize = sizeof(GUIDELINE); 768 ImmUnlockIMCC(new_context->IMC.hGuideLine); 769 770 for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++) 771 new_context->IMC.cfCandForm[i].dwIndex = ~0u; 772 773 /* Initialize the IME Private */ 774 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize); 775 776 new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps; 777 new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps; 778 779 if (!new_context->immKbd->pImeSelect(new_context, TRUE)) 780 { 781 TRACE("Selection of IME failed\n"); 782 IMM_DestroyContext(new_context); 783 return 0; 784 } 785 new_context->threadID = GetCurrentThreadId(); 786 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd); 787 788 new_context->immKbd->uSelected++; 789 TRACE("Created context %p\n",new_context); 790 791 new_context->magic = WINE_IMC_VALID_MAGIC; 792 return new_context; 793 } 794 795 static BOOL IMM_DestroyContext(HIMC hIMC) 796 { 797 InputContextData *data = get_imc_data(hIMC); 798 799 TRACE("Destroying %p\n",hIMC); 800 801 if (!data) 802 return FALSE; 803 804 data->immKbd->uSelected --; 805 data->immKbd->pImeSelect(hIMC, FALSE); 806 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd); 807 808 ImmDestroyIMCC(data->IMC.hCompStr); 809 ImmDestroyIMCC(data->IMC.hCandInfo); 810 ImmDestroyIMCC(data->IMC.hGuideLine); 811 ImmDestroyIMCC(data->IMC.hPrivate); 812 ImmDestroyIMCC(data->IMC.hMsgBuf); 813 814 data->magic = 0; 815 HeapFree(GetProcessHeap(),0,data); 816 817 return TRUE; 818 } 819 820 /*********************************************************************** 821 * ImmDestroyContext (IMM32.@) 822 */ 823 BOOL WINAPI ImmDestroyContext(HIMC hIMC) 824 { 825 if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC)) 826 return IMM_DestroyContext(hIMC); 827 else 828 return FALSE; 829 } 830 831 /*********************************************************************** 832 * ImmDisableIME (IMM32.@) 833 */ 834 BOOL WINAPI ImmDisableIME(DWORD idThread) 835 { 836 if (idThread == (DWORD)-1) 837 disable_ime = TRUE; 838 else { 839 IMMThreadData *thread_data = IMM_GetThreadData(NULL, idThread); 840 if (!thread_data) return FALSE; 841 thread_data->disableIME = TRUE; 842 LeaveCriticalSection(&threaddata_cs); 843 } 844 return TRUE; 845 } 846 847 /*********************************************************************** 848 * ImmEnumRegisterWordA (IMM32.@) 849 */ 850 UINT WINAPI ImmEnumRegisterWordA( 851 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc, 852 LPCSTR lpszReading, DWORD dwStyle, 853 LPCSTR lpszRegister, LPVOID lpData) 854 { 855 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 856 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc, 857 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData); 858 if (immHkl->hIME && immHkl->pImeEnumRegisterWord) 859 { 860 if (!is_kbd_ime_unicode(immHkl)) 861 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc, 862 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData); 863 else 864 { 865 LPWSTR lpszwReading = strdupAtoW(lpszReading); 866 LPWSTR lpszwRegister = strdupAtoW(lpszRegister); 867 BOOL rc; 868 869 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc, 870 lpszwReading, dwStyle, lpszwRegister, 871 lpData); 872 873 HeapFree(GetProcessHeap(),0,lpszwReading); 874 HeapFree(GetProcessHeap(),0,lpszwRegister); 875 return rc; 876 } 877 } 878 else 879 return 0; 880 } 881 882 /*********************************************************************** 883 * ImmEnumRegisterWordW (IMM32.@) 884 */ 885 UINT WINAPI ImmEnumRegisterWordW( 886 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc, 887 LPCWSTR lpszReading, DWORD dwStyle, 888 LPCWSTR lpszRegister, LPVOID lpData) 889 { 890 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 891 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc, 892 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData); 893 if (immHkl->hIME && immHkl->pImeEnumRegisterWord) 894 { 895 if (is_kbd_ime_unicode(immHkl)) 896 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle, 897 lpszRegister, lpData); 898 else 899 { 900 LPSTR lpszaReading = strdupWtoA(lpszReading); 901 LPSTR lpszaRegister = strdupWtoA(lpszRegister); 902 BOOL rc; 903 904 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading, 905 dwStyle, (LPCWSTR)lpszaRegister, lpData); 906 907 HeapFree(GetProcessHeap(),0,lpszaReading); 908 HeapFree(GetProcessHeap(),0,lpszaRegister); 909 return rc; 910 } 911 } 912 else 913 return 0; 914 } 915 916 static inline BOOL EscapeRequiresWA(UINT uEscape) 917 { 918 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY || 919 uEscape == IME_ESC_SET_EUDC_DICTIONARY || 920 uEscape == IME_ESC_IME_NAME || 921 uEscape == IME_ESC_GETHELPFILENAME) 922 return TRUE; 923 return FALSE; 924 } 925 926 /*********************************************************************** 927 * ImmEscapeA (IMM32.@) 928 */ 929 LRESULT WINAPI ImmEscapeA( 930 HKL hKL, HIMC hIMC, 931 UINT uEscape, LPVOID lpData) 932 { 933 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 934 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData); 935 936 if (immHkl->hIME && immHkl->pImeEscape) 937 { 938 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl)) 939 return immHkl->pImeEscape(hIMC,uEscape,lpData); 940 else 941 { 942 WCHAR buffer[81]; /* largest required buffer should be 80 */ 943 LRESULT rc; 944 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY) 945 { 946 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81); 947 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 948 } 949 else 950 { 951 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 952 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL); 953 } 954 return rc; 955 } 956 } 957 else 958 return 0; 959 } 960 961 /*********************************************************************** 962 * ImmEscapeW (IMM32.@) 963 */ 964 LRESULT WINAPI ImmEscapeW( 965 HKL hKL, HIMC hIMC, 966 UINT uEscape, LPVOID lpData) 967 { 968 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 969 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData); 970 971 if (immHkl->hIME && immHkl->pImeEscape) 972 { 973 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl)) 974 return immHkl->pImeEscape(hIMC,uEscape,lpData); 975 else 976 { 977 CHAR buffer[81]; /* largest required buffer should be 80 */ 978 LRESULT rc; 979 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY) 980 { 981 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL); 982 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 983 } 984 else 985 { 986 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 987 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80); 988 } 989 return rc; 990 } 991 } 992 else 993 return 0; 994 } 995 996 /*********************************************************************** 997 * ImmGetCandidateListA (IMM32.@) 998 */ 999 DWORD WINAPI ImmGetCandidateListA( 1000 HIMC hIMC, DWORD dwIndex, 1001 LPCANDIDATELIST lpCandList, DWORD dwBufLen) 1002 { 1003 InputContextData *data = get_imc_data(hIMC); 1004 LPCANDIDATEINFO candinfo; 1005 LPCANDIDATELIST candlist; 1006 DWORD ret = 0; 1007 1008 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen); 1009 1010 if (!data || !data->IMC.hCandInfo) 1011 return 0; 1012 1013 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1014 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset)) 1015 goto done; 1016 1017 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]); 1018 if ( !candlist->dwSize || !candlist->dwCount ) 1019 goto done; 1020 1021 if ( !is_himc_ime_unicode(data) ) 1022 { 1023 ret = candlist->dwSize; 1024 if ( lpCandList && dwBufLen >= ret ) 1025 memcpy(lpCandList, candlist, ret); 1026 } 1027 else 1028 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen); 1029 1030 done: 1031 ImmUnlockIMCC(data->IMC.hCandInfo); 1032 return ret; 1033 } 1034 1035 /*********************************************************************** 1036 * ImmGetCandidateListCountA (IMM32.@) 1037 */ 1038 DWORD WINAPI ImmGetCandidateListCountA( 1039 HIMC hIMC, LPDWORD lpdwListCount) 1040 { 1041 InputContextData *data = get_imc_data(hIMC); 1042 LPCANDIDATEINFO candinfo; 1043 DWORD ret, count; 1044 1045 TRACE("%p, %p\n", hIMC, lpdwListCount); 1046 1047 if (!data || !lpdwListCount || !data->IMC.hCandInfo) 1048 return 0; 1049 1050 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1051 1052 *lpdwListCount = count = candinfo->dwCount; 1053 1054 if ( !is_himc_ime_unicode(data) ) 1055 ret = candinfo->dwSize; 1056 else 1057 { 1058 ret = sizeof(CANDIDATEINFO); 1059 while ( count-- ) 1060 ret += ImmGetCandidateListA(hIMC, count, NULL, 0); 1061 } 1062 1063 ImmUnlockIMCC(data->IMC.hCandInfo); 1064 return ret; 1065 } 1066 1067 /*********************************************************************** 1068 * ImmGetCandidateListCountW (IMM32.@) 1069 */ 1070 DWORD WINAPI ImmGetCandidateListCountW( 1071 HIMC hIMC, LPDWORD lpdwListCount) 1072 { 1073 InputContextData *data = get_imc_data(hIMC); 1074 LPCANDIDATEINFO candinfo; 1075 DWORD ret, count; 1076 1077 TRACE("%p, %p\n", hIMC, lpdwListCount); 1078 1079 if (!data || !lpdwListCount || !data->IMC.hCandInfo) 1080 return 0; 1081 1082 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1083 1084 *lpdwListCount = count = candinfo->dwCount; 1085 1086 if ( is_himc_ime_unicode(data) ) 1087 ret = candinfo->dwSize; 1088 else 1089 { 1090 ret = sizeof(CANDIDATEINFO); 1091 while ( count-- ) 1092 ret += ImmGetCandidateListW(hIMC, count, NULL, 0); 1093 } 1094 1095 ImmUnlockIMCC(data->IMC.hCandInfo); 1096 return ret; 1097 } 1098 1099 /*********************************************************************** 1100 * ImmGetCandidateListW (IMM32.@) 1101 */ 1102 DWORD WINAPI ImmGetCandidateListW( 1103 HIMC hIMC, DWORD dwIndex, 1104 LPCANDIDATELIST lpCandList, DWORD dwBufLen) 1105 { 1106 InputContextData *data = get_imc_data(hIMC); 1107 LPCANDIDATEINFO candinfo; 1108 LPCANDIDATELIST candlist; 1109 DWORD ret = 0; 1110 1111 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen); 1112 1113 if (!data || !data->IMC.hCandInfo) 1114 return 0; 1115 1116 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1117 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset)) 1118 goto done; 1119 1120 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]); 1121 if ( !candlist->dwSize || !candlist->dwCount ) 1122 goto done; 1123 1124 if ( is_himc_ime_unicode(data) ) 1125 { 1126 ret = candlist->dwSize; 1127 if ( lpCandList && dwBufLen >= ret ) 1128 memcpy(lpCandList, candlist, ret); 1129 } 1130 else 1131 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen); 1132 1133 done: 1134 ImmUnlockIMCC(data->IMC.hCandInfo); 1135 return ret; 1136 } 1137 1138 /*********************************************************************** 1139 * ImmGetCandidateWindow (IMM32.@) 1140 */ 1141 BOOL WINAPI ImmGetCandidateWindow( 1142 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate) 1143 { 1144 InputContextData *data = get_imc_data(hIMC); 1145 1146 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate); 1147 1148 if (!data || !lpCandidate) 1149 return FALSE; 1150 1151 if (dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm)) 1152 return FALSE; 1153 1154 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex) 1155 return FALSE; 1156 1157 *lpCandidate = data->IMC.cfCandForm[dwIndex]; 1158 1159 return TRUE; 1160 } 1161 1162 /*********************************************************************** 1163 * ImmGetCompositionFontA (IMM32.@) 1164 */ 1165 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1166 { 1167 LOGFONTW lfW; 1168 BOOL rc; 1169 1170 TRACE("(%p, %p):\n", hIMC, lplf); 1171 1172 rc = ImmGetCompositionFontW(hIMC,&lfW); 1173 if (!rc || !lplf) 1174 return FALSE; 1175 1176 memcpy(lplf,&lfW,sizeof(LOGFONTA)); 1177 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName, 1178 LF_FACESIZE, NULL, NULL); 1179 return TRUE; 1180 } 1181 1182 /*********************************************************************** 1183 * ImmGetCompositionFontW (IMM32.@) 1184 */ 1185 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1186 { 1187 InputContextData *data = get_imc_data(hIMC); 1188 1189 TRACE("(%p, %p):\n", hIMC, lplf); 1190 1191 if (!data || !lplf) 1192 return FALSE; 1193 1194 *lplf = data->IMC.lfFont.W; 1195 1196 return TRUE; 1197 } 1198 1199 1200 /* Helpers for the GetCompositionString functions */ 1201 1202 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen, 1203 BOOL unicode ) 1204 { 1205 INT rc; 1206 1207 if (is_himc_ime_unicode(data) && !unicode) 1208 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL); 1209 else if (!is_himc_ime_unicode(data) && unicode) 1210 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR); 1211 else 1212 { 1213 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR); 1214 memcpy( target, source, min(slen,tlen)*dlen); 1215 rc = slen*dlen; 1216 } 1217 1218 return rc; 1219 } 1220 1221 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen, 1222 LPBYTE target, INT tlen, BOOL unicode ) 1223 { 1224 INT rc; 1225 1226 if (is_himc_ime_unicode(data) && !unicode) 1227 { 1228 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL); 1229 if (tlen) 1230 { 1231 const BYTE *src = source; 1232 LPBYTE dst = target; 1233 int i, j = 0, k = 0; 1234 1235 if (rc < tlen) 1236 tlen = rc; 1237 for (i = 0; i < sslen; ++i) 1238 { 1239 int len; 1240 1241 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1, 1242 NULL, 0, NULL, NULL); 1243 for (; len > 0; --len) 1244 { 1245 dst[j++] = src[k]; 1246 1247 if (j >= tlen) 1248 goto end; 1249 } 1250 ++k; 1251 } 1252 end: 1253 rc = j; 1254 } 1255 } 1256 else if (!is_himc_ime_unicode(data) && unicode) 1257 { 1258 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0); 1259 if (tlen) 1260 { 1261 const BYTE *src = source; 1262 LPBYTE dst = target; 1263 int i, j = 0; 1264 1265 if (rc < tlen) 1266 tlen = rc; 1267 for (i = 0; i < sslen; ++i) 1268 { 1269 if (IsDBCSLeadByte(((LPSTR)ssource)[i])) 1270 continue; 1271 1272 dst[j++] = src[i]; 1273 1274 if (j >= tlen) 1275 break; 1276 } 1277 rc = j; 1278 } 1279 } 1280 else 1281 { 1282 memcpy( target, source, min(slen,tlen)); 1283 rc = slen; 1284 } 1285 1286 return rc; 1287 } 1288 1289 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, 1290 LPBYTE target, INT tlen, BOOL unicode ) 1291 { 1292 INT rc; 1293 1294 if (is_himc_ime_unicode(data) && !unicode) 1295 { 1296 if (tlen) 1297 { 1298 int i; 1299 1300 if (slen < tlen) 1301 tlen = slen; 1302 tlen /= sizeof (DWORD); 1303 for (i = 0; i < tlen; ++i) 1304 { 1305 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, 1306 ((DWORD *)source)[i], 1307 NULL, 0, 1308 NULL, NULL); 1309 } 1310 rc = sizeof (DWORD) * i; 1311 } 1312 else 1313 rc = slen; 1314 } 1315 else if (!is_himc_ime_unicode(data) && unicode) 1316 { 1317 if (tlen) 1318 { 1319 int i; 1320 1321 if (slen < tlen) 1322 tlen = slen; 1323 tlen /= sizeof (DWORD); 1324 for (i = 0; i < tlen; ++i) 1325 { 1326 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, 1327 ((DWORD *)source)[i], 1328 NULL, 0); 1329 } 1330 rc = sizeof (DWORD) * i; 1331 } 1332 else 1333 rc = slen; 1334 } 1335 else 1336 { 1337 memcpy( target, source, min(slen,tlen)); 1338 rc = slen; 1339 } 1340 1341 return rc; 1342 } 1343 1344 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode) 1345 { 1346 int rc; 1347 1348 if (is_himc_ime_unicode(data) && !unicode) 1349 { 1350 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL); 1351 } 1352 else if (!is_himc_ime_unicode(data) && unicode) 1353 { 1354 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0); 1355 } 1356 else 1357 rc = offset; 1358 1359 return rc; 1360 } 1361 1362 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, 1363 DWORD dwBufLen, BOOL unicode) 1364 { 1365 LONG rc = 0; 1366 InputContextData *data = get_imc_data(hIMC); 1367 LPCOMPOSITIONSTRING compstr; 1368 LPBYTE compdata; 1369 1370 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen); 1371 1372 if (!data) 1373 return FALSE; 1374 1375 if (!data->IMC.hCompStr) 1376 return FALSE; 1377 1378 compdata = ImmLockIMCC(data->IMC.hCompStr); 1379 compstr = (LPCOMPOSITIONSTRING)compdata; 1380 1381 switch (dwIndex) 1382 { 1383 case GCS_RESULTSTR: 1384 TRACE("GCS_RESULTSTR\n"); 1385 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode); 1386 break; 1387 case GCS_COMPSTR: 1388 TRACE("GCS_COMPSTR\n"); 1389 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode); 1390 break; 1391 case GCS_COMPATTR: 1392 TRACE("GCS_COMPATTR\n"); 1393 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen, 1394 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, 1395 lpBuf, dwBufLen, unicode); 1396 break; 1397 case GCS_COMPCLAUSE: 1398 TRACE("GCS_COMPCLAUSE\n"); 1399 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen, 1400 compdata + compstr->dwCompStrOffset, 1401 lpBuf, dwBufLen, unicode); 1402 break; 1403 case GCS_RESULTCLAUSE: 1404 TRACE("GCS_RESULTCLAUSE\n"); 1405 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen, 1406 compdata + compstr->dwResultStrOffset, 1407 lpBuf, dwBufLen, unicode); 1408 break; 1409 case GCS_RESULTREADSTR: 1410 TRACE("GCS_RESULTREADSTR\n"); 1411 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode); 1412 break; 1413 case GCS_RESULTREADCLAUSE: 1414 TRACE("GCS_RESULTREADCLAUSE\n"); 1415 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen, 1416 compdata + compstr->dwResultStrOffset, 1417 lpBuf, dwBufLen, unicode); 1418 break; 1419 case GCS_COMPREADSTR: 1420 TRACE("GCS_COMPREADSTR\n"); 1421 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode); 1422 break; 1423 case GCS_COMPREADATTR: 1424 TRACE("GCS_COMPREADATTR\n"); 1425 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen, 1426 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, 1427 lpBuf, dwBufLen, unicode); 1428 break; 1429 case GCS_COMPREADCLAUSE: 1430 TRACE("GCS_COMPREADCLAUSE\n"); 1431 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen, 1432 compdata + compstr->dwCompStrOffset, 1433 lpBuf, dwBufLen, unicode); 1434 break; 1435 case GCS_CURSORPOS: 1436 TRACE("GCS_CURSORPOS\n"); 1437 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode); 1438 break; 1439 case GCS_DELTASTART: 1440 TRACE("GCS_DELTASTART\n"); 1441 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode); 1442 break; 1443 default: 1444 FIXME("Unhandled index 0x%x\n",dwIndex); 1445 break; 1446 } 1447 1448 ImmUnlockIMCC(data->IMC.hCompStr); 1449 1450 return rc; 1451 } 1452 1453 /*********************************************************************** 1454 * ImmGetCompositionStringA (IMM32.@) 1455 */ 1456 LONG WINAPI ImmGetCompositionStringA( 1457 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) 1458 { 1459 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE); 1460 } 1461 1462 1463 /*********************************************************************** 1464 * ImmGetCompositionStringW (IMM32.@) 1465 */ 1466 LONG WINAPI ImmGetCompositionStringW( 1467 HIMC hIMC, DWORD dwIndex, 1468 LPVOID lpBuf, DWORD dwBufLen) 1469 { 1470 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE); 1471 } 1472 1473 /*********************************************************************** 1474 * ImmGetCompositionWindow (IMM32.@) 1475 */ 1476 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1477 { 1478 InputContextData *data = get_imc_data(hIMC); 1479 1480 TRACE("(%p, %p)\n", hIMC, lpCompForm); 1481 1482 if (!data) 1483 return FALSE; 1484 1485 *lpCompForm = data->IMC.cfCompForm; 1486 return TRUE; 1487 } 1488 1489 /*********************************************************************** 1490 * ImmGetContext (IMM32.@) 1491 * 1492 */ 1493 HIMC WINAPI ImmGetContext(HWND hWnd) 1494 { 1495 HIMC rc; 1496 1497 TRACE("%p\n", hWnd); 1498 1499 if (!IsWindow(hWnd)) 1500 { 1501 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1502 return NULL; 1503 } 1504 1505 rc = GetPropW(hWnd,szwWineIMCProperty); 1506 if (rc == (HIMC)-1) 1507 rc = NULL; 1508 else if (rc == NULL) 1509 rc = get_default_context( hWnd ); 1510 1511 if (rc) 1512 { 1513 InputContextData *data = rc; 1514 data->IMC.hWnd = hWnd; 1515 } 1516 1517 TRACE("returning %p\n", rc); 1518 1519 return rc; 1520 } 1521 1522 /*********************************************************************** 1523 * ImmGetConversionListA (IMM32.@) 1524 */ 1525 DWORD WINAPI ImmGetConversionListA( 1526 HKL hKL, HIMC hIMC, 1527 LPCSTR pSrc, LPCANDIDATELIST lpDst, 1528 DWORD dwBufLen, UINT uFlag) 1529 { 1530 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1531 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst, 1532 dwBufLen, uFlag); 1533 if (immHkl->hIME && immHkl->pImeConversionList) 1534 { 1535 if (!is_kbd_ime_unicode(immHkl)) 1536 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag); 1537 else 1538 { 1539 LPCANDIDATELIST lpwDst; 1540 DWORD ret = 0, len; 1541 LPWSTR pwSrc = strdupAtoW(pSrc); 1542 1543 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag); 1544 lpwDst = HeapAlloc(GetProcessHeap(), 0, len); 1545 if ( lpwDst ) 1546 { 1547 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag); 1548 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen); 1549 HeapFree(GetProcessHeap(), 0, lpwDst); 1550 } 1551 HeapFree(GetProcessHeap(), 0, pwSrc); 1552 1553 return ret; 1554 } 1555 } 1556 else 1557 return 0; 1558 } 1559 1560 /*********************************************************************** 1561 * ImmGetConversionListW (IMM32.@) 1562 */ 1563 DWORD WINAPI ImmGetConversionListW( 1564 HKL hKL, HIMC hIMC, 1565 LPCWSTR pSrc, LPCANDIDATELIST lpDst, 1566 DWORD dwBufLen, UINT uFlag) 1567 { 1568 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1569 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst, 1570 dwBufLen, uFlag); 1571 if (immHkl->hIME && immHkl->pImeConversionList) 1572 { 1573 if (is_kbd_ime_unicode(immHkl)) 1574 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag); 1575 else 1576 { 1577 LPCANDIDATELIST lpaDst; 1578 DWORD ret = 0, len; 1579 LPSTR paSrc = strdupWtoA(pSrc); 1580 1581 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag); 1582 lpaDst = HeapAlloc(GetProcessHeap(), 0, len); 1583 if ( lpaDst ) 1584 { 1585 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag); 1586 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen); 1587 HeapFree(GetProcessHeap(), 0, lpaDst); 1588 } 1589 HeapFree(GetProcessHeap(), 0, paSrc); 1590 1591 return ret; 1592 } 1593 } 1594 else 1595 return 0; 1596 } 1597 1598 /*********************************************************************** 1599 * ImmGetConversionStatus (IMM32.@) 1600 */ 1601 BOOL WINAPI ImmGetConversionStatus( 1602 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) 1603 { 1604 InputContextData *data = get_imc_data(hIMC); 1605 1606 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence); 1607 1608 if (!data) 1609 return FALSE; 1610 1611 if (lpfdwConversion) 1612 *lpfdwConversion = data->IMC.fdwConversion; 1613 if (lpfdwSentence) 1614 *lpfdwSentence = data->IMC.fdwSentence; 1615 1616 return TRUE; 1617 } 1618 1619 static BOOL needs_ime_window(HWND hwnd) 1620 { 1621 WCHAR classW[8]; 1622 1623 if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !strcmpW(classW, szwIME)) 1624 return FALSE; 1625 if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE; 1626 1627 return TRUE; 1628 } 1629 1630 /*********************************************************************** 1631 * __wine_register_window (IMM32.@) 1632 */ 1633 BOOL WINAPI __wine_register_window(HWND hwnd) 1634 { 1635 HWND new = NULL; 1636 IMMThreadData *thread_data; 1637 TRACE("(%p)\n", hwnd); 1638 1639 if (!needs_ime_window(hwnd)) 1640 return FALSE; 1641 1642 thread_data = IMM_GetThreadData(hwnd, 0); 1643 if (!thread_data) 1644 return FALSE; 1645 1646 if (thread_data->disableIME || disable_ime) 1647 { 1648 TRACE("IME for this thread is disabled\n"); 1649 LeaveCriticalSection(&threaddata_cs); 1650 return FALSE; 1651 } 1652 thread_data->windowRefs++; 1653 TRACE("windowRefs=%u, hwndDefault=%p\n", 1654 thread_data->windowRefs, thread_data->hwndDefault); 1655 1656 /* Create default IME window */ 1657 if (thread_data->windowRefs == 1) 1658 { 1659 /* Do not create the window inside of a critical section */ 1660 LeaveCriticalSection(&threaddata_cs); 1661 new = CreateWindowExW( 0, szwIME, szwDefaultIME, 1662 WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS, 1663 0, 0, 1, 1, 0, 0, 0, 0); 1664 /* thread_data is in the current thread so we can assume it's still valid */ 1665 EnterCriticalSection(&threaddata_cs); 1666 /* See if anyone beat us */ 1667 if (thread_data->hwndDefault == NULL) 1668 { 1669 thread_data->hwndDefault = new; 1670 new = NULL; 1671 TRACE("Default is %p\n", thread_data->hwndDefault); 1672 } 1673 } 1674 1675 LeaveCriticalSection(&threaddata_cs); 1676 1677 /* Clean up an unused new window outside of the critical section */ 1678 if (new != NULL) 1679 DestroyWindow(new); 1680 return TRUE; 1681 } 1682 1683 /*********************************************************************** 1684 * __wine_unregister_window (IMM32.@) 1685 */ 1686 void WINAPI __wine_unregister_window(HWND hwnd) 1687 { 1688 HWND to_destroy = 0; 1689 IMMThreadData *thread_data; 1690 TRACE("(%p)\n", hwnd); 1691 1692 thread_data = IMM_GetThreadData(hwnd, 0); 1693 if (!thread_data) return; 1694 1695 thread_data->windowRefs--; 1696 TRACE("windowRefs=%u, hwndDefault=%p\n", 1697 thread_data->windowRefs, thread_data->hwndDefault); 1698 1699 /* Destroy default IME window */ 1700 if (thread_data->windowRefs == 0 && thread_data->hwndDefault) 1701 { 1702 to_destroy = thread_data->hwndDefault; 1703 thread_data->hwndDefault = NULL; 1704 } 1705 LeaveCriticalSection(&threaddata_cs); 1706 1707 if (to_destroy) DestroyWindow( to_destroy ); 1708 } 1709 1710 /*********************************************************************** 1711 * ImmGetDefaultIMEWnd (IMM32.@) 1712 */ 1713 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) 1714 { 1715 HWND ret; 1716 IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0); 1717 if (!thread_data) 1718 return NULL; 1719 ret = thread_data->hwndDefault; 1720 LeaveCriticalSection(&threaddata_cs); 1721 TRACE("Default is %p\n",ret); 1722 return ret; 1723 } 1724 1725 /*********************************************************************** 1726 * ImmGetDescriptionA (IMM32.@) 1727 */ 1728 UINT WINAPI ImmGetDescriptionA( 1729 HKL hKL, LPSTR lpszDescription, UINT uBufLen) 1730 { 1731 WCHAR *buf; 1732 DWORD len; 1733 1734 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen); 1735 1736 /* find out how many characters in the unicode buffer */ 1737 len = ImmGetDescriptionW( hKL, NULL, 0 ); 1738 if (!len) 1739 return 0; 1740 1741 /* allocate a buffer of that size */ 1742 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) ); 1743 if( !buf ) 1744 return 0; 1745 1746 /* fetch the unicode buffer */ 1747 len = ImmGetDescriptionW( hKL, buf, len + 1 ); 1748 1749 /* convert it back to ASCII */ 1750 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1, 1751 lpszDescription, uBufLen, NULL, NULL ); 1752 1753 HeapFree( GetProcessHeap(), 0, buf ); 1754 1755 if (len == 0) 1756 return 0; 1757 1758 return len - 1; 1759 } 1760 1761 /*********************************************************************** 1762 * ImmGetDescriptionW (IMM32.@) 1763 */ 1764 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) 1765 { 1766 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 }; 1767 1768 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen); 1769 1770 if (!hKL) return 0; 1771 if (!uBufLen) return lstrlenW( name ); 1772 lstrcpynW( lpszDescription, name, uBufLen ); 1773 return lstrlenW( lpszDescription ); 1774 } 1775 1776 /*********************************************************************** 1777 * ImmGetGuideLineA (IMM32.@) 1778 */ 1779 DWORD WINAPI ImmGetGuideLineA( 1780 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen) 1781 { 1782 FIXME("(%p, %d, %s, %d): stub\n", 1783 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen 1784 ); 1785 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1786 return 0; 1787 } 1788 1789 /*********************************************************************** 1790 * ImmGetGuideLineW (IMM32.@) 1791 */ 1792 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen) 1793 { 1794 FIXME("(%p, %d, %s, %d): stub\n", 1795 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen 1796 ); 1797 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1798 return 0; 1799 } 1800 1801 /*********************************************************************** 1802 * ImmGetIMEFileNameA (IMM32.@) 1803 */ 1804 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) 1805 { 1806 LPWSTR bufW = NULL; 1807 UINT wBufLen = uBufLen; 1808 UINT rc; 1809 1810 if (uBufLen && lpszFileName) 1811 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR)); 1812 else /* We need this to get the number of byte required */ 1813 { 1814 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR)); 1815 wBufLen = MAX_PATH; 1816 } 1817 1818 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen); 1819 1820 if (rc > 0) 1821 { 1822 if (uBufLen && lpszFileName) 1823 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName, 1824 uBufLen, NULL, NULL); 1825 else /* get the length */ 1826 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, 1827 NULL); 1828 } 1829 1830 HeapFree(GetProcessHeap(),0,bufW); 1831 return rc; 1832 } 1833 1834 /*********************************************************************** 1835 * ImmGetIMEFileNameW (IMM32.@) 1836 */ 1837 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) 1838 { 1839 HKEY hkey; 1840 DWORD length; 1841 DWORD rc; 1842 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8]; 1843 1844 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL ); 1845 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey); 1846 if (rc != ERROR_SUCCESS) 1847 { 1848 SetLastError(rc); 1849 return 0; 1850 } 1851 1852 length = 0; 1853 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length); 1854 1855 if (rc != ERROR_SUCCESS) 1856 { 1857 RegCloseKey(hkey); 1858 SetLastError(rc); 1859 return 0; 1860 } 1861 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName) 1862 { 1863 RegCloseKey(hkey); 1864 if (lpszFileName) 1865 { 1866 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1867 return 0; 1868 } 1869 else 1870 return length / sizeof(WCHAR); 1871 } 1872 1873 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length); 1874 1875 RegCloseKey(hkey); 1876 1877 return length / sizeof(WCHAR); 1878 } 1879 1880 /*********************************************************************** 1881 * ImmGetOpenStatus (IMM32.@) 1882 */ 1883 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) 1884 { 1885 InputContextData *data = get_imc_data(hIMC); 1886 static int i; 1887 1888 if (!data) 1889 return FALSE; 1890 1891 TRACE("(%p): semi-stub\n", hIMC); 1892 1893 if (!i++) 1894 FIXME("(%p): semi-stub\n", hIMC); 1895 1896 return data->IMC.fOpen; 1897 } 1898 1899 /*********************************************************************** 1900 * ImmGetProperty (IMM32.@) 1901 */ 1902 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) 1903 { 1904 DWORD rc = 0; 1905 ImmHkl *kbd; 1906 1907 TRACE("(%p, %d)\n", hKL, fdwIndex); 1908 kbd = IMM_GetImmHkl(hKL); 1909 1910 if (kbd && kbd->hIME) 1911 { 1912 switch (fdwIndex) 1913 { 1914 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break; 1915 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break; 1916 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break; 1917 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break; 1918 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break; 1919 case IGP_GETIMEVERSION: rc = IMEVER_0400; break; 1920 case IGP_UI: rc = 0; break; 1921 default: rc = 0; 1922 } 1923 } 1924 return rc; 1925 } 1926 1927 /*********************************************************************** 1928 * ImmGetRegisterWordStyleA (IMM32.@) 1929 */ 1930 UINT WINAPI ImmGetRegisterWordStyleA( 1931 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf) 1932 { 1933 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1934 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf); 1935 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle) 1936 { 1937 if (!is_kbd_ime_unicode(immHkl)) 1938 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf); 1939 else 1940 { 1941 STYLEBUFW sbw; 1942 UINT rc; 1943 1944 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw); 1945 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1, 1946 lpStyleBuf->szDescription, 32, NULL, NULL); 1947 lpStyleBuf->dwStyle = sbw.dwStyle; 1948 return rc; 1949 } 1950 } 1951 else 1952 return 0; 1953 } 1954 1955 /*********************************************************************** 1956 * ImmGetRegisterWordStyleW (IMM32.@) 1957 */ 1958 UINT WINAPI ImmGetRegisterWordStyleW( 1959 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf) 1960 { 1961 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1962 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf); 1963 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle) 1964 { 1965 if (is_kbd_ime_unicode(immHkl)) 1966 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf); 1967 else 1968 { 1969 STYLEBUFA sba; 1970 UINT rc; 1971 1972 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba); 1973 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1, 1974 lpStyleBuf->szDescription, 32); 1975 lpStyleBuf->dwStyle = sba.dwStyle; 1976 return rc; 1977 } 1978 } 1979 else 1980 return 0; 1981 } 1982 1983 /*********************************************************************** 1984 * ImmGetStatusWindowPos (IMM32.@) 1985 */ 1986 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1987 { 1988 InputContextData *data = get_imc_data(hIMC); 1989 1990 TRACE("(%p, %p)\n", hIMC, lpptPos); 1991 1992 if (!data || !lpptPos) 1993 return FALSE; 1994 1995 *lpptPos = data->IMC.ptStatusWndPos; 1996 1997 return TRUE; 1998 } 1999 2000 /*********************************************************************** 2001 * ImmGetVirtualKey (IMM32.@) 2002 */ 2003 UINT WINAPI ImmGetVirtualKey(HWND hWnd) 2004 { 2005 OSVERSIONINFOA version; 2006 InputContextData *data = ImmGetContext( hWnd ); 2007 TRACE("%p\n", hWnd); 2008 2009 if ( data ) 2010 return data->lastVK; 2011 2012 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 2013 GetVersionExA( &version ); 2014 switch(version.dwPlatformId) 2015 { 2016 case VER_PLATFORM_WIN32_WINDOWS: 2017 return VK_PROCESSKEY; 2018 case VER_PLATFORM_WIN32_NT: 2019 return 0; 2020 default: 2021 FIXME("%d not supported\n",version.dwPlatformId); 2022 return VK_PROCESSKEY; 2023 } 2024 } 2025 2026 /*********************************************************************** 2027 * ImmInstallIMEA (IMM32.@) 2028 */ 2029 HKL WINAPI ImmInstallIMEA( 2030 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText) 2031 { 2032 LPWSTR lpszwIMEFileName; 2033 LPWSTR lpszwLayoutText; 2034 HKL hkl; 2035 2036 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName), 2037 debugstr_a(lpszLayoutText)); 2038 2039 lpszwIMEFileName = strdupAtoW(lpszIMEFileName); 2040 lpszwLayoutText = strdupAtoW(lpszLayoutText); 2041 2042 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText); 2043 2044 HeapFree(GetProcessHeap(),0,lpszwIMEFileName); 2045 HeapFree(GetProcessHeap(),0,lpszwLayoutText); 2046 return hkl; 2047 } 2048 2049 /*********************************************************************** 2050 * ImmInstallIMEW (IMM32.@) 2051 */ 2052 HKL WINAPI ImmInstallIMEW( 2053 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) 2054 { 2055 INT lcid = GetUserDefaultLCID(); 2056 INT count; 2057 HKL hkl; 2058 DWORD rc; 2059 HKEY hkey; 2060 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8]; 2061 2062 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName), 2063 debugstr_w(lpszLayoutText)); 2064 2065 /* Start with 2. e001 will be blank and so default to the wine internal IME */ 2066 count = 2; 2067 2068 while (count < 0xfff) 2069 { 2070 DWORD disposition = 0; 2071 2072 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count ); 2073 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl); 2074 2075 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition); 2076 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY) 2077 break; 2078 else if (rc == ERROR_SUCCESS) 2079 RegCloseKey(hkey); 2080 2081 count++; 2082 } 2083 2084 if (count == 0xfff) 2085 { 2086 WARN("Unable to find slot to install IME\n"); 2087 return 0; 2088 } 2089 2090 if (rc == ERROR_SUCCESS) 2091 { 2092 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName, 2093 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR)); 2094 if (rc == ERROR_SUCCESS) 2095 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText, 2096 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR)); 2097 RegCloseKey(hkey); 2098 return hkl; 2099 } 2100 else 2101 { 2102 WARN("Unable to set IME registry values\n"); 2103 return 0; 2104 } 2105 } 2106 2107 /*********************************************************************** 2108 * ImmIsIME (IMM32.@) 2109 */ 2110 BOOL WINAPI ImmIsIME(HKL hKL) 2111 { 2112 ImmHkl *ptr; 2113 TRACE("(%p):\n", hKL); 2114 ptr = IMM_GetImmHkl(hKL); 2115 return (ptr && ptr->hIME); 2116 } 2117 2118 /*********************************************************************** 2119 * ImmIsUIMessageA (IMM32.@) 2120 */ 2121 BOOL WINAPI ImmIsUIMessageA( 2122 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) 2123 { 2124 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam); 2125 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 2126 (msg == WM_IME_SETCONTEXT) || 2127 (msg == WM_IME_NOTIFY) || 2128 (msg == WM_IME_COMPOSITIONFULL) || 2129 (msg == WM_IME_SELECT) || 2130 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */)) 2131 { 2132 if (hWndIME) 2133 SendMessageA(hWndIME, msg, wParam, lParam); 2134 2135 return TRUE; 2136 } 2137 return FALSE; 2138 } 2139 2140 /*********************************************************************** 2141 * ImmIsUIMessageW (IMM32.@) 2142 */ 2143 BOOL WINAPI ImmIsUIMessageW( 2144 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) 2145 { 2146 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam); 2147 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 2148 (msg == WM_IME_SETCONTEXT) || 2149 (msg == WM_IME_NOTIFY) || 2150 (msg == WM_IME_COMPOSITIONFULL) || 2151 (msg == WM_IME_SELECT) || 2152 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */)) 2153 { 2154 if (hWndIME) 2155 SendMessageW(hWndIME, msg, wParam, lParam); 2156 2157 return TRUE; 2158 } 2159 return FALSE; 2160 } 2161 2162 /*********************************************************************** 2163 * ImmNotifyIME (IMM32.@) 2164 */ 2165 BOOL WINAPI ImmNotifyIME( 2166 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) 2167 { 2168 InputContextData *data = get_imc_data(hIMC); 2169 2170 TRACE("(%p, %d, %d, %d)\n", 2171 hIMC, dwAction, dwIndex, dwValue); 2172 2173 if (hIMC == NULL) 2174 { 2175 SetLastError(ERROR_SUCCESS); 2176 return FALSE; 2177 } 2178 2179 if (!data || ! data->immKbd->pNotifyIME) 2180 { 2181 return FALSE; 2182 } 2183 2184 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue); 2185 } 2186 2187 /*********************************************************************** 2188 * ImmRegisterWordA (IMM32.@) 2189 */ 2190 BOOL WINAPI ImmRegisterWordA( 2191 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister) 2192 { 2193 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2194 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle, 2195 debugstr_a(lpszRegister)); 2196 if (immHkl->hIME && immHkl->pImeRegisterWord) 2197 { 2198 if (!is_kbd_ime_unicode(immHkl)) 2199 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle, 2200 (LPCWSTR)lpszRegister); 2201 else 2202 { 2203 LPWSTR lpszwReading = strdupAtoW(lpszReading); 2204 LPWSTR lpszwRegister = strdupAtoW(lpszRegister); 2205 BOOL rc; 2206 2207 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister); 2208 HeapFree(GetProcessHeap(),0,lpszwReading); 2209 HeapFree(GetProcessHeap(),0,lpszwRegister); 2210 return rc; 2211 } 2212 } 2213 else 2214 return FALSE; 2215 } 2216 2217 /*********************************************************************** 2218 * ImmRegisterWordW (IMM32.@) 2219 */ 2220 BOOL WINAPI ImmRegisterWordW( 2221 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister) 2222 { 2223 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2224 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle, 2225 debugstr_w(lpszRegister)); 2226 if (immHkl->hIME && immHkl->pImeRegisterWord) 2227 { 2228 if (is_kbd_ime_unicode(immHkl)) 2229 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister); 2230 else 2231 { 2232 LPSTR lpszaReading = strdupWtoA(lpszReading); 2233 LPSTR lpszaRegister = strdupWtoA(lpszRegister); 2234 BOOL rc; 2235 2236 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle, 2237 (LPCWSTR)lpszaRegister); 2238 HeapFree(GetProcessHeap(),0,lpszaReading); 2239 HeapFree(GetProcessHeap(),0,lpszaRegister); 2240 return rc; 2241 } 2242 } 2243 else 2244 return FALSE; 2245 } 2246 2247 /*********************************************************************** 2248 * ImmReleaseContext (IMM32.@) 2249 */ 2250 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) 2251 { 2252 static BOOL shown = FALSE; 2253 2254 if (!shown) { 2255 FIXME("(%p, %p): stub\n", hWnd, hIMC); 2256 shown = TRUE; 2257 } 2258 return TRUE; 2259 } 2260 2261 /*********************************************************************** 2262 * ImmRequestMessageA(IMM32.@) 2263 */ 2264 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam) 2265 { 2266 InputContextData *data = get_imc_data(hIMC); 2267 2268 TRACE("%p %ld %ld\n", hIMC, wParam, wParam); 2269 2270 if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam); 2271 2272 SetLastError(ERROR_INVALID_HANDLE); 2273 return 0; 2274 } 2275 2276 /*********************************************************************** 2277 * ImmRequestMessageW(IMM32.@) 2278 */ 2279 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam) 2280 { 2281 InputContextData *data = get_imc_data(hIMC); 2282 2283 TRACE("%p %ld %ld\n", hIMC, wParam, wParam); 2284 2285 if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam); 2286 2287 SetLastError(ERROR_INVALID_HANDLE); 2288 return 0; 2289 } 2290 2291 /*********************************************************************** 2292 * ImmSetCandidateWindow (IMM32.@) 2293 */ 2294 BOOL WINAPI ImmSetCandidateWindow( 2295 HIMC hIMC, LPCANDIDATEFORM lpCandidate) 2296 { 2297 InputContextData *data = get_imc_data(hIMC); 2298 2299 TRACE("(%p, %p)\n", hIMC, lpCandidate); 2300 2301 if (!data || !lpCandidate) 2302 return FALSE; 2303 2304 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2305 return FALSE; 2306 2307 TRACE("\t%x, %x, %s, %s\n", 2308 lpCandidate->dwIndex, lpCandidate->dwStyle, 2309 wine_dbgstr_point(&lpCandidate->ptCurrentPos), 2310 wine_dbgstr_rect(&lpCandidate->rcArea)); 2311 2312 if (lpCandidate->dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm)) 2313 return FALSE; 2314 2315 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate; 2316 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS); 2317 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex); 2318 2319 return TRUE; 2320 } 2321 2322 /*********************************************************************** 2323 * ImmSetCompositionFontA (IMM32.@) 2324 */ 2325 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 2326 { 2327 InputContextData *data = get_imc_data(hIMC); 2328 TRACE("(%p, %p)\n", hIMC, lplf); 2329 2330 if (!data || !lplf) 2331 { 2332 SetLastError(ERROR_INVALID_HANDLE); 2333 return FALSE; 2334 } 2335 2336 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2337 return FALSE; 2338 2339 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA)); 2340 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName, 2341 LF_FACESIZE); 2342 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT); 2343 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); 2344 2345 return TRUE; 2346 } 2347 2348 /*********************************************************************** 2349 * ImmSetCompositionFontW (IMM32.@) 2350 */ 2351 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 2352 { 2353 InputContextData *data = get_imc_data(hIMC); 2354 TRACE("(%p, %p)\n", hIMC, lplf); 2355 2356 if (!data || !lplf) 2357 { 2358 SetLastError(ERROR_INVALID_HANDLE); 2359 return FALSE; 2360 } 2361 2362 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2363 return FALSE; 2364 2365 data->IMC.lfFont.W = *lplf; 2366 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT); 2367 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); 2368 2369 return TRUE; 2370 } 2371 2372 /*********************************************************************** 2373 * ImmSetCompositionStringA (IMM32.@) 2374 */ 2375 BOOL WINAPI ImmSetCompositionStringA( 2376 HIMC hIMC, DWORD dwIndex, 2377 LPCVOID lpComp, DWORD dwCompLen, 2378 LPCVOID lpRead, DWORD dwReadLen) 2379 { 2380 DWORD comp_len; 2381 DWORD read_len; 2382 WCHAR *CompBuffer = NULL; 2383 WCHAR *ReadBuffer = NULL; 2384 BOOL rc; 2385 InputContextData *data = get_imc_data(hIMC); 2386 2387 TRACE("(%p, %d, %p, %d, %p, %d):\n", 2388 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 2389 2390 if (!data) 2391 return FALSE; 2392 2393 if (!(dwIndex == SCS_SETSTR || 2394 dwIndex == SCS_CHANGEATTR || 2395 dwIndex == SCS_CHANGECLAUSE || 2396 dwIndex == SCS_SETRECONVERTSTRING || 2397 dwIndex == SCS_QUERYRECONVERTSTRING)) 2398 return FALSE; 2399 2400 if (!is_himc_ime_unicode(data)) 2401 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, 2402 dwCompLen, lpRead, dwReadLen); 2403 2404 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0); 2405 if (comp_len) 2406 { 2407 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR)); 2408 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len); 2409 } 2410 2411 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0); 2412 if (read_len) 2413 { 2414 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR)); 2415 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len); 2416 } 2417 2418 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len, 2419 ReadBuffer, read_len); 2420 2421 HeapFree(GetProcessHeap(), 0, CompBuffer); 2422 HeapFree(GetProcessHeap(), 0, ReadBuffer); 2423 2424 return rc; 2425 } 2426 2427 /*********************************************************************** 2428 * ImmSetCompositionStringW (IMM32.@) 2429 */ 2430 BOOL WINAPI ImmSetCompositionStringW( 2431 HIMC hIMC, DWORD dwIndex, 2432 LPCVOID lpComp, DWORD dwCompLen, 2433 LPCVOID lpRead, DWORD dwReadLen) 2434 { 2435 DWORD comp_len; 2436 DWORD read_len; 2437 CHAR *CompBuffer = NULL; 2438 CHAR *ReadBuffer = NULL; 2439 BOOL rc; 2440 InputContextData *data = get_imc_data(hIMC); 2441 2442 TRACE("(%p, %d, %p, %d, %p, %d):\n", 2443 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 2444 2445 if (!data) 2446 return FALSE; 2447 2448 if (!(dwIndex == SCS_SETSTR || 2449 dwIndex == SCS_CHANGEATTR || 2450 dwIndex == SCS_CHANGECLAUSE || 2451 dwIndex == SCS_SETRECONVERTSTRING || 2452 dwIndex == SCS_QUERYRECONVERTSTRING)) 2453 return FALSE; 2454 2455 if (is_himc_ime_unicode(data)) 2456 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, 2457 dwCompLen, lpRead, dwReadLen); 2458 2459 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL, 2460 NULL); 2461 if (comp_len) 2462 { 2463 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len); 2464 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len, 2465 NULL, NULL); 2466 } 2467 2468 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL, 2469 NULL); 2470 if (read_len) 2471 { 2472 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len); 2473 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len, 2474 NULL, NULL); 2475 } 2476 2477 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len, 2478 ReadBuffer, read_len); 2479 2480 HeapFree(GetProcessHeap(), 0, CompBuffer); 2481 HeapFree(GetProcessHeap(), 0, ReadBuffer); 2482 2483 return rc; 2484 } 2485 2486 /*********************************************************************** 2487 * ImmSetCompositionWindow (IMM32.@) 2488 */ 2489 BOOL WINAPI ImmSetCompositionWindow( 2490 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 2491 { 2492 BOOL reshow = FALSE; 2493 InputContextData *data = get_imc_data(hIMC); 2494 2495 TRACE("(%p, %p)\n", hIMC, lpCompForm); 2496 if (lpCompForm) 2497 TRACE("\t%x, %s, %s\n", lpCompForm->dwStyle, 2498 wine_dbgstr_point(&lpCompForm->ptCurrentPos), 2499 wine_dbgstr_rect(&lpCompForm->rcArea)); 2500 2501 if (!data) 2502 { 2503 SetLastError(ERROR_INVALID_HANDLE); 2504 return FALSE; 2505 } 2506 2507 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2508 return FALSE; 2509 2510 data->IMC.cfCompForm = *lpCompForm; 2511 2512 if (IsWindowVisible(data->immKbd->UIWnd)) 2513 { 2514 reshow = TRUE; 2515 ShowWindow(data->immKbd->UIWnd,SW_HIDE); 2516 } 2517 2518 /* FIXME: this is a partial stub */ 2519 2520 if (reshow) 2521 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE); 2522 2523 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0); 2524 return TRUE; 2525 } 2526 2527 /*********************************************************************** 2528 * ImmSetConversionStatus (IMM32.@) 2529 */ 2530 BOOL WINAPI ImmSetConversionStatus( 2531 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) 2532 { 2533 DWORD oldConversion, oldSentence; 2534 InputContextData *data = get_imc_data(hIMC); 2535 2536 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence); 2537 2538 if (!data) 2539 { 2540 SetLastError(ERROR_INVALID_HANDLE); 2541 return FALSE; 2542 } 2543 2544 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2545 return FALSE; 2546 2547 if ( fdwConversion != data->IMC.fdwConversion ) 2548 { 2549 oldConversion = data->IMC.fdwConversion; 2550 data->IMC.fdwConversion = fdwConversion; 2551 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE); 2552 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0); 2553 } 2554 if ( fdwSentence != data->IMC.fdwSentence ) 2555 { 2556 oldSentence = data->IMC.fdwSentence; 2557 data->IMC.fdwSentence = fdwSentence; 2558 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE); 2559 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0); 2560 } 2561 2562 return TRUE; 2563 } 2564 2565 /*********************************************************************** 2566 * ImmSetOpenStatus (IMM32.@) 2567 */ 2568 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) 2569 { 2570 InputContextData *data = get_imc_data(hIMC); 2571 2572 TRACE("%p %d\n", hIMC, fOpen); 2573 2574 if (!data) 2575 { 2576 SetLastError(ERROR_INVALID_HANDLE); 2577 return FALSE; 2578 } 2579 2580 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2581 return FALSE; 2582 2583 if (data->immKbd->UIWnd == NULL) 2584 { 2585 /* create the ime window */ 2586 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW, 2587 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0, 2588 0, data->immKbd->hIME, 0); 2589 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data); 2590 } 2591 else if (fOpen) 2592 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data); 2593 2594 if (!fOpen != !data->IMC.fOpen) 2595 { 2596 data->IMC.fOpen = fOpen; 2597 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS); 2598 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0); 2599 } 2600 2601 return TRUE; 2602 } 2603 2604 /*********************************************************************** 2605 * ImmSetStatusWindowPos (IMM32.@) 2606 */ 2607 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 2608 { 2609 InputContextData *data = get_imc_data(hIMC); 2610 2611 TRACE("(%p, %p)\n", hIMC, lpptPos); 2612 2613 if (!data || !lpptPos) 2614 { 2615 SetLastError(ERROR_INVALID_HANDLE); 2616 return FALSE; 2617 } 2618 2619 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2620 return FALSE; 2621 2622 TRACE("\t%s\n", wine_dbgstr_point(lpptPos)); 2623 2624 data->IMC.ptStatusWndPos = *lpptPos; 2625 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS); 2626 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0); 2627 2628 return TRUE; 2629 } 2630 2631 /*********************************************************************** 2632 * ImmCreateSoftKeyboard(IMM32.@) 2633 */ 2634 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y) 2635 { 2636 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y); 2637 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2638 return 0; 2639 } 2640 2641 /*********************************************************************** 2642 * ImmDestroySoftKeyboard(IMM32.@) 2643 */ 2644 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd) 2645 { 2646 FIXME("(%p): stub\n", hSoftWnd); 2647 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2648 return FALSE; 2649 } 2650 2651 /*********************************************************************** 2652 * ImmShowSoftKeyboard(IMM32.@) 2653 */ 2654 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow) 2655 { 2656 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow); 2657 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2658 return FALSE; 2659 } 2660 2661 /*********************************************************************** 2662 * ImmSimulateHotKey (IMM32.@) 2663 */ 2664 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID) 2665 { 2666 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID); 2667 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2668 return FALSE; 2669 } 2670 2671 /*********************************************************************** 2672 * ImmUnregisterWordA (IMM32.@) 2673 */ 2674 BOOL WINAPI ImmUnregisterWordA( 2675 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister) 2676 { 2677 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2678 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle, 2679 debugstr_a(lpszUnregister)); 2680 if (immHkl->hIME && immHkl->pImeUnregisterWord) 2681 { 2682 if (!is_kbd_ime_unicode(immHkl)) 2683 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle, 2684 (LPCWSTR)lpszUnregister); 2685 else 2686 { 2687 LPWSTR lpszwReading = strdupAtoW(lpszReading); 2688 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister); 2689 BOOL rc; 2690 2691 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister); 2692 HeapFree(GetProcessHeap(),0,lpszwReading); 2693 HeapFree(GetProcessHeap(),0,lpszwUnregister); 2694 return rc; 2695 } 2696 } 2697 else 2698 return FALSE; 2699 } 2700 2701 /*********************************************************************** 2702 * ImmUnregisterWordW (IMM32.@) 2703 */ 2704 BOOL WINAPI ImmUnregisterWordW( 2705 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister) 2706 { 2707 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2708 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle, 2709 debugstr_w(lpszUnregister)); 2710 if (immHkl->hIME && immHkl->pImeUnregisterWord) 2711 { 2712 if (is_kbd_ime_unicode(immHkl)) 2713 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister); 2714 else 2715 { 2716 LPSTR lpszaReading = strdupWtoA(lpszReading); 2717 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister); 2718 BOOL rc; 2719 2720 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle, 2721 (LPCWSTR)lpszaUnregister); 2722 HeapFree(GetProcessHeap(),0,lpszaReading); 2723 HeapFree(GetProcessHeap(),0,lpszaUnregister); 2724 return rc; 2725 } 2726 } 2727 else 2728 return FALSE; 2729 } 2730 2731 /*********************************************************************** 2732 * ImmGetImeMenuItemsA (IMM32.@) 2733 */ 2734 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType, 2735 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu, 2736 DWORD dwSize) 2737 { 2738 InputContextData *data = get_imc_data(hIMC); 2739 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, 2740 lpImeParentMenu, lpImeMenu, dwSize); 2741 2742 if (!data) 2743 { 2744 SetLastError(ERROR_INVALID_HANDLE); 2745 return 0; 2746 } 2747 2748 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems) 2749 { 2750 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu)) 2751 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2752 (IMEMENUITEMINFOW*)lpImeParentMenu, 2753 (IMEMENUITEMINFOW*)lpImeMenu, dwSize); 2754 else 2755 { 2756 IMEMENUITEMINFOW lpImeParentMenuW; 2757 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL; 2758 DWORD rc; 2759 2760 if (lpImeParentMenu) 2761 parent = &lpImeParentMenuW; 2762 if (lpImeMenu) 2763 { 2764 int count = dwSize / sizeof(LPIMEMENUITEMINFOA); 2765 dwSize = count * sizeof(IMEMENUITEMINFOW); 2766 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize); 2767 } 2768 else 2769 lpImeMenuW = NULL; 2770 2771 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2772 parent, lpImeMenuW, dwSize); 2773 2774 if (lpImeParentMenu) 2775 { 2776 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA)); 2777 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem; 2778 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString, 2779 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE, 2780 NULL, NULL); 2781 } 2782 if (lpImeMenu && rc) 2783 { 2784 unsigned int i; 2785 for (i = 0; i < rc; i++) 2786 { 2787 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA)); 2788 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem; 2789 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString, 2790 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE, 2791 NULL, NULL); 2792 } 2793 } 2794 HeapFree(GetProcessHeap(),0,lpImeMenuW); 2795 return rc; 2796 } 2797 } 2798 else 2799 return 0; 2800 } 2801 2802 /*********************************************************************** 2803 * ImmGetImeMenuItemsW (IMM32.@) 2804 */ 2805 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType, 2806 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, 2807 DWORD dwSize) 2808 { 2809 InputContextData *data = get_imc_data(hIMC); 2810 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, 2811 lpImeParentMenu, lpImeMenu, dwSize); 2812 2813 if (!data) 2814 { 2815 SetLastError(ERROR_INVALID_HANDLE); 2816 return 0; 2817 } 2818 2819 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems) 2820 { 2821 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu)) 2822 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2823 lpImeParentMenu, lpImeMenu, dwSize); 2824 else 2825 { 2826 IMEMENUITEMINFOA lpImeParentMenuA; 2827 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL; 2828 DWORD rc; 2829 2830 if (lpImeParentMenu) 2831 parent = &lpImeParentMenuA; 2832 if (lpImeMenu) 2833 { 2834 int count = dwSize / sizeof(LPIMEMENUITEMINFOW); 2835 dwSize = count * sizeof(IMEMENUITEMINFOA); 2836 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize); 2837 } 2838 else 2839 lpImeMenuA = NULL; 2840 2841 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2842 (IMEMENUITEMINFOW*)parent, 2843 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize); 2844 2845 if (lpImeParentMenu) 2846 { 2847 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA)); 2848 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem; 2849 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString, 2850 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE); 2851 } 2852 if (lpImeMenu && rc) 2853 { 2854 unsigned int i; 2855 for (i = 0; i < rc; i++) 2856 { 2857 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA)); 2858 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem; 2859 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString, 2860 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE); 2861 } 2862 } 2863 HeapFree(GetProcessHeap(),0,lpImeMenuA); 2864 return rc; 2865 } 2866 } 2867 else 2868 return 0; 2869 } 2870 2871 /*********************************************************************** 2872 * ImmLockIMC(IMM32.@) 2873 */ 2874 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) 2875 { 2876 InputContextData *data = get_imc_data(hIMC); 2877 2878 if (!data) 2879 return NULL; 2880 data->dwLock++; 2881 return &data->IMC; 2882 } 2883 2884 /*********************************************************************** 2885 * ImmUnlockIMC(IMM32.@) 2886 */ 2887 BOOL WINAPI ImmUnlockIMC(HIMC hIMC) 2888 { 2889 InputContextData *data = get_imc_data(hIMC); 2890 2891 if (!data) 2892 return FALSE; 2893 if (data->dwLock) 2894 data->dwLock--; 2895 return TRUE; 2896 } 2897 2898 /*********************************************************************** 2899 * ImmGetIMCLockCount(IMM32.@) 2900 */ 2901 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) 2902 { 2903 InputContextData *data = get_imc_data(hIMC); 2904 if (!data) 2905 return 0; 2906 return data->dwLock; 2907 } 2908 2909 /*********************************************************************** 2910 * ImmCreateIMCC(IMM32.@) 2911 */ 2912 HIMCC WINAPI ImmCreateIMCC(DWORD size) 2913 { 2914 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size); 2915 } 2916 2917 /*********************************************************************** 2918 * ImmDestroyIMCC(IMM32.@) 2919 */ 2920 HIMCC WINAPI ImmDestroyIMCC(HIMCC block) 2921 { 2922 return GlobalFree(block); 2923 } 2924 2925 /*********************************************************************** 2926 * ImmLockIMCC(IMM32.@) 2927 */ 2928 LPVOID WINAPI ImmLockIMCC(HIMCC imcc) 2929 { 2930 return GlobalLock(imcc); 2931 } 2932 2933 /*********************************************************************** 2934 * ImmUnlockIMCC(IMM32.@) 2935 */ 2936 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc) 2937 { 2938 return GlobalUnlock(imcc); 2939 } 2940 2941 /*********************************************************************** 2942 * ImmGetIMCCLockCount(IMM32.@) 2943 */ 2944 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc) 2945 { 2946 return GlobalFlags(imcc) & GMEM_LOCKCOUNT; 2947 } 2948 2949 /*********************************************************************** 2950 * ImmReSizeIMCC(IMM32.@) 2951 */ 2952 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size) 2953 { 2954 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE); 2955 } 2956 2957 /*********************************************************************** 2958 * ImmGetIMCCSize(IMM32.@) 2959 */ 2960 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) 2961 { 2962 return GlobalSize(imcc); 2963 } 2964 2965 /*********************************************************************** 2966 * ImmGenerateMessage(IMM32.@) 2967 */ 2968 BOOL WINAPI ImmGenerateMessage(HIMC hIMC) 2969 { 2970 InputContextData *data = get_imc_data(hIMC); 2971 2972 if (!data) 2973 { 2974 SetLastError(ERROR_INVALID_HANDLE); 2975 return FALSE; 2976 } 2977 2978 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf); 2979 if (data->IMC.dwNumMsgBuf > 0) 2980 { 2981 LPTRANSMSG lpTransMsg; 2982 HIMCC hMsgBuf; 2983 DWORD i, dwNumMsgBuf; 2984 2985 /* We are going to detach our hMsgBuff so that if processing messages 2986 generates new messages they go into a new buffer */ 2987 hMsgBuf = data->IMC.hMsgBuf; 2988 dwNumMsgBuf = data->IMC.dwNumMsgBuf; 2989 2990 data->IMC.hMsgBuf = ImmCreateIMCC(0); 2991 data->IMC.dwNumMsgBuf = 0; 2992 2993 lpTransMsg = ImmLockIMCC(hMsgBuf); 2994 for (i = 0; i < dwNumMsgBuf; i++) 2995 ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam); 2996 2997 ImmUnlockIMCC(hMsgBuf); 2998 ImmDestroyIMCC(hMsgBuf); 2999 } 3000 3001 return TRUE; 3002 } 3003 3004 /*********************************************************************** 3005 * ImmTranslateMessage(IMM32.@) 3006 * ( Undocumented, call internally and from user32.dll ) 3007 */ 3008 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData) 3009 { 3010 InputContextData *data; 3011 HIMC imc = ImmGetContext(hwnd); 3012 BYTE state[256]; 3013 UINT scancode; 3014 LPVOID list = 0; 3015 UINT msg_count; 3016 UINT uVirtKey; 3017 static const DWORD list_count = 10; 3018 3019 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData); 3020 3021 if (imc) 3022 data = imc; 3023 else 3024 return FALSE; 3025 3026 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx) 3027 return FALSE; 3028 3029 GetKeyboardState(state); 3030 scancode = lKeyData >> 0x10 & 0xff; 3031 3032 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD)); 3033 ((DWORD*)list)[0] = list_count; 3034 3035 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST) 3036 { 3037 WCHAR chr; 3038 3039 if (!is_himc_ime_unicode(data)) 3040 ToAscii(data->lastVK, scancode, state, &chr, 0); 3041 else 3042 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0)); 3043 uVirtKey = MAKELONG(data->lastVK,chr); 3044 } 3045 else 3046 uVirtKey = data->lastVK; 3047 3048 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc); 3049 TRACE("%i messages generated\n",msg_count); 3050 if (msg_count && msg_count <= list_count) 3051 { 3052 UINT i; 3053 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD)); 3054 3055 for (i = 0; i < msg_count; i++) 3056 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam); 3057 } 3058 else if (msg_count > list_count) 3059 ImmGenerateMessage(imc); 3060 3061 HeapFree(GetProcessHeap(),0,list); 3062 3063 data->lastVK = VK_PROCESSKEY; 3064 3065 return (msg_count > 0); 3066 } 3067 3068 /*********************************************************************** 3069 * ImmProcessKey(IMM32.@) 3070 * ( Undocumented, called from user32.dll ) 3071 */ 3072 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown) 3073 { 3074 InputContextData *data; 3075 HIMC imc = ImmGetContext(hwnd); 3076 BYTE state[256]; 3077 3078 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown); 3079 3080 if (imc) 3081 data = imc; 3082 else 3083 return FALSE; 3084 3085 /* Make sure we are inputting to the correct keyboard */ 3086 if (data->immKbd->hkl != hKL) 3087 { 3088 ImmHkl *new_hkl = IMM_GetImmHkl(hKL); 3089 if (new_hkl) 3090 { 3091 data->immKbd->pImeSelect(imc, FALSE); 3092 data->immKbd->uSelected--; 3093 data->immKbd = new_hkl; 3094 data->immKbd->pImeSelect(imc, TRUE); 3095 data->immKbd->uSelected++; 3096 } 3097 else 3098 return FALSE; 3099 } 3100 3101 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey) 3102 return FALSE; 3103 3104 GetKeyboardState(state); 3105 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state)) 3106 { 3107 data->lastVK = vKey; 3108 return TRUE; 3109 } 3110 3111 data->lastVK = VK_PROCESSKEY; 3112 return FALSE; 3113 } 3114 3115 /*********************************************************************** 3116 * ImmDisableTextFrameService(IMM32.@) 3117 */ 3118 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread) 3119 { 3120 FIXME("Stub\n"); 3121 return FALSE; 3122 } 3123 3124 /*********************************************************************** 3125 * ImmEnumInputContext(IMM32.@) 3126 */ 3127 3128 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam) 3129 { 3130 FIXME("Stub\n"); 3131 return FALSE; 3132 } 3133 3134 /*********************************************************************** 3135 * ImmGetHotKey(IMM32.@) 3136 */ 3137 3138 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl) 3139 { 3140 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl); 3141 return FALSE; 3142 } 3143 3144 /*********************************************************************** 3145 * ImmDisableLegacyIME(IMM32.@) 3146 */ 3147 BOOL WINAPI ImmDisableLegacyIME(void) 3148 { 3149 FIXME("stub\n"); 3150 return TRUE; 3151 } 3152