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

  1. //
  2. //
  3. // Sapilayr TIP CAddDeleteWord implementation.
  4. //
  5. //
  6. #include "private.h"
  7. #include "sapilayr.h"
  8. #include "adddelete.h"
  9. #include "mui.h"
  10. WCHAR CAddDeleteWord::m_Delimiter[MAX_DELIMITER] = {
  11. 0x0009,0x000A,0x000D,0x0020,
  12. 0x0022,0x0023,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A, // "#%&'()*
  13. 0x002B,0x002C,0x002D,0x002F,0x003A,0x003B,0x003C,0x003D, // +,-/:;<=
  14. 0x003E,0x0040,0x005B,0x005D,0x0021,0x002E,0x003F,0x005E, // >@[]!.?^
  15. 0x007B,0x007C,0x007D,0x007E, // {|}~
  16. 0x0000
  17. };
  18. // ----------------------------------------------------------------------------------------------------------
  19. //
  20. // Implementation for CAddDeleteWord
  21. //
  22. // -----------------------------------------------------------------------------------------------------------
  23. CAddDeleteWord::CAddDeleteWord(CSapiIMX *psi)
  24. {
  25. m_psi = psi;
  26. m_cpRangeLastUsedIP = NULL;
  27. m_fCurIPIsSelection = FALSE;
  28. _pCSpTask = NULL;
  29. m_fMessagePopUp = FALSE;
  30. m_fToOpenAddDeleteUI = FALSE;
  31. m_fAddDeleteUIOpened = FALSE;
  32. m_fInDisplayAddDeleteUI = FALSE;
  33. }
  34. CAddDeleteWord::~CAddDeleteWord( )
  35. {
  36. };
  37. // This function will be called by SR SPEI_SOUND_START callback function
  38. // It will save current selection or IP.
  39. //
  40. // And compare the current IP with the last saved IP, if both of them are
  41. // not empty, and have the same start anchor, sptip tip will pop up a
  42. // message box to ask if user wants to popup SR Add/Remove Word dialog UI.
  43. //
  44. // If Add/Delete UI is not opened, we just want to inject feedbackui as usual
  45. HRESULT CAddDeleteWord::SaveCurIPAndHandleAddDelete_InjectFeedbackUI( )
  46. {
  47. HRESULT hr = E_FAIL;
  48. m_fAddDeleteUIOpened = FALSE;
  49. hr = m_psi->_RequestEditSession(ESCB_SAVECURIP_ADDDELETEUI, TF_ES_READWRITE);
  50. return hr;
  51. }
  52. HRESULT CAddDeleteWord::_SaveCurIPAndHandleAddDeleteUI(TfEditCookie ec, ITfContext *pic)
  53. {
  54. HRESULT hr = S_OK;
  55. CComPtr<ITfRange> cpCurIP;
  56. CComPtr<ITfRange> cpLastIP;
  57. BOOL fEmptyLast= FALSE;
  58. BOOL fEmptyCur = TRUE;
  59. // Save the current IP first.
  60. #ifdef SHOW_ADD_DELETE_POPUP_MESSAGE
  61. // if we need to activate this code we need to move this function
  62. // into the hypothesis handler, otherwise we will reactivate the bug
  63. // Cicero 3800 - sticky ip behavior makes typing/talking impractical
  64. // Hence I put a non conditional assert here
  65. Assert(0);
  66. m_psi->SaveCurrentIP(ec, pic);
  67. #endif
  68. // Compare current IP with last saved IP
  69. // If user selects the same range twice, just open SR Add/remove dialog UI
  70. cpCurIP = m_psi->GetSavedIP( );
  71. cpLastIP = GetLastUsedIP( );
  72. m_fAddDeleteUIOpened = FALSE;
  73. if ( cpCurIP )
  74. {
  75. // Save the Org IP by cloning the current IP.
  76. if ( m_cpRangeOrgIP )
  77. m_cpRangeOrgIP.Release( );
  78. cpCurIP->Clone(&m_cpRangeOrgIP);
  79. hr = cpCurIP->IsEmpty(ec, &fEmptyCur);
  80. }
  81. m_fCurIPIsSelection = !fEmptyCur;
  82. #ifdef SHOW_ADD_DELETE_POPUP_MESSAGE
  83. if ( (S_OK == hr) && m_fCurIPIsSelection && cpLastIP)
  84. {
  85. hr = cpLastIP->IsEmpty(ec, &fEmptyLast);
  86. if ( (S_OK == hr) && !fEmptyLast )
  87. {
  88. BOOL fEqualStart = FALSE;
  89. hr = cpCurIP->IsEqualStart(ec, cpLastIP, TF_ANCHOR_START, &fEqualStart);
  90. if ( (S_OK == hr) && fEqualStart )
  91. {
  92. // Open the dialog UI
  93. if ( !m_fMessagePopUp )
  94. {
  95. BOOL fDictStat;
  96. // If Mic status is ON, turn it off.
  97. fDictStat = m_psi->GetDICTATIONSTAT_DictOnOff( );
  98. if ( fDictStat == TRUE)
  99. {
  100. m_psi->SetDICTATIONSTAT_DictOnOff(FALSE);
  101. }
  102. DialogBoxParam(g_hInst,
  103. MAKEINTRESOURCE(IDD_OPEN_ADD_DELETE),
  104. m_psi->_GetAppMainWnd(),
  105. DlgProc,
  106. (LPARAM)this);
  107. if ( fDictStat )
  108. m_psi->SetDICTATIONSTAT_DictOnOff(TRUE);
  109. m_fMessagePopUp = TRUE;
  110. }
  111. if ( m_fToOpenAddDeleteUI )
  112. hr = _HandleAddDeleteWord(ec, pic);
  113. }
  114. }
  115. }
  116. #endif
  117. #ifdef SHOW_FEEDBACK_AT_SOUNDSTART
  118. if ( !m_fAddDeleteUIOpened && !m_fCurIPIsSelection)
  119. {
  120. BOOL fAware = IsFocusFullAware(m_psi->_tim);
  121. hr = m_psi->_AddFeedbackUI(ec,
  122. fAware ? DA_COLOR_AWARE : DA_COLOR_UNAWARE,
  123. 3);
  124. }
  125. #endif
  126. return hr;
  127. }
  128. //+---------------------------------------------------------------------------
  129. //
  130. // DlgProc
  131. //
  132. //----------------------------------------------------------------------------
  133. INT_PTR CALLBACK CAddDeleteWord::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  134. {
  135. INT_PTR iRet = TRUE;
  136. switch (uMsg)
  137. {
  138. case WM_INITDIALOG:
  139. SetThis(hDlg, lParam);
  140. break;
  141. case WM_COMMAND:
  142. GetThis(hDlg)->OnCommand(hDlg, wParam, lParam);
  143. break;
  144. default:
  145. iRet = FALSE;
  146. }
  147. return iRet;
  148. }
  149. //+---------------------------------------------------------------------------
  150. //
  151. // OnCommand
  152. //
  153. //----------------------------------------------------------------------------
  154. BOOL CAddDeleteWord::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
  155. {
  156. switch (LOWORD(wParam))
  157. {
  158. case IDOK:
  159. m_fToOpenAddDeleteUI = TRUE;
  160. EndDialog(hDlg, 1);
  161. break;
  162. case IDCANCEL:
  163. m_fToOpenAddDeleteUI = FALSE;
  164. EndDialog(hDlg, 0);
  165. break;
  166. default:
  167. m_fToOpenAddDeleteUI = FALSE;
  168. return FALSE;
  169. }
  170. return TRUE;
  171. }
  172. //+---------------------------------------------------------------------------
  173. //
  174. // CAddDeleteWord::_HandleAddDeleteWord
  175. //
  176. // Handle Add/Delete Word UI related work.
  177. // This function will be called when user clicks the speech language bar menu
  178. // and select Add/Delete Word(s)... item.
  179. //
  180. //---------------------------------------------------------------------------+
  181. HRESULT CAddDeleteWord::_HandleAddDeleteWord( TfEditCookie ec,ITfContext *pic )
  182. {
  183. HRESULT hr = S_OK;
  184. WCHAR *pwzNewWord=NULL;
  185. CComPtr<ITfRange> cpCurRange = NULL;
  186. ULONG cchSize;
  187. BOOL fEmptySelection=TRUE;
  188. // Get the current Selection
  189. TraceMsg(TF_GENERAL, "_HandleAddDeleteWord is called");
  190. if ( pic == NULL )
  191. return E_FAIL;
  192. GetSelectionSimple(ec, pic, &cpCurRange);
  193. // Check to see if the current selection is empty.
  194. if ( cpCurRange!= NULL )
  195. {
  196. hr = cpCurRange->IsEmpty(ec, &fEmptySelection);
  197. if ( hr != S_OK )
  198. return hr;
  199. }
  200. // If the current Selection is not empty, we need to get the correct word to send to the Add/Remove dialog
  201. // as its initial word.
  202. if (( cpCurRange != NULL ) && !fEmptySelection )
  203. {
  204. ULONG i, j, iKeep;
  205. BOOL fDelimiter;
  206. // Get the text of the selection.
  207. // Follow the below rules to get the right word.
  208. //
  209. // If the current selection is longer than MAX_SELECED wchars of string, discard the rest.
  210. //
  211. // If there is a delimiter ( space, tab, ... ) inside the selection, take the part prior to the first
  212. // delimiter as the right word.
  213. pwzNewWord = (WCHAR *) cicMemAllocClear( (MAX_SELECTED+1) * sizeof(WCHAR) );
  214. if ( pwzNewWord == NULL )
  215. {
  216. hr = E_OUTOFMEMORY;
  217. return hr;
  218. }
  219. cchSize = MAX_SELECTED;
  220. hr = cpCurRange->GetText(ec, 0, pwzNewWord, MAX_SELECTED, &cchSize);
  221. if ( hr != S_OK )
  222. {
  223. // GetRangeText returns wrong, release the allocated memory
  224. cicMemFree(pwzNewWord);
  225. return hr;
  226. }
  227. pwzNewWord[cchSize] = L'\0';
  228. // Get the first delimiter if there is one.
  229. fDelimiter = FALSE;
  230. iKeep = 0;
  231. for ( i=0; i < cchSize; i++)
  232. {
  233. for ( j=0; j<MAX_DELIMITER; j++)
  234. {
  235. if ( m_Delimiter[j] == 0x0000)
  236. break;
  237. if ( pwzNewWord[i] == m_Delimiter[j])
  238. {
  239. fDelimiter = TRUE;
  240. iKeep = i;
  241. break;
  242. }
  243. }
  244. if ( fDelimiter == TRUE )
  245. break;
  246. }
  247. if ( fDelimiter )
  248. {
  249. cchSize = iKeep;
  250. pwzNewWord[cchSize] = L'\0';
  251. }
  252. }
  253. else
  254. {
  255. pwzNewWord = NULL;
  256. cchSize = 0;
  257. }
  258. hr = DisplayAddDeleteUI(pwzNewWord, cchSize);
  259. if ( pwzNewWord != NULL )
  260. {
  261. cicMemFree(pwzNewWord);
  262. }
  263. return hr;
  264. }
  265. //+---------------------------------------------------------------------------
  266. //
  267. // CAddDeleteWord::_DisplayAddDeleteUI
  268. //
  269. //
  270. // Display the Add/Delete UI with pwszInitWord.
  271. //
  272. //---------------------------------------------------------------------------+
  273. HRESULT CAddDeleteWord::DisplayAddDeleteUI(WCHAR *pwzInitWord, ULONG cchSize)
  274. {
  275. HRESULT hr = S_OK;
  276. if (m_fInDisplayAddDeleteUI)
  277. {
  278. return hr;
  279. }
  280. m_fInDisplayAddDeleteUI = TRUE;
  281. m_dstrInitWord.Clear();
  282. if (pwzInitWord != NULL)
  283. m_dstrInitWord.Append(pwzInitWord, cchSize);
  284. PostMessage(m_psi->_GetWorkerWnd(), WM_PRIV_ADDDELETE, 0, 0);
  285. return hr;
  286. }
  287. HRESULT CAddDeleteWord::_DisplayAddDeleteUI(void)
  288. {
  289. HRESULT hr = S_OK;
  290. WCHAR pwzTitle[64];
  291. // Display the UI
  292. pwzTitle[0] = '\0';
  293. CicLoadStringWrapW(g_hInst, IDS_UI_ADDDELETE, pwzTitle, ARRAYSIZE(pwzTitle));
  294. CComPtr<ISpRecognizer> cpRecoEngine;
  295. m_psi->GetSpeechTask(&_pCSpTask, FALSE);
  296. if ( _pCSpTask )
  297. {
  298. hr = _pCSpTask->GetSAPIInterface(IID_ISpRecognizer, (void **)&cpRecoEngine);
  299. if (S_OK == hr && cpRecoEngine)
  300. {
  301. // If Mic status is ON, turn it off.
  302. DWORD dwDictStatBackup = m_psi->GetDictationStatBackup();
  303. DWORD dwBefore;
  304. CComPtr<ITfThreadMgr> cpTim = m_psi->_tim;
  305. if (S_OK !=
  306. GetCompartmentDWORD(cpTim, GUID_COMPARTMENT_SPEECH_DISABLED, &dwBefore, FALSE)
  307. )
  308. {
  309. dwBefore = 0;
  310. }
  311. SetCompartmentDWORD(m_psi->_GetId(), cpTim, GUID_COMPARTMENT_SPEECH_DISABLED, TF_DISABLE_DICTATION, FALSE);
  312. cpRecoEngine->DisplayUI(m_psi->_GetAppMainWnd(), pwzTitle, SPDUI_AddRemoveWord, m_dstrInitWord, m_dstrInitWord.Length() * sizeof(WCHAR));
  313. m_fAddDeleteUIOpened = TRUE;
  314. SetCompartmentDWORD(m_psi->_GetId(), cpTim, GUID_COMPARTMENT_SPEECH_DISABLED, dwBefore, FALSE);
  315. // After Add/Remove work is done, restore the previous Mic status.
  316. SetCompartmentDWORD(m_psi->_GetId(), cpTim, GUID_COMPARTMENT_SPEECH_DICTATIONSTAT, dwDictStatBackup, FALSE);
  317. }
  318. }
  319. m_fInDisplayAddDeleteUI = FALSE;
  320. return hr;
  321. }