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
768 lines
24 KiB
#include "hwxobj.h"
|
|
#include "memmgr.h"
|
|
#include "hwxfe.h" //980803:ToshiaK
|
|
#include "dbg.h"
|
|
#include "cmnhdr.h"
|
|
#ifdef UNDER_CE // Windows CE Stub for unsupported APIs
|
|
#include "stub_ce.h"
|
|
#endif // UNDER_CE
|
|
|
|
// implementation of CHwxThread, CHwxThreadMB, and CHwxThreadCAC
|
|
|
|
//----------------------------------------------------------------
|
|
//971217:ToshiaK: comment outed. changed to m_hHwxjpn as non static
|
|
//----------------------------------------------------------------
|
|
//HINSTANCE CHwxThread::m_hHwxjpn = NULL;
|
|
|
|
PHWXCONFIG CHwxThread::lpHwxConfig = NULL;
|
|
PHWXCREATE CHwxThread::lpHwxCreate = NULL;
|
|
PHWXSETCONTEXT CHwxThread::lpHwxSetContext = NULL;
|
|
PHWXSETGUIDE CHwxThread::lpHwxSetGuide = NULL;
|
|
PHWXALCVALID CHwxThread::lpHwxAlcValid = NULL;
|
|
PHWXSETPARTIAL CHwxThread::lpHwxSetPartial = NULL;
|
|
PHWXSETABORT CHwxThread::lpHwxSetAbort = NULL;
|
|
PHWXINPUT CHwxThread::lpHwxInput = NULL;
|
|
PHWXENDINPUT CHwxThread::lpHwxEndInput = NULL;
|
|
PHWXPROCESS CHwxThread::lpHwxProcess = NULL;
|
|
PHWXRESULTSAVAILABLE CHwxThread::lpHwxResultsAvailable = NULL;
|
|
PHWXGETRESULTS CHwxThread::lpHwxGetResults = NULL;
|
|
PHWXDESTROY CHwxThread::lpHwxDestroy = NULL;
|
|
|
|
|
|
CHwxThread::CHwxThread():CHwxObject(NULL)
|
|
{
|
|
m_thrdID = 0 ;
|
|
m_hThread = NULL ;
|
|
m_thrdArg = HWX_PARTIAL_ALL;
|
|
m_hStopEvent = NULL;
|
|
//----------------------------------------------------------------
|
|
//971217:ToshiaK changed m_hHwxjpn to non static data.
|
|
//so, Initialize it in Constructor.
|
|
//----------------------------------------------------------------
|
|
m_hHwxjpn = NULL;
|
|
}
|
|
|
|
CHwxThread::~CHwxThread()
|
|
{
|
|
Dbg(("CHwxThread::~CHwxThread START\n"));
|
|
// if ( IsThreadStarted() )
|
|
// {
|
|
//----------------------------------------------------------------
|
|
//970729: ToshiaK temporary, comment out.
|
|
//----------------------------------------------------------------
|
|
// StopThread();
|
|
// }
|
|
if ( m_hHwxjpn )
|
|
{
|
|
// decreament library ref count until it is equal to zero
|
|
FreeLibrary(m_hHwxjpn);
|
|
m_hHwxjpn = NULL;
|
|
}
|
|
if (m_hStopEvent)
|
|
{
|
|
CloseHandle(m_hStopEvent);
|
|
m_hStopEvent = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CHwxThread::Initialize(TCHAR * pClsName)
|
|
{
|
|
BOOL bRet = CHwxObject::Initialize(pClsName);
|
|
if ( bRet )
|
|
{
|
|
TCHAR tchPath[MAX_PATH];
|
|
//TCHAR tchMod[32];
|
|
//----------------------------------------------------------------
|
|
//980803:ToshiaK. Fareast merge.
|
|
//----------------------------------------------------------------
|
|
CHwxFE::GetRecognizerFileName(m_hInstance,
|
|
tchPath,
|
|
sizeof(tchPath)/sizeof(tchPath[0]));
|
|
//OutputDebugString("hwxthd\n");
|
|
//OutputDebugString(tchPath);
|
|
//OutputDebugString("\n");
|
|
//lstrcat(tchPath, tchMod);
|
|
if ( !m_hHwxjpn )
|
|
{
|
|
// first time load
|
|
//OutputDebugString(tchPath);
|
|
m_hHwxjpn = LoadLibrary(tchPath);
|
|
//m_hHwxjpn = LoadLibrary(TEXT("hwxjpn.dll"));
|
|
if ( m_hHwxjpn )
|
|
{
|
|
// get HwxXXXXX() API address from hwxjpn.dll
|
|
#ifndef UNDER_CE
|
|
lpHwxConfig =(PHWXCONFIG)GetProcAddress(m_hHwxjpn,"HwxConfig");
|
|
lpHwxCreate= (PHWXCREATE)GetProcAddress(m_hHwxjpn,"HwxCreate");
|
|
lpHwxSetContext= (PHWXSETCONTEXT)GetProcAddress(m_hHwxjpn,"HwxSetContext");
|
|
lpHwxSetGuide= (PHWXSETGUIDE)GetProcAddress(m_hHwxjpn,"HwxSetGuide");
|
|
lpHwxAlcValid= (PHWXALCVALID)GetProcAddress(m_hHwxjpn,"HwxALCValid");
|
|
lpHwxSetPartial= (PHWXSETPARTIAL)GetProcAddress(m_hHwxjpn,"HwxSetPartial");
|
|
lpHwxSetAbort= (PHWXSETABORT)GetProcAddress(m_hHwxjpn,"HwxSetAbort");
|
|
lpHwxInput= (PHWXINPUT)GetProcAddress(m_hHwxjpn,"HwxInput");
|
|
lpHwxEndInput= (PHWXENDINPUT)GetProcAddress(m_hHwxjpn,"HwxEndInput");
|
|
lpHwxProcess= (PHWXPROCESS)GetProcAddress(m_hHwxjpn,"HwxProcess");
|
|
lpHwxResultsAvailable= (PHWXRESULTSAVAILABLE)GetProcAddress(m_hHwxjpn,"HwxResultsAvailable");
|
|
lpHwxGetResults= (PHWXGETRESULTS)GetProcAddress(m_hHwxjpn,"HwxGetResults");
|
|
lpHwxDestroy= (PHWXDESTROY)GetProcAddress(m_hHwxjpn,"HwxDestroy");
|
|
#else // UNDER_CE
|
|
lpHwxConfig =(PHWXCONFIG)GetProcAddress(m_hHwxjpn,TEXT("HwxConfig"));
|
|
lpHwxCreate= (PHWXCREATE)GetProcAddress(m_hHwxjpn,TEXT("HwxCreate"));
|
|
lpHwxSetContext= (PHWXSETCONTEXT)GetProcAddress(m_hHwxjpn,TEXT("HwxSetContext"));
|
|
lpHwxSetGuide= (PHWXSETGUIDE)GetProcAddress(m_hHwxjpn,TEXT("HwxSetGuide"));
|
|
lpHwxAlcValid= (PHWXALCVALID)GetProcAddress(m_hHwxjpn,TEXT("HwxALCValid"));
|
|
lpHwxSetPartial= (PHWXSETPARTIAL)GetProcAddress(m_hHwxjpn,TEXT("HwxSetPartial"));
|
|
lpHwxSetAbort= (PHWXSETABORT)GetProcAddress(m_hHwxjpn,TEXT("HwxSetAbort"));
|
|
lpHwxInput= (PHWXINPUT)GetProcAddress(m_hHwxjpn,TEXT("HwxInput"));
|
|
lpHwxEndInput= (PHWXENDINPUT)GetProcAddress(m_hHwxjpn,TEXT("HwxEndInput"));
|
|
lpHwxProcess= (PHWXPROCESS)GetProcAddress(m_hHwxjpn,TEXT("HwxProcess"));
|
|
lpHwxResultsAvailable= (PHWXRESULTSAVAILABLE)GetProcAddress(m_hHwxjpn,TEXT("HwxResultsAvailable"));
|
|
lpHwxGetResults= (PHWXGETRESULTS)GetProcAddress(m_hHwxjpn,TEXT("HwxGetResults"));
|
|
lpHwxDestroy= (PHWXDESTROY)GetProcAddress(m_hHwxjpn,TEXT("HwxDestroy"));
|
|
#endif // UNDER_CE
|
|
|
|
|
|
if ( !lpHwxConfig || !lpHwxCreate || !lpHwxSetContext ||
|
|
!lpHwxSetGuide || !lpHwxAlcValid || !lpHwxSetPartial ||
|
|
!lpHwxSetAbort || !lpHwxInput || !lpHwxEndInput ||
|
|
!lpHwxProcess || !lpHwxResultsAvailable || !lpHwxGetResults ||
|
|
!lpHwxDestroy )
|
|
{
|
|
FreeLibrary(m_hHwxjpn);
|
|
m_hHwxjpn = NULL;
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
(*lpHwxConfig)();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if ( bRet && m_hHwxjpn && !IsThreadStarted() )
|
|
{
|
|
bRet = StartThread();
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CHwxThread::StartThread()
|
|
{
|
|
BOOL bRet = FALSE;
|
|
if ( !(m_hStopEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) )
|
|
return bRet;
|
|
m_Quit = FALSE;
|
|
#ifndef UNDER_CE // Windows CE does not support THREAD_QUERY_INFORMATION
|
|
m_hThread = CreateThread(NULL, 0, RealThreadProc, (void *)this, THREAD_QUERY_INFORMATION, &m_thrdID);
|
|
#else // UNDER_CE
|
|
m_hThread = CreateThread(NULL, 0, RealThreadProc, (void *)this, 0, &m_thrdID);
|
|
#endif // UNDER_CE
|
|
if ( m_hThread )
|
|
{
|
|
if ( IsMyHwxCls(TEXT("CHwxThreadCAC")) )
|
|
{
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
|
// SetThreadPriority(m_hThread, THREAD_PRIORITY_BELOW_NORMAL);
|
|
SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST);
|
|
}
|
|
bRet = TRUE;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void CHwxThread::StopThread()
|
|
{
|
|
Dbg(("StopThread START\n"));
|
|
DWORD dwReturn = 0;
|
|
if ( m_hThread && IsMyHwxCls(TEXT("CHwxThreadCAC")) )
|
|
{
|
|
//----------------------------------------------------------------
|
|
//980817:ToshiaK.Removed SetPriorityClass() line.
|
|
//This is very dangerous code, because we don't know what applicatin
|
|
//does about Priority.
|
|
//In KK's case, In WordPerfect, if we use SetPriorityClass(),
|
|
//WordPerfect never quit. I don't know why Li-zhang wrote this line.
|
|
//Anyway, it should be removed.
|
|
//----------------------------------------------------------------
|
|
//SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
|
|
SetThreadPriority(m_hThread, THREAD_PRIORITY_HIGHEST);
|
|
}
|
|
if (m_hThread &&
|
|
GetExitCodeThread(m_hThread,&dwReturn) &&
|
|
STILL_ACTIVE == dwReturn )
|
|
{
|
|
INT ret, i;
|
|
ret = PostThreadMessage(m_thrdID, THRDMSG_EXIT, 0, 0);
|
|
for(i = 0; i < 100; i++) {
|
|
Sleep(100);
|
|
if(m_Quit) {
|
|
//OutputDebugString("Thread END\n");
|
|
Dbg(("Thread Quit\n"));
|
|
break;
|
|
}
|
|
}
|
|
m_hThread = NULL;
|
|
//----------------------------------------------------------------
|
|
//971202:By Toshiak. Do not use WaitForSigleObject() to syncronize
|
|
//----------------------------------------------------------------
|
|
#ifdef RAID_2926
|
|
PostThreadMessage(m_thrdID, THRDMSG_EXIT, 0,0);
|
|
WaitForSingleObject(m_hStopEvent,INFINITE);
|
|
m_hThread = NULL ;
|
|
#endif
|
|
}
|
|
Dbg(("StopThread End\n"));
|
|
}
|
|
|
|
DWORD WINAPI CHwxThread::RealThreadProc(void * pv)
|
|
{
|
|
CHwxThread * pCHwxThread = reinterpret_cast<CHwxThread*>(pv);
|
|
return pCHwxThread->ClassThreadProc() ;
|
|
}
|
|
|
|
DWORD CHwxThread::ClassThreadProc()
|
|
{
|
|
return RecognizeThread(m_thrdArg);
|
|
}
|
|
|
|
CHwxThreadMB::CHwxThreadMB(CHwxMB * pMB,int nSize)
|
|
{
|
|
m_pMB = pMB;
|
|
#ifdef FE_CHINESE_SIMPLIFIED
|
|
m_recogMask = ALC_CHS_EXTENDED;
|
|
#elif FE_KOREAN
|
|
m_recogMask = ALC_KOR_EXTENDED;
|
|
#else
|
|
m_recogMask = ALC_JPN_EXTENDED;
|
|
#endif
|
|
m_prevChar = INVALID_CHAR;
|
|
m_hrcActive = NULL;
|
|
m_giSent = 0;
|
|
m_bDirty = FALSE;
|
|
|
|
m_guide.xOrigin = 0;
|
|
m_guide.yOrigin = 0;
|
|
|
|
m_guide.cxBox = nSize << 3;
|
|
m_guide.cyBox = nSize << 3;
|
|
|
|
// m_guide.cxBase = 0;
|
|
m_guide.cyBase = nSize << 3;
|
|
|
|
m_guide.cHorzBox = 256;
|
|
m_guide.cVertBox = 1;
|
|
|
|
m_guide.cyMid = nSize << 3;
|
|
|
|
m_guide.cxOffset = 0;
|
|
m_guide.cyOffset = 0;
|
|
|
|
m_guide.cxWriting = nSize << 3;
|
|
m_guide.cyWriting = nSize << 3;
|
|
|
|
m_guide.nDir = HWX_HORIZONTAL;
|
|
}
|
|
|
|
CHwxThreadMB::~CHwxThreadMB()
|
|
{
|
|
m_pMB = NULL;
|
|
}
|
|
|
|
BOOL CHwxThreadMB::Initialize(TCHAR * pClsName)
|
|
{
|
|
return CHwxThread::Initialize(pClsName);
|
|
}
|
|
|
|
DWORD CHwxThreadMB::RecognizeThread(DWORD dummy)
|
|
{
|
|
MSG msg;
|
|
int count;
|
|
|
|
|
|
// Now we are sitting in our message loop to wait for
|
|
// the message sent by the main thread
|
|
|
|
while (1)
|
|
{
|
|
if (!m_bDirty)
|
|
{
|
|
GetMessage(&msg, NULL, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
m_bDirty = FALSE;
|
|
|
|
(*lpHwxProcess)(m_hrcActive);
|
|
|
|
count = (*lpHwxResultsAvailable)(m_hrcActive);
|
|
|
|
if (count > m_giSent)
|
|
{
|
|
GetCharacters(m_giSent, count);
|
|
m_giSent = count;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!HandleThreadMsg(&msg))
|
|
{
|
|
//SetEvent(m_hStopEvent);
|
|
m_Quit = TRUE;
|
|
return 0;
|
|
}
|
|
}
|
|
m_Quit = TRUE;
|
|
Unref(dummy);
|
|
}
|
|
|
|
void CHwxThreadMB::GetCharacters(int iSentAlready, int iReady)
|
|
{
|
|
HWXRESULTPRI *pResult, *pHead;
|
|
HWXRESULTS *pBox;
|
|
int iIndex;
|
|
int count = iReady - iSentAlready;
|
|
|
|
pBox = (HWXRESULTS *)MemAlloc(count * (sizeof(HWXRESULTS) + (MB_NUM_CANDIDATES - 1)*sizeof(WCHAR)));
|
|
|
|
if (pBox)
|
|
{
|
|
iIndex = (*lpHwxGetResults)(m_hrcActive, MB_NUM_CANDIDATES, iSentAlready, count, pBox);
|
|
|
|
pHead = NULL;
|
|
|
|
for (iIndex = count - 1; iIndex >= 0; iIndex--)
|
|
{
|
|
// Index to the correct box results structure.
|
|
|
|
HWXRESULTS *pBoxCur = (HWXRESULTS *) (((char *) pBox) +
|
|
(iIndex *
|
|
(sizeof(HWXRESULTS) +
|
|
(MB_NUM_CANDIDATES - 1) * sizeof(WCHAR))));
|
|
|
|
pResult = GetCandidates(pBoxCur);
|
|
|
|
if (pResult == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pResult->pNext = pHead;
|
|
pHead = pResult;
|
|
}
|
|
|
|
MemFree((void *)pBox);
|
|
// Call back to the main thread to dispatch the BOXRESULTS
|
|
|
|
if (pHead)
|
|
{
|
|
PostMessage(m_pMB->GetMBWindow(), MB_WM_HWXCHAR, (WPARAM)pHead, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Function : CHwxThreadMB::HandleThreadMsg
|
|
// Type : BOOL
|
|
// Purpose :
|
|
// Args :
|
|
// : MSG * pMsg
|
|
// Return :
|
|
// DATE : Fri Oct 06 20:45:37 2000
|
|
// Histroy : 00/10/07: for Satori #2471.
|
|
// It's very difficult bug.
|
|
// Old code are following..
|
|
//
|
|
// switch(pMsg->message){
|
|
// :
|
|
// case THRDMSG_EXIT:
|
|
// default:
|
|
// return FALSE;
|
|
// }
|
|
// if HandlThreadMsg() receive unknown message,
|
|
// it always return False, then Thread quits!!!!.
|
|
// In Cicero environment, somebody post unkonwn message,
|
|
// to this Thread ID, when IMM IME is switched to Another IMM IME.
|
|
// IMEPad uses AttachThreadInput() attached application process's thread ID,
|
|
// Message is duplicated and HW thread receive this illegal
|
|
// message ID.
|
|
// So, I changed to return TRUE if HW thread receive unkonwn message
|
|
//
|
|
// switch(pMsg->message){
|
|
// :
|
|
// case THRDMSG_EXIT:
|
|
// return FALSE;
|
|
// default:
|
|
// return TRUE;
|
|
// }
|
|
//
|
|
//////////////////////////////////////////////////////////////////
|
|
BOOL CHwxThreadMB::HandleThreadMsg(MSG *pMsg)
|
|
{
|
|
PSTROKE pstr;
|
|
int iIndex;
|
|
int count;
|
|
|
|
switch (pMsg->message)
|
|
{
|
|
case THRDMSG_ADDINK:
|
|
|
|
pstr = (PSTROKE) pMsg->lParam;
|
|
|
|
if (!pstr)
|
|
return TRUE;
|
|
|
|
if (m_hrcActive == NULL)
|
|
{
|
|
m_giSent = 0;
|
|
|
|
m_hrcActive = (*lpHwxCreate)((HRC)NULL);
|
|
|
|
if (m_hrcActive == NULL)
|
|
return TRUE;
|
|
|
|
m_guide.cxBox = m_guide.cyBox = m_guide.cyBase = pMsg->wParam << 3;
|
|
m_guide.cyMid = m_guide.cxWriting = m_guide.cyWriting = pMsg->wParam << 3;
|
|
|
|
(*lpHwxSetGuide)(m_hrcActive, &m_guide);
|
|
|
|
// Setup the ALC mask everytime we do recognization
|
|
|
|
(*lpHwxAlcValid)(m_hrcActive, m_recogMask);
|
|
|
|
// Setup the context information if we have a valid prevChar
|
|
|
|
if (m_prevChar != INVALID_CHAR)
|
|
{
|
|
WCHAR ctxtChar;
|
|
|
|
// Get the correct context
|
|
if( FoldStringW(MAP_FOLDCZONE, &m_prevChar, 1, &ctxtChar, 1) )
|
|
{
|
|
(*lpHwxSetContext)(m_hrcActive, ctxtChar);
|
|
}
|
|
}
|
|
}
|
|
count = (pstr->iBox * pMsg->wParam) << 3; // Compute the offset for the box logically.
|
|
|
|
for (iIndex = 0; iIndex < pstr->cpt; iIndex++)
|
|
{
|
|
pstr->apt[iIndex].x = ((pstr->apt[iIndex].x - pstr->xLeft) << 3) + count;
|
|
pstr->apt[iIndex].y = (pstr->apt[iIndex].y << 3);
|
|
}
|
|
|
|
(*lpHwxInput)(m_hrcActive, pstr->apt,pstr->cpt,0);
|
|
|
|
MemFree((void *)pstr);
|
|
|
|
m_bDirty = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
case THRDMSG_RECOGNIZE:
|
|
|
|
if (m_hrcActive == NULL)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
(*lpHwxEndInput)(m_hrcActive);
|
|
(*lpHwxProcess)(m_hrcActive);
|
|
|
|
//
|
|
// We only get back the top 6 candidates.
|
|
//
|
|
|
|
count = pMsg->wParam; // # of boxes written in is sent here.
|
|
|
|
if (count > m_giSent)
|
|
{
|
|
GetCharacters(m_giSent, count);
|
|
m_giSent = count;
|
|
}
|
|
|
|
(*lpHwxDestroy)(m_hrcActive);
|
|
m_bDirty = FALSE;
|
|
m_hrcActive = NULL;
|
|
return TRUE;
|
|
|
|
// case THRDMSG_CHAR:
|
|
// PostMessage(m_pMB->GetMBWindow(), MB_WM_COMCHAR, pMsg->wParam, 0);
|
|
// return TRUE;
|
|
|
|
case THRDMSG_SETMASK:
|
|
m_recogMask = pMsg->wParam;
|
|
return TRUE;
|
|
|
|
case THRDMSG_SETCONTEXT:
|
|
m_prevChar = (WCHAR) pMsg->wParam;
|
|
return TRUE;
|
|
case THRDMSG_EXIT:
|
|
default:
|
|
//----------------------------------------------------------------
|
|
//Satori #2471:return TRUE not to quit thread accicentaly.
|
|
//----------------------------------------------------------------
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
HWXRESULTPRI * CHwxThreadMB::GetCandidates(HWXRESULTS *pbox)
|
|
{
|
|
HWXRESULTPRI *pResult;
|
|
int i;
|
|
|
|
pResult = (HWXRESULTPRI *)MemAlloc(sizeof(HWXRESULTPRI));
|
|
|
|
if (!pResult)
|
|
return NULL;
|
|
|
|
pResult->pNext = NULL;
|
|
|
|
for ( i=0; i<MB_NUM_CANDIDATES; i++ )
|
|
{
|
|
pResult->chCandidate[i] = pbox->rgChar[i];
|
|
if ( !pbox->rgChar[i] )
|
|
break;
|
|
}
|
|
|
|
pResult->cbCount = (USHORT)i;
|
|
pResult->iSelection = 0;
|
|
|
|
return pResult;
|
|
}
|
|
|
|
CHwxThreadCAC::CHwxThreadCAC(CHwxCAC * pCAC)
|
|
{
|
|
m_pCAC = pCAC;
|
|
}
|
|
|
|
CHwxThreadCAC::~CHwxThreadCAC()
|
|
{
|
|
m_pCAC = NULL;
|
|
}
|
|
|
|
BOOL CHwxThreadCAC::Initialize(TCHAR * pClsName)
|
|
{
|
|
return CHwxThread::Initialize(pClsName);
|
|
}
|
|
|
|
DWORD CHwxThreadCAC::RecognizeThread(DWORD dwPart)
|
|
{
|
|
MSG msg;
|
|
//UINT nPartial = dwPart;
|
|
HRC hrc;
|
|
HWXGUIDE guide;
|
|
BOOL bRecog;
|
|
DWORD cstr;
|
|
STROKE *pstr;
|
|
|
|
// Create the initial hrc for this thread, set the recognition paramters.
|
|
|
|
hrc = (*lpHwxCreate)((HRC) NULL);
|
|
if ( !hrc )
|
|
return 0;
|
|
guide.xOrigin = 0;
|
|
guide.yOrigin = 0;
|
|
guide.cxBox = 1000;
|
|
guide.cyBox = 1000;
|
|
// guide.cxBase = 0;
|
|
guide.cyBase = 1000;
|
|
guide.cHorzBox = 1;
|
|
guide.cVertBox = 1;
|
|
guide.cyMid = 1000;
|
|
guide.cxOffset = 0;
|
|
guide.cyOffset = 0;
|
|
guide.cxWriting = 1000;
|
|
guide.cyWriting = 1000;
|
|
guide.nDir = HWX_HORIZONTAL;
|
|
|
|
(*lpHwxSetGuide)(hrc, &guide); // Set the guide
|
|
// (*lpHwxSetPartial)(hrc, nPartial); // Set the recognition type
|
|
(*lpHwxSetAbort)(hrc,(UINT *)m_pCAC->GetStrokeCountAddress()); // Set the abort address
|
|
|
|
// Begin the message loop
|
|
|
|
while (TRUE)
|
|
{
|
|
bRecog = FALSE;
|
|
|
|
// Wait until we're told to recognize.
|
|
if(GetMessage(&msg, NULL, 0, 0) == FALSE)
|
|
{
|
|
if ( hrc )
|
|
(*lpHwxDestroy)(hrc);
|
|
hrc = NULL;
|
|
//971202: removed by Toshiak
|
|
//SetEvent(m_hStopEvent);
|
|
m_Quit = TRUE;
|
|
Dbg(("Recognize Thread END\n"));
|
|
return 0;
|
|
}
|
|
|
|
// We'll eat all the incoming messages
|
|
do
|
|
{
|
|
switch (msg.message)
|
|
{
|
|
case THRDMSG_SETGUIDE:
|
|
guide.cxBox = msg.wParam;
|
|
guide.cyBox = msg.wParam;
|
|
guide.cyBase = msg.wParam;
|
|
guide.cyMid = msg.wParam;
|
|
guide.cxWriting = msg.wParam;
|
|
guide.cyWriting = msg.wParam;
|
|
(*lpHwxSetGuide)(hrc, &guide); // Set the guide
|
|
break;
|
|
case THRDMSG_RECOGNIZE:
|
|
bRecog = TRUE;
|
|
break;
|
|
case THRDMSG_EXIT:
|
|
if ( hrc )
|
|
(*lpHwxDestroy)(hrc);
|
|
hrc = NULL;
|
|
//971202: removed by ToshiaK
|
|
//SetEvent(m_hStopEvent);
|
|
m_Quit = TRUE;
|
|
Dbg(("Recognize Thread END\n"));
|
|
return 0;
|
|
default:
|
|
break;
|
|
}
|
|
} while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
|
|
|
|
// Was there a message to recognize?
|
|
if (!bRecog)
|
|
continue;
|
|
|
|
bRecog = FALSE;
|
|
|
|
// Count the number of valid strokes
|
|
cstr = 0;
|
|
pstr = m_pCAC->GetStrokePointer();
|
|
while (pstr)
|
|
{
|
|
cstr++;
|
|
pstr = pstr->pNext;
|
|
}
|
|
|
|
// If the available stroke count doesn't match the actual stroke count, exit
|
|
|
|
if ((cstr != (DWORD)m_pCAC->GetStrokeCount()) || (!cstr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
recoghelper(hrc,HWX_PARTIAL_ALL,cstr);
|
|
recoghelper(hrc,HWX_PARTIAL_ORDER,cstr);
|
|
recoghelper(hrc,HWX_PARTIAL_FREE,cstr);
|
|
}
|
|
m_Quit = TRUE;
|
|
Unref(dwPart);
|
|
}
|
|
|
|
void CHwxThreadCAC::recoghelper(HRC hrc,DWORD dwPart,DWORD cstr)
|
|
{
|
|
UINT nPartial = dwPart;
|
|
HRC hrcTmp;
|
|
DWORD dwTick;
|
|
HWXRESULTS *pbox;
|
|
int ires;
|
|
STROKE *pstr;
|
|
|
|
int nSize = dwPart != HWX_PARTIAL_ALL ? PREFIXLIST : FULLLIST;
|
|
pbox = (HWXRESULTS *)MemAlloc(sizeof(HWXRESULTS) + nSize * sizeof(WCHAR));
|
|
if ( !pbox )
|
|
{
|
|
return;
|
|
}
|
|
|
|
hrcTmp = (*lpHwxCreate)(hrc);
|
|
(*lpHwxSetPartial)(hrcTmp, nPartial); // Set the recognition type
|
|
// (*lpHwxSetAbort)(hrcTmp,(UINT *)m_pCAC->GetStrokeCountAddress()); // Set the abort address
|
|
|
|
pstr = m_pCAC->GetStrokePointer();
|
|
dwTick = 0;
|
|
while (pstr)
|
|
{
|
|
dwTick +=3641L;
|
|
(*lpHwxInput)(hrcTmp, pstr->apt,pstr->cpt, dwTick);
|
|
pstr = pstr->pNext;
|
|
}
|
|
|
|
memset(pbox, '\0', sizeof(HWXRESULTS) + nSize * sizeof(WCHAR));
|
|
|
|
// Call the recognizer for results
|
|
|
|
(*lpHwxEndInput)(hrcTmp);
|
|
(*lpHwxProcess)(hrcTmp);
|
|
(*lpHwxGetResults)(hrcTmp, nSize, 0, 1, pbox);
|
|
(*lpHwxDestroy)(hrcTmp);
|
|
|
|
// Return the results
|
|
|
|
ires = 0;
|
|
while (pbox->rgChar[ires])
|
|
{
|
|
if (cstr != (DWORD)m_pCAC->GetStrokeCount())
|
|
break;
|
|
SendMessage(m_pCAC->GetCACWindow(), CAC_WM_RESULT, (nPartial << 8) | cstr, MAKELPARAM((pbox->rgChar[ires]), ires));
|
|
ires++;
|
|
}
|
|
MemFree((void *)pbox);
|
|
if ( ires )
|
|
{
|
|
SendMessage(m_pCAC->GetCACWindow(), CAC_WM_SHOWRESULT,0,0);
|
|
}
|
|
}
|
|
|
|
void CHwxThreadCAC::RecognizeNoThread(int nSize)
|
|
{
|
|
HRC hrc;
|
|
HWXGUIDE guide;
|
|
STROKE *pstr;
|
|
long numstrk = 0;
|
|
|
|
if (( pstr = m_pCAC->GetStrokePointer()) == (STROKE *) NULL)
|
|
return;
|
|
|
|
// Create the initial hrc for this thread, set the recognition paramters.
|
|
hrc = (*lpHwxCreate)((HRC) NULL);
|
|
if ( !hrc )
|
|
return;
|
|
|
|
guide.xOrigin = 0;
|
|
guide.yOrigin = 0;
|
|
|
|
guide.cxBox = nSize;
|
|
guide.cyBox = nSize;
|
|
|
|
// guide.cxBase = 0;
|
|
guide.cyBase = nSize;
|
|
guide.cHorzBox = 1;
|
|
guide.cVertBox = 1;
|
|
guide.cyMid = 0;
|
|
guide.cxOffset = 0;
|
|
guide.cyOffset = 0;
|
|
guide.cxWriting = nSize;
|
|
guide.cyWriting = nSize;
|
|
guide.nDir = HWX_HORIZONTAL;
|
|
|
|
(*lpHwxSetGuide)(hrc, &guide); // Set the guide
|
|
// (*lpHwxSetPartial)(hrc,HWX_PARTIAL_ALL); // Set the recognition type
|
|
(*lpHwxSetAbort)(hrc,(UINT *)m_pCAC->GetStrokeCountAddress());
|
|
|
|
numstrk = m_pCAC->GetStrokeCount();
|
|
recoghelper(hrc,HWX_PARTIAL_ALL,numstrk);
|
|
recoghelper(hrc,HWX_PARTIAL_ORDER,numstrk);
|
|
// recoghelper(hrc,HWX_PARTIAL_FREE,numstrk);
|
|
|
|
(*lpHwxDestroy)(hrc);
|
|
}
|