Reactos
1/*
2 * PROJECT: ReactOS msctfime.ime
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: User Interface of msctfime.ime
5 * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "msctfime.h"
9
10WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
11
12/***********************************************************************/
13
14UINT WM_MSIME_SERVICE = 0;
15UINT WM_MSIME_UIREADY = 0;
16UINT WM_MSIME_RECONVERTREQUEST = 0;
17UINT WM_MSIME_RECONVERT = 0;
18UINT WM_MSIME_DOCUMENTFEED = 0;
19UINT WM_MSIME_QUERYPOSITION = 0;
20UINT WM_MSIME_MODEBIAS = 0;
21UINT WM_MSIME_SHOWIMEPAD = 0;
22UINT WM_MSIME_MOUSE = 0;
23UINT WM_MSIME_KEYMAP = 0;
24
25/// @implemented
26BOOL IsMsImeMessage(_In_ UINT uMsg)
27{
28 return (uMsg == WM_MSIME_SERVICE ||
29 uMsg == WM_MSIME_UIREADY ||
30 uMsg == WM_MSIME_RECONVERTREQUEST ||
31 uMsg == WM_MSIME_RECONVERT ||
32 uMsg == WM_MSIME_DOCUMENTFEED ||
33 uMsg == WM_MSIME_QUERYPOSITION ||
34 uMsg == WM_MSIME_MODEBIAS ||
35 uMsg == WM_MSIME_SHOWIMEPAD ||
36 uMsg == WM_MSIME_MOUSE ||
37 uMsg == WM_MSIME_KEYMAP);
38}
39
40/// @implemented
41BOOL RegisterMSIMEMessage(VOID)
42{
43 // Using ANSI (A) version here can reduce binary size.
44 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
45 WM_MSIME_UIREADY = RegisterWindowMessageA("MSIMEUIReady");
46 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
47 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
48 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
49 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
50 WM_MSIME_MODEBIAS = RegisterWindowMessageA("MSIMEModeBias");
51 WM_MSIME_SHOWIMEPAD = RegisterWindowMessageA("MSIMEShowImePad");
52 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
53 WM_MSIME_KEYMAP = RegisterWindowMessageA("MSIMEKeyMap");
54 return (WM_MSIME_SERVICE &&
55 WM_MSIME_UIREADY &&
56 WM_MSIME_RECONVERTREQUEST &&
57 WM_MSIME_RECONVERT &&
58 WM_MSIME_DOCUMENTFEED &&
59 WM_MSIME_QUERYPOSITION &&
60 WM_MSIME_MODEBIAS &&
61 WM_MSIME_SHOWIMEPAD &&
62 WM_MSIME_MOUSE &&
63 WM_MSIME_KEYMAP);
64}
65
66/***********************************************************************/
67
68/// @implemented
69CDefCompFrameGripper::CDefCompFrameGripper(
70 CDefCompFrameWindow *pDefCompFrameWindow,
71 LPCRECT prc,
72 DWORD style) : CUIFGripper(pDefCompFrameWindow, prc, style)
73{
74 m_pDefCompFrameWindow = pDefCompFrameWindow;
75}
76
77/***********************************************************************/
78
79/// @implemented
80CCompFinalizeButton::CCompFinalizeButton(
81 CCompFrameWindow *pParent,
82 DWORD nObjectID,
83 LPCRECT prc,
84 DWORD style,
85 DWORD dwButtonFlags,
86 LPCWSTR pszText)
87 : CUIFToolbarButton(pParent, nObjectID, prc, style, dwButtonFlags, pszText)
88{
89 m_pCompFrameWindow = pParent;
90}
91
92/// @implemented
93CCompFinalizeButton::~CCompFinalizeButton()
94{
95 HICON hIcon = CUIFToolbarButton::GetIcon();
96 if (hIcon)
97 {
98 ::DestroyIcon(hIcon);
99 CUIFToolbarButton::SetIcon(NULL);
100 }
101}
102
103/// @implemented
104void CCompFinalizeButton::OnLeftClick()
105{
106 HIMC hIMC = m_pCompFrameWindow->m_hIMC;
107 if (hIMC)
108 ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
109}
110
111/***********************************************************************/
112
113/// @implemented
114CCompFrameWindow::CCompFrameWindow(HIMC hIMC, DWORD style)
115 : CUIFWindow(g_hInst, style)
116{
117 m_hIMC = hIMC;
118}
119
120/***********************************************************************/
121
122/// @implemented
123CCompButtonFrameWindow::CCompButtonFrameWindow(HIMC hIMC, DWORD style)
124 : CCompFrameWindow(hIMC, style)
125{
126}
127
128/// @implemented
129void CCompButtonFrameWindow::Init()
130{
131 if (m_pFinalizeButton)
132 return;
133
134 RECT rc = { 0, 0, 0, 0 };
135 m_pFinalizeButton = new(cicNoThrow) CCompFinalizeButton(this, 0, &rc, 0, 0x10000, NULL);
136
137 m_pFinalizeButton->Initialize();
138 m_pFinalizeButton->Init();
139
140 HICON hIcon = (HICON)::LoadImageW(g_hInst, MAKEINTRESOURCEW(IDI_DOWN), IMAGE_ICON, 16, 16, 0);
141 m_pFinalizeButton->SetIcon(hIcon);
142
143 WCHAR szText[256];
144 LoadStringW(g_hInst, IDS_FINALIZE_STRING, szText, _countof(szText));
145 m_pFinalizeButton->SetToolTip(szText);
146
147 AddUIObj(m_pFinalizeButton);
148}
149
150/// @implemented
151void CCompButtonFrameWindow::MoveShow(LONG x, LONG y, BOOL bShow)
152{
153 INT nWidth = m_Margins.cxRightWidth + m_Margins.cxLeftWidth + 18;
154 INT nHeight = m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 18;
155 Move(x, y, nWidth + 4, nHeight + 4);
156
157 if (m_pFinalizeButton)
158 {
159 RECT rc = { 1, 1, nWidth + 1, nHeight + 1 };
160 m_pFinalizeButton->SetRect(&rc);
161 }
162
163 Show(bShow);
164}
165
166/// @implemented
167STDMETHODIMP_(void) CCompButtonFrameWindow::OnCreate(HWND hWnd)
168{
169 ::SetWindowTheme(hWnd, L"TOOLBAR", NULL);
170
171 ZeroMemory(&m_Margins, sizeof(m_Margins));
172
173 CUIFTheme theme;
174 theme.m_hTheme = NULL;
175 theme.m_iPartId = 1;
176 theme.m_iStateId = 0;
177 theme.m_pszClassList = L"TOOLBAR";
178 if (SUCCEEDED(theme.InternalOpenThemeData(hWnd)))
179 theme.GetThemeMargins(NULL, 1, 3602, NULL, &m_Margins);
180}
181
182/***********************************************************************/
183
184/// @implemented
185CDefCompFrameWindow::CDefCompFrameWindow(HIMC hIMC, DWORD style)
186 : CCompFrameWindow(hIMC, style)
187{
188 LoadPosition();
189 m_iPartId = 1;
190 m_iStateId = 1;
191 m_pszClassList = L"TASKBAR";
192}
193
194/// @implemented
195CDefCompFrameWindow::~CDefCompFrameWindow()
196{
197 SavePosition();
198}
199
200/// @implemented
201void CDefCompFrameWindow::Init()
202{
203 RECT rc;
204
205 if (!m_pGripper)
206 {
207 ZeroMemory(&rc, sizeof(rc));
208 m_pGripper = new(cicNoThrow) CDefCompFrameGripper(this, &rc, 0);
209 m_pGripper->Initialize();
210 AddUIObj(m_pGripper);
211 }
212
213 if (!m_pFinalizeButton)
214 {
215 ZeroMemory(&rc, sizeof(rc));
216 m_pFinalizeButton = new(cicNoThrow) CCompFinalizeButton(this, 0, &rc, 0, 0x10000, NULL);
217 m_pFinalizeButton->Initialize();
218 m_pFinalizeButton->Init();
219
220 HICON hIcon = (HICON)LoadImageW(g_hInst, MAKEINTRESOURCEW(IDI_DOWN), IMAGE_ICON, 16, 16, 0);
221 m_pFinalizeButton->SetIcon(hIcon);
222
223 WCHAR szText[256];
224 ::LoadStringW(g_hInst, IDS_FINALIZE_STRING, szText, _countof(szText));
225 SetToolTip(szText);
226
227 AddUIObj(m_pFinalizeButton);
228 }
229}
230
231/// @implemented
232INT CDefCompFrameWindow::GetGripperWidth()
233{
234 if (!m_pGripper || FAILED(m_pGripper->EnsureThemeData(m_hWnd)))
235 return 5;
236
237 INT ret = -1;
238 HDC hDC = ::GetDC(m_hWnd);
239 SIZE partSize;
240 if (SUCCEEDED(m_pGripper->GetThemePartSize(hDC, 1, 0, TS_TRUE, &partSize)))
241 ret = partSize.cx + 4;
242
243 ::ReleaseDC(m_hWnd, hDC);
244
245 return ((ret < 0) ? 5 : ret);
246}
247
248/// @implemented
249void CDefCompFrameWindow::MyScreenToClient(LPPOINT ppt, LPRECT prc)
250{
251 if (ppt)
252 ::ScreenToClient(m_hWnd, ppt);
253
254 if (prc)
255 {
256 ::ScreenToClient(m_hWnd, (LPPOINT)prc);
257 ::ScreenToClient(m_hWnd, (LPPOINT)&prc->right);
258 }
259}
260
261/// @implemented
262void CDefCompFrameWindow::SetCompStrRect(INT nWidth, INT nHeight, BOOL bShow)
263{
264 INT GripperWidth = GetGripperWidth();
265
266 RECT rc;
267 ::GetWindowRect(m_hWnd, &rc);
268
269 Move(rc.left, rc.top, GripperWidth + nWidth + 24, nHeight + 10);
270
271 if (m_pGripper)
272 {
273 rc = { 2, 3, GripperWidth + 2, nHeight + 7 };
274 m_pGripper->SetRect(&rc);
275 }
276
277 if (m_pFinalizeButton)
278 {
279 rc = {
280 GripperWidth + nWidth + 4,
281 3,
282 m_Margins.cxLeftWidth + m_Margins.cxRightWidth + GripperWidth + nWidth + 22,
283 m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 21
284 };
285 m_pFinalizeButton->SetRect(&rc);
286 }
287
288 Show(bShow);
289
290 ::MoveWindow(m_hwndCompStr, GripperWidth + 2, 7, nWidth, nHeight, TRUE);
291 ::ShowWindow(m_hwndCompStr, (bShow ? SW_SHOWNOACTIVATE : SW_HIDE));
292}
293
294/// @implemented
295void CDefCompFrameWindow::LoadPosition()
296{
297 DWORD x = 0, y = 0;
298
299 LSTATUS error;
300 CicRegKey regKey;
301 error = regKey.Open(HKEY_CURRENT_USER,
302 TEXT("SOFTWARE\\Microsoft\\CTF\\CUAS\\DefaultCompositionWindow"));
303 if (error == ERROR_SUCCESS)
304 {
305 regKey.QueryDword(TEXT("Left"), &x);
306 regKey.QueryDword(TEXT("Top"), &y);
307 }
308
309 Move(x, y, 0, 0);
310}
311
312/// @implemented
313void CDefCompFrameWindow::SavePosition()
314{
315 LSTATUS error;
316 CicRegKey regKey;
317 error = regKey.Create(HKEY_CURRENT_USER,
318 TEXT("SOFTWARE\\Microsoft\\CTF\\CUAS\\DefaultCompositionWindow"));
319 if (error == ERROR_SUCCESS)
320 {
321 regKey.SetDword(TEXT("Left"), m_nLeft);
322 regKey.SetDword(TEXT("Top"), m_nTop);
323 }
324}
325
326/// @implemented
327STDMETHODIMP_(void) CDefCompFrameWindow::OnCreate(HWND hWnd)
328{
329 ::SetWindowTheme(hWnd, L"TASKBAR", NULL);
330
331 ZeroMemory(&m_Margins, sizeof(m_Margins));
332
333 CUIFTheme theme;
334 theme.m_hTheme = NULL;
335 theme.m_iPartId = 1;
336 theme.m_iStateId = 0;
337 theme.m_pszClassList = L"TOOLBAR";
338 if (SUCCEEDED(theme.InternalOpenThemeData(hWnd)))
339 GetThemeMargins(NULL, 1, 3602, NULL, &m_Margins);
340}
341
342/// @implemented
343STDMETHODIMP_(BOOL) CDefCompFrameWindow::OnSetCursor(UINT uMsg, LONG x, LONG y)
344{
345 if (!::IsWindow(m_hwndCompStr))
346 return FALSE;
347
348 RECT rc;
349 ::GetWindowRect(m_hwndCompStr, &rc);
350 MyScreenToClient(NULL, &rc);
351 POINT pt = { x, y };
352 return ::PtInRect(&rc, pt);
353}
354
355/// @implemented
356STDMETHODIMP_(LRESULT)
357CDefCompFrameWindow::OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
358{
359 CicIMCLock imcLock(m_hIMC);
360 if (SUCCEEDED(imcLock.m_hr))
361 ::SendMessage(imcLock.get().hWnd, WM_IME_NOTIFY, 0xF, (LPARAM)m_hIMC);
362 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
363}
364
365/// @implemented
366STDMETHODIMP_(void) CDefCompFrameWindow::HandleMouseMsg(UINT uMsg, LONG x, LONG y)
367{
368 if (::IsWindow(m_hwndCompStr))
369 {
370 RECT rc;
371 ::GetWindowRect(m_hwndCompStr, &rc);
372 MyScreenToClient(NULL, &rc);
373
374 POINT pt = { x, y };
375 if (::PtInRect(&rc, pt))
376 ::SendMessage(m_hwndCompStr, 0x7E8, 0, 0);
377 }
378
379 CUIFWindow::HandleMouseMsg(uMsg, x, y);
380}
381
382/***********************************************************************/
383
384/// @implemented
385POLYTEXTW *CPolyText::GetPolyAt(INT iItem)
386{
387 return &m_PolyTextArray[iItem];
388}
389
390/// @implemented
391HRESULT CPolyText::ShiftPolyText(INT xDelta, INT yDelta)
392{
393 for (size_t iItem = 0; iItem < m_PolyTextArray.size(); ++iItem)
394 {
395 POLYTEXTW *pPolyText = &m_PolyTextArray[iItem];
396 pPolyText->x += xDelta;
397 pPolyText->y += yDelta;
398 ::OffsetRect((LPRECT)&pPolyText->rcl, xDelta, yDelta);
399 }
400 return S_OK;
401}
402
403/// @implemented
404HRESULT CPolyText::RemoveLastLine(BOOL bHorizontal)
405{
406 size_t iItem, cItems = m_PolyTextArray.size();
407 if (!cItems)
408 return E_FAIL;
409
410 POLYTEXTW *pData1 = &m_PolyTextArray[cItems - 1];
411
412 for (iItem = 0; iItem < cItems; ++iItem)
413 {
414 POLYTEXTW *pData2 = &m_PolyTextArray[iItem];
415 if (bHorizontal)
416 {
417 if (pData1->x == pData2->x)
418 break;
419 }
420 else
421 {
422 if (pData1->y == pData2->y)
423 break;
424 }
425 }
426
427 if (iItem >= cItems)
428 return E_FAIL;
429
430 m_PolyTextArray.Remove(iItem, cItems - iItem);
431 m_ValueArray.Remove(iItem, cItems - iItem);
432 return S_OK;
433}
434
435/// @implemented
436void CPolyText::RemoveAll()
437{
438 m_PolyTextArray.clear();
439 m_ValueArray.clear();
440}
441
442/***********************************************************************/
443
444/// @implemented
445void COMPWND::_ClientToScreen(LPRECT prc)
446{
447 ::ClientToScreen(m_hWnd, (LPPOINT)prc);
448 ::ClientToScreen(m_hWnd, (LPPOINT)&prc->right);
449}
450
451/***********************************************************************/
452
453// For GetWindowLongPtr/SetWindowLongPtr
454#define UICOMP_GWLP_INDEX 0
455#define UICOMP_GWLP_SIZE (UICOMP_GWLP_INDEX + sizeof(INT))
456
457/// @unimplemented
458UIComposition::UIComposition(HWND hwndParent)
459{
460}
461
462/// @implemented
463UIComposition::~UIComposition()
464{
465 DestroyCompositionWindow();
466
467 if (m_hFont1)
468 {
469 ::DeleteObject(m_hFont1);
470 m_hFont1 = NULL;
471 }
472
473 if (m_hFont2)
474 {
475 ::DeleteObject(m_hFont2);
476 m_hFont2 = NULL;
477 }
478
479 if (m_strCompStr)
480 {
481 cicMemFree(m_strCompStr);
482 m_strCompStr = NULL;
483 }
484
485 m_cchCompStr = 0;
486}
487
488// @implemented
489BOOL UIComposition::SendMessageToUI(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam)
490{
491 HWND hImeWnd = ImmGetDefaultIMEWnd(0);
492 if (!::IsWindow(hImeWnd))
493 return TRUE;
494 TLS *pTLS = TLS::GetTLS();
495 LRESULT ret;
496 if (pTLS && pTLS->m_cWnds > 1)
497 ret = ::SendMessage(imcLock.get().hWnd, WM_IME_NOTIFY, wParam, lParam);
498 else
499 ret = ::SendMessage(hImeWnd, WM_IME_NOTIFY, wParam, lParam);
500 return !ret;
501}
502
503/// @implemented
504HRESULT UIComposition::CreateDefFrameWnd(HWND hwndParent, HIMC hIMC)
505{
506 if (!m_pDefCompFrameWindow)
507 {
508 m_pDefCompFrameWindow = new(cicNoThrow) CDefCompFrameWindow(hIMC, 0x800000A4);
509 if (!m_pDefCompFrameWindow)
510 return E_OUTOFMEMORY;
511 if (!m_pDefCompFrameWindow->Initialize())
512 {
513 delete m_pDefCompFrameWindow;
514 m_pDefCompFrameWindow = NULL;
515 return E_FAIL;
516 }
517
518 m_pDefCompFrameWindow->Init();
519 }
520
521 m_pDefCompFrameWindow->CreateWnd(hwndParent);
522 return S_OK;
523}
524
525/// @implemented
526HRESULT UIComposition::CreateCompButtonWnd(HWND hwndParent, HIMC hIMC)
527{
528 TLS *pTLS = TLS::GetTLS();
529 if (!pTLS || !pTLS->NonEACompositionEnabled())
530 return S_OK;
531
532 if (IsEALang(0))
533 {
534 if (m_pCompButtonFrameWindow)
535 {
536 delete m_pCompButtonFrameWindow;
537 m_pCompButtonFrameWindow = NULL;
538 }
539 return S_OK;
540 }
541
542 if (!m_pCompButtonFrameWindow)
543 {
544 m_pCompButtonFrameWindow = new(cicNoThrow) CCompButtonFrameWindow(hIMC, 0x800000B4);
545 if (!m_pCompButtonFrameWindow)
546 return E_OUTOFMEMORY;
547
548 if (!m_pCompButtonFrameWindow->Initialize())
549 {
550 if (m_pCompButtonFrameWindow)
551 {
552 delete m_pCompButtonFrameWindow;
553 m_pCompButtonFrameWindow = NULL;
554 }
555 return E_FAIL;
556 }
557
558 m_pCompButtonFrameWindow->Init();
559 }
560
561 m_pCompButtonFrameWindow->CreateWnd(hwndParent);
562 return S_OK;
563}
564
565/// @implemented
566HRESULT UIComposition::CreateCompositionWindow(CicIMCLock& imcLock, HWND hwndParent)
567{
568 if (FAILED(imcLock.m_hr))
569 return imcLock.m_hr;
570
571 if (!::IsWindow(hwndParent) || m_bHasCompWnd)
572 return E_FAIL;
573
574 for (INT iCompStr = 0; iCompStr < 3; ++iCompStr)
575 {
576 DWORD style = WS_POPUP | WS_DISABLED;
577 HWND hwndCompStr = ::CreateWindowExW(0, L"MSCTFIME Composition", NULL, style,
578 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);
579 m_CompStrs[iCompStr].m_hWnd = hwndCompStr;
580 ::SetWindowLongPtrW(hwndCompStr, GWLP_USERDATA, (LONG_PTR)this);
581 ::SetWindowLongPtrW(hwndCompStr, UICOMP_GWLP_INDEX, iCompStr);
582 m_CompStrs[iCompStr].m_Caret.CreateCaret(hwndCompStr, m_CaretSize);
583 }
584
585 HRESULT hr = CreateCompButtonWnd(hwndParent, imcLock.m_hIMC);
586 if (FAILED(hr))
587 {
588 DestroyCompositionWindow();
589 return E_OUTOFMEMORY;
590 }
591
592 hr = CreateDefFrameWnd(hwndParent, imcLock.m_hIMC);
593 if (FAILED(hr))
594 {
595 DestroyCompositionWindow();
596 return E_OUTOFMEMORY;
597 }
598
599 DWORD style = WS_CHILD | WS_DISABLED;
600 HWND hwndCompStr = ::CreateWindowExW(WS_EX_CLIENTEDGE, L"MSCTFIME Composition", NULL, style,
601 0, 0, 0, 0, *m_pDefCompFrameWindow, NULL, g_hInst, NULL);
602 if (!hwndCompStr)
603 {
604 DestroyCompositionWindow();
605 return E_OUTOFMEMORY;
606 }
607
608 m_CompStrs[3].m_hWnd = hwndCompStr;
609 m_pDefCompFrameWindow->m_hwndCompStr = hwndCompStr;
610 ::SetWindowLongPtrW(hwndCompStr, GWLP_USERDATA, (LONG_PTR)this);
611 ::SetWindowLongPtrW(hwndCompStr, UICOMP_GWLP_INDEX, -1);
612 m_CompStrs[3].m_Caret.CreateCaret(hwndCompStr, m_CaretSize);
613 m_bHasCompWnd = TRUE;
614
615 return S_OK;
616}
617
618/// @implemented
619HRESULT UIComposition::DestroyCompositionWindow()
620{
621 for (INT i = 0; i < 4; ++i)
622 {
623 COMPWND *pCompStr = &m_CompStrs[i];
624 pCompStr->m_Caret.DestroyCaret();
625 if (::IsWindow(pCompStr->m_hWnd))
626 {
627 DestroyWindow(pCompStr->m_hWnd);
628 pCompStr->m_PolyText.RemoveAll();
629 }
630 pCompStr->m_hWnd = NULL;
631 }
632
633 if (m_pCompButtonFrameWindow)
634 {
635 ::DestroyWindow(*m_pCompButtonFrameWindow);
636 delete m_pCompButtonFrameWindow;
637 m_pCompButtonFrameWindow = NULL;
638 }
639
640 if (m_pDefCompFrameWindow)
641 {
642 ::DestroyWindow(*m_pDefCompFrameWindow);
643 delete m_pDefCompFrameWindow;
644 m_pDefCompFrameWindow = NULL;
645 }
646
647 return 0;
648}
649
650// @implemented
651BOOL UIComposition::InquireImeUIWndState(CicIMCLock& imcLock)
652{
653 BOOL bValue = FALSE;
654 UIComposition::SendMessageToUI(imcLock, 0x11u, (LPARAM)&bValue);
655 return bValue;
656}
657
658/// @implemented
659HRESULT UIComposition::UpdateShowCompWndFlag(CicIMCLock& imcLock, DWORD *pdwCompStrLen)
660{
661 if (FAILED(imcLock.m_hr))
662 return imcLock.m_hr;
663 if (!::IsWindow(imcLock.get().hWnd))
664 return E_FAIL;
665
666 CicIMCCLock<COMPOSITIONSTRING> compStr(imcLock.get().hCompStr);
667 if (FAILED(compStr.m_hr))
668 return compStr.m_hr;
669
670 if ((m_dwUnknown56[0] & 0x80000000) && compStr.get().dwCompStrLen)
671 m_bHasCompStr = TRUE;
672 else
673 m_bHasCompStr = FALSE;
674
675 if (pdwCompStrLen)
676 *pdwCompStrLen = compStr.get().dwCompStrLen;
677
678 return S_OK;
679}
680
681/// @implemented
682HRESULT UIComposition::UpdateFont(CicIMCLock& imcLock)
683{
684 if (FAILED(imcLock.m_hr))
685 return imcLock.m_hr;
686
687 if (m_hFont1)
688 ::DeleteObject(m_hFont1);
689 if (m_hFont2)
690 ::DeleteObject(m_hFont2);
691
692 LOGFONTW lf = imcLock.get().lfFont.W;
693 m_hFont2 = ::CreateFontIndirectW(&lf);
694
695 lf.lfEscapement = 0;
696 lf.lfOrientation = 0;
697 BOOL bVertical = (lf.lfFaceName[0] == L'@');
698 if (bVertical)
699 {
700 MoveMemory(lf.lfFaceName, &lf.lfFaceName[1], sizeof(lf.lfFaceName) - sizeof(WCHAR));
701 lf.lfFaceName[_countof(lf.lfFaceName) - 1] = UNICODE_NULL;
702 }
703 m_hFont1 = ::CreateFontIndirectW(&lf);
704
705 return S_OK;
706}
707
708// @implemented
709void UIComposition::OnTimer(HWND hWnd)
710{
711 INT iCompStr = (INT)::GetWindowLongPtrW(hWnd, UICOMP_GWLP_INDEX);
712 if (iCompStr == -1)
713 m_CompStrs[3].m_Caret.OnTimer();
714 else
715 m_CompStrs[iCompStr].m_Caret.OnTimer();
716}
717
718/// @implemented
719BOOL UIComposition::GetImeUIWndTextExtent(CicIMCLock& imcLock, LPARAM lParam)
720{
721 return !UIComposition::SendMessageToUI(imcLock, 0x14, lParam);
722}
723
724/// @implemented
725LPWSTR UIComposition::GetCompStrBuffer(INT cchStr)
726{
727 if (!m_strCompStr)
728 {
729 m_strCompStr = (LPWSTR)cicMemAllocClear((cchStr + 1) * sizeof(WCHAR));
730 m_cchCompStr = cchStr;
731 }
732 if (m_cchCompStr < cchStr)
733 {
734 m_strCompStr = (LPWSTR)cicMemReAlloc(m_strCompStr, (cchStr + 1) * sizeof(WCHAR));
735 m_cchCompStr = cchStr;
736 }
737 return m_strCompStr;
738}
739
740/// @unimplemented
741void UIComposition::OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd)
742{
743 //FIXME
744}
745
746/// @implemented
747HRESULT UIComposition::OnImeCompositionUpdate(CicIMCLock& imcLock)
748{
749 m_dwUnknown56[0] |= 0x8000;
750 return UIComposition::UpdateShowCompWndFlag(imcLock, NULL);
751}
752
753/// @unimplemented
754HRESULT UIComposition::OnImeEndComposition()
755{
756 m_dwUnknown56[0] = 0;
757 return DestroyCompositionWindow();
758}
759
760/// @unimplemented
761void UIComposition::OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam)
762{
763 //FIXME
764}
765
766/// @unimplemented
767void UIComposition::OnPaintTheme(WPARAM wParam)
768{
769 //FIXME
770}
771
772/// @implemented
773HRESULT UIComposition::OnDestroy()
774{
775 return DestroyCompositionWindow();
776}
777
778/// @unimplemented
779LRESULT CALLBACK
780UIComposition::CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
781{
782 if (uMsg == WM_CREATE)
783 return -1; // FIXME
784 return 0;
785}
786
787/// @implemented
788HRESULT UIComposition::OnImeNotifySetCompositionWindow(CicIMCLock& imcLock)
789{
790 return UpdateCompositionRect(imcLock);
791}
792
793/// @unimplemented
794HRESULT UIComposition::UpdateCompositionRect(CicIMCLock& imcLock)
795{
796 return E_NOTIMPL;
797}
798
799/// @implemented
800INT UIComposition::GetLevelFromIMC(CicIMCLock& imcLock)
801{
802 DWORD dwStyle = imcLock.get().cfCompForm.dwStyle;
803 if (dwStyle == CFS_DEFAULT)
804 return 1;
805 if (!(dwStyle & (CFS_FORCE_POSITION | CFS_POINT | CFS_RECT)))
806 return 0;
807
808 RECT rc;
809 ::GetClientRect(imcLock.get().hWnd, &rc);
810 if (!::PtInRect(&rc, imcLock.get().cfCompForm.ptCurrentPos))
811 return 1;
812
813 INPUTCONTEXT *pIC = &imcLock.get();
814 if ((pIC->cfCompForm.dwStyle & CFS_RECT) &&
815 (pIC->cfCompForm.rcArea.top == pIC->cfCompForm.rcArea.bottom) &&
816 (pIC->cfCompForm.rcArea.left == pIC->cfCompForm.rcArea.right))
817 {
818 return 1;
819 }
820
821 return 2;
822}
823
824/// @implemented
825HRESULT UIComposition::OnImeSetContextAfter(CicIMCLock& imcLock)
826{
827 if ((!m_pDefCompFrameWindow || !::IsWindow(*m_pDefCompFrameWindow)) && !::IsWindow(m_CompStrs[0].m_hWnd))
828 {
829 m_dwUnknown56[0] &= ~0x8000;
830 return S_OK;
831 }
832
833 if (FAILED(imcLock.m_hr))
834 return imcLock.m_hr;
835
836 INT Level = GetLevelFromIMC(imcLock);
837 if ((Level == 1 || Level == 2) && (m_dwUnknown56[0] & 0x80000000) && m_dwUnknown56[1])
838 {
839 DWORD dwCompStrLen = 0;
840 UpdateShowCompWndFlag(imcLock, &dwCompStrLen);
841
842 if (Level == 1)
843 {
844 ::ShowWindow(*m_pDefCompFrameWindow, (m_bHasCompStr ? SW_SHOWNOACTIVATE : SW_HIDE));
845 }
846 else if (Level == 2 && !m_bHasCompStr && dwCompStrLen)
847 {
848 for (INT iCompStr = 0; iCompStr < 3; ++iCompStr)
849 {
850 m_CompStrs[iCompStr].m_Caret.HideCaret();
851 ::ShowWindow(m_CompStrs[iCompStr].m_Caret, SW_HIDE);
852 }
853 }
854 }
855 else
856 {
857 ::ShowWindow(*m_pDefCompFrameWindow, SW_HIDE);
858
859 for (INT iCompStr = 0; iCompStr < 3; ++iCompStr)
860 {
861 m_CompStrs[iCompStr].m_Caret.HideCaret();
862 ::ShowWindow(m_CompStrs[iCompStr].m_Caret, SW_HIDE);
863 }
864 }
865
866 return S_OK;
867}
868
869/***********************************************************************/
870
871// For GetWindowLongPtr/SetWindowLongPtr
872#define UI_GWLP_HIMC 0
873#define UI_GWLP_UI sizeof(HIMC)
874#define UI_GWLP_SIZE (UI_GWLP_UI + sizeof(UI*))
875
876/// @implemented
877UI::UI(HWND hWnd) : m_hWnd(hWnd)
878{
879}
880
881/// @implemented
882UI::~UI()
883{
884 delete m_pComp;
885}
886
887/// @implemented
888HRESULT UI::_Create()
889{
890 m_pComp = new(cicNoThrow) UIComposition(m_hWnd);
891 if (!m_pComp)
892 return E_OUTOFMEMORY;
893
894 ::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, (LONG_PTR)this);
895 return S_OK;
896}
897
898/// @implemented
899void UI::_Destroy()
900{
901 m_pComp->OnDestroy();
902 ::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, 0);
903}
904
905/// @implemented
906void UI::OnCreate(HWND hWnd)
907{
908 UI *pUI = (UI*)::GetWindowLongPtrW(hWnd, UI_GWLP_UI);
909 if (pUI)
910 return;
911 pUI = new(cicNoThrow) UI(hWnd);
912 if (pUI)
913 pUI->_Create();
914}
915
916/// @implemented
917void UI::OnDestroy(HWND hWnd)
918{
919 UI *pUI = (UI*)::GetWindowLongPtrW(hWnd, UI_GWLP_UI);
920 if (!pUI)
921 return;
922
923 pUI->_Destroy();
924 delete pUI;
925}
926
927/// @implemented
928void UI::OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam)
929{
930 m_pComp->OnImeSetContext(imcLock, m_hWnd, wParam, lParam);
931}
932
933/***********************************************************************/
934
935struct CIMEUIWindowHandler
936{
937 static LRESULT CALLBACK ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
938 static HRESULT CALLBACK ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam);
939 static LRESULT CALLBACK ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam);
940 static LRESULT CALLBACK ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam);
941 static LRESULT CALLBACK ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
942 static HRESULT CALLBACK ImeUIDelayedReconvertFuncCall(HWND hWnd);
943 static HRESULT CALLBACK ImeUIOnLayoutChange(LPARAM lParam);
944 static HRESULT CALLBACK ImeUIPrivateHandler(UINT uMsg, WPARAM wParam, LPARAM lParam);
945 static LRESULT CALLBACK ImeUINotifyHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
946};
947
948/// @implemented
949HRESULT CALLBACK
950CIMEUIWindowHandler::ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam)
951{
952 if ((BYTE)wParam == 0xFF)
953 return TRUE;
954
955 CicIMCLock imcLock((HIMC)lParam);
956 if (FAILED(imcLock.m_hr))
957 return imcLock.m_hr;
958
959 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
960 if (FAILED(imeContext.m_hr))
961 return FALSE;
962
963 HRESULT hr = E_FAIL;
964 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
965 if (pCicIC)
966 {
967 UINT keys = 0;
968 if (wParam & MK_LBUTTON)
969 keys |= 0x1;
970 if (wParam & MK_SHIFT)
971 keys |= 0x10;
972 if (wParam & MK_RBUTTON)
973 keys |= 0x2;
974 if (wParam & MK_MBUTTON)
975 keys |= 0x780000;
976 else if (wParam & MK_ALT)
977 keys |= 0xFF880000;
978 hr = pCicIC->MsImeMouseHandler(HIWORD(wParam), HIBYTE(LOWORD(wParam)), keys, imcLock);
979 }
980
981 return hr;
982}
983
984/// @implemented
985HRESULT CALLBACK CIMEUIWindowHandler::ImeUIOnLayoutChange(LPARAM lParam)
986{
987 CicIMCLock imcLock((HIMC)lParam);
988 if (FAILED(imcLock.m_hr))
989 return S_OK;
990
991 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
992 if (FAILED(imeContext.m_hr))
993 return S_OK;
994
995 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
996 if (pCicIC)
997 {
998 auto pContextOwnerServices = pCicIC->m_pContextOwnerServices;
999 pContextOwnerServices->AddRef();
1000 pContextOwnerServices->OnLayoutChange();
1001 pContextOwnerServices->Release();
1002 }
1003
1004 return S_OK;
1005}
1006
1007/// @implemented
1008HRESULT CALLBACK
1009CIMEUIWindowHandler::ImeUIPrivateHandler(UINT uMsg, WPARAM wParam, LPARAM lParam)
1010{
1011 CicIMCLock imcLock((HIMC)lParam);
1012 if (FAILED(imcLock.m_hr))
1013 return imcLock.m_hr;
1014
1015 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
1016 if (FAILED(imeContext.m_hr))
1017 return imeContext.m_hr;
1018
1019 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
1020 if (pCicIC && wParam == 0x10)
1021 pCicIC->EscbClearDocFeedBuffer(imcLock, TRUE);
1022
1023 return S_OK;
1024}
1025
1026/// @implemented
1027LRESULT CALLBACK
1028CIMEUIWindowHandler::ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam)
1029{
1030 if (!wParam)
1031 return TRUE;
1032
1033 CicIMCLock imcLock((HIMC)lParam);
1034 if (FAILED(imcLock.m_hr))
1035 return imcLock.m_hr;
1036
1037 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
1038 if (FAILED(imeContext.m_hr))
1039 return FALSE;
1040
1041 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
1042 if (!pCicIC)
1043 return FALSE;
1044
1045 if (wParam == 1)
1046 {
1047 if (lParam == 0 || lParam == 1 || lParam == 4 || lParam == 0x10000)
1048 {
1049 GUID guid = pCicIC->m_ModeBias.ConvertModeBias((DWORD)lParam);
1050 pCicIC->m_ModeBias.SetModeBias(guid);
1051
1052 pCicIC->m_dwUnknown7[2] |= 1;
1053 pCicIC->m_pContextOwnerServices->AddRef();
1054 pCicIC->m_pContextOwnerServices->OnAttributeChange(GUID_PROP_MODEBIAS);
1055 pCicIC->m_pContextOwnerServices->Release();
1056 return TRUE;
1057 }
1058 }
1059 else if (wParam == 2)
1060 {
1061 return pCicIC->m_ModeBias.ConvertModeBias(pCicIC->m_ModeBias.m_guid);
1062 }
1063
1064 return FALSE;
1065}
1066
1067/// @implemented
1068LRESULT CALLBACK
1069CIMEUIWindowHandler::ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam)
1070{
1071 if (wParam == 0x10000000)
1072 return TRUE;
1073
1074 HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC);
1075 CicIMCLock imcLock(hIMC);
1076 if (FAILED(imcLock.m_hr))
1077 return FALSE;
1078
1079 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
1080 if (FAILED(imeContext.m_hr))
1081 return FALSE;
1082
1083 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
1084 TLS *pTLS = TLS::GetTLS();
1085 if (!pCicIC || !pTLS)
1086 return FALSE;
1087
1088 auto pThreadMgr = pTLS->m_pThreadMgr;
1089 auto pProfile = pTLS->m_pProfile;
1090 if (!pThreadMgr || !pProfile)
1091 return FALSE;
1092
1093 UINT uCodePage = 0;
1094 pProfile->GetCodePageA(&uCodePage);
1095 pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, WM_MSIME_RECONVERT, FALSE);
1096 pCicIC->EndReconvertString(imcLock);
1097 return TRUE;
1098}
1099
1100/// @implemented
1101LRESULT CALLBACK
1102CIMEUIWindowHandler::ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1103{
1104 if (uMsg == WM_MSIME_MOUSE)
1105 return ImeUIMsImeMouseHandler(hWnd, wParam, lParam);
1106 if (uMsg == WM_MSIME_MODEBIAS)
1107 return ImeUIMsImeModeBiasHandler(hWnd, wParam, lParam);
1108 if (uMsg == WM_MSIME_RECONVERTREQUEST)
1109 return ImeUIMsImeReconvertRequest(hWnd, wParam, lParam);
1110 if (uMsg == WM_MSIME_SERVICE)
1111 {
1112 TLS *pTLS = TLS::GetTLS();
1113 if (pTLS && pTLS->m_pProfile)
1114 {
1115 LANGID LangID;
1116 pTLS->m_pProfile->GetLangId(&LangID);
1117 if (PRIMARYLANGID(LangID) == LANG_KOREAN)
1118 return FALSE;
1119 }
1120 return TRUE;
1121 }
1122 return 0;
1123}
1124
1125/// @implemented
1126HRESULT CALLBACK
1127CIMEUIWindowHandler::ImeUIDelayedReconvertFuncCall(HWND hWnd)
1128{
1129 HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC);
1130 CicIMCLock imcLock(hIMC);
1131 if (FAILED(imcLock.m_hr))
1132 return imcLock.m_hr;
1133 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
1134 if (FAILED(imeContext.m_hr))
1135 return imeContext.m_hr;
1136 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
1137 if (pCicIC)
1138 pCicIC->DelayedReconvertFuncCall(imcLock);
1139 return S_OK;
1140}
1141
1142/// @unimplemented
1143LRESULT CALLBACK
1144CIMEUIWindowHandler::ImeUINotifyHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1145{
1146 HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC);
1147 CicIMCLock imcLock(hIMC);
1148 if (FAILED(imcLock.m_hr))
1149 return imcLock.m_hr;
1150 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
1151 if (FAILED(imeContext.m_hr))
1152 return imeContext.m_hr;
1153
1154 CicInputContext *pCicIC = imeContext.get().m_pCicIC;
1155 if (pCicIC)
1156 {
1157 switch (wParam)
1158 {
1159 case IMN_CLOSECANDIDATE:
1160 {
1161 pCicIC->m_bCandidateOpen = FALSE;
1162 HWND hImeWnd = ::ImmGetDefaultIMEWnd(NULL);
1163 if (::IsWindow(hImeWnd))
1164 ::PostMessage(hImeWnd, WM_IME_NOTIFY, 0x10, (LPARAM)hIMC);
1165 break;
1166 }
1167 case IMN_OPENCANDIDATE:
1168 {
1169 pCicIC->m_bCandidateOpen = TRUE;
1170 pCicIC->ClearPrevCandidatePos();
1171 break;
1172 }
1173 case IMN_SETCANDIDATEPOS:
1174 {
1175 //FIXME
1176 break;
1177 }
1178 case IMN_SETCOMPOSITIONFONT:
1179 {
1180 //FIXME
1181 break;
1182 }
1183 case IMN_SETCOMPOSITIONWINDOW:
1184 {
1185 //FIXME
1186 break;
1187 }
1188 case 0xF:
1189 {
1190 CIMEUIWindowHandler::ImeUIOnLayoutChange(lParam);
1191 break;
1192 }
1193 case 0x10:
1194 {
1195 CIMEUIWindowHandler::ImeUIPrivateHandler(uMsg, 0x10, lParam);
1196 break;
1197 }
1198 case 0x13:
1199 {
1200 CIMEUIWindowHandler::ImeUIOnLayoutChange(lParam);
1201 break;
1202 }
1203 case 0x14:
1204 {
1205 //FIXME
1206 break;
1207 }
1208 case 0x16:
1209 {
1210 ::SetTimer(hWnd, 2, 100, NULL);
1211 break;
1212 }
1213 case 0x17:
1214 {
1215 return (LRESULT)hWnd;
1216 }
1217 case 0x10D:
1218 {
1219 //FIXME
1220 break;
1221 }
1222 case 0x10E:
1223 pCicIC->m_dwQueryPos = 0;
1224 break;
1225 }
1226 }
1227
1228 return 0;
1229}
1230
1231/// @implemented
1232LRESULT CALLBACK
1233CIMEUIWindowHandler::ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1234{
1235 TLS *pTLS = TLS::GetTLS();
1236 if (pTLS && (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON))
1237 {
1238 if (uMsg == WM_CREATE)
1239 return -1;
1240 return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
1241 }
1242
1243 switch (uMsg)
1244 {
1245 case WM_CREATE:
1246 {
1247 UI::OnCreate(hWnd);
1248 break;
1249 }
1250 case WM_DESTROY:
1251 case WM_ENDSESSION:
1252 {
1253 UI::OnDestroy(hWnd);
1254 break;
1255 }
1256 case WM_IME_STARTCOMPOSITION:
1257 case WM_IME_COMPOSITION:
1258 case WM_IME_ENDCOMPOSITION:
1259 case WM_IME_SETCONTEXT:
1260 case WM_IME_NOTIFY:
1261 case WM_IME_SELECT:
1262 case WM_TIMER:
1263 {
1264 HIMC hIMC = (HIMC)GetWindowLongPtrW(hWnd, UI_GWLP_HIMC);
1265 UI* pUI = (UI*)GetWindowLongPtrW(hWnd, UI_GWLP_UI);
1266 CicIMCLock imcLock(hIMC);
1267 switch (uMsg)
1268 {
1269 case WM_IME_STARTCOMPOSITION:
1270 {
1271 pUI->m_pComp->OnImeStartComposition(imcLock, pUI->m_hWnd);
1272 break;
1273 }
1274 case WM_IME_COMPOSITION:
1275 {
1276 if (lParam & GCS_COMPSTR)
1277 {
1278 pUI->m_pComp->OnImeCompositionUpdate(imcLock);
1279 ::SetTimer(hWnd, 0, 10, NULL);
1280 pUI->m_pComp->m_bInComposition = TRUE;
1281 }
1282 break;
1283 }
1284 case WM_IME_ENDCOMPOSITION:
1285 {
1286 ::KillTimer(hWnd, 0);
1287 pUI->m_pComp->OnImeEndComposition();
1288 break;
1289 }
1290 case WM_IME_SETCONTEXT:
1291 {
1292 pUI->OnImeSetContext(imcLock, wParam, lParam);
1293 ::KillTimer(hWnd, 1);
1294 ::SetTimer(hWnd, 1, 300, NULL);
1295 break;
1296 }
1297 case WM_TIMER:
1298 {
1299 switch (wParam)
1300 {
1301 case 0:
1302 ::KillTimer(hWnd, wParam);
1303 pUI->m_pComp->m_bInComposition = FALSE;
1304 pUI->m_pComp->OnImeNotifySetCompositionWindow(imcLock);
1305 break;
1306 case 1:
1307 ::KillTimer(hWnd, wParam);
1308 pUI->m_pComp->OnImeSetContextAfter(imcLock);
1309 break;
1310 case 2:
1311 ::KillTimer(hWnd, wParam);
1312 CIMEUIWindowHandler::ImeUIDelayedReconvertFuncCall(hWnd);
1313 break;
1314 default:
1315 break;
1316 }
1317 break;
1318 }
1319 case WM_IME_NOTIFY:
1320 case WM_IME_SELECT:
1321 default:
1322 {
1323 pUI->m_pComp->OnPaintTheme(wParam);
1324 break;
1325 }
1326 }
1327 break;
1328 }
1329 default:
1330 {
1331 if (IsMsImeMessage(uMsg))
1332 return CIMEUIWindowHandler::ImeUIMsImeHandler(hWnd, uMsg, wParam, lParam);
1333 return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
1334 }
1335 }
1336
1337 return 0;
1338}
1339
1340/***********************************************************************/
1341
1342/// @implemented
1343EXTERN_C LRESULT CALLBACK
1344UIWndProc(
1345 _In_ HWND hWnd,
1346 _In_ UINT uMsg,
1347 _In_ WPARAM wParam,
1348 _In_ LPARAM lParam)
1349{
1350 return CIMEUIWindowHandler::ImeUIWndProcWorker(hWnd, uMsg, wParam, lParam);
1351}
1352
1353/***********************************************************************/
1354
1355/// @implemented
1356BOOL RegisterImeClass(VOID)
1357{
1358 WNDCLASSEXW wcx;
1359
1360 if (!GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx))
1361 {
1362 ZeroMemory(&wcx, sizeof(wcx));
1363 wcx.cbSize = sizeof(WNDCLASSEXW);
1364 wcx.cbWndExtra = UI_GWLP_SIZE;
1365 wcx.hIcon = LoadIconW(0, (LPCWSTR)IDC_ARROW);
1366 wcx.hInstance = g_hInst;
1367 wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
1368 wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
1369 wcx.style = CS_IME | CS_GLOBALCLASS;
1370 wcx.lpfnWndProc = UIWndProc;
1371 wcx.lpszClassName = L"MSCTFIME UI";
1372 if (!RegisterClassExW(&wcx))
1373 return FALSE;
1374 }
1375
1376 if (!GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx))
1377 {
1378 ZeroMemory(&wcx, sizeof(wcx));
1379 wcx.cbSize = sizeof(WNDCLASSEXW);
1380 wcx.cbWndExtra = UICOMP_GWLP_SIZE;
1381 wcx.hIcon = NULL;
1382 wcx.hInstance = g_hInst;
1383 wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_IBEAM);
1384 wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
1385 wcx.style = CS_IME | CS_HREDRAW | CS_VREDRAW;
1386 wcx.lpfnWndProc = UIComposition::CompWndProc;
1387 wcx.lpszClassName = L"MSCTFIME Composition";
1388 if (!RegisterClassExW(&wcx))
1389 return FALSE;
1390 }
1391
1392 return TRUE;
1393}
1394
1395/// @implemented
1396VOID UnregisterImeClass(VOID)
1397{
1398 WNDCLASSEXW wcx;
1399
1400 GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx);
1401 UnregisterClassW(L"MSCTFIME UI", g_hInst);
1402 DestroyIcon(wcx.hIcon);
1403 DestroyIcon(wcx.hIconSm);
1404
1405 GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx);
1406 UnregisterClassW(L"MSCTFIME Composition", g_hInst);
1407 DestroyIcon(wcx.hIcon);
1408 DestroyIcon(wcx.hIconSm);
1409}