/**************************************************************************** KORIMX.CPP : CKorIMX class implementation(TIP Main functions) History: 15-NOV-1999 CSLim Created ****************************************************************************/ #include "private.h" #include "korimx.h" #include "hanja.h" #include "globals.h" #include "immxutil.h" #include "proputil.h" #include "kes.h" #include "helpers.h" #include "editcb.h" #include "timsink.h" #include "icpriv.h" #include "funcprv.h" #include "fnrecon.h" #include "dispattr.h" #include "insert.h" #include "statsink.h" #include "mes.h" #include "config.h" #include "osver.h" /*--------------------------------------------------------------------------- CKorIMX::CKorIMX Ctor ---------------------------------------------------------------------------*/ CKorIMX::CKorIMX() { extern void DllAddRef(void); // Init member vars m_pToolBar = NULL; m_pPadCore = NULL; m_pCurrentDim = NULL; m_ptim = NULL; m_tid = 0; m_ptimEventSink = NULL; m_pkes = NULL; m_hOwnerWnd = 0; m_fKeyFocus = fFalse; m_fPendingCleanup = fFalse; m_pFuncPrv = NULL; m_pInsertHelper = NULL; // Init Cand UI member vars m_pCandUI = NULL; m_fCandUIOpen = fFalse; // SoftKbd m_psftkbdwndes = NULL; m_pSoftKbd = NULL; m_fSoftKbdEnabled = fFalse; ZeroMemory(&m_libTLS, sizeof(m_libTLS)); // Korean Kbd driver does not exist in system(Non Korean NT4, Non Korean WIN9X) m_fNoKorKbd = fFalse; m_fSoftKbdOnOffSave = fFalse; // Increase dll ref count DllAddRef(); m_cRef = 1; /////////////////////////////////////////////////////////////////////////// // init CDisplayAttributeProvider // // Tip can add one or more TF_DISPLAYATTRIBUTE info here. // TF_DISPLAYATTRIBUTE dattr; StringCchCopyW(szProviderName, ARRAYSIZE(szProviderName), L"Korean Keyboard TIP"); // Input string attr dattr.crText.type = TF_CT_NONE; dattr.crText.nIndex = 0; dattr.crBk.type = TF_CT_NONE; dattr.crBk.nIndex = 0; dattr.lsStyle = TF_LS_NONE; dattr.fBoldLine = fFalse; ClearAttributeColor(&dattr.crLine); dattr.bAttr = TF_ATTR_INPUT; Add(GUID_ATTR_KORIMX_INPUT, L"Korean TIP Input String", &dattr); } /*--------------------------------------------------------------------------- CKorIMX::~CKorIMX Dtor ---------------------------------------------------------------------------*/ CKorIMX::~CKorIMX() { extern void DllRelease(void); if (IsSoftKbdEnabled()) TerminateSoftKbd(); DllRelease(); } /*--------------------------------------------------------------------------- CKorIMX::CreateInstance Class Factory's CreateInstance ---------------------------------------------------------------------------*/ /* static */ HRESULT CKorIMX::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj) { HRESULT hr; CKorIMX *pimx; TraceMsg(DM_TRACE, TEXT("CKorIMX_CreateInstance called.")); *ppvObj = NULL; if (NULL != pUnkOuter) return CLASS_E_NOAGGREGATION; pimx = new CKorIMX; if (pimx == NULL) return E_OUTOFMEMORY; hr = pimx->QueryInterface(riid, ppvObj); pimx->Release(); return hr; } /*--------------------------------------------------------------------------- CKorIMX::QueryInterface ---------------------------------------------------------------------------*/ STDAPI CKorIMX::QueryInterface(REFIID riid, void **ppvObj) { if (ppvObj == NULL) return E_POINTER; *ppvObj = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfTextInputProcessor)) { *ppvObj = SAFECAST(this, ITfTextInputProcessor *); } else if (IsEqualIID(riid, IID_ITfDisplayAttributeProvider)) { *ppvObj = SAFECAST(this, ITfDisplayAttributeProvider *); } else if (IsEqualIID(riid, IID_ITfThreadFocusSink)) { *ppvObj = SAFECAST(this, ITfThreadFocusSink *); } else if(IsEqualIID(riid, IID_ITfFnConfigure)) { *ppvObj = SAFECAST(this, ITfFnConfigure *); } else if(IsEqualIID(riid, IID_ITfCleanupContextSink)) { *ppvObj = SAFECAST(this, ITfCleanupContextSink *); } else if(IsEqualIID(riid, IID_ITfActiveLanguageProfileNotifySink)) { *ppvObj = SAFECAST(this, ITfActiveLanguageProfileNotifySink *); } else if(IsEqualIID(riid, IID_ITfTextEditSink)) { *ppvObj = SAFECAST(this, ITfTextEditSink *); } else if( IsEqualIID(riid, IID_ITfEditTransactionSink )) { *ppvObj = SAFECAST(this, ITfEditTransactionSink* ); } if (*ppvObj == NULL) { return E_NOINTERFACE; } AddRef(); return S_OK; } /*--------------------------------------------------------------------------- CKorIMX::AddRef ---------------------------------------------------------------------------*/ STDAPI_(ULONG) CKorIMX::AddRef() { m_cRef++; return m_cRef; } /*--------------------------------------------------------------------------- CKorIMX::Release ---------------------------------------------------------------------------*/ STDAPI_(ULONG) CKorIMX::Release() { m_cRef--; if (0 < m_cRef) return m_cRef; delete this; return 0; } /*--------------------------------------------------------------------------- CKorIMX::_KeyEventCallback ITfKeyEventSink call this function back whenever keyboard event occurs or test key down and up. ---------------------------------------------------------------------------*/ HRESULT CKorIMX::_KeyEventCallback(UINT uCode, ITfContext *pic, WPARAM wParam, LPARAM lParam, BOOL *pfEaten, void *pv) { CKorIMX *pimx; CEditSession2 *pes; ESSTRUCT ess; BYTE abKeyState[256]; UINT uVKey = (UINT)LOWORD(wParam); HRESULT hr; Assert(pv != NULL); pimx = (CKorIMX *)pv; if (pimx == NULL) { return E_FAIL; } // !!! IME or Tip switched !!! // if ITfKeyEventSink->OnSetFocus called if (uCode == KES_CODE_FOCUS) { // wParam: fForeground if (!wParam && pic && pimx->GetIPComposition(pic)) { ESStructInit(&ess, ESCB_COMPLETE); // clear display attribute only if current composition exits if (pes = new CEditSession2(pic, pimx, &ess, CKorIMX::_EditSessionCallback2)) { pes->Invoke(ES2_READWRITE | ES2_SYNC, &hr); pes->Release(); } if (pimx->m_pToolBar != NULL) { pimx->m_pToolBar->Update(UPDTTB_ALL); } } pimx->m_fKeyFocus = (BOOL)wParam; return S_OK; } // Set default return values *pfEaten = fFalse; // Default is not eaten hr = S_OK; if (pic == NULL) goto ExitKesCallback; // Do not process shift and ctrl key if (uVKey == VK_SHIFT || uVKey == VK_CONTROL) goto ExitKesCallback; // Off 10 #127987 // NT4 workaround: NT4 IMM does not send WM_KEYDOWN::VK_HANGUL to application message queue. // Unfortunately VK_JUNJA sent as WM_SYSKEYDOWN/UP, so it's useless check here. if (IsOnNT() && !IsOnNT5()) { if ((UINT)LOWORD(wParam) == VK_HANGUL /* || (UINT)LOWORD(wParam) == VK_JUNJA*/) goto AcceptThisKey; } // Ignore all Key up message if ((uCode & KES_CODE_KEYDOWN) == 0) goto ExitKesCallback; AcceptThisKey: if (GetKeyboardState(abKeyState) == fFalse) goto ExitKesCallback; // Ignore all key events while candidate UI is opening except cand keys. // Added Alt check: Bug #525842 - If Alt key pressed, always complete current interim. // This will be handled in the _IsKeyEaten function. if (pimx->IsDisabledIC(pic) && !IsAltKeyPushed(abKeyState)) { if (!IsCandKey(wParam, abKeyState)) *pfEaten = fTrue; goto ExitKesCallback; } // Check if we need to handle this key if (pimx->_IsKeyEaten(pic, pimx, wParam, lParam, abKeyState) == fFalse) goto ExitKesCallback; // if key is eaten // ITfKeyEventSink->TestKeyDown sets (KES_CODE_KEYDOWN | KES_CODE_TEST) // ITfKeyEventSink->TestKeyUp sets (KES_CODE_KEYUP | KES_CODE_TEST) // Response only for OnKeyDown and OnKeyUp if ((uCode & KES_CODE_TEST) == 0) { ESStructInit(&ess, ESCB_KEYSTROKE); ess.wParam = wParam; ess.lParam = lParam; ess.pv1 = abKeyState; if (pes = new CEditSession2(pic, pimx, &ess, CKorIMX::_EditSessionCallback2)) { pes->Invoke(ES2_READWRITE | ES2_SYNC, &hr); pes->Release(); } } if (hr == S_OK) *pfEaten = fTrue; ExitKesCallback: return hr; } /*--------------------------------------------------------------------------- CKorIMX::GetIC Get the input context at the top of the stack ---------------------------------------------------------------------------*/ ITfContext *CKorIMX::GetIC() { ITfContext *pic = NULL; ITfDocumentMgr *pdim = NULL; if (m_ptim == 0) { Assert(0); return NULL; } if (SUCCEEDED(m_ptim->GetFocus(&pdim)) && pdim) { pdim->GetTop(&pic); pdim->Release(); } return pic; } /*--------------------------------------------------------------------------- CKorIMX::SetConvMode ---------------------------------------------------------------------------*/ DWORD CKorIMX::SetConvMode(ITfContext *pic, DWORD dwConvMode) { DWORD dwCurConvMode = GetConvMode(pic); if (dwConvMode == dwCurConvMode) return dwConvMode; SetCompartmentDWORD(m_tid, GetTIM(), GUID_COMPARTMENT_KORIMX_CONVMODE, dwConvMode, fFalse); // SoftKeyboard if (IsSoftKbdEnabled()) { DWORD dwSoftKbdLayout, dwNewSoftKbdLayout; dwSoftKbdLayout = GetSoftKBDLayout(); if (dwConvMode & TIP_HANGUL_MODE) dwNewSoftKbdLayout = m_KbdHangul.dwSoftKbdLayout; else dwNewSoftKbdLayout = m_KbdStandard.dwSoftKbdLayout; if (dwSoftKbdLayout != dwNewSoftKbdLayout) SetSoftKBDLayout(dwNewSoftKbdLayout); } // if Comp string exist, finalize it. if (GetIPComposition(pic)) { CEditSession2 *pes; ESSTRUCT ess; HRESULT hr; hr = E_OUTOFMEMORY; ESStructInit(&ess, ESCB_COMPLETE); if (pes = new CEditSession2(pic, this, &ess, CKorIMX::_EditSessionCallback2)) { // Word will not allow synchronous lock at this point. pes->Invoke(ES2_READWRITE | ES2_ASYNC, &hr); pes->Release(); } } return dwConvMode; } /*--------------------------------------------------------------------------- CKorIMX::_IsKeyEaten Return fTrue if this key need to be eaten ---------------------------------------------------------------------------*/ BOOL CKorIMX::_IsKeyEaten(ITfContext *pic, CKorIMX *pimx, WPARAM wParam, LPARAM lParam, const BYTE abKeyState[256]) { CHangulAutomata *pAutomata; BOOL fCompStr = fFalse; UINT uVKey = (UINT)LOWORD(wParam); CEditSession2 *pes; ESSTRUCT ess; // Hangul and Junja key if (uVKey == VK_HANGUL || uVKey == VK_JUNJA) return fTrue; // Hanja key if (uVKey == VK_HANJA) { CICPriv *picp; if ((picp = GetInputContextPriv(pic)) == NULL) { Assert(0); return fTrue; } // Do not eat VK_HANJA for AIMM 1.2 IME_HANJAMODE . if (picp->GetAIMM() && GetIPComposition(pic) == NULL) return fFalse; else return fTrue; } // if Tip is off do nothing if (IsOn(pic) == fFalse || GetConvMode(pic) == TIP_ALPHANUMERIC_MODE) return fFalse; // Should handle Backspace in interim state if (uVKey == VK_BACK) { if (GetIPComposition(pic)) return fTrue; else return fFalse; } // Get Hangul Automata if ((pAutomata = GetAutomata(pic)) == NULL) return fFalse; // Alt+xx or Ctrl+xx processing. TIP should not eat. // Ctrl or Alt pushed with other key and comp str exist we should eat and complete the comp str. if (IsAltKeyPushed(abKeyState) || IsControlKeyPushed(abKeyState)) { pAutomata->MakeComplete(); } else { DWORD dwConvMode = GetConvMode(pic); // If Hangul mode if (dwConvMode & TIP_HANGUL_MODE) { // Start of hangul composition WORD wcCur; CIMEData ImeData; wcCur = pAutomata->GetKeyMap(uVKey, IsShiftKeyPushed(abKeyState) ? 1 : 0 ); // 2beolsik Alphanumeric keys have same layout as English key // So we don't need process when user pressed Alphanumeric key under 2beolsik if ((wcCur && ImeData.GetCurrentBeolsik() != KL_2BEOLSIK) || (wcCur & H_HANGUL) ) return fTrue; } // if IME_CMODE_FULLSHAPE if (dwConvMode & TIP_JUNJA_MODE) { if (CHangulAutomata::GetEnglishKeyMap(uVKey, IsShiftKeyPushed(abKeyState) ? 1 : 0)) return fTrue; } } // // Skipped all key matching condition mean this is no handle key. // We just complete current composition if exist. // if (GetIPComposition(pic) != NULL) { // No need to handle this key for current Automata. // Complete composition, if exist. ESStructInit(&ess, ESCB_COMPLETE); HRESULT hr; // Complete current comp char if exist if ((pes = new CEditSession2(pic, pimx, &ess, CKorIMX::_EditSessionCallback2)) == NULL) return fFalse; pes->Invoke(ES2_READWRITE | ES2_SYNC, &hr); pes->Release(); } return fFalse; } /*---------------------------------------------------------------------------- Banja2Junja Convert Ascii Half shape to Full shape character ----------------------------------------------------------------------------*/ /* static */ WCHAR CKorIMX::Banja2Junja(WCHAR bChar) { WCHAR wcJunja; if (bChar == L' ') wcJunja = 0x3000; // FullWidth space else if (bChar == L'~') wcJunja = 0xFF5E; else if (bChar == L'\\') wcJunja = 0xFFE6; // FullWidth WON sign else wcJunja = 0xFF00 + (WORD)(bChar - (BYTE)0x20); return wcJunja; } /*--------------------------------------------------------------------------- CKorIMX::_Keystroke ---------------------------------------------------------------------------*/ HRESULT CKorIMX::_Keystroke(TfEditCookie ec, ITfContext *pic, WPARAM wParam, LPARAM lParam, const BYTE abKeyState[256]) { ITfRange *pSelection = NULL; WORD wVKey = LOWORD(wParam) & 0x00FF; DWORD dwConvMode; HRESULT hResult = S_OK; // find the extent of the comp string if (GetSelectionSimple(ec, pic, &pSelection) != S_OK) { hResult = S_FALSE; goto Exit; } dwConvMode = GetConvMode(pic); switch (wVKey) { case VK_HANGUL: dwConvMode ^= TIP_HANGUL_MODE; SetConvMode(pic, dwConvMode); break; case VK_JUNJA: dwConvMode ^= TIP_JUNJA_MODE; SetConvMode(pic, dwConvMode); break; case VK_HANJA: if (GetIPComposition(pic)) DoHanjaConversion(ec, pic, pSelection); else Reconvert(pSelection); // Update Hanja button if (m_pToolBar != NULL) { m_pToolBar->Update(UPDTTB_HJMODE); } break; default: /////////////////////////////////////////////////////////////////////////// // Run Hangul Automata if (dwConvMode & TIP_HANGUL_MODE) { HAutoMata(ec, pic, pSelection, (LPBYTE)abKeyState, wVKey); } else if (dwConvMode & TIP_JUNJA_MODE) // Junja handling { WCHAR pwchKeyCode[2]; // Numeric or English key? if (pwchKeyCode[0] = CHangulAutomata::GetEnglishKeyMap(wVKey, (abKeyState[VK_SHIFT] & 0x80) ? 1:0)) { if (wVKey >= 'A' && wVKey <= 'Z') { pwchKeyCode[0] = CHangulAutomata::GetEnglishKeyMap(wVKey, (abKeyState[VK_SHIFT] & 0x80) ? 1:0 ^ ((abKeyState[VK_CAPITAL] & 0x01) ? 1:0)); } // Get Junja code pwchKeyCode[0] = Banja2Junja(pwchKeyCode[0]); pwchKeyCode[1] = L'\0'; // Finalize a Junja char if (SUCCEEDED(SetInputString(ec, pic, pSelection, pwchKeyCode, GetLangID()))) MakeResultString(ec, pic, pSelection); } } break; } Exit: if (pSelection) pSelection->Release(); return hResult; } /*--------------------------------------------------------------------------- CKorIMX::HAutoMata Run Hangul Automata ---------------------------------------------------------------------------*/ void CKorIMX::HAutoMata(TfEditCookie ec, ITfContext *pic, ITfRange *pIRange, LPBYTE lpbKeyState, WORD wVKey) { WORD wcCur; ULONG cch; LPWSTR pwstr; CHangulAutomata *pAutomata; WCHAR pwchText[256]; if ((pAutomata = GetAutomata(pic)) == NULL) return; cch = ARRAYSIZE(pwchText); pIRange->GetText(ec, 0, pwchText, ARRAYSIZE(pwchText) - 1, &cch); pwstr = pwchText; switch (wVKey) { /////////////////////////////////////////////////////////// // Back space processing case VK_BACK : if (pAutomata->BackSpace()) { CIMEData ImeData; if (ImeData.GetJasoDel()) { *pwstr++ = pAutomata->GetCompositionChar(); *pwstr = L'\0'; SetInputString(ec, pic, pIRange, pwchText, GetLangID()); } else { pAutomata->InitState(); *pwstr = L'\0'; SetInputString(ec, pic, pIRange, pwchText, GetLangID()); } // All composition deleted. if (pAutomata->GetCompositionChar() == 0) { EndIPComposition(ec, pic); // Collapse current selection to end and reset block cursor pIRange->Collapse(ec, TF_ANCHOR_END); SetSelectionSimple(ec, pic, pIRange); } } else { // BUG : impossible Assert(0); } break; default : WCHAR wchPrev = pAutomata->GetCompositionChar(); switch (pAutomata->Machine(wVKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 ) ) { case HAUTO_COMPOSITION: // pwchText[0] = pAutomata->GetCompositionChar(); pwchText[1] = L'\0'; SetInputString(ec, pic, pIRange, pwchText, GetLangID()); break; case HAUTO_COMPLETE: pwchText[0] = pAutomata->GetCompleteChar(); pwchText[1] = L'\0'; if (FAILED(SetInputString(ec, pic, pIRange, pwchText, GetLangID()))) break; MakeResultString(ec, pic, pIRange); // pwchText[0] = pAutomata->GetCompositionChar(); pwchText[1] = L'\0'; SetInputString(ec, pic, pIRange, pwchText, GetLangID()); break; //////////////////////////////////////////////////////// // User pressed Alphanumeric key. // When user type alphanumeric char in interim state. // ImeProcessKey should guarantee return fTrue only if // hangul key pressed or alphanumeric key(including special keys) // pressed in interim state or Fullshape mode. case HAUTO_NONHANGULKEY: wcCur = pAutomata->GetKeyMap(wVKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 ); if (GetConvMode(pic) & TIP_JUNJA_MODE) wcCur = Banja2Junja(wcCur); if (pAutomata->GetCompositionChar()) { pAutomata->MakeComplete(); MakeResultString(ec, pic, pIRange); } if (wcCur) { pwchText[0] = wcCur; pwchText[1] = 0; if (SUCCEEDED(SetInputString(ec, pic, pIRange, pwchText, GetLangID()))) MakeResultString(ec, pic, pIRange); } break; default : Assert(0); } // switch (pInstData->pMachine->Machine(uVirKey, (lpbKeyState[VK_SHIFT] & 0x80) ? 1 : 0 ) ) } // switch (uVirKey) } /*--------------------------------------------------------------------------- CKorIMX::DoHanjaConversion ---------------------------------------------------------------------------*/ HRESULT CKorIMX::DoHanjaConversion(TfEditCookie ec, ITfContext *pic, ITfRange *pRange) { ULONG cch; CCandidateListEx *pCandList; WCHAR pwchText[256]; Assert(pic != NULL); Assert(pRange != NULL); cch = ARRAYSIZE(pwchText); pRange->GetText(ec, 0, pwchText, ARRAYSIZE(pwchText) - 1, &cch); // REVIEW: Assume composition string is one char Assert(cch == 1); pwchText[1] = 0; if ((pCandList = CreateCandidateList(pic, pRange, pwchText)) == NULL) return E_FAIL; OpenCandidateUI(ec, pic, pRange, pCandList); pCandList->Release(); return S_OK; } /*--------------------------------------------------------------------------- CKorIMX::Reconvert ---------------------------------------------------------------------------*/ HRESULT CKorIMX::Reconvert(ITfRange *pSelection) { ITfFnReconversion *pReconv = NULL; ITfRange *pRangeReconv = NULL; BOOL fConvertable; if (FAILED(GetFunctionProvider()->GetFunction(GUID_NULL, IID_ITfFnReconversion, (IUnknown **)&pReconv))) return E_FAIL; if (pReconv->QueryRange(pSelection, &pRangeReconv, &fConvertable) != S_OK) goto Exit; if (fConvertable) pReconv->Reconvert(pRangeReconv); Exit: SafeRelease(pReconv); return S_OK; } // REVIEW /*--------------------------------------------------------------------------- CKorIMX::SetInputString ---------------------------------------------------------------------------*/ HRESULT CKorIMX::SetInputString(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, WCHAR *psz, LANGID langid) { GUID attr; ITfComposition *pComposition; ITfRange *ppCompRange = NULL; LONG cch; // BOOL fInsertOK; cch = wcslen(psz); pComposition = GetIPComposition(pic); // If start composition if (pComposition == NULL) { // if new selection, Set overtype. Assert(m_pInsertHelper != NULL); if (m_pInsertHelper) { HRESULT hr; CHangulAutomata *pAutomata; hr = m_pInsertHelper->InsertAtSelection(ec, pic, psz, cch, &ppCompRange); if (FAILED(hr)) { if ((pAutomata = GetAutomata(pic)) != NULL) pAutomata->InitState(); return hr; } /* InsertOK = (pRange != NULL);*/ if (ppCompRange == NULL) { Assert(0); return S_FALSE; } cch = -1; // flag to avoid a SetText call below pRange = ppCompRange; } CreateIPComposition(ec, pic, pRange); } // Set Korean input property attr = GUID_ATTR_KORIMX_INPUT; // Use MySetText instead of SetTextAndProperty // if cch == -1, set only attribute MySetText(ec, pic, pRange, psz , cch, langid, &attr); // Always call SetSelection for block cursor SetSelectionBlock(ec, pic, pRange); SafeRelease(ppCompRange); return S_OK; } // REVIEW /*--------------------------------------------------------------------------- CKorIMX::MakeResultString ---------------------------------------------------------------------------*/ HRESULT CKorIMX::MakeResultString(TfEditCookie ec, ITfContext *pic, ITfRange *pRange) { ITfRange *pRangeTmp; ITfProperty *pPropAttr; #if 0 ITfProperty *pProp; #endif TfGuidAtom attr; // Clone Range pRange->Clone(&pRangeTmp); // Collapse current selection to end and reset block cursor pRange->Collapse(ec, TF_ANCHOR_END); SetSelectionSimple(ec, pic, pRange); #if 0 // Flush IP Range FlushIPRange(ec, pic); #endif if (SUCCEEDED(pic->GetProperty(GUID_PROP_ATTRIBUTE, &pPropAttr))) { if (SUCCEEDED(GetAttrPropertyData(ec, pPropAttr, pRangeTmp, &attr))) { if (IsKorIMX_GUID_ATOM(attr)) { pPropAttr->Clear(ec, pRangeTmp); } } pPropAttr->Release(); #if 1 EndIPComposition(ec, pic); #else // clear the composition property if (SUCCEEDED(pic->GetProperty(GUID_PROP_COMPOSING, &pProp))) { pProp->Clear(ec, pRangeTmp); pProp->Release(); } #endif // clear any overtype if (m_pInsertHelper != NULL) { m_pInsertHelper->ReleaseBlobs(ec, pic, NULL); } } pRangeTmp->Release(); return S_OK; } #if 0 /*--------------------------------------------------------------------------- CKorIMX::_MultiRangeConversion ---------------------------------------------------------------------------*/ HRESULT CKorIMX::_MultiRangeConversion(TfEditCookie ec, UINT_PTR u, ITfContext *pic, ITfRange *pRange) { IEnumTfRanges *pEnumTrack = NULL; ITfReadOnlyProperty *pProp = NULL; ITfRange *pPropRange = NULL; HRESULT hr = E_FAIL; if (FAILED(EnumTrackTextAndFocus(ec, pic, pRange, &pProp, &pEnumTrack))) goto Exit; while(pEnumTrack->Next(1, &pPropRange, 0) == S_OK) { ITfRange *pRangeTmp = NULL; if (!IsOwnerAndFocus(ec, CLSID_KorIMX, pProp, pPropRange)) goto Next; if (FAILED(pPropRange->Clone(&pRangeTmp))) goto Next; switch (u) { case ESCB_COMPLETE: MakeResultString(ec, pic, pRangeTmp); break; } SafeRelease(pRangeTmp); Next: SafeRelease(pPropRange); } Exit: SafeRelease(pEnumTrack); SafeRelease(pProp); return hr; } #endif /*--------------------------------------------------------------------------- CKorIMX::_OwnerWndProc ---------------------------------------------------------------------------*/ LRESULT CALLBACK CKorIMX::_OwnerWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { #if 0 switch (uMsg) { case WM_CREATE: SetThis(hWnd, lParam); return 0; case (WM_USER+WM_COMMAND): // local commands return GetThis(hWnd)->OnCommand((UINT)wParam, lParam); case WM_DRAWITEM: { CKorIMX* pThis = GetThis(hWnd); if( pThis ) return pThis->OnDrawItem( wParam, lParam ); break; } case WM_MEASUREITEM: { CKBDTip* pThis = GetThis(hWnd); if( pThis ) return pThis->OnMeasureItem( wParam, lParam ); break; } } #endif return DefWindowProc(hWnd, uMsg, wParam, lParam); } //+--------------------------------------------------------------------------- // // GetDisplayName // //---------------------------------------------------------------------------- STDAPI CKorIMX::GetDisplayName(BSTR *pbstrName) { *pbstrName = SysAllocString(L"Korean Keyboard TIP Configure"); return S_OK; } //+--------------------------------------------------------------------------- // // Show // //---------------------------------------------------------------------------- STDAPI CKorIMX::Show(HWND hwnd, LANGID langid, REFGUID rguidProfile) { if (ConfigDLG(hwnd)) return S_OK; else return E_FAIL; } /*--------------------------------------------------------------------------- CKorIMX::GetAIMM ---------------------------------------------------------------------------*/ BOOL CKorIMX::GetAIMM(ITfContext *pic) { CICPriv* picp; if ((picp = GetInputContextPriv(pic)) == NULL) { Assert(0); return fFalse; } // AIMM? return picp->GetAIMM(); } /*--------------------------------------------------------------------------- CKorIMX::MySetText ---------------------------------------------------------------------------*/ BOOL CKorIMX::MySetText(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, const WCHAR *psz, LONG cchText, LANGID langid, GUID *pattr) { // bugbug: sometimes we want to set TFST_CORRECTION if (cchText != -1) // sometimes we just want to set a property value pRange->SetText(ec, 0, psz, cchText); if (cchText != 0) { HRESULT hr; ITfProperty *pProp = NULL; // set langid if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_LANGID, &pProp))) { SetLangIdPropertyData(ec, pProp, pRange, langid); pProp->Release(); } if (pattr) { // set attr if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp))) { hr = SetAttrPropertyData(&m_libTLS, ec, pProp, pRange, *pattr); pProp->Release(); } } } return fTrue; }