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.

768 lines
24 KiB

  1. #include "hwxobj.h"
  2. #include "memmgr.h"
  3. #include "hwxfe.h" //980803:ToshiaK
  4. #include "dbg.h"
  5. #include "cmnhdr.h"
  6. #ifdef UNDER_CE // Windows CE Stub for unsupported APIs
  7. #include "stub_ce.h"
  8. #endif // UNDER_CE
  9. // implementation of CHwxThread, CHwxThreadMB, and CHwxThreadCAC
  10. //----------------------------------------------------------------
  11. //971217:ToshiaK: comment outed. changed to m_hHwxjpn as non static
  12. //----------------------------------------------------------------
  13. //HINSTANCE CHwxThread::m_hHwxjpn = NULL;
  14. PHWXCONFIG CHwxThread::lpHwxConfig = NULL;
  15. PHWXCREATE CHwxThread::lpHwxCreate = NULL;
  16. PHWXSETCONTEXT CHwxThread::lpHwxSetContext = NULL;
  17. PHWXSETGUIDE CHwxThread::lpHwxSetGuide = NULL;
  18. PHWXALCVALID CHwxThread::lpHwxAlcValid = NULL;
  19. PHWXSETPARTIAL CHwxThread::lpHwxSetPartial = NULL;
  20. PHWXSETABORT CHwxThread::lpHwxSetAbort = NULL;
  21. PHWXINPUT CHwxThread::lpHwxInput = NULL;
  22. PHWXENDINPUT CHwxThread::lpHwxEndInput = NULL;
  23. PHWXPROCESS CHwxThread::lpHwxProcess = NULL;
  24. PHWXRESULTSAVAILABLE CHwxThread::lpHwxResultsAvailable = NULL;
  25. PHWXGETRESULTS CHwxThread::lpHwxGetResults = NULL;
  26. PHWXDESTROY CHwxThread::lpHwxDestroy = NULL;
  27. CHwxThread::CHwxThread():CHwxObject(NULL)
  28. {
  29. m_thrdID = 0 ;
  30. m_hThread = NULL ;
  31. m_thrdArg = HWX_PARTIAL_ALL;
  32. m_hStopEvent = NULL;
  33. //----------------------------------------------------------------
  34. //971217:ToshiaK changed m_hHwxjpn to non static data.
  35. //so, Initialize it in Constructor.
  36. //----------------------------------------------------------------
  37. m_hHwxjpn = NULL;
  38. }
  39. CHwxThread::~CHwxThread()
  40. {
  41. Dbg(("CHwxThread::~CHwxThread START\n"));
  42. // if ( IsThreadStarted() )
  43. // {
  44. //----------------------------------------------------------------
  45. //970729: ToshiaK temporary, comment out.
  46. //----------------------------------------------------------------
  47. // StopThread();
  48. // }
  49. if ( m_hHwxjpn )
  50. {
  51. // decreament library ref count until it is equal to zero
  52. FreeLibrary(m_hHwxjpn);
  53. m_hHwxjpn = NULL;
  54. }
  55. if (m_hStopEvent)
  56. {
  57. CloseHandle(m_hStopEvent);
  58. m_hStopEvent = NULL;
  59. }
  60. }
  61. BOOL CHwxThread::Initialize(TCHAR * pClsName)
  62. {
  63. BOOL bRet = CHwxObject::Initialize(pClsName);
  64. if ( bRet )
  65. {
  66. TCHAR tchPath[MAX_PATH];
  67. //TCHAR tchMod[32];
  68. //----------------------------------------------------------------
  69. //980803:ToshiaK. Fareast merge.
  70. //----------------------------------------------------------------
  71. CHwxFE::GetRecognizerFileName(m_hInstance,
  72. tchPath,
  73. sizeof(tchPath)/sizeof(tchPath[0]));
  74. //OutputDebugString("hwxthd\n");
  75. //OutputDebugString(tchPath);
  76. //OutputDebugString("\n");
  77. //lstrcat(tchPath, tchMod);
  78. if ( !m_hHwxjpn )
  79. {
  80. // first time load
  81. //OutputDebugString(tchPath);
  82. m_hHwxjpn = LoadLibrary(tchPath);
  83. //m_hHwxjpn = LoadLibrary(TEXT("hwxjpn.dll"));
  84. if ( m_hHwxjpn )
  85. {
  86. // get HwxXXXXX() API address from hwxjpn.dll
  87. #ifndef UNDER_CE
  88. lpHwxConfig =(PHWXCONFIG)GetProcAddress(m_hHwxjpn,"HwxConfig");
  89. lpHwxCreate= (PHWXCREATE)GetProcAddress(m_hHwxjpn,"HwxCreate");
  90. lpHwxSetContext= (PHWXSETCONTEXT)GetProcAddress(m_hHwxjpn,"HwxSetContext");
  91. lpHwxSetGuide= (PHWXSETGUIDE)GetProcAddress(m_hHwxjpn,"HwxSetGuide");
  92. lpHwxAlcValid= (PHWXALCVALID)GetProcAddress(m_hHwxjpn,"HwxALCValid");
  93. lpHwxSetPartial= (PHWXSETPARTIAL)GetProcAddress(m_hHwxjpn,"HwxSetPartial");
  94. lpHwxSetAbort= (PHWXSETABORT)GetProcAddress(m_hHwxjpn,"HwxSetAbort");
  95. lpHwxInput= (PHWXINPUT)GetProcAddress(m_hHwxjpn,"HwxInput");
  96. lpHwxEndInput= (PHWXENDINPUT)GetProcAddress(m_hHwxjpn,"HwxEndInput");
  97. lpHwxProcess= (PHWXPROCESS)GetProcAddress(m_hHwxjpn,"HwxProcess");
  98. lpHwxResultsAvailable= (PHWXRESULTSAVAILABLE)GetProcAddress(m_hHwxjpn,"HwxResultsAvailable");
  99. lpHwxGetResults= (PHWXGETRESULTS)GetProcAddress(m_hHwxjpn,"HwxGetResults");
  100. lpHwxDestroy= (PHWXDESTROY)GetProcAddress(m_hHwxjpn,"HwxDestroy");
  101. #else // UNDER_CE
  102. lpHwxConfig =(PHWXCONFIG)GetProcAddress(m_hHwxjpn,TEXT("HwxConfig"));
  103. lpHwxCreate= (PHWXCREATE)GetProcAddress(m_hHwxjpn,TEXT("HwxCreate"));
  104. lpHwxSetContext= (PHWXSETCONTEXT)GetProcAddress(m_hHwxjpn,TEXT("HwxSetContext"));
  105. lpHwxSetGuide= (PHWXSETGUIDE)GetProcAddress(m_hHwxjpn,TEXT("HwxSetGuide"));
  106. lpHwxAlcValid= (PHWXALCVALID)GetProcAddress(m_hHwxjpn,TEXT("HwxALCValid"));
  107. lpHwxSetPartial= (PHWXSETPARTIAL)GetProcAddress(m_hHwxjpn,TEXT("HwxSetPartial"));
  108. lpHwxSetAbort= (PHWXSETABORT)GetProcAddress(m_hHwxjpn,TEXT("HwxSetAbort"));
  109. lpHwxInput= (PHWXINPUT)GetProcAddress(m_hHwxjpn,TEXT("HwxInput"));
  110. lpHwxEndInput= (PHWXENDINPUT)GetProcAddress(m_hHwxjpn,TEXT("HwxEndInput"));
  111. lpHwxProcess= (PHWXPROCESS)GetProcAddress(m_hHwxjpn,TEXT("HwxProcess"));
  112. lpHwxResultsAvailable= (PHWXRESULTSAVAILABLE)GetProcAddress(m_hHwxjpn,TEXT("HwxResultsAvailable"));
  113. lpHwxGetResults= (PHWXGETRESULTS)GetProcAddress(m_hHwxjpn,TEXT("HwxGetResults"));
  114. lpHwxDestroy= (PHWXDESTROY)GetProcAddress(m_hHwxjpn,TEXT("HwxDestroy"));
  115. #endif // UNDER_CE
  116. if ( !lpHwxConfig || !lpHwxCreate || !lpHwxSetContext ||
  117. !lpHwxSetGuide || !lpHwxAlcValid || !lpHwxSetPartial ||
  118. !lpHwxSetAbort || !lpHwxInput || !lpHwxEndInput ||
  119. !lpHwxProcess || !lpHwxResultsAvailable || !lpHwxGetResults ||
  120. !lpHwxDestroy )
  121. {
  122. FreeLibrary(m_hHwxjpn);
  123. m_hHwxjpn = NULL;
  124. bRet = FALSE;
  125. }
  126. else
  127. {
  128. (*lpHwxConfig)();
  129. }
  130. }
  131. else
  132. {
  133. bRet = FALSE;
  134. }
  135. }
  136. }
  137. if ( bRet && m_hHwxjpn && !IsThreadStarted() )
  138. {
  139. bRet = StartThread();
  140. }
  141. return bRet;
  142. }
  143. BOOL CHwxThread::StartThread()
  144. {
  145. BOOL bRet = FALSE;
  146. if ( !(m_hStopEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) )
  147. return bRet;
  148. m_Quit = FALSE;
  149. #ifndef UNDER_CE // Windows CE does not support THREAD_QUERY_INFORMATION
  150. m_hThread = CreateThread(NULL, 0, RealThreadProc, (void *)this, THREAD_QUERY_INFORMATION, &m_thrdID);
  151. #else // UNDER_CE
  152. m_hThread = CreateThread(NULL, 0, RealThreadProc, (void *)this, 0, &m_thrdID);
  153. #endif // UNDER_CE
  154. if ( m_hThread )
  155. {
  156. if ( IsMyHwxCls(TEXT("CHwxThreadCAC")) )
  157. {
  158. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  159. // SetThreadPriority(m_hThread, THREAD_PRIORITY_BELOW_NORMAL);
  160. SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST);
  161. }
  162. bRet = TRUE;
  163. }
  164. return bRet;
  165. }
  166. void CHwxThread::StopThread()
  167. {
  168. Dbg(("StopThread START\n"));
  169. DWORD dwReturn = 0;
  170. if ( m_hThread && IsMyHwxCls(TEXT("CHwxThreadCAC")) )
  171. {
  172. //----------------------------------------------------------------
  173. //980817:ToshiaK.Removed SetPriorityClass() line.
  174. //This is very dangerous code, because we don't know what applicatin
  175. //does about Priority.
  176. //In KK's case, In WordPerfect, if we use SetPriorityClass(),
  177. //WordPerfect never quit. I don't know why Li-zhang wrote this line.
  178. //Anyway, it should be removed.
  179. //----------------------------------------------------------------
  180. //SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
  181. SetThreadPriority(m_hThread, THREAD_PRIORITY_HIGHEST);
  182. }
  183. if (m_hThread &&
  184. GetExitCodeThread(m_hThread,&dwReturn) &&
  185. STILL_ACTIVE == dwReturn )
  186. {
  187. INT ret, i;
  188. ret = PostThreadMessage(m_thrdID, THRDMSG_EXIT, 0, 0);
  189. for(i = 0; i < 100; i++) {
  190. Sleep(100);
  191. if(m_Quit) {
  192. //OutputDebugString("Thread END\n");
  193. Dbg(("Thread Quit\n"));
  194. break;
  195. }
  196. }
  197. m_hThread = NULL;
  198. //----------------------------------------------------------------
  199. //971202:By Toshiak. Do not use WaitForSigleObject() to syncronize
  200. //----------------------------------------------------------------
  201. #ifdef RAID_2926
  202. PostThreadMessage(m_thrdID, THRDMSG_EXIT, 0,0);
  203. WaitForSingleObject(m_hStopEvent,INFINITE);
  204. m_hThread = NULL ;
  205. #endif
  206. }
  207. Dbg(("StopThread End\n"));
  208. }
  209. DWORD WINAPI CHwxThread::RealThreadProc(void * pv)
  210. {
  211. CHwxThread * pCHwxThread = reinterpret_cast<CHwxThread*>(pv);
  212. return pCHwxThread->ClassThreadProc() ;
  213. }
  214. DWORD CHwxThread::ClassThreadProc()
  215. {
  216. return RecognizeThread(m_thrdArg);
  217. }
  218. CHwxThreadMB::CHwxThreadMB(CHwxMB * pMB,int nSize)
  219. {
  220. m_pMB = pMB;
  221. #ifdef FE_CHINESE_SIMPLIFIED
  222. m_recogMask = ALC_CHS_EXTENDED;
  223. #elif FE_KOREAN
  224. m_recogMask = ALC_KOR_EXTENDED;
  225. #else
  226. m_recogMask = ALC_JPN_EXTENDED;
  227. #endif
  228. m_prevChar = INVALID_CHAR;
  229. m_hrcActive = NULL;
  230. m_giSent = 0;
  231. m_bDirty = FALSE;
  232. m_guide.xOrigin = 0;
  233. m_guide.yOrigin = 0;
  234. m_guide.cxBox = nSize << 3;
  235. m_guide.cyBox = nSize << 3;
  236. // m_guide.cxBase = 0;
  237. m_guide.cyBase = nSize << 3;
  238. m_guide.cHorzBox = 256;
  239. m_guide.cVertBox = 1;
  240. m_guide.cyMid = nSize << 3;
  241. m_guide.cxOffset = 0;
  242. m_guide.cyOffset = 0;
  243. m_guide.cxWriting = nSize << 3;
  244. m_guide.cyWriting = nSize << 3;
  245. m_guide.nDir = HWX_HORIZONTAL;
  246. }
  247. CHwxThreadMB::~CHwxThreadMB()
  248. {
  249. m_pMB = NULL;
  250. }
  251. BOOL CHwxThreadMB::Initialize(TCHAR * pClsName)
  252. {
  253. return CHwxThread::Initialize(pClsName);
  254. }
  255. DWORD CHwxThreadMB::RecognizeThread(DWORD dummy)
  256. {
  257. MSG msg;
  258. int count;
  259. // Now we are sitting in our message loop to wait for
  260. // the message sent by the main thread
  261. while (1)
  262. {
  263. if (!m_bDirty)
  264. {
  265. GetMessage(&msg, NULL, 0, 0);
  266. }
  267. else
  268. {
  269. if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  270. {
  271. m_bDirty = FALSE;
  272. (*lpHwxProcess)(m_hrcActive);
  273. count = (*lpHwxResultsAvailable)(m_hrcActive);
  274. if (count > m_giSent)
  275. {
  276. GetCharacters(m_giSent, count);
  277. m_giSent = count;
  278. }
  279. continue;
  280. }
  281. }
  282. if (!HandleThreadMsg(&msg))
  283. {
  284. //SetEvent(m_hStopEvent);
  285. m_Quit = TRUE;
  286. return 0;
  287. }
  288. }
  289. m_Quit = TRUE;
  290. Unref(dummy);
  291. }
  292. void CHwxThreadMB::GetCharacters(int iSentAlready, int iReady)
  293. {
  294. HWXRESULTPRI *pResult, *pHead;
  295. HWXRESULTS *pBox;
  296. int iIndex;
  297. int count = iReady - iSentAlready;
  298. pBox = (HWXRESULTS *)MemAlloc(count * (sizeof(HWXRESULTS) + (MB_NUM_CANDIDATES - 1)*sizeof(WCHAR)));
  299. if (pBox)
  300. {
  301. iIndex = (*lpHwxGetResults)(m_hrcActive, MB_NUM_CANDIDATES, iSentAlready, count, pBox);
  302. pHead = NULL;
  303. for (iIndex = count - 1; iIndex >= 0; iIndex--)
  304. {
  305. // Index to the correct box results structure.
  306. HWXRESULTS *pBoxCur = (HWXRESULTS *) (((char *) pBox) +
  307. (iIndex *
  308. (sizeof(HWXRESULTS) +
  309. (MB_NUM_CANDIDATES - 1) * sizeof(WCHAR))));
  310. pResult = GetCandidates(pBoxCur);
  311. if (pResult == NULL)
  312. {
  313. break;
  314. }
  315. pResult->pNext = pHead;
  316. pHead = pResult;
  317. }
  318. MemFree((void *)pBox);
  319. // Call back to the main thread to dispatch the BOXRESULTS
  320. if (pHead)
  321. {
  322. PostMessage(m_pMB->GetMBWindow(), MB_WM_HWXCHAR, (WPARAM)pHead, 0);
  323. }
  324. }
  325. }
  326. //////////////////////////////////////////////////////////////////
  327. // Function : CHwxThreadMB::HandleThreadMsg
  328. // Type : BOOL
  329. // Purpose :
  330. // Args :
  331. // : MSG * pMsg
  332. // Return :
  333. // DATE : Fri Oct 06 20:45:37 2000
  334. // Histroy : 00/10/07: for Satori #2471.
  335. // It's very difficult bug.
  336. // Old code are following..
  337. //
  338. // switch(pMsg->message){
  339. // :
  340. // case THRDMSG_EXIT:
  341. // default:
  342. // return FALSE;
  343. // }
  344. // if HandlThreadMsg() receive unknown message,
  345. // it always return False, then Thread quits!!!!.
  346. // In Cicero environment, somebody post unkonwn message,
  347. // to this Thread ID, when IMM IME is switched to Another IMM IME.
  348. // IMEPad uses AttachThreadInput() attached application process's thread ID,
  349. // Message is duplicated and HW thread receive this illegal
  350. // message ID.
  351. // So, I changed to return TRUE if HW thread receive unkonwn message
  352. //
  353. // switch(pMsg->message){
  354. // :
  355. // case THRDMSG_EXIT:
  356. // return FALSE;
  357. // default:
  358. // return TRUE;
  359. // }
  360. //
  361. //////////////////////////////////////////////////////////////////
  362. BOOL CHwxThreadMB::HandleThreadMsg(MSG *pMsg)
  363. {
  364. PSTROKE pstr;
  365. int iIndex;
  366. int count;
  367. switch (pMsg->message)
  368. {
  369. case THRDMSG_ADDINK:
  370. pstr = (PSTROKE) pMsg->lParam;
  371. if (!pstr)
  372. return TRUE;
  373. if (m_hrcActive == NULL)
  374. {
  375. m_giSent = 0;
  376. m_hrcActive = (*lpHwxCreate)((HRC)NULL);
  377. if (m_hrcActive == NULL)
  378. return TRUE;
  379. m_guide.cxBox = m_guide.cyBox = m_guide.cyBase = pMsg->wParam << 3;
  380. m_guide.cyMid = m_guide.cxWriting = m_guide.cyWriting = pMsg->wParam << 3;
  381. (*lpHwxSetGuide)(m_hrcActive, &m_guide);
  382. // Setup the ALC mask everytime we do recognization
  383. (*lpHwxAlcValid)(m_hrcActive, m_recogMask);
  384. // Setup the context information if we have a valid prevChar
  385. if (m_prevChar != INVALID_CHAR)
  386. {
  387. WCHAR ctxtChar;
  388. // Get the correct context
  389. if( FoldStringW(MAP_FOLDCZONE, &m_prevChar, 1, &ctxtChar, 1) )
  390. {
  391. (*lpHwxSetContext)(m_hrcActive, ctxtChar);
  392. }
  393. }
  394. }
  395. count = (pstr->iBox * pMsg->wParam) << 3; // Compute the offset for the box logically.
  396. for (iIndex = 0; iIndex < pstr->cpt; iIndex++)
  397. {
  398. pstr->apt[iIndex].x = ((pstr->apt[iIndex].x - pstr->xLeft) << 3) + count;
  399. pstr->apt[iIndex].y = (pstr->apt[iIndex].y << 3);
  400. }
  401. (*lpHwxInput)(m_hrcActive, pstr->apt,pstr->cpt,0);
  402. MemFree((void *)pstr);
  403. m_bDirty = TRUE;
  404. return TRUE;
  405. case THRDMSG_RECOGNIZE:
  406. if (m_hrcActive == NULL)
  407. {
  408. return(TRUE);
  409. }
  410. (*lpHwxEndInput)(m_hrcActive);
  411. (*lpHwxProcess)(m_hrcActive);
  412. //
  413. // We only get back the top 6 candidates.
  414. //
  415. count = pMsg->wParam; // # of boxes written in is sent here.
  416. if (count > m_giSent)
  417. {
  418. GetCharacters(m_giSent, count);
  419. m_giSent = count;
  420. }
  421. (*lpHwxDestroy)(m_hrcActive);
  422. m_bDirty = FALSE;
  423. m_hrcActive = NULL;
  424. return TRUE;
  425. // case THRDMSG_CHAR:
  426. // PostMessage(m_pMB->GetMBWindow(), MB_WM_COMCHAR, pMsg->wParam, 0);
  427. // return TRUE;
  428. case THRDMSG_SETMASK:
  429. m_recogMask = pMsg->wParam;
  430. return TRUE;
  431. case THRDMSG_SETCONTEXT:
  432. m_prevChar = (WCHAR) pMsg->wParam;
  433. return TRUE;
  434. case THRDMSG_EXIT:
  435. default:
  436. //----------------------------------------------------------------
  437. //Satori #2471:return TRUE not to quit thread accicentaly.
  438. //----------------------------------------------------------------
  439. return TRUE;
  440. }
  441. }
  442. HWXRESULTPRI * CHwxThreadMB::GetCandidates(HWXRESULTS *pbox)
  443. {
  444. HWXRESULTPRI *pResult;
  445. int i;
  446. pResult = (HWXRESULTPRI *)MemAlloc(sizeof(HWXRESULTPRI));
  447. if (!pResult)
  448. return NULL;
  449. pResult->pNext = NULL;
  450. for ( i=0; i<MB_NUM_CANDIDATES; i++ )
  451. {
  452. pResult->chCandidate[i] = pbox->rgChar[i];
  453. if ( !pbox->rgChar[i] )
  454. break;
  455. }
  456. pResult->cbCount = (USHORT)i;
  457. pResult->iSelection = 0;
  458. return pResult;
  459. }
  460. CHwxThreadCAC::CHwxThreadCAC(CHwxCAC * pCAC)
  461. {
  462. m_pCAC = pCAC;
  463. }
  464. CHwxThreadCAC::~CHwxThreadCAC()
  465. {
  466. m_pCAC = NULL;
  467. }
  468. BOOL CHwxThreadCAC::Initialize(TCHAR * pClsName)
  469. {
  470. return CHwxThread::Initialize(pClsName);
  471. }
  472. DWORD CHwxThreadCAC::RecognizeThread(DWORD dwPart)
  473. {
  474. MSG msg;
  475. //UINT nPartial = dwPart;
  476. HRC hrc;
  477. HWXGUIDE guide;
  478. BOOL bRecog;
  479. DWORD cstr;
  480. STROKE *pstr;
  481. // Create the initial hrc for this thread, set the recognition paramters.
  482. hrc = (*lpHwxCreate)((HRC) NULL);
  483. if ( !hrc )
  484. return 0;
  485. guide.xOrigin = 0;
  486. guide.yOrigin = 0;
  487. guide.cxBox = 1000;
  488. guide.cyBox = 1000;
  489. // guide.cxBase = 0;
  490. guide.cyBase = 1000;
  491. guide.cHorzBox = 1;
  492. guide.cVertBox = 1;
  493. guide.cyMid = 1000;
  494. guide.cxOffset = 0;
  495. guide.cyOffset = 0;
  496. guide.cxWriting = 1000;
  497. guide.cyWriting = 1000;
  498. guide.nDir = HWX_HORIZONTAL;
  499. (*lpHwxSetGuide)(hrc, &guide); // Set the guide
  500. // (*lpHwxSetPartial)(hrc, nPartial); // Set the recognition type
  501. (*lpHwxSetAbort)(hrc,(UINT *)m_pCAC->GetStrokeCountAddress()); // Set the abort address
  502. // Begin the message loop
  503. while (TRUE)
  504. {
  505. bRecog = FALSE;
  506. // Wait until we're told to recognize.
  507. if(GetMessage(&msg, NULL, 0, 0) == FALSE)
  508. {
  509. if ( hrc )
  510. (*lpHwxDestroy)(hrc);
  511. hrc = NULL;
  512. //971202: removed by Toshiak
  513. //SetEvent(m_hStopEvent);
  514. m_Quit = TRUE;
  515. Dbg(("Recognize Thread END\n"));
  516. return 0;
  517. }
  518. // We'll eat all the incoming messages
  519. do
  520. {
  521. switch (msg.message)
  522. {
  523. case THRDMSG_SETGUIDE:
  524. guide.cxBox = msg.wParam;
  525. guide.cyBox = msg.wParam;
  526. guide.cyBase = msg.wParam;
  527. guide.cyMid = msg.wParam;
  528. guide.cxWriting = msg.wParam;
  529. guide.cyWriting = msg.wParam;
  530. (*lpHwxSetGuide)(hrc, &guide); // Set the guide
  531. break;
  532. case THRDMSG_RECOGNIZE:
  533. bRecog = TRUE;
  534. break;
  535. case THRDMSG_EXIT:
  536. if ( hrc )
  537. (*lpHwxDestroy)(hrc);
  538. hrc = NULL;
  539. //971202: removed by ToshiaK
  540. //SetEvent(m_hStopEvent);
  541. m_Quit = TRUE;
  542. Dbg(("Recognize Thread END\n"));
  543. return 0;
  544. default:
  545. break;
  546. }
  547. } while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
  548. // Was there a message to recognize?
  549. if (!bRecog)
  550. continue;
  551. bRecog = FALSE;
  552. // Count the number of valid strokes
  553. cstr = 0;
  554. pstr = m_pCAC->GetStrokePointer();
  555. while (pstr)
  556. {
  557. cstr++;
  558. pstr = pstr->pNext;
  559. }
  560. // If the available stroke count doesn't match the actual stroke count, exit
  561. if ((cstr != (DWORD)m_pCAC->GetStrokeCount()) || (!cstr))
  562. {
  563. continue;
  564. }
  565. recoghelper(hrc,HWX_PARTIAL_ALL,cstr);
  566. recoghelper(hrc,HWX_PARTIAL_ORDER,cstr);
  567. recoghelper(hrc,HWX_PARTIAL_FREE,cstr);
  568. }
  569. m_Quit = TRUE;
  570. Unref(dwPart);
  571. }
  572. void CHwxThreadCAC::recoghelper(HRC hrc,DWORD dwPart,DWORD cstr)
  573. {
  574. UINT nPartial = dwPart;
  575. HRC hrcTmp;
  576. DWORD dwTick;
  577. HWXRESULTS *pbox;
  578. int ires;
  579. STROKE *pstr;
  580. int nSize = dwPart != HWX_PARTIAL_ALL ? PREFIXLIST : FULLLIST;
  581. pbox = (HWXRESULTS *)MemAlloc(sizeof(HWXRESULTS) + nSize * sizeof(WCHAR));
  582. if ( !pbox )
  583. {
  584. return;
  585. }
  586. hrcTmp = (*lpHwxCreate)(hrc);
  587. (*lpHwxSetPartial)(hrcTmp, nPartial); // Set the recognition type
  588. // (*lpHwxSetAbort)(hrcTmp,(UINT *)m_pCAC->GetStrokeCountAddress()); // Set the abort address
  589. pstr = m_pCAC->GetStrokePointer();
  590. dwTick = 0;
  591. while (pstr)
  592. {
  593. dwTick +=3641L;
  594. (*lpHwxInput)(hrcTmp, pstr->apt,pstr->cpt, dwTick);
  595. pstr = pstr->pNext;
  596. }
  597. memset(pbox, '\0', sizeof(HWXRESULTS) + nSize * sizeof(WCHAR));
  598. // Call the recognizer for results
  599. (*lpHwxEndInput)(hrcTmp);
  600. (*lpHwxProcess)(hrcTmp);
  601. (*lpHwxGetResults)(hrcTmp, nSize, 0, 1, pbox);
  602. (*lpHwxDestroy)(hrcTmp);
  603. // Return the results
  604. ires = 0;
  605. while (pbox->rgChar[ires])
  606. {
  607. if (cstr != (DWORD)m_pCAC->GetStrokeCount())
  608. break;
  609. SendMessage(m_pCAC->GetCACWindow(), CAC_WM_RESULT, (nPartial << 8) | cstr, MAKELPARAM((pbox->rgChar[ires]), ires));
  610. ires++;
  611. }
  612. MemFree((void *)pbox);
  613. if ( ires )
  614. {
  615. SendMessage(m_pCAC->GetCACWindow(), CAC_WM_SHOWRESULT,0,0);
  616. }
  617. }
  618. void CHwxThreadCAC::RecognizeNoThread(int nSize)
  619. {
  620. HRC hrc;
  621. HWXGUIDE guide;
  622. STROKE *pstr;
  623. long numstrk = 0;
  624. if (( pstr = m_pCAC->GetStrokePointer()) == (STROKE *) NULL)
  625. return;
  626. // Create the initial hrc for this thread, set the recognition paramters.
  627. hrc = (*lpHwxCreate)((HRC) NULL);
  628. if ( !hrc )
  629. return;
  630. guide.xOrigin = 0;
  631. guide.yOrigin = 0;
  632. guide.cxBox = nSize;
  633. guide.cyBox = nSize;
  634. // guide.cxBase = 0;
  635. guide.cyBase = nSize;
  636. guide.cHorzBox = 1;
  637. guide.cVertBox = 1;
  638. guide.cyMid = 0;
  639. guide.cxOffset = 0;
  640. guide.cyOffset = 0;
  641. guide.cxWriting = nSize;
  642. guide.cyWriting = nSize;
  643. guide.nDir = HWX_HORIZONTAL;
  644. (*lpHwxSetGuide)(hrc, &guide); // Set the guide
  645. // (*lpHwxSetPartial)(hrc,HWX_PARTIAL_ALL); // Set the recognition type
  646. (*lpHwxSetAbort)(hrc,(UINT *)m_pCAC->GetStrokeCountAddress());
  647. numstrk = m_pCAC->GetStrokeCount();
  648. recoghelper(hrc,HWX_PARTIAL_ALL,numstrk);
  649. recoghelper(hrc,HWX_PARTIAL_ORDER,numstrk);
  650. // recoghelper(hrc,HWX_PARTIAL_FREE,numstrk);
  651. (*lpHwxDestroy)(hrc);
  652. }