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