STDAPI CDIME::OnCompositionTerminated(TfEditCookie ecWrite, _In_ ITfComposition *pComposition) { debugPrint(L"CDIME::OnCompositionTerminated()"); HRESULT hr = S_OK; ITfContext* pContext = _pContext; // Clear dummy composition _RemoveDummyCompositionForComposing(ecWrite, pComposition); // Clear display attribute and end composition, _EndComposition will release composition for us if (pContext) { pContext->AddRef(); } _EndComposition(pContext); _DeleteCandidateList(TRUE, pContext); if (pContext) { pContext->Release(); pContext = nullptr; } return hr; }
STDAPI CExtentMonitorTextService::OnSetFocus(ITfDocumentMgr *pDocMgrFocus, ITfDocumentMgr *pDocMgrPrevFocus) { // // Whenever focus is changed, we initialize the TextEditSink. // ITfDocumentMgr *pDocMgrTarget = NULL; if (GetNonTransitoryDim(pDocMgrFocus, &pDocMgrTarget) != S_OK) { if (pDocMgrFocus) { pDocMgrTarget = pDocMgrFocus; pDocMgrTarget->AddRef(); } } _InitTextEditSink(pDocMgrTarget); if (pDocMgrTarget) { ITfContext *pContext; if (SUCCEEDED(pDocMgrTarget->GetBase(&pContext))) { DumpExtent(pContext, DE_EVENTID_ONSETFOCUS); pContext->Release(); } pDocMgrTarget->Release(); } return S_OK; }
void CTextService::InsertHello() { ITfDocumentMgr *pDocMgrFocus; ITfContext *pContext; CInsertHelloEditSession *pInsertHelloEditSession; HRESULT hr; // get the focus document if (_pThreadMgr->GetFocus(&pDocMgrFocus) != S_OK) return; // we want the topmost context, since the main doc context could be // superceded by a modal tip context if (pDocMgrFocus->GetTop(&pContext) != S_OK) { pContext = NULL; goto Exit; } if (pInsertHelloEditSession = new CInsertHelloEditSession(pContext)) { // we need a document write lock to insert text // the CInsertHelloEditSession will do all the work when the // CInsertHelloEditSession::DoEditSession method is called by the context pContext->RequestEditSession(_tfClientId, pInsertHelloEditSession, TF_ES_READWRITE | TF_ES_ASYNCDONTCARE, &hr); pInsertHelloEditSession->Release(); } Exit: if (pContext) pContext->Release(); pDocMgrFocus->Release(); }
HRESULT CCandidateListUIPresenter::_CandidateChangeNotification(_In_ enum CANDWND_ACTION action) { HRESULT hr = E_FAIL; TfClientId tfClientId = _pTextService->_GetClientId(); ITfThreadMgr* pThreadMgr = nullptr; ITfDocumentMgr* pDocumentMgr = nullptr; ITfContext* pContext = nullptr; _KEYSTROKE_STATE KeyState; KeyState.Category = _Category; KeyState.Function = FUNCTION_FINALIZE_CANDIDATELIST; if (CAND_ITEM_SELECT != action) { goto Exit; } pThreadMgr = _pTextService->_GetThreadMgr(); if (nullptr == pThreadMgr) { goto Exit; } hr = pThreadMgr->GetFocus(&pDocumentMgr); if (FAILED(hr)) { goto Exit; } hr = pDocumentMgr->GetTop(&pContext); if (FAILED(hr)) { pDocumentMgr->Release(); goto Exit; } CKeyHandlerEditSession *pEditSession = new (std::nothrow) CKeyHandlerEditSession(_pTextService, pContext, 0, 0, KeyState); if (nullptr != pEditSession) { HRESULT hrSession = S_OK; hr = pContext->RequestEditSession(tfClientId, pEditSession, TF_ES_SYNC | TF_ES_READWRITE, &hrSession); if (hrSession == TF_E_SYNCHRONOUS || hrSession == TS_E_READONLY) { hr = pContext->RequestEditSession(tfClientId, pEditSession, TF_ES_ASYNC | TF_ES_READWRITE, &hrSession); } pEditSession->Release(); } pContext->Release(); pDocumentMgr->Release(); Exit: return hr; }
void CExtentMonitorTextService::DumpExtentFocusContext(UINT nEventId) { ITfDocumentMgr *pDocMgrFocus; if ((_pThreadMgr->GetFocus(&pDocMgrFocus) == S_OK) && (pDocMgrFocus != NULL)) { ITfContext *pContext; if (SUCCEEDED(pDocMgrFocus->GetBase(&pContext))) { DumpExtent(pContext, nEventId); pContext->Release(); } pDocMgrFocus->Release(); } }
BOOL CDIME::_UpdateLanguageBarOnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus) { debugPrint(L"_UpdateLanguageBarOnSetFocus()"); BOOL needDisableButtons = FALSE; if (!pDocMgrFocus) { needDisableButtons = TRUE; } else { IEnumTfContexts* pEnumContext = nullptr; if (FAILED(pDocMgrFocus->EnumContexts(&pEnumContext)) || !pEnumContext) { needDisableButtons = TRUE; } else { ULONG fetched = 0; ITfContext* pContext = nullptr; if (FAILED(pEnumContext->Next(1, &pContext, &fetched)) || fetched != 1) { needDisableButtons = TRUE; } if (pContext == nullptr) { // context is not associated needDisableButtons = TRUE; } else { pContext->Release(); } } if (pEnumContext) { pEnumContext->Release(); } } SetLanguageBarStatus(TF_LBI_STATUS_DISABLED, needDisableButtons); return needDisableButtons; }
void CIME::_UpdateLanguageBarOnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus) { BOOL needDisableButtons = FALSE; if (!pDocMgrFocus) { needDisableButtons = TRUE; } else { IEnumTfContexts* pEnumContext = nullptr; if (FAILED(pDocMgrFocus->EnumContexts(&pEnumContext)) || !pEnumContext) { needDisableButtons = TRUE; } else { ULONG fetched = 0; ITfContext* pContext = nullptr; if (FAILED(pEnumContext->Next(1, &pContext, &fetched)) || fetched != 1) { needDisableButtons = TRUE; } if (!pContext) { // context is not associated needDisableButtons = TRUE; } else { pContext->Release(); } } if (pEnumContext) { pEnumContext->Release(); } } CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr; pCompositionProcessorEngine = _pCompositionProcessorEngine; pCompositionProcessorEngine->SetLanguageBarStatus(TF_LBI_STATUS_DISABLED, needDisableButtons); }
ComPtr<ITfCompartment> TextService::contextCompartment(const GUID& key, ITfContext* context) { ITfContext* curContext = NULL; if(!context) { curContext = currentContext(); context = curContext; } if(context) { ComQIPtr<ITfCompartmentMgr> compartmentMgr = context; if(compartmentMgr) { ComPtr<ITfCompartment> compartment; compartmentMgr->GetCompartment(key, &compartment); return compartment; } } if(curContext) curContext->Release(); return NULL; }
// called when the keyboard is opened or closed // virtual void TextService::onKeyboardStatusChanged(bool opened) { Ime::TextService::onKeyboardStatusChanged(opened); if(client_) client_->onKeyboardStatusChanged(opened); if(opened) { // keyboard is opened } else { // keyboard is closed if(isComposing()) { // end current composition if needed ITfContext* context = currentContext(); if(context) { endComposition(context); context->Release(); } } if(showingCandidates()) // disable candidate window if it's opened hideCandidates(); hideMessage(); // hide message window, if there's any } }
void CTextService::_AttachStaticProperty(WCHAR *psz) { ITfDocumentMgr *pDocMgrFocus; ITfContext *pContext; if ((_pThreadMgr->GetFocus(&pDocMgrFocus) == S_OK) && (pDocMgrFocus != NULL)) { if (pDocMgrFocus->GetTop(&pContext) == S_OK) { CStaticPropertyEditSession *pEditSession; if (pEditSession = new CStaticPropertyEditSession(this, pContext, psz)) { HRESULT hr; pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr); pEditSession->Release(); } pContext->Release(); } pDocMgrFocus->Release(); } return; }
STDAPI CSampleIME::OnCompositionTerminated(TfEditCookie ecWrite, _In_ ITfComposition *pComposition) { // Clear dummy composition _RemoveDummyCompositionForComposing(ecWrite, pComposition); // Clear display attribute and end composition, _EndComposition will release composition for us ITfContext* pContext = _pContext; if (pContext) { pContext->AddRef(); } _EndComposition(_pContext); _DeleteCandidateList(FALSE, pContext); if (pContext) { pContext->Release(); pContext = nullptr; } return S_OK; }
STDAPI CMarkTextService::OnEndEdit(ITfContext *pContext, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord) { ITfRange *pRangeComposition; IEnumTfRanges *pEnumRanges; ITfRange *pRange; ITfContext *pCompositionContext; TF_SELECTION tfSelection; BOOL fResult; BOOL fCancelComposition; ULONG cFetched; if (_pComposition == NULL) return S_OK; // are we responsible for the edit? if (pContext->InWriteSession(_tfClientId, &fResult) == S_OK && fResult) return S_OK; // is this the context our composition lives in? if (_pComposition->GetRange(&pRangeComposition) != S_OK) return S_OK; if (pRangeComposition->GetContext(&pCompositionContext) != S_OK) goto Exit; fResult = IsEqualUnknown(pCompositionContext, pContext); pCompositionContext->Release(); if (!fResult) goto Exit; // different context fCancelComposition = FALSE; // we're composing in this context, cancel the composition if anything suspicious happened // did the selection move outside the composition? if (pEditRecord->GetSelectionStatus(&fResult) == S_OK && fResult) { if (pContext->GetSelection(ecReadOnly, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) == S_OK && cFetched == 1) { if (_pComposition->GetRange(&pRangeComposition) == S_OK) { fResult = IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition); pRangeComposition->Release(); if (!fResult) { fCancelComposition = TRUE; } } tfSelection.range->Release(); } } if (fCancelComposition) goto CancelComposition; // did someone else edit the document text? if (pEditRecord->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0, &pEnumRanges) == S_OK) { // is the enumerator empty? if (pEnumRanges->Next(1, &pRange, NULL) == S_OK) { pRange->Release(); fCancelComposition = TRUE; } pEnumRanges->Release(); } if (fCancelComposition) { CancelComposition: // we need a write edit session to cancel the composition _TerminateCompositionInContext(pContext); } Exit: pRangeComposition->Release(); return S_OK; }
STDAPI CCompositionEditSession::DoEditSession(TfEditCookie ec) { ITfInsertAtSelection *pInsertAtSelection; ITfContextComposition *pContextComposition; ITfComposition *pComposition; ITfRange *pRangeComposition; ITfRange *pRangeInsert; ITfContext *pCompositionContext; HRESULT hr; BOOL fEqualContexts; // get an interface on the context we can use to deal with compositions if (_pContext->QueryInterface(IID_ITfContextComposition, (void **)&pContextComposition) != S_OK) return E_FAIL; hr = E_FAIL; pInsertAtSelection = NULL; if (_pMark->_IsComposing()) { // we have a composition, let's terminate it // it's possible our current composition is in another context...let's find out fEqualContexts = TRUE; if (_pMark->_GetComposition()->GetRange(&pRangeComposition) == S_OK) { if (pRangeComposition->GetContext(&pCompositionContext) == S_OK) { fEqualContexts = IsEqualUnknown(pCompositionContext, _pContext); if (!fEqualContexts) { // need an edit session in the composition context _pMark->_TerminateCompositionInContext(pCompositionContext); } pCompositionContext->Release(); } pRangeComposition->Release(); } // if the composition is in pContext, we already have an edit cookie if (fEqualContexts) { _pMark->_TerminateComposition(ec); } } else { // let's start a new composition over the current selection // this is totally contrived, a real text service would have // some meaningful logic to trigger this // first, test where a keystroke would go in the document if we did an insert // we need a special interface to insert text at the selection if (_pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection) != S_OK) { pInsertAtSelection = NULL; goto Exit; } if (pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeInsert) != S_OK) goto Exit; // start the composition if (pContextComposition->StartComposition(ec, pRangeInsert, _pMark, &pComposition) != S_OK) { pComposition = NULL; } pRangeInsert->Release(); // _pComposition may be NULL even if StartComposition return S_OK, this mean the application // rejected the composition if (pComposition != NULL) { _pMark->_SetComposition(pComposition); // underline the composition text to give the user some feedback UI _pMark->_SetCompositionDisplayAttributes(ec); } } // if we make it here, we've succeeded hr = S_OK; Exit: SafeRelease(pInsertAtSelection); pContextComposition->Release(); return hr; }
STDMETHODIMP TextService::Deactivate() { //::MessageBox(0, L"Deactivate", 0, 0); // terminate composition properly if(isComposing()) { ITfContext* context = currentContext(); if(context) { endComposition(context); context->Release(); } } onDeactivate(); // uninitialize language bar if(!langBarButtons_.empty()) { ComPtr<ITfLangBarItemMgr> langBarItemMgr; if(threadMgr_->QueryInterface(IID_ITfLangBarItemMgr, (void**)&langBarItemMgr) == S_OK) { for(vector<LangBarButton*>::iterator it = langBarButtons_.begin(); it != langBarButtons_.end(); ++it) { LangBarButton* button = *it; langBarItemMgr->RemoveItem(button); } } } if(langBarMgr_) { langBarMgr_->UnadviseEventSink(langBarSinkCookie_); langBarSinkCookie_ = TF_INVALID_COOKIE; langBarMgr_ = NULL; } // unadvice event sinks // ITfThreadMgrEventSink ComQIPtr<ITfSource> source = threadMgr_; if(source) { source->UnadviseSink(threadMgrEventSinkCookie_); source->UnadviseSink(activateLanguageProfileNotifySinkCookie_); threadMgrEventSinkCookie_ = TF_INVALID_COOKIE; activateLanguageProfileNotifySinkCookie_ = TF_INVALID_COOKIE; } // ITfTextEditSink, // ITfKeyEventSink ComQIPtr<ITfKeystrokeMgr> keystrokeMgr = threadMgr_; if(keystrokeMgr) { keystrokeMgr->UnadviseKeyEventSink(clientId_); // unregister preserved keys if(!preservedKeys_.empty()) { vector<PreservedKey>::iterator it; for(it = preservedKeys_.begin(); it != preservedKeys_.end(); ++it) { PreservedKey& preservedKey = *it; keystrokeMgr->UnpreserveKey(preservedKey.guid, &preservedKey); } } } // ITfCompositionSink // ITfCompartmentEventSink // thread specific compartment ComPtr<ITfCompartment> compartment = threadCompartment(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE); if(compartment) { ComQIPtr<ITfSource> compartmentSource = compartment; if(compartmentSource) compartmentSource->UnadviseSink(keyboardOpenEventSinkCookie_); keyboardOpenEventSinkCookie_ = TF_INVALID_COOKIE; } /* // global compartment compartment = globalCompartment(XXX_GUID); if(compartment) { ComQIPtr<ITfSource> compartmentSource = compartment; if(compartmentSource) compartmentSource->UnadviseSink(globalCompartmentEventSinkCookie_); globalCompartmentEventSinkCookie_ = TF_INVALID_COOKIE; } */ threadMgr_ = NULL; clientId_ = TF_CLIENTID_NULL; activateFlags_ = 0; return S_OK; }
BOOL CTextService::_IsKeyboardDisabled() { ITfCompartmentMgr *pCompMgr = NULL; ITfDocumentMgr *pDocMgrFocus = NULL; ITfContext *pContext = NULL; BOOL fDisabled = FALSE; if ((_pThreadMgr->GetFocus(&pDocMgrFocus) != S_OK) || (pDocMgrFocus == NULL)) { // if there is no focus document manager object, the keyboard // is disabled. fDisabled = TRUE; goto Exit; } if ((pDocMgrFocus->GetTop(&pContext) != S_OK) || (pContext == NULL)) { // if there is no context object, the keyboard is disabled. fDisabled = TRUE; goto Exit; } if (pContext->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr) == S_OK) { ITfCompartment *pCompartmentDisabled; ITfCompartment *pCompartmentEmptyContext; // Check GUID_COMPARTMENT_KEYBOARD_DISABLED. if (pCompMgr->GetCompartment(GUID_COMPARTMENT_KEYBOARD_DISABLED, &pCompartmentDisabled) == S_OK) { VARIANT var; if (S_OK == pCompartmentDisabled->GetValue(&var)) { if (var.vt == VT_I4) // Even VT_EMPTY, GetValue() can succeed { fDisabled = (BOOL)var.lVal; } } pCompartmentDisabled->Release(); } // Check GUID_COMPARTMENT_EMPTYCONTEXT. if (pCompMgr->GetCompartment(GUID_COMPARTMENT_EMPTYCONTEXT, &pCompartmentEmptyContext) == S_OK) { VARIANT var; if (S_OK == pCompartmentEmptyContext->GetValue(&var)) { if (var.vt == VT_I4) // Even VT_EMPTY, GetValue() can succeed { fDisabled = (BOOL)var.lVal; } } pCompartmentEmptyContext->Release(); } pCompMgr->Release(); } Exit: if (pContext) pContext->Release(); if (pDocMgrFocus) pDocMgrFocus->Release(); return fDisabled; }