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