// // // Sapilayr TIP CCapCmdHandler implementation. // // #include "private.h" #include "sapilayr.h" #include "capital.h" // ---------------------------------------------------------------------------------------------------------- // // Implementation for CCapCmdHandler // // ----------------------------------------------------------------------------------------------------------- CCapCmdHandler::CCapCmdHandler(CSapiIMX *psi) { m_psi = psi; } CCapCmdHandler::~CCapCmdHandler( ) { }; /* -------------------------------------------------------- // Function Name: ProcessCapCommands // // Description: public functions used by command handler // to handle any Capital related dictation // commands. // // ----------------------------------------------------------*/ HRESULT CCapCmdHandler::ProcessCapCommands(CAPCOMMAND_ID idCapCmd, WCHAR *pwszTextToCap, ULONG ulLen ) { HRESULT hr = E_FAIL; if ( !m_psi ) return E_FAIL; if ( (idCapCmd > CAPCOMMAND_MinIdWithText ) && (!pwszTextToCap || !ulLen)) return E_INVALIDARG; WCHAR *pwszText=NULL; ESDATA esData; memset(&esData, 0, sizeof(ESDATA)); if ( pwszTextToCap ) { esData.pData = pwszTextToCap; esData.uByte = (ulLen + 1) * sizeof(WCHAR); } esData.lData1 = (LONG_PTR)idCapCmd; esData.lData2 = (LONG_PTR)ulLen; hr = m_psi->_RequestEditSession(ESCB_PROCESS_CAP_COMMANDS, TF_ES_READWRITE, &esData); return hr; } /* -------------------------------------------------------- // Function Name: _ProcessCapCommands // // Description: Edit session call back funtion for // ProcessSelectionWord. // // it does real work for selection handling // ----------------------------------------------------------*/ HRESULT CCapCmdHandler::_ProcessCapCommands(TfEditCookie ec,ITfContext *pic, CAPCOMMAND_ID idCapCmd, WCHAR *pwszTextToCap, ULONG ulLen) { HRESULT hr = S_OK; // Get the Dictation Grammar TraceMsg(TF_GENERAL, "_ProcessCapCommands() is called"); if ( m_psi == NULL) return E_FAIL; CComPtr cpIP; cpIP = m_psi->GetSavedIP(); if ( cpIP == NULL ) { // Get the current IP. hr = GetSelectionSimple(ec, pic, &cpIP); } // Start to a new command. // Clear all the information saved for the previous command handling. m_dstrTextToCap.Clear( ); m_cpCapRange = cpIP; m_idCapCmd = idCapCmd; switch ( idCapCmd ) { case CAPCOMMAND_CapThat : case CAPCOMMAND_AllCapsThat : case CAPCOMMAND_NoCapsThat : hr = _HandleCapsThat(ec, pic); break; case CAPCOMMAND_CapsOn : hr = _CapsOnOff(ec, pic, TRUE); break; case CAPCOMMAND_CapsOff : hr = _CapsOnOff(ec, pic, FALSE); break; // Below commands require pwszTextToCap contains real text to be capitalized // injected to the document. case CAPCOMMAND_CapIt : case CAPCOMMAND_AllCaps : case CAPCOMMAND_NoCaps : m_dstrTextToCap.Append(pwszTextToCap); m_ulLen = ulLen; hr = _HandleCapsIt(ec, pic); break; case CAPCOMMAND_CapLetter : hr = _HandleCapsThat(ec, pic, towlower(pwszTextToCap[0])); break; default : break; } // update the saved ip so that next time the hypothesis will // start from this new selection. m_psi->SaveLastUsedIPRange( ); m_psi->SaveIPRange(NULL); return hr; } /* -------------------------------------------------------------- // Function Name: _SetNewText // // Description: Inject the new text to m_cpCapRange in // the document and update necessary property // data. // // --------------------------------------------------------------*/ HRESULT CCapCmdHandler::_SetNewText(TfEditCookie ec,ITfContext *pic, WCHAR *pwszNewText, BOOL fSapiText) { HRESULT hr = S_OK; BOOL fInsertOk; CComPtr cpRange; if (!pwszNewText) return E_INVALIDARG; m_cpCapRange->Clone(&cpRange); hr = cpRange->AdjustForInsert(ec, wcslen(pwszNewText), &fInsertOk); if (S_OK == hr && fInsertOk) { // start a composition here if we haven't already m_psi->_CheckStartComposition(ec, cpRange); // set the text hr = cpRange->SetText(ec, 0, pwszNewText, -1); if ( fSapiText ) { // // set attribute range // CComPtr cpAttrRange = NULL; CComPtr cpProp = NULL; if (hr == S_OK) { hr = pic->GetProperty(GUID_PROP_SAPI_DISPATTR, &cpProp); } if (S_OK == hr) { hr = cpRange->Clone(&cpAttrRange); } if (S_OK == hr && cpAttrRange) { SetGUIDPropertyData(m_psi->_GetLibTLS( ), ec, cpProp, cpAttrRange, GUID_ATTR_SAPI_INPUT); } // // setup langid property // //_SetLangID(ec, pic, cpRange, langid); } if ( hr == S_OK ) { cpRange->Collapse(ec, TF_ANCHOR_END); SetSelectionSimple(ec, pic, cpRange); } } return hr; } /* ------------------------------------------------------------------ // Function Name: _CapsText // // Description: Generate capitalized text based on current // Capital command id. // // Inside this function, it will allocate memory // for new generated capitaized text. // Caller is responsible for release the allocated // memory // -------------------------------------------------------------------*/ HRESULT CCapCmdHandler::_CapsText(WCHAR **pwszNewText, WCHAR wchLetter) { HRESULT hr = S_OK; WCHAR *pwszNew, *pwszTextToCap; ULONG i; // Generate new text based on the requirement if ( !pwszNewText ) return E_INVALIDARG; *pwszNewText = NULL; pwszTextToCap = (WCHAR *)m_dstrTextToCap; pwszNew = (WCHAR *)cicMemAlloc((m_ulLen+1)*sizeof(WCHAR)); if ( pwszNew ) { WCHAR wch; switch (m_idCapCmd) { case CAPCOMMAND_CapThat : case CAPCOMMAND_CapIt : case CAPCOMMAND_CapLetter : { BOOL fFoundFirstAlpha=FALSE; for (i=0; i cpCapRange; BOOL bSapiText = FALSE; if ( !m_psi ) return E_FAIL; if ( !fSapiText ) return E_INVALIDARG; hr = m_psi->_GetCmdThatRange(ec, pic, &cpCapRange); if ( hr == S_OK && cpCapRange ) { m_cpCapRange = cpCapRange; // Set bSapiText here. // If the range is inside a dictated phrase, set bSapiText = TRUE; CComPtr cpProp; CComPtr cpSapiPropRange; long l1=0, l2=0; hr = pic->GetProperty(GUID_PROP_SAPI_DISPATTR, &cpProp); if ( hr == S_OK ) hr = cpProp->FindRange(ec, cpCapRange, &cpSapiPropRange, TF_ANCHOR_START); // Is cpRange inside cpSapiPropRange ? if ( hr == S_OK ) hr = cpCapRange->CompareStart(ec, cpSapiPropRange, TF_ANCHOR_START, &l1); if ( hr == S_OK ) hr = cpCapRange->CompareEnd(ec, cpSapiPropRange, TF_ANCHOR_END, &l2); if ( hr == S_OK && (l1>=0 && l2<=0) ) { // the Range is inside SAPI input range. bSapiText = TRUE; } // hr could be S_FALSE, if the range is not dictated. // We still treat S_FALSE as S_OK in the return hr. if ( SUCCEEDED(hr) ) hr = S_OK; } *fSapiText = bSapiText; return hr; } HRESULT CCapCmdHandler::_HandleCapsThat(TfEditCookie ec,ITfContext *pic, WCHAR wchLetter) { HRESULT hr = S_OK; BOOL fSapiText; // Get the range to capitalize hr = _GetCapPhrase(ec, pic, &fSapiText); if ( hr == S_OK ) { CComPtr cpRangeCloned; BOOL fEmpty = TRUE; hr = m_cpCapRange->IsEmpty(ec, &fEmpty); if ( hr == S_OK && !fEmpty ) { hr = m_cpCapRange->Clone(&cpRangeCloned); // Get the text in the CapRange. if ( hr == S_OK ) { ULONG ucch; while(S_OK == hr && (S_OK == cpRangeCloned->IsEmpty(ec, &fEmpty)) && !fEmpty) { WCHAR sz[128]; hr = cpRangeCloned->GetText(ec, TF_TF_MOVESTART, sz, ARRAYSIZE(sz)-1, &ucch); if (S_OK == hr) { sz[ucch] = L'\0'; m_dstrTextToCap.Append(sz); } } m_ulLen = m_dstrTextToCap.Length( ); } if ( hr==S_OK && m_dstrTextToCap) { // Generate new text based on the requirement WCHAR *pwszNewText; hr = _CapsText(&pwszNewText, wchLetter); if ( hr == S_OK ) { hr = _SetNewText(ec, pic, (WCHAR *)pwszNewText, fSapiText); cicMemFree(pwszNewText); } } } } return hr; } HRESULT CCapCmdHandler::_CapsOnOff(TfEditCookie ec,ITfContext *pic, BOOL fOn) { HRESULT hr = S_OK; return hr; } HRESULT CCapCmdHandler::_HandleCapsIt(TfEditCookie ec,ITfContext *pic) { HRESULT hr = S_OK; if ( m_dstrTextToCap) { // Generate new text based on the requirement WCHAR *pwszNewText; hr = _CapsText(&pwszNewText); if ( hr == S_OK ) { hr = _SetNewText(ec, pic, (WCHAR *)pwszNewText, TRUE); cicMemFree(pwszNewText); } } return hr; }