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