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.

2335 lines
97 KiB

  1. #include "stdafx.h"
  2. #ifndef StdSentEnum_h
  3. #include "stdsentenum.h"
  4. #endif
  5. #pragma warning (disable : 4296)
  6. /***********************************************************************************************
  7. * IsNumericCompactDate *
  8. *----------------------*
  9. * Description:
  10. * Checks the incoming Item's text to determine whether or not it
  11. * is a Date, and if so, which type.
  12. *
  13. * RegExp:
  14. * {[1-12]{'/' || '-' || '.'}[1-31]{'/' || '-' || '.'}[0-9999]} ||
  15. * {[1-31]{'/' || '-' || '.'}[1-12]{'/' || '-' || '.'}[0-9999]} ||
  16. * {[0-9999]{'/' || '-' || '.'}[1-12]{'/' || '-' || '.'}[1-31]}
  17. *
  18. * Types assigned:
  19. * Date
  20. ********************************************************************* AH **********************/
  21. HRESULT CStdSentEnum::IsNumericCompactDate( TTSItemInfo*& pItemNormInfo, const WCHAR* Context,
  22. CSentItemMemory& MemoryManager )
  23. {
  24. SPDBG_FUNC( "CStdSentEnum::IsNumericCompactDate" );
  25. HRESULT hr = S_OK;
  26. WCHAR *pFirstChunk = 0, *pSecondChunk = 0, *pThirdChunk = 0, *pLeftOver = 0, *pDelimiter = 0;
  27. ULONG ulFirst = 0;
  28. ULONG ulSecond = 0;
  29. ULONG ulThird = 0;
  30. ULONG ulTokenLen = (ULONG)(m_pEndOfCurrItem - m_pNextChar);
  31. bool bThree = false, bTwo = false;
  32. bool fMonthDayYear = false, fDayMonthYear = false, fYearMonthDay = false;
  33. //--- Max length of a string matching the regexp is 10 characters
  34. if ( ulTokenLen > 10 )
  35. {
  36. hr = E_INVALIDARG;
  37. }
  38. else
  39. {
  40. //--- Get the preferred order of the compact Date
  41. if ( Context != NULL )
  42. {
  43. if ( _wcsicmp( Context, L"Date_MDY" ) == 0 )
  44. {
  45. fMonthDayYear = true;
  46. }
  47. else if ( _wcsicmp( Context, L"Date_DMY" ) == 0 )
  48. {
  49. fDayMonthYear = true;
  50. }
  51. else if ( _wcsicmp( Context, L"Date_YMD" ) == 0 )
  52. {
  53. fYearMonthDay = true;
  54. }
  55. else
  56. {
  57. if ( m_eShortDateOrder & MONTH_DAY_YEAR )
  58. {
  59. fMonthDayYear = true;
  60. }
  61. else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
  62. {
  63. fDayMonthYear = true;
  64. }
  65. else
  66. {
  67. fYearMonthDay = true;
  68. }
  69. }
  70. }
  71. else
  72. {
  73. if ( m_eShortDateOrder & MONTH_DAY_YEAR )
  74. {
  75. fMonthDayYear = true;
  76. }
  77. else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
  78. {
  79. fDayMonthYear = true;
  80. }
  81. else
  82. {
  83. fYearMonthDay = true;
  84. }
  85. }
  86. pFirstChunk = (WCHAR*) m_pNextChar;
  87. //----------------------------------------------
  88. // First Try To Get Three Numerical Values
  89. //----------------------------------------------
  90. ulFirst = my_wcstoul( pFirstChunk, &pSecondChunk );
  91. if ( pFirstChunk != pSecondChunk &&
  92. ( pSecondChunk - pFirstChunk ) <= 4 )
  93. {
  94. pDelimiter = pSecondChunk;
  95. if ( MatchDateDelimiter( &pSecondChunk ) )
  96. {
  97. ulSecond = my_wcstoul( pSecondChunk, &pThirdChunk );
  98. if ( pSecondChunk != pThirdChunk &&
  99. ( pThirdChunk - pSecondChunk ) <= 4 )
  100. {
  101. if ( *pThirdChunk == *pDelimiter &&
  102. MatchDateDelimiter( &pThirdChunk ) )
  103. {
  104. ulThird = my_wcstoul( pThirdChunk, &pLeftOver );
  105. if ( pThirdChunk != pLeftOver &&
  106. pLeftOver == ( pFirstChunk + ulTokenLen ) &&
  107. ( pLeftOver - pThirdChunk ) <= 4 )
  108. {
  109. //--- Successfully Matched { d+{'/' || '-' || '.'}d+{'/' || '-' || '.'}d+ }
  110. bThree = true;
  111. }
  112. else
  113. {
  114. //--- Digit-String Delimiter Digit-String Delimiter non-digit cannot be a Date,
  115. //--- nor can Digit-String Delimiter Digit-String Delimiter Digit-String String
  116. hr = E_INVALIDARG;
  117. }
  118. }
  119. else
  120. {
  121. if ( pThirdChunk == m_pEndOfCurrItem )
  122. {
  123. //--- Successfully Matched { d+{'/' || '-' || '.'}d+ }
  124. bTwo = true;
  125. }
  126. else
  127. {
  128. //--- Digit-String Delimiter Digit-String non-delimiter cannot be a Date
  129. hr = E_INVALIDARG;
  130. }
  131. }
  132. }
  133. }
  134. else
  135. {
  136. //--- Digit-String followed by non-delimiter cannot be a Date
  137. hr = E_INVALIDARG;
  138. }
  139. }
  140. //------------------------------------------------
  141. // Now Figure Out What To Do With The Values
  142. //------------------------------------------------
  143. //--- Matched a Month, Day, and Year ---//
  144. if ( SUCCEEDED( hr ) &&
  145. bThree )
  146. {
  147. //--- Try to valiDate values
  148. ULONG ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk - 1);
  149. ULONG ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk - 1);
  150. ULONG ulThirdChunkLength = (ULONG)(pLeftOver - pThirdChunk);
  151. //--- Preferred order is Month Day Year
  152. if (fMonthDayYear)
  153. {
  154. //--- Try Month Day Year, then Day Month Year, then Year Month Day
  155. if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
  156. ( ulFirstChunkLength <= 3 ) &&
  157. ( DAYMIN <= ulSecond && ulSecond <= DAYMAX) &&
  158. ( ulSecondChunkLength <= 3 ) &&
  159. ( YEARMIN <= ulThird && ulThird <= YEARMAX) &&
  160. ( ulThirdChunkLength >= 2 ) )
  161. {
  162. NULL;
  163. }
  164. else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  165. ( ulFirstChunkLength <= 3 ) &&
  166. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  167. ( ulSecondChunkLength <= 3 ) &&
  168. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  169. ( ulThirdChunkLength >= 2 ) )
  170. {
  171. fMonthDayYear = false;
  172. fDayMonthYear = true;
  173. }
  174. else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  175. ( ulFirstChunkLength >= 2 ) &&
  176. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  177. ( ulSecondChunkLength <= 3 ) &&
  178. ( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
  179. ( ulThirdChunkLength <= 3 ) )
  180. {
  181. fMonthDayYear = false;
  182. fYearMonthDay = true;
  183. }
  184. else
  185. {
  186. hr = E_INVALIDARG;
  187. }
  188. }
  189. //--- Preferred order is Day Month Year
  190. else if ( fDayMonthYear )
  191. {
  192. //--- Try Day Month Year, then Month Day Year, then Year Month Day
  193. if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  194. ( ulFirstChunkLength <= 3 ) &&
  195. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  196. ( ulSecondChunkLength <= 3 ) &&
  197. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  198. ( ulThirdChunkLength >= 2 ) )
  199. {
  200. NULL;
  201. }
  202. else if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
  203. ( ulFirstChunkLength <= 3 ) &&
  204. ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
  205. ( ulSecondChunkLength <= 3 ) &&
  206. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  207. ( ulThirdChunkLength >= 2 ) )
  208. {
  209. fDayMonthYear = false;
  210. fMonthDayYear = true;
  211. }
  212. else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  213. ( ulFirstChunkLength >= 2 ) &&
  214. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  215. ( ulSecondChunkLength <= 3 ) &&
  216. ( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
  217. ( ulThirdChunkLength <= 3 ) )
  218. {
  219. fDayMonthYear = false;
  220. fYearMonthDay = true;
  221. }
  222. else
  223. {
  224. hr = E_INVALIDARG;
  225. }
  226. }
  227. //--- Preferred order is Year Month Day
  228. else if (fYearMonthDay)
  229. {
  230. //--- Try Year Month Day, then Month Day Year, then Day Month Year
  231. if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  232. ( ulFirstChunkLength >= 2 ) &&
  233. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  234. ( ulSecondChunkLength <= 3 ) &&
  235. ( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
  236. ( ulThirdChunkLength <= 3 ) )
  237. {
  238. NULL;
  239. }
  240. else if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
  241. ( ulFirstChunkLength <= 3 ) &&
  242. ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
  243. ( ulSecondChunkLength <= 3 ) &&
  244. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  245. ( ulThirdChunkLength >= 2 ) )
  246. {
  247. fYearMonthDay = false;
  248. fMonthDayYear = true;
  249. }
  250. else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  251. ( ulFirstChunkLength <= 3 ) &&
  252. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  253. ( ulSecondChunkLength <= 3 ) &&
  254. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  255. ( ulThirdChunkLength >= 2 ) )
  256. {
  257. fYearMonthDay = false;
  258. fDayMonthYear = true;
  259. }
  260. else
  261. {
  262. hr = E_INVALIDARG;
  263. }
  264. }
  265. else
  266. {
  267. hr = E_INVALIDARG;
  268. }
  269. //--- Fill out DateItemInfo structure appropriately.
  270. if ( SUCCEEDED( hr ) )
  271. {
  272. pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
  273. if ( SUCCEEDED( hr ) )
  274. {
  275. ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
  276. pItemNormInfo->Type = eDATE;
  277. if ( fMonthDayYear )
  278. {
  279. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
  280. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  281. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  282. if ( SUCCEEDED( hr ) )
  283. {
  284. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  285. if ( *pSecondChunk == L'0' )
  286. {
  287. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk + 1;
  288. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  289. }
  290. else
  291. {
  292. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
  293. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulSecondChunkLength;
  294. }
  295. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pSecondChunk +
  296. ulSecondChunkLength;
  297. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  298. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  299. if ( SUCCEEDED( hr ) )
  300. {
  301. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
  302. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
  303. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
  304. }
  305. }
  306. }
  307. else if ( fDayMonthYear )
  308. {
  309. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
  310. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  311. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  312. if ( SUCCEEDED( hr ) )
  313. {
  314. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  315. if ( *pFirstChunk == L'0' )
  316. {
  317. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk + 1;
  318. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  319. }
  320. else
  321. {
  322. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
  323. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulFirstChunkLength;
  324. }
  325. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pFirstChunk +
  326. ulFirstChunkLength;
  327. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  328. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  329. if ( SUCCEEDED( hr ) )
  330. {
  331. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
  332. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
  333. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
  334. }
  335. }
  336. }
  337. else if ( fYearMonthDay )
  338. {
  339. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
  340. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  341. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  342. if ( SUCCEEDED( hr ) )
  343. {
  344. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  345. if ( *pThirdChunk == L'0' )
  346. {
  347. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk + 1;
  348. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  349. }
  350. else
  351. {
  352. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk;
  353. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulThirdChunkLength;
  354. }
  355. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pThirdChunk +
  356. ulThirdChunkLength;
  357. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  358. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  359. if ( SUCCEEDED( hr ) )
  360. {
  361. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
  362. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pFirstChunk;
  363. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulFirstChunkLength;
  364. }
  365. }
  366. }
  367. }
  368. }
  369. }
  370. //--- Matched just a Month and Day, or a Month and Year ---//
  371. else if ( SUCCEEDED( hr ) &&
  372. Context &&
  373. bTwo )
  374. {
  375. ULONG ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk - 1);
  376. ULONG ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
  377. if ( _wcsicmp(Context, L"Date_MD") == 0 )
  378. {
  379. if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
  380. ( ulFirstChunkLength <= 2 ) &&
  381. ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
  382. ( ulSecondChunkLength <= 2 ) )
  383. {
  384. //--- Successfully matched a month and day
  385. pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
  386. if ( SUCCEEDED( hr ) )
  387. {
  388. ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
  389. pItemNormInfo->Type = eDATE;
  390. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
  391. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  392. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  393. if ( SUCCEEDED( hr ) )
  394. {
  395. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  396. if ( pSecondChunk[0] == L'0' )
  397. {
  398. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk + 1;
  399. ulSecondChunkLength--;
  400. }
  401. else
  402. {
  403. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
  404. }
  405. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulSecondChunkLength;
  406. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar =
  407. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar + ulSecondChunkLength;
  408. }
  409. }
  410. }
  411. else // values out of range
  412. {
  413. hr = E_INVALIDARG;
  414. }
  415. }
  416. else if ( _wcsicmp(Context, L"Date_DM") == 0 )
  417. {
  418. if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  419. ( ulFirstChunkLength <= 2 ) &&
  420. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  421. ( ulSecondChunkLength <= 2 ) )
  422. {
  423. //--- Successfully matched a month and day
  424. pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
  425. if ( SUCCEEDED( hr ) )
  426. {
  427. ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
  428. pItemNormInfo->Type = eDATE;
  429. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
  430. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  431. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  432. if ( SUCCEEDED( hr ) )
  433. {
  434. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  435. if ( m_pNextChar[0] == L'0' )
  436. {
  437. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk + 1;
  438. ulFirstChunkLength--;
  439. }
  440. else
  441. {
  442. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
  443. }
  444. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulFirstChunkLength;
  445. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar =
  446. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar + ulFirstChunkLength;
  447. }
  448. }
  449. }
  450. else // values out of range
  451. {
  452. hr = E_INVALIDARG;
  453. }
  454. }
  455. else if ( _wcsicmp(Context, L"Date_MY") == 0 )
  456. {
  457. if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
  458. ( ulFirstChunkLength <= 2 ) &&
  459. ( YEARMIN <= ulSecond && ulSecond <= YEARMAX ) &&
  460. ( ulSecondChunkLength >= 2 ) )
  461. {
  462. //--- Successfully matched a month and year
  463. pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
  464. if ( SUCCEEDED( hr ) )
  465. {
  466. ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
  467. pItemNormInfo->Type = eDATE;
  468. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
  469. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  470. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  471. if ( SUCCEEDED( hr ) )
  472. {
  473. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
  474. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pSecondChunk;
  475. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulSecondChunkLength;
  476. }
  477. }
  478. }
  479. else // values out of range
  480. {
  481. hr = E_INVALIDARG;
  482. }
  483. }
  484. else if ( _wcsicmp(Context, L"Date_YM") == 0 )
  485. {
  486. if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  487. ( ulFirstChunkLength >= 2 ) &&
  488. ( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
  489. ( ulSecondChunkLength <= 2 ) )
  490. {
  491. //--- Successfully matched a month and year
  492. pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
  493. if ( SUCCEEDED( hr ) )
  494. {
  495. ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
  496. pItemNormInfo->Type = eDATE;
  497. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
  498. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  499. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  500. if ( SUCCEEDED( hr ) )
  501. {
  502. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
  503. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pFirstChunk;
  504. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulFirstChunkLength;
  505. }
  506. }
  507. }
  508. else // values out of range
  509. {
  510. hr = E_INVALIDARG;
  511. }
  512. }
  513. //--- not a date unless context specifies...
  514. else
  515. {
  516. hr = E_INVALIDARG;
  517. }
  518. }
  519. else
  520. {
  521. hr = E_INVALIDARG;
  522. }
  523. }
  524. return hr;
  525. } /* IsNumericCompactDate */
  526. /***********************************************************************************************
  527. * IsMonthStringCompactDate *
  528. *--------------------------*
  529. * Description:
  530. * Checks the incoming Item's text to determine whether or not it
  531. * is a Date with a string for the month, and if so, which type.
  532. *
  533. * RegExp:
  534. * {[MonthString]{'/' || '-' || '.'}[1-31]{'/' || '-' || '.'}[0-9999]} ||
  535. * {[1-31]{'/' || '-' || '.'}[MonthString]{'/' || '-' || '.'}[0-9999]} ||
  536. * {[0-9999]{'/' || '-' || '.'}[MonthString]{'/' || '-' || '.'}[1-31]}
  537. *
  538. * Types assigned:
  539. * Date
  540. ********************************************************************* AH **********************/
  541. HRESULT CStdSentEnum::IsMonthStringCompactDate( TTSItemInfo*& pItemNormInfo, const WCHAR* Context,
  542. CSentItemMemory& MemoryManager )
  543. {
  544. SPDBG_FUNC( "DateNorm.cpp IsMonthStringCompactDate" );
  545. HRESULT hr = S_OK;
  546. WCHAR *pFirstChunk = 0, *pSecondChunk = 0, *pThirdChunk = 0, *pLeftOver = 0;
  547. ULONG ulFirst = 0;
  548. ULONG ulSecond = 0;
  549. ULONG ulThird = 0;
  550. ULONG ulTokenLen = (ULONG)(m_pEndOfCurrItem - m_pNextChar);
  551. ULONG ulFirstChunkLength = 0, ulSecondChunkLength = 0, ulThirdChunkLength = 0;
  552. bool fMonthDayYear = false, fDayMonthYear = false, fYearMonthDay = false;
  553. //--- Max length of a Date matching this regexp is 17 characters
  554. if ( ulTokenLen > 17 )
  555. {
  556. hr = E_INVALIDARG;
  557. }
  558. else
  559. {
  560. //--- Get preferred order of Month, Day, and Year for this user
  561. if (Context != NULL)
  562. {
  563. if ( _wcsicmp( Context, L"Date_MDY" ) == 0 )
  564. {
  565. fMonthDayYear = true;
  566. }
  567. else if ( _wcsicmp( Context, L"Date_DMY" ) == 0 )
  568. {
  569. fDayMonthYear = true;
  570. }
  571. else if ( _wcsicmp( Context, L"Date_YMD" ) == 0 )
  572. {
  573. fYearMonthDay = true;
  574. }
  575. else
  576. {
  577. if ( m_eShortDateOrder & MONTH_DAY_YEAR )
  578. {
  579. fMonthDayYear = true;
  580. }
  581. else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
  582. {
  583. fDayMonthYear = true;
  584. }
  585. else
  586. {
  587. fYearMonthDay = true;
  588. }
  589. }
  590. }
  591. else
  592. {
  593. if ( m_eShortDateOrder & MONTH_DAY_YEAR )
  594. {
  595. fMonthDayYear = true;
  596. }
  597. else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
  598. {
  599. fDayMonthYear = true;
  600. }
  601. else
  602. {
  603. fYearMonthDay = true;
  604. }
  605. }
  606. pFirstChunk = (WCHAR*) m_pNextChar;
  607. pSecondChunk = pFirstChunk;
  608. //--- Try MonthString-Day-Year format
  609. if ( iswalpha( *pFirstChunk ) )
  610. {
  611. ulFirst = MatchMonthString( pSecondChunk, ulTokenLen );
  612. if ( ulFirst )
  613. {
  614. ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk);
  615. if ( MatchDateDelimiter( &pSecondChunk ) )
  616. {
  617. pThirdChunk = pSecondChunk;
  618. ulSecond = my_wcstoul( pSecondChunk, &pThirdChunk );
  619. if ( pSecondChunk != pThirdChunk &&
  620. pThirdChunk - pSecondChunk <= 2 )
  621. {
  622. ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
  623. if ( MatchDateDelimiter( &pThirdChunk ) )
  624. {
  625. ulThird = my_wcstoul( pThirdChunk, &pLeftOver );
  626. if ( pThirdChunk != pLeftOver &&
  627. pLeftOver - pThirdChunk <= 4 )
  628. {
  629. ulThirdChunkLength = (ULONG)(pLeftOver - pThirdChunk);
  630. //--- May have matched a month, day and year - valiDate values
  631. if ( ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
  632. ( ulSecondChunkLength <= 2 ) &&
  633. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  634. ( ulThirdChunkLength >= 2 ) )
  635. {
  636. //--- Successfully matched a month, day and year
  637. fMonthDayYear = true;
  638. fDayMonthYear = false;
  639. fYearMonthDay = false;
  640. }
  641. else
  642. {
  643. hr = E_INVALIDARG;
  644. }
  645. }
  646. else
  647. {
  648. hr = E_INVALIDARG;
  649. }
  650. }
  651. else
  652. {
  653. if ( !Context ||
  654. ( Context &&
  655. _wcsicmp( Context, L"Date_MD" ) == 0 ) )
  656. {
  657. if ( ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
  658. ( ulSecondChunkLength <= 2 ) )
  659. {
  660. fMonthDayYear = true;
  661. fDayMonthYear = false;
  662. fYearMonthDay = false;
  663. pThirdChunk = NULL;
  664. }
  665. else
  666. {
  667. fMonthDayYear = false;
  668. fDayMonthYear = false;
  669. fYearMonthDay = true;
  670. pFirstChunk = pSecondChunk;
  671. ulFirstChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
  672. ulSecond = ulFirst;
  673. pThirdChunk = NULL;
  674. }
  675. }
  676. else if ( Context &&
  677. _wcsicmp( Context, L"Date_MY" ) == 0 )
  678. {
  679. if ( ( YEARMIN <= ulSecond && ulSecond <= YEARMAX ) &&
  680. ( ulSecondChunkLength <= 4 ) )
  681. {
  682. fMonthDayYear = false;
  683. fDayMonthYear = false;
  684. fYearMonthDay = true;
  685. pFirstChunk = pSecondChunk;
  686. ulFirstChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
  687. ulSecond = ulFirst;
  688. pThirdChunk = NULL;
  689. }
  690. else
  691. {
  692. hr = E_INVALIDARG;
  693. }
  694. }
  695. else
  696. {
  697. hr = E_INVALIDARG;
  698. }
  699. }
  700. }
  701. else if ( pSecondChunk != pThirdChunk &&
  702. pThirdChunk - pSecondChunk <= 4 )
  703. {
  704. if ( ( YEARMIN <= ulSecond && ulSecond <= YEARMAX ) )
  705. {
  706. fMonthDayYear = false;
  707. fDayMonthYear = false;
  708. fYearMonthDay = true;
  709. pFirstChunk = pSecondChunk;
  710. ulFirstChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
  711. ulSecond = ulFirst;
  712. pThirdChunk = NULL;
  713. }
  714. else
  715. {
  716. hr = E_INVALIDARG;
  717. }
  718. }
  719. else
  720. {
  721. hr = E_INVALIDARG;
  722. }
  723. }
  724. else
  725. {
  726. hr = E_INVALIDARG;
  727. }
  728. }
  729. else
  730. {
  731. hr = E_INVALIDARG;
  732. }
  733. }
  734. //--- Try Day-MonthString-Year and Year-MonthString-Day Formats
  735. else if ( isdigit( *pFirstChunk ) )
  736. {
  737. ulFirst = my_wcstoul( pFirstChunk, &pSecondChunk );
  738. if ( pFirstChunk != pSecondChunk &&
  739. pSecondChunk - pFirstChunk <= 4 )
  740. {
  741. ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk);
  742. if ( MatchDateDelimiter( &pSecondChunk ) )
  743. {
  744. pThirdChunk = pSecondChunk;
  745. ulSecond = MatchMonthString( pThirdChunk, ulTokenLen - ulFirstChunkLength );
  746. if ( ulSecond )
  747. {
  748. ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
  749. if ( MatchDateDelimiter( &pThirdChunk ) )
  750. {
  751. ulThird = my_wcstoul( pThirdChunk, &pLeftOver );
  752. if ( pThirdChunk != pLeftOver &&
  753. pLeftOver - pThirdChunk <= 4 )
  754. {
  755. ulThirdChunkLength = (ULONG)(pLeftOver - pThirdChunk);
  756. //--- May have matched a month, day, and year - valiDate values
  757. if ( fDayMonthYear ||
  758. fMonthDayYear )
  759. {
  760. //--- Preferred format is Month Day Year, or Day Month Year - in either case
  761. //--- Day Month Year is preferable to Year Month Day
  762. if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  763. ( ulFirstChunkLength <= 2 ) &&
  764. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  765. ( ulThirdChunkLength >= 2 ) )
  766. {
  767. //--- Successfully matched a day, month and year
  768. fDayMonthYear = true;
  769. fMonthDayYear = false;
  770. fYearMonthDay = false;
  771. }
  772. else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  773. ( ulFirstChunkLength >= 2 ) &&
  774. ( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
  775. ( ulThirdChunkLength <= 2 ) )
  776. {
  777. //--- Successfully matched a year, month and day
  778. fYearMonthDay = true;
  779. fMonthDayYear = false;
  780. fDayMonthYear = false;
  781. }
  782. else
  783. {
  784. hr = E_INVALIDARG;
  785. }
  786. }
  787. else // fYearMonthDay
  788. {
  789. //--- Preferred format is Year Month Day
  790. if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  791. ( ulFirstChunkLength >= 2 ) &&
  792. ( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
  793. ( ulThirdChunkLength <= 2 ) )
  794. {
  795. //--- Successfully matched a year, month, and day
  796. fYearMonthDay = true;
  797. fMonthDayYear = false;
  798. fDayMonthYear = false;
  799. }
  800. else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  801. ( ulFirstChunkLength <= 2 ) &&
  802. ( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
  803. ( ulThirdChunkLength >= 2 ) )
  804. {
  805. //--- Successfully matched a day, month, and year
  806. fDayMonthYear = true;
  807. fMonthDayYear = false;
  808. fYearMonthDay = false;
  809. }
  810. else
  811. {
  812. hr = E_INVALIDARG;
  813. }
  814. }
  815. }
  816. else
  817. {
  818. hr = E_INVALIDARG;
  819. }
  820. }
  821. //--- Matched two - either Day-Monthstring or Year-Monthstring
  822. else
  823. {
  824. if ( !Context ||
  825. ( Context &&
  826. _wcsicmp( Context, L"Date_DM" ) == 0 ) )
  827. {
  828. //--- Preferred format is Month Day Year, or Day Month Year - in either case
  829. //--- Day Month Year is preferable to Year Month Day
  830. if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  831. ( ulFirstChunkLength <= 2 ) )
  832. {
  833. //--- Successfully matched a day, month and year
  834. fDayMonthYear = true;
  835. fMonthDayYear = false;
  836. fYearMonthDay = false;
  837. pThirdChunk = NULL;
  838. }
  839. else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  840. ( ulFirstChunkLength <= 4 ) )
  841. {
  842. //--- Successfully matched a year, month and day
  843. fYearMonthDay = true;
  844. fMonthDayYear = false;
  845. fDayMonthYear = false;
  846. pThirdChunk = NULL;
  847. }
  848. else
  849. {
  850. hr = E_INVALIDARG;
  851. }
  852. }
  853. else if ( Context &&
  854. _wcsicmp( Context, L"Date_YM" ) == 0 )
  855. {
  856. //--- Preferred format is Year Month Day
  857. if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
  858. ( ulFirstChunkLength <= 4 ) )
  859. {
  860. //--- Successfully matched a year, month, and day
  861. fYearMonthDay = true;
  862. fMonthDayYear = false;
  863. fDayMonthYear = false;
  864. pThirdChunk = NULL;
  865. }
  866. else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
  867. ( ulFirstChunkLength <= 2 ) )
  868. {
  869. //--- Successfully matched a day, month, and year
  870. fDayMonthYear = true;
  871. fMonthDayYear = false;
  872. fYearMonthDay = false;
  873. pThirdChunk = NULL;
  874. }
  875. else
  876. {
  877. hr = E_INVALIDARG;
  878. }
  879. }
  880. else
  881. {
  882. hr = E_INVALIDARG;
  883. }
  884. }
  885. }
  886. else
  887. {
  888. hr = E_INVALIDARG;
  889. }
  890. }
  891. else
  892. {
  893. hr = E_INVALIDARG;
  894. }
  895. }
  896. else
  897. {
  898. hr = E_INVALIDARG;
  899. }
  900. }
  901. else
  902. {
  903. hr = E_INVALIDARG;
  904. }
  905. }
  906. //--- Fill out DateItemInfo structure appropriately.
  907. if ( SUCCEEDED( hr ) )
  908. {
  909. pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
  910. if ( SUCCEEDED( hr ) )
  911. {
  912. ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
  913. pItemNormInfo->Type = eDATE;
  914. if ( fMonthDayYear )
  915. {
  916. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
  917. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  918. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  919. if ( SUCCEEDED( hr ) )
  920. {
  921. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  922. if ( ulSecondChunkLength == 2 )
  923. {
  924. if ( *pSecondChunk != L'0' )
  925. {
  926. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
  927. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 2;
  928. }
  929. else
  930. {
  931. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk + 1;
  932. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  933. }
  934. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pSecondChunk + 2;
  935. }
  936. else
  937. {
  938. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
  939. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  940. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pSecondChunk + 1;
  941. }
  942. if ( pThirdChunk )
  943. {
  944. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  945. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  946. if ( SUCCEEDED( hr ) )
  947. {
  948. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
  949. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
  950. }
  951. }
  952. else
  953. {
  954. ( (TTSDateItemInfo*) pItemNormInfo )->pYear = NULL;
  955. }
  956. }
  957. }
  958. else if ( fDayMonthYear )
  959. {
  960. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
  961. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  962. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  963. if ( SUCCEEDED( hr ) )
  964. {
  965. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  966. if ( ulFirstChunkLength == 2 )
  967. {
  968. if ( *pFirstChunk != L'0' )
  969. {
  970. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
  971. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 2;
  972. }
  973. else
  974. {
  975. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk + 1;
  976. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  977. }
  978. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pFirstChunk + 2;
  979. }
  980. else
  981. {
  982. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
  983. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  984. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pFirstChunk + 1;
  985. }
  986. if ( pThirdChunk )
  987. {
  988. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  989. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  990. if ( SUCCEEDED( hr ) )
  991. {
  992. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
  993. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
  994. }
  995. }
  996. else
  997. {
  998. ( (TTSDateItemInfo*) pItemNormInfo )->pYear = NULL;
  999. }
  1000. }
  1001. }
  1002. else if ( fYearMonthDay )
  1003. {
  1004. ( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
  1005. if ( SUCCEEDED( hr ) )
  1006. {
  1007. if ( pThirdChunk )
  1008. {
  1009. ( (TTSDateItemInfo*) pItemNormInfo )->pDay =
  1010. (TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
  1011. if ( ulThirdChunkLength == 2 )
  1012. {
  1013. ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
  1014. if ( *pThirdChunk != L'0' )
  1015. {
  1016. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk;
  1017. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 2;
  1018. }
  1019. else
  1020. {
  1021. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk + 1;
  1022. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  1023. }
  1024. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pThirdChunk + 2;
  1025. }
  1026. else
  1027. {
  1028. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk;
  1029. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
  1030. ( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pThirdChunk + 1;
  1031. }
  1032. }
  1033. else
  1034. {
  1035. ( (TTSDateItemInfo*) pItemNormInfo )->pDay = NULL;
  1036. }
  1037. ( (TTSDateItemInfo*) pItemNormInfo )->pYear =
  1038. (TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
  1039. if ( SUCCEEDED( hr ) )
  1040. {
  1041. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pFirstChunk;
  1042. ( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulFirstChunkLength;
  1043. }
  1044. }
  1045. }
  1046. else
  1047. {
  1048. //--- should never get here.
  1049. hr = E_UNEXPECTED;
  1050. }
  1051. }
  1052. }
  1053. return hr;
  1054. } /* IsMonthStringCompactDate */
  1055. /***********************************************************************************************
  1056. * IsLongFormDate_DMDY *
  1057. *---------------------*
  1058. * Description:
  1059. * Checks the incoming Item's text to determine whether or not it
  1060. * is a long form Date.
  1061. *
  1062. * RegExp:
  1063. * [[DayString][,]?]? [MonthString][,]? [Day][,]? [Year]?
  1064. *
  1065. * Types assigned:
  1066. * Date
  1067. ********************************************************************* AH **********************/
  1068. HRESULT CStdSentEnum::IsLongFormDate_DMDY( TTSItemInfo*& pItemNormInfo, CSentItemMemory& MemoryManager,
  1069. CWordList& WordList )
  1070. {
  1071. SPDBG_FUNC( "CStdSentEnum::IsLongFormDate_DMDY" );
  1072. HRESULT hr = S_OK;
  1073. WCHAR *pDayString = NULL, *pMonthString = NULL, *pDay = NULL, *pYear = NULL;
  1074. ULONG ulDayLength = 0, ulYearLength = 0;
  1075. long lDayString = -1, lMonthString = -1, lDay = 0, lYear = 0;
  1076. const WCHAR *pStartChar = m_pNextChar, *pEndOfItem = m_pEndOfCurrItem, *pEndChar = m_pEndChar;
  1077. const WCHAR *pTempEndChar = NULL, *pTempEndOfItem = NULL;
  1078. const SPVTEXTFRAG* pFrag = m_pCurrFrag, *pTempFrag = NULL;
  1079. const SPVSTATE *pDayStringXMLState = NULL, *pMonthStringXMLState = NULL, *pDayXMLState = NULL;
  1080. const SPVSTATE *pYearXMLState = NULL;
  1081. CItemList PostDayStringList, PostMonthStringList, PostDayList;
  1082. BOOL fNoYear = false;
  1083. //--- Try to match Day String
  1084. pDayString = (WCHAR*) pStartChar;
  1085. lDayString = MatchDayString( pDayString, (WCHAR*) pEndOfItem );
  1086. //--- Failed to match a Day String
  1087. if ( lDayString == 0 )
  1088. {
  1089. pDayString = NULL;
  1090. }
  1091. //--- Matched a Day String, but it wasn't by itself or followed by a comma
  1092. else if ( pDayString != pEndOfItem &&
  1093. ( pDayString != pEndOfItem - 1 ||
  1094. *pEndOfItem != L',' ) )
  1095. {
  1096. hr = E_INVALIDARG;
  1097. }
  1098. //--- Matched a Day String - save XML State and move ahead in text
  1099. else
  1100. {
  1101. pDayString = (WCHAR*) pStartChar;
  1102. pDayStringXMLState = &pFrag->State;
  1103. pStartChar = pEndOfItem;
  1104. if ( *pStartChar == L',' )
  1105. {
  1106. pStartChar++;
  1107. }
  1108. hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayStringList );
  1109. if ( !pStartChar &&
  1110. SUCCEEDED( hr ) )
  1111. {
  1112. hr = E_INVALIDARG;
  1113. }
  1114. else if ( pStartChar &&
  1115. SUCCEEDED( hr ) )
  1116. {
  1117. pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
  1118. }
  1119. }
  1120. //--- Try to match Month String
  1121. if ( SUCCEEDED( hr ) )
  1122. {
  1123. pMonthString = (WCHAR*) pStartChar;
  1124. lMonthString = MatchMonthString( pMonthString, (ULONG)(pEndOfItem - pMonthString) );
  1125. //--- Failed to match Month String, or Month String was not by itself...
  1126. if ( !lMonthString ||
  1127. ( pMonthString != pEndOfItem &&
  1128. ( pMonthString != pEndOfItem - 1 ||
  1129. *pMonthString != L',' ) ) )
  1130. {
  1131. hr = E_INVALIDARG;
  1132. }
  1133. //--- Matched a Month String - save XML State and move ahead in text
  1134. else
  1135. {
  1136. pMonthString = (WCHAR*) pStartChar;
  1137. pMonthStringXMLState = &pFrag->State;
  1138. pStartChar = pEndOfItem;
  1139. hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostMonthStringList );
  1140. if ( !pStartChar &&
  1141. SUCCEEDED( hr ) )
  1142. {
  1143. hr = E_INVALIDARG;
  1144. }
  1145. else if ( pStartChar &&
  1146. SUCCEEDED( hr ) )
  1147. {
  1148. pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
  1149. //--- Strip trailing punctuation, etc. since the next token could be the last one if
  1150. //--- this is just a Monthstring and Day...
  1151. while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1152. IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1153. IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1154. IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
  1155. {
  1156. if ( *(pEndOfItem - 1) != L',' )
  1157. {
  1158. fNoYear = true;
  1159. }
  1160. pEndOfItem--;
  1161. }
  1162. }
  1163. }
  1164. }
  1165. //--- Try to match Day
  1166. if ( SUCCEEDED( hr ) )
  1167. {
  1168. lDay = my_wcstoul( pStartChar, &pDay );
  1169. //--- Matched a Day - save XML State and move ahead in text
  1170. if ( ( DAYMIN <= lDay && lDay <= DAYMAX ) &&
  1171. pDay - pStartChar <= 2 &&
  1172. ( pDay == pEndOfItem ||
  1173. ( pDay == (pEndOfItem - 1) && *pDay == L',' ) ) )
  1174. {
  1175. if ( pDay == pEndOfItem )
  1176. {
  1177. ulDayLength = (ULONG)(pEndOfItem - pStartChar);
  1178. }
  1179. else if ( pDay == pEndOfItem - 1 )
  1180. {
  1181. ulDayLength = (ULONG)((pEndOfItem - 1) - pStartChar);
  1182. }
  1183. pDay = (WCHAR*) pStartChar;
  1184. pDayXMLState = &pFrag->State;
  1185. if ( !fNoYear )
  1186. {
  1187. //--- Save pointers, in case there is no year present
  1188. pTempEndChar = pEndChar;
  1189. pTempEndOfItem = pEndOfItem;
  1190. pTempFrag = pFrag;
  1191. if ( *pEndOfItem == L',' )
  1192. {
  1193. pStartChar = pEndOfItem + 1;
  1194. }
  1195. else
  1196. {
  1197. pStartChar = pEndOfItem;
  1198. }
  1199. hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayList );
  1200. if ( !pStartChar &&
  1201. SUCCEEDED( hr ) )
  1202. {
  1203. fNoYear = true;
  1204. pYear = NULL;
  1205. }
  1206. else if ( pStartChar &&
  1207. ( SUCCEEDED( hr ) ) )
  1208. {
  1209. pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
  1210. //--- Strip trailing punctuation, since the next token will be the last one
  1211. //--- if this is Monthstring, Day, Year
  1212. while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1213. IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1214. IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1215. IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
  1216. {
  1217. pEndOfItem--;
  1218. }
  1219. }
  1220. }
  1221. }
  1222. //--- Failed to match a day
  1223. else if ( ( YEARMIN <= lDay && lDay <= YEARMAX ) &&
  1224. pDay - pStartChar <= 4 &&
  1225. pDay == pEndOfItem )
  1226. {
  1227. //--- Successfully matched Month String and Year
  1228. pYearXMLState = &pFrag->State;
  1229. ulYearLength = (ULONG)(pEndOfItem - pStartChar);
  1230. pYear = (WCHAR*) pStartChar;
  1231. //--- Don't try to match a year again
  1232. fNoYear = true;
  1233. }
  1234. else
  1235. {
  1236. hr = E_INVALIDARG;
  1237. }
  1238. }
  1239. //--- Try to match Year
  1240. if ( SUCCEEDED( hr ) &&
  1241. !fNoYear )
  1242. {
  1243. lYear = my_wcstoul( pStartChar, &pYear );
  1244. //--- Matched a Year
  1245. if ( ( YEARMIN <= lYear && lYear <= YEARMAX ) &&
  1246. pYear - pStartChar <= 4 &&
  1247. pYear == pEndOfItem )
  1248. {
  1249. //--- Successfully matched Month String, Day, and Year (and possibly Day String)
  1250. pYearXMLState = &pFrag->State;
  1251. ulYearLength = (ULONG)(pEndOfItem - pStartChar);
  1252. pYear = (WCHAR*) pStartChar;
  1253. }
  1254. else
  1255. {
  1256. //--- Failed to match Year - replace pointers with previous values
  1257. pEndChar = pTempEndChar;
  1258. pEndOfItem = pTempEndOfItem;
  1259. pFrag = pTempFrag;
  1260. pYear = NULL;
  1261. }
  1262. }
  1263. if ( SUCCEEDED( hr ) )
  1264. {
  1265. TTSWord Word;
  1266. ZeroMemory( &Word, sizeof(TTSWord) );
  1267. Word.eWordPartOfSpeech = MS_Unknown;
  1268. pItemNormInfo = (TTSItemInfo*) MemoryManager.GetMemory( sizeof(TTSItemInfo), &hr );
  1269. if ( SUCCEEDED( hr ) )
  1270. {
  1271. pItemNormInfo->Type = eDATE_LONGFORM;
  1272. //--- Insert Day String, if present
  1273. if ( pDayString )
  1274. {
  1275. Word.pXmlState = pDayStringXMLState;
  1276. Word.pWordText = g_days[lDayString - 1].pStr;
  1277. Word.ulWordLen = g_days[lDayString - 1].Len;
  1278. Word.pLemma = Word.pWordText;
  1279. Word.ulLemmaLen = Word.ulWordLen;
  1280. WordList.AddTail( Word );
  1281. }
  1282. //--- Insert Post Day String XML States
  1283. while ( !PostDayStringList.IsEmpty() )
  1284. {
  1285. WordList.AddTail( ( PostDayStringList.RemoveHead() ).Words[0] );
  1286. }
  1287. //--- Insert Month String
  1288. Word.pXmlState = pMonthStringXMLState;
  1289. Word.pWordText = g_months[lMonthString - 1].pStr;
  1290. Word.ulWordLen = g_months[lMonthString - 1].Len;
  1291. Word.pLemma = Word.pWordText;
  1292. Word.ulLemmaLen = Word.ulWordLen;
  1293. WordList.AddTail( Word );
  1294. //--- Insert Post Month String XML State
  1295. while ( !PostMonthStringList.IsEmpty() )
  1296. {
  1297. WordList.AddTail( ( PostMonthStringList.RemoveHead() ).Words[0] );
  1298. }
  1299. SPLISTPOS WordListPos = WordList.GetTailPosition();
  1300. //--- Expand Day
  1301. if ( ulDayLength == 1 )
  1302. {
  1303. NumberGroup Garbage;
  1304. ExpandDigitOrdinal( *pDay, Garbage, WordList );
  1305. }
  1306. else if ( ulDayLength == 2 )
  1307. {
  1308. NumberGroup Garbage;
  1309. ExpandTwoOrdinal( pDay, Garbage, WordList );
  1310. }
  1311. //--- Clean Up Day XML States
  1312. WordList.GetNext( WordListPos );
  1313. while ( WordListPos )
  1314. {
  1315. TTSWord& TempWord = WordList.GetNext( WordListPos );
  1316. TempWord.pXmlState = pDayXMLState;
  1317. }
  1318. //--- Insert Post Day XML State
  1319. while ( !PostDayList.IsEmpty() )
  1320. {
  1321. WordList.AddTail( ( PostDayList.RemoveHead() ).Words[0] );
  1322. }
  1323. WordListPos = WordList.GetTailPosition();
  1324. //--- Expand Year, if present
  1325. if ( pYear )
  1326. {
  1327. TTSYearItemInfo TempYearInfo;
  1328. TempYearInfo.pYear = pYear;
  1329. TempYearInfo.ulNumDigits = ulYearLength;
  1330. hr = ExpandYear( &TempYearInfo, WordList );
  1331. if ( SUCCEEDED( hr ) )
  1332. {
  1333. //--- Clean Up Year XML States
  1334. WordList.GetNext( WordListPos );
  1335. while ( WordListPos )
  1336. {
  1337. TTSWord& TempWord = WordList.GetNext( WordListPos );
  1338. TempWord.pXmlState = pYearXMLState;
  1339. }
  1340. }
  1341. }
  1342. //--- Advance pointers
  1343. m_pCurrFrag = pFrag;
  1344. m_pEndChar = pEndChar;
  1345. m_pEndOfCurrItem = pEndOfItem;
  1346. }
  1347. }
  1348. return hr;
  1349. } /* IsLongFormDate_DMDY */
  1350. /***********************************************************************************************
  1351. * IsLongFormDate_DDMY *
  1352. *---------------------*
  1353. * Description:
  1354. * Checks the incoming Item's text to determine whether or not it
  1355. * is a long form Date.
  1356. *
  1357. * RegExp:
  1358. * [[DayString][,]?]? [Day][,]? [MonthString][,]? [Year]?
  1359. *
  1360. * Types assigned:
  1361. * Date
  1362. ********************************************************************* AH **********************/
  1363. HRESULT CStdSentEnum::IsLongFormDate_DDMY( TTSItemInfo*& pItemNormInfo, CSentItemMemory& MemoryManager,
  1364. CWordList& WordList )
  1365. {
  1366. SPDBG_FUNC( "CStdSentEnum::IsLongFormDate_DDMY" );
  1367. HRESULT hr = S_OK;
  1368. WCHAR *pDayString = NULL, *pMonthString = NULL, *pDay = NULL, *pYear = NULL;
  1369. ULONG ulDayLength = 0, ulYearLength = 0;
  1370. long lDayString = -1, lMonthString = -1, lDay = 0, lYear = 0;
  1371. const WCHAR *pStartChar = m_pNextChar, *pEndOfItem = m_pEndOfCurrItem, *pEndChar = m_pEndChar;
  1372. const WCHAR *pTempEndChar = NULL, *pTempEndOfItem = NULL;
  1373. const SPVTEXTFRAG* pFrag = m_pCurrFrag, *pTempFrag = NULL;
  1374. const SPVSTATE *pDayStringXMLState = NULL, *pMonthStringXMLState = NULL, *pDayXMLState = NULL;
  1375. const SPVSTATE *pYearXMLState = NULL;
  1376. CItemList PostDayStringList, PostMonthStringList, PostDayList;
  1377. BOOL fNoYear = false;
  1378. //--- Try to match Day String
  1379. pDayString = (WCHAR*) pStartChar;
  1380. lDayString = MatchDayString( pDayString, (WCHAR*) pEndOfItem );
  1381. //--- Failed to match a Day String
  1382. if ( lDayString == 0 )
  1383. {
  1384. pDayString = NULL;
  1385. }
  1386. //--- Matched a Day String, but it wasn't by itself or followed by a comma
  1387. else if ( pDayString != pEndOfItem &&
  1388. ( pDayString != pEndOfItem - 1 ||
  1389. *pEndOfItem != L',' ) )
  1390. {
  1391. hr = E_INVALIDARG;
  1392. }
  1393. //--- Matched a Day String - save XML State and move ahead in text
  1394. else
  1395. {
  1396. pDayString = (WCHAR*) pStartChar;
  1397. pDayStringXMLState = &pFrag->State;
  1398. pStartChar = pEndOfItem;
  1399. if ( *pStartChar == L',' )
  1400. {
  1401. pStartChar++;
  1402. }
  1403. hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayStringList );
  1404. if ( !pStartChar &&
  1405. SUCCEEDED( hr ) )
  1406. {
  1407. hr = E_INVALIDARG;
  1408. }
  1409. else if ( pStartChar &&
  1410. SUCCEEDED( hr ) )
  1411. {
  1412. pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
  1413. }
  1414. }
  1415. //--- Try to match Day
  1416. if ( SUCCEEDED( hr ) )
  1417. {
  1418. lDay = my_wcstoul( pStartChar, &pDay );
  1419. //--- Matched a Day - save XML State and move ahead in text
  1420. if ( ( DAYMIN <= lDay && lDay <= DAYMAX ) &&
  1421. pDay - pStartChar <= 2 &&
  1422. ( pDay == pEndOfItem ||
  1423. ( pDay == (pEndOfItem - 1) && *pDay == L',' ) ) )
  1424. {
  1425. if ( pDay == pEndOfItem )
  1426. {
  1427. ulDayLength = (ULONG)(pEndOfItem - pStartChar);
  1428. }
  1429. else if ( pDay == pEndOfItem - 1 )
  1430. {
  1431. ulDayLength = (ULONG)((pEndOfItem - 1) - pStartChar);
  1432. }
  1433. pDay = (WCHAR*) pStartChar;
  1434. pDayXMLState = &pFrag->State;
  1435. if ( *pEndOfItem == L',' )
  1436. {
  1437. pStartChar = pEndOfItem + 1;
  1438. }
  1439. else
  1440. {
  1441. pStartChar = pEndOfItem;
  1442. }
  1443. hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayList );
  1444. if ( !pStartChar &&
  1445. SUCCEEDED( hr ) )
  1446. {
  1447. hr = E_INVALIDARG;
  1448. }
  1449. else if ( pStartChar &&
  1450. ( SUCCEEDED( hr ) ) )
  1451. {
  1452. pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
  1453. //--- Strip trailing punctuation, since the next token will be the last one
  1454. //--- if this is Monthstring, Day, Year
  1455. while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1456. IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1457. IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1458. IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
  1459. {
  1460. if ( *(pEndOfItem - 1) != L',' )
  1461. {
  1462. fNoYear = true;
  1463. }
  1464. pEndOfItem--;
  1465. }
  1466. }
  1467. }
  1468. //--- Failed to match a day
  1469. else
  1470. {
  1471. hr = E_INVALIDARG;
  1472. }
  1473. }
  1474. //--- Try to match Month String
  1475. if ( SUCCEEDED( hr ) )
  1476. {
  1477. pMonthString = (WCHAR*) pStartChar;
  1478. lMonthString = MatchMonthString( pMonthString, (ULONG)(pEndOfItem - pMonthString) );
  1479. //--- Failed to match Month String, or Month String was not by itself...
  1480. if ( !lMonthString ||
  1481. ( pMonthString != pEndOfItem &&
  1482. ( pMonthString != pEndOfItem - 1 ||
  1483. *pMonthString != L',' ) ) )
  1484. {
  1485. hr = E_INVALIDARG;
  1486. }
  1487. //--- Matched a Month String - save XML State and move ahead in text
  1488. else
  1489. {
  1490. pMonthString = (WCHAR*) pStartChar;
  1491. pMonthStringXMLState = &pFrag->State;
  1492. if ( !fNoYear )
  1493. {
  1494. //--- Save pointers, in case there is no year present
  1495. pTempEndChar = pEndChar;
  1496. pTempEndOfItem = pEndOfItem;
  1497. pTempFrag = pFrag;
  1498. if ( *pEndOfItem == L',' )
  1499. {
  1500. pStartChar = pEndOfItem + 1;
  1501. }
  1502. else
  1503. {
  1504. pStartChar = pEndOfItem;
  1505. }
  1506. hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostMonthStringList );
  1507. if ( !pStartChar &&
  1508. SUCCEEDED( hr ) )
  1509. {
  1510. fNoYear = true;
  1511. pYear = NULL;
  1512. }
  1513. else if ( pStartChar &&
  1514. SUCCEEDED( hr ) )
  1515. {
  1516. pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
  1517. //--- Strip trailing punctuation, etc. since the next token could be the last one if
  1518. //--- this is Day, Monthstring, Year
  1519. while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1520. IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1521. IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
  1522. IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
  1523. {
  1524. pEndOfItem--;
  1525. }
  1526. }
  1527. }
  1528. }
  1529. }
  1530. //--- Try to match Year
  1531. if ( SUCCEEDED( hr ) &&
  1532. !fNoYear )
  1533. {
  1534. lYear = my_wcstoul( pStartChar, &pYear );
  1535. //--- Matched a Year
  1536. if ( ( YEARMIN <= lYear && lYear <= YEARMAX ) &&
  1537. pYear - pStartChar <= 4 &&
  1538. pYear == pEndOfItem )
  1539. {
  1540. //--- Successfully matched Month String, Day, and Year (and possibly Day String)
  1541. pYearXMLState = &pFrag->State;
  1542. ulYearLength = (ULONG)(pEndOfItem - pStartChar);
  1543. pYear = (WCHAR*) pStartChar;
  1544. }
  1545. else
  1546. {
  1547. //--- Failed to match Year - replace pointers with previous values
  1548. pEndChar = pTempEndChar;
  1549. pEndOfItem = pTempEndOfItem;
  1550. pFrag = pTempFrag;
  1551. pYear = NULL;
  1552. }
  1553. }
  1554. if ( SUCCEEDED( hr ) )
  1555. {
  1556. TTSWord Word;
  1557. ZeroMemory( &Word, sizeof(TTSWord) );
  1558. Word.eWordPartOfSpeech = MS_Unknown;
  1559. pItemNormInfo = (TTSItemInfo*) MemoryManager.GetMemory( sizeof(TTSItemInfo), &hr );
  1560. if ( SUCCEEDED( hr ) )
  1561. {
  1562. pItemNormInfo->Type = eDATE_LONGFORM;
  1563. //--- Insert Day String, if present
  1564. if ( pDayString )
  1565. {
  1566. Word.pXmlState = pDayStringXMLState;
  1567. Word.pWordText = g_days[lDayString - 1].pStr;
  1568. Word.ulWordLen = g_days[lDayString - 1].Len;
  1569. Word.pLemma = Word.pWordText;
  1570. Word.ulLemmaLen = Word.ulWordLen;
  1571. WordList.AddTail( Word );
  1572. }
  1573. //--- Insert Post Day String XML States
  1574. while ( !PostDayStringList.IsEmpty() )
  1575. {
  1576. WordList.AddTail( ( PostDayStringList.RemoveHead() ).Words[0] );
  1577. }
  1578. //--- Insert Month String
  1579. Word.pXmlState = pMonthStringXMLState;
  1580. Word.pWordText = g_months[lMonthString - 1].pStr;
  1581. Word.ulWordLen = g_months[lMonthString - 1].Len;
  1582. Word.pLemma = Word.pWordText;
  1583. Word.ulLemmaLen = Word.ulWordLen;
  1584. WordList.AddTail( Word );
  1585. //--- Insert Post Month String XML State
  1586. while ( !PostMonthStringList.IsEmpty() )
  1587. {
  1588. WordList.AddTail( ( PostMonthStringList.RemoveHead() ).Words[0] );
  1589. }
  1590. SPLISTPOS WordListPos = WordList.GetTailPosition();
  1591. //--- Expand Day
  1592. if ( ulDayLength == 1 )
  1593. {
  1594. NumberGroup Garbage;
  1595. ExpandDigitOrdinal( *pDay, Garbage, WordList );
  1596. }
  1597. else if ( ulDayLength == 2 )
  1598. {
  1599. NumberGroup Garbage;
  1600. ExpandTwoOrdinal( pDay, Garbage, WordList );
  1601. }
  1602. //--- Clean Up Day XML States
  1603. WordList.GetNext( WordListPos );
  1604. while ( WordListPos )
  1605. {
  1606. TTSWord& TempWord = WordList.GetNext( WordListPos );
  1607. TempWord.pXmlState = pDayXMLState;
  1608. }
  1609. //--- Insert Post Day XML State
  1610. while ( !PostDayList.IsEmpty() )
  1611. {
  1612. WordList.AddTail( ( PostDayList.RemoveHead() ).Words[0] );
  1613. }
  1614. WordListPos = WordList.GetTailPosition();
  1615. //--- Expand Year, if present
  1616. if ( pYear )
  1617. {
  1618. TTSYearItemInfo TempYearInfo;
  1619. TempYearInfo.pYear = pYear;
  1620. TempYearInfo.ulNumDigits = ulYearLength;
  1621. hr = ExpandYear( &TempYearInfo, WordList );
  1622. if ( SUCCEEDED( hr ) )
  1623. {
  1624. //--- Clean Up Year XML States
  1625. WordList.GetNext( WordListPos );
  1626. while ( WordListPos )
  1627. {
  1628. TTSWord& TempWord = WordList.GetNext( WordListPos );
  1629. TempWord.pXmlState = pYearXMLState;
  1630. }
  1631. }
  1632. }
  1633. //--- Advance pointers
  1634. m_pCurrFrag = pFrag;
  1635. m_pEndChar = pEndChar;
  1636. m_pEndOfCurrItem = pEndOfItem;
  1637. }
  1638. }
  1639. return hr;
  1640. } /* IsLongFormDate_DMDY */
  1641. /***********************************************************************************************
  1642. * ExpandDate *
  1643. *------------*
  1644. * Description:
  1645. * Expands Items previously determined to be of type Date by IsNumericCompactDate,
  1646. * IsMonthStringCompactDate, or IsTwoValueDate.
  1647. *
  1648. * NOTE: This function does not do parameter validation. Assumed to be done by caller.
  1649. ********************************************************************* AH **********************/
  1650. HRESULT CStdSentEnum::ExpandDate( TTSDateItemInfo* pItemInfo, CWordList& WordList )
  1651. {
  1652. SPDBG_FUNC( "CStdSentEnum::ExpandDate" );
  1653. HRESULT hr = S_OK;
  1654. TTSWord Word;
  1655. ZeroMemory( &Word, sizeof(TTSWord) );
  1656. Word.pXmlState = &m_pCurrFrag->State;
  1657. Word.eWordPartOfSpeech = MS_Unknown;
  1658. //--- Insert DayString, if present.
  1659. if ( pItemInfo->ulDayIndex )
  1660. {
  1661. Word.pWordText = g_days[pItemInfo->ulDayIndex - 1].pStr;
  1662. Word.ulWordLen = g_days[pItemInfo->ulDayIndex - 1].Len;
  1663. Word.pLemma = Word.pWordText;
  1664. Word.ulLemmaLen = Word.ulWordLen;
  1665. WordList.AddTail( Word );
  1666. }
  1667. //--- Insert Month
  1668. Word.pWordText = g_months[pItemInfo->ulMonthIndex - 1].pStr;
  1669. Word.ulWordLen = g_months[pItemInfo->ulMonthIndex - 1].Len;
  1670. Word.pLemma = Word.pWordText;
  1671. Word.ulLemmaLen = Word.ulWordLen;
  1672. WordList.AddTail( Word );
  1673. //--- Expand Day, if present.
  1674. if ( pItemInfo->pDay )
  1675. {
  1676. if ( pItemInfo->pDay->lLeftOver == 1 )
  1677. {
  1678. NumberGroup Garbage;
  1679. ExpandDigitOrdinal( *pItemInfo->pDay->pStartChar, Garbage, WordList );
  1680. }
  1681. else if ( pItemInfo->pDay->lLeftOver == 2 )
  1682. {
  1683. NumberGroup Garbage;
  1684. ExpandTwoOrdinal( pItemInfo->pDay->pStartChar, Garbage, WordList );
  1685. }
  1686. }
  1687. //--- Expand Year, if present.
  1688. if ( pItemInfo->pYear )
  1689. {
  1690. ExpandYear( pItemInfo->pYear, WordList );
  1691. }
  1692. return hr;
  1693. } /* ExpandDate_Standard */
  1694. /***********************************************************************************************
  1695. * ExpandYear *
  1696. *-------------*
  1697. * Description:
  1698. * Expands four digit strings into words in groups of two, and inserts them into Item List
  1699. * at ListPos. Thus 1999 come out as "nineteen ninety nine" rather than "one thousand nine
  1700. * hundred ninety nine"...
  1701. * Note: This function does not do parameter validation. Assumed to be done by caller.
  1702. ********************************************************************* AH **********************/
  1703. HRESULT CStdSentEnum::ExpandYear( TTSYearItemInfo* pItemInfo, CWordList& WordList )
  1704. {
  1705. SPDBG_FUNC( "CStdSentEnum::ExpandYear" );
  1706. // 1000 - 9999
  1707. HRESULT hr = S_OK;
  1708. TTSWord Word;
  1709. ZeroMemory( &Word, sizeof(TTSWord) );
  1710. Word.pXmlState = &m_pCurrFrag->State;
  1711. Word.eWordPartOfSpeech = MS_Unknown;
  1712. NumberGroup Garbage;
  1713. switch ( pItemInfo->ulNumDigits )
  1714. {
  1715. case 2:
  1716. //--- Expand as "two thousand" if the two digits are both zeroes.
  1717. if ( pItemInfo->pYear[0] == L'0' &&
  1718. pItemInfo->pYear[1] == L'0' )
  1719. {
  1720. //--- Insert "two".
  1721. Word.pWordText = g_ones[2].pStr;
  1722. Word.ulWordLen = g_ones[2].Len;
  1723. Word.pLemma = Word.pWordText;
  1724. Word.ulLemmaLen = Word.ulWordLen;
  1725. WordList.AddTail( Word );
  1726. //--- Insert "thousand".
  1727. Word.pWordText = g_quantifiers[1].pStr;
  1728. Word.ulWordLen = g_quantifiers[1].Len;
  1729. Word.pLemma = Word.pWordText;
  1730. Word.ulLemmaLen = Word.ulWordLen;
  1731. WordList.AddTail( Word );
  1732. }
  1733. //--- Expand as "oh number" if the first digit is zero.
  1734. else if ( pItemInfo->pYear[0] == L'0' )
  1735. {
  1736. Word.pWordText = g_O.pStr;
  1737. Word.ulWordLen = g_O.Len;
  1738. Word.pLemma = Word.pWordText;
  1739. Word.ulLemmaLen = Word.ulWordLen;
  1740. WordList.AddTail( Word );
  1741. ExpandDigit( pItemInfo->pYear[1], Garbage, WordList );
  1742. }
  1743. //--- Otherwise just expand as a two digit cardinal number
  1744. else
  1745. {
  1746. ExpandTwoDigits( pItemInfo->pYear, Garbage, WordList );
  1747. }
  1748. break;
  1749. case 3:
  1750. //--- Expand as a three digit cardinal number;
  1751. ExpandThreeDigits( pItemInfo->pYear, Garbage, WordList );
  1752. break;
  1753. case 4:
  1754. //--- If of form "[x]00[y]" expand as "x thousand y", or just "x thousand" if y is also zero.
  1755. if ( pItemInfo->pYear[1] == L'0' &&
  1756. pItemInfo->pYear[2] == L'0' &&
  1757. pItemInfo->pYear[0] != L'0' )
  1758. {
  1759. //--- "x"
  1760. ExpandDigit( pItemInfo->pYear[0], Garbage, WordList );
  1761. //--- "thousand".
  1762. Word.pWordText = g_quantifiers[1].pStr;
  1763. Word.ulWordLen = g_quantifiers[1].Len;
  1764. Word.pLemma = Word.pWordText;
  1765. Word.ulLemmaLen = Word.ulWordLen;
  1766. WordList.AddTail( Word );
  1767. //--- "y"
  1768. if ( pItemInfo->pYear[3] != L'0' )
  1769. {
  1770. ExpandDigit( pItemInfo->pYear[3], Garbage, WordList );
  1771. }
  1772. }
  1773. // Otherwise...
  1774. else
  1775. {
  1776. //--- Expand first two digits - e.g. "nineteen"
  1777. ExpandTwoDigits( pItemInfo->pYear, Garbage, WordList );
  1778. //--- Expand last two digits - e.g. "nineteen", "hundred", or "oh nine".
  1779. if ( pItemInfo->pYear[2] != '0' )
  1780. {
  1781. //--- the tens is not zero - e.g. 1919 -> "nineteen nineteen"
  1782. ExpandTwoDigits( pItemInfo->pYear + 2, Garbage, WordList );
  1783. }
  1784. else if ( pItemInfo->pYear[3] == '0' )
  1785. {
  1786. //--- tens and ones are both zero - expand as "hundred", e.g. 1900 -> "nineteen hundred"
  1787. Word.pWordText = g_quantifiers[0].pStr;
  1788. Word.ulWordLen = g_quantifiers[0].Len;
  1789. Word.pLemma = Word.pWordText;
  1790. Word.ulLemmaLen = Word.ulWordLen;
  1791. WordList.AddTail( Word );
  1792. }
  1793. else
  1794. {
  1795. //--- just the tens is zero, expand as "oh x" - e.g. 1909 -> "nineteen oh nine",
  1796. //--- unless both thousands and hundreds were also zero - e.g. 0002 -> "two"
  1797. if ( pItemInfo->pYear[0] != '0' ||
  1798. pItemInfo->pYear[1] != '0' )
  1799. {
  1800. Word.pWordText = g_O.pStr;
  1801. Word.ulWordLen = g_O.Len;
  1802. Word.pLemma = Word.pWordText;
  1803. Word.ulLemmaLen = Word.ulWordLen;
  1804. WordList.AddTail( Word );
  1805. }
  1806. ExpandDigit( pItemInfo->pYear[3], Garbage, WordList );
  1807. }
  1808. }
  1809. }
  1810. return hr;
  1811. } /* ExpandYear */
  1812. /***********************************************************************************************
  1813. * IsDecade *
  1814. *----------*
  1815. * Description:
  1816. * Checks the incoming Item's text to determine whether or not it
  1817. * is a Decade.
  1818. *
  1819. * RegExp:
  1820. * { ddd0s || d0s || 'd0s || ddd0's || d0's }
  1821. *
  1822. * Types assigned:
  1823. * Decade
  1824. ********************************************************************* AH **********************/
  1825. HRESULT CStdSentEnum::IsDecade( TTSItemInfo*& pItemNormInfo, CSentItemMemory& MemoryManager )
  1826. {
  1827. SPDBG_FUNC( "CStdSentEnum::IsDecade" );
  1828. HRESULT hr = S_OK;
  1829. ULONG ulTokenLen = (ULONG)(m_pEndOfCurrItem - m_pNextChar);
  1830. if ( ulTokenLen < 3 ||
  1831. ulTokenLen > 6 )
  1832. {
  1833. hr = E_INVALIDARG;
  1834. }
  1835. else
  1836. {
  1837. switch ( ulTokenLen )
  1838. {
  1839. case 6:
  1840. if ( m_pNextChar[5] == L's' &&
  1841. m_pNextChar[4] == L'\'' &&
  1842. m_pNextChar[3] == L'0' &&
  1843. iswdigit( m_pNextChar[2] ) &&
  1844. iswdigit( m_pNextChar[1] ) &&
  1845. iswdigit( m_pNextChar[0] ) )
  1846. {
  1847. //--- Decade of form ddd0's
  1848. pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
  1849. if ( SUCCEEDED( hr ) )
  1850. {
  1851. ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
  1852. pItemNormInfo->Type = eDECADE;
  1853. ( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = m_pNextChar;
  1854. ( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[2] - L'0';
  1855. }
  1856. }
  1857. else
  1858. {
  1859. hr = E_INVALIDARG;
  1860. }
  1861. break;
  1862. case 5:
  1863. if ( m_pNextChar[4] == L's' &&
  1864. m_pNextChar[3] == L'0' &&
  1865. iswdigit( m_pNextChar[2] ) &&
  1866. iswdigit( m_pNextChar[1] ) &&
  1867. iswdigit( m_pNextChar[0] ) )
  1868. {
  1869. //--- Decade of form ddd0s
  1870. pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
  1871. if ( SUCCEEDED( hr ) )
  1872. {
  1873. ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
  1874. pItemNormInfo->Type = eDECADE;
  1875. ( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = m_pNextChar;
  1876. ( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[2] - L'0';
  1877. }
  1878. }
  1879. else
  1880. {
  1881. hr = E_INVALIDARG;
  1882. }
  1883. break;
  1884. case 4:
  1885. if ( m_pNextChar[3] == L's' &&
  1886. m_pNextChar[2] == L'0' &&
  1887. iswdigit( m_pNextChar[1] ) &&
  1888. m_pNextChar[0] == L'\'' )
  1889. {
  1890. //--- Decade of form 'd0s
  1891. pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
  1892. if ( SUCCEEDED( hr ) )
  1893. {
  1894. ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
  1895. pItemNormInfo->Type = eDECADE;
  1896. ( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = NULL;
  1897. ( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[1] - L'0';
  1898. }
  1899. }
  1900. else if ( m_pNextChar[3] == L's' &&
  1901. m_pNextChar[2] == L'\'' &&
  1902. m_pNextChar[1] == L'0' &&
  1903. iswdigit( m_pNextChar[0] ) )
  1904. {
  1905. //--- Decade of form d0's
  1906. pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
  1907. if ( SUCCEEDED( hr ) )
  1908. {
  1909. ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
  1910. pItemNormInfo->Type = eDECADE;
  1911. ( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = NULL;
  1912. ( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[0] - L'0';
  1913. }
  1914. }
  1915. else
  1916. {
  1917. hr = E_INVALIDARG;
  1918. }
  1919. break;
  1920. case 3:
  1921. if ( m_pNextChar[2] == L's' &&
  1922. m_pNextChar[1] == L'0' &&
  1923. iswdigit( m_pNextChar[0] ) )
  1924. {
  1925. //--- Decade of form d0s
  1926. pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
  1927. if ( SUCCEEDED( hr ) )
  1928. {
  1929. ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
  1930. pItemNormInfo->Type = eDECADE;
  1931. ( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = NULL;
  1932. ( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[0] - L'0';
  1933. }
  1934. }
  1935. else
  1936. {
  1937. hr = E_INVALIDARG;
  1938. }
  1939. break;
  1940. default:
  1941. hr = E_INVALIDARG;
  1942. break;
  1943. }
  1944. }
  1945. return hr;
  1946. } /* IsDecade */
  1947. /***********************************************************************************************
  1948. * ExpandDecade *
  1949. *--------------*
  1950. * Description:
  1951. * Expands Items previously determined to be of type Decade by IsDecade.
  1952. *
  1953. * NOTE: This function does not do parameter validation. Assumed to be done by caller.
  1954. ********************************************************************* AH **********************/
  1955. HRESULT CStdSentEnum::ExpandDecade( TTSDecadeItemInfo* pItemInfo, CWordList& WordList )
  1956. {
  1957. HRESULT hr = S_OK;
  1958. BOOL fDone = false;
  1959. TTSWord Word;
  1960. ZeroMemory( &Word, sizeof(TTSWord) );
  1961. Word.pXmlState = &m_pCurrFrag->State;
  1962. Word.eWordPartOfSpeech = MS_Unknown;
  1963. //--- Four digit form
  1964. if ( pItemInfo->pCentury )
  1965. {
  1966. //--- Cover special cases first
  1967. //--- 00dds
  1968. if ( pItemInfo->pCentury[0] == '0' &&
  1969. pItemInfo->pCentury[1] == '0' )
  1970. {
  1971. //--- 0000s - expand as "zeroes"
  1972. if ( pItemInfo->ulDecade == 0 )
  1973. {
  1974. Word.pWordText = g_Zeroes.pStr;
  1975. Word.ulWordLen = g_Zeroes.Len;
  1976. Word.pLemma = Word.pWordText;
  1977. Word.ulLemmaLen = Word.ulWordLen;
  1978. WordList.AddTail( Word );
  1979. fDone = true;
  1980. }
  1981. //--- 00d0s
  1982. else
  1983. {
  1984. // Just expand the decade part as we normally would
  1985. NULL;
  1986. }
  1987. }
  1988. //--- 0dd0s - expand as "d hundreds" or "d hundred [decade part]"
  1989. else if ( pItemInfo->pCentury[0] == '0' )
  1990. {
  1991. //--- insert first digit
  1992. Word.pWordText = g_ones[ pItemInfo->pCentury[0] - L'0' ].pStr;
  1993. Word.ulWordLen = g_ones[ pItemInfo->pCentury[0] - L'0' ].Len;
  1994. Word.pLemma = Word.pWordText;
  1995. Word.ulLemmaLen = Word.ulWordLen;
  1996. WordList.AddTail( Word );
  1997. //--- 0d00s - expand as "d hundreds"
  1998. if ( SUCCEEDED( hr ) &&
  1999. pItemInfo->ulDecade == 0 )
  2000. {
  2001. Word.pWordText = g_Hundreds.pStr;
  2002. Word.ulWordLen = g_Hundreds.Len;
  2003. Word.pLemma = Word.pWordText;
  2004. Word.ulLemmaLen = Word.ulWordLen;
  2005. WordList.AddTail( Word );
  2006. fDone = true;
  2007. }
  2008. //--- 0dd0s - expand as "d hundred [decade part]"
  2009. else if ( SUCCEEDED( hr ) )
  2010. {
  2011. Word.pWordText = g_hundred.pStr;
  2012. Word.ulWordLen = g_hundred.Len;
  2013. Word.pLemma = Word.pWordText;
  2014. Word.ulLemmaLen = Word.ulWordLen;
  2015. WordList.AddTail( Word );
  2016. }
  2017. }
  2018. //--- d000s, dd00s - expand as "d thousands" or "dd hundreds"
  2019. else if ( pItemInfo->ulDecade == 0 )
  2020. {
  2021. //--- d000s - "d thousands" ( "thousands" will get inserted below )
  2022. if ( pItemInfo->pCentury[1] == '0' )
  2023. {
  2024. Word.pWordText = g_ones[ pItemInfo->pCentury[0] - L'0' ].pStr;
  2025. Word.ulWordLen = g_ones[ pItemInfo->pCentury[0] - L'0' ].Len;
  2026. Word.pLemma = Word.pWordText;
  2027. Word.ulLemmaLen = Word.ulWordLen;
  2028. WordList.AddTail( Word );
  2029. }
  2030. //--- dd00s - "dd hundreds"
  2031. else
  2032. {
  2033. NumberGroup Garbage;
  2034. ExpandTwoDigits( pItemInfo->pCentury, Garbage, WordList );
  2035. Word.pWordText = g_Hundreds.pStr;
  2036. Word.ulWordLen = g_Hundreds.Len;
  2037. Word.pLemma = Word.pWordText;
  2038. Word.ulLemmaLen = Word.ulWordLen;
  2039. WordList.AddTail( Word );
  2040. fDone = true;
  2041. }
  2042. }
  2043. //--- Default case: ddd0s - expand as "dd [decade part]"
  2044. else
  2045. {
  2046. NumberGroup Garbage;
  2047. ExpandTwoDigits( pItemInfo->pCentury, Garbage, WordList );
  2048. }
  2049. }
  2050. //--- Special case - 00s should expand as "two thousands"
  2051. else if ( pItemInfo->ulDecade == 0 )
  2052. {
  2053. Word.pWordText = g_ones[2].pStr;
  2054. Word.ulWordLen = g_ones[2].Len;
  2055. Word.pLemma = Word.pWordText;
  2056. Word.ulLemmaLen = Word.ulWordLen;
  2057. WordList.AddTail( Word );
  2058. }
  2059. //--- Expand decade part, if necessary
  2060. if ( SUCCEEDED(hr) &&
  2061. !fDone )
  2062. {
  2063. Word.pWordText = g_Decades[ pItemInfo->ulDecade ].pStr;
  2064. Word.ulWordLen = g_Decades[ pItemInfo->ulDecade ].Len;
  2065. Word.pLemma = Word.pWordText;
  2066. Word.ulLemmaLen = Word.ulWordLen;
  2067. WordList.AddTail( Word );
  2068. }
  2069. return hr;
  2070. } /* ExpandDecade */
  2071. /***********************************************************************************************
  2072. * MatchMonthString *
  2073. *------------------*
  2074. * Description:
  2075. * This is just a helper function - it returns the integer value of the month found in
  2076. * its WCHAR string parameter ("January" is 1, "February" 2, etc.) or zero if it finds no match.
  2077. * It also checks three letter abbreviations - "Jan", "Feb", etc.
  2078. * Note: This function does not do parameter validation. Assumed to be done by caller
  2079. * (GetNumber should be called first to get the NumberInfo structure and valiDate parameters).
  2080. ********************************************************************* AH **********************/
  2081. ULONG CStdSentEnum::MatchMonthString( WCHAR*& pMonth, ULONG ulLength )
  2082. {
  2083. ULONG ulMonth = 0;
  2084. //--- Check full months strings
  2085. for ( int i = 0; i < sp_countof(g_months); i++ )
  2086. {
  2087. if ( ulLength >= (ULONG) g_months[i].Len &&
  2088. wcsnicmp( pMonth, g_months[i].pStr, g_months[i].Len ) == 0 )
  2089. {
  2090. ulMonth = i + 1;
  2091. pMonth = pMonth + g_months[i].Len;
  2092. break;
  2093. }
  2094. }
  2095. //--- Check month abbreviations
  2096. if ( !ulMonth )
  2097. {
  2098. for ( i = 0; i < sp_countof(g_monthAbbreviations); i++ )
  2099. {
  2100. if ( ulLength >= (ULONG) g_monthAbbreviations[i].Len &&
  2101. wcsnicmp( pMonth, g_monthAbbreviations[i].pStr, g_monthAbbreviations[i].Len ) == 0 )
  2102. {
  2103. if ( i > 8 )
  2104. {
  2105. ulMonth = i;
  2106. }
  2107. else
  2108. {
  2109. ulMonth = i + 1;
  2110. }
  2111. pMonth = pMonth + g_monthAbbreviations[i].Len;
  2112. if ( *pMonth == L'.' )
  2113. {
  2114. pMonth++;
  2115. }
  2116. break;
  2117. }
  2118. }
  2119. }
  2120. return ulMonth;
  2121. } /* MatchMonthString */
  2122. /***********************************************************************************************
  2123. * MatchDayString *
  2124. *----------------*
  2125. * Description:
  2126. * This is just a helper function - it returns the integer value of the day found in
  2127. * its WCHAR string parameter ("Monday" is 0, "Tuesday" 1, etc.) or -1 if it finds no match.
  2128. * It also checks abbreviations - "Mon", "Tue", etc.
  2129. * Note: This function does not do parameter validation. Assumed to be done by caller
  2130. ********************************************************************* AH **********************/
  2131. ULONG CStdSentEnum::MatchDayString( WCHAR*& pDayString, WCHAR* pEndChar )
  2132. {
  2133. ULONG ulDay = 0;
  2134. //--- Check full day strings
  2135. for ( int i = 0; i < sp_countof(g_days); i++ )
  2136. {
  2137. if ( pEndChar - pDayString >= g_days[i].Len &&
  2138. wcsnicmp( pDayString, g_days[i].pStr, g_days[i].Len ) == 0 )
  2139. {
  2140. ulDay = i + 1;
  2141. pDayString = pDayString + g_days[i].Len;
  2142. break;
  2143. }
  2144. }
  2145. //--- Check month abbreviations
  2146. if ( !ulDay )
  2147. {
  2148. for ( i = 0; i < sp_countof(g_dayAbbreviations); i++ )
  2149. {
  2150. if ( pEndChar - pDayString >= g_dayAbbreviations[i].Len &&
  2151. wcsncmp( pDayString, g_dayAbbreviations[i].pStr, g_dayAbbreviations[i].Len ) == 0 )
  2152. {
  2153. switch (i)
  2154. {
  2155. //--- Mon, Tues
  2156. case 0:
  2157. case 1:
  2158. ulDay = i + 1;
  2159. break;
  2160. //--- Tue, Wed, Thurs
  2161. case 2:
  2162. case 3:
  2163. case 4:
  2164. ulDay = i;
  2165. break;
  2166. //--- Thur, Thu
  2167. case 5:
  2168. case 6:
  2169. ulDay = 4;
  2170. break;
  2171. //--- Fri, Sat, Sun
  2172. case 7:
  2173. case 8:
  2174. case 9:
  2175. ulDay = i - 2;
  2176. break;
  2177. }
  2178. pDayString = pDayString + g_dayAbbreviations[i].Len;
  2179. if ( *pDayString == L'.' )
  2180. {
  2181. pDayString++;
  2182. }
  2183. break;
  2184. }
  2185. }
  2186. }
  2187. return ulDay;
  2188. } /* MatchDayString */
  2189. /***********************************************************************************************
  2190. * MatchDateDelimiter *
  2191. *--------------------*
  2192. * Description:
  2193. * This is just a helper function - it returns true or false based on whether the first
  2194. * character in its parameter string is a valid Date Delimiter. It also advances its parameter
  2195. * string pointer one position (past the Date Delimiter) and replaces a valid delimiter with
  2196. * a null terminator.
  2197. * Note: This function does not do parameter validation. Assumed to be done by caller
  2198. * (GetNumber should be called first to get the NumberInfo structure and valiDate parameters).
  2199. ********************************************************************* AH **********************/
  2200. bool CStdSentEnum::MatchDateDelimiter( WCHAR** DateString )
  2201. {
  2202. bool bIsDelimiter = false;
  2203. if (DateString)
  2204. {
  2205. for (int i = 0; i < sp_countof(g_DateDelimiters); i++)
  2206. {
  2207. if (*DateString[0] == g_DateDelimiters[i])
  2208. {
  2209. bIsDelimiter = true;
  2210. *DateString = *DateString + 1;
  2211. break;
  2212. }
  2213. }
  2214. }
  2215. return bIsDelimiter;
  2216. } /* MatchDateDelimiter */
  2217. //------------End Of File-----------------------------------------------------------------------------