ReactOS 0.4.16-dev-2332-g4cba65d
conime.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Console IME
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing Console IME Input for Far-East Asian
5 * COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#define WIN32_NO_STATUS
9#include <windef.h>
10#include <winbase.h>
11#include <winuser.h>
12#include <winnls.h>
13#include <winreg.h>
14#include <wincon.h>
15#include <imm.h>
16#include <immdev.h>
17#include <stdlib.h>
18#include <wchar.h>
19#include <undocuser.h>
20#include <imm32_undoc.h>
21#include <wincon_undoc.h>
22#include <cjkcode.h>
23#include <strsafe.h>
24
25#define NTOS_MODE_USER
26#include <ndk/ntndk.h>
27
28#include "conime.h"
29#include "resource.h"
30
31#include <wine/debug.h>
33
34// Special values for COPYDATASTRUCT.dwData
35#define MAGIC_SEND_COMPSTR 0x4B425930 // 'KBY0'
36#define MAGIC_SEND_IMEDISPLAY 0x4B425931 // 'KBY1'
37#define MAGIC_SEND_GUIDELINE 0x4B425932 // 'KBY2'
38#define MAGIC_SEND_CANDLIST 0x4B425935 // 'KBY5'
39#define MAGIC_SEND_IMESYSTEM 0x4B425936 // 'KBY6'
40
41#define _FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
42#define _BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
43
44// Global variables
46PCONENTRY* g_ppEntries = NULL; // begins from &g_ppEntries[1] (g_ppEntries[0] is ignored)
53
55{
56 UINT divisor = 1;
57 if (width > 1)
58 {
59 UINT tempWidth = width - 1;
60 do
61 {
62 divisor *= 10;
63 --tempWidth;
64 } while (tempWidth);
65 }
66
67 for (UINT i = divisor, ich = 0; i > 0; i /= 10, ++ich)
68 {
69 UINT digit = value / i;
70 value %= i;
71
72 if (digit == 0 && ich > 0)
73 {
74 WCHAR prevChar = pszBuffer[ich - 1];
75 if (prevChar == L' ' || prevChar == L'/')
76 {
77 pszBuffer[ich] = L' ';
78 continue;
79 }
80 }
81
82 pszBuffer[ich] = (WCHAR)(L'0' + digit);
83 }
84}
85
88{
89 // Characters from SPACE (0x20) to TILDE (0x7E) are always single-width
90 if (0x0020 <= wch && wch <= 0x007E)
91 return FALSE;
92
93 // East Asian scripts (Full-width blocks)
94 if ((0x3041 <= wch && wch <= 0x3094) || // Hiragana
95 (0x30A1 <= wch && wch <= 0x30F6) || // Katakana
96 (0x3105 <= wch && wch <= 0x312C) || // Bopomofo
97 (0x3131 <= wch && wch <= 0x318E) || // Hangul Compatibility Jamo
98 (0xAC00 <= wch && wch <= 0xD7A3) || // Hangul Syllables
99 (0xFF01 <= wch && wch <= 0xFF5E)) // Full-width Forms (e.g., A, B, !)
100 {
101 return TRUE;
102 }
103
104 // Half-width East Asian blocks
105 if ((0xFF61 <= wch && wch <= 0xFF9F) || // Half-width Katakana
106 (0xFFA0 <= wch && wch <= 0xFFBE) || // Half-width Hangul
107 (0xFFC2 <= wch && wch <= 0xFFC7) || // Specific Half-width Jamo variants
108 (0xFFCA <= wch && wch <= 0xFFCF) ||
109 (0xFFD2 <= wch && wch <= 0xFFD7) ||
110 (0xFFDA <= wch && wch <= 0xFFDC))
111 {
112 return FALSE;
113 }
114
115 // CJK Ideographs and supplemental Full-width symbols
116 if ((0xFFE0 <= wch && wch <= 0xFFE6) || // Full-width currency/symbols (¢, £, ¥, etc.)
117 (0x4E00 <= wch && wch <= 0x9FA5) || // CJK Unified Ideographs (Common Kanji/Hanzi)
118 (0xF900 <= wch && wch <= 0xFA2D)) // CJK Compatibility Ideographs
119 {
120 return TRUE;
121 }
122
123 // Fallback for undefined ranges
124 ULONG cbMultiByte = 0;
125 NTSTATUS Status = RtlUnicodeToMultiByteSize(&cbMultiByte, &wch, sizeof(WCHAR));
126 if (NT_SUCCESS(Status))
127 return cbMultiByte == 2;
128
129 return FALSE;
130}
131
133{
134 INT cch = 0;
135 while (*pch)
136 cch += IntIsDoubleWidthChar(*pch++) + 1;
137 return cch;
138}
139
140BOOL IntSendDataToConsole(HWND hwndConsole, HWND hwndSender, PCOPYDATASTRUCT pCopyData)
141{
142 TRACE("IntSendDataToConsole(%p, %p): 0x%lX, 0x%lX\n", hwndConsole, hwndSender,
143 pCopyData->dwData, pCopyData->cbData);
144
145 if (!hwndConsole || !IsWindow(hwndConsole))
146 {
147 ERR("%p is null or invalid window\n", hwndConsole);
148 return FALSE;
149 }
150
152 if (!SendMessageTimeoutW(hwndConsole, WM_COPYDATA, (WPARAM)hwndSender, (LPARAM)pCopyData,
153 SMTO_ABORTIFHUNG, 3000, &result))
154 {
155 ERR("SendMessageTimeoutW(%p) failed\n", hwndConsole);
156 return FALSE;
157 }
158
159 TRACE("IntSendDataToConsole -> %p\n", result);
160 return TRUE;
161}
162
164// and stores the result in a global variable.
166{
168 HANDLE hToken;
169 ULONG returnLength;
170 TOKEN_STATISTICS tokenStats;
171 static const LUID systemLuid = SYSTEM_LUID;
172
174 if (!NT_SUCCESS(Status))
175 return g_bIsLogOnSession;
176
177 Status = NtQueryInformationToken(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats),
178 &returnLength);
179 NtClose(hToken);
180
181 if (!NT_SUCCESS(Status))
182 return g_bIsLogOnSession;
183
184 g_bIsLogOnSession = RtlEqualMemory(&tokenStats.AuthenticationId, &systemLuid,
185 sizeof(systemLuid));
186 return g_bIsLogOnSession;
187}
188
190{
192
193 if (g_ppEntries)
194 {
195 for (UINT iEntry = 1; iEntry < g_cEntries; ++iEntry)
196 {
197 PCONENTRY pEntry = g_ppEntries[iEntry];
198 if (!pEntry)
199 continue;
200
201 if (!pEntry->hConsole)
202 {
204 continue;
205 }
206
207 if (pEntry->bOpened)
208 {
209 pEntry->bOpened = FALSE;
210 ImmSetOpenStatus(pEntry->hNewIMC, FALSE);
211 }
212
213 if (pEntry->hNewIMC)
214 ImmDestroyContext(pEntry->hNewIMC);
215
216 if (pEntry->pCompStr)
217 {
218 LocalFree(pEntry->pCompStr);
219 pEntry->pCompStr = NULL;
220 }
221
222 for (UINT iList = 0; iList < MAX_CANDLIST; ++iList)
223 {
224 if (!pEntry->apCandList[iList])
225 continue;
226 LocalFree(pEntry->apCandList[iList]);
227 pEntry->apCandList[iList] = NULL;
228 pEntry->acbCandList[iList] = 0;
229 }
230
231 if (pEntry->pdwCandPageStart)
232 {
233 LocalFree(pEntry->pdwCandPageStart);
234 pEntry->pdwCandPageStart = NULL;
235 pEntry->cbCandPageData = 0;
236 }
237
238 if (pEntry->pKLInfo)
239 {
240 LocalFree(pEntry->pKLInfo);
241 pEntry->pKLInfo = NULL;
242 }
243
245 }
246
249 g_cEntries = 0;
250 }
251
253}
254
255static void IntSetCurrentConsole(HANDLE hConsole)
256{
257 TRACE("g_hConsole: %p\n", hConsole);
258 g_hConsole = hConsole;
259}
260
263{
265
266 if (!g_hConsole)
267 IntSetCurrentConsole(hConsole);
268
269 PCONENTRY pFound = NULL;
270 for (UINT iEntry = 1; iEntry < g_cEntries; ++iEntry)
271 {
272 PCONENTRY pEntry = g_ppEntries[iEntry];
273 if (pEntry && pEntry->hConsole == hConsole && !pEntry->bWndEnabled)
274 {
275 pFound = pEntry;
276 break;
277 }
278 }
279
281 TRACE("hConsole %p --> PCONENTRY %p\n", hConsole, pFound);
282 return pFound;
283}
284
287{
289
291
293 {
297 }
298}
299
301{
302 size_t cGrow = 5;
303 size_t cNewCount = g_cEntries + cGrow;
304 size_t cbOld = sizeof(PCONENTRY) * g_cEntries;
305 size_t cbNew = sizeof(PCONENTRY) * cNewCount;
306 PCONENTRY* ppEntries = LocalAlloc(LPTR, cbNew);
307 if (!ppEntries)
308 return FALSE;
309
310 CopyMemory(ppEntries, g_ppEntries, cbOld);
311
312 PCONENTRY* ppOldEntries = g_ppEntries;
313 g_ppEntries = ppEntries;
314 g_cEntries = cNewCount;
315 LocalFree(ppOldEntries);
316
317 return TRUE;
318}
319
322{
323 TRACE("ConIme_UnInitEntry: %p\n", pEntry);
324
325 if (!pEntry->bConsoleEnabled)
326 {
327 pEntry->bWndEnabled = TRUE;
328 return TRUE;
329 }
330
331 pEntry->hConsole = NULL;
332 pEntry->ScreenSize.X = 0;
333 pEntry->nCodePage = pEntry->nOutputCodePage = CP_ACP;
334 pEntry->hKL = NULL;
335 ImmDestroyContext(pEntry->hNewIMC);
336
337 // Free composition string info
338 if (pEntry->pCompStr)
339 {
340 LocalFree(pEntry->pCompStr);
341 pEntry->pCompStr = NULL;
342 }
343
344 // Free candidate list
345 for (UINT iList = 0; iList < _countof(pEntry->apCandList); ++iList)
346 {
347 if (!pEntry->apCandList[iList])
348 continue;
349 LocalFree(pEntry->apCandList[iList]);
350 pEntry->apCandList[iList] = NULL;
351 }
352
353 // Free candidate separators
354 if (pEntry->pdwCandPageStart)
355 {
356 LocalFree(pEntry->pdwCandPageStart);
357 pEntry->pdwCandPageStart = NULL;
358 }
359
360 // Free keyboard list info
361 if (pEntry->pKLInfo)
362 {
363 LocalFree(pEntry->pKLInfo);
364 pEntry->pKLInfo = NULL;
365 }
366
367 pEntry->bConsoleEnabled = FALSE;
368 pEntry->bWndEnabled = FALSE;
369 return TRUE;
370}
371
373// If necessary, sets the input mode abbreviation (szMode) from an internal table.
375{
376 pEntry->szMode[0] = pEntry->szLayoutText[0] = UNICODE_NULL;
377
378 HIMC hIMC = pEntry->hOldIMC;
379 HKL hKL = pEntry->hKL;
380
381 // Attempt to get IME name
382 WCHAR szLayoutName[MAX_PATH];
383 if (ImmEscapeW(hKL, hIMC, IME_ESC_IME_NAME, szLayoutName) ||
384 ImmGetIMEFileNameW(hKL, szLayoutName, _countof(szLayoutName)))
385 {
386 StringCchCopyW(pEntry->szLayoutText, _countof(pEntry->szLayoutText), szLayoutName);
387 return TRUE;
388 }
389
390 // Non IME Keyboard?
391 if (!GetKeyboardLayoutNameW(szLayoutName) ||
392 (szLayoutName[0] != L'E' && szLayoutName[0] != L'e'))
393 {
394 return FALSE;
395 }
396
397 // Build registry path
398 WCHAR szKeyPath[MAX_PATH];
399 StringCchCopyW(szKeyPath, _countof(szKeyPath),
400 L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\");
401 StringCchCatW(szKeyPath, _countof(szKeyPath), szLayoutName);
402
403 HKEY hKey;
405 if (error == ERROR_SUCCESS)
406 {
407 DWORD cbData = sizeof(pEntry->szLayoutText);
408 RegQueryValueExW(hKey, L"Layout Text", NULL, NULL, (PBYTE)pEntry->szLayoutText, &cbData);
410 }
411
412 PCWSTR pszText = pEntry->szLayoutText;
413 if (pszText[0])
414 {
415#define PREFIX_LEN 2
416#define COLUMN_COUNT 7
417 static const WCHAR awchTable[] =
418 {
419 0x5009, 0x9821, 0x8ACB, 0x8F38, 0x5165, 0x5B57, 0x6839, // L"倉頡請輸入字根"
420 0x5167, 0x78BC, 0x8ACB, 0x8F38, 0x5165, 0x5167, 0x78BC, // L"內碼請輸入內碼"
421 0x55AE, 0x78BC, 0x8ACB, 0x8F38, 0x5165, 0x55AE, 0x78BC, // L"單碼請輸入單碼"
422 0x901F, 0x6210, 0x8ACB, 0x8F38, 0x5165, 0x5B57, 0x6839, // L"速成請輸入字根"
423 0x5927, 0x6613, 0x8ACB, 0x8F38, 0x5165, 0x5B57, 0x6839, // L"大易請輸入字根"
424 0x82F1, 0x6570, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // L"英数     "
425 0xFF55, 0xFF53, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // L"us     "
426 0x6CE8, 0x97F3, 0x8ACB, 0x8F38, 0x5165, 0x7B26, 0x865F, // L"注音請輸入符號"
427 0x6CE8, 0x97F3, 0x8ACB, 0x3000, 0x9078, 0x3000, 0x5B57, // L"注音請 選 字"
428 };
429
430 INT ich;
431 for (ich = 0; ich < _countof(awchTable); ich += COLUMN_COUNT)
432 {
433 if (RtlEqualMemory(pszText, &awchTable[ich], PREFIX_LEN * sizeof(WCHAR)))
434 break;
435 }
436
437 if (ich < _countof(awchTable))
438 StringCchCopyW(pEntry->szMode, (COLUMN_COUNT - PREFIX_LEN) + 1, &awchTable[ich + 2]);
439 }
440
441 return TRUE;
442}
443
445{
446 LANGID wLangId = LOWORD(pEntry->hKL);
447 switch (wLangId)
448 {
451 case LANGID_KOREAN:
452 if (!ImmGetOpenStatus(hIMC))
453 return FALSE;
454 return ImmIsIME(pEntry->hKL);
455 case LANGID_JAPANESE:
456 return ImmGetOpenStatus(hIMC);
457 default:
458 return FALSE;
459 }
460}
461
463// Traditional Chinese IME candidate list
465{
466 PCOMPSTRINFO pCompStr = pEntry->pCompStr;
467 PCANDINFO pCandInfo = pEntry->pCandInfo;
468 if (!pCandInfo)
469 return;
470
471 PBYTE pbAttrIndex = (PBYTE)pCandInfo + pCandInfo->dwAttrsOffset;
472 PCHAR_INFO pDest = &pDisplay->CharInfo[iCand];
473
474 for (PWCHAR pchSrc = pCandInfo->szCandStr; *pchSrc; ++pchSrc, ++pbAttrIndex, ++pDest)
475 {
476 pDest->Char.UnicodeChar = *pchSrc;
477 if (*pbAttrIndex < _countof(pCompStr->awAttrColor))
478 pDest->Attributes = pCompStr->awAttrColor[*pbAttrIndex];
479 }
480}
481
484{
485 PWCHAR pLayoutSrc = pEntry->szLayoutText;
486
487 UINT width;
488 for (width = 0; *pLayoutSrc && width < 5 - 1;)
489 {
490 WCHAR wch = *pLayoutSrc++;
491 pDisplay->CharInfo[cch++].Char.UnicodeChar = wch;
492 width += IntIsDoubleWidthChar(wch) + 1;
493 }
494
495 INT paddingCount = 5 - width;
496 for (INT i = 0; i < paddingCount; ++i)
497 pDisplay->CharInfo[cch++].Char.UnicodeChar = L' ';
498
499 WCHAR modeChar;
500 if (pEntry->dwConversion & IME_CMODE_FULLSHAPE)
501 modeChar = 0x5168; // L'全' (full-width)
502 else
503 modeChar = 0x534A; // L'半' (half-width)
504
505 pDisplay->CharInfo[cch++].Char.UnicodeChar = modeChar;
506 pDisplay->CharInfo[cch++].Char.UnicodeChar = L' ';
507 pDisplay->CharInfo[cch++].Char.UnicodeChar = L':';
508
509 for (UINT i = 0; i < cch; ++i)
511
512 return cch;
513}
514
516{
517 UINT maxX = max(pEntry->ScreenSize.X, IMEDISPLAY_MAX_X);
518
519 PCOMPSTRINFO pCompStr = pEntry->pCompStr;
520 if (!pCompStr || !pCompStr->dwCompStrLen)
521 return;
522
523 PWCHAR pchSrc = (PWCHAR)&pCompStr[1]; // bottom of COMPSTRINFO
524 size_t cbCompStr = pCompStr->dwCompStrLen + sizeof(UNICODE_NULL);
525 PBYTE pbAttrIndex = (PBYTE)pchSrc + cbCompStr;
526 PCHAR_INFO pDest = &pDisplay->CharInfo[cch];
527
528 DWORD dwCharCount = pCompStr->dwCompStrLen / sizeof(WCHAR);
529 for (DWORD ich = 0; ich < dwCharCount && ich < maxX; ++ich, ++pDest)
530 {
531 pDest->Char.UnicodeChar = pchSrc[ich];
532
533 BYTE ibColor = pbAttrIndex[ich];
534 if (ibColor < _countof(pCompStr->awAttrColor))
535 pDest->Attributes = pCompStr->awAttrColor[ibColor];
536 }
537}
538
540{
541 UINT ret = 0;
542 for (UINT ich = 0; ich < cch; ++ich)
543 ret += IntIsDoubleWidthChar(pCharInfo[ich].Char.UnicodeChar) + 1;
544 return ret;
545}
546
548{
549 return IntIsDoubleWidthChar(wch) ? 2 : 1;
550}
551
554{
555 const UINT maxX = max(pEntry->ScreenSize.X, IMEDISPLAY_MAX_X);
556
557 UINT currentWidth = IntGetCharInfoWidth(pDisplay->CharInfo, cch);
558 UINT index = cch;
559 while (currentWidth > maxX && index > 0)
560 {
561 --index;
562 WCHAR wch = pDisplay->CharInfo[index].Char.UnicodeChar;
563 currentWidth -= IntGetCharDisplayWidth(wch);
564 }
565
566 const UINT remainingSpace = maxX - currentWidth;
567 const UINT ichFinal = index + remainingSpace;
568
569 if (remainingSpace > 0)
570 {
571 for (UINT ich = index; ich < ichFinal; ++ich)
572 {
573 PCHAR_INFO pChar = &pDisplay->CharInfo[ich];
574 pChar->Char.UnicodeChar = L' ';
575
576 if (ich < cch)
577 pChar->Attributes = pDisplay->CharInfo[ich].Attributes;
578 else
580 }
581 }
582
583 return ichFinal;
584}
585
587// display (CHAR_INFO array).
589{
590 UINT cch = 0;
591 if (ImmIsIME(pEntry->hKL))
592 {
593 cch = IntFillImeModeCHT(pEntry, pDisplay, cch);
594 if (pEntry->bInComposition)
595 {
596 if (pEntry->bHasAnyCand)
598 else
600 }
602 }
603
604 pDisplay->bFlag = FALSE;
605 pDisplay->uCharInfoLen = cch;
606 return TRUE;
607}
608
609inline void IntCopyUnicodeToCharInfo(PCHAR_INFO* ppDest, PCWSTR pszSrc)
610{
611 if (!ppDest || !*ppDest || !pszSrc)
612 return;
613
614 PCHAR_INFO pCurrent;
615 for (pCurrent = *ppDest; *pszSrc; ++pCurrent)
616 {
617 pCurrent->Char.UnicodeChar = *pszSrc++;
618 pCurrent->Attributes = 0;
619 }
620
621 *ppDest = pCurrent;
622}
623
626{
627 PCHAR_INFO pChar = pDisplay->CharInfo;
628 DWORD dwConversion = pEntry->dwConversion, dwSentence = pEntry->dwSentence;
629 UINT cch = 0;
630 WCHAR wchSentence = L' ';
631
632 if (!pEntry->bOpened)
633 goto DoSetAttributes;
634
635 // Determines the input character type (full-width/half-width, hiragana/katakana/alphanumeric)
636 if (dwConversion & IME_CMODE_FULLSHAPE) // Full-width (全角)
637 {
638 if (dwConversion & IME_CMODE_NATIVE)
639 {
640 if (dwConversion & IME_CMODE_KATAKANA)
641 IntCopyUnicodeToCharInfo(&pChar, L"\x5168\x30AB"); // L"全カ"
642 else
643 IntCopyUnicodeToCharInfo(&pChar, L"\x5168\x3042"); // L"全あ"
644 }
645 else
646 {
647 IntCopyUnicodeToCharInfo(&pChar, L"\x5168\xFF21"); // L"全A"
648 }
649 cch = 2;
650 }
651 else // Half-width (半角)
652 {
653 if (dwConversion & IME_CMODE_NATIVE)
654 {
655 if (dwConversion & IME_CMODE_KATAKANA)
656 IntCopyUnicodeToCharInfo(&pChar, L"\x534A\xFF76 "); // L"半カ "
657 else
658 IntCopyUnicodeToCharInfo(&pChar, L"\x534A\xFF71 "); // L"半ア "
659 }
660 else
661 {
662 IntCopyUnicodeToCharInfo(&pChar, L"\x534A\x0041 "); // L"半A "
663 }
664 cch = 3;
665 }
666
667 // Determine phrase conversion mode (compound phrase, simple phrase, automatic, multi-phrase)
668 if (dwSentence & IME_SMODE_PLAURALCLAUSE)
669 wchSentence = L'\x8907'; // L'複'
670 else if (dwSentence & IME_SMODE_SINGLECONVERT)
671 wchSentence = L'\x5358'; // L'単'
672 else if (dwSentence & IME_SMODE_AUTOMATIC)
673 wchSentence = L'\x81EA'; // L'自'
674 else if (dwSentence & IME_SMODE_PHRASEPREDICT)
675 wchSentence = L'\x9023'; // L'連'
676
677 pDisplay->CharInfo[cch++].Char.UnicodeChar = wchSentence;
678 ++pChar;
679
680 // Input method (kana input / romaji input) detection
681 if (GetKeyState(VK_KANA) & 1)
682 {
683 IntCopyUnicodeToCharInfo(&pChar, L"\xFF76\xFF85 "); // L"カナ "
684 cch += 4;
685 }
686 else if (dwConversion & IME_CMODE_ROMAN)
687 {
688 IntCopyUnicodeToCharInfo(&pChar, L"\xFF9B\xFF70\xFF8F "); // L"ローマ "
689 cch += 4;
690 }
691
692DoSetAttributes:
693 for (UINT ich = 0; ich < cch; ++ich)
694 pDisplay->CharInfo[ich].Attributes = _FOREGROUND_WHITE;
695
696 pDisplay->uCharInfoLen = cch;
697 pDisplay->bFlag = TRUE;
698 return TRUE;
699}
700
703{
704 pDisplay->CharInfo[0].Char.UnicodeChar = L' ';
706 pDisplay->uCharInfoLen = 1;
707 pDisplay->bFlag = TRUE;
708 return TRUE;
709}
710
713{
714 DWORD dwConversion = pEntry->dwConversion;
715 UINT width = 0;
716
717 for (PWCHAR pLayoutSrc = pEntry->szLayoutText; *pLayoutSrc; ++pLayoutSrc)
718 {
719 WCHAR wch = *pLayoutSrc;
720 if (wch == 0x8F93) // U+8F93 L'输'
721 break;
722
723 pDisplay->CharInfo[cch++].Char.UnicodeChar = wch;
724
725 width += (IntIsDoubleWidthChar(wch) + 1);
726 if (width >= 9)
727 {
728 cch++;
729 pLayoutSrc++;
730 break;
731 }
732 }
733
734 INT paddingCount = 9 - width;
735 for (INT i = 0; i < paddingCount; ++i)
736 pDisplay->CharInfo[cch++].Char.UnicodeChar = L' ';
737
738 WCHAR modeChar;
739 if (dwConversion & IME_CMODE_FULLSHAPE)
740 modeChar = 0x5168; // U+5168 L'全'
741 else
742 modeChar = 0x534A; // U+534A L'半'
743
744 pDisplay->CharInfo[cch++].Char.UnicodeChar = modeChar;
745 pDisplay->CharInfo[cch++].Char.UnicodeChar = L':';
746
747 for (UINT ich = 0; ich < cch; ++ich)
748 pDisplay->CharInfo[ich].Attributes = _FOREGROUND_WHITE;
749
750 return cch;
751}
752
754// Simplified Chinese IME candidate list
756{
757 PCOMPSTRINFO pCompStr = pEntry->pCompStr;
758
759 if (!pEntry->pCandInfo)
760 return cch;
761
762 UINT displayCols = 0;
763 DWORD strPosByte = 0;
764
765 if (pCompStr->dwCompStrLen > 0)
766 {
767 PWCHAR pszComp = (PWCHAR)&pCompStr[1]; // bottom of COMPSTRINFO
768 size_t cbCompStr = pCompStr->dwCompStrLen + sizeof(UNICODE_NULL);
769 PBYTE pbAttrs = (PBYTE)pszComp + cbCompStr;
770
771 while (displayCols < 10)
772 {
773 pDisplay->CharInfo[cch].Char.UnicodeChar = *pszComp;
774 pDisplay->CharInfo[cch].Attributes = pCompStr->awAttrColor[*pbAttrs];
775 ++cch;
776
777 strPosByte += sizeof(WCHAR);
778 displayCols += IntIsDoubleWidthChar(*pszComp) + 1;
779 ++pszComp;
780 ++pbAttrs;
781
782 if (strPosByte >= pCompStr->dwCompStrLen)
783 break;
784 }
785 }
786
787 INT padCount = 10 - displayCols;
788 for (INT i = 0; i < padCount; ++i)
789 pDisplay->CharInfo[cch++].Char.UnicodeChar = L' ';
790
791 pDisplay->CharInfo[cch++].Char.UnicodeChar = L':';
792
793 PCANDINFO pCandInfo = pEntry->pCandInfo;
794 PBYTE pbCandAttrs = (PBYTE)pCandInfo + pCandInfo->dwAttrsOffset;
795
796 for (PWCHAR pszCand = pCandInfo->szCandStr; *pszCand; ++pszCand)
797 {
798 pDisplay->CharInfo[cch].Char.UnicodeChar = *pszCand;
799 pDisplay->CharInfo[cch].Attributes = pCompStr->awAttrColor[*pbCandAttrs];
800 ++cch;
801 ++pbCandAttrs;
802 }
803
804 return cch;
805}
806
809{
810 UINT cch = 0;
811 if (ImmIsIME(pEntry->hKL))
812 {
813 cch = IntFillImeModeCHS(pEntry, pDisplay, cch);
814 if (pEntry->bInComposition)
815 {
816 if (pEntry->bHasAnyCand)
818 else
820 }
822 }
823 pDisplay->bFlag = FALSE;
824 pDisplay->uCharInfoLen = cch;
825 return TRUE;
826}
827
830{
831 LANGID wLangId = LOWORD(pEntry->hKL);
832 switch (wLangId)
833 {
835 return IntFillImeDisplayCHS(pEntry, pDisplay);
837 return IntFillImeDisplayCHT(pEntry, pDisplay);
838 case LANGID_JAPANESE:
839 return IntFillImeDisplayJPN(pEntry, pDisplay);
840 case LANGID_KOREAN:
841 return IntFillImeDisplayKOR(pEntry, pDisplay);
842 default:
843 return FALSE;
844 }
845}
846
849{
850 // Find active console entries
852 if (!pEntry)
853 return FALSE;
854
855 // Get IME context
856 HIMC hIMC = ImmGetContext(hwndTarget);
857 if (!hIMC)
858 return FALSE;
859
860 // Update IME state in an entry
861 pEntry->bOpened = IntIsImeOpen(hIMC, pEntry);
862 ImmGetConversionStatus(hIMC, &pEntry->dwConversion, &pEntry->dwSentence);
863
864 // Send status to console according to conditions
865 BOOL bSuccess = TRUE;
866 if (pEntry->ScreenSize.X)
867 {
868 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
869 if (pDisplay)
870 {
871 COPYDATASTRUCT CopyData;
872 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
873 CopyData.cbData = sizeof(*pDisplay);
874 CopyData.lpData = pDisplay;
875
876 if (IntFillImeDisplay(pEntry, pDisplay))
877 IntSendDataToConsole(pEntry->hwndConsole, hwndTarget, &CopyData);
878
879 LocalFree(pDisplay);
880 }
881 else
882 {
883 bSuccess = FALSE;
884 }
885 }
886
887 ImmReleaseContext(hwndTarget, hIMC);
888 return bSuccess;
889}
890
892{
893 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
894 if (!pDisplay)
895 return;
896
897 COPYDATASTRUCT CopyData;
898 CopyData.cbData = sizeof(*pDisplay);
899 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
900 CopyData.lpData = pDisplay;
901 if (IntFillImeDisplayCHT(pEntry, pDisplay))
902 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
903
904 LocalFree(pDisplay);
905}
906
908{
909 PCOMPSTRINFO pCompStr = pEntry->pCompStr;
910 if (!pCompStr)
911 return;
912
913 COPYDATASTRUCT CopyData;
914 CopyData.dwData = MAGIC_SEND_COMPSTR;
915 CopyData.lpData = pCompStr;
916 CopyData.cbData = pCompStr->dwSize;
917 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
918}
919
921{
922 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
923 if (!pDisplay)
924 return;
925
926 COPYDATASTRUCT CopyData;
927 CopyData.cbData = sizeof(*pDisplay);
928 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
929 CopyData.lpData = pDisplay;
930 if (IntFillImeDisplayCHS(pEntry, pDisplay))
931 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
932
933 LocalFree(pDisplay);
934}
935
937{
939 if (!pEntry || !pEntry->bInComposition)
940 return;
941
942 LANGID wLangId = LOWORD(pEntry->hKL);
943 switch (wLangId)
944 {
947 break;
950 break;
951 case LANGID_JAPANESE:
952 case LANGID_KOREAN:
954 break;
955 }
956}
957
960{
962 if (!pEntry)
963 return FALSE;
964
965 if (g_bDisabled)
967
968 HKL hOldKL = pEntry->hKL;
969 pEntry->hKL = hKL;
971
973
974 if (!hOldKL)
975 {
977 pEntry->dwImeProp = ImmGetProperty(pEntry->hKL, IGP_PROPERTY);
978 }
979
981 IntSetCurrentConsole(hConsole);
983
984 if (pEntry->pCompStr)
986
987 return TRUE;
988}
989
992{
994 if (!pEntry)
995 return FALSE;
996
997 if (g_bDisabled)
998 {
1000 }
1001 else
1002 {
1005 }
1006
1007 return TRUE;
1008}
1009
1012{
1014 if (!pEntry)
1015 return FALSE;
1016
1017 pEntry->ScreenSize = ScreenSize;
1018 return TRUE;
1019}
1020
1022BOOL ConIme_OnGo(HWND hwnd, HANDLE hConsole, HKL hKL, INT iDirection)
1023{
1025 if (!pEntry)
1026 return FALSE; // Deny
1027
1028 LANGID wTargetLang = 0;
1029 switch (pEntry->nOutputCodePage)
1030 {
1032 wTargetLang = LANGID_CHINESE_SIMPLIFIED;
1033 break;
1035 wTargetLang = LANGID_CHINESE_TRADITIONAL;
1036 break;
1037 case CP_JAPANESE:
1038 wTargetLang = LANGID_JAPANESE;
1039 break;
1040 case CP_KOREAN:
1041 wTargetLang = LANGID_KOREAN;
1042 break;
1043 default:
1044 return TRUE; // Allow
1045 }
1046
1047 if (!IS_IME_HKL(hKL) || LOWORD(hKL) == wTargetLang)
1048 return TRUE; // Allow
1049
1050 if (iDirection == 0)
1051 return FALSE; // Deny
1052
1053 // Get keyboard list
1054 INT cKLs = GetKeyboardLayoutList(0, NULL);
1055 if (cKLs <= 0)
1056 return FALSE; // Deny
1057 HKL* phKLs = LocalAlloc(LPTR, cKLs * sizeof(HKL));
1058 if (!phKLs)
1059 return FALSE; // Deny
1060 GetKeyboardLayoutList(cKLs, phKLs);
1061
1062 // Get current keyboard
1063 INT iCurrent = 0;
1064 for (; iCurrent < cKLs; ++iCurrent)
1065 {
1066 if (pEntry->hKL == phKLs[iCurrent])
1067 break;
1068 }
1069
1070 if (iCurrent < cKLs)
1071 {
1072 for (INT iAttempt = 0, iNext = iCurrent; iAttempt < cKLs; ++iAttempt)
1073 {
1074 iNext += iDirection;
1075
1076 if (iNext < 0)
1077 iNext = cKLs - 1;
1078 else if (iNext >= cKLs)
1079 iNext = 0;
1080
1081 HKL hKL = phKLs[iNext];
1082 LANGID wLangId = LOWORD(hKL);
1083 if (!IS_IME_HKL(hKL) || wLangId == wTargetLang)
1084 {
1085 PostMessageW(pEntry->hwndConsole, WM_USER + 0x0F, (WPARAM)hKL, 0);
1086 break;
1087 }
1088 }
1089 }
1090
1091 LocalFree(phKLs);
1092 return FALSE; // Deny
1093}
1094
1097{
1099 if (!pEntry)
1100 return FALSE;
1101
1102 HIMC hIMC = ImmGetContext(hWnd);
1103 if (!hIMC)
1104 return FALSE;
1105
1106 BOOL ret;
1107 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
1108 if (pDisplay)
1109 {
1110 ImmGetConversionStatus(hIMC, &pEntry->dwConversion, &pEntry->dwSentence);
1111
1112 COPYDATASTRUCT CopyData;
1113 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
1114 CopyData.cbData = sizeof(*pDisplay);
1115 CopyData.lpData = pDisplay;
1116 if (IntFillImeDisplay(pEntry, pDisplay))
1117 IntSendDataToConsole(pEntry->hwndConsole, hWnd, &CopyData);
1118
1119 LocalFree(pDisplay);
1120 ret = TRUE;
1121 }
1122 else
1123 {
1124 ret = FALSE;
1125 }
1126
1127 ImmReleaseContext(hWnd, hIMC);
1128 return ret;
1129}
1130
1132{
1133 TRACE("(%p, %p, %p)\n", hwnd, wParam, hKL);
1134
1136 if (!pEntry)
1137 return FALSE;
1138
1139 pEntry->hKL = hKL;
1140 ActivateKeyboardLayout(hKL, 0);
1143 return TRUE;
1144}
1145
1147BOOL ConIme_InitEntry(HWND hwnd, HANDLE hConsole, HWND hwndConsole)
1148{
1149 TRACE("(%p, %p, %p)\n", hwnd, hConsole, hwndConsole);
1150
1152
1153 for (UINT iEntry = 1; ; ++iEntry)
1154 {
1155 while (iEntry >= g_cEntries)
1156 {
1157 if (!IntGrowEntries())
1158 return FALSE;
1159 }
1160
1161 pEntry = g_ppEntries[iEntry];
1162 if (!pEntry)
1163 {
1164 pEntry = LocalAlloc(LPTR, sizeof(CONENTRY));
1165 if (!pEntry)
1166 return FALSE;
1167
1168 g_ppEntries[iEntry] = pEntry;
1169 }
1170
1171 if (!pEntry->hConsole)
1172 break;
1173
1174 if (pEntry->bWndEnabled && pEntry->bConsoleEnabled)
1176
1177 if (!pEntry->hConsole)
1178 break;
1179 }
1180
1181 ZeroMemory(pEntry, sizeof(*pEntry));
1182 PKLINFO pKLInfo = pEntry->pKLInfo = LocalAlloc(LPTR, sizeof(KLINFO));
1183 if (!pEntry->pKLInfo)
1184 return FALSE;
1185
1186 pKLInfo->hKL = NULL;
1187 pKLInfo->dwConversion = 0;
1188 pEntry->cKLs = 1;
1189
1190 HIMC hIMC = ImmCreateContext();
1191 if (!hIMC)
1192 {
1193 LocalFree(pKLInfo);
1194 pEntry->pKLInfo = NULL;
1195 return FALSE;
1196 }
1197
1198 pEntry->hNewIMC = hIMC;
1199 pEntry->hConsole = hConsole;
1200 pEntry->hwndConsole = hwndConsole;
1201 pEntry->bConsoleEnabled = TRUE;
1202 pEntry->ScreenSize.X = 80;
1203 pEntry->awAttrColor[0] = COMMON_LVB_UNDERSCORE | 0x7;
1204 pEntry->awAttrColor[1] = BACKGROUND_BLUE | _FOREGROUND_WHITE;
1207 pEntry->awAttrColor[4] = COMMON_LVB_UNDERSCORE | FOREGROUND_RED;
1208 pEntry->awAttrColor[5] = COMMON_LVB_UNDERSCORE | FOREGROUND_RED;
1209 pEntry->awAttrColor[6] = COMMON_LVB_UNDERSCORE | FOREGROUND_RED;
1210 pEntry->awAttrColor[7] = COMMON_LVB_UNDERSCORE | FOREGROUND_RED;
1212 TRACE("ConIme_InitEntry --> %p\n", pEntry);
1213 return TRUE;
1214}
1215
1218{
1221 BOOL ret;
1222 if (pEntry)
1224 else
1225 ret = FALSE;
1227 return ret;
1228}
1229
1231BOOL ConIme_OnInit(HWND hwnd, HANDLE hConsole, HWND hwndConsole)
1232{
1233 if (IntFindConsoleEntry(hConsole))
1234 return TRUE;
1235
1236 BOOL ret;
1238 if (ConIme_InitEntry(hwnd, hConsole, hwndConsole))
1239 {
1240 ConIme_OnNotifySetOpenStatus(hwndConsole);
1241 ret = TRUE;
1242 }
1243 else
1244 {
1245 ret = FALSE;
1246 }
1247
1249 return ret;
1250}
1251
1254{
1255 HIMC hIMC = ImmGetContext(hwnd);
1256 if (hIMC)
1257 {
1258 g_hOldIMC = hIMC;
1259 ImmReleaseContext(hwnd, hIMC);
1260 }
1261 return TRUE;
1262}
1263
1266{
1267 HIMC hIMC = ImmGetContext(hwnd);
1268 if (!hIMC)
1269 return;
1270
1271 DWORD dwCompLen = 0; // composition string length (in bytes, excluding)
1272 DWORD dwAttrLen = 0; // attribute info length (in bytes)
1273 size_t cbCompStr, cbNeeded;
1274 COPYDATASTRUCT CopyData;
1275
1276 if (dwFlags & GCS_COMPSTR)
1277 {
1278 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
1279 if ((LONG)dwCompLen < 0)
1280 goto EXIT;
1281
1282 if (dwFlags & GCS_COMPATTR)
1283 {
1284 dwAttrLen = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
1285 if ((LONG)dwAttrLen < 0)
1286 goto EXIT;
1287 }
1288 }
1289 else if (dwFlags & GCS_RESULTSTR)
1290 {
1291 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
1292 if ((LONG)dwCompLen < 0)
1293 goto EXIT;
1294 }
1295 else if (dwFlags == 0)
1296 {
1297 dwCompLen = 0;
1298 }
1299 else
1300 {
1301 goto EXIT;
1302 }
1303
1304 cbCompStr = dwCompLen + sizeof(UNICODE_NULL);
1305 cbNeeded = sizeof(COMPSTRINFO) + cbCompStr + (dwAttrLen + 1);
1306 if (pEntry->pCompStr && pEntry->pCompStr->dwSize < cbNeeded)
1307 {
1308 LocalFree(pEntry->pCompStr);
1309 pEntry->pCompStr = NULL;
1310 }
1311
1312 if (!pEntry->pCompStr)
1313 {
1314 pEntry->pCompStr = LocalAlloc(LPTR, cbNeeded);
1315 if (!pEntry->pCompStr)
1316 goto EXIT;
1317 pEntry->pCompStr->dwSize = (DWORD)cbNeeded;
1318 }
1319
1320 PCOMPSTRINFO pCompStr = pEntry->pCompStr;
1321 ZeroMemory(&pCompStr->dwCompAttrLen, pCompStr->dwSize - offsetof(COMPSTRINFO, dwCompAttrLen));
1322 CopyMemory(pCompStr->awAttrColor, pEntry->awAttrColor, sizeof(pCompStr->awAttrColor));
1323
1324 PWCHAR pszDest = (PWCHAR)&pCompStr[1]; // bottom of COMPSTRINFO
1325 PBYTE pAttrDest = (PBYTE)pszDest + cbCompStr;
1326
1327 if (dwFlags & GCS_COMPSTR)
1328 {
1329 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, pszDest, dwCompLen);
1330 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1331
1332 if (dwAttrLen)
1333 {
1334 ImmGetCompositionStringW(hIMC, GCS_COMPATTR, pAttrDest, dwAttrLen);
1335 pAttrDest[dwAttrLen] = 0;
1336 }
1337
1338 LONG cursorPos = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0);
1339 if (cursorPos >= 0 && (DWORD)cursorPos < dwAttrLen)
1340 pAttrDest[cursorPos] |= BACKGROUND_BLUE;
1341 else
1342 pAttrDest[0] |= BACKGROUND_GREEN;
1343
1344 pCompStr->dwCompStrLen = dwCompLen;
1345 pCompStr->dwCompStrOffset = sizeof(COMPSTRINFO);
1346 pCompStr->dwCompAttrLen = dwAttrLen;
1347 pCompStr->dwCompAttrOffset = sizeof(COMPSTRINFO) + cbCompStr;
1348 }
1349 else if (dwFlags & GCS_RESULTSTR)
1350 {
1351 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, pszDest, dwCompLen);
1352 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1353
1354 pCompStr->dwResultStrLen = dwCompLen;
1355 pCompStr->dwResultStrOffset = sizeof(COMPSTRINFO);
1356 }
1357
1358 CopyData.dwData = MAGIC_SEND_COMPSTR;
1359 CopyData.cbData = pCompStr->dwSize;
1360 CopyData.lpData = pCompStr;
1361 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
1362
1363EXIT:
1364 ImmReleaseContext(hwnd, hIMC);
1365}
1366
1369{
1370 HIMC hIMC = ImmGetContext(hwnd);
1371 if (!hIMC)
1372 return;
1373
1374 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
1375 if (!pDisplay)
1376 {
1377 ImmReleaseContext(hwnd, hIMC);
1378 return;
1379 }
1380
1381 DWORD dwCompLen = 0; // composition string length (in bytes, excluding)
1382 DWORD dwAttrLen = 0; // attribute info length (in bytes)
1383 size_t cbCompStr, cbNeeded;
1384 COPYDATASTRUCT CopyData;
1385
1386 if (dwFlags & GCS_COMPSTR)
1387 {
1388 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
1389 if ((LONG)dwCompLen < 0)
1390 goto EXIT;
1391
1392 if (dwFlags & GCS_COMPATTR)
1393 {
1394 dwAttrLen = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
1395 if ((LONG)dwAttrLen < 0)
1396 goto EXIT;
1397 }
1398 }
1399 else if (dwFlags & GCS_RESULTSTR)
1400 {
1401 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
1402 if ((LONG)dwCompLen < 0)
1403 goto EXIT;
1404 }
1405 else if (dwFlags == 0)
1406 {
1407 dwCompLen = 0;
1408 }
1409 else
1410 {
1411 goto EXIT;
1412 }
1413
1414 cbCompStr = dwCompLen + sizeof(UNICODE_NULL);
1415 cbNeeded = sizeof(COMPSTRINFO) + cbCompStr + (dwAttrLen + 1);
1416 if (pEntry->pCompStr && cbNeeded > pEntry->pCompStr->dwSize)
1417 {
1418 LocalFree(pEntry->pCompStr);
1419 pEntry->pCompStr = NULL;
1420 }
1421
1422 if (!pEntry->pCompStr)
1423 {
1424 pEntry->pCompStr = LocalAlloc(LPTR, cbNeeded);
1425 if (!pEntry->pCompStr)
1426 goto EXIT;
1427 pEntry->pCompStr->dwSize = (DWORD)cbNeeded;
1428 }
1429
1430 PCOMPSTRINFO pCompStr = pEntry->pCompStr;
1431 ZeroMemory(&pCompStr->dwCompAttrLen, pCompStr->dwSize - offsetof(COMPSTRINFO, dwCompAttrLen));
1432 CopyMemory(pCompStr->awAttrColor, pEntry->awAttrColor, sizeof(pCompStr->awAttrColor));
1433
1434 PWCHAR pszDest = (PWCHAR)&pCompStr[1]; // bottom of COMPSTRINFO
1435 PBYTE pAttrDest = (PBYTE)pszDest + cbCompStr;
1436
1437 if (dwFlags & GCS_COMPSTR)
1438 {
1439 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, pszDest, dwCompLen);
1440 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1441
1442 if (dwAttrLen)
1443 {
1444 ImmGetCompositionStringW(hIMC, GCS_COMPATTR, pAttrDest, dwAttrLen);
1445 pAttrDest[dwAttrLen] = 0;
1446 }
1447
1448 pCompStr->dwCompStrLen = dwCompLen;
1449 pCompStr->dwCompStrOffset = sizeof(COMPSTRINFO);
1450 pCompStr->dwCompAttrLen = dwAttrLen;
1451 pCompStr->dwCompAttrOffset = sizeof(COMPSTRINFO) + cbCompStr;
1452 }
1453 else if (dwFlags & GCS_RESULTSTR)
1454 {
1455 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, pszDest, dwCompLen);
1456 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1457
1458 pCompStr->dwResultStrLen = dwCompLen;
1459 pCompStr->dwResultStrOffset = sizeof(COMPSTRINFO);
1460
1461 CopyData.dwData = MAGIC_SEND_COMPSTR;
1462 CopyData.cbData = pCompStr->dwSize;
1463 CopyData.lpData = pCompStr;
1464 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
1465 goto EXIT;
1466 }
1467
1468 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
1469 CopyData.cbData = sizeof(IMEDISPLAY);
1470 CopyData.lpData = pDisplay;
1471 if (IntFillImeDisplayCHS(pEntry, pDisplay))
1472 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
1473
1474EXIT:
1475 if (pDisplay)
1476 LocalFree(pDisplay);
1477 ImmReleaseContext(hwnd, hIMC);
1478}
1479
1481// notifies the console
1483{
1484 HIMC hIMC = ImmGetContext(hWnd);
1485 if (!hIMC)
1486 return;
1487
1488 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
1489 if (!pDisplay)
1490 {
1491 ImmReleaseContext(hWnd, hIMC);
1492 return;
1493 }
1494
1495 DWORD dwCompLen = 0; // composition string length (in bytes)
1496 DWORD dwAttrLen = 0; // attribute info length (in bytes)
1497 COPYDATASTRUCT CopyData;
1498 size_t cbCompStr, cbNeeded;
1499 PCOMPSTRINFO pCompStr;
1500 PWCHAR pszDest;
1501 PBYTE pAttrDest;
1502
1503 if (dwFlags & GCS_COMPSTR)
1504 {
1505 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
1506 if ((LONG)dwCompLen < 0)
1507 goto EXIT;
1508
1509 if (dwFlags & GCS_COMPATTR)
1510 {
1511 dwAttrLen = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
1512 if ((LONG)dwAttrLen < 0)
1513 goto EXIT;
1514 }
1515 }
1516 else if (dwFlags & GCS_RESULTSTR)
1517 {
1518 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
1519 if ((LONG)dwCompLen < 0)
1520 goto EXIT;
1521 }
1522 else if (dwFlags != 0)
1523 {
1524 goto EXIT;
1525 }
1526
1527 cbCompStr = dwCompLen + sizeof(UNICODE_NULL);
1528 cbNeeded = sizeof(COMPSTRINFO) + cbCompStr + (dwAttrLen + 1);
1529 if (pEntry->pCompStr && cbNeeded > pEntry->pCompStr->dwSize)
1530 {
1531 LocalFree(pEntry->pCompStr);
1532 pEntry->pCompStr = NULL;
1533 }
1534
1535 if (!pEntry->pCompStr)
1536 {
1537 pEntry->pCompStr = LocalAlloc(LPTR, cbNeeded);
1538 if (!pEntry->pCompStr)
1539 goto EXIT;
1540 pEntry->pCompStr->dwSize = (DWORD)cbNeeded;
1541 }
1542
1543 pCompStr = pEntry->pCompStr;
1544 ZeroMemory(&pCompStr->dwCompAttrLen, pCompStr->dwSize - sizeof(DWORD));
1545 CopyMemory(pCompStr->awAttrColor, pEntry->awAttrColor, sizeof(pCompStr->awAttrColor));
1546
1547 pszDest = (PWCHAR)&pCompStr[1]; // bottom of COMPSTRINFO
1548 pAttrDest = (PBYTE)pszDest + cbCompStr;
1549
1550 if (dwFlags & GCS_COMPSTR)
1551 {
1552 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, pszDest, dwCompLen);
1553 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1554
1555 if (dwAttrLen)
1556 {
1557 ImmGetCompositionStringW(hIMC, GCS_COMPATTR, pAttrDest, dwAttrLen);
1558 pAttrDest[dwAttrLen] = 0;
1559 }
1560
1561 pCompStr->dwCompStrLen = dwCompLen;
1562 if (dwCompLen)
1563 pCompStr->dwCompStrOffset = sizeof(COMPSTRINFO);
1564 else
1565 pCompStr->dwCompStrOffset = 0;
1566
1567 pCompStr->dwCompAttrLen = dwAttrLen;
1568 if (dwAttrLen)
1569 pCompStr->dwCompAttrOffset = sizeof(COMPSTRINFO) + cbCompStr;
1570 else
1571 pCompStr->dwCompAttrOffset = 0;
1572 }
1573 else if (dwFlags & GCS_RESULTSTR)
1574 {
1575 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, pszDest, dwCompLen);
1576 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1577
1578 pCompStr->dwResultStrLen = dwCompLen;
1579 if (dwCompLen)
1580 pCompStr->dwResultStrOffset = sizeof(COMPSTRINFO);
1581 else
1582 pCompStr->dwResultStrOffset = 0;
1583
1584 CopyData.dwData = MAGIC_SEND_COMPSTR;
1585 CopyData.cbData = pCompStr->dwSize;
1586 CopyData.lpData = pCompStr;
1587 IntSendDataToConsole(pEntry->hwndConsole, hWnd, &CopyData);
1588 goto EXIT;
1589 }
1590
1591 CopyData.lpData = pDisplay;
1592 CopyData.cbData = sizeof(*pDisplay);
1593 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
1594 if (IntFillImeDisplayCHT(pEntry, pDisplay))
1595 IntSendDataToConsole(pEntry->hwndConsole, hWnd, &CopyData);
1596
1597EXIT:
1598 if (pDisplay)
1599 LocalFree(pDisplay);
1600 ImmReleaseContext(hWnd, hIMC);
1601}
1602
1605{
1606 HIMC hIMC = ImmGetContext(hwnd);
1607 if (!hIMC)
1608 return;
1609
1610 DWORD dwCompLen = 0; // composition string length (in bytes)
1611 DWORD dwAttrLen = 0; // attribute info length (in bytes)
1612 size_t cbCompStr, cbNeeded;
1613 PCOMPSTRINFO pCompStr;
1614 PWCHAR pszDest;
1615 PBYTE pAttrDest;
1616 COPYDATASTRUCT CopyData;
1617
1618 if (dwFlags & GCS_COMPSTR)
1619 {
1620 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
1621 if ((LONG)dwCompLen < 0)
1622 goto EXIT;
1623
1624 if (dwFlags & GCS_COMPATTR)
1625 {
1626 dwAttrLen = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
1627 if ((LONG)dwAttrLen < 0)
1628 goto EXIT;
1629 }
1630 else
1631 {
1632 dwAttrLen = dwCompLen;
1633 }
1634 }
1635 else if (dwFlags & GCS_RESULTSTR)
1636 {
1637 dwCompLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
1638 if ((LONG)dwCompLen < 0)
1639 goto EXIT;
1640 dwAttrLen = 0;
1641 }
1642 else if (dwFlags == 0)
1643 {
1644 dwCompLen = 0;
1645 dwAttrLen = 0;
1646 }
1647 else
1648 {
1649 goto EXIT;
1650 }
1651
1652 cbCompStr = dwCompLen + sizeof(UNICODE_NULL);
1653 cbNeeded = sizeof(COMPSTRINFO) + cbCompStr + (dwAttrLen + 1);
1654 if (pEntry->pCompStr && pEntry->pCompStr->dwSize < cbNeeded)
1655 {
1656 LocalFree(pEntry->pCompStr);
1657 pEntry->pCompStr = NULL;
1658 }
1659
1660 if (!pEntry->pCompStr)
1661 {
1662 pEntry->pCompStr = LocalAlloc(LPTR, cbNeeded);
1663 if (!pEntry->pCompStr)
1664 goto EXIT;
1665 pEntry->pCompStr->dwSize = cbNeeded;
1666 }
1667
1668 pCompStr = pEntry->pCompStr;
1669 ZeroMemory(&pCompStr->dwCompAttrLen, pCompStr->dwSize - offsetof(COMPSTRINFO, dwCompAttrLen));
1670 CopyMemory(pCompStr->awAttrColor, pEntry->awAttrColor, sizeof(pCompStr->awAttrColor));
1671
1672 pszDest = (PWCHAR)&pCompStr[1]; // bottom of COMPSTRINFO
1673 pAttrDest = (PBYTE)pszDest + cbCompStr;
1674
1676 {
1677 *pszDest = wch;
1678 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1679 *pAttrDest = 1;
1680 pAttrDest[dwAttrLen] = 0;
1681 }
1682 else if (dwFlags & GCS_COMPSTR)
1683 {
1684 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, pszDest, dwCompLen);
1685 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1686
1687 if (dwFlags & GCS_COMPATTR)
1688 {
1689 ImmGetCompositionStringW(hIMC, GCS_COMPATTR, pAttrDest, dwAttrLen);
1690 pAttrDest[dwAttrLen] = 0;
1691 }
1692 else
1693 {
1694 ZeroMemory(pAttrDest, dwAttrLen);
1695 pAttrDest[dwAttrLen] = 0;
1696 }
1697 pCompStr->dwCompStrLen = dwCompLen;
1698 pCompStr->dwCompStrOffset = (DWORD)((PBYTE)pszDest - (PBYTE)pCompStr);
1699 pCompStr->dwCompAttrLen = dwAttrLen;
1700 pCompStr->dwCompAttrOffset = (DWORD)((PBYTE)pAttrDest - (PBYTE)pCompStr);
1701 }
1702 else if (dwFlags & GCS_RESULTSTR)
1703 {
1704 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, pszDest, dwCompLen);
1705 pszDest[dwCompLen / sizeof(WCHAR)] = UNICODE_NULL;
1706 pCompStr->dwResultStrLen = dwCompLen;
1707 pCompStr->dwResultStrOffset = (DWORD)((PBYTE)pszDest - (PBYTE)pCompStr);
1708 }
1709
1710 CopyData.dwData = MAGIC_SEND_COMPSTR;
1711 CopyData.cbData = pCompStr->dwSize;
1712 CopyData.lpData = pCompStr;
1713 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
1714
1715EXIT:
1716 ImmReleaseContext(hwnd, hIMC);
1717}
1718
1720{
1722 if (!pEntry)
1723 return;
1724
1725 switch (pEntry->nOutputCodePage)
1726 {
1729 break;
1732 break;
1733 case CP_JAPANESE:
1735 break;
1736 case CP_KOREAN:
1738 break;
1739 }
1740}
1741
1744{
1745 TRACE("WM_IME_COMPOSITION\n");
1746 if (!lParam)
1748 if (lParam & GCS_RESULTSTR)
1750 if (lParam & GCS_COMPSTR)
1752 if (lParam & _GCS_SINGLECHAR)
1754 if (lParam & 0x4000)
1755 IntDoImeComp(hwnd, (DWORD)(lParam & 0x4010), wParam);
1756}
1757
1759 PCANDIDATELIST pCandList,
1760 PWSTR pszCandStrDest,
1761 PBYTE pbAttrsDest,
1762 UINT width,
1763 UINT labelWidth,
1765 BOOL bIsCode)
1766{
1767 if (pCandList->dwSelection >= pCandList->dwCount)
1768 pCandList->dwSelection = 0;
1769
1770 UINT pageIndex;
1771 for (pageIndex = pEntry->dwCandIndexMax; pageIndex > 0; --pageIndex)
1772 {
1773 if (pCandList->dwSelection >= pEntry->pdwCandPageStart[pageIndex])
1774 break;
1775 }
1776
1777 ZeroMemory(pbAttrsDest, width);
1778
1779 PWSTR pszCurrentPos = pszCandStrDest;
1780 PBYTE pbCurrentAttr = pbAttrsDest;
1781 UINT currentX = 0;
1782 UINT candNum = 1;
1783
1784 if (bIsCode)
1785 {
1786 WCHAR szCharCode[8];
1787 CHAR asz[2];
1788
1789 PCWCH pwchCand = (PCWCH)((PBYTE)pCandList + pCandList->dwOffset[pCandList->dwSelection]);
1790 WideCharToMultiByte(CP_OEMCP, 0, pwchCand, 1, asz, _countof(asz), NULL, NULL);
1791
1792 StringCchPrintfW(szCharCode, _countof(szCharCode), L"[%04X] ", MAKEWORD(asz[0], asz[1]));
1793
1794 size_t cchCode = wcslen(szCharCode);
1795 StringCchCopyW(pszCurrentPos, cchCode + 1, szCharCode);
1796
1797 currentX = cchCode;
1798 pszCurrentPos += cchCode;
1799 pbCurrentAttr += cchCode;
1800 }
1801
1802 DWORD iStart = pEntry->pdwCandPageStart[pageIndex];
1803 DWORD iEnd = pEntry->pdwCandPageStart[pageIndex + 1];
1804 for (DWORD i = iStart; i < iEnd; ++i)
1805 {
1806 const WCHAR* pszSrc = (const WCHAR*)((PBYTE)pCandList + pCandList->dwOffset[i]);
1807 size_t cchSrc = wcslen(pszSrc);
1808 UINT strWidth = IntGetStringWidth(pszSrc);
1809 BOOL bTruncated = FALSE;
1810
1811 if (currentX + strWidth + 3 > width - labelWidth)
1812 {
1813 UINT tmpW = 0, ichSrc = 0;
1814 for (ichSrc = 0; ichSrc < cchSrc; ++ichSrc)
1815 {
1816 tmpW += IntIsDoubleWidthChar(pszSrc[ichSrc]) + 1;
1817 if (currentX + tmpW > width - labelWidth - 3)
1818 break;
1819 }
1820
1821 cchSrc = (ichSrc > 0) ? ichSrc - 1 : 0;
1822 strWidth = tmpW;
1823 bTruncated = TRUE;
1824 }
1825
1826 if (currentX + strWidth + labelWidth + 3 > width)
1827 break;
1828
1829 if (i == pCandList->dwSelection)
1830 FillMemory(pbCurrentAttr, cchSrc + 2, FOREGROUND_BLUE);
1831
1832 *pszCurrentPos++ = (WCHAR)(L'0' + candNum);
1833 *pszCurrentPos++ = L':';
1834 CopyMemory(pszCurrentPos, pszSrc, cchSrc * sizeof(WCHAR));
1835 pszCurrentPos += cchSrc;
1836 *pszCurrentPos++ = L' ';
1837
1838 currentX += strWidth + 3;
1839 pbCurrentAttr += cchSrc + 3;
1840 candNum++;
1841
1842 if (bTruncated)
1843 break;
1844 }
1845
1846 *pszCurrentPos = UNICODE_NULL;
1847
1848 UINT totalWidth = IntGetStringWidth(pszCandStrDest);
1849 UINT usableWidth = width - labelWidth;
1850
1851 if (totalWidth <= usableWidth)
1852 {
1853 if (bIsCode)
1854 {
1855 if (totalWidth < width)
1856 {
1857 UINT pad = width - totalWidth;
1858 wmemset(pszCurrentPos, L' ', pad);
1859 pszCurrentPos += pad;
1860 }
1861 }
1862 else
1863 {
1864 if (totalWidth < usableWidth)
1865 {
1866 UINT pad = usableWidth - totalWidth;
1867 wmemset(pszCurrentPos, L' ', pad);
1868 pszCurrentPos += pad;
1869 }
1870
1871 UINT halfLabel = (labelWidth - 1) / 2;
1872
1873 IntFormatNumber(pszCurrentPos, pCandList->dwSelection + 1, halfLabel);
1874 pszCurrentPos += halfLabel;
1875
1876 *pszCurrentPos++ = L'/';
1877
1878 IntFormatNumber(pszCurrentPos, pCandList->dwCount, halfLabel);
1879 pszCurrentPos += halfLabel;
1880 }
1881
1882 *pszCurrentPos = UNICODE_NULL;
1883 }
1884
1885 return pageIndex;
1886}
1887
1889 PCANDIDATELIST pCandList,
1890 PWSTR pszCandStrDest,
1891 PBYTE pbAttrsDest,
1892 UINT width,
1893 UINT labelWidth,
1895{
1896 if (pCandList->dwSelection >= pCandList->dwCount)
1897 pCandList->dwSelection = 0;
1898
1899 UINT pageIndex;
1900 for (pageIndex = pEntry->dwCandIndexMax; pageIndex > 0; --pageIndex)
1901 {
1902 if (pCandList->dwSelection >= pEntry->pdwCandPageStart[pageIndex])
1903 break;
1904 }
1905
1906 ZeroMemory(pbAttrsDest, width);
1907
1908 PWSTR pszCurrentStr = pszCandStrDest;
1909 PBYTE pbCurrentAttr = pbAttrsDest;
1910
1911 DWORD iStart = pEntry->pdwCandPageStart[pageIndex];
1912 DWORD iEnd = pEntry->pdwCandPageStart[pageIndex + 1];
1913
1914 UINT currentX = 0;
1915 UINT usableWidth = width - labelWidth;
1916 WORD candidateNum = !!(pEntry->dwImeProp & IME_PROP_CANDLIST_START_FROM_1);
1917
1918 for (DWORD i = iStart; i < iEnd; ++i)
1919 {
1920 const WCHAR* pszSrc = (const WCHAR*)((PBYTE)pCandList + pCandList->dwOffset[i]);
1921 size_t cchSrc = wcslen(pszSrc);
1922 UINT strWidth = IntGetStringWidth(pszSrc);
1923 BOOL bTruncated = FALSE;
1924
1925 if (currentX + strWidth + 3 > usableWidth)
1926 {
1927 size_t tmpW = 0, ichSrc;
1928 for (ichSrc = 0; ichSrc < cchSrc; ++ichSrc)
1929 {
1930 tmpW += IntIsDoubleWidthChar(pszSrc[ichSrc]) + 1;
1931 if (currentX + tmpW > usableWidth - 3)
1932 break;
1933 }
1934
1935 cchSrc = (ichSrc > 0) ? ichSrc - 1 : 0;
1936 strWidth = tmpW;
1937 bTruncated = TRUE;
1938 }
1939
1940 if (currentX + strWidth + labelWidth + 3 > width)
1941 break;
1942
1943 if (i == pCandList->dwSelection)
1944 FillMemory(pbCurrentAttr, cchSrc + 2, FOREGROUND_BLUE);
1945
1946 *pszCurrentStr++ = (WCHAR)(L'0' + candidateNum);
1947 *pszCurrentStr++ = L':';
1948
1949 CopyMemory(pszCurrentStr, pszSrc, cchSrc * sizeof(WCHAR));
1950 pszCurrentStr += cchSrc;
1951 *pszCurrentStr++ = L' ';
1952
1953 currentX += strWidth + 3;
1954 pbCurrentAttr += cchSrc + 3;
1955 candidateNum++;
1956
1957 if (bTruncated)
1958 break;
1959 }
1960
1961 *pszCurrentStr = UNICODE_NULL;
1962
1963 if (IntGetStringWidth(pszCandStrDest) <= usableWidth)
1964 {
1965 *pszCurrentStr = L' ';
1966 PWSTR pszLabelPos = pszCurrentStr + 1;
1967
1968 UINT halfLabel = (labelWidth - 1) / 2;
1969
1970 IntFormatNumber(pszLabelPos, pCandList->dwSelection + 1, halfLabel);
1971
1972 pszLabelPos[halfLabel] = L'/';
1973
1974 IntFormatNumber(&pszLabelPos[halfLabel + 1], pCandList->dwCount, halfLabel);
1975 pszLabelPos[labelWidth] = UNICODE_NULL;
1976 }
1977
1978 return pageIndex;
1979}
1980
1982 PCANDIDATELIST pCandList,
1983 PWSTR pszCandStrDest,
1984 PBYTE pbAttrsDest,
1985 UINT width,
1986 UINT labelWidth,
1988{
1989 if (pCandList->dwSelection >= pCandList->dwCount)
1990 pCandList->dwSelection = 0;
1991
1992 UINT pageIndex;
1993 for (pageIndex = pEntry->dwCandIndexMax; pageIndex > 0; --pageIndex)
1994 {
1995 if (pCandList->dwSelection >= pEntry->pdwCandPageStart[pageIndex])
1996 break;
1997 }
1998
1999 ZeroMemory(pbAttrsDest, width);
2000
2001 PWSTR pszCurrentPos = pszCandStrDest;
2002 PBYTE pbCurrentAttr = pbAttrsDest;
2003 UINT currentX = 0;
2004 UINT usableWidth = width - labelWidth;
2005 WORD candidateNum = !!(pEntry->dwImeProp & IME_PROP_CANDLIST_START_FROM_1);
2006
2007 DWORD iStart = pEntry->pdwCandPageStart[pageIndex];
2008 DWORD iEnd = pEntry->pdwCandPageStart[pageIndex + 1];
2009 for (DWORD i = iStart; i < iEnd; ++i)
2010 {
2011 const WCHAR* pszSrc = (const WCHAR*)((PBYTE)pCandList + pCandList->dwOffset[i]);
2012 size_t cchSrc = wcslen(pszSrc);
2013 UINT strWidth = IntGetStringWidth(pszSrc);
2014 BOOL bTruncated = FALSE;
2015
2016 if (strWidth + currentX + 3 > usableWidth)
2017 {
2018 size_t tmpW = 0, ichSrc = 0;
2019 for (ichSrc = 0; ichSrc < cchSrc; ++ichSrc)
2020 {
2021 tmpW += IntIsDoubleWidthChar(pszSrc[ichSrc]) + 1;
2022 if (currentX + tmpW > usableWidth - 3)
2023 break;
2024 }
2025
2026 cchSrc = (ichSrc > 0) ? ichSrc - 1 : 0;
2027 strWidth = tmpW;
2028 bTruncated = TRUE;
2029 }
2030
2031 if (currentX + strWidth + labelWidth + 3 > width)
2032 break;
2033
2034 if (i == pCandList->dwSelection)
2035 FillMemory(pbCurrentAttr, cchSrc + 2, FOREGROUND_BLUE);
2036
2037 *pszCurrentPos++ = (WCHAR)(L'0' + candidateNum);
2038 *pszCurrentPos++ = L':';
2039 CopyMemory(pszCurrentPos, pszSrc, cchSrc * sizeof(WCHAR));
2040 pszCurrentPos += cchSrc;
2041 *pszCurrentPos++ = L' ';
2042
2043 currentX += strWidth + 3;
2044 pbCurrentAttr += cchSrc + 3;
2045 candidateNum++;
2046
2047 if (bTruncated)
2048 break;
2049 }
2050
2051 *pszCurrentPos = UNICODE_NULL;
2052 return pageIndex;
2053}
2054
2056{
2057 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
2058 if (!pDisplay)
2059 return FALSE;
2060
2061 for (DWORD dwIndex = 0; dwIndex < MAX_CANDLIST; ++dwIndex)
2062 {
2063 if (!(dwCandidates & (1 << dwIndex)))
2064 continue;
2065
2066 DWORD cbList = ImmGetCandidateListW(hIMC, dwIndex, NULL, 0);
2067 if (cbList == 0)
2068 continue;
2069
2070 if (pEntry->apCandList[dwIndex] && pEntry->acbCandList[dwIndex] != cbList)
2071 {
2072 LocalFree(pEntry->apCandList[dwIndex]);
2073 pEntry->apCandList[dwIndex] = NULL;
2074 }
2075
2076 if (!pEntry->apCandList[dwIndex])
2077 {
2078 pEntry->apCandList[dwIndex] = LocalAlloc(LPTR, cbList);
2079 if (!pEntry->apCandList[dwIndex])
2080 continue;
2081 pEntry->acbCandList[dwIndex] = cbList;
2082 }
2083
2084 PCANDIDATELIST pCandList = pEntry->apCandList[dwIndex];
2085 ImmGetCandidateListW(hIMC, dwIndex, pCandList, cbList);
2086
2087 UINT screenX = max(min(pEntry->ScreenSize.X, 128), 12);
2088 UINT usableWidth = screenX - 8;
2089 if (usableWidth < 7)
2090 usableWidth = 7;
2091
2092 UINT maxItemsPerPage = (usableWidth - 7) / 5;
2093 maxItemsPerPage = min(max(maxItemsPerPage, 1), 9);
2094
2095 UINT numDigits = 0;
2096 for (UINT tmpCount = 1; tmpCount <= pCandList->dwCount; (tmpCount *= 10), ++numDigits)
2097 {
2098 if (tmpCount > MAXDWORD / 10)
2099 break;
2100 }
2101
2102 UINT labelWidth = 2 * numDigits + 1;
2103
2104 DWORD nPageCountNeeded;
2105 if ((pCandList->dwCount / maxItemsPerPage + 10) >= 100)
2106 nPageCountNeeded = 100;
2107 else
2108 nPageCountNeeded = (pCandList->dwCount / maxItemsPerPage + 10);
2109
2110 if (pEntry->pdwCandPageStart &&
2111 pEntry->cbCandPageData != nPageCountNeeded * sizeof(DWORD))
2112 {
2113 LocalFree(pEntry->pdwCandPageStart);
2114 pEntry->pdwCandPageStart = NULL;
2115 }
2116
2117 if (!pEntry->pdwCandPageStart)
2118 {
2119 pEntry->pdwCandPageStart = LocalAlloc(LPTR, nPageCountNeeded * sizeof(DWORD));
2120 if (!pEntry->pdwCandPageStart)
2121 {
2122 LocalFree(pDisplay);
2123 return FALSE;
2124 }
2125 pEntry->cbCandPageData = nPageCountNeeded * sizeof(DWORD);
2126 }
2127
2128 if (bOpen)
2129 pEntry->dwCandOffset = 0;
2130
2131 pEntry->pdwCandPageStart[0] = pEntry->dwCandOffset;
2132
2133 PWCHAR firstStr = (PWCHAR)((PBYTE)pCandList + pCandList->dwOffset[0]);
2134 UINT currentX = IntGetStringWidth(firstStr) + 3;
2135
2136 UINT iItem = 0, iCand = 1;
2137 for (iItem = 1; iItem < pCandList->dwCount && iCand < nPageCountNeeded - 1; ++iItem)
2138 {
2139 PWCHAR szText = (PWCHAR)((PBYTE)pCandList + pCandList->dwOffset[iItem]);
2140 UINT strWidth = IntGetStringWidth(szText);
2141
2142 if (currentX + strWidth + 3 > (usableWidth - labelWidth))
2143 {
2144 pEntry->pdwCandPageStart[iCand++] = iItem;
2145 currentX = strWidth + 3;
2146 }
2147 else
2148 {
2149 currentX += strWidth + 3;
2150 }
2151 }
2152
2153 pEntry->pdwCandPageStart[iCand] = pCandList->dwCount;
2154 pEntry->dwCandIndexMax = iCand;
2155
2156 UINT cbCandInfo = 3 * usableWidth + 4;
2157 if (pEntry->dwSystemLineSize < cbCandInfo)
2158 {
2159 if (pEntry->pCandInfo)
2160 LocalFree(pEntry->pCandInfo);
2161 pEntry->pCandInfo = LocalAlloc(LPTR, cbCandInfo);
2162 if (!pEntry->pCandInfo)
2163 {
2164 LocalFree(pDisplay);
2165 return FALSE;
2166 }
2167 pEntry->dwSystemLineSize = cbCandInfo;
2168 }
2169
2170 PCANDINFO pCI = pEntry->pCandInfo;
2171 pCI->dwAttrsOffset = 2 * usableWidth + 4;
2172
2173 PBYTE pbAttrs = (PBYTE)pCI + pCI->dwAttrsOffset;
2174 UINT iPage = IntFormatCandLineCHT(pCandList, pCI->szCandStr, pbAttrs, usableWidth,
2175 labelWidth, pEntry);
2176
2177 // Send page messages
2178 pEntry->bSkipPageMsg = TRUE;
2179 ImmNotifyIME(hIMC, NI_SETCANDIDATE_PAGESTART, dwIndex, pEntry->pdwCandPageStart[iPage]);
2181 pEntry->pdwCandPageStart[iPage + 1] - pEntry->pdwCandPageStart[iPage]);
2182 pEntry->bSkipPageMsg = FALSE;
2183
2184 COPYDATASTRUCT CopyData;
2185 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
2186 CopyData.cbData = sizeof(*pDisplay);
2187 CopyData.lpData = pDisplay;
2188
2189 if (IntFillImeDisplayCHT(pEntry, pDisplay))
2190 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2191 }
2192
2193 LocalFree(pDisplay);
2194 return TRUE;
2195}
2196
2198{
2199 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
2200 if (!pDisplay)
2201 return FALSE;
2202
2203 for (DWORD dwIndex = 0; dwIndex < MAX_CANDLIST; ++dwIndex)
2204 {
2205 if (!(dwCandidates & (1 << dwIndex)))
2206 continue;
2207
2208 DWORD cbList = ImmGetCandidateListW(hIMC, dwIndex, NULL, 0);
2209 if (!cbList)
2210 {
2211 LocalFree(pDisplay);
2212 return FALSE;
2213 }
2214
2215 if (pEntry->apCandList[dwIndex] && pEntry->acbCandList[dwIndex] != cbList)
2216 {
2217 LocalFree(pEntry->apCandList[dwIndex]);
2218 pEntry->apCandList[dwIndex] = NULL;
2219 pEntry->acbCandList[dwIndex] = 0;
2220 }
2221
2222 if (!pEntry->apCandList[dwIndex])
2223 {
2224 pEntry->apCandList[dwIndex] = LocalAlloc(LPTR, cbList);
2225 if (!pEntry->apCandList[dwIndex])
2226 {
2227 LocalFree(pDisplay);
2228 return FALSE;
2229 }
2230 pEntry->acbCandList[dwIndex] = cbList;
2231 }
2232
2233 PCANDIDATELIST pCandList = pEntry->apCandList[dwIndex];
2234 ImmGetCandidateListW(hIMC, dwIndex, pCandList, cbList);
2235
2236 UINT screenX = max(min(pEntry->ScreenSize.X, 128), 12);
2237
2238 INT usableWidth = (INT)screenX - 25;
2239
2240 UINT maxItemsPerPage;
2241 if (usableWidth <= 7)
2242 maxItemsPerPage = 1;
2243 else
2244 maxItemsPerPage = (UINT)((usableWidth - 7) / 5);
2245
2246 if (maxItemsPerPage > 9)
2247 maxItemsPerPage = 9;
2248
2249 DWORD nPageCountNeeded = pCandList->dwCount / maxItemsPerPage + 10;
2250 if (nPageCountNeeded > 100)
2251 nPageCountNeeded = 100;
2252
2253 if (pEntry->pdwCandPageStart &&
2254 pEntry->cbCandPageData != nPageCountNeeded * sizeof(DWORD))
2255 {
2256 LocalFree(pEntry->pdwCandPageStart);
2257 pEntry->pdwCandPageStart = NULL;
2258 }
2259 if (!pEntry->pdwCandPageStart)
2260 {
2261 pEntry->pdwCandPageStart = LocalAlloc(LPTR, nPageCountNeeded * sizeof(DWORD));
2262 if (!pEntry->pdwCandPageStart)
2263 {
2264 LocalFree(pDisplay);
2265 return FALSE;
2266 }
2267 pEntry->cbCandPageData = nPageCountNeeded * sizeof(DWORD);
2268 }
2269
2270 if (bOpen)
2271 pEntry->dwCandOffset = 0;
2272
2273 pEntry->pdwCandPageStart[0] = pEntry->dwCandOffset;
2274
2275 PWCHAR szFirstStr = (PWCHAR)((PBYTE)pCandList + pCandList->dwOffset[0]);
2276 UINT currentX = IntGetStringWidth(szFirstStr) + 3;
2277
2278 UINT iItem = 0, iCand = 1;
2279 for (iItem = 1; iItem < pCandList->dwCount && iCand < nPageCountNeeded - 1; ++iItem)
2280 {
2281 WCHAR* szText = (WCHAR*)((BYTE*)pCandList + pCandList->dwOffset[iItem]);
2282 UINT strWidth = IntGetStringWidth(szText);
2283
2284 if (currentX + strWidth + 3 > usableWidth ||
2285 (iItem - pEntry->pdwCandPageStart[iCand-1]) >= 9)
2286 {
2287 pEntry->pdwCandPageStart[iCand++] = iItem;
2288 currentX = strWidth + 3;
2289 }
2290 else
2291 {
2292 currentX += strWidth + 3;
2293 }
2294 }
2295
2296 pEntry->pdwCandPageStart[iCand] = pCandList->dwCount;
2297 pEntry->dwCandIndexMax = iCand;
2298
2299 DWORD cbCandInfo = 3 * usableWidth + 4;
2300 if (pEntry->dwSystemLineSize < cbCandInfo)
2301 {
2302 if (pEntry->pCandInfo)
2303 LocalFree(pEntry->pCandInfo);
2304 pEntry->pCandInfo = LocalAlloc(LPTR, cbCandInfo);
2305 if (!pEntry->pCandInfo)
2306 {
2307 LocalFree(pDisplay);
2308 return FALSE;
2309 }
2310 pEntry->dwSystemLineSize = cbCandInfo;
2311 }
2312
2313 PCANDINFO pCI = pEntry->pCandInfo;
2314 pCI->dwAttrsOffset = 2 * usableWidth + 4;
2315
2316 PBYTE pbAttrs = (PBYTE)pCI + pCI->dwAttrsOffset;
2317 UINT iPage = IntFormatCandLineCHS(pCandList, pCI->szCandStr, pbAttrs, usableWidth, 0,
2318 pEntry);
2319
2320 // Send page messages
2321 pEntry->bSkipPageMsg = TRUE;
2322 ImmNotifyIME(hIMC, NI_SETCANDIDATE_PAGESTART, dwIndex, pEntry->pdwCandPageStart[iPage]);
2324 pEntry->pdwCandPageStart[iPage + 1] - pEntry->pdwCandPageStart[iPage]);
2325 pEntry->bSkipPageMsg = FALSE;
2326
2327 COPYDATASTRUCT CopyData;
2328 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
2329 CopyData.cbData = sizeof(*pDisplay);
2330 CopyData.lpData = pDisplay;
2331
2332 if (IntFillImeDisplayCHS(pEntry, pDisplay))
2333 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2334 }
2335
2336 LocalFree(pDisplay);
2337 return TRUE;
2338}
2339
2340BOOL
2342{
2343 for (DWORD dwIndex = 0; dwIndex < MAX_CANDLIST; ++dwIndex)
2344 {
2345 if (!(dwCandidates & (1 << dwIndex)))
2346 continue;
2347
2348 DWORD cbList = ImmGetCandidateListW(hIMC, dwIndex, NULL, 0);
2349 if (!cbList)
2350 return FALSE;
2351
2352 if (pEntry->apCandList[dwIndex] && pEntry->acbCandList[dwIndex] != cbList)
2353 {
2354 LocalFree(pEntry->apCandList[dwIndex]);
2355 pEntry->apCandList[dwIndex] = NULL;
2356 }
2357
2358 if (!pEntry->apCandList[dwIndex])
2359 {
2360 pEntry->apCandList[dwIndex] = LocalAlloc(LPTR, cbList);
2361 if (!pEntry->apCandList[dwIndex])
2362 return FALSE;
2363 pEntry->acbCandList[dwIndex] = cbList;
2364 }
2365
2366 PCANDIDATELIST pCandList = pEntry->apCandList[dwIndex];
2367 ImmGetCandidateListW(hIMC, dwIndex, pCandList, cbList);
2368
2369 UINT screenX = max(min(pEntry->ScreenSize.X, 128), 12);
2370
2371 UINT maxItems = (screenX - 7) / 5;
2372 if (maxItems > 9) maxItems = 9;
2373
2374 BOOL bIsCode = (pCandList->dwStyle == IME_CAND_CODE);
2375 UINT labelWidth;
2376 if (bIsCode)
2377 {
2378 labelWidth = 7;
2379 }
2380 else
2381 {
2382 UINT digits = 0;
2383 for (UINT tmp = 1; tmp <= pCandList->dwCount; tmp *= 10)
2384 {
2385 if (tmp > MAXDWORD / 10)
2386 break;
2387 ++digits;
2388 }
2389 labelWidth = 2 * digits + 1;
2390 }
2391
2392 DWORD nPageCountNeeded = (pCandList->dwCount / maxItems + 10);
2393 if (nPageCountNeeded > 100)
2394 nPageCountNeeded = 100;
2395
2396 if (pEntry->pdwCandPageStart &&
2397 pEntry->cbCandPageData != nPageCountNeeded * sizeof(DWORD))
2398 {
2399 LocalFree(pEntry->pdwCandPageStart);
2400 pEntry->pdwCandPageStart = NULL;
2401 }
2402
2403 if (!pEntry->pdwCandPageStart)
2404 {
2405 pEntry->pdwCandPageStart = LocalAlloc(LPTR, nPageCountNeeded * sizeof(DWORD));
2406 if (!pEntry->pdwCandPageStart)
2407 return FALSE;
2408 pEntry->cbCandPageData = nPageCountNeeded * sizeof(DWORD);
2409 }
2410
2411 DWORD iItem, iCand = 1;
2412
2413 if (bIsCode)
2414 {
2415 if (bOpen)
2416 pEntry->dwCandOffset = pCandList->dwSelection % 9;
2417
2418 pEntry->pdwCandPageStart[0] = 0;
2419 for (iItem = pEntry->dwCandOffset; iItem < pCandList->dwCount; iItem += 9)
2420 pEntry->pdwCandPageStart[iCand++] = iItem;
2421
2422 if (iItem > pCandList->dwCount)
2423 iItem = pCandList->dwCount;
2424 }
2425 else
2426 {
2427 if (bOpen)
2428 pEntry->dwCandOffset = 0;
2429
2430 pEntry->pdwCandPageStart[0] = pEntry->dwCandOffset;
2431
2432 UINT currentX =
2433 IntGetStringWidth((PWCHAR)((PBYTE)pCandList + pCandList->dwOffset[0])) + 3;
2434 UINT usableWidth = screenX - labelWidth;
2435
2436 for (DWORD i = 1; i < pCandList->dwCount; ++i)
2437 {
2438 UINT strWidth =
2439 IntGetStringWidth((PWCHAR)((PBYTE)pCandList + pCandList->dwOffset[i]));
2440 if (currentX + strWidth + 3 > usableWidth ||
2441 (i - pEntry->pdwCandPageStart[iCand - 1]) >= 9)
2442 {
2443 pEntry->pdwCandPageStart[iCand++] = i;
2444 currentX = strWidth + 3;
2445 }
2446 else
2447 {
2448 currentX += strWidth + 3;
2449 }
2450 }
2451
2452 iItem = pCandList->dwCount;
2453 }
2454
2455 pEntry->pdwCandPageStart[iCand] = iItem;
2456 pEntry->dwCandIndexMax = iCand;
2457
2458 DWORD cbCandInfo = 3 * screenX + 4;
2459 if (pEntry->dwSystemLineSize < cbCandInfo)
2460 {
2461 if (pEntry->pCandInfo)
2462 LocalFree(pEntry->pCandInfo);
2463 pEntry->pCandInfo = LocalAlloc(LPTR, cbCandInfo);
2464 if (!pEntry->pCandInfo)
2465 return FALSE;
2466 pEntry->dwSystemLineSize = cbCandInfo;
2467 }
2468
2469 PCANDINFO pCI = pEntry->pCandInfo;
2470 pCI->dwAttrsOffset = 2 * screenX + 4;
2471
2472 PBYTE pbAttrs = (PBYTE)pCI + pCI->dwAttrsOffset;
2473 UINT iPage = IntFormatCandLineJPNorKOR(pCandList, pCI->szCandStr, pbAttrs,
2474 screenX, labelWidth, pEntry, bIsCode);
2475
2476 // Send page messages
2477 pEntry->bSkipPageMsg = TRUE;
2478 ImmNotifyIME(hIMC, NI_SETCANDIDATE_PAGESTART, dwIndex, pEntry->pdwCandPageStart[iPage]);
2480 pEntry->pdwCandPageStart[iPage + 1] - pEntry->pdwCandPageStart[iPage]);
2481 pEntry->bSkipPageMsg = FALSE;
2482
2483 COPYDATASTRUCT CopyData;
2484 CopyData.dwData = MAGIC_SEND_CANDLIST;
2485 CopyData.cbData = cbCandInfo;
2486 CopyData.lpData = pCI;
2487 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2488 }
2489
2490 return TRUE;
2491}
2492
2494// list process.
2496{
2498 if (!pEntry)
2499 return FALSE;
2500
2501 if (pEntry->bSkipPageMsg)
2502 return TRUE;
2503
2504 HIMC hIMC = ImmGetContext(hwnd);
2505 if (!hIMC)
2506 return FALSE;
2507
2508 pEntry->bHasAnyCand = TRUE;
2509
2510 LANGID wLangId = LOWORD(pEntry->hKL);
2511 switch (wLangId)
2512 {
2514 IntSendCandListCHS(hwnd, hIMC, pEntry, (DWORD)lParam, bOpen);
2515 break;
2517 IntSendCandListCHT(hwnd, hIMC, pEntry, (DWORD)lParam, bOpen);
2518 break;
2519 case LANGID_JAPANESE:
2520 case LANGID_KOREAN:
2522 break;
2523 default:
2524 ImmReleaseContext(hwnd, hIMC);
2525 return FALSE;
2526 }
2527
2528 ImmReleaseContext(hwnd, hIMC);
2529 return TRUE;
2530}
2531
2533{
2535}
2536
2539{
2541 if (!pEntry)
2542 return FALSE;
2543
2544 HIMC hIMC = ImmGetContext(hWnd);
2545 if (!hIMC)
2546 return FALSE;
2547
2548 COPYDATASTRUCT CopyData;
2549 CopyData.dwData = MAGIC_SEND_GUIDELINE;
2550
2551 BOOL ret = FALSE;
2552 size_t cbGuideLine = ImmGetGuideLineW(hIMC, GGL_STRING, NULL, 0);
2553 if (!cbGuideLine)
2554 {
2555 CopyData.cbData = 0;
2556 CopyData.lpData = NULL;
2557 IntSendDataToConsole(pEntry->hwndConsole, hWnd, &CopyData);
2558 ret = TRUE;
2559 }
2560 else
2561 {
2562 size_t cbAlloc = cbGuideLine + sizeof(UNICODE_NULL);
2563 PWSTR pszGuideLine = LocalAlloc(LPTR, cbAlloc);
2564 if (pszGuideLine)
2565 {
2566 ImmGetGuideLineW(hIMC, GGL_STRING, pszGuideLine, cbGuideLine);
2567
2568 CopyData.cbData = cbAlloc;
2569 CopyData.lpData = pszGuideLine;
2570 IntSendDataToConsole(pEntry->hwndConsole, hWnd, &CopyData);
2571
2572 LocalFree(pszGuideLine);
2573 ret = TRUE;
2574 }
2575 }
2576
2577 ImmReleaseContext(hWnd, hIMC);
2578 return ret;
2579}
2580
2583{
2585 if (!pEntry)
2586 return 0;
2587
2588 HIMC hIMC = ImmGetContext(hWnd);
2589 if (!hIMC)
2590 return _IME_CMODE_DEACTIVATE;
2591
2592 ImmGetConversionStatus(hIMC, &pEntry->dwConversion, &pEntry->dwSentence);
2593 pEntry->bOpened = IntIsImeOpen(hIMC, pEntry);
2594 ImmReleaseContext(hWnd, hIMC);
2595 return pEntry->dwConversion + (pEntry->bOpened ? _IME_CMODE_OPEN : 0);
2596}
2597
2599BOOL IntSetImeState(HWND hwnd, HANDLE hConsole, DWORD dwConversion)
2600{
2602 if (!pEntry)
2603 return FALSE;
2604
2605 if (dwConversion & _IME_CMODE_DEACTIVATE)
2606 {
2609 pEntry->hOldIMC = NULL;
2610 }
2611 else
2612 {
2613 ImmAssociateContext(hwnd, pEntry->hNewIMC);
2615 pEntry->hOldIMC = pEntry->hNewIMC;
2616 }
2617
2618 HIMC hIMC = ImmGetContext(hwnd);
2619 if (!hIMC)
2620 return TRUE;
2621
2622 BOOL bOpened = !!(dwConversion & _IME_CMODE_OPEN);
2623 pEntry->bOpened = bOpened;
2624 ImmSetOpenStatus(hIMC, bOpened);
2625
2626 DWORD dwImeConversion = (dwConversion & ~_IME_CMODE_MASK);
2627 if (pEntry->dwConversion != dwImeConversion)
2628 {
2629 pEntry->dwConversion = dwImeConversion;
2630 ImmSetConversionStatus(hIMC, dwImeConversion, pEntry->dwSentence);
2631 }
2632
2633 ImmReleaseContext(hwnd, hIMC);
2634 return TRUE;
2635}
2636
2638BOOL ConIme_SetCodePage(HWND hwnd, HANDLE hConsole, BOOL bOutput, WORD wCodePage)
2639{
2641 if (!pEntry)
2642 return FALSE;
2643
2644 if (bOutput)
2645 pEntry->nOutputCodePage = wCodePage;
2646 else
2647 pEntry->nCodePage = wCodePage;
2648
2649 return TRUE;
2650}
2651
2654{
2656 if (!pEntry)
2657 return FALSE;
2658
2659 COPYDATASTRUCT CopyData;
2660 CopyData.lpData = &wParam;
2661 CopyData.dwData = MAGIC_SEND_IMESYSTEM;
2662 CopyData.cbData = sizeof(wParam);
2663 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2664 return TRUE;
2665}
2666
2669{
2670 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
2671 if (!pDisplay)
2672 return FALSE;
2673
2674 PCANDIDATELIST* apCandList = pEntry->apCandList;
2675 for (DWORD iCand = 0; iCand < MAX_CANDLIST; ++iCand)
2676 {
2677 if ((dwCandidates & (1 << iCand)) && apCandList[iCand])
2678 {
2679 LocalFree(apCandList[iCand]);
2680 apCandList[iCand] = NULL;
2681 pEntry->acbCandList[iCand] = 0;
2682 }
2683 }
2684
2685 COPYDATASTRUCT CopyData;
2686 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
2687 CopyData.cbData = sizeof(*pDisplay);
2688 CopyData.lpData = pDisplay;
2689 if (IntFillImeDisplayCHT(pEntry, pDisplay))
2690 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2691
2692 LocalFree(pDisplay);
2693 return TRUE;
2694}
2695
2698{
2699 PCANDIDATELIST* apCandList = pEntry->apCandList;
2700 for (DWORD iCand = 0; iCand < MAX_CANDLIST; ++iCand)
2701 {
2702 if ((dwCandidates & (1 << iCand)) && apCandList[iCand])
2703 {
2704 LocalFree(apCandList[iCand]);
2705 apCandList[iCand] = NULL;
2706 pEntry->acbCandList[iCand] = 0;
2707 }
2708 }
2709
2710 COPYDATASTRUCT CopyData = { MAGIC_SEND_CANDLIST };
2711 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2712 return TRUE;
2713}
2714
2717{
2718 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
2719 if (!pDisplay)
2720 return FALSE;
2721
2722 PCANDIDATELIST* apCandList = pEntry->apCandList;
2723 for (DWORD iCand = 0; iCand < MAX_CANDLIST; ++iCand)
2724 {
2725 if ((dwCandidates & (1 << iCand)) && apCandList[iCand])
2726 {
2727 LocalFree(apCandList[iCand]);
2728 apCandList[iCand] = NULL;
2729 pEntry->acbCandList[iCand] = 0;
2730 }
2731 }
2732
2733 COPYDATASTRUCT CopyData;
2734 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
2735 CopyData.cbData = sizeof(*pDisplay);
2736 CopyData.lpData = pDisplay;
2737 if (IntFillImeDisplayCHS(pEntry, pDisplay))
2738 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
2739
2740 LocalFree(pDisplay);
2741 return TRUE;
2742}
2743
2746{
2748 if (!pEntry)
2749 return FALSE;
2750
2751 HIMC hIMC = ImmGetContext(hwnd);
2752 if (!hIMC)
2753 return FALSE;
2754
2755 pEntry->bHasAnyCand = FALSE;
2756
2757 LANGID wLang = LOWORD(pEntry->hKL);
2758 switch (wLang)
2759 {
2761 IntCloseCandsCHS(hwnd, hIMC, pEntry, dwCandidates);
2762 break;
2764 IntCloseCandsCHT(hwnd, hIMC, pEntry, dwCandidates);
2765 break;
2766 case LANGID_JAPANESE:
2767 case LANGID_KOREAN:
2768 IntCloseCandsJPNorKOR(hwnd, hIMC, pEntry, dwCandidates);
2769 break;
2770 default:
2771 ImmReleaseContext(hwnd, hIMC);
2772 return FALSE;
2773 }
2774
2775 ImmReleaseContext(hwnd, hIMC);
2776 return TRUE;
2777}
2778
2781{
2782 switch (wParam)
2783 {
2785 TRACE("IMN_OPENSTATUSWINDOW\n");
2787 break;
2788 case IMN_OPENCANDIDATE:
2789 TRACE("IMN_OPENCANDIDATE\n");
2791 break;
2793 TRACE("IMN_CHANGECANDIDATE\n");
2795 break;
2796 case IMN_CLOSECANDIDATE:
2797 TRACE("IMN_CLOSECANDIDATE\n");
2799 break;
2801 TRACE("IMN_SETCONVERSIONMODE\n");
2803 return FALSE; // Return FALSE to allow default processing to continue
2804 case IMN_SETOPENSTATUS:
2805 TRACE("IMN_SETOPENSTATUS\n");
2807 return FALSE;
2808 case IMN_GUIDELINE:
2809 TRACE("IMN_GUIDELINE\n");
2811 break;
2812 default:
2813 return FALSE;
2814 }
2815
2816 return TRUE;
2817}
2818
2820{
2821 TRACE("(%p, %u, %p, %p)\n", hwnd, uMsg, wParam, lParam);
2823 if (pEntry)
2824 return PostMessageW(pEntry->hwndConsole, uMsg + WM_ROUTE, wParam, lParam);
2825 return FALSE;
2826}
2827
2830{
2831 TRACE("(%p, %u, %p, %p)\n", hwnd, uMsg, wParam, lParam);
2832
2833 WPARAM wch = wParam;
2834 if (HIWORD(wParam))
2835 {
2836 if (uMsg == WM_ROUTE_KEYDOWN || uMsg == WM_ROUTE_KEYUP ||
2837 uMsg == WM_ROUTE_SYSKEYDOWN || uMsg == WM_ROUTE_SYSKEYUP)
2838 {
2839 wch = UNICODE_NULL;
2840 }
2841 else if (HIWORD(wParam) <= 0xFF)
2842 {
2843 wch = HIWORD(wParam);
2844 }
2845 else
2846 {
2847 WCHAR wsz[2] = { HIWORD(wParam), 0 };
2848 CHAR ach;
2849 WideCharToMultiByte(CP_ACP, 0, wsz, 1, &ach, 1, NULL, NULL);
2850 wch = ach;
2851 }
2852 }
2853
2854 UINT vkey, uKeyMsg = ((HIWORD(lParam) & KF_UP) ? WM_KEYUP : WM_KEYDOWN);
2855 LRESULT ret = ImmCallImeConsoleIME(hwnd, uKeyMsg, wParam, lParam, &vkey);
2856
2857 if (!(ret & IPHK_HOTKEY))
2858 {
2859 if (ret & IPHK_PROCESSBYIME)
2860 return ImmTranslateMessage(hwnd, uKeyMsg, wParam, lParam);
2861 else if ((ret & IPHK_CHECKCTRL) || uMsg == WM_ROUTE_CHAR || uMsg == WM_ROUTE_SYSCHAR)
2862 return ConIme_OnKeyChar(hwnd, uMsg - WM_ROUTE, wch, lParam);
2863 else
2864 return ConIme_OnKeyChar(hwnd, uMsg - WM_ROUTE, (UINT)wParam, lParam);
2865 }
2866
2867 return ret;
2868}
2869
2872{
2873 TRACE("WM_USER_SIMHOTKEY\n");
2875}
2876
2879{
2881 for (UINT iEntry = 1; iEntry < g_cEntries; ++iEntry)
2882 {
2883 PCONENTRY pEntry = g_ppEntries[iEntry];
2884 if (pEntry && pEntry->hConsole)
2885 {
2886 // Enable the console window and bring it to the front
2887 if (!pEntry->bConsoleEnabled && !IsWindowEnabled(pEntry->hwndConsole))
2888 {
2889 EnableWindow(pEntry->hwndConsole, TRUE);
2890 pEntry->bConsoleEnabled = TRUE;
2891 if (!pEntry->bWndEnabled)
2892 SetForegroundWindow(pEntry->hwndConsole);
2893 }
2894 }
2895 }
2897}
2898
2901{
2903 if (pEntry && pEntry->hConsole)
2904 {
2905 pEntry->bConsoleEnabled = FALSE;
2906 EnableWindow(pEntry->hwndConsole, FALSE);
2907 g_bDisabled = TRUE;
2908 }
2909}
2910
2913{
2914 TRACE("WM_IME_STARTCOMPOSITION\n");
2916 if (pEntry)
2917 pEntry->bInComposition = TRUE;
2918}
2919
2922{
2923 TRACE("WM_IME_ENDCOMPOSITION\n");
2924
2925 // Find the currently active console entry
2927 if (!pEntry)
2928 return;
2929
2930 pEntry->bInComposition = FALSE;
2931
2932 // Free composition string info
2933 if (pEntry->pCompStr)
2934 {
2935 LocalFree(pEntry->pCompStr);
2936 pEntry->pCompStr = NULL;
2937 }
2938}
2939
2942{
2944 if (!pEntry)
2946 if (!pEntry || !pEntry->pKLInfo)
2947 return;
2948
2949 HKL hOldKL = pEntry->hKL;
2950
2951 if (IS_IME_HKL(hOldKL)) // IME HKL?
2952 {
2953 INT iKL;
2954 PKLINFO pKLInfo = pEntry->pKLInfo;
2955
2956 for (iKL = 0; iKL < pEntry->cKLs; ++iKL)
2957 {
2958 if (!pKLInfo[iKL].hKL || pKLInfo[iKL].hKL == hOldKL)
2959 break;
2960 }
2961
2962 if (iKL >= pEntry->cKLs)
2963 {
2964 INT newCount = pEntry->cKLs + 1;
2965 PKLINFO phNewKLs = LocalAlloc(LPTR, newCount * sizeof(KLINFO));
2966 if (!phNewKLs)
2967 return;
2968
2969 CopyMemory(phNewKLs, pEntry->pKLInfo, pEntry->cKLs * sizeof(KLINFO));
2970 LocalFree(pEntry->pKLInfo);
2971 pEntry->pKLInfo = phNewKLs;
2972 pEntry->cKLs = newCount;
2973 }
2974
2975 pEntry->pKLInfo[iKL].hKL = hOldKL;
2976
2977 DWORD dwConversion = pEntry->dwConversion | (pEntry->bOpened ? _IME_CMODE_OPEN : 0);
2978 pEntry->pKLInfo[iKL].dwConversion = dwConversion;
2979 }
2980
2981 ActivateKeyboardLayout(hNewKL, 0);
2982 pEntry->hKL = hNewKL;
2983
2986 pEntry->dwImeProp = ImmGetProperty(pEntry->hKL, IGP_PROPERTY);
2987
2988 PIMEDISPLAY pDisplay = LocalAlloc(LPTR, sizeof(IMEDISPLAY));
2989 if (!pDisplay)
2990 return;
2991
2992 COPYDATASTRUCT CopyData;
2993 CopyData.dwData = MAGIC_SEND_IMEDISPLAY;
2994 CopyData.cbData = sizeof(*pDisplay);
2995 CopyData.lpData = pDisplay;
2996
2997 if (IS_IME_HKL(hNewKL)) // IME HKL?
2998 {
2999 for (INT iKL = 0; iKL < pEntry->cKLs; ++iKL)
3000 {
3001 if (pEntry->pKLInfo[iKL].hKL != hNewKL)
3002 continue;
3003
3004 IntSetImeState(hwnd, hConsole, pEntry->pKLInfo[iKL].dwConversion);
3006
3007 if (IntFillImeDisplay(pEntry, pDisplay))
3008 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
3009
3010 break;
3011 }
3012 }
3013 else // Non-IME HKL?
3014 {
3015 IntSetImeState(hwnd, hConsole, pEntry->dwConversion & ~_IME_CMODE_OPEN);
3016 pDisplay->uCharInfoLen = 0;
3017 pDisplay->bFlag = TRUE;
3018 IntSendDataToConsole(pEntry->hwndConsole, hwnd, &CopyData);
3019 }
3020
3021 LocalFree(pDisplay);
3022}
3023
3026{
3027 TRACE("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam);
3028 switch (uMsg)
3029 {
3030 case WM_USER_INIT:
3032 case WM_USER_UNINIT:
3034 case WM_USER_SWITCHIME:
3036 case WM_USER_DEACTIVATE:
3038 case WM_USER_SIMHOTKEY:
3041 return IntGetImeState(hWnd, (HANDLE)wParam);
3045 {
3048 }
3050 return ConIme_SendImeStatus(hWnd);
3053 return TRUE;
3056 case WM_USER_GO:
3057 return ConIme_OnGo(hWnd, (HANDLE)wParam, (HKL)lParam, 0);
3058 case WM_USER_GONEXT:
3059 return ConIme_OnGo(hWnd, (HANDLE)wParam, (HKL)lParam, +1);
3060 case WM_USER_GOBACK:
3061 return ConIme_OnGo(hWnd, (HANDLE)wParam, (HKL)lParam, -1);
3062 default:
3063 ERR("Unknown uMsg %u\n", uMsg);
3064 return FALSE;
3065 }
3066}
3067
3070{
3071 TRACE("(%p, %p, %p)\n", hWnd, wParam, lParam);
3072
3074 if (!pEntry)
3075 return FALSE;
3076
3077 // Forward messages to the console window
3078 PostMessageW(pEntry->hwndConsole, WM_INPUTLANGCHANGEREQUEST, wParam, lParam);
3079 return TRUE;
3080}
3081
3085{
3086 switch (uMsg)
3087 {
3088 case WM_CREATE:
3089 return (ConIme_OnCreate(hWnd) ? 0 : -1);
3090
3091 case WM_DESTROY:
3092 ConIme_OnEnd(hWnd, uMsg);
3093 PostQuitMessage(0);
3094 break;
3095
3096 case WM_CLOSE:
3098 break;
3099
3100 case WM_QUERYENDSESSION:
3101 return TRUE;
3102
3103 case WM_ENDSESSION:
3104 ConIme_OnEnd(hWnd, uMsg);
3105 break;
3106
3107 case WM_INPUTLANGCHANGE:
3109 return TRUE;
3110
3111 case WM_INPUTLANGCHANGEREQUEST:
3113 return TRUE;
3114 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
3115
3116 case WM_ENABLE:
3117 if (wParam) // Enabled?
3119 else
3121 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
3122
3123 case WM_IME_STARTCOMPOSITION:
3125 return TRUE;
3126
3127 case WM_IME_ENDCOMPOSITION:
3129 return TRUE;
3130
3131 case WM_IME_COMPOSITION:
3133 return TRUE;
3134
3135 case WM_KEYDOWN:
3136 case WM_KEYUP:
3137 case WM_CHAR:
3138 case WM_DEADCHAR:
3139 case WM_SYSKEYDOWN:
3140 case WM_SYSKEYUP:
3141 case WM_SYSCHAR:
3142 case WM_SYSDEADCHAR:
3144 return TRUE;
3145
3146 case WM_IME_SETCONTEXT:
3147 return DefWindowProcW(hWnd, uMsg, wParam, (lParam & ~ISC_SHOWUIALL));
3148
3149 case WM_IME_NOTIFY:
3151 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
3152 return TRUE;
3153
3155 return TRUE;
3156
3157 case WM_IME_SYSTEM:
3159 {
3161 return TRUE;
3162 }
3163 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
3164
3165 default:
3166 {
3167 if (WM_USER_INIT <= uMsg && uMsg <= WM_USER_GOBACK)
3168 return ConIme_OnUser(hWnd, uMsg, wParam, lParam);
3169
3170 if (WM_ROUTE_KEYDOWN <= uMsg && uMsg <= WM_ROUTE_SYSDEADCHAR)
3171 {
3173 return TRUE;
3174 }
3175
3176 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
3177 }
3178 }
3179
3180 return 0;
3181}
3182
3185{
3186 BOOL bIsConImeOnSystemProcessEnabled = FALSE;
3187
3188 HKEY hKey;
3190 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Console",
3191 0, KEY_QUERY_VALUE, &hKey);
3192 if (error == ERROR_SUCCESS)
3193 {
3194 DWORD dwValue = FALSE, cbValue = sizeof(dwValue);
3195 error = RegQueryValueExW(hKey, L"EnableConImeOnSystemProcess", NULL, NULL,
3196 (PBYTE)&dwValue, &cbValue);
3197 if (error == ERROR_SUCCESS)
3198 bIsConImeOnSystemProcessEnabled = !!dwValue;
3200 }
3201
3202 return bIsConImeOnSystemProcessEnabled;
3203}
3204
3207{
3208 BOOL bIsConImeOnSystemProcessEnabled = IntIsConImeOnSystemProcessEnabled();
3209 if (!bIsConImeOnSystemProcessEnabled && IntIsLogOnSession())
3210 return FALSE;
3211
3212 const UINT cEntries = 10;
3214 if (!g_ppEntries)
3215 return FALSE;
3216
3218
3220
3221 // Open a startup synchronization event
3222 HANDLE hStartUpEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"ConsoleIME_StartUp_Event");
3223 if (!hStartUpEvent)
3224 {
3226 return FALSE;
3227 }
3228
3229 INT x, y, cx, cy, cxScreen, cyMenu;
3230 HWND hWnd;
3231
3232 // Register window class
3233 WNDCLASSEXW wc = { sizeof(wc) };
3235 wc.hInstance = hInstance;
3239 wc.lpszClassName = L"ConsoleIMEClass";
3240 ATOM atom = RegisterClassExW(&wc);
3241 if (!atom)
3242 goto Cleanup1;
3243
3244 // Create main window
3245 cxScreen = GetSystemMetrics(SM_CXSCREEN);
3246 cyMenu = GetSystemMetrics(SM_CYMENU);
3247 x = cxScreen - (cxScreen / 3);
3248 y = cyMenu;
3249 cx = cxScreen / 3;
3250 cy = 10 * cyMenu;
3251 hWnd = CreateWindowW(L"ConsoleIMEClass", L"", WS_OVERLAPPEDWINDOW,
3252 x, y, cx, cy, NULL, NULL, hInstance, NULL);
3253 if (!hWnd)
3254 goto Cleanup2;
3255
3256 // Console IME registration and threaded input synchronization
3259 {
3260 SetEvent(hStartUpEvent);
3261 CloseHandle(hStartUpEvent);
3262 return TRUE; // Success
3263 }
3264
3267
3268 if (hWnd)
3270
3271Cleanup2:
3272 if (atom)
3273 UnregisterClassW(L"ConsoleIMEClass", hInstance);
3274
3275Cleanup1:
3276 if (hStartUpEvent)
3277 {
3278 SetEvent(hStartUpEvent); // Set to release the waiting side even if it fails
3279 CloseHandle(hStartUpEvent);
3280 }
3281
3283 return FALSE; // Failed
3284}
3285
3286INT WINAPI
3287wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, INT nCmdShow)
3288{
3289 WCHAR szSysDir[MAX_PATH];
3290 if (GetSystemDirectoryW(szSysDir, _countof(szSysDir)))
3291 SetCurrentDirectoryW(szSysDir);
3292
3293 ImmDisableTextFrameService(0xFFFFFFFF);
3294
3296 {
3297 ERR("ConIme_InitInstance failed\n");
3299 return 0;
3300 }
3301
3302 MSG msg;
3303 _SEH2_TRY
3304 {
3305 // Main loop
3306 while (GetMessageW(&msg, NULL, 0, 0))
3307 {
3310 }
3311 }
3313 {
3314 ERR("Exception\n");
3315 msg.wParam = -1;
3316 }
3317 _SEH2_END;
3318
3321
3322 return (INT)msg.wParam;
3323}
#define msg(x)
Definition: auth_time.c:54
HWND hWnd
Definition: settings.c:17
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define IDI_MAINICON
Definition: resource.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define index(s, c)
Definition: various.h:29
#define ERR(fmt,...)
Definition: precomp.h:57
#define BACKGROUND_GREEN
Definition: blue.h:66
#define BACKGROUND_BLUE
Definition: blue.h:65
#define FOREGROUND_BLUE
Definition: blue.h:61
#define FOREGROUND_RED
Definition: blue.h:63
#define RegCloseKey(hKey)
Definition: registry.h:49
HINSTANCE hInstance
Definition: charmap.c:19
#define LANGID_KOREAN
Definition: cjkcode.h:53
#define LANGID_JAPANESE
Definition: cjkcode.h:52
#define LANGID_CHINESE_SIMPLIFIED
Definition: cjkcode.h:50
#define CP_CHINESE_SIMPLIFIED
Definition: cjkcode.h:23
#define CP_JAPANESE
Definition: cjkcode.h:21
#define CP_CHINESE_TRADITIONAL
Definition: cjkcode.h:24
#define CP_KOREAN
Definition: cjkcode.h:22
#define LANGID_CHINESE_TRADITIONAL
Definition: cjkcode.h:51
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define _FOREGROUND_WHITE
Definition: conime.c:41
void IntFillImeCandidatesCHT(PCONENTRY pEntry, PIMEDISPLAY pDisplay, UINT iCand)
Fills the status buffer with characters and attributes from the.
Definition: conime.c:464
void ConIme_OnEnd(HWND hwnd, UINT uMsg)
Terminate Console IME.
Definition: conime.c:286
void ConIme_OnChangeKeyboard(HWND hwnd, HANDLE hConsole, HKL hNewKL)
WM_USER_CHANGEKEYBOARD.
Definition: conime.c:2941
#define MAGIC_SEND_GUIDELINE
Definition: conime.c:37
BOOL IntFillImeDisplayJPN(PCONENTRY pEntry, PIMEDISPLAY pDisplay)
Converts the current Japanese IME status into a string for display (CHAR_INFO array).
Definition: conime.c:625
BOOL ConIme_UnInitEntry(HWND hwnd, PCONENTRY pEntry)
Frees the resources associated with the console entry.
Definition: conime.c:321
BOOL IntSendCandListJPNorKOR(HWND hwnd, HIMC hIMC, PCONENTRY pEntry, DWORD dwCandidates, BOOL bOpen)
Definition: conime.c:2341
LRESULT ConIme_OnInputLangChangeRequest(HWND hWnd, WPARAM wParam, LPARAM lParam)
WM_INPUTLANGCHANGEREQUEST.
Definition: conime.c:3069
void IntDoImeComp(HWND hwnd, DWORD dwFlags, WCHAR wch)
Definition: conime.c:1719
void ConIme_OnEnable(void)
WM_ENABLE.
Definition: conime.c:2878
BOOL IntFillImeDisplay(PCONENTRY pEntry, PIMEDISPLAY pDisplay)
Converts the current IME status into a string for display (CHAR_INFO array).
Definition: conime.c:829
BOOL IntFillImeDisplayCHS(PCONENTRY pEntry, PIMEDISPLAY pDisplay)
Converts the current Simplified Chinese IME status into a string for display (CHAR_INFO array).
Definition: conime.c:808
BOOL ConIme_OnImeSystem(HWND hwnd, WPARAM wParam, LPARAM lParam)
WM_IME_SYSTEM.
Definition: conime.c:2653
UINT IntFillImeCandidatesCHS(PCONENTRY pEntry, PIMEDISPLAY pDisplay, UINT cch)
Fills the status buffer with characters and attributes from the.
Definition: conime.c:755
BOOL IntIsConImeOnSystemProcessEnabled(VOID)
Is Console IME on system process enabled?
Definition: conime.c:3184
BOOL ConIme_SetCodePage(HWND hwnd, HANDLE hConsole, BOOL bOutput, WORD wCodePage)
WM_USER_SETCODEPAGE.
Definition: conime.c:2638
BOOL IntSendCandListCHT(HWND hwnd, HIMC hIMC, PCONENTRY pEntry, DWORD dwCandidates, BOOL bOpen)
Definition: conime.c:2055
UINT g_cEntries
Definition: conime.c:47
void IntSendConversionStatus(HWND hwnd)
Definition: conime.c:936
BOOL ConIme_OnSwitchIme(HWND hwnd, HANDLE hConsole, HKL hKL)
WM_USER_SWITCHIME.
Definition: conime.c:959
BOOL ConIme_OnNotifyGuideLine(HWND hWnd)
Handles guideline notifications (error messages, etc.) from IME.
Definition: conime.c:2538
BOOL IntGetImeLayoutText(PCONENTRY pEntry)
Gets the name of the current keyboard layout or IME and stores it in the entry.
Definition: conime.c:374
#define MAGIC_SEND_IMESYSTEM
Definition: conime.c:39
BOOL IntCloseCandsJPNorKOR(HWND hwnd, HIMC hIMC, PCONENTRY pEntry, DWORD dwCandidates)
Sends the IME candidate list for Japanese/Korean.
Definition: conime.c:2697
void IntSendConversionStatusJPNorKOR(HWND hwnd, PCONENTRY pEntry)
Definition: conime.c:907
#define PREFIX_LEN
BOOL ConIme_OnNotifySetOpenStatus(HWND hwndTarget)
IMN_SETOPENSTATUS.
Definition: conime.c:848
BOOL ConIme_OnImeNotify(HWND hWnd, WPARAM wParam, LPARAM lParam)
WM_IME_NOTIFY.
Definition: conime.c:2780
UINT IntFillImeModeCHT(PCONENTRY pEntry, PIMEDISPLAY pDisplay, INT cch)
Builds a buffer for displaying the Traditional Chinese IME mode.
Definition: conime.c:483
#define MAGIC_SEND_IMEDISPLAY
Definition: conime.c:36
#define _BACKGROUND_WHITE
Definition: conime.c:42
void ConIme_OnImeStartComposition(HWND hwnd)
WM_IME_STARTCOMPOSITION.
Definition: conime.c:2912
void ConIme_OnImeEndComposition(HWND hWnd)
WM_IME_ENDCOMPOSITION.
Definition: conime.c:2921
BOOL ConIme_SimulateHotKey(HWND hwnd, WPARAM wParam, LPARAM lParam)
WM_USER_SIMHOTKEY.
Definition: conime.c:2871
UINT IntFormatCandLineCHS(PCANDIDATELIST pCandList, PWSTR pszCandStrDest, PBYTE pbAttrsDest, UINT width, UINT labelWidth, PCONENTRY pEntry)
Definition: conime.c:1981
UINT IntGetCharDisplayWidth(WCHAR wch)
Definition: conime.c:547
BOOL IntFillImeDisplayKOR(PCONENTRY pEntry, PIMEDISPLAY pDisplay)
Converts the current Korean IME status into a string for display (CHAR_INFO array).
Definition: conime.c:702
BOOL IntSendDataToConsole(HWND hwndConsole, HWND hwndSender, PCOPYDATASTRUCT pCopyData)
Definition: conime.c:140
void IntDoImeCompCHT(HWND hWnd, PCONENTRY pEntry, DWORD dwFlags)
Processes the input composition status of the Chinese (Traditional) IME and.
Definition: conime.c:1482
BOOL ConIme_InitEntry(HWND hwnd, HANDLE hConsole, HWND hwndConsole)
Initializes and allocates a CONENTRY structure for the new console connection.
Definition: conime.c:1147
BOOL IntIsDoubleWidthChar(WCHAR wch)
Determines if a Unicode character should be rendered as "Double Width" (2 columns).
Definition: conime.c:87
BOOL IntIsImeOpen(HIMC hIMC, PCONENTRY pEntry)
Definition: conime.c:444
UINT IntFormatCandLineCHT(PCANDIDATELIST pCandList, PWSTR pszCandStrDest, PBYTE pbAttrsDest, UINT width, UINT labelWidth, PCONENTRY pEntry)
Definition: conime.c:1888
BOOL ConIme_OnGo(HWND hwnd, HANDLE hConsole, HKL hKL, INT iDirection)
Handles keyboard layout switch requests.
Definition: conime.c:1022
BOOL ConIme_OnInit(HWND hwnd, HANDLE hConsole, HWND hwndConsole)
WM_USER_INIT.
Definition: conime.c:1231
BOOL ConIme_SendImeStatus(HWND hWnd)
WM_USER_SENDIMESTATUS.
Definition: conime.c:1096
UINT IntGetCharInfoWidth(PCHAR_INFO pCharInfo, UINT cch)
Definition: conime.c:539
#define MAGIC_SEND_CANDLIST
Definition: conime.c:38
void IntDoImeCompCHS(HWND hwnd, PCONENTRY pEntry, DWORD dwFlags)
Notifies the input composition status of the Chinese (Simplified) IME to the console.
Definition: conime.c:1368
#define MAGIC_SEND_COMPSTR
Definition: conime.c:35
void IntFormatNumber(PWSTR pszBuffer, UINT value, UINT width)
Definition: conime.c:54
LRESULT ConIme_OnRoute(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
WM_ROUTE_...
Definition: conime.c:2829
BOOL IntFillImeDisplayCHT(PCONENTRY pEntry, PIMEDISPLAY pDisplay)
Converts the current Traditional Chinese IME status into a string for.
Definition: conime.c:588
UINT IntFormatCandLineJPNorKOR(PCANDIDATELIST pCandList, PWSTR pszCandStrDest, PBYTE pbAttrsDest, UINT width, UINT labelWidth, PCONENTRY pEntry, BOOL bIsCode)
Definition: conime.c:1758
#define COLUMN_COUNT
void IntFreeConsoleEntries(void)
Definition: conime.c:189
INT IntGetStringWidth(PCWSTR pch)
Definition: conime.c:132
void IntDoImeCompJPN(HWND hwnd, PCONENTRY pEntry, DWORD dwFlags)
Processes Japanese IME Composition and Result strings.
Definition: conime.c:1265
BOOL ConIme_InitInstance(HINSTANCE hInstance)
Initialize Console IME instance.
Definition: conime.c:3206
BOOL ConIme_OnNotifyCloseCandidate(HWND hwnd, DWORD dwCandidates)
IMN_CLOSECANDIDATE.
Definition: conime.c:2745
BOOL IntSetImeState(HWND hwnd, HANDLE hConsole, DWORD dwConversion)
WM_USER_SETIMESTATE.
Definition: conime.c:2599
BOOL ConIme_OnInputLangChange(HWND hwnd, WPARAM wParam, HKL hKL)
Definition: conime.c:1131
HIMC g_hOldIMC
Definition: conime.c:48
BOOL IntSendCandListCHS(HWND hwnd, HIMC hIMC, PCONENTRY pEntry, DWORD dwCandidates, BOOL bOpen)
Definition: conime.c:2197
LRESULT CALLBACK ConIme_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
The main window procedure for the Console IME.
Definition: conime.c:3084
BOOL g_bDisabled
Definition: conime.c:51
BOOL ConIme_OnNotifyOpenCandidate(HWND hwnd, LPARAM lParam, BOOL bOpen)
When the conversion candidate window opens, invoke the language-specific candidate.
Definition: conime.c:2495
static void IntSetCurrentConsole(HANDLE hConsole)
Definition: conime.c:255
BOOL ConIme_OnDeactivate(HWND hwnd, HANDLE hConsole)
WM_USER_DEACTIVATE.
Definition: conime.c:991
CRITICAL_SECTION g_csLock
Definition: conime.c:52
BOOL ConIme_SetScreenSize(HWND hwnd, HANDLE hConsole, COORD ScreenSize)
WM_USER_SETSCREENSIZE.
Definition: conime.c:1011
BOOL ConIme_OnNotifyChangeCandidate(HWND hwnd, LPARAM lParam)
Definition: conime.c:2532
PCONENTRY * g_ppEntries
Definition: conime.c:46
void IntFillImeCompStrCHSorCHT(PCONENTRY pEntry, PIMEDISPLAY pDisplay, UINT cch)
Definition: conime.c:515
BOOL IntGrowEntries(void)
Definition: conime.c:300
BOOL IntIsLogOnSession(void)
Determines whether the current process is an interactive logon session (such as Winlogon)
Definition: conime.c:165
BOOL ConIme_OnCreate(HWND hwnd)
WM_CREATE.
Definition: conime.c:1253
BOOL g_bIsLogOnSession
Definition: conime.c:50
void IntSendConversionStatusCHS(HWND hwnd, PCONENTRY pEntry)
Definition: conime.c:920
BOOL ConIme_OnUnInit(HWND hwnd, HANDLE hConsole)
WM_USER_UNINIT.
Definition: conime.c:1217
INT IntFillImeModeCHS(PCONENTRY pEntry, PIMEDISPLAY pDisplay, UINT cch)
Builds a buffer for displaying the Simplified Chinese IME mode.
Definition: conime.c:712
DWORD IntGetImeState(HWND hWnd, HANDLE hConsole)
WM_USER_GETIMESTATE.
Definition: conime.c:2582
INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, INT nCmdShow)
Definition: conime.c:3287
void IntCopyUnicodeToCharInfo(PCHAR_INFO *ppDest, PCWSTR pszSrc)
Definition: conime.c:609
void IntDoImeCompKOR(HWND hwnd, PCONENTRY pEntry, DWORD dwFlags, WCHAR wch)
Processes the Korean IME input composition state and notifies the console.
Definition: conime.c:1604
void ConIme_OnDisable(void)
WM_ENABLE.
Definition: conime.c:2900
void ConIme_OnImeComposition(HWND hwnd, WPARAM wParam, LPARAM lParam)
WM_IME_COMPOSITION.
Definition: conime.c:1743
LRESULT ConIme_OnUser(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
(WM_USER + ...)
Definition: conime.c:3025
void IntSendConversionStatusCHT(HWND hwnd, PCONENTRY pEntry)
Definition: conime.c:891
BOOL ConIme_OnKeyChar(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: conime.c:2819
BOOL IntCloseCandsCHS(HWND hwnd, HIMC hIMC, PCONENTRY pEntry, DWORD dwCandidates)
Sends the IME candidate list for Simplified Chinese (CHS).
Definition: conime.c:2716
HANDLE g_hConsole
Definition: conime.c:45
PCONENTRY IntFindConsoleEntry(HANDLE hConsole)
Finds the CONENTRY structure corresponding to the specified console handle.
Definition: conime.c:262
DWORD g_dwAttachToThreadId
Definition: conime.c:49
BOOL IntCloseCandsCHT(HWND hwnd, HIMC hIMC, PCONENTRY pEntry, DWORD dwCandidates)
Sends candidate list for Traditional Chinese (CHT).
Definition: conime.c:2668
UINT IntFillImeSpaceCHSorCHT(PCONENTRY pEntry, PIMEDISPLAY pDisplay, UINT cch)
Adjusts the width of the status display and pads it with spaces.
Definition: conime.c:553
#define WM_USER_SWITCHIME
Definition: conime.h:12
#define WM_USER_GONEXT
Definition: conime.h:22
#define WM_USER_GETIMESTATE
Definition: conime.h:15
#define WM_USER_SETCODEPAGE
Definition: conime.h:20
#define IMEDISPLAY_MAX_X
Definition: conime.h:37
#define WM_ROUTE_CHAR
Definition: conime.h:28
#define WM_ROUTE
Definition: conime.h:25
#define WM_USER_GOBACK
Definition: conime.h:23
#define WM_ROUTE_SYSKEYUP
Definition: conime.h:31
struct tagIMEDISPLAY IMEDISPLAY
#define WM_USER_SETIMESTATE
Definition: conime.h:16
#define _IME_CMODE_OPEN
Definition: conime.h:55
#define _IME_CMODE_DEACTIVATE
Definition: conime.h:56
#define WM_USER_GO
Definition: conime.h:21
#define WM_USER_SETSCREENSIZE
Definition: conime.h:17
#define WM_ROUTE_KEYDOWN
Definition: conime.h:26
struct tagCOMPSTRINFO COMPSTRINFO
#define WM_ROUTE_SYSDEADCHAR
Definition: conime.h:33
#define WM_USER_INIT
Definition: conime.h:10
#define WM_USER_UNINIT
Definition: conime.h:11
#define WM_USER_DEACTIVATE
Definition: conime.h:13
#define WM_USER_CHANGEKEYBOARD
Definition: conime.h:19
#define WM_ROUTE_KEYUP
Definition: conime.h:27
#define MAX_CANDLIST
Definition: conime.h:59
#define WM_USER_SIMHOTKEY
Definition: conime.h:14
struct tagCONENTRY * PCONENTRY
#define WM_ROUTE_SYSCHAR
Definition: conime.h:32
#define WM_ROUTE_SYSKEYDOWN
Definition: conime.h:30
#define _GCS_SINGLECHAR
Definition: conime.h:35
#define WM_USER_SENDIMESTATUS
Definition: conime.h:18
BOOL WINAPI ImmDisableTextFrameService(_In_ DWORD dwThreadId)
Definition: ctf.c:1088
#define ERROR_SUCCESS
Definition: deptool.c:10
WORD ATOM
Definition: dimm.idl:113
DWORD HIMC
Definition: dimm.idl:75
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define CloseHandle
Definition: compat.h:739
#define CP_ACP
Definition: compat.h:109
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
BOOL WINAPI DECLSPEC_HOTPATCH RegisterConsoleIME(_In_ HWND hWnd, _Out_opt_ LPDWORD pdwAttachToThreadId)
Definition: console.c:3133
BOOL WINAPI DECLSPEC_HOTPATCH UnregisterConsoleIME(VOID)
Definition: console.c:3166
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2168
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2232
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
static wchar_t *__cdecl wmemset(wchar_t *s, wchar_t c, size_t n)
Definition: wchar.h:77
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
#define FillMemory(BUF, SIZ, MASK)
Definition: strucsup.c:31
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint coord
Definition: glext.h:9511
GLuint index
Definition: glext.h:6031
GLuint divisor
Definition: glext.h:6313
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
DWORD WINAPI ImmCallImeConsoleIME(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _Out_ LPUINT puVK)
Definition: keymsg.c:1188
#define IMS_CONSOLEIME_1B
Definition: imm32_undoc.h:50
BOOL WINAPI ImmSetActiveContextConsoleIME(_In_ HWND hwnd, _In_ BOOL fFlag)
Definition: imm.c:1271
#define IS_IME_HKL(hKL)
Definition: imm32_undoc.h:21
#define WM_IME_SYSTEM
Definition: imm32_undoc.h:32
#define IMS_CONSOLEIME_1A
Definition: imm32_undoc.h:49
HIMC WINAPI ImmAssociateContext(_In_ HWND hWnd, _In_opt_ HIMC hIMC)
Definition: imm.c:500
#define IME_CMODE_KATAKANA
Definition: imm.h:343
#define IME_CMODE_ROMAN
Definition: imm.h:346
#define IME_PROP_CANDLIST_START_FROM_1
Definition: imm.h:248
BOOL WINAPI ImmGetConversionStatus(_In_ HIMC hIMC, _Out_opt_ LPDWORD lpfdwConversion, _Out_opt_ LPDWORD lpfdwSentence)
Definition: ime.c:1501
#define IMN_GUIDELINE
Definition: imm.h:384
BOOL WINAPI ImmSetConversionStatus(_In_ HIMC hIMC, _In_ DWORD fdwConversion, _In_ DWORD fdwSentence)
Definition: ime.c:1534
#define IME_CMODE_NATIVE
Definition: imm.h:337
DWORD WINAPI ImmGetGuideLineW(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_writes_bytes_opt_(dwBufLen) LPWSTR lpBuf, _In_ DWORD dwBufLen)
Definition: guideline.c:209
#define GCS_COMPATTR
Definition: imm.h:228
DWORD WINAPI ImmGetCandidateListW(_In_ HIMC hIMC, _In_ DWORD deIndex, _Out_writes_bytes_opt_(dwBufLen) LPCANDIDATELIST lpCandList, _In_ DWORD dwBufLen)
Definition: candidate.c:383
UINT WINAPI ImmGetIMEFileNameW(_In_ HKL hKL, _Out_writes_opt_(uBufLen) LPWSTR lpszFileName, _In_ UINT uBufLen)
Definition: ime.c:732
#define IMN_CLOSECANDIDATE
Definition: imm.h:375
#define GCS_RESULTSTR
Definition: imm.h:234
BOOL WINAPI ImmSimulateHotKey(_In_ HWND hWnd, _In_ DWORD dwHotKeyID)
Definition: keymsg.c:675
HIMC WINAPI ImmGetContext(_In_ HWND hWnd)
Definition: imm.c:1065
#define IMN_CHANGECANDIDATE
Definition: imm.h:374
#define IGP_PROPERTY
Definition: imm.h:300
LRESULT WINAPI ImmEscapeW(_In_ HKL hKL, _In_ HIMC hIMC, _In_ UINT uSubFunc, _Inout_opt_ LPVOID lpData)
Definition: ime.c:913
HIMC WINAPI ImmCreateContext(VOID)
Definition: imm.c:606
#define GGL_STRING
Definition: imm.h:270
#define IMN_OPENCANDIDATE
Definition: imm.h:376
DWORD WINAPI ImmGetProperty(_In_ HKL hKL, _In_ DWORD fdwIndex)
Definition: ime.c:767
BOOL WINAPI ImmReleaseContext(_In_ HWND hWnd, _In_ HIMC hIMC)
Definition: imm.c:1109
BOOL WINAPI ImmGetOpenStatus(_In_ HIMC hIMC)
Definition: ime.c:996
#define GCS_COMPSTR
Definition: imm.h:227
#define IMN_OPENSTATUSWINDOW
Definition: imm.h:373
#define IME_SMODE_PLAURALCLAUSE
Definition: imm.h:357
#define GCS_CURSORPOS
Definition: imm.h:230
#define IME_SMODE_SINGLECONVERT
Definition: imm.h:358
#define ISC_SHOWUIALL
Definition: imm.h:175
#define IME_ESC_IME_NAME
Definition: imm.h:419
LONG WINAPI ImmGetCompositionStringW(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_writes_bytes_opt_(dwBufLen) LPVOID lpBuf, _In_ DWORD dwBufLen)
Definition: compstr.c:908
BOOL WINAPI ImmIsIME(_In_ HKL hKL)
Definition: ime.c:429
BOOL WINAPI ImmDestroyContext(_In_ HIMC hIMC)
Definition: imm.c:931
#define IME_SMODE_PHRASEPREDICT
Definition: imm.h:360
#define IMN_SETOPENSTATUS
Definition: imm.h:379
#define IME_CAND_CODE
Definition: imm.h:366
BOOL WINAPI ImmSetOpenStatus(_In_ HIMC hIMC, _In_ BOOL fOpen)
Definition: ime.c:1020
#define IME_CMODE_FULLSHAPE
Definition: imm.h:345
#define IME_SMODE_AUTOMATIC
Definition: imm.h:359
#define IMN_SETCONVERSIONMODE
Definition: imm.h:377
BOOL WINAPI ImmNotifyIME(_In_ HIMC hIMC, _In_ DWORD dwAction, _In_ DWORD dwIndex, _In_ DWORD_PTR dwValue)
Definition: ime.c:458
BOOL WINAPI ImmTranslateMessage(_In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wParam, _In_ LPARAM lKeyData)
Definition: keymsg.c:1020
#define NI_SETCANDIDATE_PAGESIZE
Definition: immdev.h:383
#define NI_SETCANDIDATE_PAGESTART
Definition: immdev.h:382
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
static const int digits[]
Definition: decode.c:71
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
USHORT LANGID
Definition: mui.h:9
if(dx< 0)
Definition: linetemp.h:194
#define ZeroMemory
Definition: minwinbase.h:31
#define LPTR
Definition: minwinbase.h:93
#define CopyMemory
Definition: minwinbase.h:29
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
#define error(str)
Definition: mkdosfs.c:1605
#define pch(ap)
Definition: match.c:418
#define for
Definition: utility.h:88
#define min(a, b)
Definition: monoChain.cc:55
UINT_PTR HKL
Definition: msctf.idl:125
unsigned int UINT
Definition: ndis.h:50
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:145
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define DWORD
Definition: nt_native.h:44
CONST WCHAR * PCWCH
Definition: ntbasedef.h:423
#define UNICODE_NULL
#define MAXDWORD
NTSTATUS NTAPI NtOpenProcessToken(IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT PHANDLE TokenHandle)
Definition: security.c:350
#define LOWORD(l)
Definition: pedump.c:82
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
BYTE * PBYTE
Definition: pedump.c:66
long LONG
Definition: pedump.c:60
#define INT
Definition: polytest.cpp:20
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
_In_opt_ _In_opt_ _In_ _In_ DWORD cbData
Definition: shlwapi.h:761
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define offsetof(TYPE, MEMBER)
_In_ UINT _In_ UINT cch
Definition: shellapi.h:432
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
WCHAR UnicodeChar
Definition: wincon.h:214
WORD Attributes
Definition: wincon.h:217
union _CHAR_INFO::@3473 Char
LUID AuthenticationId
Definition: setypes.h:1099
LPCWSTR lpszClassName
Definition: winuser.h:3328
HBRUSH hbrBackground
Definition: winuser.h:3326
WNDPROC lpfnWndProc
Definition: winuser.h:3320
HCURSOR hCursor
Definition: winuser.h:3325
HINSTANCE hInstance
Definition: winuser.h:3323
HICON hIcon
Definition: winuser.h:3324
DWORD dwCount
Definition: imm.h:59
DWORD dwStyle
Definition: imm.h:58
DWORD dwOffset[ANYSIZE_ARRAY]
Definition: imm.h:63
DWORD dwSelection
Definition: imm.h:60
WCHAR szCandStr[ANYSIZE_ARRAY]
Definition: conime.h:79
DWORD dwAttrsOffset
Definition: conime.h:78
WORD awAttrColor[MAX_ATTR_COLORS]
Definition: conime.h:72
DWORD dwCompStrLen
Definition: conime.h:68
DWORD dwSize
Definition: conime.h:65
DWORD dwCompStrOffset
Definition: conime.h:69
DWORD dwCompAttrLen
Definition: conime.h:66
DWORD dwCompAttrOffset
Definition: conime.h:67
DWORD dwResultStrOffset
Definition: conime.h:71
DWORD dwResultStrLen
Definition: conime.h:70
Definition: blue.h:25
ULONG_PTR dwData
Definition: winuser.h:3103
UINT uCharInfoLen
Definition: conime.h:42
CHAR_INFO CharInfo[IMEDISPLAY_MAX_X]
Definition: conime.h:44
BOOL bFlag
Definition: conime.h:43
DWORD dwConversion
Definition: conime.h:51
HKL hKL
Definition: conime.h:50
#define max(a, b)
Definition: svc.c:63
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: synch.c:618
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:687
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
Queries a specific type of information in regard of an access token based upon the information class....
Definition: tokencls.c:473
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define MAKEWORD(a, b)
Definition: typedefs.h:248
int32_t INT
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
#define IPHK_HOTKEY
Definition: undocuser.h:140
#define IPHK_PROCESSBYIME
Definition: undocuser.h:141
#define IPHK_CHECKCTRL
Definition: undocuser.h:142
Definition: pdh_main.c:96
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define EVENT_MODIFY_STATE
Definition: winbase.h:165
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define COMMON_LVB_UNDERSCORE
Definition: wincon.h:82
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define WINAPI
Definition: msvc.h:6
HGDIOBJ WINAPI GetStockObject(_In_ int)
_In_ UINT _In_ UINT cEntries
Definition: wingdi.h:4067
#define BLACK_BRUSH
Definition: wingdi.h:896
_In_ UINT iStart
Definition: wingdi.h:4066
#define CP_OEMCP
Definition: winnls.h:249
_In_ DWORD _In_ int cchSrc
Definition: winnls.h:1264
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
BOOL WINAPI GetKeyboardLayoutNameW(_Out_writes_(KL_NAMELENGTH) LPWSTR)
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define WM_CLOSE
Definition: winuser.h:1649
#define VK_KANA
Definition: winuser.h:2243
#define WM_ENABLE
Definition: winuser.h:1643
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define WM_KEYUP
Definition: winuser.h:1744
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define WM_IME_NOTIFY
Definition: winuser.h:1858
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_CREATE
Definition: winuser.h:1636
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define IDC_ARROW
Definition: winuser.h:695
#define SM_CYMENU
Definition: winuser.h:987
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2474
LRESULT WINAPI SendMessageTimeoutW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM, _In_ UINT, _In_ UINT, _Out_opt_ PDWORD_PTR)
#define WM_IME_SETCONTEXT
Definition: winuser.h:1857
#define KF_UP
Definition: winuser.h:2487
#define WM_SYSCHAR
Definition: winuser.h:1749
#define WM_SYSDEADCHAR
Definition: winuser.h:1750
UINT WINAPI GetKeyboardLayoutList(_In_ int nBuff, _Out_writes_to_opt_(nBuff, return) HKL FAR *lpList)
#define WM_QUERYENDSESSION
Definition: winuser.h:1650
ATOM WINAPI RegisterClassExW(_In_ CONST WNDCLASSEXW *)
#define WM_COPYDATA
Definition: winuser.h:1692
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
#define WM_SYSKEYUP
Definition: winuser.h:1748
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4418
#define WM_IME_COMPOSITIONFULL
Definition: winuser.h:1860
#define WM_CHAR
Definition: winuser.h:1745
BOOL WINAPI IsWindowEnabled(_In_ HWND)
#define SMTO_ABORTIFHUNG
Definition: winuser.h:1234
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
#define WM_USER
Definition: winuser.h:1923
#define WM_DESTROY
Definition: winuser.h:1637
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define SM_CXSCREEN
Definition: winuser.h:970
#define WM_KEYDOWN
Definition: winuser.h:1743
#define WM_ENDSESSION
Definition: winuser.h:1655
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
HKL WINAPI ActivateKeyboardLayout(_In_ HKL, _In_ UINT)
BOOL WINAPI DestroyWindow(_In_ HWND)
#define WM_DEADCHAR
Definition: winuser.h:1746
HICON WINAPI LoadIconW(_In_opt_ HINSTANCE hInstance, _In_ LPCWSTR lpIconName)
Definition: cursoricon.c:2444
int WINAPI GetSystemMetrics(_In_ int)
#define WM_SYSKEYDOWN
Definition: winuser.h:1747
SHORT WINAPI GetKeyState(_In_ int)
#define TOKEN_QUERY
Definition: setypes.h:940
@ TokenStatistics
Definition: setypes.h:987
#define SYSTEM_LUID
Definition: setypes.h:700
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193