#include "stdafx.h" #include #include "comp.h" #include "StreamHlp.h" //#define INPROC /**************************************************************************** * CCompiler::~CCompiler * *---------------------------* * Description: * Releases objects created by CCompiler **************************************************************** Leonro *****/ CCompiler::~CCompiler() { m_cpRichEdit.Release(); m_cpTextDoc.Release(); m_cpTextSel.Release(); m_cpRecognizer.Release(); m_cpRecoContext.Release(); m_cpCompiler.Release(); m_cpRecoGrammar.Release(); if( m_hMod ) { FreeLibrary( m_hMod ); } } /**************************************************************************** * CCompiler::Initialize * *---------------------------* * Description: * Set up the windows, as well as the RichEdit objects. * Also it initializes some SAPI objects. ************************************************************** Leonro *******/ HRESULT CCompiler::Initialize( int nCmdShow ) { TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // Window class HRESULT hr = S_OK; WNDCLASSEX wcex; // Initialize global strings LoadString( m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); LoadString( m_hInstance, IDC_GRAMCOMP, szWindowClass, MAX_LOADSTRING ); // Register the windows class wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = m_hInstance; wcex.hIcon = LoadIcon(m_hInstance, (LPCTSTR)IDI_GRAMCOMP); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_GRAMCOMP; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); // Register window and create the sapi grammar compiler if( RegisterClassEx(&wcex) ) { hr = m_cpCompiler.CoCreateInstance( CLSID_SpGrammarCompiler ); if( FAILED( hr ) ) { MessageBox( NULL, _T("Error initializing speech objects. Shutting down.\n\n" " Please make sure SAPI5 is installed!"), _T("Error"), MB_OK ); } } else { MessageBox( NULL, _T("Error initializing application. Shutting down."), _T("Error"), MB_OK ); hr = E_FAIL; } // Load DLL for Rich Edit 3.0 if( SUCCEEDED( hr ) ) { m_hMod = LoadLibrary( "RICHED20.DLL" ); if( !m_hMod ) { MessageBox( NULL, "Couldn't find required riched32.dll. Shutting down!", "Error - Missing dll", MB_OK ); hr = E_FAIL; } } if( SUCCEEDED( hr ) ) { // Perform application initialization: m_hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, m_hInstance, this ); if( m_hWnd && m_hWndStatus && m_hWndEdit ) { // Get TOM interfaces SendMessage( m_hWndEdit, EM_GETOLEINTERFACE, 0, (LPARAM)(LPVOID FAR *)&m_cpRichEdit ); SendMessage( m_hWndEdit, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_KEYEVENTS ); if( !m_cpRichEdit ) { hr = E_NOINTERFACE; } if( SUCCEEDED( hr ) ) { hr = m_cpRichEdit->QueryInterface( IID_ITextDocument, (void**)&m_cpTextDoc ); if( SUCCEEDED( hr ) ) { hr = m_cpTextDoc->GetSelection( &m_cpTextSel ); } } if( SUCCEEDED( hr ) ) { // Load Accelerators m_hAccelTable = LoadAccelerators( m_hInstance, MAKEINTRESOURCE(IDR_GRAMACCEL) ); ::ShowWindow( m_hWnd, nCmdShow ); ::UpdateWindow( m_hWnd ); } else { MessageBox( m_hWnd, _T("Error initializing edit control. Shutting down!"), _T("Error"), MB_OK ); } } } return hr; } /**************************************************************************************** * CCompiler::Run() * *----------------------* * Description: * Contains the message loop for the application **************************************************************************** Leonro *****/ int CCompiler::Run() { MSG msg; // Main message loop: while( ::GetMessage(&msg, NULL, 0, 0) ) { if( !::TranslateAccelerator(m_hWnd, m_hAccelTable, &msg) ) { ::TranslateMessage( &msg ); ::DispatchMessage( &msg ); } } return msg.wParam; } /* CCompiler::Run */ /**************************************************************************** * CCompiler::WndProc * *---------------------------* * Description: * Processes messages for the main window. ***************************************************************** Leonro ****/ LRESULT CALLBACK CCompiler::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; static BOOL bFileOpened = FALSE; PAINTSTRUCT psMain, psStatus; HDC hMainDC=0, hStatusDC=0; long lSaved = 0; HRESULT hr = S_OK; static TCHAR szTitle[NORM_SIZE] = _T(""); TCHAR szFileName[NORM_SIZE] = _T(""); static TCHAR szSaveFileName[NORM_SIZE] = _T(""); HMENU hMenu=0; static int iNumUndos=0; long lStart, lEnd; CCompiler* pThis = (CCompiler *)GetWindowLong(hWnd, GWL_USERDATA); // get the handle to the menu hMenu = GetMenu( hWnd ); switch (message) { case WM_SETFOCUS: SetFocus (pThis->m_hWndEdit); break; case WM_CREATE: pThis = (CCompiler *)(((CREATESTRUCT *) lParam)->lpCreateParams); SetWindowLong(hWnd, GWL_USERDATA, (LPARAM)pThis); pThis->m_hWnd = hWnd; // Create the compile status window pThis->m_hWndStatus = CreateWindowEx ( WS_EX_CLIENTEDGE, _T("LISTBOX"), NULL, WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_HSCROLL, 1, 1, 1, 1, hWnd, NULL, pThis->m_hInstance, NULL); // Create the actual rich edit window pThis->m_hWndEdit = CreateWindowEx( WS_EX_CLIENTEDGE, RICHEDIT_CLASS, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN, 1, 1, 1, 1, hWnd, (HMENU)IDC_RICHEDITWND, pThis->m_hInstance, NULL ); break; case WM_ERASEBKGND: return TRUE; case WM_SIZE: { // move the editor and compiler window LONG lListBoxHeight = (HIWORD(lParam) / 4); LONG lCodeHeight = HIWORD(lParam) - lListBoxHeight; MoveWindow (pThis->m_hWndEdit, 0, 0, LOWORD(lParam), lCodeHeight , FALSE); MoveWindow (pThis->m_hWndStatus, 0, lCodeHeight, LOWORD(lParam), lListBoxHeight, FALSE); // repaint InvalidateRect( hWnd, NULL, FALSE ); } break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Update available menu items pThis->m_cpTextSel->GetStart( &lStart ); pThis->m_cpTextSel->GetStoryLength( &lEnd ); if( lEnd-lStart > 1 ) { EnableMenuItem( hMenu, IDM_EDIT_CUT, MF_ENABLED ); EnableMenuItem( hMenu, IDM_EDIT_COPY, MF_ENABLED ); } else { EnableMenuItem( hMenu, IDM_EDIT_CUT, MF_GRAYED ); EnableMenuItem( hMenu, IDM_EDIT_COPY, MF_GRAYED ); } // Parse the menu selections: switch( wmId ) { case IDM_FILE_NEW: // Check if the file has been changed and save if necessary hr = pThis->m_cpTextDoc->GetSaved( &lSaved ); if( lSaved == tomFalse && SUCCEEDED( hr ) ) { int iRetVal = MessageBox( pThis->m_hWndEdit, _T("Do you want to save your changes?"), _T("Grammar Compiler"), MB_YESNO ); if( iRetVal == IDYES ) { BOOL bRetVal = TRUE; // No need to call save file dialog if there's already a file name if( !_tcscmp( szSaveFileName, "" ) ) { bRetVal = pThis->CallSaveFileDialog( hWnd, szSaveFileName ); } // TOM save file if( bRetVal ) { // TOM save file pThis->FileSave( hWnd, pThis, szSaveFileName ); } } else { pThis->m_cpTextDoc->SetSaved( tomTrue ); } } // call TOM new pThis->m_cpTextDoc->New(); pThis->m_cpTextDoc->SetSaved( tomTrue ); // Add the file name to the title bar LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); _tcscat( szTitle, _T(" - []") ); SetWindowText( hWnd, szTitle ); // reset defaults ::SendMessage( pThis->m_hWndStatus, LB_RESETCONTENT, 0, 0 ); ::SendMessage( pThis->m_hWndStatus, LB_SETHORIZONTALEXTENT, 0, 0 ); pThis->m_szCFGDestFile[0] = 0; pThis->m_szHeaderDestFile[0] = 0; pThis->m_szXMLSrcFile[0] = 0; pThis->m_fNeedStartCompile = TRUE; pThis->m_hrWorstError = 0; _tcscpy( szSaveFileName, _T("") ); InvalidateRect( hWnd, NULL, FALSE ); break; case IDM_FILE_OPEN: // Save old file first if one exists and it has not been saved hr = pThis->m_cpTextDoc->GetSaved( &lSaved ); if( lSaved == tomFalse && SUCCEEDED( hr ) ) { int iRetVal = MessageBox( pThis->m_hWndEdit, _T("Do you want to save your changes?"), _T("Grammar Compiler"), MB_YESNO ); if( iRetVal == IDYES ) { // reset errors pThis->m_hrWorstError = 0; // TOM save file hr = pThis->FileSave( hWnd, pThis, szSaveFileName ); if( hr == STG_E_ACCESSDENIED ) // Handle read only files { MessageBox( pThis->m_hWndEdit, _T("This file exists with Read Only attributes.\n Please use a different file name."), _T("File Save"), MB_OK ); // Call FileSave again but this time pop the save file dialog box pThis->FileSave( hWnd, pThis, szSaveFileName ); } } else { pThis->m_cpTextDoc->SetSaved( tomTrue ); } } bFileOpened = pThis->CallOpenFileDialog( hWnd, szFileName, _T("XML (*.xml)\0*.xml\0TXT (*.txt)\0*.txt\0All Files (*.*)\0*.*\0") ); // Copy the open file name to the Save file name for use later _tcscpy( szSaveFileName, szFileName ); if( bFileOpened ) { HRESULT hr = S_OK; VARIANT Var; USES_CONVERSION; // reset text in windows _tcscpy(pThis->m_szXMLSrcFile, szFileName); ::SendMessage( pThis->m_hWndStatus, LB_RESETCONTENT, 0, 0 ); ::SendMessage( pThis->m_hWndStatus, LB_SETHORIZONTALEXTENT, 0, 0 ); InvalidateRect( hWnd, NULL, FALSE ); // Open the file in the rich edit control VariantInit( &Var ); Var.vt = VT_BSTR; Var.bstrVal = SysAllocString( T2W(szFileName) ); // Will use Win32 file command hr = pThis->m_cpTextDoc->Open( &Var, tomOpenExisting, 0 ); hr &= ~0x40000; // Mask off bit 18 if( hr == STG_E_ACCESSDENIED ) // Handle read only files { pThis->m_cpTextDoc->Open( &Var, tomReadOnly | tomOpenExisting, 0 ); } SysFreeString( Var.bstrVal ); // reset defaults pThis->m_szCFGDestFile[0] = 0; pThis->m_szHeaderDestFile[0] = 0; pThis->m_fNeedStartCompile = TRUE; pThis->m_hrWorstError = 0; // no changes to the file yet so set SetSaved to true pThis->m_cpTextDoc->SetSaved( tomTrue ); // Add the file name to the title bar LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); _tcscat( szTitle, _T(" - [") ); _tcscat( szTitle, szFileName ); _tcscat( szTitle, _T("]") ); SetWindowText( hWnd, szTitle ); } break; case IDM_FILE_SAVEAS: // Remove old save file name if one exists _tcscpy( szSaveFileName, _T("") ); // no break here case IDM_FILE_SAVE: // TOM save file hr = pThis->FileSave( hWnd, pThis, szSaveFileName ); if( hr == STG_E_ACCESSDENIED ) // Handle read only files { MessageBox( pThis->m_hWndEdit, _T("This file exists with Read Only attributes.\n Please use a different file name."), _T("File Save"), MB_OK ); // Call FileSave again but this time pop the save file dialog box hr = pThis->FileSave( hWnd, pThis, szSaveFileName ); } // Add the file name to the title bar if( SUCCEEDED( hr ) ) { LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); _tcscat( szTitle, _T(" - [") ); _tcscat( szTitle, szSaveFileName ); _tcscat( szTitle, _T("]") ); SetWindowText( hWnd, szTitle ); } break; case IDM_BUILD_COMPILE: if( pThis->m_fNeedStartCompile ) { pThis->Compile( hWnd, szSaveFileName, szTitle, pThis ); } break; case IDC_RICHEDITWND: // When user changes contents of edit control update status bar on top if( wmEvent == EN_CHANGE ) { TCHAR szTitleNotSaved[NORM_SIZE] = _T(""); if( !_tcscmp( szTitle, _T("") ) ) { LoadString( pThis->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); _tcscat( szTitle, _T(" - []") ); } _tcscpy( szTitleNotSaved, szTitle ); _tcscat( szTitleNotSaved, _T("*") ); SetWindowText( hWnd, szTitleNotSaved ); pThis->m_fNeedStartCompile = TRUE; //Update edit menu items EnableMenuItem( hMenu, IDM_EDIT_UNDO, MF_ENABLED ); } break; case IDM_EDIT_UNDO: // Undo pThis->m_cpTextDoc->Undo( 1, NULL ); EnableMenuItem( hMenu, IDM_EDIT_REDO, MF_ENABLED ); iNumUndos++; break; case IDM_EDIT_REDO: // Redo pThis->m_cpTextDoc->Redo( 1, NULL ); if( --iNumUndos < 1 ) { EnableMenuItem( hMenu, IDM_EDIT_REDO, MF_GRAYED ); iNumUndos = 0; } break; case IDM_EDIT_COPY: // Copy pThis->m_cpTextSel->Copy( NULL ); EnableMenuItem( hMenu, IDM_EDIT_PASTE, MF_ENABLED ); break; case IDM_EDIT_CUT: // Cut pThis->m_cpTextSel->Cut( NULL ); EnableMenuItem( hMenu, IDM_EDIT_PASTE, MF_ENABLED ); break; case IDM_EDIT_PASTE: // Paste pThis->m_cpTextSel->Paste( NULL, 0 ); break; case IDM_EDIT_DELETE: // Delete pThis->m_cpTextSel->Delete( tomCharacter, 1, NULL ); break; case IDM_EDIT_SELECTALL: // Select all { pThis->m_cpTextSel->GetStart( &lStart ); pThis->m_cpTextSel->GetStoryLength( &lEnd ); pThis->m_cpTextSel->MoveStart( tomCharacter, -lStart, NULL ); pThis->m_cpTextSel->MoveEnd( tomCharacter, lEnd-lStart, NULL ); } break; case IDM_EDIT_FIND: // Find DialogBoxParam( pThis->m_hInstance, (LPCTSTR)IDD_FIND, hWnd, (DLGPROC)Find, (LPARAM)pThis); break; case IDM_EDIT_GOTO: // Find DialogBoxParam( pThis->m_hInstance, (LPCTSTR)IDD_GOTO, hWnd, (DLGPROC)Goto, (LPARAM)pThis); break; case IDM_TESTGRAMMAR: // Only compile if necessary if( pThis->m_fNeedStartCompile ) { hr = pThis->Compile( hWnd, szSaveFileName, szTitle, pThis ); } // Create new dialog box if( SUCCEEDED( hr ) ) { DialogBoxParam( pThis->m_hInstance, (LPCTSTR)IDD_TESTGRAMMAR, hWnd, (DLGPROC)TestGrammar, (LPARAM)pThis); } else if( hr == E_INVALIDARG ) { MessageBox( pThis->m_hWndEdit, _T("Please enter text or open an xml file first."), _T("Compile Error"), MB_OK ); } else if( hr == E_FAIL ) { MessageBox( pThis->m_hWndEdit, _T("Please save file first."), _T("Compile Error"), MB_OK ); } else { MessageBox( pThis->m_hWndEdit, _T("Error compiling xml file."), _T("Compile Error"), MB_OK ); } break; case IDM_ABOUT: // About box DialogBox( pThis->m_hInstance, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About ); break; case IDM_EXIT: SendMessage( hWnd, WM_CLOSE, 0, 0 ); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_CLOSE: { int iRetVal = 0; // Check if the file has been changed and save if necessary hr = pThis->m_cpTextDoc->GetSaved( &lSaved ); if( lSaved == tomFalse && SUCCEEDED( hr ) ) { iRetVal = MessageBox( pThis->m_hWndEdit, _T("Do you want to save your changes?"), _T("Grammar Compiler"), MB_YESNOCANCEL ); if( iRetVal == IDYES ) { // No need to call save file dialog if there's already a file name if( !_tcscmp( szSaveFileName, "" ) ) { pThis->CallSaveFileDialog( hWnd, szSaveFileName ); } // TOM save file pThis->FileSave( hWnd, pThis, szSaveFileName ); } else { pThis->m_cpTextDoc->SetSaved( tomTrue ); } } if( iRetVal != IDCANCEL ) { DestroyWindow( hWnd ); } } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } /**************************************************************************** * CCompiler::About * *---------------------------* * Description: * Message handler for About box. ***************************************************************** Leonro ****/ LRESULT CALLBACK CCompiler::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } /**************************************************************************** * CCompiler::Find * *---------------------------* * Description: * Message handler for Find box. ***************************************************************** Leonro ****/ LRESULT CALLBACK CCompiler::Find(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { TCHAR szFindText[NORM_SIZE]=_T(""); CComBSTR bStr( _T("Grammar") ); long lUpDown = tomForward; long lFlags=0; CCompiler* pThis = (CCompiler *)GetWindowLong( hDlg, GWL_USERDATA ); switch (message) { case WM_INITDIALOG: SetWindowLong( hDlg, GWL_USERDATA, lParam ); SendDlgItemMessage( hDlg, IDB_DOWN, BM_SETCHECK, BST_CHECKED, 0 ); return TRUE; case WM_COMMAND: { switch( LOWORD( wParam ) ) { case IDB_FINDNEXT: // Get text string GetDlgItemText( hDlg, IDE_FINDTEXT, szFindText, NORM_SIZE ); bStr = szFindText; // Search up or down? SendDlgItemMessage( hDlg, IDB_DOWN, BM_GETCHECK, 0, 0 )? lUpDown = tomForward : lUpDown = tomBackward; // Match case? SendDlgItemMessage( hDlg, IDB_MATCHCASE, BM_GETCHECK, 0, 0 )? lFlags=tomMatchCase : lFlags=0; pThis->m_cpTextSel->FindText( bStr, lUpDown, lFlags, NULL ); return TRUE; case IDB_CANCEL: case IDCANCEL: EndDialog( hDlg, LOWORD(wParam) ); return TRUE; } } break; case WM_CLOSE: EndDialog( hDlg, LOWORD(wParam) ); return TRUE; } return FALSE; } /**************************************************************************** * CCompiler::Goto * *---------------------------* * Description: * Message handler for Goto box. **************************************************************** Leonro *****/ LRESULT CALLBACK CCompiler::Goto( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { TCHAR szGotoLine[NORM_SIZE]=_T(""); TCHAR szCurrLine[NORM_SIZE]=_T(""); long iGotoLine, iCurrLine, iLinesToMove; CCompiler* pThis = (CCompiler *)GetWindowLong( hDlg, GWL_USERDATA ); switch (message) { case WM_INITDIALOG: SetWindowLong( hDlg, GWL_USERDATA, lParam ); pThis = (CCompiler *)lParam; pThis->m_cpTextSel->GetIndex( tomLine, &iCurrLine ); _itoa( iCurrLine, szCurrLine, 10 ); SetDlgItemText( hDlg, IDE_LINE, szCurrLine ); return TRUE; case WM_COMMAND: { switch( LOWORD( wParam ) ) { case IDB_OK: // Get current line pThis->m_cpTextSel->GetIndex( tomLine, &iCurrLine ); // Get goto line GetDlgItemText( hDlg, IDE_LINE, szGotoLine, NORM_SIZE ); iGotoLine = atoi( szGotoLine ); EndDialog( hDlg, LOWORD(wParam) ); // Calculate number of lines to move iLinesToMove = iGotoLine - iCurrLine; // Move pThis->m_cpTextSel->MoveDown( tomLine, iLinesToMove, tomMove, NULL ); return TRUE; case IDB_CANCEL: case IDCANCEL: EndDialog( hDlg, LOWORD(wParam) ); return TRUE; } } break; case WM_CLOSE: EndDialog( hDlg, LOWORD(wParam) ); return TRUE; } return FALSE; } /**************************************************************************** * CCompiler::TestGrammar * *---------------------------* * Description: * Message handler for TestGrammar box. **************************************************************** Leonro *****/ LRESULT CALLBACK CCompiler::TestGrammar(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HRESULT hr = S_OK; CCompiler* pThis = (CCompiler *)GetWindowLong( hDlg, GWL_USERDATA ); switch (message) { case WM_RECOEVENT: { pThis->RecoEvent( hDlg, pThis ); } return TRUE; case WM_INITDIALOG: { SetWindowLong( hDlg, GWL_USERDATA, lParam ); pThis = (CCompiler *)lParam; // Create the shared sapi reco instance if the app hasn't already done so if( !pThis->m_cpRecognizer ) { #ifdef INPROC // Create the inproc engine hr = pThis->m_cpRecognizer.CoCreateInstance( CLSID_SpInprocRecognizer ); // Create default audio input CComPtr cpAudioToken; if (SUCCEEDED(hr)) { hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &cpAudioToken); } if (SUCCEEDED(hr)) { pThis->m_cpRecognizer->SetInput(cpAudioToken, TRUE); } #else // Create the shared engine hr = pThis->m_cpRecognizer.CoCreateInstance( CLSID_SpSharedRecognizer ); #endif // Create the Reco context if( SUCCEEDED( hr ) ) { hr = pThis->m_cpRecognizer->CreateRecoContext( &pThis->m_cpRecoContext ); } } // Set up windows messageing for recognition events if( SUCCEEDED( hr ) ) { hr = pThis->m_cpRecoContext->SetNotifyWindowMessage( hDlg, WM_RECOEVENT, 0, 0); } if( SUCCEEDED( hr ) ) { const ULONGLONG ullInterest = SPFEI(SPEI_SOUND_END) | SPFEI(SPEI_SOUND_START) | SPFEI(SPEI_HYPOTHESIS) | SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_FALSE_RECOGNITION); hr = pThis->m_cpRecoContext->SetInterest( ullInterest, ullInterest ); } // Get locale/font settings if( SUCCEEDED( hr ) ) { LCID lcid = GetUserDefaultLCID(); // Pick an appropriate font. On Windows 2000, let the system fontlink. DWORD dwVersion = GetVersion(); if ( dwVersion >= 0x80000000 || LOBYTE(LOWORD(dwVersion)) < 5 || LANGIDFROMLCID(lcid) != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)) { TCHAR achCodePage[6]; UINT uiCodePage; if( 0 != GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, achCodePage, 6) ) { uiCodePage = atoi(achCodePage); } else { uiCodePage = GetACP(); } CComPtr cpMultiLanguage; MIMECPINFO MimeCpInfo; if ( SUCCEEDED(cpMultiLanguage.CoCreateInstance(CLSID_CMultiLanguage)) && SUCCEEDED(cpMultiLanguage->GetCodePageInfo(uiCodePage, &MimeCpInfo))) { USES_CONVERSION; HFONT hfont = CreateFont( 0, 0, 0, 0, FW_NORMAL, 0, 0, 0, MimeCpInfo.bGDICharset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, W2T(MimeCpInfo.wszProportionalFont )); } } } // Update status edit box if( SUCCEEDED( hr ) ) { const static TCHAR szPrefixText[] = _T("Current C&&C Grammar: "); TCHAR szDesc[sp_countof(pThis->m_szCFGDestFile) + sp_countof(szPrefixText) + 4]; _tcscpy( szDesc, szPrefixText ); if( *pThis->m_szCFGDestFile ) { _tcscat( szDesc, pThis->m_szCFGDestFile ); } else { _tcscat( szDesc, _T("none") ); } SendDlgItemMessage( hDlg, IDC_GRAMMAR_STATUS, WM_SETTEXT, 0, (LPARAM)szDesc ); } if( FAILED( hr ) ) { MessageBox( hDlg, _T("Error initializing Speech Recognizer."), _T("Error"), MB_OK ); EndDialog( hDlg, LOWORD(wParam) ); } } return TRUE; case WM_COMMAND: { switch( LOWORD( wParam ) ) { case IDC_BEGINRECO: // Load the grammar if( SendDlgItemMessage( hDlg, IDC_BEGINRECO, BM_GETCHECK, 0, 0 ) ) { // Enable Emulate Recognition feature EnableWindow( GetDlgItem(hDlg, IDC_EDIT_PARSETEXT), TRUE ); TCHAR* szPath = pThis->m_szCFGDestFile; hr = pThis->LoadGrammar( szPath ); if( FAILED( hr ) ) { MessageBox( hDlg, _T("Error loading grammar. Make sure") _T(" a file is loaded, saved, and compiled."), _T("Error"), MB_OK ); } // Activate the grammar if( SUCCEEDED( hr ) ) { hr = pThis->m_cpRecoGrammar->SetRuleState(NULL, NULL, SPRS_ACTIVE); } if( FAILED( hr ) ) { // Release grammar pThis->m_cpRecoGrammar.Release(); MessageBox( NULL, _T("Error loading grammar."), _T("Error"), MB_OK ); EndDialog( hDlg, LOWORD(wParam) ); return FALSE; } } else { // Disable Emulate Recognition EnableWindow( GetDlgItem(hDlg, IDC_EDIT_PARSETEXT), FALSE ); // Release grammar pThis->m_cpRecoGrammar.Release(); } return TRUE; case IDB_MUTE: { // Check if the user has selected mute if( SendDlgItemMessage( hDlg, IDB_MUTE, BM_GETCHECK, 0, 0 ) ) { pThis->m_cpRecognizer->SetRecoState( SPRST_INACTIVE ); } else { pThis->m_cpRecognizer->SetRecoState( SPRST_ACTIVE ); } } return TRUE; case IDC_BUTTON_SUBMIT: { CSpDynamicString dstrText; int iStrLen = 0; TCHAR szEmulateRecoText[NORM_SIZE]; USES_CONVERSION; UINT numChar = GetDlgItemText( hDlg, IDC_EDIT_PARSETEXT, szEmulateRecoText, NORM_SIZE ); if( pThis->m_cpRecoGrammar ) { pThis->m_dstr = L""; HRESULT hr = pThis->EmulateRecognition(T2W(szEmulateRecoText)); if( SP_NO_PARSE_FOUND == hr ) { ::SendMessage( GetDlgItem(hDlg, IDC_LIST_PHRASES), WM_SETTEXT, 0, (LPARAM)""); } } } return TRUE; } } return TRUE; case WM_CLOSE: { // Release grammar pThis->m_cpRecoGrammar.Release(); EndDialog( hDlg, LOWORD(wParam) ); } return TRUE; } return FALSE; } /**************************************************************************** * CCompiler::AddStatus * *---------------------------* * Description: * Writes compile output to the status window. *****************************************************************************/ void CCompiler::AddStatus(HRESULT hr, UINT uID, const TCHAR * pFmtString) { USES_CONVERSION; TCHAR sz[MAX_PATH]; ::LoadString(m_hInstance, uID, sz, sp_countof(sz)); if (pFmtString) { TCHAR szFormatted[MAX_PATH]; ::wsprintf(szFormatted, sz, pFmtString); AddError(-1, hr, T2W(szFormatted), NULL, 0); } else { AddError(-1, hr, T2W(sz), NULL, 0); } } /**************************************************************************** * CCompiler::AddError * *---------------------------* * Description: * Writes compile error messages to the status window. *****************************************************************************/ STDMETHODIMP CCompiler::AddError(const long lLine, HRESULT hr, const WCHAR * pszDescription, const WCHAR * pszHelpFile, DWORD dwHelpContext) { if (FAILED(hr) && SUCCEEDED(m_hrWorstError)) { m_hrWorstError = hr; } USES_CONVERSION; TCHAR *pszText = NULL; TCHAR *pszFinalOutput = NULL; if (hr == S_OK) { pszFinalOutput = W2T(pszDescription); } else { pszText = new TCHAR[ MAX_PATH + _tcslen( m_szXMLSrcFile ) + _tcslen( W2T(pszDescription) ) ]; if ( pszText ) { if (lLine >= 0) { wsprintf(pszText, SUCCEEDED(hr) ? _T("%s(%d) Warning: %s\n") : _T("%s(%d) Error: %s\n"), m_szXMLSrcFile, lLine, W2T(pszDescription)); } else { wsprintf(pszText, SUCCEEDED(hr) ? _T("%s Warning: %s\n") : _T("%s Error: %s\n"), m_szXMLSrcFile, W2T(pszDescription)); } pszFinalOutput = pszText; } else { // out of memory: just give the description pszFinalOutput = W2T(pszDescription); } } bool fNeedToUpdateWidth = false; // Might need to tell the listbox to show the hscroll HWND hwndList = NULL; if( m_hDlg ) // dialog { if( m_fCommandLine ) { int iRet = ::SendDlgItemMessage(m_hDlg, IDC_LIST_STATUS, LB_ADDSTRING, 0, (LPARAM)pszFinalOutput); hwndList = ::GetDlgItem( m_hDlg, IDC_LIST_STATUS ); fNeedToUpdateWidth = (LB_ERR != iRet); } else { _tprintf( pszFinalOutput ); } } else // window { int iRet = ::SendMessage( m_hWndStatus, LB_ADDSTRING, 0, (LPARAM) pszFinalOutput ); hwndList = m_hWndStatus; fNeedToUpdateWidth = (LB_ERR != iRet); } if ( fNeedToUpdateWidth ) { // Listboxes do not update their horizontal extent dynamically, // so we need to do so here. HDC hdc = ::GetDC( hwndList ); SIZE size; ::GetTextExtentPoint32( hdc, pszFinalOutput, _tcslen( pszFinalOutput ), &size ); ::ReleaseDC( hwndList, hdc ); int iCurrentWidth = (int) ::SendMessage( hwndList, LB_GETHORIZONTALEXTENT, 0, 0 ); if ( size.cx > iCurrentWidth ) { ::SendMessage( hwndList, LB_SETHORIZONTALEXTENT, size.cx, 0 ); } } if ( pszText ) { delete[] pszText; } return S_OK; } /**************************************************************************** * CCompiler::EnterIdle * *---------------------------* * Description: * Calls the SAPI grammar compiler to compile the xml file. *****************************************************************************/ HRESULT CCompiler::EnterIdle() { HRESULT hr = S_OK; if (m_fNeedStartCompile) { BOOL bWorked = FALSE; m_fNeedStartCompile = FALSE; CSpFileStream Source(&hr, m_szXMLSrcFile); AddInternalError(hr, IDS_CANTOPENSOURCE, m_szXMLSrcFile); if (SUCCEEDED(hr)) { CSpFileStream Dest(&hr, m_szCFGDestFile, GENERIC_WRITE, 0, CREATE_ALWAYS); AddInternalError(hr, IDS_CANTOPENDEST, m_szCFGDestFile); if (SUCCEEDED(hr) && strlen(m_szHeaderDestFile)) { CSpFileStream Header(&hr, m_szHeaderDestFile, GENERIC_WRITE, 0, CREATE_ALWAYS); AddInternalError(hr, IDS_CANTOPENDEST, m_szHeaderDestFile); WriteStream(&Header, "#ifndef __"); StripWrite(&Header, m_szHeaderDestFile); WriteStream(&Header, "_IDs__\n"); WriteStream(&Header, "#define __"); StripWrite(&Header, m_szHeaderDestFile); WriteStream(&Header, "_IDs__\n\n"); if (SUCCEEDED(hr)) { if( !m_fSilent ) { hr = m_cpCompiler->CompileStream(&Source, &Dest, &Header, NULL, this, 0); } else { hr = m_cpCompiler->CompileStream(&Source, &Dest, &Header, NULL, m_cpError, 0); } } if (SUCCEEDED(hr)) { WriteStream(&Header, "\n#endif\n"); } } else { if (SUCCEEDED(hr)) { if( !m_fSilent ) { hr = m_cpCompiler->CompileStream(&Source, &Dest, NULL, NULL, this, 0); } else { hr = m_cpCompiler->CompileStream(&Source, &Dest, NULL, NULL, m_cpError, 0); } } } if (SUCCEEDED(hr) && SUCCEEDED(m_hrWorstError)) { AddStatus(S_OK, IDS_COMPILESUCCESS); bWorked = TRUE; if (m_fSilent) { ::EndDialog(m_hDlg, S_OK); } } else { AddStatus(hr, IDS_COMPILEFAILURE); bWorked = FALSE; if (m_fSilent) { ::EndDialog(m_hDlg, S_OK); } } } if (!bWorked) { ::DeleteFile(m_szCFGDestFile); } } return hr; } /**************************************************************************** * CCompiler::LoadGrammar * *---------------------------* * Description: * Loads and activates the Grammar ***************************************************************** Leonro ****/ HRESULT CCompiler::LoadGrammar( TCHAR* szPath ) { HRESULT hr = S_OK; // load grammar hr = m_cpRecoContext->CreateGrammar(GRAM_ID, &m_cpRecoGrammar); if (SUCCEEDED(hr)) { USES_CONVERSION; hr = m_cpRecoGrammar->LoadCmdFromFile( T2W(szPath), SPLO_STATIC ); if (FAILED(hr)) { m_cpRecoGrammar.Release(); } } return hr; } /**************************************************************************** * CCompiler::WriteStream * *---------------------------* * Description: * Calls write on the output stream *****************************************************************************/ HRESULT CCompiler::WriteStream(IStream * pStream, const char * pszText) { ULONG cch = strlen(pszText); return pStream->Write(pszText, cch, NULL); } /**************************************************************************** * CCompiler::StripWrite * *---------------------------* * Description: * Strips characters off strings *****************************************************************************/ HRESULT CCompiler::StripWrite(IStream * pStream, const char * pszText) { ULONG cch = strlen(pszText); char * psz = (char *)_alloca((cch + 1) * sizeof(char)); char c; char * pszWork = psz; do { c = *pszText++; *pszWork++ = ((c == 0) || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) ? c : '_'; } while (c); return pStream->Write(psz, cch, NULL); } /**************************************************************************** * CCompiler::CallOpenFileDialog * *---------------------------* * Description: * Displays the open dialog box to retrieve the * user-selected .txt or .xml file for synthisizing *************************************************************** Leonro ******/ BOOL CCompiler::CallOpenFileDialog( HWND hWnd, LPSTR szFileName, TCHAR* szFilter ) { OPENFILENAME ofn; BOOL bRetVal = TRUE; LONG lRetVal; HKEY hkResult; TCHAR szPath[NORM_SIZE] = _T(""); DWORD size = NORM_SIZE; // Open the last directory used by this app (stored in registry) lRetVal = RegCreateKeyEx( HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Speech\\AppData\\PathToGrammarFiles"), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkResult, NULL ); if( lRetVal == ERROR_SUCCESS ) { RegQueryValueEx( hkResult, _T("GramCompFiles"), NULL, NULL, (PBYTE)szPath, &size ); } ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; ofn.hwndOwner = hWnd; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nFilterIndex = 1; ofn.lpstrInitialDir = szPath; ofn.lpstrFile = szFileName; ofn.nMaxFile = NORM_SIZE; ofn.lpstrTitle = NULL; ofn.lpstrFileTitle = NULL; ofn.lpstrDefExt = _T("xml"); ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; // Pop the dialog bRetVal = GetOpenFileName( &ofn ); // Write the directory path you're in to the registry TCHAR pathstr[NORM_SIZE] = _T(""); strcpy( pathstr, szFileName ); int i=0; while( pathstr[i] != NULL ) { i++; } while( pathstr[i] != '\\' ) { i --; } pathstr[i] = NULL; RegSetValueEx( hkResult, _T("GramCompFiles"), NULL, REG_EXPAND_SZ, (PBYTE)pathstr, strlen(pathstr)+1 ); RegCloseKey( hkResult ); return bRetVal; } /**************************************************************************** * CCompiler::CallSaveFileDialog * *---------------------------* * Description: * Displays the save file dialog box and retrieves * the user-selected save file name. *************************************************************** Leonro ******/ BOOL CCompiler::CallSaveFileDialog( HWND hWnd, TCHAR* szSaveFile ) { TCHAR pszFileName[MAX_PATH] = _T(""); BOOL bSuccess = TRUE; static TCHAR pszFilter[MAX_PATH] = _T("leon"); OPENFILENAME ofn; ZeroMemory( &ofn, OPENFILENAME_SIZE_VERSION_400 ); ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; ofn.hwndOwner = hWnd; ofn.hInstance = m_hInstance; ofn.lpstrFilter = "XML Files (*.xml)\0*.xml\0Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0"; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szSaveFile; ofn.nMaxFile = MAX_PATH; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrFileTitle = NULL; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = OFN_CREATEPROMPT; ofn.lpstrDefExt = "xml"; bSuccess = GetSaveFileName( &ofn ); return bSuccess; } /**************************************************************************** * CCompiler::FileSave * *---------------------------* * Description: * Saves the TOM file to disk **************************************************************** Leonro *****/ HRESULT CCompiler::FileSave( HWND hWnd, CCompiler* pComp, TCHAR* szSaveFile ) // { VARIANT Var; HRESULT hr = S_OK; BOOL bRetVal = TRUE; USES_CONVERSION; // Call save file dialog if there's no file name already if( !_tcscmp( szSaveFile, "" ) ) { bRetVal = CallSaveFileDialog( hWnd, szSaveFile ); } // TOM save file if( bRetVal ) { // Save it VariantInit( &Var ); Var.vt = VT_BSTR; Var.bstrVal = SysAllocString( T2W(szSaveFile) ); // Will use Win32 file command hr = pComp->m_cpTextDoc->Save( &Var, tomCreateAlways, 1200 ); hr &= ~0x40000; // Mask off bit 18 SysFreeString( Var.bstrVal ); if( SUCCEEDED( hr ) ) { // Set the compiler source file to the newly saved file _tcscpy( pComp->m_szXMLSrcFile, szSaveFile ); } else { _tcscpy( szSaveFile, _T("") ); } // If the text document has been saved if( SUCCEEDED( hr ) ) { pComp->m_cpTextDoc->SetSaved( tomTrue ); } } else { hr = E_FAIL; } return hr; } /**************************************************************************** * CCompiler::Compile * *---------------------------* * Description: * Handles compiling the text in the editor. This function calls CCompiler::EnterIdle * to do the actual compiling. ***************************************************************** Leonro ****/ HRESULT CCompiler::Compile( HWND hWnd, TCHAR* szSaveFileName, TCHAR* szTitle, CCompiler* pComp ) { HRESULT hr = S_OK; long lSaved = 0; // reset errors pComp->m_hrWorstError = 0; // Save file first if it has not been saved hr = pComp->m_cpTextDoc->GetSaved( &lSaved ); if( lSaved == tomFalse && SUCCEEDED( hr ) ) { // TOM save file hr = FileSave( hWnd, pComp, szSaveFileName ); if( hr == STG_E_ACCESSDENIED ) // Handle read only files { MessageBox( pComp->m_hWndEdit, _T("This file exists with Read Only attributes.\n Please use a different file name."), _T("File Save"), MB_OK ); // Call FileSave again but this time pop the save file dialog box hr = FileSave( hWnd, pComp, szSaveFileName ); } // Add the file name to the title bar if( SUCCEEDED( hr ) ) { LoadString( pComp->m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); _tcscat( szTitle, _T(" - [") ); _tcscat( szTitle, szSaveFileName ); _tcscat( szTitle, _T("]") ); SetWindowText( hWnd, szTitle ); } } // If everything has succeeded but there is no source text in the editor // set hr to InvalidArg if( SUCCEEDED( hr ) && !*pComp->m_szXMLSrcFile ) { hr = E_INVALIDARG; } // Clear out the listbox of any previous errors ::SendMessage( m_hWndStatus, LB_RESETCONTENT, 0, 0 ); // Set up the compiler and do it if( SUCCEEDED( hr ) ) { // construct name from m_szXMLSrcFile _tcscpy(pComp->m_szCFGDestFile, pComp->m_szXMLSrcFile); _tcscpy(&pComp->m_szCFGDestFile[strlen(pComp->m_szCFGDestFile) -3], _T("cfg")); // update text in Status Window TCHAR sz[MAX_PATH]; TCHAR *pszOutput = new TCHAR[ sp_countof(sz) + _tcslen( pComp->m_szXMLSrcFile ) ]; if ( pszOutput ) { LoadString( m_hInstance, IDS_COMPFILE, sz, sp_countof(sz) ); wsprintf( pszOutput, sz, pComp->m_szXMLSrcFile ); ::SendMessage( m_hWndStatus, LB_INSERTSTRING, 0, (LPARAM) pszOutput ); // Size the listbox HDC hdc = ::GetDC( m_hWndStatus ); SIZE size; ::GetTextExtentPoint32( hdc, pszOutput, _tcslen( pszOutput ), &size ); ::ReleaseDC( m_hWndStatus, hdc ); ::SendMessage( m_hWndStatus, LB_SETHORIZONTALEXTENT, size.cx, 0 ); delete[] pszOutput; } // call the actual compile step pComp->EnterIdle(); // repaint InvalidateRect( hWnd, NULL, FALSE ); // Check for compile errors hr = pComp->m_hrWorstError; if( FAILED( hr ) ) { pComp->m_fNeedStartCompile = TRUE; } else { pComp->m_fNeedStartCompile = FALSE; } } return hr; } /**************************************************************************** * CCompiler::RecoEvent * *---------------------------* * Description: * Helper function that handles speech events **************************************************************** Leonro *****/ void CCompiler::RecoEvent( HWND hDlg, CCompiler* pComp ) { USES_CONVERSION; HRESULT hr=S_OK; CSpEvent event; long iNewPhrase=0; static BOOL fStartSound = FALSE; if( pComp->m_cpRecoContext ) { while( event.GetFrom(pComp->m_cpRecoContext) == S_OK ) { // Switch on recognition event switch( event.eEventId ) { case SPEI_SOUND_START: fStartSound = TRUE; m_dstr = L""; break; case SPEI_SOUND_END: if( fStartSound ) { fStartSound = FALSE; if( !pComp->m_fGotReco ) { CSpDynamicString dstrText = L""; TCHAR* szUnRecoString = W2T( dstrText.m_psz ); iNewPhrase = SendDlgItemMessage( hDlg, IDC_LIST_PHRASES, LB_ADDSTRING, 0, (LPARAM)szUnRecoString ); SendDlgItemMessage( hDlg, IDC_LIST_PHRASES, LB_SETCURSEL, iNewPhrase, 0); } pComp->m_fGotReco = FALSE; } break; case SPEI_FALSE_RECOGNITION: ::SendMessage( GetDlgItem(hDlg, IDC_LIST_PHRASES), WM_SETTEXT, 0, (LPARAM)""); break; case SPEI_RECOGNITION: case SPEI_HYPOTHESIS: Recognize( hDlg, *pComp, event ); break; } } } } /**************************************************************************** * CCompiler::Recognize * *----------------------* * Description: * Helper function that handles recognition events *************************************************************** MarkNik *****/ void CCompiler::Recognize( HWND hDlg, CCompiler &rComp, CSpEvent &rEvent ) { USES_CONVERSION; CComPtr cpResult; cpResult = rEvent.RecoResult(); HRESULT hr = S_OK; long iNewPhrase=0; rComp.m_fGotReco = TRUE; CSpDynamicString dstrText; SPPHRASE *pElements; if( SUCCEEDED( cpResult->GetPhrase( &pElements ) ) ) { _ASSERT(pElements->ullGrammarID == GRAM_ID); TCHAR szText[256]; HWND hwndEdit = GetDlgItem(hDlg, IDC_LIST_PHRASES); ULONG CurrentLen = ::SendMessage( hwndEdit, WM_GETTEXTLENGTH, 0, 0 ); if( SPEI_RECOGNITION == rEvent.eEventId ) { m_dstr.Append( L"------------- Recognition Event: ------------- \r\n\r\n" ); } else if ( SPEI_HYPOTHESIS == rEvent.eEventId ) { m_dstr.Append( L"------------- Hypothesis Event: ------------- \r\n\r\n" ); } else { m_dstr.Append( L"Unknown Event...:\r\n\r\n" ); } if (pElements->Rule.pszName || pElements->Rule.ulId) { wsprintf(szText, "RULE=\"%s\" (%05d)\r\n", W2T(pElements->Rule.pszName), pElements->Rule.ulId); m_dstr.Append( T2W(szText) ); hr = cpResult->GetText( SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL ); if( SUCCEEDED( hr ) ) { m_dstr.Append( dstrText ); } else { m_dstr.Append( L"" ); } } else { m_dstr = L"DICTATION\r\n"; CSpDynamicString dstrText; hr = cpResult->GetText( SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL ); if( SUCCEEDED( hr ) ) { m_dstr.Append( dstrText ); } else { m_dstr.Append( L"" ); } } m_dstr.Append(L"\r\n"); if (pElements->pProperties) { m_dstr.Append(L"\r\nPROPERTIES:\r\n"); ConstructPropertyDisplay(pElements->pElements, pElements->pProperties, m_dstr, 0); } m_dstr.Append(L"\r\nPARSE TREE:\r\n"); ConstructRuleDisplay(&pElements->Rule, m_dstr, 0); m_dstr.Append(L"\r\nELEMENTS:\r\n"); for (ULONG i = 0; i < pElements->Rule.ulCountOfElements; i++) { wsprintf(szText, " <%u - %u> \"%s\" %c(%c)\r\n", pElements->pElements[i].ulAudioStreamOffset, pElements->pElements[i].ulAudioStreamOffset + pElements->pElements[i].ulAudioSizeBytes, W2T(pElements->pElements[i].pszDisplayText), ConfidenceGroupChar(pElements->pElements[i].ActualConfidence), ConfidenceGroupChar(pElements->pElements[i].RequiredConfidence)); m_dstr.Append(T2W(szText)); } m_dstr.Append( L"\r\n\r\n" ); ::SendMessage( hwndEdit, WM_SETTEXT, 0, (LPARAM)W2T(m_dstr)); ::CoTaskMemFree(pElements); } else { ::SendMessage( GetDlgItem(hDlg, IDC_LIST_PHRASES), WM_SETTEXT, 0, (LPARAM)""); } } /**************************************************************************** * CCompiler::EmulateRecognition * *-----------------------------------* * Description: * Allows users to input text to emmulate recognition * ***************************************************************** PhilSch ***/ HRESULT CCompiler::EmulateRecognition(WCHAR *pszText) { HRESULT hr = S_OK; // Get local info SPRECOGNIZERSTATUS stat; LANGID LangID; ZeroMemory(&stat, sizeof(stat)); m_cpRecognizer->GetStatus(&stat); LangID = stat.aLangID[0]; CComPtr cpPhrase; if (SUCCEEDED(CreatePhraseFromText(pszText, &cpPhrase, LangID)) && m_cpRecognizer) { return( m_cpRecognizer->EmulateRecognition(cpPhrase) ); } return S_FALSE; } /* MEMBER FUNCTIONS FOR THE COMMAND LINE VERSION OF THE APPLICATION ONLY*/ /**************************************************************************** * CCompiler::InitDialog * *---------------------------* * Description: * Initializes the command line version of the compile status dialog box *****************************************************************************/ BOOL CCompiler::InitDialog(HWND hDlg) { m_hDlg = hDlg; TCHAR sz[MAX_PATH]; ::LoadString(m_hInstance, IDS_COMPFILE, sz, sp_countof(sz)); TCHAR szTitle[MAX_PATH]; wsprintf(szTitle, sz, m_szXMLSrcFile); ::SendDlgItemMessage(hDlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szTitle); return TRUE; } /**************************************************************************** * CCompiler::DialogProc * *---------------------------* * Description: * Message handler for command line version of dialog box *****************************************************************************/ int CALLBACK CCompiler::DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { CCompiler * pThis = (CCompiler *)::GetWindowLong(hDlg, GWL_USERDATA); switch (message) { case WM_INITDIALOG: ::SetWindowLong(hDlg, GWL_USERDATA, lParam); pThis = (CCompiler *)lParam; return pThis->InitDialog(hDlg); //1 case WM_PAINT: if (pThis->m_fNeedStartCompile) { ::PostMessage(hDlg, WM_APP, 0, 0); } break; case WM_APP: pThis->EnterIdle(); return TRUE; case WM_COMMAND: { if (LOWORD(wParam) == IDOK) { EndDialog(hDlg, 0); return TRUE; } } break; } return FALSE; } /**************************************************************************** * CError::AddError * *------------------* * Description: * * Returns: * ***************************************************************** PhilSch ***/ HRESULT CError::AddError(const long lLine, HRESULT hr, const WCHAR * pszDescription, const WCHAR * pszHelpFile, DWORD dwHelpContext) { SPDBG_FUNC("CError::AddError"); USES_CONVERSION; ATLTRACE(L"%s(%d) : %s\n", T2W(m_pszFileName), lLine, pszDescription); return S_OK; } /**************************************************************************** * CError::Init * *--------------* * Description: * * Returns: * ***************************************************************** PhilSch ***/ HRESULT CError::Init(const char *pszFileName) { SPDBG_FUNC("CError::Init"); m_pszFileName = pszFileName; return S_OK; } /**************************************************************************** * CRecoDlgClass::ConstructPropertyDisplay * *-----------------------------------------* * Description: * * Returns: * ***************************************************************** PhilSch ***/ HRESULT CCompiler::ConstructPropertyDisplay(const SPPHRASEELEMENT *pElem, const SPPHRASEPROPERTY *pProp, CSpDynamicString & dstr, ULONG ulLevel) { SPDBG_FUNC("CRecoDlgClass::ConstructPropertyDisplay"); HRESULT hr = S_OK; USES_CONVERSION; TCHAR szText[256]; // constrcut indent while(SUCCEEDED(hr) && pProp) { wsprintf(szText, " [%2d, %2d] ", pProp->ulFirstElement, pProp->ulFirstElement + pProp->ulCountOfElements); for (ULONG i = 0; i < ulLevel; i++) { dstr.Append(L"\t"); } if (pProp->pszName) { if (wcslen(pProp->pszName) > 240) { dstr.Append(L"\"(Rule name too long)\" = \""); } else { wsprintf(szText, "\"%s\" = \"", W2T(pProp->pszName)); dstr.Append(T2W(szText)); } } else { dstr.Append(L"\"(UNK)\" = \""); } if (!pProp->pszValue) { // construct the value from the elements! ULONG ulEndElement = pProp->ulFirstElement + pProp->ulCountOfElements; for (ULONG j = pProp->ulFirstElement; j < ulEndElement; j++) { if (j+1 < ulEndElement) { dstr.Append2(pElem[j].pszDisplayText, L" "); } else { dstr.Append(pElem[j].pszDisplayText); } } } else { dstr.Append(pProp->pszValue); } if (pProp->vValue.vt != VT_EMPTY) { CComVariant cv = pProp->vValue; cv.ChangeType(VT_BSTR); wsprintf(szText, "\" (%d = %s)", pProp->ulId, W2T(cv.bstrVal)); } else { wsprintf(szText, "\" (%d)", pProp->ulId); } dstr.Append2(T2W(szText), L"\r\n"); if (pProp->pFirstChild) { hr = ConstructPropertyDisplay(pElem, pProp->pFirstChild, dstr, ulLevel + 1); } pProp = pProp->pNextSibling; } return hr; } /**************************************************************************** * CRecoDlgClass::ConstructRuleDisplay * *-------------------------------------* * Description: * * Returns: * ***************************************************************** PhilSch ***/ HRESULT CCompiler::ConstructRuleDisplay(const SPPHRASERULE *pRule, CSpDynamicString &dstr, ULONG ulLevel) { SPDBG_FUNC("CRecoDlgClass::ConstructRuleDisplay"); HRESULT hr = S_OK; USES_CONVERSION; TCHAR szText[256]; // constrcut indent while(SUCCEEDED(hr) && pRule) { wsprintf(szText, " [%2d, %2d] ", pRule->ulFirstElement, pRule->ulFirstElement + pRule->ulCountOfElements); for (ULONG i = 0; i < ulLevel; i++) { dstr.Append(L"\t"); } if (pRule->pszName) { if (wcslen(pRule->pszName) > 240) { dstr.Append(L"\"(Rule name too long)\" = \""); } else { wsprintf(szText, "%s \"%s\" (%d)", szText, W2T(pRule->pszName), pRule->ulId); dstr.Append(T2W(szText)); } } else { dstr.Append(L"\"(UNK)\" = \""); } dstr.Append(L"\r\n"); if (pRule->pFirstChild) { hr = ConstructRuleDisplay(pRule->pFirstChild, dstr, ulLevel + 1); } pRule = pRule->pNextSibling; } return hr; }