Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410/* * PROJECT: ReactOS msctfime.ime * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: User Interface of msctfime.ime * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "msctfime.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
/***********************************************************************/
UINT WM_MSIME_SERVICE = 0;UINT WM_MSIME_UIREADY = 0;UINT WM_MSIME_RECONVERTREQUEST = 0;UINT WM_MSIME_RECONVERT = 0;UINT WM_MSIME_DOCUMENTFEED = 0;UINT WM_MSIME_QUERYPOSITION = 0;UINT WM_MSIME_MODEBIAS = 0;UINT WM_MSIME_SHOWIMEPAD = 0;UINT WM_MSIME_MOUSE = 0;UINT WM_MSIME_KEYMAP = 0;
/// @implementedBOOL IsMsImeMessage(_In_ UINT uMsg){ return (uMsg == WM_MSIME_SERVICE || uMsg == WM_MSIME_UIREADY || uMsg == WM_MSIME_RECONVERTREQUEST || uMsg == WM_MSIME_RECONVERT || uMsg == WM_MSIME_DOCUMENTFEED || uMsg == WM_MSIME_QUERYPOSITION || uMsg == WM_MSIME_MODEBIAS || uMsg == WM_MSIME_SHOWIMEPAD || uMsg == WM_MSIME_MOUSE || uMsg == WM_MSIME_KEYMAP);}
/// @implementedBOOL RegisterMSIMEMessage(VOID){ // Using ANSI (A) version here can reduce binary size. WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); WM_MSIME_UIREADY = RegisterWindowMessageA("MSIMEUIReady"); WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); WM_MSIME_MODEBIAS = RegisterWindowMessageA("MSIMEModeBias"); WM_MSIME_SHOWIMEPAD = RegisterWindowMessageA("MSIMEShowImePad"); WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); WM_MSIME_KEYMAP = RegisterWindowMessageA("MSIMEKeyMap"); return (WM_MSIME_SERVICE && WM_MSIME_UIREADY && WM_MSIME_RECONVERTREQUEST && WM_MSIME_RECONVERT && WM_MSIME_DOCUMENTFEED && WM_MSIME_QUERYPOSITION && WM_MSIME_MODEBIAS && WM_MSIME_SHOWIMEPAD && WM_MSIME_MOUSE && WM_MSIME_KEYMAP);}
/***********************************************************************/
/// @implementedCDefCompFrameGripper::CDefCompFrameGripper( CDefCompFrameWindow *pDefCompFrameWindow, LPCRECT prc, DWORD style) : CUIFGripper(pDefCompFrameWindow, prc, style){ m_pDefCompFrameWindow = pDefCompFrameWindow;}
/***********************************************************************/
/// @implementedCCompFinalizeButton::CCompFinalizeButton( CCompFrameWindow *pParent, DWORD nObjectID, LPCRECT prc, DWORD style, DWORD dwButtonFlags, LPCWSTR pszText) : CUIFToolbarButton(pParent, nObjectID, prc, style, dwButtonFlags, pszText){ m_pCompFrameWindow = pParent;}
/// @implementedCCompFinalizeButton::~CCompFinalizeButton(){ HICON hIcon = CUIFToolbarButton::GetIcon(); if (hIcon) { ::DestroyIcon(hIcon); CUIFToolbarButton::SetIcon(NULL); }}
/// @implementedvoid CCompFinalizeButton::OnLeftClick(){ HIMC hIMC = m_pCompFrameWindow->m_hIMC; if (hIMC) ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);}
/***********************************************************************/
/// @implementedCCompFrameWindow::CCompFrameWindow(HIMC hIMC, DWORD style) : CUIFWindow(g_hInst, style){ m_hIMC = hIMC;}
/***********************************************************************/
/// @implementedCCompButtonFrameWindow::CCompButtonFrameWindow(HIMC hIMC, DWORD style) : CCompFrameWindow(hIMC, style){}
/// @implementedvoid CCompButtonFrameWindow::Init(){ if (m_pFinalizeButton) return;
RECT rc = { 0, 0, 0, 0 }; m_pFinalizeButton = new(cicNoThrow) CCompFinalizeButton(this, 0, &rc, 0, 0x10000, NULL);
m_pFinalizeButton->Initialize(); m_pFinalizeButton->Init();
HICON hIcon = (HICON)::LoadImageW(g_hInst, MAKEINTRESOURCEW(IDI_DOWN), IMAGE_ICON, 16, 16, 0); m_pFinalizeButton->SetIcon(hIcon);
WCHAR szText[256]; LoadStringW(g_hInst, IDS_FINALIZE_STRING, szText, _countof(szText)); m_pFinalizeButton->SetToolTip(szText);
AddUIObj(m_pFinalizeButton);}
/// @implementedvoid CCompButtonFrameWindow::MoveShow(LONG x, LONG y, BOOL bShow){ INT nWidth = m_Margins.cxRightWidth + m_Margins.cxLeftWidth + 18; INT nHeight = m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 18; Move(x, y, nWidth + 4, nHeight + 4);
if (m_pFinalizeButton) { RECT rc = { 1, 1, nWidth + 1, nHeight + 1 }; m_pFinalizeButton->SetRect(&rc); }
Show(bShow);}
/// @implementedSTDMETHODIMP_(void) CCompButtonFrameWindow::OnCreate(HWND hWnd){ ::SetWindowTheme(hWnd, L"TOOLBAR", NULL);
ZeroMemory(&m_Margins, sizeof(m_Margins));
CUIFTheme theme; theme.m_hTheme = NULL; theme.m_iPartId = 1; theme.m_iStateId = 0; theme.m_pszClassList = L"TOOLBAR"; if (SUCCEEDED(theme.InternalOpenThemeData(hWnd))) theme.GetThemeMargins(NULL, 1, 3602, NULL, &m_Margins);}
/***********************************************************************/
/// @implementedCDefCompFrameWindow::CDefCompFrameWindow(HIMC hIMC, DWORD style) : CCompFrameWindow(hIMC, style){ LoadPosition(); m_iPartId = 1; m_iStateId = 1; m_pszClassList = L"TASKBAR";}
/// @implementedCDefCompFrameWindow::~CDefCompFrameWindow(){ SavePosition();}
/// @implementedvoid CDefCompFrameWindow::Init(){ RECT rc;
if (!m_pGripper) { ZeroMemory(&rc, sizeof(rc)); m_pGripper = new(cicNoThrow) CDefCompFrameGripper(this, &rc, 0); m_pGripper->Initialize(); AddUIObj(m_pGripper); }
if (!m_pFinalizeButton) { ZeroMemory(&rc, sizeof(rc)); m_pFinalizeButton = new(cicNoThrow) CCompFinalizeButton(this, 0, &rc, 0, 0x10000, NULL); m_pFinalizeButton->Initialize(); m_pFinalizeButton->Init();
HICON hIcon = (HICON)LoadImageW(g_hInst, MAKEINTRESOURCEW(IDI_DOWN), IMAGE_ICON, 16, 16, 0); m_pFinalizeButton->SetIcon(hIcon);
WCHAR szText[256]; ::LoadStringW(g_hInst, IDS_FINALIZE_STRING, szText, _countof(szText)); SetToolTip(szText);
AddUIObj(m_pFinalizeButton); }}
/// @implementedINT CDefCompFrameWindow::GetGripperWidth(){ if (!m_pGripper || FAILED(m_pGripper->EnsureThemeData(m_hWnd))) return 5;
INT ret = -1; HDC hDC = ::GetDC(m_hWnd); SIZE partSize; if (SUCCEEDED(m_pGripper->GetThemePartSize(hDC, 1, 0, TS_TRUE, &partSize))) ret = partSize.cx + 4;
::ReleaseDC(m_hWnd, hDC);
return ((ret < 0) ? 5 : ret);}
/// @implementedvoid CDefCompFrameWindow::MyScreenToClient(LPPOINT ppt, LPRECT prc){ if (ppt) ::ScreenToClient(m_hWnd, ppt);
if (prc) { ::ScreenToClient(m_hWnd, (LPPOINT)prc); ::ScreenToClient(m_hWnd, (LPPOINT)&prc->right); }}
/// @implementedvoid CDefCompFrameWindow::SetCompStrRect(INT nWidth, INT nHeight, BOOL bShow){ INT GripperWidth = GetGripperWidth();
RECT rc; ::GetWindowRect(m_hWnd, &rc);
Move(rc.left, rc.top, GripperWidth + nWidth + 24, nHeight + 10);
if (m_pGripper) { rc = { 2, 3, GripperWidth + 2, nHeight + 7 }; m_pGripper->SetRect(&rc); }
if (m_pFinalizeButton) { rc = { GripperWidth + nWidth + 4, 3, m_Margins.cxLeftWidth + m_Margins.cxRightWidth + GripperWidth + nWidth + 22, m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 21 }; m_pFinalizeButton->SetRect(&rc); }
Show(bShow);
::MoveWindow(m_hwndCompStr, GripperWidth + 2, 7, nWidth, nHeight, TRUE); ::ShowWindow(m_hwndCompStr, (bShow ? SW_SHOWNOACTIVATE : SW_HIDE));}
/// @implementedvoid CDefCompFrameWindow::LoadPosition(){ DWORD x = 0, y = 0;
LSTATUS error; CicRegKey regKey; error = regKey.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\CUAS\\DefaultCompositionWindow")); if (error == ERROR_SUCCESS) { regKey.QueryDword(TEXT("Left"), &x); regKey.QueryDword(TEXT("Top"), &y); }
Move(x, y, 0, 0);}
/// @implementedvoid CDefCompFrameWindow::SavePosition(){ LSTATUS error; CicRegKey regKey; error = regKey.Create(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\CUAS\\DefaultCompositionWindow")); if (error == ERROR_SUCCESS) { regKey.SetDword(TEXT("Left"), m_nLeft); regKey.SetDword(TEXT("Top"), m_nTop); }}
/// @implementedSTDMETHODIMP_(void) CDefCompFrameWindow::OnCreate(HWND hWnd){ ::SetWindowTheme(hWnd, L"TASKBAR", NULL);
ZeroMemory(&m_Margins, sizeof(m_Margins));
CUIFTheme theme; theme.m_hTheme = NULL; theme.m_iPartId = 1; theme.m_iStateId = 0; theme.m_pszClassList = L"TOOLBAR"; if (SUCCEEDED(theme.InternalOpenThemeData(hWnd))) GetThemeMargins(NULL, 1, 3602, NULL, &m_Margins);}
/// @implementedSTDMETHODIMP_(BOOL) CDefCompFrameWindow::OnSetCursor(UINT uMsg, LONG x, LONG y){ if (!::IsWindow(m_hwndCompStr)) return FALSE;
RECT rc; ::GetWindowRect(m_hwndCompStr, &rc); MyScreenToClient(NULL, &rc); POINT pt = { x, y }; return ::PtInRect(&rc, pt);}
/// @implementedSTDMETHODIMP_(LRESULT)CDefCompFrameWindow::OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ CicIMCLock imcLock(m_hIMC); if (SUCCEEDED(imcLock.m_hr)) ::SendMessage(imcLock.get().hWnd, WM_IME_NOTIFY, 0xF, (LPARAM)m_hIMC); return ::DefWindowProc(hWnd, uMsg, wParam, lParam);}
/// @implementedSTDMETHODIMP_(void) CDefCompFrameWindow::HandleMouseMsg(UINT uMsg, LONG x, LONG y){ if (::IsWindow(m_hwndCompStr)) { RECT rc; ::GetWindowRect(m_hwndCompStr, &rc); MyScreenToClient(NULL, &rc);
POINT pt = { x, y }; if (::PtInRect(&rc, pt)) ::SendMessage(m_hwndCompStr, 0x7E8, 0, 0); }
CUIFWindow::HandleMouseMsg(uMsg, x, y);}
/***********************************************************************/
/// @implementedPOLYTEXTW *CPolyText::GetPolyAt(INT iItem){ return &m_PolyTextArray[iItem];}
/// @implementedHRESULT CPolyText::ShiftPolyText(INT xDelta, INT yDelta){ for (size_t iItem = 0; iItem < m_PolyTextArray.size(); ++iItem) { POLYTEXTW *pPolyText = &m_PolyTextArray[iItem]; pPolyText->x += xDelta; pPolyText->y += yDelta; ::OffsetRect((LPRECT)&pPolyText->rcl, xDelta, yDelta); } return S_OK;}
/// @implementedHRESULT CPolyText::RemoveLastLine(BOOL bHorizontal){ size_t iItem, cItems = m_PolyTextArray.size(); if (!cItems) return E_FAIL;
POLYTEXTW *pData1 = &m_PolyTextArray[cItems - 1];
for (iItem = 0; iItem < cItems; ++iItem) { POLYTEXTW *pData2 = &m_PolyTextArray[iItem]; if (bHorizontal) { if (pData1->x == pData2->x) break; } else { if (pData1->y == pData2->y) break; } }
if (iItem >= cItems) return E_FAIL;
m_PolyTextArray.Remove(iItem, cItems - iItem); m_ValueArray.Remove(iItem, cItems - iItem); return S_OK;}
/// @implementedvoid CPolyText::RemoveAll(){ m_PolyTextArray.clear(); m_ValueArray.clear();}
/***********************************************************************/
/// @implementedvoid COMPWND::_ClientToScreen(LPRECT prc){ ::ClientToScreen(m_hWnd, (LPPOINT)prc); ::ClientToScreen(m_hWnd, (LPPOINT)&prc->right);}
/***********************************************************************/
// For GetWindowLongPtr/SetWindowLongPtr#define UICOMP_GWLP_INDEX 0#define UICOMP_GWLP_SIZE (UICOMP_GWLP_INDEX + sizeof(INT))
/// @unimplementedUIComposition::UIComposition(HWND hwndParent){}
/// @implementedUIComposition::~UIComposition(){ DestroyCompositionWindow();
if (m_hFont1) { ::DeleteObject(m_hFont1); m_hFont1 = NULL; }
if (m_hFont2) { ::DeleteObject(m_hFont2); m_hFont2 = NULL; }
if (m_strCompStr) { cicMemFree(m_strCompStr); m_strCompStr = NULL; }
m_cchCompStr = 0;}
// @implementedBOOL UIComposition::SendMessageToUI(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam){ HWND hImeWnd = ImmGetDefaultIMEWnd(0); if (!::IsWindow(hImeWnd)) return TRUE; TLS *pTLS = TLS::GetTLS(); LRESULT ret; if (pTLS && pTLS->m_cWnds > 1) ret = ::SendMessage(imcLock.get().hWnd, WM_IME_NOTIFY, wParam, lParam); else ret = ::SendMessage(hImeWnd, WM_IME_NOTIFY, wParam, lParam); return !ret;}
/// @implementedHRESULT UIComposition::CreateDefFrameWnd(HWND hwndParent, HIMC hIMC){ if (!m_pDefCompFrameWindow) { m_pDefCompFrameWindow = new(cicNoThrow) CDefCompFrameWindow(hIMC, 0x800000A4); if (!m_pDefCompFrameWindow) return E_OUTOFMEMORY; if (!m_pDefCompFrameWindow->Initialize()) { delete m_pDefCompFrameWindow; m_pDefCompFrameWindow = NULL; return E_FAIL; }
m_pDefCompFrameWindow->Init(); }
m_pDefCompFrameWindow->CreateWnd(hwndParent); return S_OK;}
/// @implementedHRESULT UIComposition::CreateCompButtonWnd(HWND hwndParent, HIMC hIMC){ TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->NonEACompositionEnabled()) return S_OK;
if (IsEALang(0)) { if (m_pCompButtonFrameWindow) { delete m_pCompButtonFrameWindow; m_pCompButtonFrameWindow = NULL; } return S_OK; }
if (!m_pCompButtonFrameWindow) { m_pCompButtonFrameWindow = new(cicNoThrow) CCompButtonFrameWindow(hIMC, 0x800000B4); if (!m_pCompButtonFrameWindow) return E_OUTOFMEMORY;
if (!m_pCompButtonFrameWindow->Initialize()) { if (m_pCompButtonFrameWindow) { delete m_pCompButtonFrameWindow; m_pCompButtonFrameWindow = NULL; } return E_FAIL; }
m_pCompButtonFrameWindow->Init(); }
m_pCompButtonFrameWindow->CreateWnd(hwndParent); return S_OK;}
/// @implementedHRESULT UIComposition::CreateCompositionWindow(CicIMCLock& imcLock, HWND hwndParent){ if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
if (!::IsWindow(hwndParent) || m_bHasCompWnd) return E_FAIL;
for (INT iCompStr = 0; iCompStr < 3; ++iCompStr) { DWORD style = WS_POPUP | WS_DISABLED; HWND hwndCompStr = ::CreateWindowExW(0, L"MSCTFIME Composition", NULL, style, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL); m_CompStrs[iCompStr].m_hWnd = hwndCompStr; ::SetWindowLongPtrW(hwndCompStr, GWLP_USERDATA, (LONG_PTR)this); ::SetWindowLongPtrW(hwndCompStr, UICOMP_GWLP_INDEX, iCompStr); m_CompStrs[iCompStr].m_Caret.CreateCaret(hwndCompStr, m_CaretSize); }
HRESULT hr = CreateCompButtonWnd(hwndParent, imcLock.m_hIMC); if (FAILED(hr)) { DestroyCompositionWindow(); return E_OUTOFMEMORY; }
hr = CreateDefFrameWnd(hwndParent, imcLock.m_hIMC); if (FAILED(hr)) { DestroyCompositionWindow(); return E_OUTOFMEMORY; }
DWORD style = WS_CHILD | WS_DISABLED; HWND hwndCompStr = ::CreateWindowExW(WS_EX_CLIENTEDGE, L"MSCTFIME Composition", NULL, style, 0, 0, 0, 0, *m_pDefCompFrameWindow, NULL, g_hInst, NULL); if (!hwndCompStr) { DestroyCompositionWindow(); return E_OUTOFMEMORY; }
m_CompStrs[3].m_hWnd = hwndCompStr; m_pDefCompFrameWindow->m_hwndCompStr = hwndCompStr; ::SetWindowLongPtrW(hwndCompStr, GWLP_USERDATA, (LONG_PTR)this); ::SetWindowLongPtrW(hwndCompStr, UICOMP_GWLP_INDEX, -1); m_CompStrs[3].m_Caret.CreateCaret(hwndCompStr, m_CaretSize); m_bHasCompWnd = TRUE;
return S_OK;}
/// @implementedHRESULT UIComposition::DestroyCompositionWindow(){ for (INT i = 0; i < 4; ++i) { COMPWND *pCompStr = &m_CompStrs[i]; pCompStr->m_Caret.DestroyCaret(); if (::IsWindow(pCompStr->m_hWnd)) { DestroyWindow(pCompStr->m_hWnd); pCompStr->m_PolyText.RemoveAll(); } pCompStr->m_hWnd = NULL; }
if (m_pCompButtonFrameWindow) { ::DestroyWindow(*m_pCompButtonFrameWindow); delete m_pCompButtonFrameWindow; m_pCompButtonFrameWindow = NULL; }
if (m_pDefCompFrameWindow) { ::DestroyWindow(*m_pDefCompFrameWindow); delete m_pDefCompFrameWindow; m_pDefCompFrameWindow = NULL; }
return 0;}
// @implementedBOOL UIComposition::InquireImeUIWndState(CicIMCLock& imcLock){ BOOL bValue = FALSE; UIComposition::SendMessageToUI(imcLock, 0x11u, (LPARAM)&bValue); return bValue;}
/// @implementedHRESULT UIComposition::UpdateShowCompWndFlag(CicIMCLock& imcLock, DWORD *pdwCompStrLen){ if (FAILED(imcLock.m_hr)) return imcLock.m_hr; if (!::IsWindow(imcLock.get().hWnd)) return E_FAIL;
CicIMCCLock<COMPOSITIONSTRING> compStr(imcLock.get().hCompStr); if (FAILED(compStr.m_hr)) return compStr.m_hr;
if ((m_dwUnknown56[0] & 0x80000000) && compStr.get().dwCompStrLen) m_bHasCompStr = TRUE; else m_bHasCompStr = FALSE;
if (pdwCompStrLen) *pdwCompStrLen = compStr.get().dwCompStrLen;
return S_OK;}
/// @implementedHRESULT UIComposition::UpdateFont(CicIMCLock& imcLock){ if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
if (m_hFont1) ::DeleteObject(m_hFont1); if (m_hFont2) ::DeleteObject(m_hFont2);
LOGFONTW lf = imcLock.get().lfFont.W; m_hFont2 = ::CreateFontIndirectW(&lf);
lf.lfEscapement = 0; lf.lfOrientation = 0; BOOL bVertical = (lf.lfFaceName[0] == L'@'); if (bVertical) { MoveMemory(lf.lfFaceName, &lf.lfFaceName[1], sizeof(lf.lfFaceName) - sizeof(WCHAR)); lf.lfFaceName[_countof(lf.lfFaceName) - 1] = UNICODE_NULL; } m_hFont1 = ::CreateFontIndirectW(&lf);
return S_OK;}
// @implementedvoid UIComposition::OnTimer(HWND hWnd){ INT iCompStr = (INT)::GetWindowLongPtrW(hWnd, UICOMP_GWLP_INDEX); if (iCompStr == -1) m_CompStrs[3].m_Caret.OnTimer(); else m_CompStrs[iCompStr].m_Caret.OnTimer();}
/// @implementedBOOL UIComposition::GetImeUIWndTextExtent(CicIMCLock& imcLock, LPARAM lParam){ return !UIComposition::SendMessageToUI(imcLock, 0x14, lParam);}
/// @implementedLPWSTR UIComposition::GetCompStrBuffer(INT cchStr){ if (!m_strCompStr) { m_strCompStr = (LPWSTR)cicMemAllocClear((cchStr + 1) * sizeof(WCHAR)); m_cchCompStr = cchStr; } if (m_cchCompStr < cchStr) { m_strCompStr = (LPWSTR)cicMemReAlloc(m_strCompStr, (cchStr + 1) * sizeof(WCHAR)); m_cchCompStr = cchStr; } return m_strCompStr;}
/// @unimplementedvoid UIComposition::OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd){ //FIXME}
/// @implementedHRESULT UIComposition::OnImeCompositionUpdate(CicIMCLock& imcLock){ m_dwUnknown56[0] |= 0x8000; return UIComposition::UpdateShowCompWndFlag(imcLock, NULL);}
/// @unimplementedHRESULT UIComposition::OnImeEndComposition(){ m_dwUnknown56[0] = 0; return DestroyCompositionWindow();}
/// @unimplementedvoid UIComposition::OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam){ //FIXME}
/// @unimplementedvoid UIComposition::OnPaintTheme(WPARAM wParam){ //FIXME}
/// @implementedHRESULT UIComposition::OnDestroy(){ return DestroyCompositionWindow();}
/// @unimplementedLRESULT CALLBACKUIComposition::CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ if (uMsg == WM_CREATE) return -1; // FIXME return 0;}
/// @implementedHRESULT UIComposition::OnImeNotifySetCompositionWindow(CicIMCLock& imcLock){ return UpdateCompositionRect(imcLock);}
/// @unimplementedHRESULT UIComposition::UpdateCompositionRect(CicIMCLock& imcLock){ return E_NOTIMPL;}
/// @implementedINT UIComposition::GetLevelFromIMC(CicIMCLock& imcLock){ DWORD dwStyle = imcLock.get().cfCompForm.dwStyle; if (dwStyle == CFS_DEFAULT) return 1; if (!(dwStyle & (CFS_FORCE_POSITION | CFS_POINT | CFS_RECT))) return 0;
RECT rc; ::GetClientRect(imcLock.get().hWnd, &rc); if (!::PtInRect(&rc, imcLock.get().cfCompForm.ptCurrentPos)) return 1;
INPUTCONTEXT *pIC = &imcLock.get(); if ((pIC->cfCompForm.dwStyle & CFS_RECT) && (pIC->cfCompForm.rcArea.top == pIC->cfCompForm.rcArea.bottom) && (pIC->cfCompForm.rcArea.left == pIC->cfCompForm.rcArea.right)) { return 1; }
return 2;}
/// @implementedHRESULT UIComposition::OnImeSetContextAfter(CicIMCLock& imcLock){ if ((!m_pDefCompFrameWindow || !::IsWindow(*m_pDefCompFrameWindow)) && !::IsWindow(m_CompStrs[0].m_hWnd)) { m_dwUnknown56[0] &= ~0x8000; return S_OK; }
if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
INT Level = GetLevelFromIMC(imcLock); if ((Level == 1 || Level == 2) && (m_dwUnknown56[0] & 0x80000000) && m_dwUnknown56[1]) { DWORD dwCompStrLen = 0; UpdateShowCompWndFlag(imcLock, &dwCompStrLen);
if (Level == 1) { ::ShowWindow(*m_pDefCompFrameWindow, (m_bHasCompStr ? SW_SHOWNOACTIVATE : SW_HIDE)); } else if (Level == 2 && !m_bHasCompStr && dwCompStrLen) { for (INT iCompStr = 0; iCompStr < 3; ++iCompStr) { m_CompStrs[iCompStr].m_Caret.HideCaret(); ::ShowWindow(m_CompStrs[iCompStr].m_Caret, SW_HIDE); } } } else { ::ShowWindow(*m_pDefCompFrameWindow, SW_HIDE);
for (INT iCompStr = 0; iCompStr < 3; ++iCompStr) { m_CompStrs[iCompStr].m_Caret.HideCaret(); ::ShowWindow(m_CompStrs[iCompStr].m_Caret, SW_HIDE); } }
return S_OK;}
/***********************************************************************/
// For GetWindowLongPtr/SetWindowLongPtr#define UI_GWLP_HIMC 0#define UI_GWLP_UI sizeof(HIMC)#define UI_GWLP_SIZE (UI_GWLP_UI + sizeof(UI*))
/// @implementedUI::UI(HWND hWnd) : m_hWnd(hWnd){}
/// @implementedUI::~UI(){ delete m_pComp;}
/// @implementedHRESULT UI::_Create(){ m_pComp = new(cicNoThrow) UIComposition(m_hWnd); if (!m_pComp) return E_OUTOFMEMORY;
::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, (LONG_PTR)this); return S_OK;}
/// @implementedvoid UI::_Destroy(){ m_pComp->OnDestroy(); ::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, 0);}
/// @implementedvoid UI::OnCreate(HWND hWnd){ UI *pUI = (UI*)::GetWindowLongPtrW(hWnd, UI_GWLP_UI); if (pUI) return; pUI = new(cicNoThrow) UI(hWnd); if (pUI) pUI->_Create();}
/// @implementedvoid UI::OnDestroy(HWND hWnd){ UI *pUI = (UI*)::GetWindowLongPtrW(hWnd, UI_GWLP_UI); if (!pUI) return;
pUI->_Destroy(); delete pUI;}
/// @implementedvoid UI::OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam){ m_pComp->OnImeSetContext(imcLock, m_hWnd, wParam, lParam);}
/***********************************************************************/
struct CIMEUIWindowHandler{ static LRESULT CALLBACK ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static HRESULT CALLBACK ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static HRESULT CALLBACK ImeUIDelayedReconvertFuncCall(HWND hWnd); static HRESULT CALLBACK ImeUIOnLayoutChange(LPARAM lParam); static HRESULT CALLBACK ImeUIPrivateHandler(UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK ImeUINotifyHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);};
/// @implementedHRESULT CALLBACKCIMEUIWindowHandler::ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam){ if ((BYTE)wParam == 0xFF) return TRUE;
CicIMCLock imcLock((HIMC)lParam); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return FALSE;
HRESULT hr = E_FAIL; CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC) { UINT keys = 0; if (wParam & MK_LBUTTON) keys |= 0x1; if (wParam & MK_SHIFT) keys |= 0x10; if (wParam & MK_RBUTTON) keys |= 0x2; if (wParam & MK_MBUTTON) keys |= 0x780000; else if (wParam & MK_ALT) keys |= 0xFF880000; hr = pCicIC->MsImeMouseHandler(HIWORD(wParam), HIBYTE(LOWORD(wParam)), keys, imcLock); }
return hr;}
/// @implementedHRESULT CALLBACK CIMEUIWindowHandler::ImeUIOnLayoutChange(LPARAM lParam){ CicIMCLock imcLock((HIMC)lParam); if (FAILED(imcLock.m_hr)) return S_OK;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return S_OK;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC) { auto pContextOwnerServices = pCicIC->m_pContextOwnerServices; pContextOwnerServices->AddRef(); pContextOwnerServices->OnLayoutChange(); pContextOwnerServices->Release(); }
return S_OK;}
/// @implementedHRESULT CALLBACKCIMEUIWindowHandler::ImeUIPrivateHandler(UINT uMsg, WPARAM wParam, LPARAM lParam){ CicIMCLock imcLock((HIMC)lParam); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC && wParam == 0x10) pCicIC->EscbClearDocFeedBuffer(imcLock, TRUE);
return S_OK;}
/// @implementedLRESULT CALLBACKCIMEUIWindowHandler::ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam){ if (!wParam) return TRUE;
CicIMCLock imcLock((HIMC)lParam); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return FALSE;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return FALSE;
if (wParam == 1) { if (lParam == 0 || lParam == 1 || lParam == 4 || lParam == 0x10000) { GUID guid = pCicIC->m_ModeBias.ConvertModeBias((DWORD)lParam); pCicIC->m_ModeBias.SetModeBias(guid);
pCicIC->m_dwUnknown7[2] |= 1; pCicIC->m_pContextOwnerServices->AddRef(); pCicIC->m_pContextOwnerServices->OnAttributeChange(GUID_PROP_MODEBIAS); pCicIC->m_pContextOwnerServices->Release(); return TRUE; } } else if (wParam == 2) { return pCicIC->m_ModeBias.ConvertModeBias(pCicIC->m_ModeBias.m_guid); }
return FALSE;}
/// @implementedLRESULT CALLBACKCIMEUIWindowHandler::ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam){ if (wParam == 0x10000000) return TRUE;
HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return FALSE;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return FALSE;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; TLS *pTLS = TLS::GetTLS(); if (!pCicIC || !pTLS) return FALSE;
auto pThreadMgr = pTLS->m_pThreadMgr; auto pProfile = pTLS->m_pProfile; if (!pThreadMgr || !pProfile) return FALSE;
UINT uCodePage = 0; pProfile->GetCodePageA(&uCodePage); pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, WM_MSIME_RECONVERT, FALSE); pCicIC->EndReconvertString(imcLock); return TRUE;}
/// @implementedLRESULT CALLBACKCIMEUIWindowHandler::ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ if (uMsg == WM_MSIME_MOUSE) return ImeUIMsImeMouseHandler(hWnd, wParam, lParam); if (uMsg == WM_MSIME_MODEBIAS) return ImeUIMsImeModeBiasHandler(hWnd, wParam, lParam); if (uMsg == WM_MSIME_RECONVERTREQUEST) return ImeUIMsImeReconvertRequest(hWnd, wParam, lParam); if (uMsg == WM_MSIME_SERVICE) { TLS *pTLS = TLS::GetTLS(); if (pTLS && pTLS->m_pProfile) { LANGID LangID; pTLS->m_pProfile->GetLangId(&LangID); if (PRIMARYLANGID(LangID) == LANG_KOREAN) return FALSE; } return TRUE; } return 0;}
/// @implementedHRESULT CALLBACKCIMEUIWindowHandler::ImeUIDelayedReconvertFuncCall(HWND hWnd){ HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr; CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr; CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC) pCicIC->DelayedReconvertFuncCall(imcLock); return S_OK;}
/// @unimplementedLRESULT CALLBACKCIMEUIWindowHandler::ImeUINotifyHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr; CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC) { switch (wParam) { case IMN_CLOSECANDIDATE: { pCicIC->m_bCandidateOpen = FALSE; HWND hImeWnd = ::ImmGetDefaultIMEWnd(NULL); if (::IsWindow(hImeWnd)) ::PostMessage(hImeWnd, WM_IME_NOTIFY, 0x10, (LPARAM)hIMC); break; } case IMN_OPENCANDIDATE: { pCicIC->m_bCandidateOpen = TRUE; pCicIC->ClearPrevCandidatePos(); break; } case IMN_SETCANDIDATEPOS: { //FIXME break; } case IMN_SETCOMPOSITIONFONT: { //FIXME break; } case IMN_SETCOMPOSITIONWINDOW: { //FIXME break; } case 0xF: { CIMEUIWindowHandler::ImeUIOnLayoutChange(lParam); break; } case 0x10: { CIMEUIWindowHandler::ImeUIPrivateHandler(uMsg, 0x10, lParam); break; } case 0x13: { CIMEUIWindowHandler::ImeUIOnLayoutChange(lParam); break; } case 0x14: { //FIXME break; } case 0x16: { ::SetTimer(hWnd, 2, 100, NULL); break; } case 0x17: { return (LRESULT)hWnd; } case 0x10D: { //FIXME break; } case 0x10E: pCicIC->m_dwQueryPos = 0; break; } }
return 0;}
/// @implementedLRESULT CALLBACKCIMEUIWindowHandler::ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ TLS *pTLS = TLS::GetTLS(); if (pTLS && (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON)) { if (uMsg == WM_CREATE) return -1; return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); }
switch (uMsg) { case WM_CREATE: { UI::OnCreate(hWnd); break; } case WM_DESTROY: case WM_ENDSESSION: { UI::OnDestroy(hWnd); break; } case WM_IME_STARTCOMPOSITION: case WM_IME_COMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY: case WM_IME_SELECT: case WM_TIMER: { HIMC hIMC = (HIMC)GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); UI* pUI = (UI*)GetWindowLongPtrW(hWnd, UI_GWLP_UI); CicIMCLock imcLock(hIMC); switch (uMsg) { case WM_IME_STARTCOMPOSITION: { pUI->m_pComp->OnImeStartComposition(imcLock, pUI->m_hWnd); break; } case WM_IME_COMPOSITION: { if (lParam & GCS_COMPSTR) { pUI->m_pComp->OnImeCompositionUpdate(imcLock); ::SetTimer(hWnd, 0, 10, NULL); pUI->m_pComp->m_bInComposition = TRUE; } break; } case WM_IME_ENDCOMPOSITION: { ::KillTimer(hWnd, 0); pUI->m_pComp->OnImeEndComposition(); break; } case WM_IME_SETCONTEXT: { pUI->OnImeSetContext(imcLock, wParam, lParam); ::KillTimer(hWnd, 1); ::SetTimer(hWnd, 1, 300, NULL); break; } case WM_TIMER: { switch (wParam) { case 0: ::KillTimer(hWnd, wParam); pUI->m_pComp->m_bInComposition = FALSE; pUI->m_pComp->OnImeNotifySetCompositionWindow(imcLock); break; case 1: ::KillTimer(hWnd, wParam); pUI->m_pComp->OnImeSetContextAfter(imcLock); break; case 2: ::KillTimer(hWnd, wParam); CIMEUIWindowHandler::ImeUIDelayedReconvertFuncCall(hWnd); break; default: break; } break; } case WM_IME_NOTIFY: case WM_IME_SELECT: default: { pUI->m_pComp->OnPaintTheme(wParam); break; } } break; } default: { if (IsMsImeMessage(uMsg)) return CIMEUIWindowHandler::ImeUIMsImeHandler(hWnd, uMsg, wParam, lParam); return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); } }
return 0;}
/***********************************************************************/
/// @implementedEXTERN_C LRESULT CALLBACKUIWndProc( _In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam){ return CIMEUIWindowHandler::ImeUIWndProcWorker(hWnd, uMsg, wParam, lParam);}
/***********************************************************************/
/// @implementedBOOL RegisterImeClass(VOID){ WNDCLASSEXW wcx;
if (!GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx)) { ZeroMemory(&wcx, sizeof(wcx)); wcx.cbSize = sizeof(WNDCLASSEXW); wcx.cbWndExtra = UI_GWLP_SIZE; wcx.hIcon = LoadIconW(0, (LPCWSTR)IDC_ARROW); wcx.hInstance = g_hInst; wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wcx.style = CS_IME | CS_GLOBALCLASS; wcx.lpfnWndProc = UIWndProc; wcx.lpszClassName = L"MSCTFIME UI"; if (!RegisterClassExW(&wcx)) return FALSE; }
if (!GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx)) { ZeroMemory(&wcx, sizeof(wcx)); wcx.cbSize = sizeof(WNDCLASSEXW); wcx.cbWndExtra = UICOMP_GWLP_SIZE; wcx.hIcon = NULL; wcx.hInstance = g_hInst; wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_IBEAM); wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wcx.style = CS_IME | CS_HREDRAW | CS_VREDRAW; wcx.lpfnWndProc = UIComposition::CompWndProc; wcx.lpszClassName = L"MSCTFIME Composition"; if (!RegisterClassExW(&wcx)) return FALSE; }
return TRUE;}
/// @implementedVOID UnregisterImeClass(VOID){ WNDCLASSEXW wcx;
GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx); UnregisterClassW(L"MSCTFIME UI", g_hInst); DestroyIcon(wcx.hIcon); DestroyIcon(wcx.hIconSm);
GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx); UnregisterClassW(L"MSCTFIME Composition", g_hInst); DestroyIcon(wcx.hIcon); DestroyIcon(wcx.hIconSm);}