Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

422 lines
12 KiB

//
//
// 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<ITfRange> cpCurIP;
CComPtr<ITfRange> 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<ITfRange> 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<MAX_DELIMITER; j++)
{
if ( m_Delimiter[j] == 0x0000)
break;
if ( pwzNewWord[i] == m_Delimiter[j])
{
fDelimiter = TRUE;
iKeep = i;
break;
}
}
if ( fDelimiter == TRUE )
break;
}
if ( fDelimiter )
{
cchSize = iKeep;
pwzNewWord[cchSize] = L'\0';
}
}
else
{
pwzNewWord = NULL;
cchSize = 0;
}
hr = DisplayAddDeleteUI(pwzNewWord, cchSize);
if ( pwzNewWord != NULL )
{
cicMemFree(pwzNewWord);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CAddDeleteWord::_DisplayAddDeleteUI
//
//
// Display the Add/Delete UI with pwszInitWord.
//
//---------------------------------------------------------------------------+
HRESULT CAddDeleteWord::DisplayAddDeleteUI(WCHAR *pwzInitWord, ULONG cchSize)
{
HRESULT hr = S_OK;
if (m_fInDisplayAddDeleteUI)
{
return hr;
}
m_fInDisplayAddDeleteUI = TRUE;
m_dstrInitWord.Clear();
if (pwzInitWord != NULL)
m_dstrInitWord.Append(pwzInitWord, cchSize);
PostMessage(m_psi->_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<ISpRecognizer> 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<ITfThreadMgr> 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;
}