1 /*
2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IMM32 Win3.x compatibility
5 * COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8 #include "precomp.h"
9
10 WINE_DEFAULT_DEBUG_CHANNEL(imm);
11
12 #ifdef IMM_WIN3_SUPPORT /* 3.x support */
13
14 /* Win: JTransCompositionA */
15 DWORD APIENTRY
Imm32JTransCompA(LPINPUTCONTEXTDX pIC,LPCOMPOSITIONSTRING pCS,const TRANSMSG * pSrc,LPTRANSMSG pDest)16 Imm32JTransCompA(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
17 const TRANSMSG *pSrc, LPTRANSMSG pDest)
18 {
19 FIXME("\n");
20 *pDest = *pSrc;
21 return 1;
22 }
23
24 /* Win: JTransCompositionW */
25 DWORD APIENTRY
Imm32JTransCompW(LPINPUTCONTEXTDX pIC,LPCOMPOSITIONSTRING pCS,const TRANSMSG * pSrc,LPTRANSMSG pDest)26 Imm32JTransCompW(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
27 const TRANSMSG *pSrc, LPTRANSMSG pDest)
28 {
29 FIXME("\n");
30 *pDest = *pSrc;
31 return 1;
32 }
33
34 typedef LRESULT (WINAPI *FN_SendMessage)(HWND, UINT, WPARAM, LPARAM);
35
36 DWORD APIENTRY
WINNLSTranslateMessageJ(DWORD dwCount,LPTRANSMSG pTrans,LPINPUTCONTEXTDX pIC,LPCOMPOSITIONSTRING pCS,BOOL bAnsi)37 WINNLSTranslateMessageJ(DWORD dwCount, LPTRANSMSG pTrans, LPINPUTCONTEXTDX pIC,
38 LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
39 {
40 DWORD ret = 0;
41 HWND hWnd, hwndDefIME;
42 LPTRANSMSG pTempList, pEntry, pNext;
43 DWORD dwIndex, iCandForm, dwNumber, cbTempList;
44 HGLOBAL hGlobal;
45 CANDIDATEFORM CandForm;
46 FN_SendMessage pSendMessage;
47
48 hWnd = pIC->hWnd;
49 hwndDefIME = ImmGetDefaultIMEWnd(hWnd);
50 pSendMessage = (IsWindowUnicode(hWnd) ? SendMessageW : SendMessageA);
51
52 // clone the message list
53 cbTempList = (dwCount + 1) * sizeof(TRANSMSG);
54 pTempList = ImmLocalAlloc(HEAP_ZERO_MEMORY, cbTempList);
55 if (IS_NULL_UNEXPECTEDLY(pTempList))
56 return 0;
57 RtlCopyMemory(pTempList, pTrans, dwCount * sizeof(TRANSMSG));
58
59 if (pIC->dwUIFlags & 0x2)
60 {
61 // find WM_IME_ENDCOMPOSITION
62 pEntry = pTempList;
63 for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pEntry)
64 {
65 if (pEntry->message == WM_IME_ENDCOMPOSITION)
66 break;
67 }
68
69 if (pEntry->message == WM_IME_ENDCOMPOSITION) // if found
70 {
71 // move WM_IME_ENDCOMPOSITION to the end of the list
72 for (pNext = pEntry + 1; pNext->message != 0; ++pEntry, ++pNext)
73 *pEntry = *pNext;
74
75 pEntry->message = WM_IME_ENDCOMPOSITION;
76 pEntry->wParam = 0;
77 pEntry->lParam = 0;
78 }
79 }
80
81 for (pEntry = pTempList; pEntry->message != 0; ++pEntry)
82 {
83 switch (pEntry->message)
84 {
85 case WM_IME_STARTCOMPOSITION:
86 if (!(pIC->dwUIFlags & 0x2))
87 {
88 // send IR_OPENCONVERT
89 if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
90 pSendMessage(hWnd, WM_IME_REPORT, IR_OPENCONVERT, 0);
91
92 goto DoDefault;
93 }
94 break;
95
96 case WM_IME_ENDCOMPOSITION:
97 if (pIC->dwUIFlags & 0x2)
98 {
99 // send IR_UNDETERMINE
100 hGlobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(UNDETERMINESTRUCT));
101 if (hGlobal)
102 {
103 pSendMessage(hWnd, WM_IME_REPORT, IR_UNDETERMINE, (LPARAM)hGlobal);
104 GlobalFree(hGlobal);
105 }
106 }
107 else
108 {
109 // send IR_CLOSECONVERT
110 if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
111 pSendMessage(hWnd, WM_IME_REPORT, IR_CLOSECONVERT, 0);
112
113 goto DoDefault;
114 }
115 break;
116
117 case WM_IME_COMPOSITION:
118 if (bAnsi)
119 dwNumber = Imm32JTransCompA(pIC, pCS, pEntry, pTrans);
120 else
121 dwNumber = Imm32JTransCompW(pIC, pCS, pEntry, pTrans);
122
123 ret += dwNumber;
124 pTrans += dwNumber;
125
126 // send IR_CHANGECONVERT
127 if (!(pIC->dwUIFlags & 0x2))
128 {
129 if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
130 pSendMessage(hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
131 }
132 break;
133
134 case WM_IME_NOTIFY:
135 if (pEntry->wParam == IMN_OPENCANDIDATE)
136 {
137 if (IsWindow(hWnd) && (pIC->dwUIFlags & 0x2))
138 {
139 // send IMC_SETCANDIDATEPOS
140 for (iCandForm = 0; iCandForm < MAX_CANDIDATEFORM; ++iCandForm)
141 {
142 if (!(pEntry->lParam & (1 << iCandForm)))
143 continue;
144
145 CandForm.dwIndex = iCandForm;
146 CandForm.dwStyle = CFS_EXCLUDE;
147 CandForm.ptCurrentPos = pIC->cfCompForm.ptCurrentPos;
148 CandForm.rcArea = pIC->cfCompForm.rcArea;
149 pSendMessage(hwndDefIME, WM_IME_CONTROL, IMC_SETCANDIDATEPOS,
150 (LPARAM)&CandForm);
151 }
152 }
153 }
154
155 if (!(pIC->dwUIFlags & 0x2))
156 goto DoDefault;
157
158 // send a WM_IME_NOTIFY notification to the default ime window
159 pSendMessage(hwndDefIME, pEntry->message, pEntry->wParam, pEntry->lParam);
160 break;
161
162 DoDefault:
163 default:
164 // default processing
165 *pTrans++ = *pEntry;
166 ++ret;
167 break;
168 }
169 }
170
171 ImmLocalFree(pTempList);
172 return ret;
173 }
174
175 DWORD APIENTRY
WINNLSTranslateMessageK(DWORD dwCount,LPTRANSMSG pEntries,LPINPUTCONTEXTDX pIC,LPCOMPOSITIONSTRING pCS,BOOL bAnsi)176 WINNLSTranslateMessageK(DWORD dwCount, LPTRANSMSG pEntries, LPINPUTCONTEXTDX pIC,
177 LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
178 {
179 FIXME("(0x%X, %p, %p, %p, %d)\n", dwCount, pEntries, pIC, pCS, bAnsi);
180 return dwCount;
181 }
182
183 DWORD APIENTRY
WINNLSTranslateMessage(DWORD dwCount,LPTRANSMSG pEntries,HIMC hIMC,BOOL bAnsi,WORD wLang)184 WINNLSTranslateMessage(DWORD dwCount, LPTRANSMSG pEntries, HIMC hIMC, BOOL bAnsi, WORD wLang)
185 {
186 BOOL ret = FALSE;
187 LPINPUTCONTEXTDX pIC;
188 LPCOMPOSITIONSTRING pCS;
189
190 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
191 if (IS_NULL_UNEXPECTEDLY(pIC))
192 return 0;
193
194 pCS = ImmLockIMCC(pIC->hCompStr);
195 if (IS_NULL_UNEXPECTEDLY(pCS))
196 {
197 ImmUnlockIMC(hIMC);
198 return 0;
199 }
200
201 if (wLang == LANG_JAPANESE)
202 ret = WINNLSTranslateMessageJ(dwCount, pEntries, pIC, pCS, bAnsi);
203 else if (wLang == LANG_KOREAN)
204 ret = WINNLSTranslateMessageK(dwCount, pEntries, pIC, pCS, bAnsi);
205
206 ImmUnlockIMCC(pIC->hCompStr);
207 ImmUnlockIMC(hIMC);
208 return ret;
209 }
210
211 #endif /* IMM_WIN3_SUPPORT */
212
213 /***********************************************************************
214 * ImmSendIMEMessageExA(IMM32.@)
215 */
ImmSendIMEMessageExA(HWND hWnd,LPARAM lParam)216 WORD WINAPI ImmSendIMEMessageExA(HWND hWnd, LPARAM lParam)
217 {
218 FIXME("(%p, %p)\n", hWnd, lParam);
219 return 0;
220 }
221
222 /***********************************************************************
223 * ImmSendIMEMessageExW(IMM32.@)
224 */
ImmSendIMEMessageExW(HWND hWnd,LPARAM lParam)225 WORD WINAPI ImmSendIMEMessageExW(HWND hWnd, LPARAM lParam)
226 {
227 FIXME("(%p, %p)\n", hWnd, lParam);
228 return 0;
229 }
230