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.
 
 
 
 
 
 

487 lines
13 KiB

//
//
// 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<ITfRange> 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<ITfRange> 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<ITfRange> cpAttrRange = NULL;
CComPtr<ITfProperty> 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<m_ulLen; i++)
{
wch = pwszTextToCap[i];
if ( iswalpha(wch) && !fFoundFirstAlpha )
{
if ( (wchLetter==0) && (m_idCapCmd != CAPCOMMAND_CapLetter) )
pwszNew[i] = towupper(wch);
else
{
if (wch == wchLetter)
pwszNew[i] = towupper(wch);
else
pwszNew[i] = wch;
}
fFoundFirstAlpha = TRUE;
}
else
{
pwszNew[i] = wch;
//
// We treat apostrophe as a normal character when handling capitalization
//
if ( (towupper(wch) == towlower(wch)) && ( wch != L'\'') && ( wch != 0x2019) )
{
// reach to a non-alpha character.
// now start to find first alphar for next word.
fFoundFirstAlpha = FALSE;
}
}
}
pwszNew[m_ulLen] = L'\0';
}
break;
case CAPCOMMAND_AllCapsThat :
case CAPCOMMAND_AllCaps :
for ( i=0; i<m_ulLen; i++)
{
wch = pwszTextToCap[i];
if ( iswalpha(wch) )
pwszNew[i] = towupper(wch);
else
pwszNew[i] = wch;
}
pwszNew[m_ulLen] = L'\0';
break;
case CAPCOMMAND_NoCapsThat :
case CAPCOMMAND_NoCaps :
for ( i=0; i<m_ulLen; i++)
{
wch = pwszTextToCap[i];
if ( iswalpha(wch) )
pwszNew[i] = towlower(wch);
else
pwszNew[i] = wch;
}
pwszNew[m_ulLen] = L'\0';
break;
}
*pwszNewText = pwszNew;
}
if ( *pwszNewText != NULL )
hr = S_OK;
else
{
if ( pwszNew )
cicMemFree(pwszNew);
hr = E_FAIL;
}
return hr;
}
/* ------------------------------------------------------------------
// Function Name: _GetCapPhrase
//
// Description: Generate the range to capitalize.
// it could be previous dictated phrase,
// or current selection,
// or current word around IP or before IP
// depends on the current text situation.
// -------------------------------------------------------------------*/
HRESULT CCapCmdHandler::_GetCapPhrase(TfEditCookie ec,ITfContext *pic, BOOL *fSapiText)
{
HRESULT hr = S_OK;
CComPtr<ITfRange> 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<ITfProperty> cpProp;
CComPtr<ITfRange> 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<ITfRange> 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;
}