Source code of Windows XP (NT5)
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.

288 lines
7.7 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // TextRules.cpp: implementation of the CTextRules class.
  3. //
  4. // Created by JOEM 04-2000
  5. // Copyright (C) 2000 Microsoft Corporation
  6. // All Rights Reserved
  7. //
  8. /////////////////////////////////////////////////////// JOEM 4-2000 //
  9. #include "stdafx.h"
  10. #include "TextRules.h"
  11. #include "common.h"
  12. #include <comdef.h>
  13. #include <stdio.h>
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CTextRules::CTextRules()
  18. {
  19. m_pIScriptInterp = NULL;
  20. m_pszRuleScript = NULL;
  21. m_pszScriptLanguage = NULL;
  22. m_fActive = false;
  23. }
  24. CTextRules::~CTextRules()
  25. {
  26. if ( m_pIScriptInterp )
  27. {
  28. m_pIScriptInterp->Reset();
  29. m_pIScriptInterp->Release();
  30. m_pIScriptInterp = NULL;
  31. }
  32. if ( m_pszRuleScript )
  33. {
  34. free(m_pszRuleScript);
  35. m_pszRuleScript = NULL;
  36. }
  37. if ( m_pszScriptLanguage )
  38. {
  39. free(m_pszScriptLanguage);
  40. m_pszScriptLanguage = NULL;
  41. }
  42. }
  43. //////////////////////////////////////////////////////////////////////
  44. // CTextRules::ApplyRule
  45. //
  46. // On first execution, creates script interpreter, sets the script
  47. // language, and loads/parses the script.
  48. //
  49. // On first and subsequent calls, checks loaded script for a
  50. // text expansion/normalization rule (pszRuleName), applies the rule
  51. // to pszOriginalText, producing ppszNewText.
  52. //
  53. /////////////////////////////////////////////////////// JOEM 4-2000 //
  54. HRESULT CTextRules::ApplyRule(const WCHAR* pszRuleName, const WCHAR* pszOriginalText, WCHAR** ppszNewText)
  55. {
  56. SPDBG_FUNC( "CTextRules::ApplyRule" );
  57. HRESULT hr = S_OK;
  58. LPSAFEARRAY psaScriptPar = NULL;
  59. _variant_t varNewText;
  60. SPDBG_ASSERT (pszRuleName);
  61. SPDBG_ASSERT (pszOriginalText);
  62. hr = SetInputParam(pszOriginalText, &psaScriptPar);
  63. // IMPORTANT NOTE:
  64. // Script code must be added (AddCode) and used (Run) within the same thread.
  65. // SAPI's LazyInit is a different thread than Speak calls, so AddCode must be
  66. // delayed until the first Run call is needed. Once AddCode has occurred,
  67. // the m_fActive flag is turned on so the code doesn't get added multiple times.
  68. if ( !m_fActive )
  69. {
  70. if ( !m_pszRuleScript || !m_pszScriptLanguage )
  71. {
  72. hr = E_INVALIDARG;
  73. }
  74. // Initialize Script Control
  75. if ( SUCCEEDED(hr) )
  76. {
  77. hr = CoCreateInstance(CLSID_ScriptControl, NULL, CLSCTX_ALL, IID_IScriptControl, (LPVOID *)&m_pIScriptInterp);
  78. }
  79. if ( SUCCEEDED (hr) )
  80. {
  81. hr = m_pIScriptInterp->put_Language( (_bstr_t)m_pszScriptLanguage );
  82. }
  83. if ( SUCCEEDED (hr) )
  84. {
  85. hr = m_pIScriptInterp->AddCode( (_bstr_t)m_pszRuleScript );
  86. }
  87. if ( SUCCEEDED(hr) )
  88. {
  89. m_fActive = true;
  90. if ( m_pszRuleScript )
  91. {
  92. free(m_pszRuleScript);
  93. m_pszRuleScript = NULL;
  94. }
  95. if ( m_pszScriptLanguage )
  96. {
  97. free(m_pszScriptLanguage);
  98. m_pszScriptLanguage = NULL;
  99. }
  100. }
  101. else
  102. {
  103. if ( m_pIScriptInterp )
  104. {
  105. m_pIScriptInterp->Reset();
  106. m_pIScriptInterp->Release();
  107. m_pIScriptInterp = NULL;
  108. }
  109. }
  110. }
  111. if ( SUCCEEDED(hr) )
  112. {
  113. hr = m_pIScriptInterp->Run( (_bstr_t)pszRuleName, &psaScriptPar, &varNewText);
  114. }
  115. if ( SUCCEEDED (hr) )
  116. {
  117. if ( varNewText.vt == VT_EMPTY )
  118. {
  119. hr = E_UNEXPECTED;
  120. }
  121. }
  122. if ( SUCCEEDED(hr) )
  123. {
  124. *ppszNewText = wcsdup( (wchar_t*) ( (_bstr_t)varNewText ) );
  125. if ( !*ppszNewText )
  126. {
  127. hr = E_OUTOFMEMORY;
  128. }
  129. }
  130. if ( psaScriptPar )
  131. {
  132. SafeArrayDestroy(psaScriptPar);
  133. psaScriptPar = NULL;
  134. }
  135. SPDBG_REPORT_ON_FAIL( hr );
  136. return hr;
  137. }
  138. //////////////////////////////////////////////////////////////////////
  139. // CTextRules::SetInputParam
  140. //
  141. // Builds a SafeArray input parameter for the script engine,
  142. // out of the text to be modified.
  143. //
  144. /////////////////////////////////////////////////////// JOEM 4-2000 //
  145. HRESULT CTextRules::SetInputParam(const WCHAR *pswzTextParam, LPSAFEARRAY *ppsaScriptPar)
  146. {
  147. SPDBG_FUNC( "CTextRules::SetInputParam" );
  148. HRESULT hr = S_OK;
  149. VARIANT vFlavors[1];
  150. long lZero = 0;
  151. int i = 0;
  152. SAFEARRAYBOUND rgsabound[] = {1, 0}; // 1 element, 0 - base start
  153. *ppsaScriptPar = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  154. if (! *ppsaScriptPar)
  155. {
  156. hr = E_FAIL;
  157. }
  158. if ( SUCCEEDED(hr) )
  159. {
  160. VariantInit(&vFlavors[0]);
  161. V_VT(&vFlavors[0]) = VT_BSTR;
  162. V_BSTR(&vFlavors[0]) = SysAllocString( (_bstr_t)pswzTextParam );
  163. hr = SafeArrayPutElement(*ppsaScriptPar, &lZero, &vFlavors[0]);
  164. if ( FAILED(hr) )
  165. {
  166. SafeArrayDestroy(*ppsaScriptPar);
  167. *ppsaScriptPar = NULL;
  168. }
  169. SysFreeString(vFlavors[0].bstrVal);
  170. }
  171. SPDBG_REPORT_ON_FAIL( hr );
  172. return hr;
  173. }
  174. //////////////////////////////////////////////////////////////////////
  175. // CTextRules::ReadRules
  176. //
  177. // Reads in the script from the script file. Sets the script language.
  178. //
  179. /////////////////////////////////////////////////////// JOEM 4-2000 //
  180. HRESULT CTextRules::ReadRules(const WCHAR* pszScriptLanguage, const WCHAR *pszPath)
  181. {
  182. SPDBG_FUNC( "CTextRules::ReadRules" );
  183. HRESULT hr = S_OK;
  184. FILE* phRuleFile = NULL;
  185. LONG ret = 0;
  186. // Open the rule file and read in the script
  187. phRuleFile = _wfopen(pszPath, L"r");
  188. if ( phRuleFile == NULL )
  189. {
  190. hr = E_ACCESSDENIED;
  191. }
  192. if ( SUCCEEDED(hr) )
  193. {
  194. fseek(phRuleFile, 0L, SEEK_SET);
  195. LONG start = ftell(phRuleFile);
  196. fseek(phRuleFile, 0L, SEEK_END);
  197. LONG end = ftell(phRuleFile);
  198. rewind(phRuleFile);
  199. LONG len = end - start;
  200. // allocate len (bytes) plus an extra char for a NULL char
  201. m_pszRuleScript = (char*) malloc( len + sizeof(char) );
  202. if ( !m_pszRuleScript )
  203. {
  204. hr = E_OUTOFMEMORY;
  205. }
  206. if ( SUCCEEDED (hr) )
  207. {
  208. ret = fread(m_pszRuleScript, sizeof(char), len, phRuleFile);
  209. if ( ftell(phRuleFile) != end )
  210. {
  211. hr = E_ABORT;
  212. }
  213. }
  214. if ( SUCCEEDED (hr) )
  215. {
  216. m_pszRuleScript[ret] = '\0';
  217. }
  218. fclose(phRuleFile);
  219. }
  220. if ( SUCCEEDED(hr) )
  221. {
  222. m_pszScriptLanguage = wcsdup(pszScriptLanguage);
  223. if ( !m_pszScriptLanguage )
  224. {
  225. hr = E_OUTOFMEMORY;
  226. }
  227. }
  228. // Create the script interpreter and add code. This is to check
  229. // that the code is valid. Later, ApplyRule will add the code again,
  230. // because script code must be added and used within the same thread.
  231. // (SAPI's LazyInit is a different thread than Speak).
  232. if ( SUCCEEDED(hr) )
  233. {
  234. hr = CoCreateInstance(CLSID_ScriptControl, NULL, CLSCTX_ALL, IID_IScriptControl, (LPVOID *)&m_pIScriptInterp);
  235. }
  236. if ( SUCCEEDED(hr) )
  237. {
  238. hr = m_pIScriptInterp->put_Language( (_bstr_t)m_pszScriptLanguage );
  239. if ( SUCCEEDED (hr) )
  240. {
  241. hr = m_pIScriptInterp->AddCode( (_bstr_t)m_pszRuleScript );
  242. }
  243. // Release immediately, since this Instance is useless in this thread.
  244. m_pIScriptInterp->Release();
  245. m_pIScriptInterp = NULL;
  246. }
  247. SPDBG_REPORT_ON_FAIL( hr );
  248. return hr;
  249. }