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.

953 lines
23 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // PhoneContext.cpp: implementation of the CPhoneContext class and
  3. // subclasses.
  4. //
  5. // Created by JOEM 03-2000
  6. // Copyright (C) 2000 Microsoft Corporation
  7. // All Rights Reserved
  8. //
  9. /////////////////////////////////////////////////////// JOEM 3-2000 //
  10. #include "stdafx.h"
  11. #include "PhoneContext.h"
  12. #include <stdio.h>
  13. //////////////////////////////////////////////////////////////////////
  14. // CPhoneContext
  15. // Construction/Destruction
  16. /////////////////////////////////////////////////////// JOEM 3-2000 //
  17. CPhoneContext::CPhoneContext()
  18. {
  19. m_ulNRules = 0;
  20. m_ppContextRules = NULL;
  21. }
  22. CPhoneContext::~CPhoneContext()
  23. {
  24. ULONG i = 0;
  25. ULONG j = 0;
  26. ULONG k = 0;
  27. for (i=0; i<m_ulNRules; i++)
  28. {
  29. DeleteContextRule( m_ppContextRules[i] );
  30. }
  31. free (m_ppContextRules);
  32. }
  33. //////////////////////////////////////////////////////////////////////
  34. // CPhoneContext::Load
  35. //
  36. // Reads in the phone context file.
  37. //
  38. /////////////////////////////////////////////////////// JOEM 3-2000 //
  39. HRESULT CPhoneContext::Load(const WCHAR *pszPathName)
  40. {
  41. HRESULT hr = S_OK;
  42. FILE* fp = NULL;
  43. WCHAR line[256] = L"";
  44. WCHAR* ptr = NULL;
  45. Macro* macros = NULL;
  46. USHORT nMacros = 0;
  47. USHORT state = 0;
  48. SPDBG_ASSERT (pszPathName);
  49. if ((fp = _wfopen(pszPathName, L"r")) == NULL)
  50. {
  51. hr = E_FAIL;
  52. }
  53. state = 0;
  54. while ( SUCCEEDED(hr) && fgetws (line, sizeof(line), fp) )
  55. {
  56. // Strip off the newline character
  57. if (line[wcslen(line)-1] == L'\n')
  58. {
  59. line[wcslen(line)-1] = L'\0';
  60. }
  61. // Line ends when a comment marker is found
  62. if ( (ptr = wcschr (line, L'#')) != NULL )
  63. {
  64. *ptr = L'\0';
  65. }
  66. ptr = line;
  67. WSkipWhiteSpace (ptr);
  68. if (!*ptr)
  69. {
  70. continue;
  71. }
  72. // Could be a macro
  73. if (*ptr == L'%')
  74. {
  75. hr = ReadMacro (ptr, &macros, &nMacros);
  76. }
  77. else
  78. {
  79. // It's not a macro, must be a rule
  80. while ( SUCCEEDED(hr) && *ptr )
  81. {
  82. switch (state) {
  83. case 0:
  84. {
  85. WCHAR* end;
  86. end = ptr;
  87. WSkipNonWhiteSpace(end);
  88. *end++ = L'\0';
  89. state = 1;
  90. hr = CreateRule (ptr);
  91. if ( SUCCEEDED(hr) )
  92. {
  93. ptr = end;
  94. WSkipWhiteSpace (ptr);
  95. }
  96. }
  97. break;
  98. case 1:
  99. if (*ptr == L'{')
  100. {
  101. ptr++;
  102. WSkipWhiteSpace(ptr);
  103. state = 2;
  104. }
  105. else
  106. {
  107. hr = E_FAIL;
  108. }
  109. break;
  110. case 2:
  111. // We are in a rule, load several phoneClasses
  112. if (*ptr == L'}')
  113. {
  114. state = 0;
  115. ptr++;
  116. WSkipWhiteSpace (ptr);
  117. }
  118. else
  119. {
  120. hr = ParsePhoneClass (macros, nMacros, m_ppContextRules[m_ulNRules-1], &ptr);
  121. }
  122. break;
  123. default:
  124. hr = E_FAIL;
  125. }
  126. } // while (*ptr)
  127. } // else (Not a macro)
  128. } // while ( SUCCEEDED(hr) && fgetws ...
  129. if (fp)
  130. {
  131. fclose(fp);
  132. }
  133. if (macros)
  134. {
  135. free(macros);
  136. }
  137. return hr;
  138. }
  139. //////////////////////////////////////////////////////////////////////
  140. // CPhoneContext::Apply
  141. //
  142. // Applies phone context rules to determine transition cost between
  143. // the previous and current entry.
  144. //
  145. /////////////////////////////////////////////////////// JOEM 3-2000 //
  146. HRESULT CPhoneContext::Apply(IPromptEntry *pPreviousIPE, IPromptEntry *pCurrentIPE, double *pdCost)
  147. {
  148. HRESULT hr = S_OK;
  149. double partialCost = 0;
  150. const WCHAR* prevPhone = NULL;
  151. const WCHAR* prevContext = NULL;
  152. const WCHAR* curPhone = NULL;
  153. const WCHAR* curContext = NULL;
  154. SPDBG_ASSERT (pPreviousIPE);
  155. SPDBG_ASSERT (pCurrentIPE);
  156. SPDBG_ASSERT (pdCost);
  157. *pdCost = 0.0;
  158. // Should these two partial costs have the same weight?
  159. if ( SUCCEEDED(hr) )
  160. {
  161. hr = SearchPhoneTag (pPreviousIPE, &prevPhone, g_Phone_Tags[END_TAG]);
  162. }
  163. if ( SUCCEEDED(hr) )
  164. {
  165. hr = SearchPhoneTag (pCurrentIPE, &curContext, g_Phone_Tags[LEFT_TAG]);
  166. }
  167. if ( SUCCEEDED(hr) )
  168. {
  169. hr = ApplyPhoneticRule (prevPhone, curContext, &partialCost);
  170. if ( SUCCEEDED(hr) )
  171. {
  172. *pdCost += partialCost;
  173. }
  174. }
  175. if ( SUCCEEDED(hr) )
  176. {
  177. hr = SearchPhoneTag (pPreviousIPE, &prevContext, g_Phone_Tags[RIGHT_TAG]);
  178. }
  179. if ( SUCCEEDED(hr) )
  180. {
  181. SearchPhoneTag (pCurrentIPE, &curPhone, g_Phone_Tags[START_TAG]);
  182. }
  183. if ( SUCCEEDED(hr) )
  184. {
  185. hr = ApplyPhoneticRule (curPhone, prevContext, &partialCost);
  186. if ( SUCCEEDED(hr) )
  187. {
  188. *pdCost += partialCost;
  189. }
  190. }
  191. return hr;
  192. }
  193. //////////////////////////////////////////////////////////////////////
  194. // CPhoneContext::ReadMacro
  195. //
  196. // Helper function to read in a macro from the Phone context file.
  197. //
  198. /////////////////////////////////////////////////////// JOEM 3-2000 //
  199. HRESULT CPhoneContext::ReadMacro(const WCHAR *pszText, Macro **ppMacros, USHORT *punMacros)
  200. {
  201. HRESULT hr = S_OK;
  202. SPDBG_ASSERT(pszText);
  203. SPDBG_ASSERT(ppMacros);
  204. SPDBG_ASSERT(punMacros);
  205. if (*ppMacros)
  206. {
  207. *ppMacros = (Macro*) realloc (*ppMacros, (*punMacros + 1) * sizeof (**ppMacros));
  208. }
  209. else
  210. {
  211. *ppMacros = (Macro*) malloc (sizeof (**ppMacros));
  212. }
  213. if (*ppMacros == NULL)
  214. {
  215. hr = E_OUTOFMEMORY;
  216. }
  217. if ( SUCCEEDED(hr) )
  218. {
  219. if (swscanf (pszText, L"%%%32s %lf", (*ppMacros)[*punMacros].name, &(*ppMacros)[*punMacros].value) != 2)
  220. {
  221. hr = E_FAIL;
  222. }
  223. }
  224. if ( SUCCEEDED(hr) )
  225. {
  226. (*punMacros)++;
  227. }
  228. return hr;
  229. }
  230. //////////////////////////////////////////////////////////////////////
  231. // CPhoneContext::CreateRule
  232. //
  233. // Helper function to read in a macro from the Phone context file.
  234. //
  235. /////////////////////////////////////////////////////// JOEM 3-2000 //
  236. HRESULT CPhoneContext::CreateRule(const WCHAR *pszText)
  237. {
  238. HRESULT hr = S_OK;
  239. CContextRule* newRule = NULL;
  240. SPDBG_ASSERT (pszText);
  241. if (m_ppContextRules)
  242. {
  243. m_ppContextRules = (CContextRule**) realloc (m_ppContextRules, (m_ulNRules + 1) * sizeof(*m_ppContextRules));
  244. }
  245. else
  246. {
  247. m_ppContextRules = (CContextRule**) malloc (sizeof(*m_ppContextRules));
  248. }
  249. if (!m_ppContextRules)
  250. {
  251. hr = E_OUTOFMEMORY;
  252. }
  253. if ( SUCCEEDED(hr) )
  254. {
  255. if ((newRule = (CContextRule*) calloc (1, sizeof(*newRule))) == NULL)
  256. {
  257. hr = E_OUTOFMEMORY;
  258. }
  259. }
  260. if ( SUCCEEDED(hr) )
  261. {
  262. if ( (newRule->m_pszRuleName = wcsdup(pszText)) == NULL)
  263. {
  264. hr = E_OUTOFMEMORY;
  265. }
  266. else
  267. {
  268. hr = RegularizeText(newRule->m_pszRuleName, KEEP_PUNCTUATION);
  269. }
  270. }
  271. if ( SUCCEEDED(hr) )
  272. {
  273. m_ppContextRules[m_ulNRules] = newRule;
  274. m_ulNRules++;
  275. }
  276. if ( FAILED(hr) )
  277. {
  278. if ( newRule )
  279. {
  280. if ( newRule->m_pszRuleName )
  281. {
  282. free (newRule->m_pszRuleName);
  283. newRule->m_pszRuleName = NULL;
  284. }
  285. free (newRule);
  286. newRule = NULL;
  287. }
  288. }
  289. return hr;
  290. }
  291. //////////////////////////////////////////////////////////////////////
  292. // CPhoneContext::ParsePhoneClass
  293. //
  294. // Reads, parses, creates a phone class. Adds phones to class.
  295. //
  296. /////////////////////////////////////////////////////// JOEM 3-2000 //
  297. HRESULT CPhoneContext::ParsePhoneClass(const Macro *pMacros, const USHORT unMacros, CContextRule* pRule, WCHAR **ppszOrig)
  298. {
  299. HRESULT hr = S_OK;
  300. WCHAR* ptr = NULL;
  301. WCHAR* end = NULL;
  302. int i;
  303. SPDBG_ASSERT (ppszOrig && *ppszOrig);
  304. ptr = *ppszOrig;
  305. WSkipWhiteSpace (ptr);
  306. end = ptr;
  307. WSkipNonWhiteSpace (end);
  308. *end++ = L'\0';
  309. if ( SUCCEEDED(hr) )
  310. {
  311. hr = CreatePhoneClass (&pRule->m_pvPhoneClasses, &pRule->m_unNPhoneClasses, ptr);
  312. }
  313. if ( SUCCEEDED(hr) )
  314. {
  315. ptr = end;
  316. WSkipWhiteSpace (ptr);
  317. if (*ptr != L'{') {
  318. return 0;
  319. }
  320. ptr ++;
  321. WSkipWhiteSpace (ptr);
  322. }
  323. if ( SUCCEEDED(hr) )
  324. {
  325. while ( SUCCEEDED(hr) && *ptr!= L'}' )
  326. {
  327. if (*ptr == L'\0')
  328. {
  329. hr = E_FAIL;
  330. }
  331. if ( SUCCEEDED(hr) )
  332. {
  333. end = ptr;
  334. WSkipNonWhiteSpace (end);
  335. *end++ = L'\0';
  336. hr = AddPhoneToClass (pRule->m_pvPhoneClasses[pRule->m_unNPhoneClasses-1], ptr);
  337. }
  338. if ( SUCCEEDED(hr) )
  339. {
  340. ptr = end;
  341. WSkipWhiteSpace (ptr);
  342. }
  343. }
  344. }
  345. if ( SUCCEEDED(hr) )
  346. {
  347. ptr++;
  348. WSkipWhiteSpace(ptr);
  349. if (*ptr == L'%')
  350. {
  351. // It is a macro
  352. ptr++;
  353. for (i=0; i<unMacros; i++)
  354. {
  355. if (wcsncmp (ptr, pMacros[i].name, wcslen(pMacros[i].name)) == 0)
  356. {
  357. pRule->m_pvPhoneClasses[pRule->m_unNPhoneClasses-1]->m_dWeight
  358. = pMacros[i].value;
  359. break;
  360. }
  361. }
  362. if (i == unMacros)
  363. {
  364. hr = E_FAIL;
  365. }
  366. }
  367. else
  368. {
  369. // Get the value directly
  370. pRule->m_pvPhoneClasses[pRule->m_unNPhoneClasses-1]->m_dWeight
  371. = wcstod(ptr, NULL);
  372. }
  373. }
  374. if ( SUCCEEDED(hr) )
  375. {
  376. WSkipNonWhiteSpace(ptr);
  377. WSkipWhiteSpace(ptr);
  378. *ppszOrig = ptr;
  379. }
  380. return hr;
  381. }
  382. //////////////////////////////////////////////////////////////////////
  383. // CPhoneContext
  384. //
  385. // CreatePhoneClass
  386. //
  387. /////////////////////////////////////////////////////// JOEM 3-2000 //
  388. HRESULT CPhoneContext::CreatePhoneClass(CPhoneClass*** pppClasses, USHORT* punClasses, const WCHAR *psz)
  389. {
  390. HRESULT hr = S_OK;
  391. CPhoneClass* phClass = NULL;
  392. SPDBG_ASSERT (pppClasses);
  393. SPDBG_ASSERT (punClasses);
  394. SPDBG_ASSERT (psz);
  395. if ( SUCCEEDED(hr) )
  396. {
  397. if ((phClass = (CPhoneClass*) calloc (1, sizeof(*phClass))) == NULL)
  398. {
  399. hr = E_OUTOFMEMORY;
  400. }
  401. }
  402. if ( SUCCEEDED(hr) )
  403. {
  404. if ((phClass->m_pszPhoneClassName = wcsdup(psz)) == NULL)
  405. {
  406. hr = E_OUTOFMEMORY;
  407. }
  408. else
  409. {
  410. hr = RegularizeText(phClass->m_pszPhoneClassName, KEEP_PUNCTUATION);
  411. }
  412. }
  413. if ( SUCCEEDED(hr) )
  414. {
  415. if (*pppClasses)
  416. {
  417. *pppClasses = (CPhoneClass**) realloc (*pppClasses, (*punClasses +1) * sizeof(**pppClasses));
  418. }
  419. else
  420. {
  421. *pppClasses = (CPhoneClass**) malloc (sizeof(**pppClasses));
  422. }
  423. if (*pppClasses == NULL)
  424. {
  425. hr = E_OUTOFMEMORY;
  426. }
  427. }
  428. if ( SUCCEEDED(hr) )
  429. {
  430. (*pppClasses)[*punClasses] = phClass;
  431. (*punClasses)++;
  432. }
  433. if ( FAILED(hr) )
  434. {
  435. DeletePhoneClass (phClass);
  436. }
  437. return hr;
  438. }
  439. //////////////////////////////////////////////////////////////////////
  440. // CPhoneContext
  441. //
  442. // AddPhoneToClass
  443. //
  444. /////////////////////////////////////////////////////// JOEM 3-2000 //
  445. HRESULT CPhoneContext::AddPhoneToClass(CPhoneClass* phClass, WCHAR *phone)
  446. {
  447. HRESULT hr = S_OK;
  448. SPDBG_ASSERT(phClass);
  449. if (phClass->m_pppszPhones)
  450. {
  451. phClass->m_pppszPhones = (WCHAR**) realloc (phClass->m_pppszPhones, (phClass->m_unNPhones +1) * sizeof (*phClass->m_pppszPhones));
  452. }
  453. else
  454. {
  455. phClass->m_pppszPhones = (WCHAR**) malloc (sizeof (*phClass->m_pppszPhones));
  456. }
  457. if (phClass->m_pppszPhones == NULL)
  458. {
  459. hr = E_OUTOFMEMORY;
  460. }
  461. if ( SUCCEEDED(hr) )
  462. {
  463. if ( (phClass->m_pppszPhones[phClass->m_unNPhones] = wcsdup(phone)) == NULL )
  464. {
  465. hr = E_OUTOFMEMORY;
  466. }
  467. else
  468. {
  469. hr = RegularizeText(phClass->m_pppszPhones[phClass->m_unNPhones], KEEP_PUNCTUATION);
  470. }
  471. }
  472. if ( SUCCEEDED(hr) )
  473. {
  474. phClass->m_unNPhones++;
  475. }
  476. return hr;
  477. }
  478. //////////////////////////////////////////////////////////////////////
  479. // CPhoneContext
  480. //
  481. // SearchPhoneTag
  482. //
  483. /////////////////////////////////////////////////////// JOEM 3-2000 //
  484. HRESULT CPhoneContext::SearchPhoneTag(IPromptEntry *pIPE, const WCHAR **result, CONTEXT_PHONE_TAG phoneTag)
  485. {
  486. HRESULT hr = S_OK;
  487. WCHAR* ptr = NULL;
  488. USHORT nTags = 0;
  489. const WCHAR* tag = L"";
  490. int i = 0;
  491. SPDBG_ASSERT (result);
  492. switch ( phoneTag.iPhoneTag )
  493. {
  494. case START_TAG:
  495. hr = pIPE->GetStartPhone( result );
  496. break;
  497. case END_TAG:
  498. hr = pIPE->GetEndPhone( result );
  499. break;
  500. case RIGHT_TAG:
  501. hr = pIPE->GetRightContext( result );
  502. break;
  503. case LEFT_TAG:
  504. hr = pIPE->GetLeftContext( result );
  505. break;
  506. default:
  507. *result = NULL;
  508. break;
  509. }
  510. return hr;
  511. }
  512. //////////////////////////////////////////////////////////////////////
  513. // CPhoneContext
  514. //
  515. // ApplyPhoneticRule
  516. //
  517. /////////////////////////////////////////////////////// JOEM 3-2000 //
  518. HRESULT CPhoneContext::ApplyPhoneticRule(const WCHAR *pszPhone, const WCHAR *pszContext, double *cost)
  519. {
  520. HRESULT hr = S_OK;
  521. CContextRule* rule = NULL;
  522. bool fDone = false;
  523. WCHAR* phnNextRule = NULL;
  524. WCHAR* cntxtNextRule = NULL;
  525. SPDBG_ASSERT (cost);
  526. if ( SUCCEEDED(hr) )
  527. {
  528. hr = FindContextRule (L"MAIN", &rule);
  529. }
  530. if ( SUCCEEDED(hr) )
  531. {
  532. // cost initialized to no match at all
  533. hr = GetWeight (rule, L"NONE", cost);
  534. }
  535. if ( !pszPhone || !pszContext )
  536. {
  537. fDone = true;
  538. }
  539. if ( SUCCEEDED(hr) && !fDone )
  540. {
  541. // First try if they are the same
  542. if (wcscmp (pszPhone, pszContext) == 0)
  543. {
  544. hr = GetWeight (rule, L"ALL", cost);
  545. fDone = true;
  546. }
  547. }
  548. if ( SUCCEEDED(hr) && !fDone )
  549. {
  550. // Now iterate over the rules
  551. do
  552. {
  553. if ( SUCCEEDED(hr) && !fDone )
  554. {
  555. hr = ApplyRule (rule, pszPhone, &phnNextRule);
  556. }
  557. if ( SUCCEEDED(hr) && !fDone )
  558. {
  559. hr = ApplyRule (rule, pszContext, &cntxtNextRule);
  560. }
  561. if ( SUCCEEDED(hr) && !fDone && phnNextRule && cntxtNextRule )
  562. {
  563. // if the two phones are both in the same next rule, continue. Otherwise, done.
  564. if ( phnNextRule && cntxtNextRule && wcscmp(phnNextRule, cntxtNextRule) )
  565. {
  566. fDone = true;
  567. }
  568. }
  569. if ( SUCCEEDED(hr) && !fDone && phnNextRule && cntxtNextRule )
  570. {
  571. // They are the same, get the cost for the next iteration
  572. hr = GetWeight (rule, phnNextRule, cost);
  573. }
  574. if ( SUCCEEDED(hr) && !fDone && phnNextRule && cntxtNextRule )
  575. {
  576. // And the next rule to apply
  577. hr = FindContextRule (phnNextRule, &rule);
  578. if ( FAILED(hr) )
  579. {
  580. fDone = true;
  581. hr = S_OK;
  582. }
  583. }
  584. } while ( !fDone && rule && phnNextRule && cntxtNextRule);
  585. }
  586. return hr;
  587. }
  588. //////////////////////////////////////////////////////////////////////
  589. // CPhoneContext
  590. //
  591. // FindContextRule
  592. //
  593. /////////////////////////////////////////////////////// JOEM 3-2000 //
  594. HRESULT CPhoneContext::FindContextRule(const WCHAR *pszName, CContextRule** ppRule)
  595. {
  596. HRESULT hr = E_FAIL;
  597. USHORT i = 0;
  598. SPDBG_ASSERT(pszName);
  599. for (i=0; i< m_ulNRules; i++)
  600. {
  601. if ( wcscmp (m_ppContextRules[i]->m_pszRuleName, pszName) == 0 )
  602. {
  603. *ppRule = m_ppContextRules[i];
  604. hr = S_OK;
  605. break;
  606. }
  607. }
  608. return hr;
  609. }
  610. //////////////////////////////////////////////////////////////////////
  611. // CPhoneContext
  612. //
  613. // ApplyRule
  614. //
  615. /////////////////////////////////////////////////////// JOEM 3-2000 //
  616. HRESULT CPhoneContext::ApplyRule(const CContextRule *pRule, const WCHAR *pszPhone, WCHAR** ppszNextRule)
  617. {
  618. HRESULT hr = S_FALSE;
  619. USHORT i = 0;
  620. USHORT j = 0;
  621. SPDBG_ASSERT (pRule);
  622. SPDBG_ASSERT (pszPhone);
  623. *ppszNextRule = NULL;
  624. for ( i=0; i < pRule->m_unNPhoneClasses; i++ )
  625. {
  626. for ( j=0; j < pRule->m_pvPhoneClasses[i]->m_unNPhones; j++ )
  627. {
  628. if ( wcscmp( pszPhone, pRule->m_pvPhoneClasses[i]->m_pppszPhones[j] ) == 0 )
  629. {
  630. *ppszNextRule = pRule->m_pvPhoneClasses[i]->m_pszPhoneClassName;
  631. hr = S_OK;
  632. break;
  633. }
  634. }
  635. if ( hr == S_OK )
  636. {
  637. break;
  638. }
  639. }
  640. return hr;
  641. }
  642. //////////////////////////////////////////////////////////////////////
  643. // CPhoneContext
  644. //
  645. // GetWeight
  646. //
  647. /////////////////////////////////////////////////////// JOEM 3-2000 //
  648. HRESULT CPhoneContext::GetWeight(const CContextRule *pRule, const WCHAR *pszName, double *pdCost)
  649. {
  650. HRESULT hr = E_FAIL;
  651. USHORT i = 0;
  652. SPDBG_ASSERT (pRule);
  653. SPDBG_ASSERT (pszName);
  654. SPDBG_ASSERT (pdCost);
  655. for (i=0; i < pRule->m_unNPhoneClasses; i++)
  656. {
  657. if ( wcscmp(pRule->m_pvPhoneClasses[i]->m_pszPhoneClassName, pszName) == 0 )
  658. {
  659. *pdCost = pRule->m_pvPhoneClasses[i]->m_dWeight;
  660. hr = S_OK;
  661. break;
  662. }
  663. }
  664. return hr;
  665. }
  666. //////////////////////////////////////////////////////////////////////
  667. // CPhoneContext
  668. //
  669. // DeletePhoneClass
  670. //
  671. /////////////////////////////////////////////////////// JOEM 3-2000 //
  672. void CPhoneContext::DeletePhoneClass(CPhoneClass *pClass)
  673. {
  674. if (pClass)
  675. {
  676. if (pClass->m_pszPhoneClassName)
  677. {
  678. free (pClass->m_pszPhoneClassName);
  679. }
  680. if (pClass->m_pppszPhones)
  681. {
  682. int i;
  683. for (i=0; i<pClass->m_unNPhones; i++)
  684. {
  685. free (pClass->m_pppszPhones[i]);
  686. }
  687. free (pClass->m_pppszPhones);
  688. }
  689. free (pClass);
  690. }
  691. }
  692. //////////////////////////////////////////////////////////////////////
  693. // CPhoneContext
  694. //
  695. // DeleteContextRule
  696. //
  697. /////////////////////////////////////////////////////// JOEM 3-2000 //
  698. void CPhoneContext::DeleteContextRule(CContextRule *pRule)
  699. {
  700. if (pRule)
  701. {
  702. if (pRule->m_pszRuleName)
  703. {
  704. free (pRule->m_pszRuleName);
  705. }
  706. if (pRule->m_pvPhoneClasses)
  707. {
  708. int i;
  709. for (i=0; i<pRule->m_unNPhoneClasses; i++)
  710. {
  711. DeletePhoneClass (pRule->m_pvPhoneClasses[i]);
  712. }
  713. free (pRule->m_pvPhoneClasses);
  714. }
  715. free (pRule);
  716. }
  717. }
  718. //////////////////////////////////////////////////////////////////////
  719. // CPhoneContext
  720. //
  721. // DebugPhoneContext
  722. //
  723. // Function for debug help - just outputs the entire CPhoneContext
  724. // class.
  725. //
  726. /////////////////////////////////////////////////////// JOEM 3-2000 //
  727. void CPhoneContext::DebugContextClass()
  728. {
  729. USHORT i = 0;
  730. USHORT j = 0;
  731. USHORT k = 0;
  732. WCHAR* RuleName = NULL;
  733. WCHAR* PhoneClassName = NULL;
  734. WCHAR* Phone = NULL;
  735. ULONG NumRules = 0;
  736. USHORT NumPhoneClasses = 0;
  737. USHORT NumPhones = 0;
  738. USHORT RuleCount = 0;
  739. USHORT PCCount = 0;
  740. USHORT PhoneCount = 0;
  741. double Weight = 0.0;
  742. WCHAR DebugStr[128];
  743. // Print out each rule
  744. for (i=0; i<m_ulNRules; i++)
  745. {
  746. RuleCount = i+1;
  747. NumRules = m_ulNRules;
  748. RuleName = m_ppContextRules[i]->m_pszRuleName;
  749. swprintf (DebugStr, L"Rule: %s, (%d of %d)\n", RuleName, RuleCount, NumRules);
  750. OutputDebugStringW(DebugStr);
  751. // Within each rule, print out the phone classes
  752. for (j=0; j<m_ppContextRules[i]->m_unNPhoneClasses; j++)
  753. {
  754. PCCount = j+1;
  755. NumPhoneClasses = m_ppContextRules[i]->m_unNPhoneClasses;
  756. PhoneClassName = m_ppContextRules[i]->m_pvPhoneClasses[j]->m_pszPhoneClassName;
  757. Weight = m_ppContextRules[i]->m_pvPhoneClasses[j]->m_dWeight;
  758. swprintf (DebugStr, L"\tPhoneClass: %s, (%d of %d) ... weight=%f\n", PhoneClassName, PCCount, NumPhoneClasses, Weight);
  759. OutputDebugStringW(DebugStr);
  760. // Within each phone class, print out the phones
  761. for (k=0; k<m_ppContextRules[i]->m_pvPhoneClasses[j]->m_unNPhones; k++)
  762. {
  763. PhoneCount = k+1;
  764. NumPhones = m_ppContextRules[i]->m_pvPhoneClasses[j]->m_unNPhones;
  765. Phone = m_ppContextRules[i]->m_pvPhoneClasses[j]->m_pppszPhones[k];
  766. swprintf (DebugStr, L"\t\tPhone: %s, (%d of %d)\n", Phone, PhoneCount, NumPhones);
  767. OutputDebugStringW(DebugStr);
  768. }
  769. }
  770. }
  771. }
  772. HRESULT CPhoneContext::LoadDefault()
  773. {
  774. HRESULT hr = S_OK;
  775. USHORT i = 0;
  776. USHORT j = 0;
  777. Macro* macros = NULL;
  778. USHORT nMacros = 0;
  779. WCHAR* pText = NULL;
  780. WCHAR* ptr = NULL;
  781. // Load the macros
  782. for ( i=0; i < g_nMacros; i++ )
  783. {
  784. pText = wcsdup(g_macros[i]);
  785. if ( !pText )
  786. {
  787. hr = E_OUTOFMEMORY;
  788. }
  789. else
  790. {
  791. hr = ReadMacro (pText, &macros, &nMacros);
  792. free(pText);
  793. pText = NULL;
  794. }
  795. }
  796. // Load the rules
  797. for ( i=0; i < g_nRules && SUCCEEDED(hr); i++ )
  798. {
  799. hr = CreateRule(g_rules[i].name);
  800. if ( SUCCEEDED(hr) )
  801. {
  802. j=0;
  803. while ( SUCCEEDED(hr) && g_rules[i].rule[j] )
  804. {
  805. if ( SUCCEEDED(hr) )
  806. {
  807. pText = wcsdup(g_rules[i].rule[j]);
  808. if ( !pText )
  809. {
  810. hr = E_OUTOFMEMORY;
  811. }
  812. else
  813. {
  814. ptr = pText;
  815. hr = ParsePhoneClass (macros, nMacros, m_ppContextRules[m_ulNRules-1], &ptr);
  816. free(pText);
  817. pText = NULL;
  818. }
  819. }
  820. j++;
  821. }
  822. }
  823. }
  824. if (macros)
  825. {
  826. free(macros);
  827. }
  828. //DebugContextClass();
  829. return hr;
  830. }