xref: /reactos/dll/win32/imm32/win3.c (revision 09dde2cf)
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
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
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
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
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
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  */
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  */
225 WORD WINAPI ImmSendIMEMessageExW(HWND hWnd, LPARAM lParam)
226 {
227     FIXME("(%p, %p)\n", hWnd, lParam);
228     return 0;
229 }
230