ReactOS  0.4.15-dev-5131-g311fcc6
candidate.c
Go to the documentation of this file.
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 candidate lists
5  * COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #include "precomp.h"
9 
11 
12 // Win: InternalGetCandidateListWtoA
15  UINT uCodePage)
16 {
17  BOOL bUsedDefault;
18  DWORD dwSize, dwIndex, cbGot, cbLeft;
19  const BYTE *pbWide;
20  LPBYTE pbAnsi;
21  LPDWORD pibOffsets;
22 
23  /* calculate total ansi size */
24  if (pWideCL->dwCount > 0)
25  {
26  dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
27  for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
28  {
29  pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
30  cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, NULL, 0,
31  NULL, &bUsedDefault);
32  dwSize += cbGot;
33  }
34  }
35  else
36  {
37  dwSize = sizeof(CANDIDATELIST);
38  }
39 
41  if (dwBufLen == 0)
42  return dwSize;
43  if (dwBufLen < dwSize)
44  return 0;
45 
46  /* store to ansi */
47  pAnsiCL->dwSize = dwBufLen;
48  pAnsiCL->dwStyle = pWideCL->dwStyle;
49  pAnsiCL->dwCount = pWideCL->dwCount;
50  pAnsiCL->dwSelection = pWideCL->dwSelection;
51  pAnsiCL->dwPageStart = pWideCL->dwPageStart;
52  pAnsiCL->dwPageSize = pWideCL->dwPageSize;
53 
54  pibOffsets = pAnsiCL->dwOffset;
55  if (pWideCL->dwCount > 0)
56  {
57  pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
58  cbLeft = dwBufLen - pibOffsets[0];
59 
60  for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
61  {
62  pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
63  pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
64 
65  /* convert to ansi */
66  cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
67  (LPSTR)pbAnsi, cbLeft, NULL, &bUsedDefault);
68  cbLeft -= cbGot;
69 
70  if (dwIndex < pWideCL->dwCount - 1)
71  pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
72  }
73  }
74  else
75  {
76  pibOffsets[0] = sizeof(CANDIDATELIST);
77  }
78 
79  return dwBufLen;
80 }
81 
82 // Win: InternalGetCandidateListAtoW
85  UINT uCodePage)
86 {
87  DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
88  const BYTE *pbAnsi;
89  LPBYTE pbWide;
90  LPDWORD pibOffsets;
91 
92  /* calculate total wide size */
93  if (pAnsiCL->dwCount > 0)
94  {
95  dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * sizeof(DWORD));
96  for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
97  {
98  pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
99  cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1, NULL, 0);
100  dwSize += cchGot * sizeof(WCHAR);
101  }
102  }
103  else
104  {
105  dwSize = sizeof(CANDIDATELIST);
106  }
107 
109  if (dwBufLen == 0)
110  return dwSize;
111  if (dwBufLen < dwSize)
112  return 0;
113 
114  /* store to wide */
115  pWideCL->dwSize = dwBufLen;
116  pWideCL->dwStyle = pAnsiCL->dwStyle;
117  pWideCL->dwCount = pAnsiCL->dwCount;
118  pWideCL->dwSelection = pAnsiCL->dwSelection;
119  pWideCL->dwPageStart = pAnsiCL->dwPageStart;
120  pWideCL->dwPageSize = pAnsiCL->dwPageSize;
121 
122  pibOffsets = pWideCL->dwOffset;
123  if (pAnsiCL->dwCount > 0)
124  {
125  pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
126  cbLeft = dwBufLen - pibOffsets[0];
127 
128  for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
129  {
130  pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
131  pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
132 
133  /* convert to wide */
134  cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1,
135  (LPWSTR)pbWide, cbLeft / sizeof(WCHAR));
136  cbGot = cchGot * sizeof(WCHAR);
137  cbLeft -= cbGot;
138 
139  if (dwIndex + 1 < pAnsiCL->dwCount)
140  pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
141  }
142  }
143  else
144  {
145  pibOffsets[0] = sizeof(CANDIDATELIST);
146  }
147 
148  return dwBufLen;
149 }
150 
151 // Win: ImmGetCandidateListWorker
152 static DWORD APIENTRY
154  BOOL bAnsi)
155 {
156  DWORD ret = 0;
157  LPINPUTCONTEXT pIC;
158  PCLIENTIMC pClientImc;
159  LPCANDIDATEINFO pCI;
160  LPCANDIDATELIST pCL;
161  DWORD dwSize;
162 
163  pClientImc = ImmLockClientImc(hIMC);
164  if (!pClientImc)
165  return 0;
166 
167  pIC = ImmLockIMC(hIMC);
168  if (pIC == NULL)
169  {
170  ImmUnlockClientImc(pClientImc);
171  return 0;
172  }
173 
174  pCI = ImmLockIMCC(pIC->hCandInfo);
175  if (pCI == NULL)
176  {
177  ImmUnlockIMC(hIMC);
178  ImmUnlockClientImc(pClientImc);
179  return 0;
180  }
181 
182  if (pCI->dwSize < sizeof(CANDIDATEINFO) || pCI->dwCount <= dwIndex)
183  goto Quit;
184 
185  /* get required size */
186  pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
187  if (bAnsi)
188  {
189  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
191  else
192  dwSize = pCL->dwSize;
193  }
194  else
195  {
196  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
197  dwSize = pCL->dwSize;
198  else
200  }
201 
202  if (dwBufLen != 0 && dwSize != 0)
203  {
204  if (lpCandList == NULL || dwBufLen < dwSize)
205  goto Quit;
206 
207  /* store */
208  if (bAnsi)
209  {
210  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
211  CandidateListAnsiToWide(pCL, lpCandList, dwSize, CP_ACP);
212  else
213  RtlCopyMemory(lpCandList, pCL, dwSize);
214  }
215  else
216  {
217  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
218  RtlCopyMemory(lpCandList, pCL, dwSize);
219  else
220  CandidateListWideToAnsi(pCL, lpCandList, dwSize, CP_ACP);
221  }
222  }
223 
224  ret = dwSize;
225 
226 Quit:
227  ImmUnlockIMCC(pIC->hCandInfo);
228  ImmUnlockIMC(hIMC);
229  ImmUnlockClientImc(pClientImc);
230  return ret;
231 }
232 
233 // Win: ImmGetCandidateListCountWorker
235 ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
236 {
237  DWORD ret = 0, cbGot, dwIndex;
238  PCLIENTIMC pClientImc;
239  LPINPUTCONTEXT pIC;
240  const CANDIDATEINFO *pCI;
241  const BYTE *pb;
242  const CANDIDATELIST *pCL;
243  const DWORD *pdwOffsets;
244 
245  if (lpdwListCount == NULL)
246  return 0;
247 
248  *lpdwListCount = 0;
249 
250  pClientImc = ImmLockClientImc(hIMC);
251  if (pClientImc == NULL)
252  return 0;
253 
254  pIC = ImmLockIMC(hIMC);
255  if (pIC == NULL)
256  {
257  ImmUnlockClientImc(pClientImc);
258  return 0;
259  }
260 
261  pCI = ImmLockIMCC(pIC->hCandInfo);
262  if (pCI == NULL)
263  {
264  ImmUnlockIMC(hIMC);
265  ImmUnlockClientImc(pClientImc);
266  return 0;
267  }
268 
269  if (pCI->dwSize < sizeof(CANDIDATEINFO))
270  goto Quit;
271 
272  *lpdwListCount = pCI->dwCount; /* the number of candidate lists */
273 
274  /* calculate total size of candidate lists */
275  if (bAnsi)
276  {
277  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
278  {
279  ret = ROUNDUP4(pCI->dwPrivateSize);
280  pdwOffsets = pCI->dwOffset;
281  for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
282  {
283  pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
284  pCL = (const CANDIDATELIST *)pb;
285  cbGot = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
286  ret += cbGot;
287  }
288  }
289  else
290  {
291  ret = pCI->dwSize;
292  }
293  }
294  else
295  {
296  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
297  {
298  ret = pCI->dwSize;
299  }
300  else
301  {
302  ret = ROUNDUP4(pCI->dwPrivateSize);
303  pdwOffsets = pCI->dwOffset;
304  for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
305  {
306  pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
307  pCL = (const CANDIDATELIST *)pb;
308  cbGot = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
309  ret += cbGot;
310  }
311  }
312  }
313 
314 Quit:
315  ImmUnlockIMCC(pIC->hCandInfo);
316  ImmUnlockIMC(hIMC);
317  ImmUnlockClientImc(pClientImc);
318  return ret;
319 }
320 
321 /***********************************************************************
322  * ImmGetCandidateListA (IMM32.@)
323  */
326 {
327  return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
328 }
329 
330 /***********************************************************************
331  * ImmGetCandidateListCountA (IMM32.@)
332  */
334 {
335  return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
336 }
337 
338 /***********************************************************************
339  * ImmGetCandidateListCountW (IMM32.@)
340  */
342 {
343  return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
344 }
345 
346 /***********************************************************************
347  * ImmGetCandidateListW (IMM32.@)
348  */
351 {
352  return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
353 }
354 
355 /***********************************************************************
356  * ImmGetCandidateWindow (IMM32.@)
357  */
358 BOOL WINAPI
359 ImmGetCandidateWindow(HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
360 {
361  BOOL ret = FALSE;
362  LPINPUTCONTEXT pIC;
363  LPCANDIDATEFORM pCF;
364 
365  TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
366 
367  pIC = ImmLockIMC(hIMC);
368  if (pIC == NULL)
369  return FALSE;
370 
371  pCF = &pIC->cfCandForm[dwIndex];
372  if (pCF->dwIndex != IMM_INVALID_CANDFORM)
373  {
374  *lpCandidate = *pCF;
375  ret = TRUE;
376  }
377 
378  ImmUnlockIMC(hIMC);
379  return ret;
380 }
381 
382 /***********************************************************************
383  * ImmSetCandidateWindow (IMM32.@)
384  */
386 {
387  HWND hWnd;
388  LPINPUTCONTEXT pIC;
389 
390  TRACE("(%p, %p)\n", hIMC, lpCandidate);
391 
392  if (lpCandidate->dwIndex >= MAX_CANDIDATEFORM)
393  return FALSE;
394 
395  if (Imm32IsCrossThreadAccess(hIMC))
396  return FALSE;
397 
398  pIC = ImmLockIMC(hIMC);
399  if (pIC == NULL)
400  return FALSE;
401 
402  hWnd = pIC->hWnd;
403  pIC->cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
404 
405  ImmUnlockIMC(hIMC);
406 
408  IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
409  return TRUE;
410 }
DWORD APIENTRY CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, DWORD dwBufLen, UINT uCodePage)
Definition: candidate.c:84
DWORD APIENTRY ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
Definition: candidate.c:235
DWORD WINAPI ImmGetCandidateListCountW(HIMC hIMC, LPDWORD lpdwListCount)
Definition: candidate.c:341
DWORD WINAPI ImmGetCandidateListCountA(HIMC hIMC, LPDWORD lpdwListCount)
Definition: candidate.c:333
DWORD dwCount
Definition: dimm.idl:94
DWORD dwPageSize
Definition: dimm.idl:97
struct tagCANDIDATELIST CANDIDATELIST
#define WideCharToMultiByte
Definition: compat.h:111
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define IMC_SETCANDIDATEPOS
Definition: imm.h:279
BOOL APIENTRY Imm32MakeIMENotify(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue, DWORD_PTR dwCommand, DWORD_PTR dwData)
Definition: utils.c:368
#define TRUE
Definition: types.h:120
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
Definition: imm.c:1015
#define CP_ACP
Definition: compat.h:109
CANDIDATEFORM cfCandForm[4]
Definition: immdev.h:67
DWORD dwCount
Definition: imm.h:206
#define MB_PRECOMPOSED
Definition: winnls.h:281
HWND hWnd
Definition: settings.c:17
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
Definition: utils.c:1109
DWORD dwSize
Definition: imm.h:205
char * LPSTR
Definition: xmlstorage.h:182
BOOL WINAPI ImmGetCandidateWindow(HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
Definition: candidate.c:359
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_ DWORD _In_ DWORD dwBufLen
Definition: wincrypt.h:4245
#define DWORD
Definition: nt_native.h:44
#define NI_CONTEXTUPDATED
Definition: imm.h:226
DWORD dwPageSize
Definition: imm.h:76
WINE_DEFAULT_DEBUG_CHANNEL(imm)
#define CLIENTIMC_WIDE
Definition: ntuser.h:1328
DWORD APIENTRY CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen, UINT uCodePage)
Definition: candidate.c:14
unsigned char * LPBYTE
Definition: typedefs.h:53
#define ROUNDUP4(n)
Definition: precomp.h:63
#define FALSE
Definition: types.h:117
DWORD dwPrivateSize
Definition: imm.h:208
DWORD dwPageStart
Definition: imm.h:75
HIMCC hCandInfo
Definition: immdev.h:69
unsigned int BOOL
Definition: ntddk_ex.h:94
DWORD dwSize
Definition: imm.h:71
DWORD dwOffset[1]
Definition: dimm.idl:98
DWORD dwOffset[1]
Definition: imm.h:77
#define IMN_SETCANDIDATEPOS
Definition: imm.h:529
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
Definition: imm.c:901
DWORD dwStyle
Definition: imm.h:72
const char * LPCSTR
Definition: xmlstorage.h:183
DWORD HIMC
Definition: dimm.idl:75
DWORD dwCount
Definition: imm.h:73
#define MAX_CANDIDATEFORM
Definition: precomp.h:53
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwStyle
Definition: dimm.idl:93
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
static BOOL Imm32IsCrossThreadAccess(HIMC hIMC)
Definition: precomp.h:100
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
Definition: utils.c:1119
int ret
DWORD dwOffset[32]
Definition: imm.h:207
struct tagCANDIDATELIST * LPCANDIDATELIST
static DWORD APIENTRY ImmGetCandidateListAW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen, BOOL bAnsi)
Definition: candidate.c:153
unsigned char BYTE
Definition: xxhash.c:193
DWORD dwPageStart
Definition: dimm.idl:96
#define IMM_INVALID_CANDFORM
Definition: precomp.h:51
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
DWORD WINAPI ImmGetCandidateListW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
Definition: candidate.c:350
#define MultiByteToWideChar
Definition: compat.h:110
DWORD dwFlags
Definition: ntuser.h:1308
BOOL WINAPI ImmSetCandidateWindow(HIMC hIMC, LPCANDIDATEFORM lpCandidate)
Definition: candidate.c:385
DWORD dwSelection
Definition: imm.h:74
uint32_t * LPDWORD
Definition: typedefs.h:59
DWORD dwIndex
Definition: imm.h:63
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
WCHAR * LPWSTR
Definition: xmlstorage.h:184
DWORD dwSelection
Definition: dimm.idl:95
DWORD WINAPI ImmGetCandidateListA(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
Definition: candidate.c:325
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
Definition: imm.c:1024
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define APIENTRY
Definition: api.h:79
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
Definition: imm.c:946