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.

1264 lines
30 KiB

  1. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation. All rights reserved.
  4. //
  5. // Module:
  6. // volcano/dll/FreeApi.c
  7. //
  8. // Description:
  9. // Implement external free input API for DLL.
  10. //
  11. // Author:
  12. // hrowley
  13. //
  14. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  15. #include "volcanop.h"
  16. #include "factoid.h"
  17. #include "recdefs.h"
  18. #include "brknet.h"
  19. /*
  20. * Definitions from penwin.h needed for inksets. We can't include it because
  21. * it has conflicts with recog.h
  22. */
  23. // inkset returns:
  24. #define ISR_ERROR (-1) // Memory or other error
  25. #define ISR_BADINKSET (-2) // bad source inkset
  26. #define ISR_BADINDEX (-3) // bad inkset index
  27. #define IX_END 0xFFFF // to or past last available index
  28. #ifdef HWX_TUNE
  29. #include <stdio.h>
  30. #endif
  31. //#define DEBUG_LOG_API
  32. #ifdef DEBUG_LOG_API
  33. #include <stdio.h>
  34. static void LogMessage(char *format, ...)
  35. {
  36. FILE *f=fopen("c:/log.txt","a");
  37. va_list marker;
  38. va_start(marker,format);
  39. vfprintf(f,format,marker);
  40. va_end(marker);
  41. fclose(f);
  42. }
  43. #else
  44. static void LogMessage(char *format, ...)
  45. {
  46. va_list marker;
  47. va_start(marker,format);
  48. va_end(marker);
  49. }
  50. #endif
  51. HRC CreateCompatibleHRC(HRC hrctemplate, HREC hrec)
  52. {
  53. VRC *pVRC;
  54. LogMessage("CreateCompatibleHRC()\n");
  55. hrec = hrec;
  56. // Alloc the VRC.
  57. pVRC = ExternAlloc(sizeof(VRC));
  58. if (!pVRC) {
  59. goto error1;
  60. }
  61. // Initialize it.
  62. pVRC->fBoxedInput = FALSE;
  63. pVRC->fHaveInput = FALSE;
  64. pVRC->fEndInput = FALSE;
  65. pVRC->fBeginProcess = FALSE;
  66. pVRC->pLatticePath = (LATTICE_PATH *)0;
  67. if (!hrctemplate) {
  68. pVRC->pLattice = AllocateLattice();
  69. if (!pVRC->pLattice) {
  70. goto error2;
  71. }
  72. } else {
  73. VRC *pVRCTemplate = (VRC *)hrctemplate;
  74. pVRC->pLattice = CreateCompatibleLattice(
  75. pVRCTemplate->pLattice
  76. );
  77. if (!pVRC->pLattice) {
  78. goto error2;
  79. }
  80. }
  81. // Success, cast to HRC and return it.
  82. return (HRC)pVRC;
  83. error2:
  84. ExternFree(pVRC);
  85. error1:
  86. return (HRC)0;
  87. }
  88. int DestroyHRC(HRC hrc)
  89. {
  90. VRC *pVRC = (VRC *)hrc;
  91. LogMessage("DestroyHRC()\n");
  92. // Did we get a handle? Is if a free input handle?
  93. if (!hrc || pVRC->fBoxedInput) {
  94. return HRCR_ERROR;
  95. }
  96. // Free the lattice. Should it be an error if there is not one?
  97. if (pVRC->pLattice) {
  98. FreeLattice(pVRC->pLattice);
  99. } else {
  100. ASSERT(pVRC->pLattice);
  101. }
  102. // Free the lattice path.
  103. if (pVRC->pLatticePath) {
  104. FreeLatticePath(pVRC->pLatticePath);
  105. }
  106. // Free the VRC itself.
  107. ExternFree(pVRC);
  108. return HRCR_OK;
  109. }
  110. int AddPenInputHRC(
  111. HRC hrc,
  112. POINT *ppnt,
  113. void *pvOem,
  114. UINT oemdatatype,
  115. STROKEINFO *psi
  116. ) {
  117. VRC *pVRC = (VRC *)hrc;
  118. int retVal;
  119. LogMessage("AddPenInputHRC()\n");
  120. pvOem = pvOem;
  121. oemdatatype = oemdatatype;
  122. // Did we get a handle? Does it have a lattice?
  123. if (!hrc || pVRC->fBoxedInput
  124. || !pVRC->pLattice || pVRC->fEndInput
  125. ) {
  126. return HRCR_ERROR;
  127. }
  128. // Do we have valid ink?
  129. if (psi->cPnt == 0 || !ppnt) {
  130. return HRCR_ERROR;
  131. }
  132. if (!(psi->wPdk & PDK_DOWN)) {
  133. return HRCR_OK;
  134. }
  135. // Add stroke to the lattice.
  136. retVal = AddStrokeToLattice(pVRC->pLattice, psi->cPnt, ppnt, psi->dwTick);
  137. // Mark as having input.
  138. pVRC->fHaveInput = TRUE;
  139. return(retVal ? HRCR_OK : HRCR_MEMERR);
  140. }
  141. int EndPenInputHRC(HRC hrc)
  142. {
  143. VRC *pVRC = (VRC *)hrc;
  144. LogMessage("EndPenInputHRC()\n");
  145. // Did we get a handle? Is it free input?
  146. // Does it have a lattice?
  147. // JBENN: Should it be an error if we have no strokes?
  148. if (!hrc || pVRC->fBoxedInput || !pVRC->pLattice) {
  149. return HRCR_ERROR;
  150. }
  151. pVRC->fEndInput = TRUE;
  152. return HRCR_OK;
  153. }
  154. int ProcessHRC(HRC hrc, DWORD timeout)
  155. {
  156. VRC *pVRC = (VRC *)hrc;
  157. LogMessage("ProcessHRC()\n");
  158. timeout = timeout;
  159. // Did we get a handle? Is it free input?
  160. // Does it have a lattice?
  161. // JBENN: Should it be an error if we have no strokes?
  162. if (!hrc || pVRC->fBoxedInput || !pVRC->pLattice)
  163. {
  164. return HRCR_ERROR;
  165. }
  166. // Have we already finished all processing?
  167. // if (pVRC->pLatticePath) {
  168. // return HRCR_OK;
  169. // }
  170. // Do any processing we can.
  171. if (!ProcessLattice(pVRC->pLattice, pVRC->fEndInput))
  172. {
  173. return HRCR_ERROR;
  174. }
  175. pVRC->fBeginProcess = TRUE;
  176. // in free mode, run the brknet to update the lattice
  177. // we only call this if end input had been called
  178. if (!pVRC->pLattice->fUseGuide && pVRC->fEndInput && !pVRC->pLattice->fSepMode && !pVRC->pLattice->fWordMode
  179. #ifdef HWX_TUNE
  180. && g_pTuneFile == NULL
  181. #endif
  182. )
  183. {
  184. UpdateLattice(pVRC->pLattice);
  185. }
  186. #ifdef USE_IFELANG3
  187. // Do we have all the input? Also, make sure we are not in separator mode
  188. if (pVRC->fEndInput && !pVRC->pLattice->fSepMode)
  189. {
  190. // Apply the language model.
  191. #ifdef HWX_TUNE
  192. // If we have tuning enabled, then never call IFELang3 directly.
  193. if (g_pTuneFile == NULL)
  194. #endif
  195. {
  196. ApplyLanguageModel(pVRC->pLattice, NULL);
  197. }
  198. }
  199. #endif
  200. // Free the old path, in case we got called before
  201. if (pVRC->pLatticePath != NULL)
  202. {
  203. FreeLatticePath(pVRC->pLatticePath);
  204. pVRC->pLatticePath = NULL;
  205. }
  206. // Get our final path. Note that the path may get changed
  207. // if ProcessHRC is called again, particularly after
  208. // EndPenInputHRC is called, because the language model will
  209. // be applied.
  210. if (!GetCurrentPath(pVRC->pLattice, &pVRC->pLatticePath))
  211. {
  212. return HRCR_ERROR;
  213. }
  214. ASSERT(pVRC->pLatticePath!=NULL);
  215. return HRCR_OK;
  216. }
  217. // Hacked free input results call.
  218. int GetResultsHRC(
  219. HRC hrc,
  220. UINT uType,
  221. HRCRESULT *pHRCResults,
  222. UINT cResults
  223. ) {
  224. VRC *pVRC = (VRC *)hrc;
  225. VRCRESULT *pVRCResults;
  226. LogMessage("GetResultsHRC()\n");
  227. // Check parameters.
  228. if (!hrc || pVRC->fBoxedInput || !pVRC->pLattice || !pHRCResults) {
  229. ASSERT(("Bad lattice\n",0));
  230. return HRCR_ERROR;
  231. }
  232. if (!pVRC->pLatticePath) {
  233. ASSERT(("Haven't processed input\n",0));
  234. return HRCR_ERROR;
  235. }
  236. if (uType == GRH_GESTURE || cResults == 0) {
  237. ASSERT(("Requested zero alternates\n",0));
  238. return 0;
  239. }
  240. // if (GetLatticeStrokeCount(pVRC->pLattice) < 1) {
  241. // ASSERT(("No strokes\n",0));
  242. // return 0;
  243. // }
  244. // Allocate space to hold results.
  245. pVRCResults = ExternAlloc(sizeof(VRCRESULT));
  246. if (!pVRCResults) {
  247. ASSERT(("No memory\n",0));
  248. return HRCR_ERROR;
  249. }
  250. // OK we have results. We always return a special code to indicate
  251. // return top one for everything.
  252. pVRCResults->pVRC = pVRC;
  253. pVRCResults->wch = ALL_TOP_ONE;
  254. *pHRCResults = (HRCRESULT)pVRCResults;
  255. return 1;
  256. }
  257. // The other hacked free input results call.
  258. int GetAlternateWordsHRCRESULT(
  259. HRCRESULT hrcResult,
  260. UINT iChar,
  261. UINT cChar,
  262. HRCRESULT *pHRCResults,
  263. UINT cHRCResults
  264. ) {
  265. VRCRESULT *pVRCResult = (VRCRESULT *)hrcResult;
  266. VRC *pVRC;
  267. UINT ii;
  268. UINT maxAlts, cAlts;
  269. UINT iCorrect;
  270. HRCRESULT hCorrect;
  271. wchar_t aAlts[MAX_ALTERNATES];
  272. LogMessage("GetAlternateWordsHRCRESULT()\n");
  273. // Check parameters.
  274. if (!hrcResult || !pHRCResults) {
  275. return HRCR_ERROR;
  276. }
  277. pVRC = pVRCResult->pVRC;
  278. if (!pVRC || pVRC->fBoxedInput || !pVRC->pLatticePath) {
  279. ASSERT(("Bad lattice or haven't processed input",0));
  280. return HRCR_ERROR;
  281. }
  282. if (pVRCResult->wch != ALL_TOP_ONE || cChar != 1) {
  283. return HRCR_UNSUPPORTED;
  284. }
  285. if (iChar >= (UINT)pVRC->pLatticePath->nChars) {
  286. return HRCR_UNSUPPORTED;
  287. }
  288. // Compute limit on alternates to return.
  289. maxAlts = min(MAX_ALTERNATES, cHRCResults);
  290. // Get the alternates.
  291. cAlts = GetAlternatesForCharacterInCurrentPath(
  292. pVRC->pLattice, pVRC->pLatticePath, iChar, maxAlts, aAlts
  293. );
  294. // Now build up array of results structures.
  295. iCorrect = (UINT)-1;
  296. for (ii = 0; ii < cAlts; ++ii) {
  297. VRCRESULT *pNew;
  298. // Allocate space to hold results.
  299. pNew = ExternAlloc(sizeof(VRCRESULT));
  300. if (!pNew) {
  301. UINT jj;
  302. // Clean up any allocated results
  303. for (jj = 0 ; jj < ii; ++jj) {
  304. ExternFree(pHRCResults[jj]);
  305. }
  306. return HRCR_ERROR;
  307. }
  308. // Fill in this alternate.
  309. pNew->pVRC = pVRC;
  310. pNew->wch = aAlts[ii];
  311. pNew->iChar = (short)iChar;
  312. pHRCResults[ii] = (HRCRESULT)pNew;
  313. if (pVRC->pLatticePath->pElem[iChar].wChar == aAlts[ii]) {
  314. iCorrect = ii;
  315. }
  316. }
  317. // If answer in path is not in list, over-write the last entry.
  318. if (iCorrect == (UINT)-1) {
  319. iCorrect = cAlts - 1;
  320. ((VRCRESULT *)(pHRCResults[iCorrect]))->wch = pVRC->pLatticePath->pElem[iChar].wChar;
  321. }
  322. // Now do the reorder as needed.
  323. hCorrect = pHRCResults[iCorrect];
  324. for (ii = iCorrect; ii > 0 ; --ii) {
  325. pHRCResults[ii] = pHRCResults[ii - 1];
  326. }
  327. pHRCResults[0] = hCorrect;
  328. // For debug version, be paranoid, and zero any unused elements in
  329. // the output array.
  330. # ifdef DBG
  331. for (ii = cAlts ; ii < cHRCResults; ++ii) {
  332. pHRCResults[ii] = (HRCRESULT)0;
  333. }
  334. # endif
  335. return cAlts;
  336. }
  337. // This does NOT include a null symbol at the end.
  338. int GetSymbolCountHRCRESULT(HRCRESULT hrcResult)
  339. {
  340. VRCRESULT *pVRCResult = (VRCRESULT *)hrcResult;
  341. VRC *pVRC;
  342. LogMessage("GetSymbolCountHRCRESULT()\n");
  343. if (!hrcResult) {
  344. return HRCR_ERROR;
  345. }
  346. pVRC = pVRCResult->pVRC;
  347. if (!pVRC || pVRC->fBoxedInput
  348. || !pVRC->pLatticePath
  349. ) {
  350. return HRCR_ERROR;
  351. }
  352. // Terminal HRCResults reflect only one character.
  353. if (pVRCResult->wch != ALL_TOP_ONE) {
  354. return 1;
  355. }
  356. // The path tells us how many character there are.
  357. LogMessage(" %d chars\n",pVRC->pLatticePath->nChars);
  358. return pVRC->pLatticePath->nChars;
  359. }
  360. // Convert an HRCRESULT into the correct character(s).
  361. int GetSymbolsHRCRESULT(
  362. HRCRESULT hrcResult,
  363. UINT iSyv,
  364. SYV *pSyv,
  365. UINT cSyv
  366. ) {
  367. VRCRESULT *pVRCResult = (VRCRESULT *)hrcResult;
  368. VRC *pVRC;
  369. LogMessage("GetSymbolsHRCRESULT()\n");
  370. if (!hrcResult) {
  371. return HRCR_ERROR;
  372. }
  373. pVRC = pVRCResult->pVRC;
  374. if (!pVRC || pVRC->fBoxedInput || pVRC->fBoxedInput
  375. || !pVRC->pLatticePath
  376. ) {
  377. return HRCR_ERROR;
  378. }
  379. // Did they really ask for anything.
  380. if (cSyv == 0 || iSyv >= (UINT)pVRC->pLatticePath->nChars) {
  381. return 0;
  382. }
  383. // Are we getting the full string, or just an alternate.
  384. if (pVRCResult->wch != ALL_TOP_ONE) {
  385. // Just one alternate.
  386. pSyv[0] = MAKELONG(pVRCResult->wch, SYVHI_UNICODE);
  387. LogMessage(" result U+%04X\n",pVRCResult->wch);
  388. return 1;
  389. } else {
  390. // Getting a full string.
  391. UINT ii;
  392. UINT cValid;
  393. // Characters available from requested starting position.
  394. cValid = pVRC->pLatticePath->nChars - iSyv;
  395. // Does the caller want fewer than we have available.
  396. if (cValid > cSyv) {
  397. cValid = cSyv;
  398. }
  399. // OK, copy over what we have.
  400. for (ii = 0; ii < cValid; ++ii) {
  401. wchar_t wch;
  402. wch = pVRC->pLatticePath->pElem[ii + iSyv].wChar;
  403. //wch = LocRunDense2Unicode(&g_locRunInfo, wch);
  404. LogMessage(" char %d is U+%04X\n",ii,wch);
  405. // Convert to SYV and put in output array.
  406. pSyv[ii] = MAKELONG(wch, SYVHI_UNICODE);
  407. }
  408. return cValid;
  409. }
  410. return 0;
  411. }
  412. // Translates an array of symbols into a Unicode string.
  413. // Code copied from \hwx\common, probably should be shared.
  414. BOOL SymbolToCharacterW(SYV *pSyv, int cSyv, WCHAR *wsz, int *pCount)
  415. {
  416. int c = 0;
  417. int ret = 1;
  418. LogMessage("SymbolToCharacterW()\n");
  419. for (; cSyv; pSyv++, wsz++, cSyv--, c++) {
  420. if (HIWORD(*pSyv) == SYVHI_UNICODE) {
  421. *wsz = LOWORD(*pSyv);
  422. } else if (HIWORD(*pSyv) == SYVHI_ANSI) {
  423. // No support for ANSI in EA recognizer.
  424. ASSERT(0);
  425. ret = 0;
  426. } else if (*pSyv == SYV_NULL) {
  427. *wsz = '\0';
  428. } else {
  429. *wsz = '\0';
  430. ret = 0;
  431. }
  432. if (*wsz!=0) LogMessage(" result=U+%04X\n",*wsz);
  433. // Break on NULL done here rather than at SYV_NULL check above,
  434. // because an ANSI or UNICODE char might also be NULL.
  435. if (!*wsz) {
  436. break;
  437. }
  438. }
  439. if (pCount)
  440. *pCount = c;
  441. return ret;
  442. }
  443. // Free memory allocated for hrcResult.
  444. int DestroyHRCRESULT(HRCRESULT hrcResult)
  445. {
  446. LogMessage("DestroyHRCRESULT()\n");
  447. if (!hrcResult) {
  448. return HRCR_ERROR;
  449. }
  450. ExternFree(hrcResult);
  451. return HRCR_OK;
  452. }
  453. int SetGuideHRC(HRC hrc, LPGUIDE lpguide, UINT nFirstVisible)
  454. {
  455. VRC *pVRC = (VRC *)hrc;
  456. LogMessage("SetGuideHRC()\n");
  457. // Check parameters.
  458. if (!hrc || pVRC->fBoxedInput || !pVRC->pLattice) {
  459. ASSERT(("Invalid lattice or boxed mode",0));
  460. return HRCR_ERROR;
  461. }
  462. // The following condition should really be: fHaveInput || fEndInput || pLatticePath
  463. // but this was remove to get the free input UI working.
  464. if (pVRC->fBeginProcess || pVRC->pLatticePath) {
  465. ASSERT(("Already processed some strokes in SetGuideHRC",0));
  466. return HRCR_ERROR;
  467. }
  468. // We only work with no guide.
  469. if (lpguide!=NULL && (lpguide->cHorzBox != 0 || lpguide->cVertBox != 0)) {
  470. ASSERT(("Wrong kind of guide",0));
  471. return HRCR_ERROR;
  472. }
  473. return HRCR_OK;
  474. }
  475. int SetAlphabetHRC(HRC hrc, ALC alc, LPBYTE rgbfAlc)
  476. {
  477. VRC *pVRC = (VRC *)hrc;
  478. rgbfAlc = rgbfAlc;
  479. // Check parameters.
  480. if (!hrc || pVRC->fBoxedInput || !pVRC->pLattice) {
  481. return HRCR_ERROR;
  482. }
  483. // The following condition should really be: fHaveInput || fEndInput || pLatticePath
  484. // but this was remove to get the free input UI working.
  485. if (pVRC->fBeginProcess || pVRC->pLatticePath) {
  486. return HRCR_ERROR;
  487. }
  488. // Pass the ALC on to the lattice.
  489. SetLatticeALCValid(pVRC->pLattice, alc);
  490. return HRCR_OK;
  491. }
  492. HINKSET CreateInksetHRCRESULT(
  493. HRCRESULT hrcResult,
  494. unsigned int iChar,
  495. unsigned int cChar
  496. ) {
  497. VRCRESULT *pVRCResult = (VRCRESULT *)hrcResult;
  498. VRC *pVRC;
  499. VINKSET *pVInkSet;
  500. DWORD begin, end;
  501. LogMessage("CreateInksetHRCRESULT()\n");
  502. // Check parameters.
  503. if (!hrcResult) {
  504. return NULL;
  505. }
  506. pVRC = pVRCResult->pVRC;
  507. if (!pVRC || pVRC->fBoxedInput
  508. || !pVRC->pLatticePath
  509. ) {
  510. return NULL;
  511. }
  512. if (pVRCResult->wch != 0xFFFF) {
  513. return NULL; // Not top level result.
  514. }
  515. if (cChar < 1 || (iChar + cChar) > (UINT)pVRC->pLatticePath->nChars) {
  516. return NULL; // Not one or more characters in valid range.
  517. }
  518. // Allocate an inkset structure.
  519. pVInkSet = ExternAlloc(sizeof(VINKSET));
  520. if (!pVInkSet) {
  521. return NULL;
  522. }
  523. // Fill it in.
  524. pVInkSet->pVRC = pVRC;
  525. pVInkSet->cChar = cChar;
  526. pVInkSet->iChar = iChar;
  527. // Get the tick counts.
  528. if (GetCharacterTimeRange(
  529. pVRC->pLattice, pVRC->pLatticePath, pVInkSet->iChar,
  530. pVInkSet->iChar + pVInkSet->cChar, &begin, &end))
  531. {
  532. pVInkSet->cIntervals = 1;
  533. }
  534. else
  535. {
  536. pVInkSet->cIntervals = 0;
  537. }
  538. // Return it.
  539. return (HINKSET)pVInkSet;
  540. }
  541. BOOL DestroyInkset(HINKSET hInkset)
  542. {
  543. LogMessage("DestroyInkset()\n");
  544. if (!hInkset) {
  545. return FALSE;
  546. }
  547. ExternFree(hInkset);
  548. return TRUE;
  549. }
  550. int GetInksetInterval(
  551. HINKSET hInkset,
  552. unsigned int uIndex,
  553. INTERVAL *pI
  554. ) {
  555. VINKSET *pVInkSet = (VINKSET *)hInkset;
  556. VRC *pVRC;
  557. DWORD begin, end;
  558. LogMessage("GetInksetInterval()\n");
  559. // Check parameters
  560. if (!hInkset || !pVInkSet->pVRC) {
  561. return ISR_ERROR;
  562. }
  563. pVRC = pVInkSet->pVRC;
  564. if (!pVRC || pVRC->fBoxedInput
  565. || !pVRC->pLatticePath
  566. ) {
  567. return ISR_ERROR;
  568. }
  569. // Only one range per string.
  570. if (pVInkSet->cIntervals == 0 || (uIndex != 0 && uIndex != IX_END)) {
  571. return ISR_BADINDEX;
  572. }
  573. // Get the tick counts.
  574. GetCharacterTimeRange(
  575. pVRC->pLattice, pVRC->pLatticePath, pVInkSet->iChar,
  576. pVInkSet->iChar + pVInkSet->cChar, &begin, &end
  577. );
  578. // OK convert from ms to ABSTIME.
  579. MakeAbsTime(&pI->atBegin, 0, begin);
  580. MakeAbsTime(&pI->atEnd, 0, end);
  581. LogMessage(" interval %d to %d\n",begin,end);
  582. return 1;
  583. }
  584. int GetInksetIntervalCount(HINKSET hInkset)
  585. {
  586. VINKSET *pVInkSet = (VINKSET *)hInkset;
  587. LogMessage("GetInksetIntervalCount()\n");
  588. if (!hInkset) {
  589. return ISR_ERROR;
  590. }
  591. return pVInkSet->cIntervals;
  592. }
  593. // Given a character, make a guess at what the bounding box around it would have been.
  594. int GetBaselineHRCRESULT(
  595. HRCRESULT hrcResult,
  596. RECT *pRect,
  597. BOOL *pfBaselineValid,
  598. BOOL *pfMidlineValid)
  599. {
  600. VRCRESULT *pVRCResult = (VRCRESULT *)hrcResult;
  601. VRC *pVRC;
  602. LogMessage("GetBaselineHRCRESULT(%08X)\n",hrcResult);
  603. // Check parameters.
  604. if (!hrcResult) {
  605. return HRCR_ERROR;
  606. }
  607. pVRC = pVRCResult->pVRC;
  608. if (!pVRC || pVRC->fBoxedInput || !pVRC->pLatticePath) {
  609. return HRCR_ERROR;
  610. }
  611. if (pVRCResult->wch == ALL_TOP_ONE) {
  612. // They want a bbox for the whole ink... just
  613. // return an error in this case, since it isn't
  614. // meaningful.
  615. return HRCR_ERROR;
  616. } else {
  617. if (!GetBoxOfAlternateInCurrentPath(pVRC->pLattice, pVRC->pLatticePath, pVRCResult->iChar, pRect)) {
  618. *pfBaselineValid = FALSE;
  619. *pfMidlineValid = FALSE;
  620. } else {
  621. *pfBaselineValid = TRUE;
  622. *pfMidlineValid = TRUE;
  623. }
  624. }
  625. LogMessage(" result left,right=%d,%d top,bottom=%d,%d valid=%d,%d\n",
  626. pRect->left,pRect->right,pRect->top,pRect->bottom,
  627. *pfBaselineValid,*pfMidlineValid);
  628. return HRCR_OK;
  629. }
  630. // Set the context for the ink that is being recognized.
  631. // wszBefore and wszAfter can both be NULL. The function
  632. // return TRUE on success, and FALSE on a memory allocation
  633. // error.
  634. BOOL SetHwxCorrectionContext(HRC hrc, wchar_t *wszBefore, wchar_t *wszAfter)
  635. {
  636. VRC *pVRC = (VRC *)hrc;
  637. int iDest, i;
  638. LogMessage("SetHwxCorrectionContext(%d,%d)\n",
  639. (wszBefore == NULL ? 0 : wcslen(wszBefore)),
  640. (wszAfter == NULL ? 0 : wcslen(wszAfter)));
  641. // Check parameters.
  642. if (!hrc || !pVRC->pLattice) {
  643. return FALSE;
  644. }
  645. // Make sure we do this before any input
  646. if (pVRC->fHaveInput || pVRC->fEndInput || pVRC->pLatticePath) {
  647. return FALSE;
  648. }
  649. // Free up previous context settings
  650. ExternFree(pVRC->pLattice->wszBefore);
  651. ExternFree(pVRC->pLattice->wszAfter);
  652. pVRC->pLattice->wszBefore = NULL;
  653. pVRC->pLattice->wszAfter = NULL;
  654. // If we are given any pre-context
  655. if (wszBefore != NULL && wcslen(wszBefore) > 0)
  656. {
  657. // Make a space for the context and check for allocation failure
  658. pVRC->pLattice->wszBefore = ExternAlloc(sizeof(wchar_t) * (wcslen(wszBefore) + 1));
  659. if (pVRC->pLattice->wszBefore == NULL)
  660. {
  661. return FALSE;
  662. }
  663. // Translate the string to dense codes, reversing the order of the
  664. // characters and stopping at the first one not supported by the recognizer.
  665. iDest = 0;
  666. for (i = wcslen(wszBefore) - 1; i >= 0; i--)
  667. {
  668. wchar_t dch = LocRunUnicode2Dense(&g_locRunInfo, wszBefore[i]);
  669. pVRC->pLattice->wszBefore[iDest] = dch;
  670. if (dch == LOC_TRAIN_NO_DENSE_CODE)
  671. {
  672. break;
  673. }
  674. iDest++;
  675. }
  676. pVRC->pLattice->wszBefore[iDest] = 0;
  677. // If the context was zero length after translation, set it to NULL.
  678. if (wcslen(pVRC->pLattice->wszBefore) == 0)
  679. {
  680. ExternFree(pVRC->pLattice->wszBefore);
  681. pVRC->pLattice->wszBefore = NULL;
  682. }
  683. }
  684. // If we are given any post-context
  685. if (wszAfter != NULL && wcslen(wszAfter) > 0)
  686. {
  687. // Make a space for the context and check for allocation failure
  688. pVRC->pLattice->wszAfter = ExternAlloc(sizeof(wchar_t) * (wcslen(wszAfter) + 1));
  689. if (pVRC->pLattice->wszAfter == NULL)
  690. {
  691. ExternFree(pVRC->pLattice->wszBefore);
  692. pVRC->pLattice->wszBefore = NULL;
  693. return FALSE;
  694. }
  695. // Translate the string to dense codes, stopping at the first character
  696. // not supported by the recognizer.
  697. for (i = 0; i < (int) wcslen(wszAfter); i++)
  698. {
  699. wchar_t dch = LocRunUnicode2Dense(&g_locRunInfo, wszAfter[i]);
  700. pVRC->pLattice->wszAfter[i] = dch;
  701. if (dch == LOC_TRAIN_NO_DENSE_CODE)
  702. break;
  703. }
  704. pVRC->pLattice->wszAfter[i] = 0;
  705. // If the context was zero length after translation, set it to NULL
  706. if (wcslen(pVRC->pLattice->wszAfter) == 0)
  707. {
  708. ExternFree(pVRC->pLattice->wszAfter);
  709. pVRC->pLattice->wszAfter = NULL;
  710. }
  711. }
  712. // Return success
  713. return TRUE;
  714. }
  715. #ifndef USE_RESOURCES
  716. // The three functions below are private APIs
  717. // They are only defined in the multi-language version of the recognizer,
  718. // not the ones that get shipped.
  719. #ifdef HWX_TUNE
  720. FILE *g_pTuneFile = NULL;
  721. int g_iTuneMode = 0;
  722. #endif
  723. // Configures the lattice to record tuning information. Must be called before
  724. // any strokes are added to the lattice.
  725. int RecordTuningInformation(wchar_t *wszTuneFile)
  726. {
  727. LogMessage("RecordTuningInformation()\n");
  728. #ifdef HWX_TUNE
  729. if (g_pTuneFile != NULL)
  730. {
  731. g_iTuneMode = 0;
  732. if (fclose(g_pTuneFile) < 0)
  733. {
  734. g_pTuneFile = NULL;
  735. return HRCR_ERROR;
  736. }
  737. g_pTuneFile = NULL;
  738. }
  739. if (wszTuneFile != NULL)
  740. {
  741. BOOL fBinary = FALSE;
  742. // Get the tuning mode based on a file name component
  743. if (wcsstr(wszTuneFile, L".lintuneV.") != NULL)
  744. {
  745. g_iTuneMode = 1;
  746. fBinary = TRUE;
  747. }
  748. if (wcsstr(wszTuneFile, L".threshold.") != NULL)
  749. {
  750. g_iTuneMode = 2;
  751. }
  752. if (wcsstr(wszTuneFile, L".lattice.") != NULL)
  753. {
  754. g_iTuneMode = 3;
  755. }
  756. g_pTuneFile = _wfopen(wszTuneFile, (fBinary ? L"wb" : L"w"));
  757. if (g_pTuneFile == NULL)
  758. {
  759. g_iTuneMode = 0;
  760. return HRCR_ERROR;
  761. }
  762. }
  763. return HRCR_OK;
  764. #else
  765. return HRCR_ERROR;
  766. #endif
  767. }
  768. // Given a lattice and a string of unicode characters, find the best path through the lattice
  769. // which gives that sequence of characters. Baring that, it will find the most likely path
  770. // through the lattice with the same number of characters and the minimum number of mismatches
  771. // to the prompt. In case no such path can be found, the current path becomes empty.
  772. // The function returns the number of substitutions used, or -1 if there is no path with
  773. // the desired number of characters, -2 if a memory allocation error occurs, or -3 if a
  774. // file write error occurs.
  775. int SearchForTargetResult(HRC hrc, wchar_t *wsz)
  776. {
  777. int nSubs = 0;
  778. VRC *pVRC = (VRC *)hrc;
  779. LogMessage("SearchForTargetResult()\n");
  780. // Check parameters.
  781. if (hrc == NULL || pVRC->pLattice == NULL) {
  782. ASSERT(("Bad lattice\n",0));
  783. return HRCR_ERROR;
  784. }
  785. // Processing done?
  786. if (!(pVRC->fEndInput && pVRC->pLatticePath != NULL)) {
  787. ASSERT(("Lattice not processed yet\n",0));
  788. return HRCR_ERROR;
  789. }
  790. // Free the old path, in case we got called before
  791. if (pVRC->pLatticePath != NULL) {
  792. FreeLatticePath(pVRC->pLatticePath);
  793. pVRC->pLatticePath = NULL;
  794. }
  795. if (g_iTuneMode == 3)
  796. {
  797. // Tuning mode 3 means dump out the IFELang3 lattices and correct answers.
  798. ApplyLanguageModel(pVRC->pLattice, wsz);
  799. }
  800. else
  801. {
  802. nSubs = SearchForTargetResultInternal(pVRC->pLattice, wsz);
  803. }
  804. // Get the final path.
  805. if (!GetCurrentPath(pVRC->pLattice, &pVRC->pLatticePath))
  806. {
  807. return -2;
  808. }
  809. return nSubs;
  810. }
  811. // Accessor macros for the bitmask above
  812. #define SetAllowedChar(bpMask, dch) (bpMask)[(dch) / 8] |= 1 << ((dch) % 8)
  813. BOOL HwxSetAnswerW(HRC hrc, wchar_t *wsz, int iMode)
  814. {
  815. VRC *pVRC = (VRC *)hrc;
  816. LogMessage("HwxSetAnswerW()\n");
  817. // Check parameters.
  818. if (hrc == NULL || pVRC->pLattice == NULL)
  819. {
  820. ASSERT(("Bad lattice\n",0));
  821. return FALSE;
  822. }
  823. pVRC->pLattice->wszAnswer = ExternAlloc((wcslen(wsz) + 1) * sizeof(wchar_t));
  824. if (pVRC->pLattice->wszAnswer == NULL)
  825. {
  826. ASSERT(("Out of memory allocating space.\n", 0));
  827. return FALSE;
  828. }
  829. wcscpy(pVRC->pLattice->wszAnswer, wsz);
  830. // Mode one means running the separator
  831. if (iMode == 1)
  832. {
  833. pVRC->pLattice->fSepMode = TRUE;
  834. }
  835. // Mode 1 means we limit the characters that can be returned to those
  836. // in the answer.
  837. if (iMode == 1)
  838. {
  839. int iChar;
  840. // Allocate a bit mask which holds all the folded and dense codes
  841. int iMaskSize = (g_locRunInfo.cCodePoints + g_locRunInfo.cFoldingSets + 7) / 8;
  842. BYTE *pbMask = ExternAlloc(iMaskSize);
  843. if (pbMask == NULL)
  844. {
  845. ASSERT(("Out of memory allocating space.\n", 0));
  846. return FALSE;
  847. }
  848. // Fill in the mask based on the prompt
  849. memset(pbMask, 0, iMaskSize);
  850. for (iChar = 0; iChar < (int) wcslen(wsz); iChar++)
  851. {
  852. wchar_t dch = LocRunUnicode2Dense(&g_locRunInfo, wsz[iChar]);
  853. if (dch != LOC_TRAIN_NO_DENSE_CODE)
  854. {
  855. // Try folding the character
  856. wchar_t fdch = LocRunDense2Folded(&g_locRunInfo, dch);
  857. if (fdch != 0)
  858. {
  859. // Set the mask allowing this folding set
  860. SetAllowedChar(pbMask, fdch);
  861. }
  862. // Set the mask allowing the unfolded character
  863. SetAllowedChar(pbMask, dch);
  864. }
  865. }
  866. // Store the mask in the recog settings.
  867. pVRC->pLattice->recogSettings.pbAllowedChars = pbMask;
  868. pVRC->pLattice->recogSettings.alcValid = 0;
  869. }
  870. return TRUE;
  871. }
  872. #endif // !USE_RESOURCES
  873. BOOL SetHwxFlags(HRC hrc, DWORD dwFlags)
  874. {
  875. VRC *pVRC = (VRC *)hrc;
  876. LogMessage("SetHwxFlags(%08X,%08X)\n", hrc, dwFlags);
  877. // Check parameters.
  878. if (hrc == NULL || pVRC->pLattice == NULL)
  879. {
  880. ASSERT(("Bad lattice\n",0));
  881. return FALSE;
  882. }
  883. if (pVRC->fBeginProcess)
  884. {
  885. // ASSERT(("Already started processing in SetHwxFlags", 0));
  886. return FALSE;
  887. }
  888. if (dwFlags & ~(RECOFLAG_WORDMODE | RECOFLAG_SINGLESEG | RECOFLAG_COERCE))
  889. {
  890. // ASSERT(("Unknown flag set\n",0));
  891. return FALSE;
  892. }
  893. pVRC->pLattice->fWordMode = ((dwFlags & RECOFLAG_WORDMODE) != 0);
  894. pVRC->pLattice->fCoerceMode = ((dwFlags & RECOFLAG_COERCE) != 0);
  895. pVRC->pLattice->fSingleSeg = ((dwFlags & RECOFLAG_SINGLESEG) != 0);
  896. return TRUE;
  897. }
  898. #define MAX_FACTOIDS 10
  899. /******************************Public*Routine******************************\
  900. * SetHwxFactoid
  901. *
  902. * New API for factoids.
  903. *
  904. * Return values:
  905. * HRCR_OK success
  906. * HRCR_ERROR failure
  907. * HRCR_CONFLICT ProcessHRC has already been called, cannot call me now
  908. * HRCR_UNSUPPORTED don't support this factoid string
  909. \**************************************************************************/
  910. int SetHwxFactoid(HRC hrc, wchar_t *wszFactoid)
  911. {
  912. VRC *pVRC = (VRC *)hrc;
  913. int nFactoids, i;
  914. DWORD aFactoids[MAX_FACTOIDS];
  915. BYTE *pbOldFactoidChars;
  916. ALC alcOldFactoid;
  917. LogMessage("SetHwxFactoid(%08X,%S)\n", hrc, wszFactoid);
  918. // Check parameters.
  919. if (hrc == NULL || pVRC->pLattice == NULL)
  920. {
  921. return HRCR_ERROR;
  922. }
  923. if (pVRC->fBeginProcess)
  924. {
  925. return HRCR_CONFLICT;
  926. }
  927. // Special case to reset back to the default
  928. if (wszFactoid == NULL)
  929. {
  930. // Clear out any previous factoid settings
  931. SetFactoidDefaultInternal(pVRC->pLattice);
  932. return HRCR_OK;
  933. }
  934. // Parse the string
  935. nFactoids = ParseFactoidString(wszFactoid, MAX_FACTOIDS, aFactoids);
  936. if (nFactoids <= 0)
  937. {
  938. return HRCR_UNSUPPORTED;
  939. }
  940. // Check to see if all the factoids set are supported
  941. for (i = 0; i < nFactoids; i++)
  942. {
  943. if (!IsSupportedFactoid(aFactoids[i]))
  944. {
  945. return HRCR_UNSUPPORTED;
  946. }
  947. }
  948. // Reset to the empty set of chars and clear out any ALCs
  949. alcOldFactoid = pVRC->pLattice->alcFactoid;
  950. pbOldFactoidChars = pVRC->pLattice->pbFactoidChars;
  951. pVRC->pLattice->alcFactoid = 0;
  952. pVRC->pLattice->pbFactoidChars = NULL;
  953. // For each factoid set
  954. for (i = 0; i < nFactoids; i++)
  955. {
  956. if (!SetFactoidInternal(&g_locRunInfo, pVRC->pLattice, aFactoids[i]))
  957. {
  958. // Roll back to original settings
  959. pVRC->pLattice->alcFactoid = alcOldFactoid;
  960. ExternFree(pVRC->pLattice->pbFactoidChars);
  961. pVRC->pLattice->pbFactoidChars = pbOldFactoidChars;
  962. return HRCR_ERROR;
  963. }
  964. }
  965. pVRC->pLattice->fUseFactoid = TRUE;
  966. // Turn off the default language model if an empty factoid is set.
  967. // May want to add this to other factoids in the future, or just
  968. // use a real language model.
  969. if (nFactoids == 1 && aFactoids[0] == FACTOID_NONE)
  970. {
  971. pVRC->pLattice->fUseLM = FALSE;
  972. }
  973. else
  974. {
  975. pVRC->pLattice->fUseLM = TRUE;
  976. }
  977. // Clear out the ALCs
  978. pVRC->pLattice->recogSettings.alcValid = 0xFFFFFFFF;
  979. ExternFree(pVRC->pLattice->recogSettings.pbAllowedChars);
  980. pVRC->pLattice->recogSettings.pbAllowedChars = NULL;
  981. pVRC->pLattice->recogSettings.alcPriority = 0;
  982. ExternFree(pVRC->pLattice->recogSettings.pbPriorityChars);
  983. pVRC->pLattice->recogSettings.pbPriorityChars = NULL;
  984. return HRCR_OK;
  985. }
  986. // Note that for now this function only considers the factoid, and ignores
  987. // any ALC settings.
  988. BOOL IsWStringSupportedHRC(HRC hrc, wchar_t *wsz)
  989. {
  990. VRC *pVRC = (VRC *)hrc;
  991. BOOL fSupported = TRUE;
  992. CHARSET charset;
  993. LogMessage("IsWStringSupportedHRC()\n");
  994. // Check parameters.
  995. if (hrc == NULL || pVRC->pLattice == NULL)
  996. {
  997. ASSERT(("Bad lattice\n",0));
  998. return FALSE;
  999. }
  1000. // If no factoid has been set yet, then use the default.
  1001. if (!pVRC->pLattice->fUseFactoid)
  1002. {
  1003. SetFactoidDefaultInternal(pVRC->pLattice);
  1004. }
  1005. charset.recmask = pVRC->pLattice->alcFactoid;
  1006. charset.pbAllowedChars = pVRC->pLattice->pbFactoidChars;
  1007. // Loop over the string
  1008. while (*wsz != 0 && fSupported)
  1009. {
  1010. // First check if it is supported in the dense codes
  1011. wchar_t dch = LocRunUnicode2Dense(&g_locRunInfo, *wsz);
  1012. if (dch == LOC_TRAIN_NO_DENSE_CODE)
  1013. {
  1014. fSupported = FALSE;
  1015. break;
  1016. }
  1017. // Then check if it is allowed by the factoid
  1018. if (!IsAllowedChar(&g_locRunInfo, &charset, dch))
  1019. {
  1020. fSupported = FALSE;
  1021. break;
  1022. }
  1023. wsz++;
  1024. }
  1025. return fSupported;
  1026. }
  1027. #ifndef USE_RESOURCES
  1028. BOOL GetSupportedChars(HRC hrc, wchar_t wsz[65536])
  1029. {
  1030. VRC *pVRC = (VRC *)hrc;
  1031. CHARSET charset;
  1032. int i, iDest;
  1033. LogMessage("GetSupportedChars()\n");
  1034. // Check parameters.
  1035. if (hrc == NULL || pVRC->pLattice == NULL)
  1036. {
  1037. ASSERT(("Bad lattice\n",0));
  1038. return FALSE;
  1039. }
  1040. // If no factoid has been set yet, then use the default.
  1041. if (!pVRC->pLattice->fUseFactoid)
  1042. {
  1043. SetFactoidDefaultInternal(pVRC->pLattice);
  1044. }
  1045. charset.recmask = pVRC->pLattice->alcFactoid;
  1046. charset.pbAllowedChars = pVRC->pLattice->pbFactoidChars;
  1047. iDest = 0;
  1048. for (i = 1; i < g_locRunInfo.cCodePoints; i++)
  1049. {
  1050. if (IsAllowedChar(&g_locRunInfo, &charset, (wchar_t) i))
  1051. {
  1052. wsz[iDest++] = LocRunDense2Unicode(&g_locRunInfo, (wchar_t) i);
  1053. }
  1054. }
  1055. wsz[iDest] = 0;
  1056. return TRUE;
  1057. }
  1058. #endif