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