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.

1883 lines
65 KiB

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include "comp.h"
  4. #include "StreamHlp.h"
  5. //#define INPROC
  6. /****************************************************************************
  7. * CCompiler::~CCompiler *
  8. *---------------------------*
  9. * Description:
  10. * Releases objects created by CCompiler
  11. **************************************************************** Leonro *****/
  12. CCompiler::~CCompiler()
  13. {
  14. m_cpRichEdit.Release();
  15. m_cpTextDoc.Release();
  16. m_cpTextSel.Release();
  17. m_cpRecognizer.Release();
  18. m_cpRecoContext.Release();
  19. m_cpCompiler.Release();
  20. m_cpRecoGrammar.Release();
  21. if( m_hMod )
  22. {
  23. FreeLibrary( m_hMod );
  24. }
  25. }
  26. /****************************************************************************
  27. * CCompiler::Initialize *
  28. *---------------------------*
  29. * Description:
  30. * Set up the windows, as well as the RichEdit objects.
  31. * Also it initializes some SAPI objects.
  32. ************************************************************** Leonro *******/
  33. HRESULT CCompiler::Initialize( int nCmdShow )
  34. {
  35. TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
  36. TCHAR szWindowClass[MAX_LOADSTRING]; // Window class
  37. HRESULT hr = S_OK;
  38. WNDCLASSEX wcex;
  39. // Initialize global strings
  40. LoadString( m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
  41. LoadString( m_hInstance, IDC_GRAMCOMP, szWindowClass, MAX_LOADSTRING );
  42. // Register the windows class
  43. wcex.cbSize = sizeof(WNDCLASSEX);
  44. wcex.style = CS_HREDRAW | CS_VREDRAW;
  45. wcex.lpfnWndProc = WndProc;
  46. wcex.cbClsExtra = 0;
  47. wcex.cbWndExtra = 0;
  48. wcex.hInstance = m_hInstance;
  49. wcex.hIcon = LoadIcon(m_hInstance, (LPCTSTR)IDI_GRAMCOMP);
  50. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  51. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  52. wcex.lpszMenuName = (LPCSTR)IDC_GRAMCOMP;
  53. wcex.lpszClassName = szWindowClass;
  54. wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
  55. // Register window and create the sapi grammar compiler
  56. if( RegisterClassEx(&wcex) )
  57. {
  58. hr = m_cpCompiler.CoCreateInstance( CLSID_SpGrammarCompiler );
  59. if( FAILED( hr ) )
  60. {
  61. MessageBox( NULL, _T("Error initializing speech objects. Shutting down.\n\n"
  62. " Please make sure SAPI5 is installed!"), _T("Error"), MB_OK );
  63. }
  64. }
  65. else
  66. {
  67. MessageBox( NULL, _T("Error initializing application. Shutting down."),
  68. _T("Error"), MB_OK );
  69. hr = E_FAIL;
  70. }
  71. // Load DLL for Rich Edit 3.0
  72. if( SUCCEEDED( hr ) )
  73. {
  74. m_hMod = LoadLibrary( "RICHED20.DLL" );
  75. if( !m_hMod )
  76. {
  77. MessageBox( NULL, "Couldn't find required riched32.dll. Shutting down!",
  78. "Error - Missing dll", MB_OK );
  79. hr = E_FAIL;
  80. }
  81. }
  82. if( SUCCEEDED( hr ) )
  83. {
  84. // Perform application initialization:
  85. m_hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  86. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, m_hInstance, this );
  87. if( m_hWnd && m_hWndStatus && m_hWndEdit )
  88. {
  89. // Get TOM interfaces
  90. SendMessage( m_hWndEdit, EM_GETOLEINTERFACE, 0, (LPARAM)(LPVOID FAR *)&m_cpRichEdit );
  91. SendMessage( m_hWndEdit, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_KEYEVENTS );
  92. if( !m_cpRichEdit )
  93. {
  94. hr = E_NOINTERFACE;
  95. }
  96. if( SUCCEEDED( hr ) )
  97. {
  98. hr = m_cpRichEdit->QueryInterface( IID_ITextDocument, (void**)&m_cpTextDoc );
  99. if( SUCCEEDED( hr ) )
  100. {
  101. hr = m_cpTextDoc->GetSelection( &m_cpTextSel );
  102. }
  103. }
  104. if( SUCCEEDED( hr ) )
  105. {
  106. // Load Accelerators
  107. m_hAccelTable = LoadAccelerators( m_hInstance, MAKEINTRESOURCE(IDR_GRAMACCEL) );
  108. ::ShowWindow( m_hWnd, nCmdShow );
  109. ::UpdateWindow( m_hWnd );
  110. }
  111. else
  112. {
  113. MessageBox( m_hWnd, _T("Error initializing edit control. Shutting down!"), _T("Error"), MB_OK );
  114. }
  115. }
  116. }
  117. return hr;
  118. }
  119. /****************************************************************************************
  120. * CCompiler::Run() *
  121. *----------------------*
  122. * Description:
  123. * Contains the message loop for the application
  124. **************************************************************************** Leonro *****/
  125. int CCompiler::Run()
  126. {
  127. MSG msg;
  128. // Main message loop:
  129. while( ::GetMessage(&msg, NULL, 0, 0) )
  130. {
  131. if( !::TranslateAccelerator(m_hWnd, m_hAccelTable, &msg) )
  132. {
  133. ::TranslateMessage( &msg );
  134. ::DispatchMessage( &msg );
  135. }
  136. }
  137. return msg.wParam;
  138. } /* CCompiler::Run */
  139. /****************************************************************************
  140. * CCompiler::WndProc *
  141. *---------------------------*
  142. * Description:
  143. * Processes messages for the main window.
  144. ***************************************************************** Leonro ****/
  145. LRESULT CALLBACK CCompiler::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  146. {
  147. int wmId, wmEvent;
  148. static BOOL bFileOpened = FALSE;
  149. PAINTSTRUCT psMain, psStatus;
  150. HDC hMainDC=0, hStatusDC=0;
  151. long lSaved = 0;
  152. HRESULT hr = S_OK;
  153. static TCHAR szTitle[NORM_SIZE] = _T("");
  154. TCHAR szFileName[NORM_SIZE] = _T("");
  155. static TCHAR szSaveFileName[NORM_SIZE] = _T("");
  156. HMENU hMenu=0;
  157. static int iNumUndos=0;
  158. long lStart, lEnd;
  159. CCompiler* pThis = (CCompiler *)GetWindowLong(hWnd, GWL_USERDATA);
  160. // get the handle to the menu
  161. hMenu = GetMenu( hWnd );
  162. switch (message)
  163. {
  164. case WM_SETFOCUS:
  165. SetFocus (pThis->m_hWndEdit);
  166. break;
  167. case WM_CREATE:
  168. pThis = (CCompiler *)(((CREATESTRUCT *) lParam)->lpCreateParams);
  169. SetWindowLong(hWnd, GWL_USERDATA, (LPARAM)pThis);
  170. pThis->m_hWnd = hWnd;
  171. // Create the compile status window
  172. pThis->m_hWndStatus = CreateWindowEx (
  173. WS_EX_CLIENTEDGE,
  174. _T("LISTBOX"),
  175. NULL,
  176. WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL |
  177. WS_HSCROLL,
  178. 1, 1, 1, 1,
  179. hWnd,
  180. NULL,
  181. pThis->m_hInstance,
  182. NULL);
  183. // Create the actual rich edit window
  184. pThis->m_hWndEdit = CreateWindowEx(
  185. WS_EX_CLIENTEDGE,
  186. RICHEDIT_CLASS,
  187. NULL,
  188. WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE |
  189. WS_VSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN,
  190. 1, 1, 1, 1,
  191. hWnd,
  192. (HMENU)IDC_RICHEDITWND,
  193. pThis->m_hInstance,
  194. NULL );
  195. break;
  196. case WM_ERASEBKGND:
  197. return TRUE;
  198. case WM_SIZE:
  199. {
  200. // move the editor and compiler window
  201. LONG lListBoxHeight = (HIWORD(lParam) / 4);
  202. LONG lCodeHeight = HIWORD(lParam) - lListBoxHeight;
  203. MoveWindow (pThis->m_hWndEdit, 0, 0,
  204. LOWORD(lParam), lCodeHeight , FALSE);
  205. MoveWindow (pThis->m_hWndStatus, 0, lCodeHeight,
  206. LOWORD(lParam), lListBoxHeight, FALSE);
  207. // repaint
  208. InvalidateRect( hWnd, NULL, FALSE );
  209. }
  210. break;
  211. case WM_COMMAND:
  212. wmId = LOWORD(wParam);
  213. wmEvent = HIWORD(wParam);
  214. // Update available menu items
  215. pThis->m_cpTextSel->GetStart( &lStart );
  216. pThis->m_cpTextSel->GetStoryLength( &lEnd );
  217. if( lEnd-lStart > 1 )
  218. {
  219. EnableMenuItem( hMenu, IDM_EDIT_CUT, MF_ENABLED );
  220. EnableMenuItem( hMenu, IDM_EDIT_COPY, MF_ENABLED );
  221. }
  222. else
  223. {
  224. EnableMenuItem( hMenu, IDM_EDIT_CUT, MF_GRAYED );
  225. EnableMenuItem( hMenu, IDM_EDIT_COPY, MF_GRAYED );
  226. }
  227. // Parse the menu selections:
  228. switch( wmId )
  229. {
  230. case IDM_FILE_NEW:
  231. // Check if the file has been changed and save if necessary
  232. hr = pThis->m_cpTextDoc->GetSaved( &lSaved );
  233. if( lSaved == tomFalse && SUCCEEDED( hr ) )
  234. {
  235. int iRetVal = MessageBox( pThis->m_hWndEdit, _T("Do you want to save your changes?"),
  236. _T("Grammar Compiler"), MB_YESNO );
  237. if( iRetVal == IDYES )
  238. {
  239. BOOL bRetVal = TRUE;
  240. // No need to call save file dialog if there's already a file name
  241. if( !_tcscmp( szSaveFileName, "" ) )
  242. {
  243. bRetVal = pThis->CallSaveFileDialog( hWnd, szSaveFileName );
  244. }
  245. // TOM save file
  246. if( bRetVal )
  247. {
  248. // TOM save file
  249. pThis->FileSave( hWnd, pThis, szSaveFileName );
  250. }
  251. }
  252. else
  253. {
  254. pThis->m_cpTextDoc->SetSaved( tomTrue );
  255. }
  256. }
  257. // call TOM new
  258. pThis->m_cpTextDoc->New();
  259. pThis->m_cpTextDoc->SetSaved( tomTrue );
  260. // Add the file name to the title bar
  261. LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
  262. _tcscat( szTitle, _T(" - []") );
  263. SetWindowText( hWnd, szTitle );
  264. // reset defaults
  265. ::SendMessage( pThis->m_hWndStatus, LB_RESETCONTENT, 0, 0 );
  266. ::SendMessage( pThis->m_hWndStatus, LB_SETHORIZONTALEXTENT, 0, 0 );
  267. pThis->m_szCFGDestFile[0] = 0;
  268. pThis->m_szHeaderDestFile[0] = 0;
  269. pThis->m_szXMLSrcFile[0] = 0;
  270. pThis->m_fNeedStartCompile = TRUE;
  271. pThis->m_hrWorstError = 0;
  272. _tcscpy( szSaveFileName, _T("") );
  273. InvalidateRect( hWnd, NULL, FALSE );
  274. break;
  275. case IDM_FILE_OPEN:
  276. // Save old file first if one exists and it has not been saved
  277. hr = pThis->m_cpTextDoc->GetSaved( &lSaved );
  278. if( lSaved == tomFalse && SUCCEEDED( hr ) )
  279. {
  280. int iRetVal = MessageBox( pThis->m_hWndEdit, _T("Do you want to save your changes?"),
  281. _T("Grammar Compiler"), MB_YESNO );
  282. if( iRetVal == IDYES )
  283. {
  284. // reset errors
  285. pThis->m_hrWorstError = 0;
  286. // TOM save file
  287. hr = pThis->FileSave( hWnd, pThis, szSaveFileName );
  288. if( hr == STG_E_ACCESSDENIED ) // Handle read only files
  289. {
  290. MessageBox( pThis->m_hWndEdit, _T("This file exists with Read Only attributes.\n Please use a different file name."),
  291. _T("File Save"), MB_OK );
  292. // Call FileSave again but this time pop the save file dialog box
  293. pThis->FileSave( hWnd, pThis, szSaveFileName );
  294. }
  295. }
  296. else
  297. {
  298. pThis->m_cpTextDoc->SetSaved( tomTrue );
  299. }
  300. }
  301. bFileOpened = pThis->CallOpenFileDialog( hWnd, szFileName,
  302. _T("XML (*.xml)\0*.xml\0TXT (*.txt)\0*.txt\0All Files (*.*)\0*.*\0") );
  303. // Copy the open file name to the Save file name for use later
  304. _tcscpy( szSaveFileName, szFileName );
  305. if( bFileOpened )
  306. {
  307. HRESULT hr = S_OK;
  308. VARIANT Var;
  309. USES_CONVERSION;
  310. // reset text in windows
  311. _tcscpy(pThis->m_szXMLSrcFile, szFileName);
  312. ::SendMessage( pThis->m_hWndStatus, LB_RESETCONTENT, 0, 0 );
  313. ::SendMessage( pThis->m_hWndStatus, LB_SETHORIZONTALEXTENT, 0, 0 );
  314. InvalidateRect( hWnd, NULL, FALSE );
  315. // Open the file in the rich edit control
  316. VariantInit( &Var );
  317. Var.vt = VT_BSTR;
  318. Var.bstrVal = SysAllocString( T2W(szFileName) ); // Will use Win32 file command
  319. hr = pThis->m_cpTextDoc->Open( &Var, tomOpenExisting, 0 );
  320. hr &= ~0x40000; // Mask off bit 18
  321. if( hr == STG_E_ACCESSDENIED ) // Handle read only files
  322. {
  323. pThis->m_cpTextDoc->Open( &Var, tomReadOnly | tomOpenExisting, 0 );
  324. }
  325. SysFreeString( Var.bstrVal );
  326. // reset defaults
  327. pThis->m_szCFGDestFile[0] = 0;
  328. pThis->m_szHeaderDestFile[0] = 0;
  329. pThis->m_fNeedStartCompile = TRUE;
  330. pThis->m_hrWorstError = 0;
  331. // no changes to the file yet so set SetSaved to true
  332. pThis->m_cpTextDoc->SetSaved( tomTrue );
  333. // Add the file name to the title bar
  334. LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
  335. _tcscat( szTitle, _T(" - [") );
  336. _tcscat( szTitle, szFileName );
  337. _tcscat( szTitle, _T("]") );
  338. SetWindowText( hWnd, szTitle );
  339. }
  340. break;
  341. case IDM_FILE_SAVEAS:
  342. // Remove old save file name if one exists
  343. _tcscpy( szSaveFileName, _T("") );
  344. // no break here
  345. case IDM_FILE_SAVE:
  346. // TOM save file
  347. hr = pThis->FileSave( hWnd, pThis, szSaveFileName );
  348. if( hr == STG_E_ACCESSDENIED ) // Handle read only files
  349. {
  350. MessageBox( pThis->m_hWndEdit, _T("This file exists with Read Only attributes.\n Please use a different file name."),
  351. _T("File Save"), MB_OK );
  352. // Call FileSave again but this time pop the save file dialog box
  353. hr = pThis->FileSave( hWnd, pThis, szSaveFileName );
  354. }
  355. // Add the file name to the title bar
  356. if( SUCCEEDED( hr ) )
  357. {
  358. LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
  359. _tcscat( szTitle, _T(" - [") );
  360. _tcscat( szTitle, szSaveFileName );
  361. _tcscat( szTitle, _T("]") );
  362. SetWindowText( hWnd, szTitle );
  363. }
  364. break;
  365. case IDM_BUILD_COMPILE:
  366. if( pThis->m_fNeedStartCompile )
  367. {
  368. pThis->Compile( hWnd, szSaveFileName, szTitle, pThis );
  369. }
  370. break;
  371. case IDC_RICHEDITWND:
  372. // When user changes contents of edit control update status bar on top
  373. if( wmEvent == EN_CHANGE )
  374. {
  375. TCHAR szTitleNotSaved[NORM_SIZE] = _T("");
  376. if( !_tcscmp( szTitle, _T("") ) )
  377. {
  378. LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
  379. _tcscat( szTitle, _T(" - []") );
  380. }
  381. _tcscpy( szTitleNotSaved, szTitle );
  382. _tcscat( szTitleNotSaved, _T("*") );
  383. SetWindowText( hWnd, szTitleNotSaved );
  384. pThis->m_fNeedStartCompile = TRUE;
  385. //Update edit menu items
  386. EnableMenuItem( hMenu, IDM_EDIT_UNDO, MF_ENABLED );
  387. }
  388. break;
  389. case IDM_EDIT_UNDO:
  390. // Undo
  391. pThis->m_cpTextDoc->Undo( 1, NULL );
  392. EnableMenuItem( hMenu, IDM_EDIT_REDO, MF_ENABLED );
  393. iNumUndos++;
  394. break;
  395. case IDM_EDIT_REDO:
  396. // Redo
  397. pThis->m_cpTextDoc->Redo( 1, NULL );
  398. if( --iNumUndos < 1 )
  399. {
  400. EnableMenuItem( hMenu, IDM_EDIT_REDO, MF_GRAYED );
  401. iNumUndos = 0;
  402. }
  403. break;
  404. case IDM_EDIT_COPY:
  405. // Copy
  406. pThis->m_cpTextSel->Copy( NULL );
  407. EnableMenuItem( hMenu, IDM_EDIT_PASTE, MF_ENABLED );
  408. break;
  409. case IDM_EDIT_CUT:
  410. // Cut
  411. pThis->m_cpTextSel->Cut( NULL );
  412. EnableMenuItem( hMenu, IDM_EDIT_PASTE, MF_ENABLED );
  413. break;
  414. case IDM_EDIT_PASTE:
  415. // Paste
  416. pThis->m_cpTextSel->Paste( NULL, 0 );
  417. break;
  418. case IDM_EDIT_DELETE:
  419. // Delete
  420. pThis->m_cpTextSel->Delete( tomCharacter, 1, NULL );
  421. break;
  422. case IDM_EDIT_SELECTALL:
  423. // Select all
  424. {
  425. pThis->m_cpTextSel->GetStart( &lStart );
  426. pThis->m_cpTextSel->GetStoryLength( &lEnd );
  427. pThis->m_cpTextSel->MoveStart( tomCharacter, -lStart, NULL );
  428. pThis->m_cpTextSel->MoveEnd( tomCharacter, lEnd-lStart, NULL );
  429. }
  430. break;
  431. case IDM_EDIT_FIND:
  432. // Find
  433. DialogBoxParam( pThis->m_hInstance, (LPCTSTR)IDD_FIND, hWnd, Find, (LPARAM)pThis);
  434. break;
  435. case IDM_EDIT_GOTO:
  436. // Find
  437. DialogBoxParam( pThis->m_hInstance, (LPCTSTR)IDD_GOTO, hWnd, Goto, (LPARAM)pThis);
  438. break;
  439. case IDM_TESTGRAMMAR:
  440. // Only compile if necessary
  441. if( pThis->m_fNeedStartCompile )
  442. {
  443. hr = pThis->Compile( hWnd, szSaveFileName, szTitle, pThis );
  444. }
  445. // Create new dialog box
  446. if( SUCCEEDED( hr ) )
  447. {
  448. DialogBoxParam( pThis->m_hInstance, (LPCTSTR)IDD_TESTGRAMMAR, hWnd, TestGrammar, (LPARAM)pThis);
  449. }
  450. else if( hr == E_INVALIDARG )
  451. {
  452. MessageBox( pThis->m_hWndEdit, _T("Please enter text or open an xml file first."), _T("Compile Error"), MB_OK );
  453. }
  454. else if( hr == E_FAIL )
  455. {
  456. MessageBox( pThis->m_hWndEdit, _T("Please save file first."), _T("Compile Error"), MB_OK );
  457. }
  458. else
  459. {
  460. MessageBox( pThis->m_hWndEdit, _T("Error compiling xml file."),
  461. _T("Compile Error"), MB_OK );
  462. }
  463. break;
  464. case IDM_ABOUT:
  465. // About box
  466. DialogBox( pThis->m_hInstance, (LPCTSTR)IDD_ABOUTBOX, hWnd, About );
  467. break;
  468. case IDM_EXIT:
  469. SendMessage( hWnd, WM_CLOSE, 0, 0 );
  470. break;
  471. default:
  472. return DefWindowProc(hWnd, message, wParam, lParam);
  473. }
  474. break;
  475. case WM_CLOSE:
  476. {
  477. int iRetVal = 0;
  478. // Check if the file has been changed and save if necessary
  479. hr = pThis->m_cpTextDoc->GetSaved( &lSaved );
  480. if( lSaved == tomFalse && SUCCEEDED( hr ) )
  481. {
  482. iRetVal = MessageBox( pThis->m_hWndEdit, _T("Do you want to save your changes?"),
  483. _T("Grammar Compiler"), MB_YESNOCANCEL );
  484. if( iRetVal == IDYES )
  485. {
  486. // No need to call save file dialog if there's already a file name
  487. if( !_tcscmp( szSaveFileName, "" ) )
  488. {
  489. pThis->CallSaveFileDialog( hWnd, szSaveFileName );
  490. }
  491. // TOM save file
  492. pThis->FileSave( hWnd, pThis, szSaveFileName );
  493. }
  494. else
  495. {
  496. pThis->m_cpTextDoc->SetSaved( tomTrue );
  497. }
  498. }
  499. if( iRetVal != IDCANCEL )
  500. {
  501. DestroyWindow( hWnd );
  502. }
  503. }
  504. break;
  505. case WM_DESTROY:
  506. PostQuitMessage(0);
  507. break;
  508. default:
  509. return DefWindowProc( hWnd, message, wParam, lParam );
  510. }
  511. return 0;
  512. }
  513. /****************************************************************************
  514. * CCompiler::About *
  515. *---------------------------*
  516. * Description:
  517. * Message handler for About box.
  518. ***************************************************************** Leonro ****/
  519. INT_PTR CALLBACK CCompiler::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  520. {
  521. switch (message)
  522. {
  523. case WM_INITDIALOG:
  524. return TRUE;
  525. case WM_COMMAND:
  526. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
  527. {
  528. EndDialog(hDlg, LOWORD(wParam));
  529. return TRUE;
  530. }
  531. break;
  532. }
  533. return FALSE;
  534. }
  535. /****************************************************************************
  536. * CCompiler::Find *
  537. *---------------------------*
  538. * Description:
  539. * Message handler for Find box.
  540. ***************************************************************** Leonro ****/
  541. INT_PTR CALLBACK CCompiler::Find(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  542. {
  543. TCHAR szFindText[NORM_SIZE]=_T("");
  544. CComBSTR bStr( _T("Grammar") );
  545. long lUpDown = tomForward;
  546. long lFlags=0;
  547. CCompiler* pThis = (CCompiler *)GetWindowLong( hDlg, GWL_USERDATA );
  548. switch (message)
  549. {
  550. case WM_INITDIALOG:
  551. SetWindowLong( hDlg, GWL_USERDATA, lParam );
  552. SendDlgItemMessage( hDlg, IDB_DOWN, BM_SETCHECK, BST_CHECKED, 0 );
  553. return TRUE;
  554. case WM_COMMAND:
  555. {
  556. switch( LOWORD( wParam ) )
  557. {
  558. case IDB_FINDNEXT:
  559. // Get text string
  560. GetDlgItemText( hDlg, IDE_FINDTEXT, szFindText, NORM_SIZE );
  561. bStr = szFindText;
  562. // Search up or down?
  563. SendDlgItemMessage( hDlg, IDB_DOWN, BM_GETCHECK, 0, 0 )?
  564. lUpDown = tomForward : lUpDown = tomBackward;
  565. // Match case?
  566. SendDlgItemMessage( hDlg, IDB_MATCHCASE, BM_GETCHECK, 0, 0 )?
  567. lFlags=tomMatchCase : lFlags=0;
  568. pThis->m_cpTextSel->FindText( bStr, lUpDown, lFlags, NULL );
  569. return TRUE;
  570. case IDB_CANCEL:
  571. case IDCANCEL:
  572. EndDialog( hDlg, LOWORD(wParam) );
  573. return TRUE;
  574. }
  575. }
  576. break;
  577. case WM_CLOSE:
  578. EndDialog( hDlg, LOWORD(wParam) );
  579. return TRUE;
  580. }
  581. return FALSE;
  582. }
  583. /****************************************************************************
  584. * CCompiler::Goto *
  585. *---------------------------*
  586. * Description:
  587. * Message handler for Goto box.
  588. **************************************************************** Leonro *****/
  589. INT_PTR CALLBACK CCompiler::Goto( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
  590. {
  591. TCHAR szGotoLine[NORM_SIZE]=_T("");
  592. TCHAR szCurrLine[NORM_SIZE]=_T("");
  593. long iGotoLine, iCurrLine, iLinesToMove;
  594. CCompiler* pThis = (CCompiler *)GetWindowLong( hDlg, GWL_USERDATA );
  595. switch (message)
  596. {
  597. case WM_INITDIALOG:
  598. SetWindowLong( hDlg, GWL_USERDATA, lParam );
  599. pThis = (CCompiler *)lParam;
  600. pThis->m_cpTextSel->GetIndex( tomLine, &iCurrLine );
  601. _itoa( iCurrLine, szCurrLine, 10 );
  602. SetDlgItemText( hDlg, IDE_LINE, szCurrLine );
  603. return TRUE;
  604. case WM_COMMAND:
  605. {
  606. switch( LOWORD( wParam ) )
  607. {
  608. case IDB_OK:
  609. // Get current line
  610. pThis->m_cpTextSel->GetIndex( tomLine, &iCurrLine );
  611. // Get goto line
  612. GetDlgItemText( hDlg, IDE_LINE, szGotoLine, NORM_SIZE );
  613. iGotoLine = atoi( szGotoLine );
  614. EndDialog( hDlg, LOWORD(wParam) );
  615. // Calculate number of lines to move
  616. iLinesToMove = iGotoLine - iCurrLine;
  617. // Move
  618. pThis->m_cpTextSel->MoveDown( tomLine, iLinesToMove, tomMove, NULL );
  619. return TRUE;
  620. case IDB_CANCEL:
  621. case IDCANCEL:
  622. EndDialog( hDlg, LOWORD(wParam) );
  623. return TRUE;
  624. }
  625. }
  626. break;
  627. case WM_CLOSE:
  628. EndDialog( hDlg, LOWORD(wParam) );
  629. return TRUE;
  630. }
  631. return FALSE;
  632. }
  633. /****************************************************************************
  634. * CCompiler::TestGrammar *
  635. *---------------------------*
  636. * Description:
  637. * Message handler for TestGrammar box.
  638. **************************************************************** Leonro *****/
  639. LRESULT CALLBACK CCompiler::TestGrammar(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  640. {
  641. HRESULT hr = S_OK;
  642. CCompiler* pThis = (CCompiler *)GetWindowLong( hDlg, GWL_USERDATA );
  643. switch (message)
  644. {
  645. case WM_RECOEVENT:
  646. {
  647. pThis->RecoEvent( hDlg, pThis );
  648. }
  649. return TRUE;
  650. case WM_INITDIALOG:
  651. {
  652. SetWindowLong( hDlg, GWL_USERDATA, lParam );
  653. pThis = (CCompiler *)lParam;
  654. // Create the shared sapi reco instance if the app hasn't already done so
  655. if( !pThis->m_cpRecognizer )
  656. {
  657. #ifdef INPROC
  658. // Create the inproc engine
  659. hr = pThis->m_cpRecognizer.CoCreateInstance( CLSID_SpInprocRecognizer );
  660. // Create default audio input
  661. CComPtr<ISpObjectToken> cpAudioToken;
  662. if (SUCCEEDED(hr))
  663. {
  664. hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &cpAudioToken);
  665. }
  666. if (SUCCEEDED(hr))
  667. {
  668. pThis->m_cpRecognizer->SetInput(cpAudioToken, TRUE);
  669. }
  670. #else
  671. // Create the shared engine
  672. hr = pThis->m_cpRecognizer.CoCreateInstance( CLSID_SpSharedRecognizer );
  673. #endif
  674. // Create the Reco context
  675. if( SUCCEEDED( hr ) )
  676. {
  677. hr = pThis->m_cpRecognizer->CreateRecoContext( &pThis->m_cpRecoContext );
  678. }
  679. }
  680. // Set up windows messageing for recognition events
  681. if( SUCCEEDED( hr ) )
  682. {
  683. hr = pThis->m_cpRecoContext->SetNotifyWindowMessage( hDlg, WM_RECOEVENT, 0, 0);
  684. }
  685. if( SUCCEEDED( hr ) )
  686. {
  687. const ULONGLONG ullInterest = SPFEI(SPEI_SOUND_END) | SPFEI(SPEI_SOUND_START) | SPFEI(SPEI_HYPOTHESIS) |
  688. SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_FALSE_RECOGNITION);
  689. hr = pThis->m_cpRecoContext->SetInterest( ullInterest, ullInterest );
  690. }
  691. // Get locale/font settings
  692. if( SUCCEEDED( hr ) )
  693. {
  694. LCID lcid = GetUserDefaultLCID();
  695. // Pick an appropriate font. On Windows 2000, let the system fontlink.
  696. DWORD dwVersion = GetVersion();
  697. if ( dwVersion >= 0x80000000
  698. || LOBYTE(LOWORD(dwVersion)) < 5
  699. || LANGIDFROMLCID(lcid) != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US))
  700. {
  701. TCHAR achCodePage[6];
  702. UINT uiCodePage;
  703. if( 0 != GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, achCodePage, 6) )
  704. {
  705. uiCodePage = atoi(achCodePage);
  706. }
  707. else
  708. {
  709. uiCodePage = GetACP();
  710. }
  711. CComPtr<IMultiLanguage> cpMultiLanguage;
  712. MIMECPINFO MimeCpInfo;
  713. if ( SUCCEEDED(cpMultiLanguage.CoCreateInstance(CLSID_CMultiLanguage))
  714. && SUCCEEDED(cpMultiLanguage->GetCodePageInfo(uiCodePage, &MimeCpInfo)))
  715. {
  716. USES_CONVERSION;
  717. HFONT hfont = CreateFont( 0, 0, 0, 0, FW_NORMAL, 0, 0, 0,
  718. MimeCpInfo.bGDICharset,
  719. OUT_DEFAULT_PRECIS,
  720. CLIP_DEFAULT_PRECIS,
  721. DEFAULT_QUALITY,
  722. DEFAULT_PITCH,
  723. W2T(MimeCpInfo.wszProportionalFont ));
  724. }
  725. }
  726. }
  727. // Update status edit box
  728. if( SUCCEEDED( hr ) )
  729. {
  730. const static TCHAR szPrefixText[] = _T("Current C&&C Grammar: ");
  731. TCHAR szDesc[sp_countof(pThis->m_szCFGDestFile) + sp_countof(szPrefixText) + 4];
  732. _tcscpy( szDesc, szPrefixText );
  733. if( *pThis->m_szCFGDestFile )
  734. {
  735. _tcscat( szDesc, pThis->m_szCFGDestFile );
  736. }
  737. else
  738. {
  739. _tcscat( szDesc, _T("none") );
  740. }
  741. SendDlgItemMessage( hDlg, IDC_GRAMMAR_STATUS, WM_SETTEXT, 0, (LPARAM)szDesc );
  742. }
  743. if( FAILED( hr ) )
  744. {
  745. MessageBox( hDlg, _T("Error initializing Speech Recognizer."),
  746. _T("Error"), MB_OK );
  747. EndDialog( hDlg, LOWORD(wParam) );
  748. }
  749. }
  750. return TRUE;
  751. case WM_COMMAND:
  752. {
  753. switch( LOWORD( wParam ) )
  754. {
  755. case IDC_BEGINRECO:
  756. // Load the grammar
  757. if( SendDlgItemMessage( hDlg, IDC_BEGINRECO, BM_GETCHECK, 0, 0 ) )
  758. {
  759. // Enable Emulate Recognition feature
  760. EnableWindow( GetDlgItem(hDlg, IDC_EDIT_PARSETEXT), TRUE );
  761. TCHAR* szPath = pThis->m_szCFGDestFile;
  762. hr = pThis->LoadGrammar( szPath );
  763. if( FAILED( hr ) )
  764. {
  765. MessageBox( hDlg, _T("Error loading grammar. Make sure")
  766. _T(" a file is loaded, saved, and compiled."),
  767. _T("Error"), MB_OK );
  768. }
  769. // Activate the grammar
  770. if( SUCCEEDED( hr ) )
  771. {
  772. hr = pThis->m_cpRecoGrammar->SetRuleState(NULL, NULL, SPRS_ACTIVE);
  773. }
  774. if( FAILED( hr ) )
  775. {
  776. // Release grammar
  777. pThis->m_cpRecoGrammar.Release();
  778. MessageBox( NULL, _T("Error loading grammar."),
  779. _T("Error"), MB_OK );
  780. EndDialog( hDlg, LOWORD(wParam) );
  781. return FALSE;
  782. }
  783. }
  784. else
  785. {
  786. // Disable Emulate Recognition
  787. EnableWindow( GetDlgItem(hDlg, IDC_EDIT_PARSETEXT), FALSE );
  788. // Release grammar
  789. pThis->m_cpRecoGrammar.Release();
  790. }
  791. return TRUE;
  792. case IDB_MUTE:
  793. {
  794. // Check if the user has selected mute
  795. if( SendDlgItemMessage( hDlg, IDB_MUTE, BM_GETCHECK, 0, 0 ) )
  796. {
  797. pThis->m_cpRecognizer->SetRecoState( SPRST_INACTIVE );
  798. }
  799. else
  800. {
  801. pThis->m_cpRecognizer->SetRecoState( SPRST_ACTIVE );
  802. }
  803. }
  804. return TRUE;
  805. case IDC_BUTTON_SUBMIT:
  806. {
  807. CSpDynamicString dstrText;
  808. int iStrLen = 0;
  809. TCHAR szEmulateRecoText[NORM_SIZE];
  810. USES_CONVERSION;
  811. UINT numChar = GetDlgItemText( hDlg, IDC_EDIT_PARSETEXT,
  812. szEmulateRecoText, NORM_SIZE );
  813. if( pThis->m_cpRecoGrammar )
  814. {
  815. pThis->m_dstr = L"";
  816. HRESULT hr = pThis->EmulateRecognition(T2W(szEmulateRecoText));
  817. if( SP_NO_PARSE_FOUND == hr )
  818. {
  819. ::SendMessage( GetDlgItem(hDlg, IDC_LIST_PHRASES), WM_SETTEXT,
  820. 0, (LPARAM)"<Unrecognized phrase>");
  821. }
  822. }
  823. }
  824. return TRUE;
  825. }
  826. }
  827. return TRUE;
  828. case WM_CLOSE:
  829. {
  830. // Release grammar
  831. pThis->m_cpRecoGrammar.Release();
  832. EndDialog( hDlg, LOWORD(wParam) );
  833. }
  834. return TRUE;
  835. }
  836. return FALSE;
  837. }
  838. /****************************************************************************
  839. * CCompiler::AddStatus *
  840. *---------------------------*
  841. * Description:
  842. * Writes compile output to the status window.
  843. *****************************************************************************/
  844. void CCompiler::AddStatus(HRESULT hr, UINT uID, const TCHAR * pFmtString)
  845. {
  846. USES_CONVERSION;
  847. TCHAR sz[MAX_PATH];
  848. ::LoadString(m_hInstance, uID, sz, sp_countof(sz));
  849. if (pFmtString)
  850. {
  851. TCHAR szFormatted[MAX_PATH];
  852. ::wsprintf(szFormatted, sz, pFmtString);
  853. AddError(-1, hr, T2W(szFormatted), NULL, 0);
  854. }
  855. else
  856. {
  857. AddError(-1, hr, T2W(sz), NULL, 0);
  858. }
  859. }
  860. /****************************************************************************
  861. * CCompiler::AddError *
  862. *---------------------------*
  863. * Description:
  864. * Writes compile error messages to the status window.
  865. *****************************************************************************/
  866. STDMETHODIMP CCompiler::AddError(const long lLine, HRESULT hr, const WCHAR * pszDescription, const WCHAR * pszHelpFile, DWORD dwHelpContext)
  867. {
  868. if (FAILED(hr) && SUCCEEDED(m_hrWorstError))
  869. {
  870. m_hrWorstError = hr;
  871. }
  872. USES_CONVERSION;
  873. TCHAR *pszText = NULL;
  874. TCHAR *pszFinalOutput = NULL;
  875. if (hr == S_OK)
  876. {
  877. pszFinalOutput = W2T(pszDescription);
  878. }
  879. else
  880. {
  881. pszText = new TCHAR[ MAX_PATH + _tcslen( m_szXMLSrcFile ) + _tcslen( W2T(pszDescription) ) ];
  882. if ( pszText )
  883. {
  884. if (lLine >= 0)
  885. {
  886. wsprintf(pszText, SUCCEEDED(hr) ? _T("%s(%d) Warning: %s\n") : _T("%s(%d) Error: %s\n"),
  887. m_szXMLSrcFile, lLine, W2T(pszDescription));
  888. }
  889. else
  890. {
  891. wsprintf(pszText, SUCCEEDED(hr) ? _T("%s Warning: %s\n") : _T("%s Error: %s\n"),
  892. m_szXMLSrcFile, W2T(pszDescription));
  893. }
  894. pszFinalOutput = pszText;
  895. }
  896. else
  897. {
  898. // out of memory: just give the description
  899. pszFinalOutput = W2T(pszDescription);
  900. }
  901. }
  902. bool fNeedToUpdateWidth = false; // Might need to tell the listbox to show the hscroll
  903. HWND hwndList = NULL;
  904. if( m_hDlg ) // dialog
  905. {
  906. if( m_fCommandLine )
  907. {
  908. int iRet = ::SendDlgItemMessage(m_hDlg, IDC_LIST_STATUS, LB_ADDSTRING, 0, (LPARAM)pszFinalOutput);
  909. hwndList = ::GetDlgItem( m_hDlg, IDC_LIST_STATUS );
  910. fNeedToUpdateWidth = (LB_ERR != iRet);
  911. }
  912. else
  913. {
  914. _tprintf( pszFinalOutput );
  915. }
  916. }
  917. else // window
  918. {
  919. int iRet = ::SendMessage( m_hWndStatus, LB_ADDSTRING, 0, (LPARAM) pszFinalOutput );
  920. hwndList = m_hWndStatus;
  921. fNeedToUpdateWidth = (LB_ERR != iRet);
  922. }
  923. if ( fNeedToUpdateWidth )
  924. {
  925. // Listboxes do not update their horizontal extent dynamically,
  926. // so we need to do so here.
  927. HDC hdc = ::GetDC( hwndList );
  928. SIZE size;
  929. ::GetTextExtentPoint32( hdc, pszFinalOutput, _tcslen( pszFinalOutput ), &size );
  930. ::ReleaseDC( hwndList, hdc );
  931. int iCurrentWidth = (int) ::SendMessage( hwndList, LB_GETHORIZONTALEXTENT, 0, 0 );
  932. if ( size.cx > iCurrentWidth )
  933. {
  934. ::SendMessage( hwndList, LB_SETHORIZONTALEXTENT, size.cx, 0 );
  935. }
  936. }
  937. if ( pszText )
  938. {
  939. delete[] pszText;
  940. }
  941. return S_OK;
  942. }
  943. /****************************************************************************
  944. * CCompiler::EnterIdle *
  945. *---------------------------*
  946. * Description:
  947. * Calls the SAPI grammar compiler to compile the xml file.
  948. *****************************************************************************/
  949. HRESULT CCompiler::EnterIdle()
  950. {
  951. HRESULT hr = S_OK;
  952. if (m_fNeedStartCompile)
  953. {
  954. BOOL bWorked = FALSE;
  955. m_fNeedStartCompile = FALSE;
  956. CSpFileStream Source(&hr, m_szXMLSrcFile);
  957. AddInternalError(hr, IDS_CANTOPENSOURCE, m_szXMLSrcFile);
  958. if (SUCCEEDED(hr))
  959. {
  960. CSpFileStream Dest(&hr, m_szCFGDestFile, GENERIC_WRITE, 0, CREATE_ALWAYS);
  961. AddInternalError(hr, IDS_CANTOPENDEST, m_szCFGDestFile);
  962. if (SUCCEEDED(hr) && strlen(m_szHeaderDestFile))
  963. {
  964. CSpFileStream Header(&hr, m_szHeaderDestFile, GENERIC_WRITE, 0, CREATE_ALWAYS);
  965. AddInternalError(hr, IDS_CANTOPENDEST, m_szHeaderDestFile);
  966. WriteStream(&Header, "#ifndef __");
  967. StripWrite(&Header, m_szHeaderDestFile);
  968. WriteStream(&Header, "_IDs__\n");
  969. WriteStream(&Header, "#define __");
  970. StripWrite(&Header, m_szHeaderDestFile);
  971. WriteStream(&Header, "_IDs__\n\n");
  972. if (SUCCEEDED(hr))
  973. {
  974. if( !m_fSilent )
  975. {
  976. hr = m_cpCompiler->CompileStream(&Source, &Dest, &Header, NULL, this, 0);
  977. }
  978. else
  979. {
  980. hr = m_cpCompiler->CompileStream(&Source, &Dest, &Header, NULL, m_cpError, 0);
  981. }
  982. }
  983. if (SUCCEEDED(hr))
  984. {
  985. WriteStream(&Header, "\n#endif\n");
  986. }
  987. }
  988. else
  989. {
  990. if (SUCCEEDED(hr))
  991. {
  992. if( !m_fSilent )
  993. {
  994. hr = m_cpCompiler->CompileStream(&Source, &Dest, NULL, NULL, this, 0);
  995. }
  996. else
  997. {
  998. hr = m_cpCompiler->CompileStream(&Source, &Dest, NULL, NULL, m_cpError, 0);
  999. }
  1000. }
  1001. }
  1002. if (SUCCEEDED(hr) && SUCCEEDED(m_hrWorstError))
  1003. {
  1004. AddStatus(S_OK, IDS_COMPILESUCCESS);
  1005. bWorked = TRUE;
  1006. if (m_fSilent)
  1007. {
  1008. ::EndDialog(m_hDlg, S_OK);
  1009. }
  1010. }
  1011. else
  1012. {
  1013. AddStatus(hr, IDS_COMPILEFAILURE);
  1014. bWorked = FALSE;
  1015. if (m_fSilent)
  1016. {
  1017. ::EndDialog(m_hDlg, S_OK);
  1018. }
  1019. }
  1020. }
  1021. if (!bWorked)
  1022. {
  1023. ::DeleteFile(m_szCFGDestFile);
  1024. }
  1025. }
  1026. return hr;
  1027. }
  1028. /****************************************************************************
  1029. * CCompiler::LoadGrammar *
  1030. *---------------------------*
  1031. * Description:
  1032. * Loads and activates the Grammar
  1033. ***************************************************************** Leonro ****/
  1034. HRESULT CCompiler::LoadGrammar( TCHAR* szPath )
  1035. {
  1036. HRESULT hr = S_OK;
  1037. // load grammar
  1038. hr = m_cpRecoContext->CreateGrammar(GRAM_ID, &m_cpRecoGrammar);
  1039. if (SUCCEEDED(hr))
  1040. {
  1041. USES_CONVERSION;
  1042. hr = m_cpRecoGrammar->LoadCmdFromFile( T2W(szPath), SPLO_STATIC );
  1043. if (FAILED(hr))
  1044. {
  1045. m_cpRecoGrammar.Release();
  1046. }
  1047. }
  1048. return hr;
  1049. }
  1050. /****************************************************************************
  1051. * CCompiler::WriteStream *
  1052. *---------------------------*
  1053. * Description:
  1054. * Calls write on the output stream
  1055. *****************************************************************************/
  1056. HRESULT CCompiler::WriteStream(IStream * pStream, const char * pszText)
  1057. {
  1058. ULONG cch = strlen(pszText);
  1059. return pStream->Write(pszText, cch, NULL);
  1060. }
  1061. /****************************************************************************
  1062. * CCompiler::StripWrite *
  1063. *---------------------------*
  1064. * Description:
  1065. * Strips characters off strings
  1066. *****************************************************************************/
  1067. HRESULT CCompiler::StripWrite(IStream * pStream, const char * pszText)
  1068. {
  1069. ULONG cch = strlen(pszText);
  1070. char * psz = (char *)_alloca((cch + 1) * sizeof(char));
  1071. char c;
  1072. char * pszWork = psz;
  1073. do
  1074. {
  1075. c = *pszText++;
  1076. *pszWork++ = ((c == 0) || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) ? c : '_';
  1077. } while (c);
  1078. return pStream->Write(psz, cch, NULL);
  1079. }
  1080. /****************************************************************************
  1081. * CCompiler::CallOpenFileDialog *
  1082. *---------------------------*
  1083. * Description:
  1084. * Displays the open dialog box to retrieve the
  1085. * user-selected .txt or .xml file for synthisizing
  1086. *************************************************************** Leonro ******/
  1087. BOOL CCompiler::CallOpenFileDialog( HWND hWnd, LPSTR szFileName, TCHAR* szFilter )
  1088. {
  1089. OPENFILENAME ofn;
  1090. BOOL bRetVal = TRUE;
  1091. LONG lRetVal;
  1092. HKEY hkResult;
  1093. TCHAR szPath[NORM_SIZE] = _T("");
  1094. DWORD size = NORM_SIZE;
  1095. // Open the last directory used by this app (stored in registry)
  1096. lRetVal = RegCreateKeyEx( HKEY_CURRENT_USER,
  1097. _T("SOFTWARE\\Microsoft\\Speech\\AppData\\PathToGrammarFiles"), 0, NULL, 0,
  1098. KEY_ALL_ACCESS, NULL, &hkResult, NULL );
  1099. if( lRetVal == ERROR_SUCCESS )
  1100. {
  1101. RegQueryValueEx( hkResult, _T("GramCompFiles"), NULL, NULL, (PBYTE)szPath, &size );
  1102. }
  1103. ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
  1104. ofn.hwndOwner = hWnd;
  1105. ofn.lpstrFilter = szFilter;
  1106. ofn.lpstrCustomFilter = NULL;
  1107. ofn.nFilterIndex = 1;
  1108. ofn.lpstrInitialDir = szPath;
  1109. ofn.lpstrFile = szFileName;
  1110. ofn.nMaxFile = NORM_SIZE;
  1111. ofn.lpstrTitle = NULL;
  1112. ofn.lpstrFileTitle = NULL;
  1113. ofn.lpstrDefExt = _T("xml");
  1114. ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
  1115. // Pop the dialog
  1116. bRetVal = GetOpenFileName( &ofn );
  1117. // Write the directory path you're in to the registry
  1118. TCHAR pathstr[NORM_SIZE] = _T("");
  1119. strcpy( pathstr, szFileName );
  1120. int i=0;
  1121. while( pathstr[i] != NULL )
  1122. {
  1123. i++;
  1124. }
  1125. while( pathstr[i] != '\\' )
  1126. {
  1127. i --;
  1128. }
  1129. pathstr[i] = NULL;
  1130. RegSetValueEx( hkResult, _T("GramCompFiles"), NULL, REG_EXPAND_SZ, (PBYTE)pathstr, strlen(pathstr)+1 );
  1131. RegCloseKey( hkResult );
  1132. return bRetVal;
  1133. }
  1134. /****************************************************************************
  1135. * CCompiler::CallSaveFileDialog *
  1136. *---------------------------*
  1137. * Description:
  1138. * Displays the save file dialog box and retrieves
  1139. * the user-selected save file name.
  1140. *************************************************************** Leonro ******/
  1141. BOOL CCompiler::CallSaveFileDialog( HWND hWnd, TCHAR* szSaveFile )
  1142. {
  1143. TCHAR pszFileName[MAX_PATH] = _T("");
  1144. BOOL bSuccess = TRUE;
  1145. static TCHAR pszFilter[MAX_PATH] = _T("leon");
  1146. OPENFILENAME ofn;
  1147. ZeroMemory( &ofn, OPENFILENAME_SIZE_VERSION_400 );
  1148. ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
  1149. ofn.hwndOwner = hWnd;
  1150. ofn.hInstance = m_hInstance;
  1151. ofn.lpstrFilter = "XML Files (*.xml)\0*.xml\0Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0";
  1152. ofn.lpstrCustomFilter = NULL;
  1153. ofn.nMaxCustFilter = 0;
  1154. ofn.nFilterIndex = 0;
  1155. ofn.lpstrFile = szSaveFile;
  1156. ofn.nMaxFile = MAX_PATH;
  1157. ofn.nMaxFileTitle = MAX_PATH;
  1158. ofn.lpstrFileTitle = NULL;
  1159. ofn.lpstrInitialDir = NULL;
  1160. ofn.lpstrTitle = NULL;
  1161. ofn.Flags = OFN_CREATEPROMPT;
  1162. ofn.lpstrDefExt = "xml";
  1163. bSuccess = GetSaveFileName( &ofn );
  1164. return bSuccess;
  1165. }
  1166. /****************************************************************************
  1167. * CCompiler::FileSave *
  1168. *---------------------------*
  1169. * Description:
  1170. * Saves the TOM file to disk
  1171. **************************************************************** Leonro *****/
  1172. HRESULT CCompiler::FileSave( HWND hWnd, CCompiler* pComp, TCHAR* szSaveFile )
  1173. //
  1174. {
  1175. VARIANT Var;
  1176. HRESULT hr = S_OK;
  1177. BOOL bRetVal = TRUE;
  1178. USES_CONVERSION;
  1179. // Call save file dialog if there's no file name already
  1180. if( !_tcscmp( szSaveFile, "" ) )
  1181. {
  1182. bRetVal = CallSaveFileDialog( hWnd, szSaveFile );
  1183. }
  1184. // TOM save file
  1185. if( bRetVal )
  1186. {
  1187. // Save it
  1188. VariantInit( &Var );
  1189. Var.vt = VT_BSTR;
  1190. Var.bstrVal = SysAllocString( T2W(szSaveFile) ); // Will use Win32 file command
  1191. hr = pComp->m_cpTextDoc->Save( &Var, tomCreateAlways, 1200 );
  1192. hr &= ~0x40000; // Mask off bit 18
  1193. SysFreeString( Var.bstrVal );
  1194. if( SUCCEEDED( hr ) )
  1195. {
  1196. // Set the compiler source file to the newly saved file
  1197. _tcscpy( pComp->m_szXMLSrcFile, szSaveFile );
  1198. }
  1199. else
  1200. {
  1201. _tcscpy( szSaveFile, _T("") );
  1202. }
  1203. // If the text document has been saved
  1204. if( SUCCEEDED( hr ) )
  1205. {
  1206. pComp->m_cpTextDoc->SetSaved( tomTrue );
  1207. }
  1208. }
  1209. else
  1210. {
  1211. hr = E_FAIL;
  1212. }
  1213. return hr;
  1214. }
  1215. /****************************************************************************
  1216. * CCompiler::Compile *
  1217. *---------------------------*
  1218. * Description:
  1219. * Handles compiling the text in the editor. This function calls CCompiler::EnterIdle
  1220. * to do the actual compiling.
  1221. ***************************************************************** Leonro ****/
  1222. HRESULT CCompiler::Compile( HWND hWnd, TCHAR* szSaveFileName, TCHAR* szTitle, CCompiler* pComp )
  1223. {
  1224. HRESULT hr = S_OK;
  1225. long lSaved = 0;
  1226. // reset errors
  1227. pComp->m_hrWorstError = 0;
  1228. // Save file first if it has not been saved
  1229. hr = pComp->m_cpTextDoc->GetSaved( &lSaved );
  1230. if( lSaved == tomFalse && SUCCEEDED( hr ) )
  1231. {
  1232. // TOM save file
  1233. hr = FileSave( hWnd, pComp, szSaveFileName );
  1234. if( hr == STG_E_ACCESSDENIED ) // Handle read only files
  1235. {
  1236. MessageBox( pComp->m_hWndEdit, _T("This file exists with Read Only attributes.\n Please use a different file name."),
  1237. _T("File Save"), MB_OK );
  1238. // Call FileSave again but this time pop the save file dialog box
  1239. hr = FileSave( hWnd, pComp, szSaveFileName );
  1240. }
  1241. // Add the file name to the title bar
  1242. if( SUCCEEDED( hr ) )
  1243. {
  1244. LoadString( pComp->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
  1245. _tcscat( szTitle, _T(" - [") );
  1246. _tcscat( szTitle, szSaveFileName );
  1247. _tcscat( szTitle, _T("]") );
  1248. SetWindowText( hWnd, szTitle );
  1249. }
  1250. }
  1251. // If everything has succeeded but there is no source text in the editor
  1252. // set hr to InvalidArg
  1253. if( SUCCEEDED( hr ) && !*pComp->m_szXMLSrcFile )
  1254. {
  1255. hr = E_INVALIDARG;
  1256. }
  1257. // Clear out the listbox of any previous errors
  1258. ::SendMessage( m_hWndStatus, LB_RESETCONTENT, 0, 0 );
  1259. // Set up the compiler and do it
  1260. if( SUCCEEDED( hr ) )
  1261. {
  1262. // construct name from m_szXMLSrcFile
  1263. _tcscpy(pComp->m_szCFGDestFile, pComp->m_szXMLSrcFile);
  1264. _tcscpy(&pComp->m_szCFGDestFile[strlen(pComp->m_szCFGDestFile) -3], _T("cfg"));
  1265. // update text in Status Window
  1266. TCHAR sz[MAX_PATH];
  1267. TCHAR *pszOutput = new TCHAR[ sp_countof(sz) + _tcslen( pComp->m_szXMLSrcFile ) ];
  1268. if ( pszOutput )
  1269. {
  1270. LoadString( m_hInstance, IDS_COMPFILE, sz, sp_countof(sz) );
  1271. wsprintf( pszOutput, sz, pComp->m_szXMLSrcFile );
  1272. ::SendMessage( m_hWndStatus, LB_INSERTSTRING, 0, (LPARAM) pszOutput );
  1273. // Size the listbox
  1274. HDC hdc = ::GetDC( m_hWndStatus );
  1275. SIZE size;
  1276. ::GetTextExtentPoint32( hdc, pszOutput, _tcslen( pszOutput ), &size );
  1277. ::ReleaseDC( m_hWndStatus, hdc );
  1278. ::SendMessage( m_hWndStatus, LB_SETHORIZONTALEXTENT, size.cx, 0 );
  1279. delete[] pszOutput;
  1280. }
  1281. // call the actual compile step
  1282. pComp->EnterIdle();
  1283. // repaint
  1284. InvalidateRect( hWnd, NULL, FALSE );
  1285. // Check for compile errors
  1286. hr = pComp->m_hrWorstError;
  1287. if( FAILED( hr ) )
  1288. {
  1289. pComp->m_fNeedStartCompile = TRUE;
  1290. }
  1291. else
  1292. {
  1293. pComp->m_fNeedStartCompile = FALSE;
  1294. }
  1295. }
  1296. return hr;
  1297. }
  1298. /****************************************************************************
  1299. * CCompiler::RecoEvent *
  1300. *---------------------------*
  1301. * Description:
  1302. * Helper function that handles speech events
  1303. **************************************************************** Leonro *****/
  1304. void CCompiler::RecoEvent( HWND hDlg, CCompiler* pComp )
  1305. {
  1306. USES_CONVERSION;
  1307. HRESULT hr=S_OK;
  1308. CSpEvent event;
  1309. long iNewPhrase=0;
  1310. static BOOL fStartSound = FALSE;
  1311. if( pComp->m_cpRecoContext )
  1312. {
  1313. while( event.GetFrom(pComp->m_cpRecoContext) == S_OK )
  1314. {
  1315. // Switch on recognition event
  1316. switch( event.eEventId )
  1317. {
  1318. case SPEI_SOUND_START:
  1319. fStartSound = TRUE;
  1320. m_dstr = L"";
  1321. break;
  1322. case SPEI_SOUND_END:
  1323. if( fStartSound )
  1324. {
  1325. fStartSound = FALSE;
  1326. if( !pComp->m_fGotReco )
  1327. {
  1328. CSpDynamicString dstrText = L"<noise>";
  1329. TCHAR* szUnRecoString = W2T( dstrText.m_psz );
  1330. iNewPhrase = SendDlgItemMessage( hDlg, IDC_LIST_PHRASES, LB_ADDSTRING,
  1331. 0, (LPARAM)szUnRecoString );
  1332. SendDlgItemMessage( hDlg, IDC_LIST_PHRASES, LB_SETCURSEL, iNewPhrase, 0);
  1333. }
  1334. pComp->m_fGotReco = FALSE;
  1335. }
  1336. break;
  1337. case SPEI_FALSE_RECOGNITION:
  1338. ::SendMessage( GetDlgItem(hDlg, IDC_LIST_PHRASES), WM_SETTEXT, 0, (LPARAM)"<Unrecognized>");
  1339. break;
  1340. case SPEI_RECOGNITION:
  1341. case SPEI_HYPOTHESIS:
  1342. Recognize( hDlg, *pComp, event );
  1343. break;
  1344. }
  1345. }
  1346. }
  1347. }
  1348. /****************************************************************************
  1349. * CCompiler::Recognize *
  1350. *----------------------*
  1351. * Description:
  1352. * Helper function that handles recognition events
  1353. *************************************************************** MarkNik *****/
  1354. void CCompiler::Recognize( HWND hDlg, CCompiler &rComp, CSpEvent &rEvent )
  1355. {
  1356. USES_CONVERSION;
  1357. CComPtr<ISpRecoResult> cpResult;
  1358. cpResult = rEvent.RecoResult();
  1359. HRESULT hr = S_OK;
  1360. long iNewPhrase=0;
  1361. rComp.m_fGotReco = TRUE;
  1362. CSpDynamicString dstrText;
  1363. SPPHRASE *pElements;
  1364. if( SUCCEEDED( cpResult->GetPhrase( &pElements ) ) )
  1365. {
  1366. _ASSERT(pElements->ullGrammarID == GRAM_ID);
  1367. TCHAR szText[256];
  1368. HWND hwndEdit = GetDlgItem(hDlg, IDC_LIST_PHRASES);
  1369. ULONG CurrentLen = ::SendMessage( hwndEdit, WM_GETTEXTLENGTH, 0, 0 );
  1370. if( SPEI_RECOGNITION == rEvent.eEventId )
  1371. {
  1372. m_dstr.Append( L"------------- Recognition Event: ------------- \r\n\r\n" );
  1373. }
  1374. else if ( SPEI_HYPOTHESIS == rEvent.eEventId )
  1375. {
  1376. m_dstr.Append( L"------------- Hypothesis Event: ------------- \r\n\r\n" );
  1377. }
  1378. else
  1379. {
  1380. m_dstr.Append( L"Unknown Event...:\r\n\r\n" );
  1381. }
  1382. if (pElements->Rule.pszName || pElements->Rule.ulId)
  1383. {
  1384. wsprintf(szText, "RULE=\"%s\" (%05d)\r\n", W2T(pElements->Rule.pszName), pElements->Rule.ulId);
  1385. m_dstr.Append( T2W(szText) );
  1386. hr = cpResult->GetText( SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL );
  1387. if( SUCCEEDED( hr ) )
  1388. {
  1389. m_dstr.Append( dstrText );
  1390. }
  1391. else
  1392. {
  1393. m_dstr.Append( L"<Unrecognized phrase>" );
  1394. }
  1395. }
  1396. else
  1397. {
  1398. m_dstr = L"DICTATION\r\n";
  1399. CSpDynamicString dstrText;
  1400. hr = cpResult->GetText( SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL );
  1401. if( SUCCEEDED( hr ) )
  1402. {
  1403. m_dstr.Append( dstrText );
  1404. }
  1405. else
  1406. {
  1407. m_dstr.Append( L"<Unrecognized DICTATION>" );
  1408. }
  1409. }
  1410. m_dstr.Append(L"\r\n");
  1411. if (pElements->pProperties)
  1412. {
  1413. m_dstr.Append(L"\r\nPROPERTIES:\r\n");
  1414. ConstructPropertyDisplay(pElements->pElements, pElements->pProperties, m_dstr, 0);
  1415. }
  1416. m_dstr.Append(L"\r\nPARSE TREE:\r\n");
  1417. ConstructRuleDisplay(&pElements->Rule, m_dstr, 0);
  1418. m_dstr.Append(L"\r\nELEMENTS:\r\n");
  1419. for (ULONG i = 0; i < pElements->Rule.ulCountOfElements; i++)
  1420. {
  1421. wsprintf(szText, " <%u - %u> \"%s\" %c(%c)\r\n",
  1422. pElements->pElements[i].ulAudioStreamOffset,
  1423. pElements->pElements[i].ulAudioStreamOffset + pElements->pElements[i].ulAudioSizeBytes,
  1424. W2T(pElements->pElements[i].pszDisplayText),
  1425. ConfidenceGroupChar(pElements->pElements[i].ActualConfidence),
  1426. ConfidenceGroupChar(pElements->pElements[i].RequiredConfidence));
  1427. m_dstr.Append(T2W(szText));
  1428. }
  1429. m_dstr.Append( L"\r\n\r\n" );
  1430. ::SendMessage( hwndEdit, WM_SETTEXT, 0, (LPARAM)W2T(m_dstr));
  1431. ::CoTaskMemFree(pElements);
  1432. }
  1433. else
  1434. {
  1435. ::SendMessage( GetDlgItem(hDlg, IDC_LIST_PHRASES), WM_SETTEXT, 0, (LPARAM)"<Unrecognized>");
  1436. }
  1437. }
  1438. /****************************************************************************
  1439. * CCompiler::EmulateRecognition *
  1440. *-----------------------------------*
  1441. * Description:
  1442. * Allows users to input text to emmulate recognition
  1443. *
  1444. ***************************************************************** PhilSch ***/
  1445. HRESULT CCompiler::EmulateRecognition(WCHAR *pszText)
  1446. {
  1447. HRESULT hr = S_OK;
  1448. // Get local info
  1449. SPRECOGNIZERSTATUS stat;
  1450. LANGID LangID;
  1451. ZeroMemory(&stat, sizeof(stat));
  1452. m_cpRecognizer->GetStatus(&stat);
  1453. LangID = stat.aLangID[0];
  1454. CComPtr<ISpPhraseBuilder> cpPhrase;
  1455. if (SUCCEEDED(CreatePhraseFromText(pszText, &cpPhrase, LangID)) && m_cpRecognizer)
  1456. {
  1457. return( m_cpRecognizer->EmulateRecognition(cpPhrase) );
  1458. }
  1459. return S_FALSE;
  1460. }
  1461. /* MEMBER FUNCTIONS FOR THE COMMAND LINE VERSION OF THE APPLICATION ONLY*/
  1462. /****************************************************************************
  1463. * CCompiler::InitDialog *
  1464. *---------------------------*
  1465. * Description:
  1466. * Initializes the command line version of the compile status dialog box
  1467. *****************************************************************************/
  1468. BOOL CCompiler::InitDialog(HWND hDlg)
  1469. {
  1470. m_hDlg = hDlg;
  1471. TCHAR sz[MAX_PATH];
  1472. ::LoadString(m_hInstance, IDS_COMPFILE, sz, sp_countof(sz));
  1473. TCHAR szTitle[MAX_PATH];
  1474. wsprintf(szTitle, sz, m_szXMLSrcFile);
  1475. ::SendDlgItemMessage(hDlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szTitle);
  1476. return TRUE;
  1477. }
  1478. /****************************************************************************
  1479. * CCompiler::DialogProc *
  1480. *---------------------------*
  1481. * Description:
  1482. * Message handler for command line version of dialog box
  1483. *****************************************************************************/
  1484. int CALLBACK CCompiler::DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1485. {
  1486. CCompiler * pThis = (CCompiler *)::GetWindowLong(hDlg, GWL_USERDATA);
  1487. switch (message)
  1488. {
  1489. case WM_INITDIALOG:
  1490. ::SetWindowLong(hDlg, GWL_USERDATA, lParam);
  1491. pThis = (CCompiler *)lParam;
  1492. return pThis->InitDialog(hDlg); //1
  1493. case WM_PAINT:
  1494. if (pThis->m_fNeedStartCompile)
  1495. {
  1496. ::PostMessage(hDlg, WM_APP, 0, 0);
  1497. }
  1498. break;
  1499. case WM_APP:
  1500. pThis->EnterIdle();
  1501. return TRUE;
  1502. case WM_COMMAND:
  1503. {
  1504. if (LOWORD(wParam) == IDOK)
  1505. {
  1506. EndDialog(hDlg, 0);
  1507. return TRUE;
  1508. }
  1509. }
  1510. break;
  1511. }
  1512. return FALSE;
  1513. }
  1514. /****************************************************************************
  1515. * CError::AddError *
  1516. *------------------*
  1517. * Description:
  1518. *
  1519. * Returns:
  1520. *
  1521. ***************************************************************** PhilSch ***/
  1522. HRESULT CError::AddError(const long lLine, HRESULT hr, const WCHAR * pszDescription, const WCHAR * pszHelpFile, DWORD dwHelpContext)
  1523. {
  1524. SPDBG_FUNC("CError::AddError");
  1525. USES_CONVERSION;
  1526. ATLTRACE(L"%s(%d) : %s\n", T2W(m_pszFileName), lLine, pszDescription);
  1527. return S_OK;
  1528. }
  1529. /****************************************************************************
  1530. * CError::Init *
  1531. *--------------*
  1532. * Description:
  1533. *
  1534. * Returns:
  1535. *
  1536. ***************************************************************** PhilSch ***/
  1537. HRESULT CError::Init(const char *pszFileName)
  1538. {
  1539. SPDBG_FUNC("CError::Init");
  1540. m_pszFileName = pszFileName;
  1541. return S_OK;
  1542. }
  1543. /****************************************************************************
  1544. * CRecoDlgClass::ConstructPropertyDisplay *
  1545. *-----------------------------------------*
  1546. * Description:
  1547. *
  1548. * Returns:
  1549. *
  1550. ***************************************************************** PhilSch ***/
  1551. HRESULT CCompiler::ConstructPropertyDisplay(const SPPHRASEELEMENT *pElem, const SPPHRASEPROPERTY *pProp,
  1552. CSpDynamicString & dstr, ULONG ulLevel)
  1553. {
  1554. SPDBG_FUNC("CRecoDlgClass::ConstructPropertyDisplay");
  1555. HRESULT hr = S_OK;
  1556. USES_CONVERSION;
  1557. TCHAR szText[256];
  1558. // constrcut indent
  1559. while(SUCCEEDED(hr) && pProp)
  1560. {
  1561. wsprintf(szText, " [%2d, %2d] ", pProp->ulFirstElement, pProp->ulFirstElement + pProp->ulCountOfElements);
  1562. for (ULONG i = 0; i < ulLevel; i++)
  1563. {
  1564. dstr.Append(L"\t");
  1565. }
  1566. if (pProp->pszName)
  1567. {
  1568. if (wcslen(pProp->pszName) > 240)
  1569. {
  1570. dstr.Append(L"\"(Rule name too long)\" = \"");
  1571. }
  1572. else
  1573. {
  1574. wsprintf(szText, "\"%s\" = \"", W2T(pProp->pszName));
  1575. dstr.Append(T2W(szText));
  1576. }
  1577. }
  1578. else
  1579. {
  1580. dstr.Append(L"\"(UNK)\" = \"");
  1581. }
  1582. if (!pProp->pszValue)
  1583. {
  1584. // construct the value from the elements!
  1585. ULONG ulEndElement = pProp->ulFirstElement + pProp->ulCountOfElements;
  1586. for (ULONG j = pProp->ulFirstElement; j < ulEndElement; j++)
  1587. {
  1588. if (j+1 < ulEndElement)
  1589. {
  1590. dstr.Append2(pElem[j].pszDisplayText, L" ");
  1591. }
  1592. else
  1593. {
  1594. dstr.Append(pElem[j].pszDisplayText);
  1595. }
  1596. }
  1597. }
  1598. else
  1599. {
  1600. dstr.Append(pProp->pszValue);
  1601. }
  1602. if (pProp->vValue.vt != VT_EMPTY)
  1603. {
  1604. CComVariant cv = pProp->vValue;
  1605. cv.ChangeType(VT_BSTR);
  1606. wsprintf(szText, "\" (%d = %s)", pProp->ulId, W2T(cv.bstrVal));
  1607. }
  1608. else
  1609. {
  1610. wsprintf(szText, "\" (%d)", pProp->ulId);
  1611. }
  1612. dstr.Append2(T2W(szText), L"\r\n");
  1613. if (pProp->pFirstChild)
  1614. {
  1615. hr = ConstructPropertyDisplay(pElem, pProp->pFirstChild, dstr, ulLevel + 1);
  1616. }
  1617. pProp = pProp->pNextSibling;
  1618. }
  1619. return hr;
  1620. }
  1621. /****************************************************************************
  1622. * CRecoDlgClass::ConstructRuleDisplay *
  1623. *-------------------------------------*
  1624. * Description:
  1625. *
  1626. * Returns:
  1627. *
  1628. ***************************************************************** PhilSch ***/
  1629. HRESULT CCompiler::ConstructRuleDisplay(const SPPHRASERULE *pRule, CSpDynamicString &dstr, ULONG ulLevel)
  1630. {
  1631. SPDBG_FUNC("CRecoDlgClass::ConstructRuleDisplay");
  1632. HRESULT hr = S_OK;
  1633. USES_CONVERSION;
  1634. TCHAR szText[256];
  1635. // constrcut indent
  1636. while(SUCCEEDED(hr) && pRule)
  1637. {
  1638. wsprintf(szText, " [%2d, %2d] ", pRule->ulFirstElement, pRule->ulFirstElement + pRule->ulCountOfElements);
  1639. for (ULONG i = 0; i < ulLevel; i++)
  1640. {
  1641. dstr.Append(L"\t");
  1642. }
  1643. if (pRule->pszName)
  1644. {
  1645. if (wcslen(pRule->pszName) > 240)
  1646. {
  1647. dstr.Append(L"\"(Rule name too long)\" = \"");
  1648. }
  1649. else
  1650. {
  1651. wsprintf(szText, "%s \"%s\" (%d)", szText, W2T(pRule->pszName), pRule->ulId);
  1652. dstr.Append(T2W(szText));
  1653. }
  1654. }
  1655. else
  1656. {
  1657. dstr.Append(L"\"(UNK)\" = \"");
  1658. }
  1659. dstr.Append(L"\r\n");
  1660. if (pRule->pFirstChild)
  1661. {
  1662. hr = ConstructRuleDisplay(pRule->pFirstChild, dstr, ulLevel + 1);
  1663. }
  1664. pRule = pRule->pNextSibling;
  1665. }
  1666. return hr;
  1667. }