Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913/* * PROJECT: ReactOS msctfime.ime * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: The bridge of msctfime.ime * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "msctfime.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
/// @implementedCicBridge::CicBridge(){ m_bImmxInited = FALSE; m_bUnknown1 = FALSE; m_bDeactivating = FALSE; m_bUnknown2 = FALSE; m_pKeystrokeMgr = NULL; m_pDocMgr = NULL; m_pThreadMgrEventSink = NULL; m_cliendId = 0; m_cRefs = 1;}
/// @implementedSTDMETHODIMP CicBridge::QueryInterface(REFIID riid, LPVOID* ppvObj){ static const QITAB c_tab[] = { QITABENT(CicBridge, ITfSysHookSink), { NULL } }; return ::QISearch(this, c_tab, riid, ppvObj);}
/// @implementedSTDMETHODIMP_(ULONG) CicBridge::AddRef(){ return ::InterlockedIncrement(&m_cRefs);}
/// @implementedSTDMETHODIMP_(ULONG) CicBridge::Release(){ if (::InterlockedDecrement(&m_cRefs) == 0) { delete this; return 0; } return m_cRefs;}
/// @implementedCicBridge::~CicBridge(){ TLS *pTLS = TLS::PeekTLS(); if (!pTLS || !pTLS->m_pThreadMgr) return;
if (SUCCEEDED(DeactivateIMMX(pTLS, pTLS->m_pThreadMgr))) UnInitIMMX(pTLS);}
/// @implementedITfDocumentMgr*CicBridge::GetDocumentManager(_Inout_ CicIMCCLock<CTFIMECONTEXT>& imeContext){ CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return NULL;
pCicIC->m_pDocumentMgr->AddRef(); return pCicIC->m_pDocumentMgr;}
/// @implementedHRESULTCicBridge::CreateInputContext( _Inout_ TLS *pTLS, _In_ HIMC hIMC){ CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
if (!imcLock.get().hCtfImeContext) { HIMCC hCtfImeContext = ImmCreateIMCC(sizeof(CTFIMECONTEXT)); if (!hCtfImeContext) return E_OUTOFMEMORY; imcLock.get().hCtfImeContext = hCtfImeContext; }
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC) return S_OK;
pCicIC = new(cicNoThrow) CicInputContext(m_cliendId, &m_LibThread, hIMC); if (!pCicIC) { imeContext.unlock(); imcLock.unlock(); DestroyInputContext(pTLS, hIMC); return E_OUTOFMEMORY; }
if (!pTLS->m_pThreadMgr) { pCicIC->Release(); imeContext.unlock(); imcLock.unlock(); DestroyInputContext(pTLS, hIMC); return E_NOINTERFACE; }
imeContext.get().m_pCicIC = pCicIC;
HRESULT hr = pCicIC->CreateInputContext(pTLS->m_pThreadMgr, imcLock); if (FAILED(hr)) { pCicIC->Release(); imeContext.get().m_pCicIC = NULL; return hr; }
HWND hWnd = imcLock.get().hWnd; if (hWnd && hWnd == ::GetFocus()) { ITfDocumentMgr *pDocMgr = GetDocumentManager(imeContext); if (pDocMgr) { SetAssociate(pTLS, hWnd, hIMC, pTLS->m_pThreadMgr, pDocMgr); pDocMgr->Release(); } }
return hr;}
/// @implementedHRESULT CicBridge::DestroyInputContext(TLS *pTLS, HIMC hIMC){ CicIMCLock imcLock(hIMC); HRESULT hr = imcLock.m_hr; if (FAILED(hr)) return hr;
hr = E_FAIL; CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (imeContext) hr = imeContext.m_hr;
if (SUCCEEDED(hr) && !(imeContext.get().m_dwCicFlags & 1)) { imeContext.get().m_dwCicFlags |= 1;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (pCicIC) { imeContext.get().m_pCicIC = NULL; hr = pCicIC->DestroyInputContext(); pCicIC->Release(); imeContext.get().m_pCicIC = NULL; } }
if (imcLock.get().hCtfImeContext) { ImmDestroyIMCC(imcLock.get().hCtfImeContext); imcLock.get().hCtfImeContext = NULL; hr = S_OK; }
return hr;}
/// @implementedITfContext *CicBridge::GetInputContext(CicIMCCLock<CTFIMECONTEXT>& imeContext){ CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return NULL; return pCicIC->m_pContext;}
/// @implementedHRESULT CicBridge::OnSetOpenStatus( TLS *pTLS, ITfThreadMgr_P *pThreadMgr, CicIMCLock& imcLock, CicInputContext *pCicIC){ if (!imcLock.get().fOpen && imcLock.ValidCompositionString()) pCicIC->EscbCompComplete(imcLock);
pTLS->m_bNowOpening = TRUE; HRESULT hr = SetCompartmentDWORD(m_cliendId, pThreadMgr, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, imcLock.get().fOpen, FALSE); pTLS->m_bNowOpening = FALSE; return hr;}
/// Selects the IME context./// @implementedHRESULTCicBridge::SelectEx( _Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr, _In_ HIMC hIMC, _In_ BOOL fSelect, _In_ HKL hKL){ 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->m_bSelecting = TRUE;
if (fSelect) { if (pCicIC) pCicIC->m_bCandidateOpen = FALSE; if (imcLock.get().fOpen) OnSetOpenStatus(pTLS, pThreadMgr, imcLock, pCicIC); } else { ITfContext *pContext = GetInputContext(imeContext); pThreadMgr->RequestPostponedLock(pContext); if (pCicIC) pCicIC->m_bSelecting = FALSE; if (pContext) pContext->Release(); }
return imeContext.m_hr;}
/// Used in CicBridge::EnumCreateInputContextCallback and/// CicBridge::EnumDestroyInputContextCallback.typedef struct ENUM_CREATE_DESTROY_IC{ TLS *m_pTLS; CicBridge *m_pBridge;} ENUM_CREATE_DESTROY_IC, *PENUM_CREATE_DESTROY_IC;
/// Creates input context for the current thread./// @implementedBOOL CALLBACK CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam){ PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; pData->m_pBridge->CreateInputContext(pData->m_pTLS, hIMC); return TRUE;}
/// Destroys input context for the current thread./// @implementedBOOL CALLBACK CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam){ PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; pData->m_pBridge->DestroyInputContext(pData->m_pTLS, hIMC); return TRUE;}
/// @implementedHRESULTCicBridge::ActivateIMMX( _Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr){ HRESULT hr = pThreadMgr->ActivateEx(&m_cliendId, 1); if (hr != S_OK) { m_cliendId = 0; return E_FAIL; }
if (m_cActivateLocks++ != 0) return S_OK;
ITfSourceSingle *pSource = NULL; hr = pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void**)&pSource); if (FAILED(hr)) { DeactivateIMMX(pTLS, pThreadMgr); return hr; }
CFunctionProvider *pProvider = new(cicNoThrow) CFunctionProvider(m_cliendId); if (!pProvider) { hr = E_FAIL; goto Finish; }
pSource->AdviseSingleSink(m_cliendId, IID_ITfFunctionProvider, pProvider); pProvider->Release();
if (!m_pDocMgr) { hr = pThreadMgr->CreateDocumentMgr(&m_pDocMgr); if (FAILED(hr)) { hr = E_FAIL; goto Finish; }
SetCompartmentDWORD(m_cliendId, m_pDocMgr, GUID_COMPARTMENT_CTFIME_DIMFLAGS, TRUE, FALSE); }
pThreadMgr->SetSysHookSink(this);
hr = S_OK; if (pTLS->m_bDestroyed) { ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; ImmEnumInputContext(0, CicBridge::EnumCreateInputContextCallback, (LPARAM)&Data); }
Finish: if (FAILED(hr)) DeactivateIMMX(pTLS, pThreadMgr); if (pSource) pSource->Release(); return hr;}
/// @implementedHRESULTCicBridge::DeactivateIMMX( _Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr){ if (m_bDeactivating) return TRUE;
m_bDeactivating = TRUE;
if (m_cliendId) { ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; ImmEnumInputContext(0, CicBridge::EnumDestroyInputContextCallback, (LPARAM)&Data); pTLS->m_bDestroyed = TRUE;
ITfSourceSingle *pSource = NULL; if (pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSource) == S_OK) pSource->UnadviseSingleSink(m_cliendId, IID_ITfFunctionProvider);
m_cliendId = 0;
while (m_cActivateLocks > 0) { --m_cActivateLocks; pThreadMgr->Deactivate(); }
if (pSource) pSource->Release(); }
if (m_pDocMgr) { m_pDocMgr->Release(); m_pDocMgr = NULL; }
pThreadMgr->SetSysHookSink(NULL);
m_bDeactivating = FALSE;
return S_OK;}
/// @implementedHRESULTCicBridge::InitIMMX(_Inout_ TLS *pTLS){ if (m_bImmxInited) return S_OK;
HRESULT hr = S_OK; if (!pTLS->m_pThreadMgr) { ITfThreadMgr *pThreadMgr = NULL; hr = TF_CreateThreadMgr(&pThreadMgr); if (FAILED(hr)) return E_FAIL;
hr = pThreadMgr->QueryInterface(IID_ITfThreadMgr_P, (void **)&pTLS->m_pThreadMgr); if (pThreadMgr) pThreadMgr->Release(); if (FAILED(hr)) return E_FAIL; }
if (!m_pThreadMgrEventSink) { m_pThreadMgrEventSink = new(cicNoThrow) CThreadMgrEventSink(CThreadMgrEventSink::DIMCallback, NULL, NULL); if (!m_pThreadMgrEventSink) { UnInitIMMX(pTLS); return E_FAIL; } }
m_pThreadMgrEventSink->SetCallbackPV(m_pThreadMgrEventSink); m_pThreadMgrEventSink->_Advise(pTLS->m_pThreadMgr);
if (!pTLS->m_pProfile) { pTLS->m_pProfile = new(cicNoThrow) CicProfile(); if (!pTLS->m_pProfile) return E_OUTOFMEMORY;
hr = pTLS->m_pProfile->InitProfileInstance(pTLS); if (FAILED(hr)) { UnInitIMMX(pTLS); return E_FAIL; } }
hr = pTLS->m_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr_P, (void **)&m_pKeystrokeMgr); if (FAILED(hr)) { UnInitIMMX(pTLS); return E_FAIL; }
hr = InitDisplayAttrbuteLib(&m_LibThread); if (FAILED(hr)) { UnInitIMMX(pTLS); return E_FAIL; }
m_bImmxInited = TRUE; return S_OK;}
/// @implementedBOOL CicBridge::UnInitIMMX(_Inout_ TLS *pTLS){ UninitDisplayAttrbuteLib(&m_LibThread); TFUninitLib_Thread(&m_LibThread);
if (m_pKeystrokeMgr) { m_pKeystrokeMgr->Release(); m_pKeystrokeMgr = NULL; }
if (pTLS->m_pProfile) { pTLS->m_pProfile->Release(); pTLS->m_pProfile = NULL; }
if (m_pThreadMgrEventSink) { m_pThreadMgrEventSink->_Unadvise(); m_pThreadMgrEventSink->Release(); m_pThreadMgrEventSink = NULL; }
if (pTLS->m_pThreadMgr) { pTLS->m_pThreadMgr->Release(); pTLS->m_pThreadMgr = NULL; }
m_bImmxInited = FALSE; return TRUE;}
/// @implementedSTDMETHODIMP CicBridge::OnPreFocusDIM(HWND hwnd){ return S_OK;}
/// @unimplementedSTDMETHODIMP CicBridge::OnSysKeyboardProc(UINT, LONG){ return E_NOTIMPL;}
/// @implementedSTDMETHODIMP CicBridge::OnSysShellProc(INT, UINT, LONG){ return S_OK;}
/// @implementedvoidCicBridge::PostTransMsg( _In_ HWND hWnd, _In_ INT cTransMsgs, _In_ const TRANSMSG *pTransMsgs){ for (INT i = 0; i < cTransMsgs; ++i, ++pTransMsgs) { ::PostMessageW(hWnd, pTransMsgs->message, pTransMsgs->wParam, pTransMsgs->lParam); }}
/// @implementedHRESULTCicBridge::ConfigureGeneral( _Inout_ TLS* pTLS, _In_ ITfThreadMgr *pThreadMgr, _In_ HKL hKL, _In_ HWND hWnd){ CicProfile *pProfile = pTLS->m_pProfile; if (!pProfile) return E_OUTOFMEMORY;
TF_LANGUAGEPROFILE profile; HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); if (FAILED(hr)) return hr;
ITfFunctionProvider *pProvider = NULL; hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); if (FAILED(hr)) return hr;
ITfFnConfigure *pFnConfigure = NULL; hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigure, (IUnknown**)&pFnConfigure); if (FAILED(hr)) { pProvider->Release(); return hr; }
hr = pFnConfigure->Show(hWnd, profile.langid, profile.guidProfile);
pFnConfigure->Release(); pProvider->Release(); return hr;}
/// @implementedHRESULTCicBridge::ConfigureRegisterWord( _Inout_ TLS* pTLS, _In_ ITfThreadMgr *pThreadMgr, _In_ HKL hKL, _In_ HWND hWnd, _Inout_opt_ LPVOID lpData){ CicProfile *pProfile = pTLS->m_pProfile; if (!pProfile) return E_OUTOFMEMORY;
TF_LANGUAGEPROFILE profile; HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); if (FAILED(hr)) return hr;
ITfFunctionProvider *pProvider = NULL; hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); if (FAILED(hr)) return hr;
ITfFnConfigureRegisterWord *pFunction = NULL; hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigureRegisterWord, (IUnknown**)&pFunction); if (FAILED(hr)) { pProvider->Release(); return hr; }
REGISTERWORDW* pRegWord = (REGISTERWORDW*)lpData; if (pRegWord) { if (pRegWord->lpWord) { hr = E_OUTOFMEMORY; BSTR bstrWord = SysAllocString(pRegWord->lpWord); if (bstrWord) { hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, bstrWord); SysFreeString(bstrWord); } } else { hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, NULL); } }
pProvider->Release(); pFunction->Release(); return hr;}
/// @unimplementedvoid CicBridge::SetAssociate( TLS *pTLS, HWND hWnd, HIMC hIMC, ITfThreadMgr_P *pThreadMgr, ITfDocumentMgr *pDocMgr){ //FIXME}
HRESULTCicBridge::SetActiveContextAlways(TLS *pTLS, HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL){ auto pThreadMgr = pTLS->m_pThreadMgr; if (!pThreadMgr) return E_OUTOFMEMORY;
if (fActive) { if (!hIMC) { SetAssociate(pTLS, hWnd, hIMC, pThreadMgr, m_pDocMgr); return S_OK; }
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;
if (hIMC == ::ImmGetContext(hWnd)) { ITfDocumentMgr *pDocMgr = GetDocumentManager(imeContext); if (pDocMgr) { SetAssociate(pTLS, imcLock.get().hWnd, hIMC, pThreadMgr, pDocMgr); pDocMgr->Release(); } }
return S_OK; }
if (hIMC && !IsEALang(LOWORD(hKL))) { 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->m_dwUnknown6_5[2] && !pCicIC->m_dwUnknown6_5[3]) ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); }
if (!hIMC || (::GetFocus() != hWnd) || (hIMC != ::ImmGetContext(hWnd))) SetAssociate(pTLS, hWnd, hIMC, pThreadMgr, m_pDocMgr);
return S_OK;}
/// @unimplementedBOOLCicBridge::DoOpenCandidateHanja( ITfThreadMgr_P *pThreadMgr, CicIMCLock& imcLock, CicInputContext *pCicIC){ return FALSE;}
/// @unimplementedHRESULTCicBridge::OnSetConversionSentenceMode( ITfThreadMgr_P *pThreadMgr, CicIMCLock& imcLock, CicInputContext *pCicIC, DWORD dwValue, LANGID LangID){ return E_NOTIMPL;}
/// @implementedHRESULT CicBridge::Notify( TLS *pTLS, ITfThreadMgr_P *pThreadMgr, HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD_PTR dwValue){ 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) return E_OUTOFMEMORY;
CicProfile *pProfile = pTLS->m_pProfile; if (!pProfile) return E_OUTOFMEMORY;
LANGID LangID; pProfile->GetLangId(&LangID);
switch (dwAction) { case NI_OPENCANDIDATE: if (PRIMARYLANGID(LangID) == LANG_KOREAN) { if (DoOpenCandidateHanja(pThreadMgr, imcLock, pCicIC)) return S_OK; return E_FAIL; } return E_NOTIMPL;
case NI_COMPOSITIONSTR: switch (dwIndex) { case CPS_COMPLETE: pCicIC->EscbCompComplete(imcLock); break;
case CPS_CONVERT: case CPS_REVERT: return E_NOTIMPL;
case CPS_CANCEL: pCicIC->EscbCompCancel(imcLock); break;
default: return E_FAIL; } return S_OK;
case NI_CONTEXTUPDATED: switch (dwValue) { case IMC_SETCONVERSIONMODE: case IMC_SETSENTENCEMODE: return OnSetConversionSentenceMode(pThreadMgr, imcLock, pCicIC, dwValue, LangID);
case IMC_SETOPENSTATUS: return OnSetOpenStatus(pTLS, pThreadMgr, imcLock, pCicIC);
case IMC_SETCANDIDATEPOS: return pCicIC->OnSetCandidatePos(pTLS, imcLock);
case IMC_SETCOMPOSITIONFONT: case IMC_SETCOMPOSITIONWINDOW: return E_NOTIMPL;
default: return E_FAIL; } break;
default: return E_NOTIMPL; }}
/// @unimplementedBOOL CicBridge::ProcessKey( TLS *pTLS, ITfThreadMgr_P *pThreadMgr, HIMC hIMC, WPARAM wParam, LPARAM lParam, CONST LPBYTE lpbKeyState, INT *pnUnknown60){ return FALSE; // FIXME}
/// @unimplementedHRESULTCicBridge::ToAsciiEx( TLS *pTLS, ITfThreadMgr_P *pThreadMgr, UINT uVirtKey, UINT uScanCode, CONST LPBYTE lpbKeyState, LPTRANSMSGLIST lpTransBuf, UINT fuState, HIMC hIMC, UINT *pResult){ return E_NOTIMPL; // FIXME}
/// @implementedBOOLCicBridge::SetCompositionString( TLS *pTLS, ITfThreadMgr_P *pThreadMgr, HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen){ 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; auto pProfile = pTLS->m_pProfile; if (!pCicIC || !pProfile) return FALSE;
UINT uCodePage; pProfile->GetCodePageA(&uCodePage);
LANGID LangID; if (dwIndex != SCS_SETSTR || !lpComp || *(WORD*)lpComp || !dwCompLen || FAILED(pProfile->GetLangId(&LangID)) || PRIMARYLANGID(LangID) != LANG_KOREAN) { return pCicIC->SetCompositionString(imcLock, pThreadMgr, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, uCodePage); }
if (imcLock.get().fdwConversion & IME_CMODE_NATIVE) { ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); return TRUE; }
return FALSE;}
/// @unimplementedLRESULTCicBridge::EscHanjaMode(TLS *pTLS, HIMC hIMC, LPVOID lpData){ 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) return TRUE;
if (pCicIC->m_bCandidateOpen) return TRUE;
pCicIC->m_dwUnknown6_5[4] |= 0x1;
//FIXME
pCicIC->m_dwUnknown6_5[4] &= ~0x1;
return TRUE;}
/// @implementedLRESULTCicBridge::EscapeKorean(TLS *pTLS, HIMC hIMC, UINT uSubFunc, LPVOID lpData){ if (uSubFunc == IME_ESC_QUERY_SUPPORT) return *(DWORD*)lpData == IME_ESC_HANJA_MODE; if (uSubFunc == IME_ESC_HANJA_MODE) return EscHanjaMode(pTLS, hIMC, lpData); return 0;}
/// @implementedBOOL CicBridge::IsOwnDim(ITfDocumentMgr *pDocMgr){ DWORD dwDimFlags = 0; HRESULT hr = ::GetCompartmentDWORD(pDocMgr, GUID_COMPARTMENT_CTFIME_DIMFLAGS, &dwDimFlags, FALSE); if (FAILED(hr)) return FALSE; return !!(dwDimFlags & 0x1);}