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 if(GetActiveWindow() == data->IMC.hWnd) 612 { 613 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL); 614 data->IMC.hWnd = hWnd; 615 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL); 616 } 617 618 return old; 619 } 620 621 622 /* 623 * Helper function for ImmAssociateContextEx 624 */ 625 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam) 626 { 627 HIMC hImc = (HIMC)lParam; 628 ImmAssociateContext(hwnd,hImc); 629 return TRUE; 630 } 631 632 /*********************************************************************** 633 * ImmAssociateContextEx (IMM32.@) 634 */ 635 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) 636 { 637 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags); 638 639 if (!hWnd) 640 return FALSE; 641 642 switch (dwFlags) 643 { 644 case 0: 645 ImmAssociateContext(hWnd,hIMC); 646 return TRUE; 647 case IACE_DEFAULT: 648 { 649 HIMC defaultContext = get_default_context( hWnd ); 650 if (!defaultContext) return FALSE; 651 ImmAssociateContext(hWnd,defaultContext); 652 return TRUE; 653 } 654 case IACE_IGNORENOCONTEXT: 655 if (GetPropW(hWnd,szwWineIMCProperty)) 656 ImmAssociateContext(hWnd,hIMC); 657 return TRUE; 658 case IACE_CHILDREN: 659 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC); 660 return TRUE; 661 default: 662 FIXME("Unknown dwFlags 0x%x\n",dwFlags); 663 return FALSE; 664 } 665 } 666 667 /*********************************************************************** 668 * ImmConfigureIMEA (IMM32.@) 669 */ 670 BOOL WINAPI ImmConfigureIMEA( 671 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 672 { 673 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 674 675 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); 676 677 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData) 678 return FALSE; 679 680 if (immHkl->hIME && immHkl->pImeConfigure) 681 { 682 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl)) 683 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData); 684 else 685 { 686 REGISTERWORDW rww; 687 REGISTERWORDA *rwa = lpData; 688 BOOL rc; 689 690 rww.lpReading = strdupAtoW(rwa->lpReading); 691 rww.lpWord = strdupAtoW(rwa->lpWord); 692 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww); 693 HeapFree(GetProcessHeap(),0,rww.lpReading); 694 HeapFree(GetProcessHeap(),0,rww.lpWord); 695 return rc; 696 } 697 } 698 else 699 return FALSE; 700 } 701 702 /*********************************************************************** 703 * ImmConfigureIMEW (IMM32.@) 704 */ 705 BOOL WINAPI ImmConfigureIMEW( 706 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 707 { 708 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 709 710 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); 711 712 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData) 713 return FALSE; 714 715 if (immHkl->hIME && immHkl->pImeConfigure) 716 { 717 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl)) 718 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData); 719 else 720 { 721 REGISTERWORDW *rww = lpData; 722 REGISTERWORDA rwa; 723 BOOL rc; 724 725 rwa.lpReading = strdupWtoA(rww->lpReading); 726 rwa.lpWord = strdupWtoA(rww->lpWord); 727 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa); 728 HeapFree(GetProcessHeap(),0,rwa.lpReading); 729 HeapFree(GetProcessHeap(),0,rwa.lpWord); 730 return rc; 731 } 732 } 733 else 734 return FALSE; 735 } 736 737 /*********************************************************************** 738 * ImmCreateContext (IMM32.@) 739 */ 740 HIMC WINAPI ImmCreateContext(void) 741 { 742 InputContextData *new_context; 743 LPGUIDELINE gl; 744 LPCANDIDATEINFO ci; 745 int i; 746 747 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData)); 748 749 /* Load the IME */ 750 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0)); 751 752 if (!new_context->immKbd->hIME) 753 { 754 TRACE("IME dll could not be loaded\n"); 755 HeapFree(GetProcessHeap(),0,new_context); 756 return 0; 757 } 758 759 /* the HIMCCs are never NULL */ 760 new_context->IMC.hCompStr = ImmCreateBlankCompStr(); 761 new_context->IMC.hMsgBuf = ImmCreateIMCC(0); 762 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO)); 763 ci = ImmLockIMCC(new_context->IMC.hCandInfo); 764 memset(ci,0,sizeof(CANDIDATEINFO)); 765 ci->dwSize = sizeof(CANDIDATEINFO); 766 ImmUnlockIMCC(new_context->IMC.hCandInfo); 767 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE)); 768 gl = ImmLockIMCC(new_context->IMC.hGuideLine); 769 memset(gl,0,sizeof(GUIDELINE)); 770 gl->dwSize = sizeof(GUIDELINE); 771 ImmUnlockIMCC(new_context->IMC.hGuideLine); 772 773 for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++) 774 new_context->IMC.cfCandForm[i].dwIndex = ~0u; 775 776 /* Initialize the IME Private */ 777 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize); 778 779 new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps; 780 new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps; 781 782 if (!new_context->immKbd->pImeSelect(new_context, TRUE)) 783 { 784 TRACE("Selection of IME failed\n"); 785 IMM_DestroyContext(new_context); 786 return 0; 787 } 788 new_context->threadID = GetCurrentThreadId(); 789 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd); 790 791 new_context->immKbd->uSelected++; 792 TRACE("Created context %p\n",new_context); 793 794 new_context->magic = WINE_IMC_VALID_MAGIC; 795 return new_context; 796 } 797 798 static BOOL IMM_DestroyContext(HIMC hIMC) 799 { 800 InputContextData *data = get_imc_data(hIMC); 801 802 TRACE("Destroying %p\n",hIMC); 803 804 if (!data) 805 return FALSE; 806 807 data->immKbd->uSelected --; 808 data->immKbd->pImeSelect(hIMC, FALSE); 809 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd); 810 811 ImmDestroyIMCC(data->IMC.hCompStr); 812 ImmDestroyIMCC(data->IMC.hCandInfo); 813 ImmDestroyIMCC(data->IMC.hGuideLine); 814 ImmDestroyIMCC(data->IMC.hPrivate); 815 ImmDestroyIMCC(data->IMC.hMsgBuf); 816 817 data->magic = 0; 818 HeapFree(GetProcessHeap(),0,data); 819 820 return TRUE; 821 } 822 823 /*********************************************************************** 824 * ImmDestroyContext (IMM32.@) 825 */ 826 BOOL WINAPI ImmDestroyContext(HIMC hIMC) 827 { 828 if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC)) 829 return IMM_DestroyContext(hIMC); 830 else 831 return FALSE; 832 } 833 834 /*********************************************************************** 835 * ImmDisableIME (IMM32.@) 836 */ 837 BOOL WINAPI ImmDisableIME(DWORD idThread) 838 { 839 if (idThread == (DWORD)-1) 840 disable_ime = TRUE; 841 else { 842 IMMThreadData *thread_data = IMM_GetThreadData(NULL, idThread); 843 if (!thread_data) return FALSE; 844 thread_data->disableIME = TRUE; 845 LeaveCriticalSection(&threaddata_cs); 846 } 847 return TRUE; 848 } 849 850 /*********************************************************************** 851 * ImmEnumRegisterWordA (IMM32.@) 852 */ 853 UINT WINAPI ImmEnumRegisterWordA( 854 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc, 855 LPCSTR lpszReading, DWORD dwStyle, 856 LPCSTR lpszRegister, LPVOID lpData) 857 { 858 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 859 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc, 860 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData); 861 if (immHkl->hIME && immHkl->pImeEnumRegisterWord) 862 { 863 if (!is_kbd_ime_unicode(immHkl)) 864 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc, 865 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData); 866 else 867 { 868 LPWSTR lpszwReading = strdupAtoW(lpszReading); 869 LPWSTR lpszwRegister = strdupAtoW(lpszRegister); 870 BOOL rc; 871 872 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc, 873 lpszwReading, dwStyle, lpszwRegister, 874 lpData); 875 876 HeapFree(GetProcessHeap(),0,lpszwReading); 877 HeapFree(GetProcessHeap(),0,lpszwRegister); 878 return rc; 879 } 880 } 881 else 882 return 0; 883 } 884 885 /*********************************************************************** 886 * ImmEnumRegisterWordW (IMM32.@) 887 */ 888 UINT WINAPI ImmEnumRegisterWordW( 889 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc, 890 LPCWSTR lpszReading, DWORD dwStyle, 891 LPCWSTR lpszRegister, LPVOID lpData) 892 { 893 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 894 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc, 895 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData); 896 if (immHkl->hIME && immHkl->pImeEnumRegisterWord) 897 { 898 if (is_kbd_ime_unicode(immHkl)) 899 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle, 900 lpszRegister, lpData); 901 else 902 { 903 LPSTR lpszaReading = strdupWtoA(lpszReading); 904 LPSTR lpszaRegister = strdupWtoA(lpszRegister); 905 BOOL rc; 906 907 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading, 908 dwStyle, (LPCWSTR)lpszaRegister, lpData); 909 910 HeapFree(GetProcessHeap(),0,lpszaReading); 911 HeapFree(GetProcessHeap(),0,lpszaRegister); 912 return rc; 913 } 914 } 915 else 916 return 0; 917 } 918 919 static inline BOOL EscapeRequiresWA(UINT uEscape) 920 { 921 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY || 922 uEscape == IME_ESC_SET_EUDC_DICTIONARY || 923 uEscape == IME_ESC_IME_NAME || 924 uEscape == IME_ESC_GETHELPFILENAME) 925 return TRUE; 926 return FALSE; 927 } 928 929 /*********************************************************************** 930 * ImmEscapeA (IMM32.@) 931 */ 932 LRESULT WINAPI ImmEscapeA( 933 HKL hKL, HIMC hIMC, 934 UINT uEscape, LPVOID lpData) 935 { 936 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 937 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData); 938 939 if (immHkl->hIME && immHkl->pImeEscape) 940 { 941 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl)) 942 return immHkl->pImeEscape(hIMC,uEscape,lpData); 943 else 944 { 945 WCHAR buffer[81]; /* largest required buffer should be 80 */ 946 LRESULT rc; 947 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY) 948 { 949 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81); 950 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 951 } 952 else 953 { 954 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 955 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL); 956 } 957 return rc; 958 } 959 } 960 else 961 return 0; 962 } 963 964 /*********************************************************************** 965 * ImmEscapeW (IMM32.@) 966 */ 967 LRESULT WINAPI ImmEscapeW( 968 HKL hKL, HIMC hIMC, 969 UINT uEscape, LPVOID lpData) 970 { 971 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 972 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData); 973 974 if (immHkl->hIME && immHkl->pImeEscape) 975 { 976 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl)) 977 return immHkl->pImeEscape(hIMC,uEscape,lpData); 978 else 979 { 980 CHAR buffer[81]; /* largest required buffer should be 80 */ 981 LRESULT rc; 982 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY) 983 { 984 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL); 985 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 986 } 987 else 988 { 989 rc = immHkl->pImeEscape(hIMC,uEscape,buffer); 990 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80); 991 } 992 return rc; 993 } 994 } 995 else 996 return 0; 997 } 998 999 /*********************************************************************** 1000 * ImmGetCandidateListA (IMM32.@) 1001 */ 1002 DWORD WINAPI ImmGetCandidateListA( 1003 HIMC hIMC, DWORD dwIndex, 1004 LPCANDIDATELIST lpCandList, DWORD dwBufLen) 1005 { 1006 InputContextData *data = get_imc_data(hIMC); 1007 LPCANDIDATEINFO candinfo; 1008 LPCANDIDATELIST candlist; 1009 DWORD ret = 0; 1010 1011 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen); 1012 1013 if (!data || !data->IMC.hCandInfo) 1014 return 0; 1015 1016 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1017 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset)) 1018 goto done; 1019 1020 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]); 1021 if ( !candlist->dwSize || !candlist->dwCount ) 1022 goto done; 1023 1024 if ( !is_himc_ime_unicode(data) ) 1025 { 1026 ret = candlist->dwSize; 1027 if ( lpCandList && dwBufLen >= ret ) 1028 memcpy(lpCandList, candlist, ret); 1029 } 1030 else 1031 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen); 1032 1033 done: 1034 ImmUnlockIMCC(data->IMC.hCandInfo); 1035 return ret; 1036 } 1037 1038 /*********************************************************************** 1039 * ImmGetCandidateListCountA (IMM32.@) 1040 */ 1041 DWORD WINAPI ImmGetCandidateListCountA( 1042 HIMC hIMC, LPDWORD lpdwListCount) 1043 { 1044 InputContextData *data = get_imc_data(hIMC); 1045 LPCANDIDATEINFO candinfo; 1046 DWORD ret, count; 1047 1048 TRACE("%p, %p\n", hIMC, lpdwListCount); 1049 1050 if (!data || !lpdwListCount || !data->IMC.hCandInfo) 1051 return 0; 1052 1053 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1054 1055 *lpdwListCount = count = candinfo->dwCount; 1056 1057 if ( !is_himc_ime_unicode(data) ) 1058 ret = candinfo->dwSize; 1059 else 1060 { 1061 ret = sizeof(CANDIDATEINFO); 1062 while ( count-- ) 1063 ret += ImmGetCandidateListA(hIMC, count, NULL, 0); 1064 } 1065 1066 ImmUnlockIMCC(data->IMC.hCandInfo); 1067 return ret; 1068 } 1069 1070 /*********************************************************************** 1071 * ImmGetCandidateListCountW (IMM32.@) 1072 */ 1073 DWORD WINAPI ImmGetCandidateListCountW( 1074 HIMC hIMC, LPDWORD lpdwListCount) 1075 { 1076 InputContextData *data = get_imc_data(hIMC); 1077 LPCANDIDATEINFO candinfo; 1078 DWORD ret, count; 1079 1080 TRACE("%p, %p\n", hIMC, lpdwListCount); 1081 1082 if (!data || !lpdwListCount || !data->IMC.hCandInfo) 1083 return 0; 1084 1085 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1086 1087 *lpdwListCount = count = candinfo->dwCount; 1088 1089 if ( is_himc_ime_unicode(data) ) 1090 ret = candinfo->dwSize; 1091 else 1092 { 1093 ret = sizeof(CANDIDATEINFO); 1094 while ( count-- ) 1095 ret += ImmGetCandidateListW(hIMC, count, NULL, 0); 1096 } 1097 1098 ImmUnlockIMCC(data->IMC.hCandInfo); 1099 return ret; 1100 } 1101 1102 /*********************************************************************** 1103 * ImmGetCandidateListW (IMM32.@) 1104 */ 1105 DWORD WINAPI ImmGetCandidateListW( 1106 HIMC hIMC, DWORD dwIndex, 1107 LPCANDIDATELIST lpCandList, DWORD dwBufLen) 1108 { 1109 InputContextData *data = get_imc_data(hIMC); 1110 LPCANDIDATEINFO candinfo; 1111 LPCANDIDATELIST candlist; 1112 DWORD ret = 0; 1113 1114 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen); 1115 1116 if (!data || !data->IMC.hCandInfo) 1117 return 0; 1118 1119 candinfo = ImmLockIMCC(data->IMC.hCandInfo); 1120 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset)) 1121 goto done; 1122 1123 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]); 1124 if ( !candlist->dwSize || !candlist->dwCount ) 1125 goto done; 1126 1127 if ( is_himc_ime_unicode(data) ) 1128 { 1129 ret = candlist->dwSize; 1130 if ( lpCandList && dwBufLen >= ret ) 1131 memcpy(lpCandList, candlist, ret); 1132 } 1133 else 1134 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen); 1135 1136 done: 1137 ImmUnlockIMCC(data->IMC.hCandInfo); 1138 return ret; 1139 } 1140 1141 /*********************************************************************** 1142 * ImmGetCandidateWindow (IMM32.@) 1143 */ 1144 BOOL WINAPI ImmGetCandidateWindow( 1145 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate) 1146 { 1147 InputContextData *data = get_imc_data(hIMC); 1148 1149 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate); 1150 1151 if (!data || !lpCandidate) 1152 return FALSE; 1153 1154 if (dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm)) 1155 return FALSE; 1156 1157 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex) 1158 return FALSE; 1159 1160 *lpCandidate = data->IMC.cfCandForm[dwIndex]; 1161 1162 return TRUE; 1163 } 1164 1165 /*********************************************************************** 1166 * ImmGetCompositionFontA (IMM32.@) 1167 */ 1168 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1169 { 1170 LOGFONTW lfW; 1171 BOOL rc; 1172 1173 TRACE("(%p, %p):\n", hIMC, lplf); 1174 1175 rc = ImmGetCompositionFontW(hIMC,&lfW); 1176 if (!rc || !lplf) 1177 return FALSE; 1178 1179 memcpy(lplf,&lfW,sizeof(LOGFONTA)); 1180 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName, 1181 LF_FACESIZE, NULL, NULL); 1182 return TRUE; 1183 } 1184 1185 /*********************************************************************** 1186 * ImmGetCompositionFontW (IMM32.@) 1187 */ 1188 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1189 { 1190 InputContextData *data = get_imc_data(hIMC); 1191 1192 TRACE("(%p, %p):\n", hIMC, lplf); 1193 1194 if (!data || !lplf) 1195 return FALSE; 1196 1197 *lplf = data->IMC.lfFont.W; 1198 1199 return TRUE; 1200 } 1201 1202 1203 /* Helpers for the GetCompositionString functions */ 1204 1205 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen, 1206 BOOL unicode ) 1207 { 1208 INT rc; 1209 1210 if (is_himc_ime_unicode(data) && !unicode) 1211 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL); 1212 else if (!is_himc_ime_unicode(data) && unicode) 1213 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR); 1214 else 1215 { 1216 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR); 1217 memcpy( target, source, min(slen,tlen)*dlen); 1218 rc = slen*dlen; 1219 } 1220 1221 return rc; 1222 } 1223 1224 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen, 1225 LPBYTE target, INT tlen, BOOL unicode ) 1226 { 1227 INT rc; 1228 1229 if (is_himc_ime_unicode(data) && !unicode) 1230 { 1231 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL); 1232 if (tlen) 1233 { 1234 const BYTE *src = source; 1235 LPBYTE dst = target; 1236 int i, j = 0, k = 0; 1237 1238 if (rc < tlen) 1239 tlen = rc; 1240 for (i = 0; i < sslen; ++i) 1241 { 1242 int len; 1243 1244 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1, 1245 NULL, 0, NULL, NULL); 1246 for (; len > 0; --len) 1247 { 1248 dst[j++] = src[k]; 1249 1250 if (j >= tlen) 1251 goto end; 1252 } 1253 ++k; 1254 } 1255 end: 1256 rc = j; 1257 } 1258 } 1259 else if (!is_himc_ime_unicode(data) && unicode) 1260 { 1261 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0); 1262 if (tlen) 1263 { 1264 const BYTE *src = source; 1265 LPBYTE dst = target; 1266 int i, j = 0; 1267 1268 if (rc < tlen) 1269 tlen = rc; 1270 for (i = 0; i < sslen; ++i) 1271 { 1272 if (IsDBCSLeadByte(((LPSTR)ssource)[i])) 1273 continue; 1274 1275 dst[j++] = src[i]; 1276 1277 if (j >= tlen) 1278 break; 1279 } 1280 rc = j; 1281 } 1282 } 1283 else 1284 { 1285 memcpy( target, source, min(slen,tlen)); 1286 rc = slen; 1287 } 1288 1289 return rc; 1290 } 1291 1292 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, 1293 LPBYTE target, INT tlen, BOOL unicode ) 1294 { 1295 INT rc; 1296 1297 if (is_himc_ime_unicode(data) && !unicode) 1298 { 1299 if (tlen) 1300 { 1301 int i; 1302 1303 if (slen < tlen) 1304 tlen = slen; 1305 tlen /= sizeof (DWORD); 1306 for (i = 0; i < tlen; ++i) 1307 { 1308 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, 1309 ((DWORD *)source)[i], 1310 NULL, 0, 1311 NULL, NULL); 1312 } 1313 rc = sizeof (DWORD) * i; 1314 } 1315 else 1316 rc = slen; 1317 } 1318 else if (!is_himc_ime_unicode(data) && unicode) 1319 { 1320 if (tlen) 1321 { 1322 int i; 1323 1324 if (slen < tlen) 1325 tlen = slen; 1326 tlen /= sizeof (DWORD); 1327 for (i = 0; i < tlen; ++i) 1328 { 1329 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, 1330 ((DWORD *)source)[i], 1331 NULL, 0); 1332 } 1333 rc = sizeof (DWORD) * i; 1334 } 1335 else 1336 rc = slen; 1337 } 1338 else 1339 { 1340 memcpy( target, source, min(slen,tlen)); 1341 rc = slen; 1342 } 1343 1344 return rc; 1345 } 1346 1347 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode) 1348 { 1349 int rc; 1350 1351 if (is_himc_ime_unicode(data) && !unicode) 1352 { 1353 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL); 1354 } 1355 else if (!is_himc_ime_unicode(data) && unicode) 1356 { 1357 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0); 1358 } 1359 else 1360 rc = offset; 1361 1362 return rc; 1363 } 1364 1365 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, 1366 DWORD dwBufLen, BOOL unicode) 1367 { 1368 LONG rc = 0; 1369 InputContextData *data = get_imc_data(hIMC); 1370 LPCOMPOSITIONSTRING compstr; 1371 LPBYTE compdata; 1372 1373 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen); 1374 1375 if (!data) 1376 return FALSE; 1377 1378 if (!data->IMC.hCompStr) 1379 return FALSE; 1380 1381 compdata = ImmLockIMCC(data->IMC.hCompStr); 1382 compstr = (LPCOMPOSITIONSTRING)compdata; 1383 1384 switch (dwIndex) 1385 { 1386 case GCS_RESULTSTR: 1387 TRACE("GCS_RESULTSTR\n"); 1388 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode); 1389 break; 1390 case GCS_COMPSTR: 1391 TRACE("GCS_COMPSTR\n"); 1392 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode); 1393 break; 1394 case GCS_COMPATTR: 1395 TRACE("GCS_COMPATTR\n"); 1396 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen, 1397 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, 1398 lpBuf, dwBufLen, unicode); 1399 break; 1400 case GCS_COMPCLAUSE: 1401 TRACE("GCS_COMPCLAUSE\n"); 1402 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen, 1403 compdata + compstr->dwCompStrOffset, 1404 lpBuf, dwBufLen, unicode); 1405 break; 1406 case GCS_RESULTCLAUSE: 1407 TRACE("GCS_RESULTCLAUSE\n"); 1408 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen, 1409 compdata + compstr->dwResultStrOffset, 1410 lpBuf, dwBufLen, unicode); 1411 break; 1412 case GCS_RESULTREADSTR: 1413 TRACE("GCS_RESULTREADSTR\n"); 1414 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode); 1415 break; 1416 case GCS_RESULTREADCLAUSE: 1417 TRACE("GCS_RESULTREADCLAUSE\n"); 1418 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen, 1419 compdata + compstr->dwResultStrOffset, 1420 lpBuf, dwBufLen, unicode); 1421 break; 1422 case GCS_COMPREADSTR: 1423 TRACE("GCS_COMPREADSTR\n"); 1424 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode); 1425 break; 1426 case GCS_COMPREADATTR: 1427 TRACE("GCS_COMPREADATTR\n"); 1428 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen, 1429 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, 1430 lpBuf, dwBufLen, unicode); 1431 break; 1432 case GCS_COMPREADCLAUSE: 1433 TRACE("GCS_COMPREADCLAUSE\n"); 1434 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen, 1435 compdata + compstr->dwCompStrOffset, 1436 lpBuf, dwBufLen, unicode); 1437 break; 1438 case GCS_CURSORPOS: 1439 TRACE("GCS_CURSORPOS\n"); 1440 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode); 1441 break; 1442 case GCS_DELTASTART: 1443 TRACE("GCS_DELTASTART\n"); 1444 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode); 1445 break; 1446 default: 1447 FIXME("Unhandled index 0x%x\n",dwIndex); 1448 break; 1449 } 1450 1451 ImmUnlockIMCC(data->IMC.hCompStr); 1452 1453 return rc; 1454 } 1455 1456 /*********************************************************************** 1457 * ImmGetCompositionStringA (IMM32.@) 1458 */ 1459 LONG WINAPI ImmGetCompositionStringA( 1460 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) 1461 { 1462 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE); 1463 } 1464 1465 1466 /*********************************************************************** 1467 * ImmGetCompositionStringW (IMM32.@) 1468 */ 1469 LONG WINAPI ImmGetCompositionStringW( 1470 HIMC hIMC, DWORD dwIndex, 1471 LPVOID lpBuf, DWORD dwBufLen) 1472 { 1473 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE); 1474 } 1475 1476 /*********************************************************************** 1477 * ImmGetCompositionWindow (IMM32.@) 1478 */ 1479 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1480 { 1481 InputContextData *data = get_imc_data(hIMC); 1482 1483 TRACE("(%p, %p)\n", hIMC, lpCompForm); 1484 1485 if (!data) 1486 return FALSE; 1487 1488 *lpCompForm = data->IMC.cfCompForm; 1489 return TRUE; 1490 } 1491 1492 /*********************************************************************** 1493 * ImmGetContext (IMM32.@) 1494 * 1495 */ 1496 HIMC WINAPI ImmGetContext(HWND hWnd) 1497 { 1498 HIMC rc; 1499 1500 TRACE("%p\n", hWnd); 1501 1502 if (!IsWindow(hWnd)) 1503 { 1504 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1505 return NULL; 1506 } 1507 1508 rc = GetPropW(hWnd,szwWineIMCProperty); 1509 if (rc == (HIMC)-1) 1510 rc = NULL; 1511 else if (rc == NULL) 1512 rc = get_default_context( hWnd ); 1513 1514 if (rc) 1515 { 1516 InputContextData *data = rc; 1517 data->IMC.hWnd = hWnd; 1518 } 1519 1520 TRACE("returning %p\n", rc); 1521 1522 return rc; 1523 } 1524 1525 /*********************************************************************** 1526 * ImmGetConversionListA (IMM32.@) 1527 */ 1528 DWORD WINAPI ImmGetConversionListA( 1529 HKL hKL, HIMC hIMC, 1530 LPCSTR pSrc, LPCANDIDATELIST lpDst, 1531 DWORD dwBufLen, UINT uFlag) 1532 { 1533 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1534 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst, 1535 dwBufLen, uFlag); 1536 if (immHkl->hIME && immHkl->pImeConversionList) 1537 { 1538 if (!is_kbd_ime_unicode(immHkl)) 1539 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag); 1540 else 1541 { 1542 LPCANDIDATELIST lpwDst; 1543 DWORD ret = 0, len; 1544 LPWSTR pwSrc = strdupAtoW(pSrc); 1545 1546 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag); 1547 lpwDst = HeapAlloc(GetProcessHeap(), 0, len); 1548 if ( lpwDst ) 1549 { 1550 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag); 1551 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen); 1552 HeapFree(GetProcessHeap(), 0, lpwDst); 1553 } 1554 HeapFree(GetProcessHeap(), 0, pwSrc); 1555 1556 return ret; 1557 } 1558 } 1559 else 1560 return 0; 1561 } 1562 1563 /*********************************************************************** 1564 * ImmGetConversionListW (IMM32.@) 1565 */ 1566 DWORD WINAPI ImmGetConversionListW( 1567 HKL hKL, HIMC hIMC, 1568 LPCWSTR pSrc, LPCANDIDATELIST lpDst, 1569 DWORD dwBufLen, UINT uFlag) 1570 { 1571 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1572 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst, 1573 dwBufLen, uFlag); 1574 if (immHkl->hIME && immHkl->pImeConversionList) 1575 { 1576 if (is_kbd_ime_unicode(immHkl)) 1577 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag); 1578 else 1579 { 1580 LPCANDIDATELIST lpaDst; 1581 DWORD ret = 0, len; 1582 LPSTR paSrc = strdupWtoA(pSrc); 1583 1584 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag); 1585 lpaDst = HeapAlloc(GetProcessHeap(), 0, len); 1586 if ( lpaDst ) 1587 { 1588 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag); 1589 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen); 1590 HeapFree(GetProcessHeap(), 0, lpaDst); 1591 } 1592 HeapFree(GetProcessHeap(), 0, paSrc); 1593 1594 return ret; 1595 } 1596 } 1597 else 1598 return 0; 1599 } 1600 1601 /*********************************************************************** 1602 * ImmGetConversionStatus (IMM32.@) 1603 */ 1604 BOOL WINAPI ImmGetConversionStatus( 1605 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) 1606 { 1607 InputContextData *data = get_imc_data(hIMC); 1608 1609 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence); 1610 1611 if (!data) 1612 return FALSE; 1613 1614 if (lpfdwConversion) 1615 *lpfdwConversion = data->IMC.fdwConversion; 1616 if (lpfdwSentence) 1617 *lpfdwSentence = data->IMC.fdwSentence; 1618 1619 return TRUE; 1620 } 1621 1622 static BOOL needs_ime_window(HWND hwnd) 1623 { 1624 WCHAR classW[8]; 1625 1626 if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !strcmpW(classW, szwIME)) 1627 return FALSE; 1628 if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE; 1629 1630 return TRUE; 1631 } 1632 1633 /*********************************************************************** 1634 * __wine_register_window (IMM32.@) 1635 */ 1636 BOOL WINAPI __wine_register_window(HWND hwnd) 1637 { 1638 HWND new = NULL; 1639 IMMThreadData *thread_data; 1640 TRACE("(%p)\n", hwnd); 1641 1642 if (!needs_ime_window(hwnd)) 1643 return FALSE; 1644 1645 thread_data = IMM_GetThreadData(hwnd, 0); 1646 if (!thread_data) 1647 return FALSE; 1648 1649 if (thread_data->disableIME || disable_ime) 1650 { 1651 TRACE("IME for this thread is disabled\n"); 1652 LeaveCriticalSection(&threaddata_cs); 1653 return FALSE; 1654 } 1655 thread_data->windowRefs++; 1656 TRACE("windowRefs=%u, hwndDefault=%p\n", 1657 thread_data->windowRefs, thread_data->hwndDefault); 1658 1659 /* Create default IME window */ 1660 if (thread_data->windowRefs == 1) 1661 { 1662 /* Do not create the window inside of a critical section */ 1663 LeaveCriticalSection(&threaddata_cs); 1664 new = CreateWindowExW( 0, szwIME, szwDefaultIME, 1665 WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS, 1666 0, 0, 1, 1, 0, 0, 0, 0); 1667 /* thread_data is in the current thread so we can assume it's still valid */ 1668 EnterCriticalSection(&threaddata_cs); 1669 /* See if anyone beat us */ 1670 if (thread_data->hwndDefault == NULL) 1671 { 1672 thread_data->hwndDefault = new; 1673 new = NULL; 1674 TRACE("Default is %p\n", thread_data->hwndDefault); 1675 } 1676 } 1677 1678 LeaveCriticalSection(&threaddata_cs); 1679 1680 /* Clean up an unused new window outside of the critical section */ 1681 if (new != NULL) 1682 DestroyWindow(new); 1683 return TRUE; 1684 } 1685 1686 /*********************************************************************** 1687 * __wine_unregister_window (IMM32.@) 1688 */ 1689 void WINAPI __wine_unregister_window(HWND hwnd) 1690 { 1691 HWND to_destroy = 0; 1692 IMMThreadData *thread_data; 1693 TRACE("(%p)\n", hwnd); 1694 1695 thread_data = IMM_GetThreadData(hwnd, 0); 1696 if (!thread_data) return; 1697 1698 thread_data->windowRefs--; 1699 TRACE("windowRefs=%u, hwndDefault=%p\n", 1700 thread_data->windowRefs, thread_data->hwndDefault); 1701 1702 /* Destroy default IME window */ 1703 if (thread_data->windowRefs == 0 && thread_data->hwndDefault) 1704 { 1705 to_destroy = thread_data->hwndDefault; 1706 thread_data->hwndDefault = NULL; 1707 } 1708 LeaveCriticalSection(&threaddata_cs); 1709 1710 if (to_destroy) DestroyWindow( to_destroy ); 1711 } 1712 1713 /*********************************************************************** 1714 * ImmGetDefaultIMEWnd (IMM32.@) 1715 */ 1716 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) 1717 { 1718 HWND ret; 1719 IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0); 1720 if (!thread_data) 1721 return NULL; 1722 ret = thread_data->hwndDefault; 1723 LeaveCriticalSection(&threaddata_cs); 1724 TRACE("Default is %p\n",ret); 1725 return ret; 1726 } 1727 1728 /*********************************************************************** 1729 * ImmGetDescriptionA (IMM32.@) 1730 */ 1731 UINT WINAPI ImmGetDescriptionA( 1732 HKL hKL, LPSTR lpszDescription, UINT uBufLen) 1733 { 1734 WCHAR *buf; 1735 DWORD len; 1736 1737 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen); 1738 1739 /* find out how many characters in the unicode buffer */ 1740 len = ImmGetDescriptionW( hKL, NULL, 0 ); 1741 if (!len) 1742 return 0; 1743 1744 /* allocate a buffer of that size */ 1745 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) ); 1746 if( !buf ) 1747 return 0; 1748 1749 /* fetch the unicode buffer */ 1750 len = ImmGetDescriptionW( hKL, buf, len + 1 ); 1751 1752 /* convert it back to ASCII */ 1753 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1, 1754 lpszDescription, uBufLen, NULL, NULL ); 1755 1756 HeapFree( GetProcessHeap(), 0, buf ); 1757 1758 if (len == 0) 1759 return 0; 1760 1761 return len - 1; 1762 } 1763 1764 /*********************************************************************** 1765 * ImmGetDescriptionW (IMM32.@) 1766 */ 1767 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) 1768 { 1769 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 }; 1770 1771 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen); 1772 1773 if (!hKL) return 0; 1774 if (!uBufLen) return lstrlenW( name ); 1775 lstrcpynW( lpszDescription, name, uBufLen ); 1776 return lstrlenW( lpszDescription ); 1777 } 1778 1779 /*********************************************************************** 1780 * ImmGetGuideLineA (IMM32.@) 1781 */ 1782 DWORD WINAPI ImmGetGuideLineA( 1783 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen) 1784 { 1785 FIXME("(%p, %d, %s, %d): stub\n", 1786 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen 1787 ); 1788 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1789 return 0; 1790 } 1791 1792 /*********************************************************************** 1793 * ImmGetGuideLineW (IMM32.@) 1794 */ 1795 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen) 1796 { 1797 FIXME("(%p, %d, %s, %d): stub\n", 1798 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen 1799 ); 1800 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1801 return 0; 1802 } 1803 1804 /*********************************************************************** 1805 * ImmGetIMEFileNameA (IMM32.@) 1806 */ 1807 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) 1808 { 1809 LPWSTR bufW = NULL; 1810 UINT wBufLen = uBufLen; 1811 UINT rc; 1812 1813 if (uBufLen && lpszFileName) 1814 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR)); 1815 else /* We need this to get the number of byte required */ 1816 { 1817 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR)); 1818 wBufLen = MAX_PATH; 1819 } 1820 1821 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen); 1822 1823 if (rc > 0) 1824 { 1825 if (uBufLen && lpszFileName) 1826 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName, 1827 uBufLen, NULL, NULL); 1828 else /* get the length */ 1829 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, 1830 NULL); 1831 } 1832 1833 HeapFree(GetProcessHeap(),0,bufW); 1834 return rc; 1835 } 1836 1837 /*********************************************************************** 1838 * ImmGetIMEFileNameW (IMM32.@) 1839 */ 1840 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) 1841 { 1842 HKEY hkey; 1843 DWORD length; 1844 DWORD rc; 1845 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8]; 1846 1847 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL ); 1848 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey); 1849 if (rc != ERROR_SUCCESS) 1850 { 1851 SetLastError(rc); 1852 return 0; 1853 } 1854 1855 length = 0; 1856 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length); 1857 1858 if (rc != ERROR_SUCCESS) 1859 { 1860 RegCloseKey(hkey); 1861 SetLastError(rc); 1862 return 0; 1863 } 1864 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName) 1865 { 1866 RegCloseKey(hkey); 1867 if (lpszFileName) 1868 { 1869 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1870 return 0; 1871 } 1872 else 1873 return length / sizeof(WCHAR); 1874 } 1875 1876 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length); 1877 1878 RegCloseKey(hkey); 1879 1880 return length / sizeof(WCHAR); 1881 } 1882 1883 /*********************************************************************** 1884 * ImmGetOpenStatus (IMM32.@) 1885 */ 1886 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) 1887 { 1888 InputContextData *data = get_imc_data(hIMC); 1889 static int i; 1890 1891 if (!data) 1892 return FALSE; 1893 1894 TRACE("(%p): semi-stub\n", hIMC); 1895 1896 if (!i++) 1897 FIXME("(%p): semi-stub\n", hIMC); 1898 1899 return data->IMC.fOpen; 1900 } 1901 1902 /*********************************************************************** 1903 * ImmGetProperty (IMM32.@) 1904 */ 1905 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) 1906 { 1907 DWORD rc = 0; 1908 ImmHkl *kbd; 1909 1910 TRACE("(%p, %d)\n", hKL, fdwIndex); 1911 kbd = IMM_GetImmHkl(hKL); 1912 1913 if (kbd && kbd->hIME) 1914 { 1915 switch (fdwIndex) 1916 { 1917 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break; 1918 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break; 1919 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break; 1920 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break; 1921 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break; 1922 case IGP_GETIMEVERSION: rc = IMEVER_0400; break; 1923 case IGP_UI: rc = 0; break; 1924 default: rc = 0; 1925 } 1926 } 1927 return rc; 1928 } 1929 1930 /*********************************************************************** 1931 * ImmGetRegisterWordStyleA (IMM32.@) 1932 */ 1933 UINT WINAPI ImmGetRegisterWordStyleA( 1934 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf) 1935 { 1936 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1937 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf); 1938 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle) 1939 { 1940 if (!is_kbd_ime_unicode(immHkl)) 1941 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf); 1942 else 1943 { 1944 STYLEBUFW sbw; 1945 UINT rc; 1946 1947 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw); 1948 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1, 1949 lpStyleBuf->szDescription, 32, NULL, NULL); 1950 lpStyleBuf->dwStyle = sbw.dwStyle; 1951 return rc; 1952 } 1953 } 1954 else 1955 return 0; 1956 } 1957 1958 /*********************************************************************** 1959 * ImmGetRegisterWordStyleW (IMM32.@) 1960 */ 1961 UINT WINAPI ImmGetRegisterWordStyleW( 1962 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf) 1963 { 1964 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 1965 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf); 1966 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle) 1967 { 1968 if (is_kbd_ime_unicode(immHkl)) 1969 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf); 1970 else 1971 { 1972 STYLEBUFA sba; 1973 UINT rc; 1974 1975 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba); 1976 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1, 1977 lpStyleBuf->szDescription, 32); 1978 lpStyleBuf->dwStyle = sba.dwStyle; 1979 return rc; 1980 } 1981 } 1982 else 1983 return 0; 1984 } 1985 1986 /*********************************************************************** 1987 * ImmGetStatusWindowPos (IMM32.@) 1988 */ 1989 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1990 { 1991 InputContextData *data = get_imc_data(hIMC); 1992 1993 TRACE("(%p, %p)\n", hIMC, lpptPos); 1994 1995 if (!data || !lpptPos) 1996 return FALSE; 1997 1998 *lpptPos = data->IMC.ptStatusWndPos; 1999 2000 return TRUE; 2001 } 2002 2003 /*********************************************************************** 2004 * ImmGetVirtualKey (IMM32.@) 2005 */ 2006 UINT WINAPI ImmGetVirtualKey(HWND hWnd) 2007 { 2008 OSVERSIONINFOA version; 2009 InputContextData *data = ImmGetContext( hWnd ); 2010 TRACE("%p\n", hWnd); 2011 2012 if ( data ) 2013 return data->lastVK; 2014 2015 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 2016 GetVersionExA( &version ); 2017 switch(version.dwPlatformId) 2018 { 2019 case VER_PLATFORM_WIN32_WINDOWS: 2020 return VK_PROCESSKEY; 2021 case VER_PLATFORM_WIN32_NT: 2022 return 0; 2023 default: 2024 FIXME("%d not supported\n",version.dwPlatformId); 2025 return VK_PROCESSKEY; 2026 } 2027 } 2028 2029 /*********************************************************************** 2030 * ImmInstallIMEA (IMM32.@) 2031 */ 2032 HKL WINAPI ImmInstallIMEA( 2033 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText) 2034 { 2035 LPWSTR lpszwIMEFileName; 2036 LPWSTR lpszwLayoutText; 2037 HKL hkl; 2038 2039 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName), 2040 debugstr_a(lpszLayoutText)); 2041 2042 lpszwIMEFileName = strdupAtoW(lpszIMEFileName); 2043 lpszwLayoutText = strdupAtoW(lpszLayoutText); 2044 2045 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText); 2046 2047 HeapFree(GetProcessHeap(),0,lpszwIMEFileName); 2048 HeapFree(GetProcessHeap(),0,lpszwLayoutText); 2049 return hkl; 2050 } 2051 2052 /*********************************************************************** 2053 * ImmInstallIMEW (IMM32.@) 2054 */ 2055 HKL WINAPI ImmInstallIMEW( 2056 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) 2057 { 2058 INT lcid = GetUserDefaultLCID(); 2059 INT count; 2060 HKL hkl; 2061 DWORD rc; 2062 HKEY hkey; 2063 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8]; 2064 2065 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName), 2066 debugstr_w(lpszLayoutText)); 2067 2068 /* Start with 2. e001 will be blank and so default to the wine internal IME */ 2069 count = 2; 2070 2071 while (count < 0xfff) 2072 { 2073 DWORD disposition = 0; 2074 2075 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count ); 2076 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl); 2077 2078 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition); 2079 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY) 2080 break; 2081 else if (rc == ERROR_SUCCESS) 2082 RegCloseKey(hkey); 2083 2084 count++; 2085 } 2086 2087 if (count == 0xfff) 2088 { 2089 WARN("Unable to find slot to install IME\n"); 2090 return 0; 2091 } 2092 2093 if (rc == ERROR_SUCCESS) 2094 { 2095 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName, 2096 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR)); 2097 if (rc == ERROR_SUCCESS) 2098 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText, 2099 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR)); 2100 RegCloseKey(hkey); 2101 return hkl; 2102 } 2103 else 2104 { 2105 WARN("Unable to set IME registry values\n"); 2106 return 0; 2107 } 2108 } 2109 2110 /*********************************************************************** 2111 * ImmIsIME (IMM32.@) 2112 */ 2113 BOOL WINAPI ImmIsIME(HKL hKL) 2114 { 2115 ImmHkl *ptr; 2116 TRACE("(%p):\n", hKL); 2117 ptr = IMM_GetImmHkl(hKL); 2118 return (ptr && ptr->hIME); 2119 } 2120 2121 /*********************************************************************** 2122 * ImmIsUIMessageA (IMM32.@) 2123 */ 2124 BOOL WINAPI ImmIsUIMessageA( 2125 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) 2126 { 2127 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam); 2128 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 2129 (msg == WM_IME_SETCONTEXT) || 2130 (msg == WM_IME_NOTIFY) || 2131 (msg == WM_IME_COMPOSITIONFULL) || 2132 (msg == WM_IME_SELECT) || 2133 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */)) 2134 { 2135 if (hWndIME) 2136 SendMessageA(hWndIME, msg, wParam, lParam); 2137 2138 return TRUE; 2139 } 2140 return FALSE; 2141 } 2142 2143 /*********************************************************************** 2144 * ImmIsUIMessageW (IMM32.@) 2145 */ 2146 BOOL WINAPI ImmIsUIMessageW( 2147 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) 2148 { 2149 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam); 2150 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 2151 (msg == WM_IME_SETCONTEXT) || 2152 (msg == WM_IME_NOTIFY) || 2153 (msg == WM_IME_COMPOSITIONFULL) || 2154 (msg == WM_IME_SELECT) || 2155 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */)) 2156 { 2157 if (hWndIME) 2158 SendMessageW(hWndIME, msg, wParam, lParam); 2159 2160 return TRUE; 2161 } 2162 return FALSE; 2163 } 2164 2165 /*********************************************************************** 2166 * ImmNotifyIME (IMM32.@) 2167 */ 2168 BOOL WINAPI ImmNotifyIME( 2169 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) 2170 { 2171 InputContextData *data = get_imc_data(hIMC); 2172 2173 TRACE("(%p, %d, %d, %d)\n", 2174 hIMC, dwAction, dwIndex, dwValue); 2175 2176 if (hIMC == NULL) 2177 { 2178 SetLastError(ERROR_SUCCESS); 2179 return FALSE; 2180 } 2181 2182 if (!data || ! data->immKbd->pNotifyIME) 2183 { 2184 return FALSE; 2185 } 2186 2187 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue); 2188 } 2189 2190 /*********************************************************************** 2191 * ImmRegisterWordA (IMM32.@) 2192 */ 2193 BOOL WINAPI ImmRegisterWordA( 2194 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister) 2195 { 2196 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2197 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle, 2198 debugstr_a(lpszRegister)); 2199 if (immHkl->hIME && immHkl->pImeRegisterWord) 2200 { 2201 if (!is_kbd_ime_unicode(immHkl)) 2202 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle, 2203 (LPCWSTR)lpszRegister); 2204 else 2205 { 2206 LPWSTR lpszwReading = strdupAtoW(lpszReading); 2207 LPWSTR lpszwRegister = strdupAtoW(lpszRegister); 2208 BOOL rc; 2209 2210 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister); 2211 HeapFree(GetProcessHeap(),0,lpszwReading); 2212 HeapFree(GetProcessHeap(),0,lpszwRegister); 2213 return rc; 2214 } 2215 } 2216 else 2217 return FALSE; 2218 } 2219 2220 /*********************************************************************** 2221 * ImmRegisterWordW (IMM32.@) 2222 */ 2223 BOOL WINAPI ImmRegisterWordW( 2224 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister) 2225 { 2226 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2227 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle, 2228 debugstr_w(lpszRegister)); 2229 if (immHkl->hIME && immHkl->pImeRegisterWord) 2230 { 2231 if (is_kbd_ime_unicode(immHkl)) 2232 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister); 2233 else 2234 { 2235 LPSTR lpszaReading = strdupWtoA(lpszReading); 2236 LPSTR lpszaRegister = strdupWtoA(lpszRegister); 2237 BOOL rc; 2238 2239 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle, 2240 (LPCWSTR)lpszaRegister); 2241 HeapFree(GetProcessHeap(),0,lpszaReading); 2242 HeapFree(GetProcessHeap(),0,lpszaRegister); 2243 return rc; 2244 } 2245 } 2246 else 2247 return FALSE; 2248 } 2249 2250 /*********************************************************************** 2251 * ImmReleaseContext (IMM32.@) 2252 */ 2253 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) 2254 { 2255 static BOOL shown = FALSE; 2256 2257 if (!shown) { 2258 FIXME("(%p, %p): stub\n", hWnd, hIMC); 2259 shown = TRUE; 2260 } 2261 return TRUE; 2262 } 2263 2264 /*********************************************************************** 2265 * ImmRequestMessageA(IMM32.@) 2266 */ 2267 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam) 2268 { 2269 InputContextData *data = get_imc_data(hIMC); 2270 2271 TRACE("%p %ld %ld\n", hIMC, wParam, wParam); 2272 2273 if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam); 2274 2275 SetLastError(ERROR_INVALID_HANDLE); 2276 return 0; 2277 } 2278 2279 /*********************************************************************** 2280 * ImmRequestMessageW(IMM32.@) 2281 */ 2282 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam) 2283 { 2284 InputContextData *data = get_imc_data(hIMC); 2285 2286 TRACE("%p %ld %ld\n", hIMC, wParam, wParam); 2287 2288 if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam); 2289 2290 SetLastError(ERROR_INVALID_HANDLE); 2291 return 0; 2292 } 2293 2294 /*********************************************************************** 2295 * ImmSetCandidateWindow (IMM32.@) 2296 */ 2297 BOOL WINAPI ImmSetCandidateWindow( 2298 HIMC hIMC, LPCANDIDATEFORM lpCandidate) 2299 { 2300 InputContextData *data = get_imc_data(hIMC); 2301 2302 TRACE("(%p, %p)\n", hIMC, lpCandidate); 2303 2304 if (!data || !lpCandidate) 2305 return FALSE; 2306 2307 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2308 return FALSE; 2309 2310 TRACE("\t%x, %x, %s, %s\n", 2311 lpCandidate->dwIndex, lpCandidate->dwStyle, 2312 wine_dbgstr_point(&lpCandidate->ptCurrentPos), 2313 wine_dbgstr_rect(&lpCandidate->rcArea)); 2314 2315 if (lpCandidate->dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm)) 2316 return FALSE; 2317 2318 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate; 2319 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS); 2320 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex); 2321 2322 return TRUE; 2323 } 2324 2325 /*********************************************************************** 2326 * ImmSetCompositionFontA (IMM32.@) 2327 */ 2328 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 2329 { 2330 InputContextData *data = get_imc_data(hIMC); 2331 TRACE("(%p, %p)\n", hIMC, lplf); 2332 2333 if (!data || !lplf) 2334 { 2335 SetLastError(ERROR_INVALID_HANDLE); 2336 return FALSE; 2337 } 2338 2339 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2340 return FALSE; 2341 2342 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA)); 2343 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName, 2344 LF_FACESIZE); 2345 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT); 2346 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); 2347 2348 return TRUE; 2349 } 2350 2351 /*********************************************************************** 2352 * ImmSetCompositionFontW (IMM32.@) 2353 */ 2354 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 2355 { 2356 InputContextData *data = get_imc_data(hIMC); 2357 TRACE("(%p, %p)\n", hIMC, lplf); 2358 2359 if (!data || !lplf) 2360 { 2361 SetLastError(ERROR_INVALID_HANDLE); 2362 return FALSE; 2363 } 2364 2365 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2366 return FALSE; 2367 2368 data->IMC.lfFont.W = *lplf; 2369 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT); 2370 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); 2371 2372 return TRUE; 2373 } 2374 2375 /*********************************************************************** 2376 * ImmSetCompositionStringA (IMM32.@) 2377 */ 2378 BOOL WINAPI ImmSetCompositionStringA( 2379 HIMC hIMC, DWORD dwIndex, 2380 LPCVOID lpComp, DWORD dwCompLen, 2381 LPCVOID lpRead, DWORD dwReadLen) 2382 { 2383 DWORD comp_len; 2384 DWORD read_len; 2385 WCHAR *CompBuffer = NULL; 2386 WCHAR *ReadBuffer = NULL; 2387 BOOL rc; 2388 InputContextData *data = get_imc_data(hIMC); 2389 2390 TRACE("(%p, %d, %p, %d, %p, %d):\n", 2391 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 2392 2393 if (!data) 2394 return FALSE; 2395 2396 if (!(dwIndex == SCS_SETSTR || 2397 dwIndex == SCS_CHANGEATTR || 2398 dwIndex == SCS_CHANGECLAUSE || 2399 dwIndex == SCS_SETRECONVERTSTRING || 2400 dwIndex == SCS_QUERYRECONVERTSTRING)) 2401 return FALSE; 2402 2403 if (!is_himc_ime_unicode(data)) 2404 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, 2405 dwCompLen, lpRead, dwReadLen); 2406 2407 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0); 2408 if (comp_len) 2409 { 2410 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR)); 2411 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len); 2412 } 2413 2414 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0); 2415 if (read_len) 2416 { 2417 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR)); 2418 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len); 2419 } 2420 2421 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len, 2422 ReadBuffer, read_len); 2423 2424 HeapFree(GetProcessHeap(), 0, CompBuffer); 2425 HeapFree(GetProcessHeap(), 0, ReadBuffer); 2426 2427 return rc; 2428 } 2429 2430 /*********************************************************************** 2431 * ImmSetCompositionStringW (IMM32.@) 2432 */ 2433 BOOL WINAPI ImmSetCompositionStringW( 2434 HIMC hIMC, DWORD dwIndex, 2435 LPCVOID lpComp, DWORD dwCompLen, 2436 LPCVOID lpRead, DWORD dwReadLen) 2437 { 2438 DWORD comp_len; 2439 DWORD read_len; 2440 CHAR *CompBuffer = NULL; 2441 CHAR *ReadBuffer = NULL; 2442 BOOL rc; 2443 InputContextData *data = get_imc_data(hIMC); 2444 2445 TRACE("(%p, %d, %p, %d, %p, %d):\n", 2446 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 2447 2448 if (!data) 2449 return FALSE; 2450 2451 if (!(dwIndex == SCS_SETSTR || 2452 dwIndex == SCS_CHANGEATTR || 2453 dwIndex == SCS_CHANGECLAUSE || 2454 dwIndex == SCS_SETRECONVERTSTRING || 2455 dwIndex == SCS_QUERYRECONVERTSTRING)) 2456 return FALSE; 2457 2458 if (is_himc_ime_unicode(data)) 2459 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, 2460 dwCompLen, lpRead, dwReadLen); 2461 2462 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL, 2463 NULL); 2464 if (comp_len) 2465 { 2466 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len); 2467 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len, 2468 NULL, NULL); 2469 } 2470 2471 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL, 2472 NULL); 2473 if (read_len) 2474 { 2475 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len); 2476 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len, 2477 NULL, NULL); 2478 } 2479 2480 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len, 2481 ReadBuffer, read_len); 2482 2483 HeapFree(GetProcessHeap(), 0, CompBuffer); 2484 HeapFree(GetProcessHeap(), 0, ReadBuffer); 2485 2486 return rc; 2487 } 2488 2489 /*********************************************************************** 2490 * ImmSetCompositionWindow (IMM32.@) 2491 */ 2492 BOOL WINAPI ImmSetCompositionWindow( 2493 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 2494 { 2495 BOOL reshow = FALSE; 2496 InputContextData *data = get_imc_data(hIMC); 2497 2498 TRACE("(%p, %p)\n", hIMC, lpCompForm); 2499 if (lpCompForm) 2500 TRACE("\t%x, %s, %s\n", lpCompForm->dwStyle, 2501 wine_dbgstr_point(&lpCompForm->ptCurrentPos), 2502 wine_dbgstr_rect(&lpCompForm->rcArea)); 2503 2504 if (!data) 2505 { 2506 SetLastError(ERROR_INVALID_HANDLE); 2507 return FALSE; 2508 } 2509 2510 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2511 return FALSE; 2512 2513 data->IMC.cfCompForm = *lpCompForm; 2514 2515 if (IsWindowVisible(data->immKbd->UIWnd)) 2516 { 2517 reshow = TRUE; 2518 ShowWindow(data->immKbd->UIWnd,SW_HIDE); 2519 } 2520 2521 /* FIXME: this is a partial stub */ 2522 2523 if (reshow) 2524 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE); 2525 2526 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0); 2527 return TRUE; 2528 } 2529 2530 /*********************************************************************** 2531 * ImmSetConversionStatus (IMM32.@) 2532 */ 2533 BOOL WINAPI ImmSetConversionStatus( 2534 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) 2535 { 2536 DWORD oldConversion, oldSentence; 2537 InputContextData *data = get_imc_data(hIMC); 2538 2539 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence); 2540 2541 if (!data) 2542 { 2543 SetLastError(ERROR_INVALID_HANDLE); 2544 return FALSE; 2545 } 2546 2547 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2548 return FALSE; 2549 2550 if ( fdwConversion != data->IMC.fdwConversion ) 2551 { 2552 oldConversion = data->IMC.fdwConversion; 2553 data->IMC.fdwConversion = fdwConversion; 2554 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE); 2555 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0); 2556 } 2557 if ( fdwSentence != data->IMC.fdwSentence ) 2558 { 2559 oldSentence = data->IMC.fdwSentence; 2560 data->IMC.fdwSentence = fdwSentence; 2561 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE); 2562 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0); 2563 } 2564 2565 return TRUE; 2566 } 2567 2568 /*********************************************************************** 2569 * ImmSetOpenStatus (IMM32.@) 2570 */ 2571 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) 2572 { 2573 InputContextData *data = get_imc_data(hIMC); 2574 2575 TRACE("%p %d\n", hIMC, fOpen); 2576 2577 if (!data) 2578 { 2579 SetLastError(ERROR_INVALID_HANDLE); 2580 return FALSE; 2581 } 2582 2583 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2584 return FALSE; 2585 2586 if (data->immKbd->UIWnd == NULL) 2587 { 2588 /* create the ime window */ 2589 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW, 2590 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0, 2591 0, data->immKbd->hIME, 0); 2592 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data); 2593 } 2594 else if (fOpen) 2595 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data); 2596 2597 if (!fOpen != !data->IMC.fOpen) 2598 { 2599 data->IMC.fOpen = fOpen; 2600 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS); 2601 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0); 2602 } 2603 2604 return TRUE; 2605 } 2606 2607 /*********************************************************************** 2608 * ImmSetStatusWindowPos (IMM32.@) 2609 */ 2610 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 2611 { 2612 InputContextData *data = get_imc_data(hIMC); 2613 2614 TRACE("(%p, %p)\n", hIMC, lpptPos); 2615 2616 if (!data || !lpptPos) 2617 { 2618 SetLastError(ERROR_INVALID_HANDLE); 2619 return FALSE; 2620 } 2621 2622 if (IMM_IsCrossThreadAccess(NULL, hIMC)) 2623 return FALSE; 2624 2625 TRACE("\t%s\n", wine_dbgstr_point(lpptPos)); 2626 2627 data->IMC.ptStatusWndPos = *lpptPos; 2628 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS); 2629 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0); 2630 2631 return TRUE; 2632 } 2633 2634 /*********************************************************************** 2635 * ImmCreateSoftKeyboard(IMM32.@) 2636 */ 2637 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y) 2638 { 2639 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y); 2640 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2641 return 0; 2642 } 2643 2644 /*********************************************************************** 2645 * ImmDestroySoftKeyboard(IMM32.@) 2646 */ 2647 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd) 2648 { 2649 FIXME("(%p): stub\n", hSoftWnd); 2650 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2651 return FALSE; 2652 } 2653 2654 /*********************************************************************** 2655 * ImmShowSoftKeyboard(IMM32.@) 2656 */ 2657 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow) 2658 { 2659 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow); 2660 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2661 return FALSE; 2662 } 2663 2664 /*********************************************************************** 2665 * ImmSimulateHotKey (IMM32.@) 2666 */ 2667 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID) 2668 { 2669 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID); 2670 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2671 return FALSE; 2672 } 2673 2674 /*********************************************************************** 2675 * ImmUnregisterWordA (IMM32.@) 2676 */ 2677 BOOL WINAPI ImmUnregisterWordA( 2678 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister) 2679 { 2680 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2681 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle, 2682 debugstr_a(lpszUnregister)); 2683 if (immHkl->hIME && immHkl->pImeUnregisterWord) 2684 { 2685 if (!is_kbd_ime_unicode(immHkl)) 2686 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle, 2687 (LPCWSTR)lpszUnregister); 2688 else 2689 { 2690 LPWSTR lpszwReading = strdupAtoW(lpszReading); 2691 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister); 2692 BOOL rc; 2693 2694 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister); 2695 HeapFree(GetProcessHeap(),0,lpszwReading); 2696 HeapFree(GetProcessHeap(),0,lpszwUnregister); 2697 return rc; 2698 } 2699 } 2700 else 2701 return FALSE; 2702 } 2703 2704 /*********************************************************************** 2705 * ImmUnregisterWordW (IMM32.@) 2706 */ 2707 BOOL WINAPI ImmUnregisterWordW( 2708 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister) 2709 { 2710 ImmHkl *immHkl = IMM_GetImmHkl(hKL); 2711 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle, 2712 debugstr_w(lpszUnregister)); 2713 if (immHkl->hIME && immHkl->pImeUnregisterWord) 2714 { 2715 if (is_kbd_ime_unicode(immHkl)) 2716 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister); 2717 else 2718 { 2719 LPSTR lpszaReading = strdupWtoA(lpszReading); 2720 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister); 2721 BOOL rc; 2722 2723 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle, 2724 (LPCWSTR)lpszaUnregister); 2725 HeapFree(GetProcessHeap(),0,lpszaReading); 2726 HeapFree(GetProcessHeap(),0,lpszaUnregister); 2727 return rc; 2728 } 2729 } 2730 else 2731 return FALSE; 2732 } 2733 2734 /*********************************************************************** 2735 * ImmGetImeMenuItemsA (IMM32.@) 2736 */ 2737 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType, 2738 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu, 2739 DWORD dwSize) 2740 { 2741 InputContextData *data = get_imc_data(hIMC); 2742 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, 2743 lpImeParentMenu, lpImeMenu, dwSize); 2744 2745 if (!data) 2746 { 2747 SetLastError(ERROR_INVALID_HANDLE); 2748 return 0; 2749 } 2750 2751 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems) 2752 { 2753 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu)) 2754 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2755 (IMEMENUITEMINFOW*)lpImeParentMenu, 2756 (IMEMENUITEMINFOW*)lpImeMenu, dwSize); 2757 else 2758 { 2759 IMEMENUITEMINFOW lpImeParentMenuW; 2760 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL; 2761 DWORD rc; 2762 2763 if (lpImeParentMenu) 2764 parent = &lpImeParentMenuW; 2765 if (lpImeMenu) 2766 { 2767 int count = dwSize / sizeof(LPIMEMENUITEMINFOA); 2768 dwSize = count * sizeof(IMEMENUITEMINFOW); 2769 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize); 2770 } 2771 else 2772 lpImeMenuW = NULL; 2773 2774 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2775 parent, lpImeMenuW, dwSize); 2776 2777 if (lpImeParentMenu) 2778 { 2779 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA)); 2780 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem; 2781 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString, 2782 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE, 2783 NULL, NULL); 2784 } 2785 if (lpImeMenu && rc) 2786 { 2787 unsigned int i; 2788 for (i = 0; i < rc; i++) 2789 { 2790 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA)); 2791 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem; 2792 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString, 2793 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE, 2794 NULL, NULL); 2795 } 2796 } 2797 HeapFree(GetProcessHeap(),0,lpImeMenuW); 2798 return rc; 2799 } 2800 } 2801 else 2802 return 0; 2803 } 2804 2805 /*********************************************************************** 2806 * ImmGetImeMenuItemsW (IMM32.@) 2807 */ 2808 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType, 2809 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, 2810 DWORD dwSize) 2811 { 2812 InputContextData *data = get_imc_data(hIMC); 2813 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, 2814 lpImeParentMenu, lpImeMenu, dwSize); 2815 2816 if (!data) 2817 { 2818 SetLastError(ERROR_INVALID_HANDLE); 2819 return 0; 2820 } 2821 2822 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems) 2823 { 2824 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu)) 2825 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2826 lpImeParentMenu, lpImeMenu, dwSize); 2827 else 2828 { 2829 IMEMENUITEMINFOA lpImeParentMenuA; 2830 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL; 2831 DWORD rc; 2832 2833 if (lpImeParentMenu) 2834 parent = &lpImeParentMenuA; 2835 if (lpImeMenu) 2836 { 2837 int count = dwSize / sizeof(LPIMEMENUITEMINFOW); 2838 dwSize = count * sizeof(IMEMENUITEMINFOA); 2839 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize); 2840 } 2841 else 2842 lpImeMenuA = NULL; 2843 2844 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, 2845 (IMEMENUITEMINFOW*)parent, 2846 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize); 2847 2848 if (lpImeParentMenu) 2849 { 2850 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA)); 2851 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem; 2852 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString, 2853 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE); 2854 } 2855 if (lpImeMenu && rc) 2856 { 2857 unsigned int i; 2858 for (i = 0; i < rc; i++) 2859 { 2860 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA)); 2861 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem; 2862 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString, 2863 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE); 2864 } 2865 } 2866 HeapFree(GetProcessHeap(),0,lpImeMenuA); 2867 return rc; 2868 } 2869 } 2870 else 2871 return 0; 2872 } 2873 2874 /*********************************************************************** 2875 * ImmLockIMC(IMM32.@) 2876 */ 2877 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) 2878 { 2879 InputContextData *data = get_imc_data(hIMC); 2880 2881 if (!data) 2882 return NULL; 2883 data->dwLock++; 2884 return &data->IMC; 2885 } 2886 2887 /*********************************************************************** 2888 * ImmUnlockIMC(IMM32.@) 2889 */ 2890 BOOL WINAPI ImmUnlockIMC(HIMC hIMC) 2891 { 2892 InputContextData *data = get_imc_data(hIMC); 2893 2894 if (!data) 2895 return FALSE; 2896 if (data->dwLock) 2897 data->dwLock--; 2898 return TRUE; 2899 } 2900 2901 /*********************************************************************** 2902 * ImmGetIMCLockCount(IMM32.@) 2903 */ 2904 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) 2905 { 2906 InputContextData *data = get_imc_data(hIMC); 2907 if (!data) 2908 return 0; 2909 return data->dwLock; 2910 } 2911 2912 /*********************************************************************** 2913 * ImmCreateIMCC(IMM32.@) 2914 */ 2915 HIMCC WINAPI ImmCreateIMCC(DWORD size) 2916 { 2917 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size); 2918 } 2919 2920 /*********************************************************************** 2921 * ImmDestroyIMCC(IMM32.@) 2922 */ 2923 HIMCC WINAPI ImmDestroyIMCC(HIMCC block) 2924 { 2925 return GlobalFree(block); 2926 } 2927 2928 /*********************************************************************** 2929 * ImmLockIMCC(IMM32.@) 2930 */ 2931 LPVOID WINAPI ImmLockIMCC(HIMCC imcc) 2932 { 2933 return GlobalLock(imcc); 2934 } 2935 2936 /*********************************************************************** 2937 * ImmUnlockIMCC(IMM32.@) 2938 */ 2939 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc) 2940 { 2941 return GlobalUnlock(imcc); 2942 } 2943 2944 /*********************************************************************** 2945 * ImmGetIMCCLockCount(IMM32.@) 2946 */ 2947 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc) 2948 { 2949 return GlobalFlags(imcc) & GMEM_LOCKCOUNT; 2950 } 2951 2952 /*********************************************************************** 2953 * ImmReSizeIMCC(IMM32.@) 2954 */ 2955 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size) 2956 { 2957 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE); 2958 } 2959 2960 /*********************************************************************** 2961 * ImmGetIMCCSize(IMM32.@) 2962 */ 2963 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) 2964 { 2965 return GlobalSize(imcc); 2966 } 2967 2968 /*********************************************************************** 2969 * ImmGenerateMessage(IMM32.@) 2970 */ 2971 BOOL WINAPI ImmGenerateMessage(HIMC hIMC) 2972 { 2973 InputContextData *data = get_imc_data(hIMC); 2974 2975 if (!data) 2976 { 2977 SetLastError(ERROR_INVALID_HANDLE); 2978 return FALSE; 2979 } 2980 2981 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf); 2982 if (data->IMC.dwNumMsgBuf > 0) 2983 { 2984 LPTRANSMSG lpTransMsg; 2985 HIMCC hMsgBuf; 2986 DWORD i, dwNumMsgBuf; 2987 2988 /* We are going to detach our hMsgBuff so that if processing messages 2989 generates new messages they go into a new buffer */ 2990 hMsgBuf = data->IMC.hMsgBuf; 2991 dwNumMsgBuf = data->IMC.dwNumMsgBuf; 2992 2993 data->IMC.hMsgBuf = ImmCreateIMCC(0); 2994 data->IMC.dwNumMsgBuf = 0; 2995 2996 lpTransMsg = ImmLockIMCC(hMsgBuf); 2997 for (i = 0; i < dwNumMsgBuf; i++) 2998 ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam); 2999 3000 ImmUnlockIMCC(hMsgBuf); 3001 ImmDestroyIMCC(hMsgBuf); 3002 } 3003 3004 return TRUE; 3005 } 3006 3007 /*********************************************************************** 3008 * ImmTranslateMessage(IMM32.@) 3009 * ( Undocumented, call internally and from user32.dll ) 3010 */ 3011 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData) 3012 { 3013 InputContextData *data; 3014 HIMC imc = ImmGetContext(hwnd); 3015 BYTE state[256]; 3016 UINT scancode; 3017 LPVOID list = 0; 3018 UINT msg_count; 3019 UINT uVirtKey; 3020 static const DWORD list_count = 10; 3021 3022 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData); 3023 3024 if (imc) 3025 data = imc; 3026 else 3027 return FALSE; 3028 3029 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx) 3030 return FALSE; 3031 3032 GetKeyboardState(state); 3033 scancode = lKeyData >> 0x10 & 0xff; 3034 3035 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD)); 3036 ((DWORD*)list)[0] = list_count; 3037 3038 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST) 3039 { 3040 WCHAR chr; 3041 3042 if (!is_himc_ime_unicode(data)) 3043 ToAscii(data->lastVK, scancode, state, &chr, 0); 3044 else 3045 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0)); 3046 uVirtKey = MAKELONG(data->lastVK,chr); 3047 } 3048 else 3049 uVirtKey = data->lastVK; 3050 3051 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc); 3052 TRACE("%i messages generated\n",msg_count); 3053 if (msg_count && msg_count <= list_count) 3054 { 3055 UINT i; 3056 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD)); 3057 3058 for (i = 0; i < msg_count; i++) 3059 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam); 3060 } 3061 else if (msg_count > list_count) 3062 ImmGenerateMessage(imc); 3063 3064 HeapFree(GetProcessHeap(),0,list); 3065 3066 data->lastVK = VK_PROCESSKEY; 3067 3068 return (msg_count > 0); 3069 } 3070 3071 /*********************************************************************** 3072 * ImmProcessKey(IMM32.@) 3073 * ( Undocumented, called from user32.dll ) 3074 */ 3075 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown) 3076 { 3077 InputContextData *data; 3078 HIMC imc = ImmGetContext(hwnd); 3079 BYTE state[256]; 3080 3081 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown); 3082 3083 if (imc) 3084 data = imc; 3085 else 3086 return FALSE; 3087 3088 /* Make sure we are inputting to the correct keyboard */ 3089 if (data->immKbd->hkl != hKL) 3090 { 3091 ImmHkl *new_hkl = IMM_GetImmHkl(hKL); 3092 if (new_hkl) 3093 { 3094 data->immKbd->pImeSelect(imc, FALSE); 3095 data->immKbd->uSelected--; 3096 data->immKbd = new_hkl; 3097 data->immKbd->pImeSelect(imc, TRUE); 3098 data->immKbd->uSelected++; 3099 } 3100 else 3101 return FALSE; 3102 } 3103 3104 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey) 3105 return FALSE; 3106 3107 GetKeyboardState(state); 3108 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state)) 3109 { 3110 data->lastVK = vKey; 3111 return TRUE; 3112 } 3113 3114 data->lastVK = VK_PROCESSKEY; 3115 return FALSE; 3116 } 3117 3118 /*********************************************************************** 3119 * ImmDisableTextFrameService(IMM32.@) 3120 */ 3121 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread) 3122 { 3123 FIXME("Stub\n"); 3124 return FALSE; 3125 } 3126 3127 /*********************************************************************** 3128 * ImmEnumInputContext(IMM32.@) 3129 */ 3130 3131 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam) 3132 { 3133 FIXME("Stub\n"); 3134 return FALSE; 3135 } 3136 3137 /*********************************************************************** 3138 * ImmGetHotKey(IMM32.@) 3139 */ 3140 3141 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl) 3142 { 3143 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl); 3144 return FALSE; 3145 } 3146 3147 /*********************************************************************** 3148 * ImmDisableLegacyIME(IMM32.@) 3149 */ 3150 BOOL WINAPI ImmDisableLegacyIME(void) 3151 { 3152 FIXME("stub\n"); 3153 return TRUE; 3154 } 3155