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