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
10 WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
11
12 /***********************************************************************/
13
14 UINT WM_MSIME_SERVICE = 0;
15 UINT WM_MSIME_UIREADY = 0;
16 UINT WM_MSIME_RECONVERTREQUEST = 0;
17 UINT WM_MSIME_RECONVERT = 0;
18 UINT WM_MSIME_DOCUMENTFEED = 0;
19 UINT WM_MSIME_QUERYPOSITION = 0;
20 UINT WM_MSIME_MODEBIAS = 0;
21 UINT WM_MSIME_SHOWIMEPAD = 0;
22 UINT WM_MSIME_MOUSE = 0;
23 UINT WM_MSIME_KEYMAP = 0;
24
25 /// @implemented
IsMsImeMessage(_In_ UINT uMsg)26 BOOL 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
RegisterMSIMEMessage(VOID)41 BOOL 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
CDefCompFrameGripper(CDefCompFrameWindow * pDefCompFrameWindow,LPCRECT prc,DWORD style)69 CDefCompFrameGripper::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
CCompFinalizeButton(CCompFrameWindow * pParent,DWORD nObjectID,LPCRECT prc,DWORD style,DWORD dwButtonFlags,LPCWSTR pszText)80 CCompFinalizeButton::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
~CCompFinalizeButton()93 CCompFinalizeButton::~CCompFinalizeButton()
94 {
95 HICON hIcon = CUIFToolbarButton::GetIcon();
96 if (hIcon)
97 {
98 ::DestroyIcon(hIcon);
99 CUIFToolbarButton::SetIcon(NULL);
100 }
101 }
102
103 /// @implemented
OnLeftClick()104 void 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
CCompFrameWindow(HIMC hIMC,DWORD style)114 CCompFrameWindow::CCompFrameWindow(HIMC hIMC, DWORD style)
115 : CUIFWindow(g_hInst, style)
116 {
117 m_hIMC = hIMC;
118 }
119
120 /***********************************************************************/
121
122 /// @implemented
CCompButtonFrameWindow(HIMC hIMC,DWORD style)123 CCompButtonFrameWindow::CCompButtonFrameWindow(HIMC hIMC, DWORD style)
124 : CCompFrameWindow(hIMC, style)
125 {
126 }
127
128 /// @implemented
Init()129 void 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
MoveShow(LONG x,LONG y,BOOL bShow)151 void 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
STDMETHODIMP_(void)167 STDMETHODIMP_(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
CDefCompFrameWindow(HIMC hIMC,DWORD style)185 CDefCompFrameWindow::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
~CDefCompFrameWindow()195 CDefCompFrameWindow::~CDefCompFrameWindow()
196 {
197 SavePosition();
198 }
199
200 /// @implemented
Init()201 void 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
GetGripperWidth()232 INT 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
MyScreenToClient(LPPOINT ppt,LPRECT prc)249 void 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
SetCompStrRect(INT nWidth,INT nHeight,BOOL bShow)262 void 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
LoadPosition()295 void 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
SavePosition()313 void 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
STDMETHODIMP_(void)327 STDMETHODIMP_(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
STDMETHODIMP_(BOOL)343 STDMETHODIMP_(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
STDMETHODIMP_(LRESULT)356 STDMETHODIMP_(LRESULT)
357 CDefCompFrameWindow::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
STDMETHODIMP_(void)366 STDMETHODIMP_(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
GetPolyAt(INT iItem)385 POLYTEXTW *CPolyText::GetPolyAt(INT iItem)
386 {
387 return &m_PolyTextArray[iItem];
388 }
389
390 /// @implemented
ShiftPolyText(INT xDelta,INT yDelta)391 HRESULT 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
RemoveLastLine(BOOL bHorizontal)404 HRESULT 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
RemoveAll()436 void CPolyText::RemoveAll()
437 {
438 m_PolyTextArray.clear();
439 m_ValueArray.clear();
440 }
441
442 /***********************************************************************/
443
444 /// @implemented
_ClientToScreen(LPRECT prc)445 void 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
UIComposition(HWND hwndParent)458 UIComposition::UIComposition(HWND hwndParent)
459 {
460 }
461
462 /// @implemented
~UIComposition()463 UIComposition::~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
SendMessageToUI(CicIMCLock & imcLock,WPARAM wParam,LPARAM lParam)489 BOOL 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
CreateDefFrameWnd(HWND hwndParent,HIMC hIMC)504 HRESULT 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
CreateCompButtonWnd(HWND hwndParent,HIMC hIMC)526 HRESULT 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
CreateCompositionWindow(CicIMCLock & imcLock,HWND hwndParent)566 HRESULT 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
DestroyCompositionWindow()619 HRESULT 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
InquireImeUIWndState(CicIMCLock & imcLock)651 BOOL UIComposition::InquireImeUIWndState(CicIMCLock& imcLock)
652 {
653 BOOL bValue = FALSE;
654 UIComposition::SendMessageToUI(imcLock, 0x11u, (LPARAM)&bValue);
655 return bValue;
656 }
657
658 /// @implemented
UpdateShowCompWndFlag(CicIMCLock & imcLock,DWORD * pdwCompStrLen)659 HRESULT 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
UpdateFont(CicIMCLock & imcLock)682 HRESULT 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
OnTimer(HWND hWnd)709 void 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
GetImeUIWndTextExtent(CicIMCLock & imcLock,LPARAM lParam)719 BOOL UIComposition::GetImeUIWndTextExtent(CicIMCLock& imcLock, LPARAM lParam)
720 {
721 return !UIComposition::SendMessageToUI(imcLock, 0x14, lParam);
722 }
723
724 /// @implemented
GetCompStrBuffer(INT cchStr)725 LPWSTR 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
OnImeStartComposition(CicIMCLock & imcLock,HWND hUIWnd)741 void UIComposition::OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd)
742 {
743 //FIXME
744 }
745
746 /// @implemented
OnImeCompositionUpdate(CicIMCLock & imcLock)747 HRESULT UIComposition::OnImeCompositionUpdate(CicIMCLock& imcLock)
748 {
749 m_dwUnknown56[0] |= 0x8000;
750 return UIComposition::UpdateShowCompWndFlag(imcLock, NULL);
751 }
752
753 /// @unimplemented
OnImeEndComposition()754 HRESULT UIComposition::OnImeEndComposition()
755 {
756 m_dwUnknown56[0] = 0;
757 return DestroyCompositionWindow();
758 }
759
760 /// @unimplemented
OnImeSetContext(CicIMCLock & imcLock,HWND hUIWnd,WPARAM wParam,LPARAM lParam)761 void UIComposition::OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam)
762 {
763 //FIXME
764 }
765
766 /// @unimplemented
OnPaintTheme(WPARAM wParam)767 void UIComposition::OnPaintTheme(WPARAM wParam)
768 {
769 //FIXME
770 }
771
772 /// @implemented
OnDestroy()773 HRESULT UIComposition::OnDestroy()
774 {
775 return DestroyCompositionWindow();
776 }
777
778 /// @unimplemented
779 LRESULT CALLBACK
CompWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)780 UIComposition::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
OnImeNotifySetCompositionWindow(CicIMCLock & imcLock)788 HRESULT UIComposition::OnImeNotifySetCompositionWindow(CicIMCLock& imcLock)
789 {
790 return UpdateCompositionRect(imcLock);
791 }
792
793 /// @unimplemented
UpdateCompositionRect(CicIMCLock & imcLock)794 HRESULT UIComposition::UpdateCompositionRect(CicIMCLock& imcLock)
795 {
796 return E_NOTIMPL;
797 }
798
799 /// @implemented
GetLevelFromIMC(CicIMCLock & imcLock)800 INT 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
OnImeSetContextAfter(CicIMCLock & imcLock)825 HRESULT 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
UI(HWND hWnd)877 UI::UI(HWND hWnd) : m_hWnd(hWnd)
878 {
879 }
880
881 /// @implemented
~UI()882 UI::~UI()
883 {
884 delete m_pComp;
885 }
886
887 /// @implemented
_Create()888 HRESULT 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
_Destroy()899 void UI::_Destroy()
900 {
901 m_pComp->OnDestroy();
902 ::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, 0);
903 }
904
905 /// @implemented
OnCreate(HWND hWnd)906 void 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
OnDestroy(HWND hWnd)917 void 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
OnImeSetContext(CicIMCLock & imcLock,WPARAM wParam,LPARAM lParam)928 void UI::OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam)
929 {
930 m_pComp->OnImeSetContext(imcLock, m_hWnd, wParam, lParam);
931 }
932
933 /***********************************************************************/
934
935 struct 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
949 HRESULT CALLBACK
ImeUIMsImeMouseHandler(HWND hWnd,WPARAM wParam,LPARAM lParam)950 CIMEUIWindowHandler::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
ImeUIOnLayoutChange(LPARAM lParam)985 HRESULT 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
1008 HRESULT CALLBACK
ImeUIPrivateHandler(UINT uMsg,WPARAM wParam,LPARAM lParam)1009 CIMEUIWindowHandler::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
1027 LRESULT CALLBACK
ImeUIMsImeModeBiasHandler(HWND hWnd,WPARAM wParam,LPARAM lParam)1028 CIMEUIWindowHandler::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
1068 LRESULT CALLBACK
ImeUIMsImeReconvertRequest(HWND hWnd,WPARAM wParam,LPARAM lParam)1069 CIMEUIWindowHandler::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
1101 LRESULT CALLBACK
ImeUIMsImeHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1102 CIMEUIWindowHandler::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
1126 HRESULT CALLBACK
ImeUIDelayedReconvertFuncCall(HWND hWnd)1127 CIMEUIWindowHandler::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
1143 LRESULT CALLBACK
ImeUINotifyHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1144 CIMEUIWindowHandler::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
1232 LRESULT CALLBACK
ImeUIWndProcWorker(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1233 CIMEUIWindowHandler::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
1343 EXTERN_C LRESULT CALLBACK
UIWndProc(_In_ HWND hWnd,_In_ UINT uMsg,_In_ WPARAM wParam,_In_ LPARAM lParam)1344 UIWndProc(
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
RegisterImeClass(VOID)1356 BOOL 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
UnregisterImeClass(VOID)1396 VOID 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 }
1410