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.

557 lines
18 KiB

  1. /////////////////////////////////////////////////////////
  2. // TestITN_CHS.cpp : Implementation of CTestITN_CHS
  3. //
  4. // ITN Interpretor for Simplified Chinese:
  5. //
  6. // Integer,
  7. // Decimal,
  8. // Percent,
  9. // Ratio,
  10. // Fraction,
  11. // Minus number,
  12. // Time
  13. //
  14. /////////////////////////////////////////////////////////
  15. #include "stdafx.h"
  16. #include "Itngram_CHS.h"
  17. #include "TestITN_CHS.h"
  18. #include "sphelper.h"
  19. #include "test_CHS.h"
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CTestITN_CHS
  22. /****************************************************************************
  23. * CTestITN_CHS::InitGrammar *
  24. *-------------------------*
  25. * Description:
  26. *
  27. * Returns:
  28. *
  29. ********************************************************************* RAL ***/
  30. STDMETHODIMP CTestITN_CHS::InitGrammar(const WCHAR * pszGrammarName, const void ** pvGrammarData)
  31. {
  32. HRESULT hr = S_OK;
  33. HRSRC hResInfo = ::FindResource(_Module.GetModuleInstance(), _T("TEST"), _T("ITNGRAMMAR"));
  34. if (hResInfo)
  35. {
  36. HGLOBAL hData = ::LoadResource(_Module.GetModuleInstance(), hResInfo);
  37. if (hData)
  38. {
  39. *pvGrammarData = ::LockResource(hData);
  40. if (*pvGrammarData == NULL)
  41. {
  42. hr = HRESULT_FROM_WIN32(::GetLastError());
  43. }
  44. }
  45. else
  46. {
  47. hr = HRESULT_FROM_WIN32(::GetLastError());
  48. }
  49. }
  50. else
  51. {
  52. hr = HRESULT_FROM_WIN32(::GetLastError());
  53. }
  54. return hr;
  55. }
  56. /****************************************************************************
  57. * CTestITN_CHS::Interpret *
  58. *-----------------------*
  59. * Description:
  60. *
  61. * Returns:
  62. *
  63. ********************************************************************* RAL ***/
  64. class CSpPhrasePtrTemp : public CSpPhrasePtr
  65. {
  66. public:
  67. const WCHAR * TextValueOfId(ULONG IdProp);
  68. const double DoubleValueOfId(ULONG IdProp);
  69. const ULONGLONG ULongLongValueOfId(ULONG IdProp);
  70. HRESULT ElementInfoOfId(ULONG IdProp, ULONG *pulFirstElement, ULONG *pulCountOfElements);
  71. private:
  72. const SPPHRASEPROPERTY * FindPropertyById(ULONG IdProp);
  73. const SPPHRASEPROPERTY * FindPropertyByIdHelper(ULONG IdProp, const SPPHRASEPROPERTY *);
  74. };
  75. const WCHAR * CSpPhrasePtrTemp::TextValueOfId(ULONG IdProp)
  76. {
  77. _ASSERT(m_pPhrase);
  78. SPDBG_ASSERT(m_pPhrase);
  79. const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
  80. return pProp ? pProp->pszValue : NULL;
  81. }
  82. const double CSpPhrasePtrTemp::DoubleValueOfId(ULONG IdProp)
  83. {
  84. SPDBG_ASSERT(m_pPhrase);
  85. const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
  86. return pProp ? pProp->vValue.dblVal : 0;
  87. }
  88. const ULONGLONG CSpPhrasePtrTemp::ULongLongValueOfId(ULONG IdProp)
  89. {
  90. SPDBG_ASSERT(m_pPhrase);
  91. const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
  92. return pProp ? pProp->vValue.ulVal : 0;
  93. }
  94. HRESULT CSpPhrasePtrTemp::ElementInfoOfId(ULONG IdProp, ULONG *pulFirstElement, ULONG *pulCountOfElements)
  95. {
  96. _ASSERT(m_pPhrase);
  97. SPDBG_ASSERT(m_pPhrase);
  98. const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
  99. if (pProp)
  100. {
  101. *pulFirstElement = pProp->ulFirstElement;
  102. *pulCountOfElements = pProp->ulCountOfElements;
  103. }
  104. else
  105. {
  106. *pulFirstElement = *pulCountOfElements = 0;
  107. }
  108. return pProp ? S_OK : E_FAIL;
  109. }
  110. const SPPHRASEPROPERTY * CSpPhrasePtrTemp::FindPropertyById(const ULONG IdProp)
  111. {
  112. return FindPropertyByIdHelper(IdProp, m_pPhrase->pProperties);
  113. }
  114. const SPPHRASEPROPERTY * CSpPhrasePtrTemp::FindPropertyByIdHelper(ULONG IdProp, const SPPHRASEPROPERTY * pProp)
  115. {
  116. const SPPHRASEPROPERTY * pRet = NULL;
  117. if (pProp->ulId == IdProp)
  118. {
  119. pRet = pProp;
  120. }
  121. else
  122. {
  123. if (pProp->pFirstChild)
  124. {
  125. pRet = FindPropertyByIdHelper(IdProp, pProp->pFirstChild);
  126. }
  127. if (!pRet && pProp->pNextSibling)
  128. {
  129. pRet = FindPropertyByIdHelper(IdProp, pProp->pNextSibling);
  130. }
  131. }
  132. return pRet;
  133. }
  134. // assume that we have only THOUSANDS(qian), HUNDREDS(bai), TENS(shi), and ONES(ge) here!!
  135. HRESULT ComputeNum9999(const SPPHRASEPROPERTY *pProperties, __int64 *pVal, ULONG *pulLength)
  136. {
  137. ULONG ulVal = 0;
  138. if (pProperties->pFirstChild)
  139. {
  140. for (const SPPHRASEPROPERTY * pProp = pProperties; pProp; pProp = pProp->pNextSibling)
  141. {
  142. if ( 0 != pProp->ulId )
  143. {
  144. SPDBG_ASSERT( pProp->pFirstChild );
  145. SPDBG_ASSERT( VT_UI4 == pProp->vValue.vt );
  146. SPDBG_ASSERT( VT_UI4 == pProp->pFirstChild->vValue.vt );
  147. ulVal += pProp->pFirstChild->vValue.ulVal * pProp->vValue.ulVal;
  148. }
  149. }
  150. }
  151. *pVal = ulVal;
  152. return S_OK;
  153. }
  154. HRESULT ComputeNum10000(const SPPHRASEPROPERTY *pProperties, __int64 *pVal, ULONG *pulLength)
  155. {
  156. HRESULT hr = S_OK;
  157. *pVal = 0;
  158. *pulLength = 0;
  159. WCHAR * pszStopped;
  160. ULONG v2 = wcstol(pProperties->pszValue, &pszStopped, 10);
  161. *pVal += v2;
  162. return hr;
  163. }
  164. /***********************************************************************
  165. * GetMinAndMaxPos *
  166. *-----------------*
  167. * Description:
  168. * Gets the minimum and maximum elements spanned by the
  169. * set of properties
  170. *************************************************************************/
  171. void GetMinAndMaxPos( const SPPHRASEPROPERTY *pProperties,
  172. ULONG *pulMinPos,
  173. ULONG *pulMaxPos )
  174. {
  175. if ( !pulMinPos || !pulMaxPos )
  176. {
  177. return;
  178. }
  179. ULONG ulMin = 9999999;
  180. ULONG ulMax = 0;
  181. for ( const SPPHRASEPROPERTY *pProp = pProperties; pProp; pProp = pProp->pNextSibling )
  182. {
  183. ulMin = __min( ulMin, pProp->ulFirstElement );
  184. ulMax = __max( ulMax, pProp->ulFirstElement + pProp->ulCountOfElements );
  185. }
  186. *pulMinPos = ulMin;
  187. *pulMaxPos = ulMax;
  188. } /* GetMinAndMaxPos */
  189. HRESULT FormatOutput(WCHAR *pBuffer, __int64 Value)
  190. {
  191. swprintf(pBuffer, L"%I64d", Value);
  192. if (Value < 0)
  193. pBuffer++; // keep the '-', replace the rest
  194. int l = wcslen(pBuffer);
  195. if (l<=3)
  196. return S_OK;
  197. int head = l%3;
  198. int block = l/3;
  199. WCHAR buf[100];
  200. wcscpy(buf, pBuffer);
  201. pBuffer[0] = 0;
  202. if (head)
  203. {
  204. wcsncat(pBuffer, buf, head);
  205. pBuffer[head] = 0;
  206. wcscat(pBuffer, L",");
  207. }
  208. for (int i=0; i<block; i++)
  209. {
  210. wcsncat(pBuffer, buf+i*3+head, 3);
  211. if (i<block-1)
  212. wcscat(pBuffer, L",");
  213. }
  214. return S_OK;
  215. }
  216. STDMETHODIMP CTestITN_CHS::Interpret(ISpPhraseBuilder * pPhrase, const ULONG ulFirstElement, const ULONG ulCountOfElements, ISpCFGInterpreterSite * pSite)
  217. {
  218. HRESULT hr = S_OK;
  219. ULONG ulRuleId = 0;
  220. CSpPhrasePtrTemp cpPhrase;
  221. WCHAR szBuff[MAX_PATH], szBuff2[MAX_PATH]; /* pwch;*/
  222. szBuff[0] = 0;
  223. szBuff2[0] = 0;
  224. hr = pPhrase->GetPhrase(&cpPhrase);
  225. m_pSite = pSite;
  226. ULONG ulMinPos;
  227. ULONG ulMaxPos;
  228. GetMinAndMaxPos( cpPhrase->pProperties, &ulMinPos, &ulMaxPos );
  229. if (SUCCEEDED(hr))
  230. {
  231. switch (cpPhrase->Rule.ulId)
  232. {
  233. case GRID_NUMBER: // Number
  234. {
  235. __int64 ulValue = 0;
  236. ULONG ulLength = 0;
  237. //ULONG ulMinPos = 999999999;
  238. //ULONG ulMaxPos = 0;
  239. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp ? pProp = pProp->pNextSibling : NULL)
  240. {
  241. switch(pProp->ulId)
  242. {
  243. case TENTHOUSANDS_:
  244. {
  245. __int64 v1 = 0;
  246. _ASSERT(pProp);
  247. SPDBG_ASSERT(pProp);
  248. hr = ComputeNum10000(pProp, &v1, &ulLength);
  249. if (SUCCEEDED(hr))
  250. {
  251. ulValue += v1 * 10000;
  252. }
  253. }
  254. break;
  255. case TENTHOUSANDS:
  256. {
  257. __int64 v1 = 0;
  258. _ASSERT(pProp->pFirstChild);
  259. SPDBG_ASSERT(pProp->pFirstChild);
  260. hr = ComputeNum9999(pProp->pFirstChild, &v1, &ulLength);
  261. if (SUCCEEDED(hr))
  262. {
  263. ulValue += v1 * 10000;
  264. }
  265. }
  266. break;
  267. case HUNDREDMILLIONS:
  268. {
  269. __int64 v1 = 0;
  270. _ASSERT(pProp->pFirstChild);
  271. SPDBG_ASSERT(pProp->pFirstChild);
  272. hr = ComputeNum9999(pProp->pFirstChild, &v1, &ulLength);
  273. if (SUCCEEDED(hr))
  274. {
  275. ulValue += v1 * 100000000;
  276. }
  277. }
  278. break;
  279. case ONES:
  280. {
  281. __int64 v1 = 0;
  282. SPDBG_ASSERT(pProp->pFirstChild);
  283. hr = ComputeNum9999(pProp->pFirstChild, &v1, &ulLength);
  284. if (SUCCEEDED(hr))
  285. {
  286. ulValue += v1;
  287. pProp = NULL;
  288. }
  289. }
  290. break;
  291. case ONES_THOUSANDS:
  292. {
  293. SPDBG_ASSERT(pProp->pFirstChild);
  294. ulValue += pProp->pFirstChild->vValue.ulVal;
  295. pProp = NULL;
  296. }
  297. break;
  298. case THOUSANDS:
  299. case HUNDREDS:
  300. default:
  301. _ASSERT(false);
  302. SPDBG_ASSERT(false);
  303. }
  304. }
  305. ATLTRACE(L"GRID_NUMBER: %d\t(%d + %d)\n", ulValue, ulMinPos, ulMaxPos - ulMinPos);
  306. FormatOutput(szBuff, ulValue);
  307. }
  308. break;
  309. case GRID_DECIMAL:
  310. {
  311. szBuff2[0] = 0;
  312. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
  313. {
  314. switch (pProp->ulId)
  315. {
  316. case INTEGER:
  317. {
  318. wcscpy(szBuff, pProp->pszValue);
  319. wcscat(szBuff, L".");
  320. }
  321. break;
  322. default:
  323. {
  324. wcscat(szBuff2, pProp->pszValue);
  325. }
  326. break;
  327. }
  328. }
  329. ATLTRACE(L"GRID_DECIMAL");
  330. wcscat(szBuff, szBuff2);
  331. }
  332. break;
  333. case PERCENT:
  334. {
  335. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
  336. {
  337. switch (pProp->ulId)
  338. {
  339. case DECIMAL:
  340. case INTEGER:
  341. {
  342. wcscpy(szBuff, pProp->pszValue);
  343. wcscat(szBuff, L"%");
  344. }
  345. break;
  346. default:
  347. break;
  348. }
  349. }
  350. ATLTRACE(L"PERCENT");
  351. }
  352. break;
  353. case PERCENT100:
  354. {
  355. ATLTRACE(L"PERCENT100");
  356. wcscpy(szBuff, L"100%");
  357. }
  358. break;
  359. case RATIO:
  360. {
  361. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
  362. {
  363. switch (pProp->ulId)
  364. {
  365. case RATIO1:
  366. wcscpy(szBuff, pProp->pszValue);
  367. break;
  368. case RATIO2:
  369. wcscpy(szBuff2, pProp->pszValue);
  370. break;
  371. default:
  372. break;
  373. }
  374. }
  375. ATLTRACE(L"RATIO");
  376. wcscat(szBuff, L":");
  377. wcscat(szBuff, szBuff2);
  378. }
  379. break;
  380. case FRACTION:
  381. {
  382. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
  383. {
  384. switch (pProp->ulId)
  385. {
  386. case DENOMINATOR:
  387. wcscpy(szBuff2, pProp->pszValue);
  388. break;
  389. case NUMERATOR:
  390. wcscpy(szBuff, pProp->pszValue);
  391. break;
  392. default:
  393. break;
  394. }
  395. }
  396. ATLTRACE(L"FRACTION");
  397. wcscat(szBuff, L"/");
  398. wcscat(szBuff, szBuff2);
  399. }
  400. break;
  401. case GRID_NUMBER_MINUS:
  402. {
  403. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
  404. {
  405. switch (pProp->ulId)
  406. {
  407. case POS_OF_MINUS:
  408. wcscpy(szBuff2, pProp->pszValue);
  409. break;
  410. default:
  411. break;
  412. }
  413. }
  414. ATLTRACE(L"GRID_NUMBER_MINUS");
  415. wcscpy(szBuff, L"-");
  416. wcscat(szBuff, szBuff2);
  417. }
  418. break;
  419. case TIME:
  420. {
  421. for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
  422. {
  423. switch (pProp->ulId)
  424. {
  425. case HOUR:
  426. wcscpy(szBuff, pProp->pszValue);
  427. break;
  428. case MINUTE:
  429. wcscpy(szBuff2, pProp->pszValue);
  430. break;
  431. default:
  432. break;
  433. }
  434. }
  435. ATLTRACE(L"TIME");
  436. wcscat(szBuff, L":");
  437. wcscat(szBuff, szBuff2);
  438. }
  439. break;
  440. default:
  441. _ASSERT(FALSE);
  442. break;
  443. }
  444. hr = AddPropertyAndReplacement( szBuff, 0,
  445. ulMinPos, ulMaxPos, ulMinPos, ulMaxPos - ulMinPos );//ulFirstElement, ulCountOfElements );
  446. }
  447. return hr;
  448. }
  449. /***********************************************************************
  450. * CTestITN_CHS::AddPropertyAndReplacement *
  451. *---------------------------------------*
  452. * Description:
  453. * Takes all of the info that we want to pass into the
  454. * engine site, forms the SPPHRASEPROPERTY and
  455. * SPPHRASERREPLACEMENT, and adds them to the engine site
  456. * Return:
  457. * Return values of ISpCFGInterpreterSite::AddProperty()
  458. * and ISpCFGInterpreterSite::AddTextReplacement()
  459. *************************************************************************/
  460. HRESULT CTestITN_CHS::AddPropertyAndReplacement( const WCHAR *szBuff,
  461. const DOUBLE dblValue,
  462. const ULONG ulMinPos,
  463. const ULONG ulMaxPos,
  464. const ULONG ulFirstElement,
  465. const ULONG ulCountOfElements )
  466. {
  467. // Add the property
  468. SPPHRASEPROPERTY prop;
  469. memset(&prop,0,sizeof(prop));
  470. prop.pszValue = szBuff;
  471. prop.vValue.vt = VT_R8;
  472. prop.vValue.dblVal = dblValue;
  473. prop.ulFirstElement = ulMinPos;
  474. prop.ulCountOfElements = ulMaxPos - ulMinPos;
  475. HRESULT hr = m_pSite->AddProperty(&prop);
  476. if (SUCCEEDED(hr))
  477. {
  478. SPPHRASEREPLACEMENT repl;
  479. memset(&repl,0, sizeof(repl));
  480. //repl.bDisplayAttributes = SPAF_ONE_TRAILING_SPACE;
  481. // No space after the ITNed string in Chinese
  482. repl.bDisplayAttributes = 0;
  483. repl.pszReplacementText = szBuff;
  484. repl.ulFirstElement = ulFirstElement;
  485. repl.ulCountOfElements = ulCountOfElements;
  486. hr = m_pSite->AddTextReplacement(&repl);
  487. }
  488. return hr;
  489. } /* CTestITN_CHS::AddPropertyAndReplacement */