2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IME manipulation of IMM32
5 * COPYRIGHT: Copyright 1998 Patrik Stridvall
6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * Copyright 2017 James Tabor <james.tabor@reactos.org>
8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
9 * Copyright 2020-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
14 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
16 RTL_CRITICAL_SECTION gcsImeDpi
; // Win: gcsImeDpi
17 PIMEDPI gpImeDpiList
= NULL
; // Win: gpImeDpi
20 PIMEDPI APIENTRY
Imm32FindImeDpi(HKL hKL
)
24 RtlEnterCriticalSection(&gcsImeDpi
);
25 for (pImeDpi
= gpImeDpiList
; pImeDpi
!= NULL
; pImeDpi
= pImeDpi
->pNext
)
27 if (pImeDpi
->hKL
== hKL
)
30 RtlLeaveCriticalSection(&gcsImeDpi
);
36 VOID APIENTRY
Imm32FreeIME(PIMEDPI pImeDpi
, BOOL bDestroy
)
38 if (pImeDpi
->hInst
== NULL
)
41 pImeDpi
->ImeDestroy(0);
42 FreeLibrary(pImeDpi
->hInst
);
43 pImeDpi
->hInst
= NULL
;
47 BOOL APIENTRY
Imm32InquireIme(PIMEDPI pImeDpi
)
51 DWORD dwSysInfoFlags
= 0;
52 LPIMEINFO pImeInfo
= &pImeDpi
->ImeInfo
;
54 if (NtUserGetThreadState(THREADSTATE_ISWINLOGON2
))
55 dwSysInfoFlags
|= IME_SYSINFO_WINLOGON
;
57 if (IS_IME_HKL(pImeDpi
->hKL
))
59 if (!pImeDpi
->ImeInquire(pImeInfo
, szUIClass
, dwSysInfoFlags
))
62 else if (Imm32IsCiceroMode() && pImeDpi
->CtfImeInquireExW
)
64 if (!pImeDpi
->CtfImeInquireExW(pImeInfo
, szUIClass
, dwSysInfoFlags
, pImeDpi
->hKL
))
72 szUIClass
[_countof(szUIClass
) - 1] = 0;
74 if (pImeInfo
->dwPrivateDataSize
== 0)
75 pImeInfo
->dwPrivateDataSize
= sizeof(DWORD
);
77 #define VALID_IME_PROP (IME_PROP_AT_CARET | \
78 IME_PROP_SPECIAL_UI | \
79 IME_PROP_CANDLIST_START_FROM_1 | \
81 IME_PROP_COMPLETE_ON_UNSELECT | \
82 IME_PROP_END_UNLOAD | \
83 IME_PROP_KBD_CHAR_FIRST | \
84 IME_PROP_IGNORE_UPKEYS | \
85 IME_PROP_NEED_ALTKEY | \
86 IME_PROP_NO_KEYS_ON_CLOSE | \
87 IME_PROP_ACCEPT_WIDE_VKEY)
88 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
90 IME_CMODE_KATAKANA | \
91 IME_CMODE_LANGUAGE | \
92 IME_CMODE_FULLSHAPE | \
94 IME_CMODE_CHARCODE | \
95 IME_CMODE_HANJACONVERT | \
97 IME_CMODE_NOCONVERSION | \
101 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \
102 IME_SMODE_PLAURALCLAUSE | \
103 IME_SMODE_SINGLECONVERT | \
104 IME_SMODE_AUTOMATIC | \
105 IME_SMODE_PHRASEPREDICT | \
106 IME_SMODE_CONVERSATION)
107 #define VALID_UI_CAPS (UI_CAP_2700 | \
111 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
113 SCS_CAP_SETRECONVERTSTRING)
114 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
116 if (pImeInfo
->fdwProperty
& ~VALID_IME_PROP
)
118 if (pImeInfo
->fdwConversionCaps
& ~VALID_CMODE_CAPS
)
120 if (pImeInfo
->fdwSentenceCaps
& ~VALID_SMODE_CAPS
)
122 if (pImeInfo
->fdwUICaps
& ~VALID_UI_CAPS
)
124 if (pImeInfo
->fdwSCSCaps
& ~VALID_SCS_CAPS
)
126 if (pImeInfo
->fdwSelectCaps
& ~VALID_SELECT_CAPS
)
129 #undef VALID_IME_PROP
130 #undef VALID_CMODE_CAPS
131 #undef VALID_SMODE_CAPS
133 #undef VALID_SCS_CAPS
134 #undef VALID_SELECT_CAPS
136 if (pImeInfo
->fdwProperty
& IME_PROP_UNICODE
)
138 StringCchCopyW(pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
), szUIClass
);
142 if (pImeDpi
->uCodePage
!= GetACP() && pImeDpi
->uCodePage
)
145 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, (LPSTR
)szUIClass
, -1,
146 pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
));
149 return GetClassInfoW(pImeDpi
->hInst
, pImeDpi
->szUIClass
, &wcW
);
153 BOOL APIENTRY
Imm32LoadIME(PIMEINFOEX pImeInfoEx
, PIMEDPI pImeDpi
)
155 WCHAR szPath
[MAX_PATH
];
160 if (!Imm32GetSystemLibraryPath(szPath
, _countof(szPath
), pImeInfoEx
->wszImeFile
))
163 hIME
= GetModuleHandleW(szPath
);
166 hIME
= LoadLibraryW(szPath
);
169 ERR("Imm32LoadIME: LoadLibraryW(%S) failed\n", szPath
);
173 pImeDpi
->hInst
= hIME
;
175 #define DEFINE_IME_ENTRY(type, name, params, optional) \
177 fn = GetProcAddress(hIME, #name); \
178 if (fn) pImeDpi->name = (FN_##name)fn; \
179 else if (!(optional)) { \
180 ERR("'%s' not found in the IME module '%s'.\n", #name, debugstr_w(szPath)); \
184 #include "imetable.h"
185 #undef DEFINE_IME_ENTRY
187 if (Imm32InquireIme(pImeDpi
))
193 ERR("Imm32InquireIme failed\n");
196 FreeLibrary(pImeDpi
->hInst
);
197 pImeDpi
->hInst
= NULL
;
200 if (pImeInfoEx
->fLoadFlag
== 0)
204 C_ASSERT(sizeof(pImeInfoEx
->wszUIClass
) == sizeof(pImeDpi
->szUIClass
));
205 pImeInfoEx
->ImeInfo
= pImeDpi
->ImeInfo
;
206 RtlCopyMemory(pImeInfoEx
->wszUIClass
, pImeDpi
->szUIClass
,
207 sizeof(pImeInfoEx
->wszUIClass
));
208 pImeInfoEx
->fLoadFlag
= 2;
212 pImeInfoEx
->fLoadFlag
= 1;
215 NtUserSetImeInfoEx(pImeInfoEx
);
222 PIMEDPI APIENTRY
Ime32LoadImeDpi(HKL hKL
, BOOL bLock
)
226 PIMEDPI pImeDpiNew
, pImeDpiFound
;
230 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
) ||
231 ImeInfoEx
.fLoadFlag
== 1)
236 pImeDpiNew
= ImmLocalAlloc(HEAP_ZERO_MEMORY
, sizeof(IMEDPI
));
237 if (pImeDpiNew
== NULL
)
240 pImeDpiNew
->hKL
= hKL
;
243 if (TranslateCharsetInfo((LPDWORD
)(DWORD_PTR
)lcid
, &ci
, TCI_SRCLOCALE
))
244 uCodePage
= ci
.ciACP
;
247 pImeDpiNew
->uCodePage
= uCodePage
;
249 if (!Imm32LoadIME(&ImeInfoEx
, pImeDpiNew
))
251 ImmLocalFree(pImeDpiNew
);
255 RtlEnterCriticalSection(&gcsImeDpi
);
257 pImeDpiFound
= Imm32FindImeDpi(hKL
);
261 pImeDpiFound
->dwFlags
&= ~IMEDPI_FLAG_LOCKED
;
263 RtlLeaveCriticalSection(&gcsImeDpi
);
264 Imm32FreeIME(pImeDpiNew
, FALSE
);
265 ImmLocalFree(pImeDpiNew
);
272 pImeDpiNew
->dwFlags
|= IMEDPI_FLAG_LOCKED
;
273 pImeDpiNew
->cLockObj
= 1;
276 pImeDpiNew
->pNext
= gpImeDpiList
;
277 gpImeDpiList
= pImeDpiNew
;
279 RtlLeaveCriticalSection(&gcsImeDpi
);
284 // Win: FindOrLoadImeDpi
285 PIMEDPI APIENTRY
Imm32FindOrLoadImeDpi(HKL hKL
)
289 if (!IS_IME_HKL(hKL
) && (!Imm32IsCiceroMode() || Imm32Is16BitMode()))
292 pImeDpi
= ImmLockImeDpi(hKL
);
294 pImeDpi
= Ime32LoadImeDpi(hKL
, TRUE
);
298 static LRESULT APIENTRY
299 ImeDpi_Escape(PIMEDPI pImeDpi
, HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
, HKL hKL
)
302 return pImeDpi
->ImeEscape(hIMC
, uSubFunc
, lpData
);
304 if (Imm32IsCiceroMode() && pImeDpi
->CtfImeEscapeEx
)
305 return pImeDpi
->CtfImeEscapeEx(hIMC
, uSubFunc
, lpData
, hKL
);
311 BOOL APIENTRY
Imm32ReleaseIME(HKL hKL
)
314 PIMEDPI pImeDpi0
, pImeDpi1
;
316 RtlEnterCriticalSection(&gcsImeDpi
);
318 for (pImeDpi0
= gpImeDpiList
; pImeDpi0
; pImeDpi0
= pImeDpi0
->pNext
)
320 if (pImeDpi0
->hKL
== hKL
)
327 if (pImeDpi0
->cLockObj
)
329 pImeDpi0
->dwFlags
|= IMEDPI_FLAG_UNKNOWN
;
334 if (gpImeDpiList
== pImeDpi0
)
336 gpImeDpiList
= pImeDpi0
->pNext
;
338 else if (gpImeDpiList
)
340 for (pImeDpi1
= gpImeDpiList
; pImeDpi1
; pImeDpi1
= pImeDpi1
->pNext
)
342 if (pImeDpi1
->pNext
== pImeDpi0
)
344 pImeDpi1
->pNext
= pImeDpi0
->pNext
;
350 Imm32FreeIME(pImeDpi0
, TRUE
);
351 ImmLocalFree(pImeDpi0
);
354 RtlLeaveCriticalSection(&gcsImeDpi
);
358 // We will transport the IME menu items by using a flat memory block via
359 // a file mapping object beyond the boundary of a process.
361 #define MAX_IMEMENU_BITMAP_BYTES 0xF00
363 typedef struct tagIMEMENUITEM
365 IMEMENUITEMINFOW Info
;
366 BYTE abChecked
[MAX_IMEMENU_BITMAP_BYTES
];
367 BYTE abUnchecked
[MAX_IMEMENU_BITMAP_BYTES
];
368 BYTE abItem
[MAX_IMEMENU_BITMAP_BYTES
];
369 } IMEMENUITEM
, *PIMEMENUITEM
;
371 typedef struct tagIMEMENU
377 IMEMENUITEMINFOW Parent
;
378 IMEMENUITEM Items
[ANYSIZE_ARRAY
];
379 } IMEMENU
, *PIMEMENU
;
381 /***********************************************************************
382 * ImmPutImeMenuItemsIntoMappedFile (IMM32.@)
384 * Called from user32.dll to transport the IME menu items by using a
385 * file mapping object. This function is provided for WM_IME_SYSTEM:IMS_GETIMEMENU
388 LRESULT WINAPI
ImmPutImeMenuItemsIntoMappedFile(HIMC hIMC
)
393 LPIMEMENUITEMINFOW pParent
= NULL
, pItems
= NULL
;
394 DWORD i
, cItems
, cbItems
= 0;
396 hMapping
= OpenFileMappingW(FILE_MAP_ALL_ACCESS
, FALSE
, L
"ImmMenuInfo");
397 pView
= MapViewOfFile(hMapping
, FILE_MAP_ALL_ACCESS
, 0, 0, 0);
398 if (!pView
|| pView
->dwVersion
!= 1)
400 ERR("hMapping %p, pView %p\n", hMapping
, pView
);
404 if (pView
->Parent
.cbSize
> 0)
405 pParent
= &pView
->Parent
;
407 if (pView
->dwItemCount
> 0)
409 cbItems
= pView
->dwItemCount
* sizeof(IMEMENUITEMINFOW
);
410 pItems
= ImmLocalAlloc(HEAP_ZERO_MEMORY
, cbItems
);
418 cItems
= ImmGetImeMenuItemsW(hIMC
, pView
->dwFlags
, pView
->dwType
, pParent
, pItems
, cbItems
);
419 pView
->dwItemCount
= cItems
;
425 for (i
= 0; i
< cItems
; ++i
)
427 pView
->Items
[i
].Info
= pItems
[i
];
429 // store bitmaps to bytes
430 if (pItems
[i
].hbmpChecked
)
432 Imm32StoreBitmapToBytes(pItems
[i
].hbmpChecked
, pView
->Items
[i
].abChecked
,
433 MAX_IMEMENU_BITMAP_BYTES
);
434 DeleteObject(pItems
[i
].hbmpChecked
);
436 if (pItems
[i
].hbmpUnchecked
)
438 Imm32StoreBitmapToBytes(pItems
[i
].hbmpUnchecked
, pView
->Items
[i
].abUnchecked
,
439 MAX_IMEMENU_BITMAP_BYTES
);
440 DeleteObject(pItems
[i
].hbmpUnchecked
);
442 if (pItems
[i
].hbmpItem
)
444 Imm32StoreBitmapToBytes(pItems
[i
].hbmpItem
, pView
->Items
[i
].abItem
,
445 MAX_IMEMENU_BITMAP_BYTES
);
446 DeleteObject(pItems
[i
].hbmpItem
);
455 ImmLocalFree(pItems
);
457 UnmapViewOfFile(pView
);
459 CloseHandle(hMapping
);
463 // Win: ImmGetImeMenuItemsInterProcess
465 Imm32GetImeMenuItemWInterProcess(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
, LPVOID lpImeParentMenu
,
466 LPVOID lpImeMenu
, DWORD dwSize
)
470 DWORD i
, cbView
, dwItemCount
, ret
= 0;
472 PIMEMENUITEM pGotItem
;
473 LPIMEMENUITEMINFOW pSetInfo
;
475 hImeWnd
= (HWND
)NtUserQueryInputContext(hIMC
, QIC_DEFAULTWINDOWIME
);
476 if (!hImeWnd
|| !IsWindow(hImeWnd
))
478 ERR("hImeWnd %p\n", hImeWnd
);
482 dwItemCount
= (lpImeMenu
? (dwSize
/ sizeof(IMEMENUITEMINFOW
)) : 0);
483 cbView
= sizeof(IMEMENU
) + ((size_t)dwItemCount
- 1) * sizeof(IMEMENUITEM
);
485 RtlEnterCriticalSection(&gcsImeDpi
);
487 // create a file mapping
488 hMapping
= CreateFileMappingW(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
,
489 0, cbView
, L
"ImmMenuInfo");
490 pView
= MapViewOfFile(hMapping
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
493 ERR("hMapping %p, pView %p\n", hMapping
, pView
);
497 ZeroMemory(pView
, cbView
);
498 pView
->dwVersion
= 1;
499 pView
->dwFlags
= dwFlags
;
500 pView
->dwType
= dwType
;
501 pView
->dwItemCount
= dwItemCount
;
504 pView
->Parent
= *(LPIMEMENUITEMINFOW
)lpImeParentMenu
;
505 pView
->Parent
.cbSize
= sizeof(IMEMENUITEMINFOW
);
508 if (!SendMessageW(hImeWnd
, WM_IME_SYSTEM
, IMS_GETIMEMENU
, (LPARAM
)hIMC
))
511 ret
= pView
->dwItemCount
;
516 for (i
= 0; i
< ret
; ++i
)
518 pGotItem
= &(pView
->Items
[i
]);
519 pSetInfo
= &((LPIMEMENUITEMINFOW
)lpImeMenu
)[i
];
521 *pSetInfo
= pGotItem
->Info
;
523 // load bitmaps from bytes
524 if (pSetInfo
->hbmpChecked
)
526 pSetInfo
->hbmpChecked
= Imm32LoadBitmapFromBytes(pGotItem
->abChecked
);
528 if (pSetInfo
->hbmpUnchecked
)
530 pSetInfo
->hbmpUnchecked
= Imm32LoadBitmapFromBytes(pGotItem
->abUnchecked
);
532 if (pSetInfo
->hbmpItem
)
534 pSetInfo
->hbmpItem
= Imm32LoadBitmapFromBytes(pGotItem
->abItem
);
539 RtlLeaveCriticalSection(&gcsImeDpi
);
541 UnmapViewOfFile(pView
);
543 CloseHandle(hMapping
);
547 // Win: ImmGetImeMenuItemsWorker
549 ImmGetImeMenuItemsAW(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
, LPVOID lpImeParentMenu
,
550 LPVOID lpImeMenu
, DWORD dwSize
, BOOL bTargetIsAnsi
)
552 DWORD ret
= 0, cbTotal
, dwProcessId
, dwThreadId
, iItem
;
554 PIMEDPI pImeDpi
= NULL
;
555 IMEMENUITEMINFOA ParentA
;
556 IMEMENUITEMINFOW ParentW
;
557 LPIMEMENUITEMINFOA pItemA
;
558 LPIMEMENUITEMINFOW pItemW
;
559 LPVOID pNewItems
= NULL
, pNewParent
= NULL
;
566 dwProcessId
= (DWORD
)NtUserQueryInputContext(hIMC
, QIC_INPUTPROCESSID
);
567 if (dwProcessId
== 0)
570 if (dwProcessId
!= GetCurrentProcessId())
574 return Imm32GetImeMenuItemWInterProcess(hIMC
, dwFlags
, dwType
, lpImeParentMenu
,
578 pIC
= ImmLockIMC(hIMC
);
582 dwThreadId
= (DWORD
)NtUserQueryInputContext(hIMC
, QIC_INPUTTHREADID
);
589 hKL
= GetKeyboardLayout(dwThreadId
);
590 pImeDpi
= ImmLockImeDpi(hKL
);
597 if (pImeDpi
->ImeGetImeMenuItems
== NULL
)
600 bImcIsAnsi
= Imm32IsImcAnsi(hIMC
);
602 if (bImcIsAnsi
!= bTargetIsAnsi
)
607 pNewParent
= &ParentW
;
611 cbTotal
= ((dwSize
/ sizeof(IMEMENUITEMINFOA
)) * sizeof(IMEMENUITEMINFOW
));
612 pNewItems
= ImmLocalAlloc(0, cbTotal
);
620 pNewParent
= &ParentA
;
624 cbTotal
= ((dwSize
/ sizeof(IMEMENUITEMINFOW
)) * sizeof(IMEMENUITEMINFOA
));
625 pNewItems
= ImmLocalAlloc(0, cbTotal
);
633 pNewItems
= lpImeMenu
;
634 pNewParent
= lpImeParentMenu
;
637 ret
= pImeDpi
->ImeGetImeMenuItems(hIMC
, dwFlags
, dwType
, pNewParent
, pNewItems
, dwSize
);
638 if (!ret
|| !lpImeMenu
)
641 if (bImcIsAnsi
!= bTargetIsAnsi
)
646 Imm32ImeMenuWideToAnsi(pNewParent
, lpImeParentMenu
, CP_ACP
);
650 for (iItem
= 0; iItem
< ret
; ++iItem
, ++pItemW
, ++pItemA
)
652 if (!Imm32ImeMenuWideToAnsi(pItemW
, pItemA
, CP_ACP
))
662 Imm32ImeMenuAnsiToWide(pNewParent
, lpImeParentMenu
, pImeDpi
->uCodePage
, TRUE
);
666 for (iItem
= 0; iItem
< dwSize
; ++iItem
, ++pItemA
, ++pItemW
)
668 if (!Imm32ImeMenuAnsiToWide(pItemA
, pItemW
, pImeDpi
->uCodePage
, TRUE
))
678 if (pNewItems
!= lpImeMenu
)
679 ImmLocalFree(pNewItems
);
680 ImmUnlockImeDpi(pImeDpi
);
685 /***********************************************************************
686 * ImmInstallIMEA (IMM32.@)
688 HKL WINAPI
ImmInstallIMEA(LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
691 LPWSTR pszFileNameW
= NULL
, pszLayoutTextW
= NULL
;
693 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName
), debugstr_a(lpszLayoutText
));
695 pszFileNameW
= Imm32WideFromAnsi(lpszIMEFileName
);
699 pszLayoutTextW
= Imm32WideFromAnsi(lpszLayoutText
);
703 hKL
= ImmInstallIMEW(pszFileNameW
, pszLayoutTextW
);
706 ImmLocalFree(pszFileNameW
);
707 ImmLocalFree(pszLayoutTextW
);
711 /***********************************************************************
712 * ImmInstallIMEW (IMM32.@)
714 HKL WINAPI
ImmInstallIMEW(LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
716 WCHAR szImeFileName
[MAX_PATH
], szImeDestPath
[MAX_PATH
], szImeKey
[20];
719 UINT iLayout
, cLayouts
;
722 PREG_IME pLayouts
= NULL
;
724 TRACE("(%s, %s)\n", debugstr_w(lpszIMEFileName
), debugstr_w(lpszLayoutText
));
726 GetFullPathNameW(lpszIMEFileName
, _countof(szImeFileName
), szImeFileName
, &pchFilePart
);
727 CharUpperW(szImeFileName
);
731 /* Load the IME version info */
732 InfoEx
.hkl
= hNewKL
= NULL
;
733 StringCchCopyW(InfoEx
.wszImeFile
, _countof(InfoEx
.wszImeFile
), pchFilePart
);
734 if (Imm32LoadImeVerInfo(&InfoEx
) && InfoEx
.hkl
)
735 wLangID
= LOWORD(InfoEx
.hkl
);
739 /* Get the IME layouts from registry */
740 cLayouts
= Imm32GetImeLayout(NULL
, 0);
743 pLayouts
= ImmLocalAlloc(0, cLayouts
* sizeof(REG_IME
));
744 if (!pLayouts
|| !Imm32GetImeLayout(pLayouts
, cLayouts
))
746 ImmLocalFree(pLayouts
);
750 for (iLayout
= 0; iLayout
< cLayouts
; ++iLayout
)
752 if (lstrcmpiW(pLayouts
[iLayout
].szFileName
, pchFilePart
) == 0)
754 if (wLangID
!= LOWORD(pLayouts
[iLayout
].hKL
))
755 goto Quit
; /* The language is different */
757 hNewKL
= pLayouts
[iLayout
].hKL
; /* Found */
763 /* If the IME for the specified filename is valid, then unload it now */
764 if (ImmGetImeInfoEx(&InfoEx
, ImeInfoExImeFileName
, pchFilePart
) &&
765 !UnloadKeyboardLayout(InfoEx
.hkl
))
771 Imm32GetSystemLibraryPath(szImeDestPath
, _countof(szImeDestPath
), pchFilePart
);
772 CharUpperW(szImeDestPath
);
774 /* If the source and the destination pathnames were different, then copy the IME file */
775 if (lstrcmpiW(szImeFileName
, szImeDestPath
) != 0 &&
776 !Imm32CopyImeFile(szImeFileName
, szImeDestPath
))
783 hNewKL
= Imm32AssignNewLayout(cLayouts
, pLayouts
, wLangID
);
787 /* Write the IME layout to registry */
788 if (Imm32WriteImeLayout(hNewKL
, pchFilePart
, lpszLayoutText
))
790 /* Load the keyboard layout */
791 Imm32UIntToStr((DWORD
)(DWORD_PTR
)hNewKL
, 16, szImeKey
, _countof(szImeKey
));
792 hNewKL
= LoadKeyboardLayoutW(szImeKey
, KLF_REPLACELANG
);
801 ImmLocalFree(pLayouts
);
805 /***********************************************************************
808 BOOL WINAPI
ImmIsIME(HKL hKL
)
811 TRACE("(%p)\n", hKL
);
812 return !!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayoutTFS
, &hKL
);
815 /***********************************************************************
816 * ImmGetDefaultIMEWnd (IMM32.@)
818 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
824 return (HWND
)NtUserGetThreadState(THREADSTATE_DEFAULTIMEWINDOW
);
826 return (HWND
)NtUserQueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_IME
);
829 /***********************************************************************
830 * ImmNotifyIME (IMM32.@)
832 BOOL WINAPI
ImmNotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
838 TRACE("(%p, %lu, %lu, %lu)\n", hIMC
, dwAction
, dwIndex
, dwValue
);
840 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
843 hKL
= GetKeyboardLayout(0);
844 pImeDpi
= ImmLockImeDpi(hKL
);
848 ret
= pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
849 ImmUnlockImeDpi(pImeDpi
);
853 /***********************************************************************
854 * ImmDisableLegacyIME(IMM32.@)
856 BOOL WINAPI
ImmDisableLegacyIME(void)
862 /***********************************************************************
863 * ImmGetImeInfoEx (IMM32.@)
866 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
, IMEINFOEXCLASS SearchType
, PVOID pvSearchKey
)
869 if (SearchType
== ImeInfoExKeyboardLayout
|| SearchType
== ImeInfoExKeyboardLayoutTFS
)
871 hKL
= *(HKL
*)pvSearchKey
;
872 pImeInfoEx
->hkl
= hKL
;
874 if (SearchType
== ImeInfoExKeyboardLayoutTFS
)
876 if (!IS_IME_HKL(hKL
))
878 if (!CtfImmIsTextFrameServiceDisabled() ||
879 !Imm32IsCiceroMode() || Imm32Is16BitMode())
885 SearchType
= ImeInfoExKeyboardLayout
;
889 if (!IS_IME_HKL(hKL
))
893 else if (SearchType
== ImeInfoExImeFileName
)
895 StringCchCopyW(pImeInfoEx
->wszImeFile
, _countof(pImeInfoEx
->wszImeFile
),
903 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);
906 /***********************************************************************
907 * ImmLockImeDpi (IMM32.@)
909 PIMEDPI WINAPI
ImmLockImeDpi(HKL hKL
)
911 PIMEDPI pImeDpi
= NULL
;
913 TRACE("(%p)\n", hKL
);
915 RtlEnterCriticalSection(&gcsImeDpi
);
918 for (pImeDpi
= gpImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
920 if (pImeDpi
->hKL
== hKL
) /* found */
922 /* lock if possible */
923 if (pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
)
926 ++(pImeDpi
->cLockObj
);
931 RtlLeaveCriticalSection(&gcsImeDpi
);
935 /***********************************************************************
936 * ImmUnlockImeDpi (IMM32.@)
938 VOID WINAPI
ImmUnlockImeDpi(PIMEDPI pImeDpi
)
942 TRACE("(%p)\n", pImeDpi
);
947 RtlEnterCriticalSection(&gcsImeDpi
);
950 --(pImeDpi
->cLockObj
);
951 if (pImeDpi
->cLockObj
!= 0)
953 RtlLeaveCriticalSection(&gcsImeDpi
);
957 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
) == 0)
959 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_LOCKED
) == 0 ||
960 (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_END_UNLOAD
) == 0)
962 RtlLeaveCriticalSection(&gcsImeDpi
);
967 /* Remove from list */
968 for (ppEntry
= &gpImeDpiList
; *ppEntry
; ppEntry
= &((*ppEntry
)->pNext
))
970 if (*ppEntry
== pImeDpi
) /* found */
972 *ppEntry
= pImeDpi
->pNext
;
977 Imm32FreeIME(pImeDpi
, TRUE
);
978 ImmLocalFree(pImeDpi
);
980 RtlLeaveCriticalSection(&gcsImeDpi
);
983 /***********************************************************************
984 * ImmLoadIME (IMM32.@)
986 BOOL WINAPI
ImmLoadIME(HKL hKL
)
990 if (!IS_IME_HKL(hKL
) && (!Imm32IsCiceroMode() || Imm32Is16BitMode()))
993 pImeDpi
= Imm32FindImeDpi(hKL
);
995 pImeDpi
= Ime32LoadImeDpi(hKL
, FALSE
);
996 return (pImeDpi
!= NULL
);
999 /***********************************************************************
1000 * ImmDisableIME (IMM32.@)
1002 BOOL WINAPI
ImmDisableIME(DWORD dwThreadId
)
1004 return NtUserDisableThreadIme(dwThreadId
);
1007 /***********************************************************************
1008 * ImmGetDescriptionA (IMM32.@)
1010 UINT WINAPI
ImmGetDescriptionA(HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
1015 TRACE("(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
1017 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
1020 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
1021 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
1022 lpszDescription
, uBufLen
, NULL
, NULL
);
1024 lpszDescription
[cch
] = 0;
1028 /***********************************************************************
1029 * ImmGetDescriptionW (IMM32.@)
1031 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
1036 TRACE("(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
1038 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
1042 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
1044 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
1048 /***********************************************************************
1049 * ImmGetIMEFileNameA (IMM32.@)
1051 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
1057 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
1059 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
1062 lpszFileName
[0] = 0;
1066 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
1068 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeFile
, (INT
)cch
,
1069 lpszFileName
, uBufLen
, NULL
, &bDefUsed
);
1073 if (cch
> uBufLen
- 1)
1076 lpszFileName
[cch
] = 0;
1080 /***********************************************************************
1081 * ImmGetIMEFileNameW (IMM32.@)
1083 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
1088 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
1090 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
1093 lpszFileName
[0] = 0;
1097 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
1101 StringCchCopyNW(lpszFileName
, uBufLen
, info
.wszImeFile
, cch
);
1103 if (cch
> uBufLen
- 1)
1106 lpszFileName
[cch
] = 0;
1110 /***********************************************************************
1111 * ImmGetProperty (IMM32.@)
1113 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
1115 IMEINFOEX ImeInfoEx
;
1118 PIMEDPI pImeDpi
= NULL
;
1120 TRACE("(%p, %lu)\n", hKL
, fdwIndex
);
1122 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
))
1125 if (fdwIndex
== IGP_GETIMEVERSION
)
1126 return ImeInfoEx
.dwImeWinVersion
;
1128 if (ImeInfoEx
.fLoadFlag
!= 2)
1130 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1131 if (pImeDpi
== NULL
)
1134 pImeInfo
= &pImeDpi
->ImeInfo
;
1138 pImeInfo
= &ImeInfoEx
.ImeInfo
;
1143 case IGP_PROPERTY
: dwValue
= pImeInfo
->fdwProperty
; break;
1144 case IGP_CONVERSION
: dwValue
= pImeInfo
->fdwConversionCaps
; break;
1145 case IGP_SENTENCE
: dwValue
= pImeInfo
->fdwSentenceCaps
; break;
1146 case IGP_UI
: dwValue
= pImeInfo
->fdwUICaps
; break;
1147 case IGP_SETCOMPSTR
: dwValue
= pImeInfo
->fdwSCSCaps
; break;
1148 case IGP_SELECT
: dwValue
= pImeInfo
->fdwSelectCaps
; break;
1149 default: dwValue
= 0; break;
1153 ImmUnlockImeDpi(pImeDpi
);
1157 /***********************************************************************
1158 * ImmEscapeA (IMM32.@)
1160 LRESULT WINAPI
ImmEscapeA(HKL hKL
, HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
1165 CHAR szA
[MAX_IMM_FILENAME
];
1166 WCHAR szW
[MAX_IMM_FILENAME
];
1168 TRACE("(%p, %p, %u, %p)\n", hKL
, hIMC
, uSubFunc
, lpData
);
1170 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1174 if (!ImeDpi_IsUnicode(pImeDpi
) || !lpData
)
1176 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1177 ImmUnlockImeDpi(pImeDpi
);
1183 case IME_ESC_SEQUENCE_TO_INTERNAL
:
1184 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1188 szW
[cch
++] = HIWORD(ret
);
1190 szW
[cch
++] = LOWORD(ret
);
1192 cch
= WideCharToMultiByte(pImeDpi
->uCodePage
, 0, szW
, cch
, szA
, _countof(szA
),
1197 ret
= MAKEWORD(szA
[0], 0);
1200 ret
= MAKEWORD(szA
[1], szA
[0]);
1203 ret
= MAKELONG(MAKEWORD(szA
[2], szA
[1]), MAKEWORD(szA
[0], 0));
1206 ret
= MAKELONG(MAKEWORD(szA
[3], szA
[2]), MAKEWORD(szA
[1], szA
[0]));
1214 case IME_ESC_GET_EUDC_DICTIONARY
:
1215 case IME_ESC_IME_NAME
:
1216 case IME_ESC_GETHELPFILENAME
:
1217 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szW
, hKL
);
1220 szW
[_countof(szW
) - 1] = 0;
1221 WideCharToMultiByte(pImeDpi
->uCodePage
, 0, szW
, -1,
1222 lpData
, MAX_IMM_FILENAME
, NULL
, NULL
);
1223 ((LPSTR
)lpData
)[MAX_IMM_FILENAME
- 1] = 0;
1227 case IME_ESC_SET_EUDC_DICTIONARY
:
1228 case IME_ESC_HANJA_MODE
:
1229 MultiByteToWideChar(pImeDpi
->uCodePage
, MB_PRECOMPOSED
,
1230 lpData
, -1, szW
, _countof(szW
));
1231 szW
[_countof(szW
) - 1] = 0;
1232 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szW
, hKL
);
1236 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1240 ImmUnlockImeDpi(pImeDpi
);
1244 /***********************************************************************
1245 * ImmEscapeW (IMM32.@)
1247 LRESULT WINAPI
ImmEscapeW(HKL hKL
, HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
1252 CHAR szA
[MAX_IMM_FILENAME
];
1253 WCHAR szW
[MAX_IMM_FILENAME
];
1256 TRACE("(%p, %p, %u, %p)\n", hKL
, hIMC
, uSubFunc
, lpData
);
1258 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1262 if (ImeDpi_IsUnicode(pImeDpi
) || !lpData
)
1264 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1265 ImmUnlockImeDpi(pImeDpi
);
1271 case IME_ESC_SEQUENCE_TO_INTERNAL
:
1272 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1277 szA
[cch
++] = HIBYTE(word
);
1279 szA
[cch
++] = LOBYTE(word
);
1281 cch
= MultiByteToWideChar(pImeDpi
->uCodePage
, MB_PRECOMPOSED
,
1282 szA
, cch
, szW
, _countof(szW
));
1285 case 1: ret
= szW
[0]; break;
1286 case 2: ret
= MAKELONG(szW
[1], szW
[0]); break;
1287 default: ret
= 0; break;
1291 case IME_ESC_GET_EUDC_DICTIONARY
:
1292 case IME_ESC_IME_NAME
:
1293 case IME_ESC_GETHELPFILENAME
:
1294 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szA
, hKL
);
1297 szA
[_countof(szA
) - 1] = 0;
1298 MultiByteToWideChar(pImeDpi
->uCodePage
, MB_PRECOMPOSED
,
1299 szA
, -1, lpData
, MAX_IMM_FILENAME
);
1300 ((LPWSTR
)lpData
)[MAX_IMM_FILENAME
- 1] = 0;
1304 case IME_ESC_SET_EUDC_DICTIONARY
:
1305 case IME_ESC_HANJA_MODE
:
1306 WideCharToMultiByte(pImeDpi
->uCodePage
, 0,
1307 lpData
, -1, szA
, _countof(szA
), NULL
, NULL
);
1308 szA
[_countof(szA
) - 1] = 0;
1309 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szA
, hKL
);
1313 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1317 ImmUnlockImeDpi(pImeDpi
);
1321 /***********************************************************************
1322 * ImmGetOpenStatus (IMM32.@)
1324 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
1329 TRACE("(%p)\n", hIMC
);
1334 pIC
= ImmLockIMC(hIMC
);
1344 /***********************************************************************
1345 * ImmSetOpenStatus (IMM32.@)
1347 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
1352 BOOL bHasChange
= FALSE
;
1354 TRACE("(%p, %d)\n", hIMC
, fOpen
);
1356 if (Imm32IsCrossThreadAccess(hIMC
))
1359 pIC
= ImmLockIMC(hIMC
);
1363 if (pIC
->fOpen
!= fOpen
)
1367 dwConversion
= pIC
->fdwConversion
;
1375 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
1376 IMC_SETOPENSTATUS
, IMN_SETOPENSTATUS
, 0);
1377 NtUserNotifyIMEStatus(hWnd
, fOpen
, dwConversion
);
1383 /***********************************************************************
1384 * ImmGetStatusWindowPos (IMM32.@)
1386 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
1391 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
1393 pIC
= ImmLockIMC(hIMC
);
1397 ret
= !!(pIC
->fdwInit
& INIT_STATUSWNDPOS
);
1399 *lpptPos
= pIC
->ptStatusWndPos
;
1405 /***********************************************************************
1406 * ImmSetStatusWindowPos (IMM32.@)
1408 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
1413 TRACE("(%p, {%ld, %ld})\n", hIMC
, lpptPos
->x
, lpptPos
->y
);
1415 if (Imm32IsCrossThreadAccess(hIMC
))
1418 pIC
= ImmLockIMC(hIMC
);
1423 pIC
->ptStatusWndPos
= *lpptPos
;
1424 pIC
->fdwInit
|= INIT_STATUSWNDPOS
;
1428 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
1429 IMC_SETSTATUSWINDOWPOS
, IMN_SETSTATUSWINDOWPOS
, 0);
1433 /***********************************************************************
1434 * ImmGetCompositionWindow (IMM32.@)
1436 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
1441 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
1443 pIC
= ImmLockIMC(hIMC
);
1447 if (pIC
->fdwInit
& INIT_COMPFORM
)
1449 *lpCompForm
= pIC
->cfCompForm
;
1457 /***********************************************************************
1458 * ImmSetCompositionWindow (IMM32.@)
1460 BOOL WINAPI
ImmSetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
1465 if (Imm32IsCrossThreadAccess(hIMC
))
1468 pIC
= ImmLockIMC(hIMC
);
1472 pIC
->cfCompForm
= *lpCompForm
;
1473 pIC
->fdwInit
|= INIT_COMPFORM
;
1479 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
1480 IMC_SETCOMPOSITIONWINDOW
, IMN_SETCOMPOSITIONWINDOW
, 0);
1484 /***********************************************************************
1485 * ImmGetCompositionFontA (IMM32.@)
1487 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1489 PCLIENTIMC pClientImc
;
1490 BOOL ret
= FALSE
, bWide
;
1493 TRACE("(%p, %p)\n", hIMC
, lplf
);
1495 pClientImc
= ImmLockClientImc(hIMC
);
1496 if (pClientImc
== NULL
)
1499 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1500 ImmUnlockClientImc(pClientImc
);
1502 pIC
= ImmLockIMC(hIMC
);
1506 if (pIC
->fdwInit
& INIT_LOGFONT
)
1509 LogFontWideToAnsi(&pIC
->lfFont
.W
, lplf
);
1511 *lplf
= pIC
->lfFont
.A
;
1520 /***********************************************************************
1521 * ImmGetCompositionFontW (IMM32.@)
1523 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1525 PCLIENTIMC pClientImc
;
1530 TRACE("(%p, %p)\n", hIMC
, lplf
);
1532 pClientImc
= ImmLockClientImc(hIMC
);
1533 if (pClientImc
== NULL
)
1536 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1537 ImmUnlockClientImc(pClientImc
);
1539 pIC
= ImmLockIMC(hIMC
);
1543 if (pIC
->fdwInit
& INIT_LOGFONT
)
1546 *lplf
= pIC
->lfFont
.W
;
1548 LogFontAnsiToWide(&pIC
->lfFont
.A
, lplf
);
1557 /***********************************************************************
1558 * ImmSetCompositionFontA (IMM32.@)
1560 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1563 PCLIENTIMC pClientImc
;
1565 LPINPUTCONTEXTDX pIC
;
1570 TRACE("(%p, %p)\n", hIMC
, lplf
);
1572 if (Imm32IsCrossThreadAccess(hIMC
))
1575 pClientImc
= ImmLockClientImc(hIMC
);
1576 if (pClientImc
== NULL
)
1579 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1580 ImmUnlockClientImc(pClientImc
);
1584 LogFontAnsiToWide(lplf
, &lfW
);
1585 return ImmSetCompositionFontW(hIMC
, &lfW
);
1588 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1592 pTeb
= NtCurrentTeb();
1593 if (pTeb
->Win32ClientInfo
[2] < 0x400)
1595 lcid
= GetSystemDefaultLCID();
1596 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&& !(pIC
->dwUIFlags
& 2) &&
1597 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1599 PostMessageA(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
1603 pIC
->lfFont
.A
= *lplf
;
1604 pIC
->fdwInit
|= INIT_LOGFONT
;
1609 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
1610 IMN_SETCOMPOSITIONFONT
, 0);
1614 /***********************************************************************
1615 * ImmSetCompositionFontW (IMM32.@)
1617 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1620 PCLIENTIMC pClientImc
;
1623 LPINPUTCONTEXTDX pIC
;
1627 TRACE("(%p, %p)\n", hIMC
, lplf
);
1629 if (Imm32IsCrossThreadAccess(hIMC
))
1632 pClientImc
= ImmLockClientImc(hIMC
);
1633 if (pClientImc
== NULL
)
1636 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1637 ImmUnlockClientImc(pClientImc
);
1641 LogFontWideToAnsi(lplf
, &lfA
);
1642 return ImmSetCompositionFontA(hIMC
, &lfA
);
1645 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1649 pTeb
= NtCurrentTeb();
1650 if (pTeb
->Win32ClientInfo
[2] < 0x400)
1652 lcid
= GetSystemDefaultLCID();
1653 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&&
1654 !(pIC
->dwUIFlags
& 2) &&
1655 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1657 PostMessageW(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
1661 pIC
->lfFont
.W
= *lplf
;
1662 pIC
->fdwInit
|= INIT_LOGFONT
;
1667 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
1668 IMN_SETCOMPOSITIONFONT
, 0);
1672 /***********************************************************************
1673 * ImmGetConversionListA (IMM32.@)
1676 ImmGetConversionListA(HKL hKL
, HIMC hIMC
, LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
1677 DWORD dwBufLen
, UINT uFlag
)
1681 LPWSTR pszSrcW
= NULL
;
1682 LPCANDIDATELIST pCL
= NULL
;
1685 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_a(pSrc
),
1686 lpDst
, dwBufLen
, uFlag
);
1688 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1689 if (pImeDpi
== NULL
)
1692 if (!ImeDpi_IsUnicode(pImeDpi
))
1694 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
1695 ImmUnlockImeDpi(pImeDpi
);
1701 pszSrcW
= Imm32WideFromAnsi(pSrc
);
1702 if (pszSrcW
== NULL
)
1706 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, NULL
, 0, uFlag
);
1710 pCL
= ImmLocalAlloc(0, cb
);
1714 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, pCL
, cb
, uFlag
);
1718 ret
= CandidateListWideToAnsi(pCL
, lpDst
, dwBufLen
, CP_ACP
);
1721 ImmLocalFree(pszSrcW
);
1723 ImmUnlockImeDpi(pImeDpi
);
1727 /***********************************************************************
1728 * ImmGetConversionListW (IMM32.@)
1731 ImmGetConversionListW(HKL hKL
, HIMC hIMC
, LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
1732 DWORD dwBufLen
, UINT uFlag
)
1737 LPCANDIDATELIST pCL
= NULL
;
1738 LPSTR pszSrcA
= NULL
;
1740 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_w(pSrc
),
1741 lpDst
, dwBufLen
, uFlag
);
1743 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1747 if (ImeDpi_IsUnicode(pImeDpi
))
1749 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
1750 ImmUnlockImeDpi(pImeDpi
);
1756 pszSrcA
= Imm32AnsiFromWide(pSrc
);
1757 if (pszSrcA
== NULL
)
1761 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, NULL
, 0, uFlag
);
1765 pCL
= ImmLocalAlloc(0, cb
);
1769 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, pCL
, cb
, uFlag
);
1773 ret
= CandidateListAnsiToWide(pCL
, lpDst
, dwBufLen
, CP_ACP
);
1776 ImmLocalFree(pszSrcA
);
1778 ImmUnlockImeDpi(pImeDpi
);
1782 /***********************************************************************
1783 * ImmGetConversionStatus (IMM32.@)
1785 BOOL WINAPI
ImmGetConversionStatus(HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
1789 TRACE("(%p %p %p)\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
1791 pIC
= ImmLockIMC(hIMC
);
1795 if (lpfdwConversion
)
1796 *lpfdwConversion
= pIC
->fdwConversion
;
1798 *lpfdwSentence
= pIC
->fdwSentence
;
1804 /***********************************************************************
1805 * ImmSetConversionStatus (IMM32.@)
1807 BOOL WINAPI
ImmSetConversionStatus(HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
1811 DWORD dwOldConversion
, dwOldSentence
;
1812 BOOL fOpen
= FALSE
, fConversionChange
= FALSE
, fSentenceChange
= FALSE
, fUseCicero
= FALSE
;
1815 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC
, fdwConversion
, fdwSentence
);
1817 hKL
= GetKeyboardLayout(0);
1818 if (!IS_IME_HKL(hKL
) && Imm32IsCiceroMode() && !Imm32Is16BitMode())
1821 if (Imm32IsCrossThreadAccess(hIMC
))
1824 pIC
= ImmLockIMC(hIMC
);
1828 if (pIC
->fdwConversion
!= fdwConversion
)
1830 dwOldConversion
= pIC
->fdwConversion
;
1831 pIC
->fdwConversion
= fdwConversion
;
1832 fConversionChange
= TRUE
;
1835 if (pIC
->fdwSentence
!= fdwSentence
)
1837 dwOldSentence
= pIC
->fdwSentence
;
1838 pIC
->fdwSentence
= fdwSentence
;
1839 fSentenceChange
= TRUE
;
1846 if (fConversionChange
|| fUseCicero
)
1848 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldConversion
,
1849 IMC_SETCONVERSIONMODE
, IMN_SETCONVERSIONMODE
, 0);
1850 if (fConversionChange
)
1851 NtUserNotifyIMEStatus(hWnd
, fOpen
, fdwConversion
);
1854 if (fSentenceChange
|| fUseCicero
)
1856 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldSentence
,
1857 IMC_SETSENTENCEMODE
, IMN_SETSENTENCEMODE
, 0);
1863 /***********************************************************************
1864 * ImmConfigureIMEA (IMM32.@)
1866 BOOL WINAPI
ImmConfigureIMEA(HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
1870 REGISTERWORDW RegWordW
;
1871 LPREGISTERWORDA pRegWordA
;
1873 TRACE("(%p, %p, 0x%lX, %p)\n", hKL
, hWnd
, dwMode
, lpData
);
1875 if (!ValidateHwnd(hWnd
) || Imm32IsCrossProcessAccess(hWnd
))
1878 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1882 RtlZeroMemory(&RegWordW
, sizeof(RegWordW
));
1884 if (!ImeDpi_IsUnicode(pImeDpi
) || !lpData
|| dwMode
!= IME_CONFIG_REGISTERWORD
)
1889 if (pRegWordA
->lpReading
)
1891 RegWordW
.lpReading
= Imm32WideFromAnsi(pRegWordA
->lpReading
);
1892 if (!RegWordW
.lpReading
)
1896 if (pRegWordA
->lpWord
)
1898 RegWordW
.lpWord
= Imm32WideFromAnsi(pRegWordA
->lpWord
);
1899 if (!RegWordW
.lpWord
)
1906 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1B, 0);
1907 ret
= pImeDpi
->ImeConfigure(hKL
, hWnd
, dwMode
, lpData
);
1908 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1A, 0);
1911 ImmLocalFree(RegWordW
.lpReading
);
1912 ImmLocalFree(RegWordW
.lpWord
);
1913 ImmUnlockImeDpi(pImeDpi
);
1917 /***********************************************************************
1918 * ImmConfigureIMEW (IMM32.@)
1920 BOOL WINAPI
ImmConfigureIMEW(HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
1924 REGISTERWORDA RegWordA
;
1925 LPREGISTERWORDW pRegWordW
;
1927 TRACE("(%p, %p, 0x%lX, %p)\n", hKL
, hWnd
, dwMode
, lpData
);
1929 if (!ValidateHwnd(hWnd
) || Imm32IsCrossProcessAccess(hWnd
))
1932 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1936 RtlZeroMemory(&RegWordA
, sizeof(RegWordA
));
1938 if (ImeDpi_IsUnicode(pImeDpi
) || !lpData
|| dwMode
!= IME_CONFIG_REGISTERWORD
)
1943 if (pRegWordW
->lpReading
)
1945 RegWordA
.lpReading
= Imm32AnsiFromWide(pRegWordW
->lpReading
);
1946 if (!RegWordA
.lpReading
)
1950 if (pRegWordW
->lpWord
)
1952 RegWordA
.lpWord
= Imm32AnsiFromWide(pRegWordW
->lpWord
);
1953 if (!RegWordA
.lpWord
)
1960 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1B, 0);
1961 ret
= pImeDpi
->ImeConfigure(hKL
, hWnd
, dwMode
, lpData
);
1962 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1A, 0);
1965 ImmLocalFree(RegWordA
.lpReading
);
1966 ImmLocalFree(RegWordA
.lpWord
);
1967 ImmUnlockImeDpi(pImeDpi
);
1971 /***********************************************************************
1972 * ImmGetImeMenuItemsA (IMM32.@)
1975 ImmGetImeMenuItemsA(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
1976 LPIMEMENUITEMINFOA lpImeParentMenu
,
1977 LPIMEMENUITEMINFOA lpImeMenu
, DWORD dwSize
)
1979 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
1980 hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
);
1981 return ImmGetImeMenuItemsAW(hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
, TRUE
);
1984 /***********************************************************************
1985 * ImmGetImeMenuItemsW (IMM32.@)
1988 ImmGetImeMenuItemsW(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
1989 LPIMEMENUITEMINFOW lpImeParentMenu
,
1990 LPIMEMENUITEMINFOW lpImeMenu
, DWORD dwSize
)
1992 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
1993 hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
);
1994 return ImmGetImeMenuItemsAW(hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
, FALSE
);