void TextService::setCompositionString(EditSession* session, const wchar_t* str, int len) { ITfContext* context = session->context(); if(context) { TfEditCookie editCookie = session->editCookie(); TF_SELECTION selection; ULONG selectionNum; // get current selection/insertion point if(context->GetSelection(editCookie, TF_DEFAULT_SELECTION, 1, &selection, &selectionNum) == S_OK) { ComPtr<ITfRange> compositionRange; if(composition_->GetRange(&compositionRange) == S_OK) { bool selPosInComposition = true; // if current insertion point is not covered by composition, we cannot insert text here. if(selPosInComposition) { // replace context of composion area with the new string. compositionRange->SetText(editCookie, TF_ST_CORRECTION, str, len); // move the insertion point to end of the composition string selection.range->Collapse(editCookie, TF_ANCHOR_END); context->SetSelection(editCookie, 1, &selection); } // set display attribute to the composition range ComPtr<ITfProperty> dispAttrProp; if(context->GetProperty(GUID_PROP_ATTRIBUTE, &dispAttrProp) == S_OK) { VARIANT val; val.vt = VT_I4; val.lVal = module_->inputAttrib()->atom(); dispAttrProp->SetValue(editCookie, compositionRange, &val); } } selection.range->Release(); } } }
// callback from edit session for starting composition HRESULT TextService::doStartCompositionEditSession(TfEditCookie cookie, StartCompositionEditSession* session) { ITfContext* context = session->context(); ITfContextComposition* contextComposition; if(context->QueryInterface(IID_ITfContextComposition, (void**)&contextComposition) == S_OK) { // get current insertion point in the current context ITfRange* range = NULL; ITfInsertAtSelection* insertAtSelection; if(context->QueryInterface(IID_ITfInsertAtSelection, (void **)&insertAtSelection) == S_OK) { // get current selection range & insertion position (query only, did not insert any text) insertAtSelection->InsertTextAtSelection(cookie, TF_IAS_QUERYONLY, NULL, 0, &range); insertAtSelection->Release(); } if(range) { if(contextComposition->StartComposition(cookie, range, (ITfCompositionSink*)this, &composition_) == S_OK) { // according to the TSF sample provided by M$, we need to reset current // selection here. (maybe the range is altered by StartComposition()? // So mysterious. TSF is absolutely overly-engineered! TF_SELECTION selection; selection.range = range; selection.style.ase = TF_AE_NONE; selection.style.fInterimChar = FALSE; context->SetSelection(cookie, 1, &selection); // we did not release composition_ object. we store it for use later } range->Release(); } contextComposition->Release(); } return S_OK; }