xref: /reactos/dll/win32/imm32/guideline.c (revision 990ba545)
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 guidelines
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 DWORD APIENTRY
13 ImmGetGuideLineAW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsi)
14 {
15     PCLIENTIMC pClientImc;
16     LPINPUTCONTEXT pIC;
17     LPGUIDELINE pGuideLine;
18     DWORD cb, ret = 0;
19     LPVOID pvStr, pvPrivate;
20     BOOL bUsedDefault;
21 
22     pClientImc = ImmLockClientImc(hIMC);
23     if (!pClientImc)
24         return 0;
25 
26     pIC = ImmLockIMC(hIMC);
27     if (!pIC)
28     {
29         ImmUnlockClientImc(pClientImc);
30         return 0;
31     }
32 
33     pGuideLine = ImmLockIMCC(pIC->hGuideLine);
34     if (!pGuideLine)
35     {
36         ImmUnlockIMC(hIMC);
37         ImmUnlockClientImc(pClientImc);
38         return 0;
39     }
40 
41     if (dwIndex == GGL_LEVEL)
42     {
43         ret = pGuideLine->dwLevel;
44         goto Quit;
45     }
46 
47     if (dwIndex == GGL_INDEX)
48     {
49         ret = pGuideLine->dwIndex;
50         goto Quit;
51     }
52 
53     if (dwIndex == GGL_STRING)
54     {
55         pvStr = (LPBYTE)pGuideLine + pGuideLine->dwStrOffset;
56 
57         /* get size */
58         if (bAnsi)
59         {
60             if (pClientImc->dwFlags & CLIENTIMC_WIDE)
61             {
62                 cb = WideCharToMultiByte(CP_ACP, 0, pvStr, pGuideLine->dwStrLen,
63                                          NULL, 0, NULL, &bUsedDefault);
64             }
65             else
66             {
67                 cb = pGuideLine->dwStrLen * sizeof(CHAR);
68             }
69         }
70         else
71         {
72             if (pClientImc->dwFlags & CLIENTIMC_WIDE)
73             {
74                 cb = pGuideLine->dwStrLen * sizeof(WCHAR);
75             }
76             else
77             {
78                 cb = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, pGuideLine->dwStrLen,
79                                          NULL, 0) * sizeof(WCHAR);
80             }
81         }
82 
83         if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
84         {
85             ret = cb;
86             goto Quit;
87         }
88 
89         /* store to buffer */
90         if (bAnsi)
91         {
92             if (pClientImc->dwFlags & CLIENTIMC_WIDE)
93             {
94                 ret = WideCharToMultiByte(CP_ACP, 0, pvStr, pGuideLine->dwStrLen,
95                                           lpBuf, dwBufLen, NULL, &bUsedDefault);
96                 goto Quit;
97             }
98         }
99         else
100         {
101             if (!(pClientImc->dwFlags & CLIENTIMC_WIDE))
102             {
103                 ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, pGuideLine->dwStrLen,
104                                           lpBuf, dwBufLen) * sizeof(WCHAR);
105                 goto Quit;
106             }
107         }
108 
109         RtlCopyMemory(lpBuf, pvStr, cb);
110         ret = cb;
111         goto Quit;
112     }
113 
114     if (dwIndex == GGL_PRIVATE)
115     {
116         pvPrivate = (LPBYTE)pGuideLine + pGuideLine->dwPrivateOffset;
117 
118         /* get size */
119         if (bAnsi)
120         {
121             if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
122                 pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
123             {
124                 cb = CandidateListWideToAnsi(pvPrivate, NULL, 0, CP_ACP);
125             }
126             else
127             {
128                 cb = pGuideLine->dwPrivateSize;
129             }
130         }
131         else
132         {
133             if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
134                 pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
135             {
136                 cb = CandidateListAnsiToWide(pvPrivate, NULL, 0, CP_ACP);
137             }
138             else
139             {
140                 cb = pGuideLine->dwPrivateSize;
141             }
142         }
143 
144         if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
145         {
146             ret = cb;
147             goto Quit;
148         }
149 
150         /* store to buffer */
151         if (bAnsi)
152         {
153             if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
154                 pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
155             {
156                 ret = CandidateListWideToAnsi(pvPrivate, lpBuf, cb, CP_ACP);
157                 goto Quit;
158             }
159         }
160         else
161         {
162             if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
163                 pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
164             {
165                 ret = CandidateListAnsiToWide(pvPrivate, lpBuf, cb, CP_ACP);
166                 goto Quit;
167             }
168         }
169 
170         RtlCopyMemory(lpBuf, pvPrivate, cb);
171         ret = cb;
172         goto Quit;
173     }
174 
175 Quit:
176     ImmUnlockIMCC(pIC->hGuideLine);
177     ImmUnlockIMC(hIMC);
178     ImmUnlockClientImc(pClientImc);
179     return ret;
180 }
181 
182 /***********************************************************************
183  *		ImmGetGuideLineA (IMM32.@)
184  */
185 DWORD WINAPI ImmGetGuideLineA(HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
186 {
187     TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
188     return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
189 }
190 
191 /***********************************************************************
192  *		ImmGetGuideLineW (IMM32.@)
193  */
194 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
195 {
196     TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
197     return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
198 }
199