// // // Sapilayr TIP CAddDeleteWord implementation. // // #include "private.h" #include "sapilayr.h" #include "adddelete.h" #include "mui.h" WCHAR CAddDeleteWord::m_Delimiter[MAX_DELIMITER] = { 0x0009,0x000A,0x000D,0x0020, 0x0022,0x0023,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A, // "#%&'()* 0x002B,0x002C,0x002D,0x002F,0x003A,0x003B,0x003C,0x003D, // +,-/:;<= 0x003E,0x0040,0x005B,0x005D,0x0021,0x002E,0x003F,0x005E, // >@[]!.?^ 0x007B,0x007C,0x007D,0x007E, // {|}~ 0x0000 }; // ---------------------------------------------------------------------------------------------------------- // // Implementation for CAddDeleteWord // // ----------------------------------------------------------------------------------------------------------- CAddDeleteWord::CAddDeleteWord(CSapiIMX *psi) { m_psi = psi; m_cpRangeLastUsedIP = NULL; m_fCurIPIsSelection = FALSE; _pCSpTask = NULL; m_fMessagePopUp = FALSE; m_fToOpenAddDeleteUI = FALSE; m_fAddDeleteUIOpened = FALSE; m_fInDisplayAddDeleteUI = FALSE; } CAddDeleteWord::~CAddDeleteWord( ) { }; // This function will be called by SR SPEI_SOUND_START callback function // It will save current selection or IP. // // And compare the current IP with the last saved IP, if both of them are // not empty, and have the same start anchor, sptip tip will pop up a // message box to ask if user wants to popup SR Add/Remove Word dialog UI. // // If Add/Delete UI is not opened, we just want to inject feedbackui as usual HRESULT CAddDeleteWord::SaveCurIPAndHandleAddDelete_InjectFeedbackUI( ) { HRESULT hr = E_FAIL; m_fAddDeleteUIOpened = FALSE; hr = m_psi->_RequestEditSession(ESCB_SAVECURIP_ADDDELETEUI, TF_ES_READWRITE); return hr; } HRESULT CAddDeleteWord::_SaveCurIPAndHandleAddDeleteUI(TfEditCookie ec, ITfContext *pic) { HRESULT hr = S_OK; CComPtr cpCurIP; CComPtr cpLastIP; BOOL fEmptyLast= FALSE; BOOL fEmptyCur = TRUE; // Save the current IP first. #ifdef SHOW_ADD_DELETE_POPUP_MESSAGE // if we need to activate this code we need to move this function // into the hypothesis handler, otherwise we will reactivate the bug // Cicero 3800 - sticky ip behavior makes typing/talking impractical // Hence I put a non conditional assert here Assert(0); m_psi->SaveCurrentIP(ec, pic); #endif // Compare current IP with last saved IP // If user selects the same range twice, just open SR Add/remove dialog UI cpCurIP = m_psi->GetSavedIP( ); cpLastIP = GetLastUsedIP( ); m_fAddDeleteUIOpened = FALSE; if ( cpCurIP ) { // Save the Org IP by cloning the current IP. if ( m_cpRangeOrgIP ) m_cpRangeOrgIP.Release( ); cpCurIP->Clone(&m_cpRangeOrgIP); hr = cpCurIP->IsEmpty(ec, &fEmptyCur); } m_fCurIPIsSelection = !fEmptyCur; #ifdef SHOW_ADD_DELETE_POPUP_MESSAGE if ( (S_OK == hr) && m_fCurIPIsSelection && cpLastIP) { hr = cpLastIP->IsEmpty(ec, &fEmptyLast); if ( (S_OK == hr) && !fEmptyLast ) { BOOL fEqualStart = FALSE; hr = cpCurIP->IsEqualStart(ec, cpLastIP, TF_ANCHOR_START, &fEqualStart); if ( (S_OK == hr) && fEqualStart ) { // Open the dialog UI if ( !m_fMessagePopUp ) { BOOL fDictStat; // If Mic status is ON, turn it off. fDictStat = m_psi->GetDICTATIONSTAT_DictOnOff( ); if ( fDictStat == TRUE) { m_psi->SetDICTATIONSTAT_DictOnOff(FALSE); } DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_OPEN_ADD_DELETE), m_psi->_GetAppMainWnd(), DlgProc, (LPARAM)this); if ( fDictStat ) m_psi->SetDICTATIONSTAT_DictOnOff(TRUE); m_fMessagePopUp = TRUE; } if ( m_fToOpenAddDeleteUI ) hr = _HandleAddDeleteWord(ec, pic); } } } #endif #ifdef SHOW_FEEDBACK_AT_SOUNDSTART if ( !m_fAddDeleteUIOpened && !m_fCurIPIsSelection) { BOOL fAware = IsFocusFullAware(m_psi->_tim); hr = m_psi->_AddFeedbackUI(ec, fAware ? DA_COLOR_AWARE : DA_COLOR_UNAWARE, 3); } #endif return hr; } //+--------------------------------------------------------------------------- // // DlgProc // //---------------------------------------------------------------------------- INT_PTR CALLBACK CAddDeleteWord::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR iRet = TRUE; switch (uMsg) { case WM_INITDIALOG: SetThis(hDlg, lParam); break; case WM_COMMAND: GetThis(hDlg)->OnCommand(hDlg, wParam, lParam); break; default: iRet = FALSE; } return iRet; } //+--------------------------------------------------------------------------- // // OnCommand // //---------------------------------------------------------------------------- BOOL CAddDeleteWord::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) { case IDOK: m_fToOpenAddDeleteUI = TRUE; EndDialog(hDlg, 1); break; case IDCANCEL: m_fToOpenAddDeleteUI = FALSE; EndDialog(hDlg, 0); break; default: m_fToOpenAddDeleteUI = FALSE; return FALSE; } return TRUE; } //+--------------------------------------------------------------------------- // // CAddDeleteWord::_HandleAddDeleteWord // // Handle Add/Delete Word UI related work. // This function will be called when user clicks the speech language bar menu // and select Add/Delete Word(s)... item. // //---------------------------------------------------------------------------+ HRESULT CAddDeleteWord::_HandleAddDeleteWord( TfEditCookie ec,ITfContext *pic ) { HRESULT hr = S_OK; WCHAR *pwzNewWord=NULL; CComPtr cpCurRange = NULL; ULONG cchSize; BOOL fEmptySelection=TRUE; // Get the current Selection TraceMsg(TF_GENERAL, "_HandleAddDeleteWord is called"); if ( pic == NULL ) return E_FAIL; GetSelectionSimple(ec, pic, &cpCurRange); // Check to see if the current selection is empty. if ( cpCurRange!= NULL ) { hr = cpCurRange->IsEmpty(ec, &fEmptySelection); if ( hr != S_OK ) return hr; } // If the current Selection is not empty, we need to get the correct word to send to the Add/Remove dialog // as its initial word. if (( cpCurRange != NULL ) && !fEmptySelection ) { ULONG i, j, iKeep; BOOL fDelimiter; // Get the text of the selection. // Follow the below rules to get the right word. // // If the current selection is longer than MAX_SELECED wchars of string, discard the rest. // // If there is a delimiter ( space, tab, ... ) inside the selection, take the part prior to the first // delimiter as the right word. pwzNewWord = (WCHAR *) cicMemAllocClear( (MAX_SELECTED+1) * sizeof(WCHAR) ); if ( pwzNewWord == NULL ) { hr = E_OUTOFMEMORY; return hr; } cchSize = MAX_SELECTED; hr = cpCurRange->GetText(ec, 0, pwzNewWord, MAX_SELECTED, &cchSize); if ( hr != S_OK ) { // GetRangeText returns wrong, release the allocated memory cicMemFree(pwzNewWord); return hr; } pwzNewWord[cchSize] = L'\0'; // Get the first delimiter if there is one. fDelimiter = FALSE; iKeep = 0; for ( i=0; i < cchSize; i++) { for ( j=0; j_GetWorkerWnd(), WM_PRIV_ADDDELETE, 0, 0); return hr; } HRESULT CAddDeleteWord::_DisplayAddDeleteUI(void) { HRESULT hr = S_OK; WCHAR pwzTitle[64]; // Display the UI pwzTitle[0] = '\0'; CicLoadStringWrapW(g_hInst, IDS_UI_ADDDELETE, pwzTitle, ARRAYSIZE(pwzTitle)); CComPtr cpRecoEngine; m_psi->GetSpeechTask(&_pCSpTask, FALSE); if ( _pCSpTask ) { hr = _pCSpTask->GetSAPIInterface(IID_ISpRecognizer, (void **)&cpRecoEngine); if (S_OK == hr && cpRecoEngine) { // If Mic status is ON, turn it off. DWORD dwDictStatBackup = m_psi->GetDictationStatBackup(); DWORD dwBefore; CComPtr cpTim = m_psi->_tim; if (S_OK != GetCompartmentDWORD(cpTim, GUID_COMPARTMENT_SPEECH_DISABLED, &dwBefore, FALSE) ) { dwBefore = 0; } SetCompartmentDWORD(m_psi->_GetId(), cpTim, GUID_COMPARTMENT_SPEECH_DISABLED, TF_DISABLE_DICTATION, FALSE); cpRecoEngine->DisplayUI(m_psi->_GetAppMainWnd(), pwzTitle, SPDUI_AddRemoveWord, m_dstrInitWord, m_dstrInitWord.Length() * sizeof(WCHAR)); m_fAddDeleteUIOpened = TRUE; SetCompartmentDWORD(m_psi->_GetId(), cpTim, GUID_COMPARTMENT_SPEECH_DISABLED, dwBefore, FALSE); // After Add/Remove work is done, restore the previous Mic status. SetCompartmentDWORD(m_psi->_GetId(), cpTim, GUID_COMPARTMENT_SPEECH_DICTATIONSTAT, dwDictStatBackup, FALSE); } } m_fInDisplayAddDeleteUI = FALSE; return hr; }