1229 lines
33 KiB
C
1229 lines
33 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
|
|
|
|
Module Name:
|
|
|
|
SEARCH.c
|
|
|
|
++*/
|
|
|
|
#include <windows.h>
|
|
#include <immdev.h>
|
|
#include "imeattr.h"
|
|
#include "imedefs.h"
|
|
|
|
#if !defined(ROMANIME)
|
|
#if defined(WINAR30)
|
|
/**********************************************************************/
|
|
/* SearchQuickKey() */
|
|
/* Description: */
|
|
/* Search for the quick key table */
|
|
/* file format can be changed in different version for */
|
|
/* performance consideration, ISVs should not assume its format */
|
|
/* Array has the CopyRight of this table file */
|
|
/**********************************************************************/
|
|
void PASCAL SearchQuickKey(
|
|
LPCANDIDATELIST lpCandList,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
UINT uStart, uEnd;
|
|
HANDLE hHighWordTbl;
|
|
LPWORD lpHighWordTbl;
|
|
|
|
if (lpImcP->bSeq[1]) {
|
|
uStart = (lpImcP->bSeq[0] - 1) * 300 + (lpImcP->bSeq[1] - 1) * 10 +
|
|
300;
|
|
} else {
|
|
uStart = (lpImcP->bSeq[0] - 1) * 10;
|
|
}
|
|
|
|
hHighWordTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szTblFile[1]);
|
|
if (!hHighWordTbl) {
|
|
return;
|
|
}
|
|
|
|
lpHighWordTbl = MapViewOfFile(hHighWordTbl, FILE_MAP_READ,
|
|
0, 0, 0);
|
|
if (!lpHighWordTbl) {
|
|
goto SrchQuickKeyOvr;
|
|
}
|
|
|
|
uEnd = uStart + 10;
|
|
|
|
for (; uStart < uEnd; uStart++) {
|
|
UINT uCode;
|
|
|
|
uCode = (WORD)*(lpHighWordTbl + uStart);
|
|
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
}
|
|
|
|
UnmapViewOfFile(lpHighWordTbl);
|
|
|
|
SrchQuickKeyOvr:
|
|
CloseHandle(hHighWordTbl);
|
|
}
|
|
#endif
|
|
|
|
#if defined(DAYI) || defined(UNIIME)
|
|
/**********************************************************************/
|
|
/* SearchPhraseTbl() */
|
|
/* Description: */
|
|
/* file format can be changed in different version for */
|
|
/* performance consideration, ISVs should not assume its format */
|
|
/**********************************************************************/
|
|
void PASCAL SearchPhraseTbl( // searching the phrase table files
|
|
#if defined(UNIIME)
|
|
LPIMEL lpImeL,
|
|
#endif
|
|
UINT uTblIndex,
|
|
LPCANDIDATELIST lpCandList,
|
|
DWORD dwPattern)
|
|
{
|
|
HANDLE hTbl;
|
|
LPBYTE lpTbl;
|
|
int iLo, iHi, iMid;
|
|
BOOL bFound;
|
|
LPBYTE lpPattern;
|
|
|
|
hTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szTblFile[uTblIndex]);
|
|
if (!hTbl) {
|
|
return;
|
|
}
|
|
|
|
lpTbl = (LPBYTE)MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpTbl) {
|
|
CloseHandle(hTbl);
|
|
return;
|
|
}
|
|
|
|
iLo = 0;
|
|
#ifdef UNICODE
|
|
iHi = lpImeL->uTblSize[uTblIndex] / (lpImeL->nSeqBytes + sizeof(DWORD));
|
|
#else
|
|
iHi = lpImeL->uTblSize[uTblIndex] / (lpImeL->nSeqBytes + sizeof(WORD));
|
|
#endif
|
|
iMid = (iHi + iLo) /2;
|
|
|
|
// binary search
|
|
for (; iLo <= iHi; ) {
|
|
LPUNADWORD lpCurr;
|
|
|
|
#ifdef UNICODE
|
|
lpCurr = (LPDWORD)(lpTbl + (lpImeL->nSeqBytes + sizeof(DWORD)) *
|
|
iMid);
|
|
#else
|
|
lpCurr = (LPDWORD)(lpTbl + (lpImeL->nSeqBytes + sizeof(WORD)) *
|
|
iMid);
|
|
#endif
|
|
|
|
if (dwPattern > (*lpCurr & lpImeL->dwPatternMask)) {
|
|
iLo = iMid + 1;
|
|
} else if (dwPattern < (*lpCurr & lpImeL->dwPatternMask)) {
|
|
iHi = iMid - 1;
|
|
} else {
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
iMid = (iHi + iLo) /2;
|
|
}
|
|
|
|
if (bFound) {
|
|
HANDLE hPhrase;
|
|
LPBYTE lpPhrase;
|
|
LPWORD lpStart, lpEnd;
|
|
|
|
// find the lower bound
|
|
#ifdef UNICODE
|
|
lpPattern = lpTbl + (lpImeL->nSeqBytes + sizeof(DWORD)) * iMid;
|
|
#else
|
|
lpPattern = lpTbl + (lpImeL->nSeqBytes + sizeof(WORD)) * iMid;
|
|
#endif
|
|
|
|
#ifdef UNICODE
|
|
for (; (LPBYTE)lpPattern >= lpTbl; (LPBYTE)lpPattern -=
|
|
lpImeL->nSeqBytes + sizeof(DWORD)) {
|
|
#else
|
|
for (; (LPBYTE)lpPattern >= lpTbl; (LPBYTE)lpPattern -=
|
|
lpImeL->nSeqBytes + sizeof(WORD)) {
|
|
#endif
|
|
if (dwPattern > (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask)) {
|
|
// previous one is the lower bound
|
|
#ifdef UNICODE
|
|
(LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(DWORD);
|
|
#else
|
|
(LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(WORD);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((LPBYTE)lpPattern <= lpTbl) {
|
|
goto SrchPhrUnmapPattern;
|
|
}
|
|
|
|
hPhrase = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szTblFile[uTblIndex + 1]);
|
|
if (!hPhrase) {
|
|
goto SrchPhrUnmapPattern;
|
|
}
|
|
|
|
lpPhrase = (LPBYTE)MapViewOfFile(hPhrase, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpPhrase) {
|
|
goto SrchPhrClosePhr;
|
|
}
|
|
|
|
// offset of the string
|
|
#ifdef UNICODE
|
|
lpEnd = (LPWORD)lpPhrase + *(LPUNADWORD)(lpPattern +
|
|
lpImeL->nSeqBytes);
|
|
#else
|
|
lpEnd = (LPWORD)lpPhrase + *(LPUNAWORD)(lpPattern + lpImeL->nSeqBytes);
|
|
#endif
|
|
|
|
#ifdef UNICODE
|
|
for (; dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask);
|
|
(LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(DWORD)) {
|
|
#else
|
|
for (; dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask);
|
|
(LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(WORD)) {
|
|
#endif
|
|
WORD wCode;
|
|
DWORD dwStrLen;
|
|
|
|
lpStart = lpEnd;
|
|
|
|
// offset of next string
|
|
#ifdef UNICODE
|
|
lpEnd = (LPWORD)lpPhrase + *(LPUNADWORD)(lpPattern +
|
|
lpImeL->nSeqBytes * 2 + sizeof(DWORD));
|
|
#else
|
|
lpEnd = (LPWORD)lpPhrase + *(LPUNAWORD)(lpPattern +
|
|
lpImeL->nSeqBytes * 2 + sizeof(WORD));
|
|
#endif
|
|
|
|
for (dwStrLen = 0; lpStart < lpEnd; lpStart++,
|
|
dwStrLen += sizeof(WORD)) {
|
|
|
|
wCode = *lpStart;
|
|
|
|
#ifndef UNICODE
|
|
wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
|
|
#endif
|
|
|
|
// add this char into candidate list
|
|
*(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
|
|
lpCandList->dwCount] + dwStrLen) = wCode;
|
|
}
|
|
|
|
// null terminator
|
|
*(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
|
|
lpCandList->dwCount] + dwStrLen) = '\0';
|
|
|
|
dwStrLen += sizeof(TCHAR);
|
|
|
|
// add one string into candidate list
|
|
lpCandList->dwCount++;
|
|
|
|
if (lpCandList->dwCount >= MAXCAND) {
|
|
// Grow memory here and do something,
|
|
// if you still want to process it.
|
|
break;
|
|
}
|
|
|
|
// string length plus size of the null terminator
|
|
lpCandList->dwOffset[lpCandList->dwCount] =
|
|
lpCandList->dwOffset[lpCandList->dwCount - 1] +
|
|
dwStrLen + sizeof(TCHAR);
|
|
}
|
|
|
|
UnmapViewOfFile(lpPhrase);
|
|
|
|
SrchPhrClosePhr:
|
|
CloseHandle(hPhrase);
|
|
}
|
|
|
|
SrchPhrUnmapPattern:
|
|
UnmapViewOfFile(lpTbl);
|
|
|
|
CloseHandle(hTbl);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
#if defined(WINAR30)
|
|
/**********************************************************************/
|
|
/* SearchPhraseTbl() */
|
|
/* Description: */
|
|
/* file format can be changed in different version for */
|
|
/* performance consideration, ISVs should not assume its format */
|
|
/**********************************************************************/
|
|
void PASCAL SearchPhraseTbl( // searching the phrase table files
|
|
UINT uTblIndex,
|
|
LPCANDIDATELIST lpCandList,
|
|
DWORD dwPattern)
|
|
{
|
|
HANDLE hTbl;
|
|
LPBYTE lpTbl;
|
|
int iLo, iHi, iMid;
|
|
BOOL bFound;
|
|
LPBYTE lpPattern,lpPattern_end;
|
|
hTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szTblFile[uTblIndex]);
|
|
if (!hTbl) {
|
|
return;
|
|
}
|
|
|
|
lpTbl = (LPBYTE)MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpTbl) {
|
|
CloseHandle(hTbl);
|
|
return;
|
|
}
|
|
|
|
iLo = 1;
|
|
// iHi = lpImeL->uTblSize[uTblIndex] / (lpImeL->nSeqBytes *2);
|
|
iHi = (*(LPDWORD)(lpTbl) & lpImeL->dwPatternMask);
|
|
iMid = (iHi + iLo) /2;
|
|
|
|
// binary search
|
|
for (; iLo <= iHi; ) {
|
|
LPUNADWORD lpCurr;
|
|
|
|
lpCurr = (LPDWORD)(lpTbl + (lpImeL->nSeqBytes * 2 ) *
|
|
iMid);
|
|
|
|
if (dwPattern > (*lpCurr & lpImeL->dwPatternMask)) {
|
|
iLo = iMid + 1;
|
|
} else if (dwPattern < (*lpCurr & lpImeL->dwPatternMask)) {
|
|
iHi = iMid - 1;
|
|
} else {
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
iMid = (iHi + iLo) /2;
|
|
}
|
|
|
|
if (bFound) {
|
|
HANDLE hPhrase;
|
|
LPBYTE lpPhrase;
|
|
LPWORD lpStart, lpEnd;
|
|
|
|
// find the lower bound
|
|
lpPattern = lpTbl + (lpImeL->nSeqBytes * 2) * iMid;
|
|
|
|
for (; (LPBYTE)lpPattern >= lpTbl; (LPBYTE)lpPattern -=
|
|
lpImeL->nSeqBytes * 2 ) {
|
|
if (dwPattern > (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask)) {
|
|
// previous one is the lower bound
|
|
(LPBYTE)lpPattern += lpImeL->nSeqBytes * 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((LPBYTE)lpPattern <= lpTbl) {
|
|
goto SrchPhrUnmapPattern;
|
|
}
|
|
|
|
hPhrase = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szTblFile[uTblIndex + 1]);
|
|
if (!hPhrase) {
|
|
goto SrchPhrUnmapPattern;
|
|
}
|
|
|
|
lpPhrase = (LPBYTE)MapViewOfFile(hPhrase, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpPhrase) {
|
|
goto SrchPhrClosePhr;
|
|
}
|
|
|
|
// offset of the string
|
|
lpEnd = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern + lpImeL->nSeqBytes) & lpImeL->dwPatternMask);
|
|
|
|
for (; dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask);
|
|
(LPBYTE)lpPattern += lpImeL->nSeqBytes * 2 ) {
|
|
WORD wCode;
|
|
DWORD dwStrLen;
|
|
|
|
lpStart = lpEnd;
|
|
|
|
// offset of next string
|
|
lpEnd = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern +
|
|
lpImeL->nSeqBytes * 3) & lpImeL->dwPatternMask);
|
|
|
|
for (dwStrLen = 0; lpStart < lpEnd; lpStart++,
|
|
dwStrLen += sizeof(WORD)) {
|
|
|
|
wCode = *lpStart;
|
|
|
|
// add this char into candidate list
|
|
*(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
|
|
lpCandList->dwCount] + dwStrLen) = wCode;
|
|
}
|
|
|
|
// null terminator
|
|
*(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
|
|
lpCandList->dwCount] + dwStrLen) = '\0';
|
|
|
|
dwStrLen += sizeof(TCHAR);
|
|
|
|
// add one string into candidate list
|
|
lpCandList->dwCount++;
|
|
|
|
if (lpCandList->dwCount >= MAXCAND) {
|
|
// Grow memory here and do something,
|
|
// if you still want to process it.
|
|
break;
|
|
}
|
|
|
|
// string length plus size of the null terminator
|
|
lpCandList->dwOffset[lpCandList->dwCount] =
|
|
lpCandList->dwOffset[lpCandList->dwCount - 1] +
|
|
dwStrLen + sizeof(TCHAR);
|
|
}
|
|
|
|
iHi = (*(LPDWORD)(lpTbl) & lpImeL->dwPatternMask);
|
|
lpPattern = lpTbl + (lpImeL->nSeqBytes * 2) * iHi;
|
|
iHi = (*(LPDWORD)(lpTbl+4) & lpImeL->dwPatternMask);
|
|
lpPattern_end = lpTbl + (lpImeL->nSeqBytes * 2) * iHi;
|
|
|
|
for (; (LPBYTE)lpPattern < lpPattern_end; (LPBYTE)lpPattern +=
|
|
lpImeL->nSeqBytes * 2 ) {
|
|
WORD wCode;
|
|
DWORD dwStrLen;
|
|
if (dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask)) {
|
|
lpStart = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern + lpImeL->nSeqBytes) & lpImeL->dwPatternMask);
|
|
lpEnd = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern + (lpImeL->nSeqBytes *3)) & lpImeL->dwPatternMask);
|
|
for (dwStrLen = 0; lpStart < lpEnd; lpStart++,
|
|
dwStrLen += sizeof(WORD)) {
|
|
wCode = *lpStart;
|
|
// add this char into candidate list
|
|
*(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
|
|
lpCandList->dwCount] + dwStrLen) = wCode;
|
|
}
|
|
// null terminator
|
|
*(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
|
|
lpCandList->dwCount] + dwStrLen) = '\0';
|
|
dwStrLen += sizeof(TCHAR);
|
|
// add one string into candidate list
|
|
lpCandList->dwCount++;
|
|
if (lpCandList->dwCount >= MAXCAND) {
|
|
// Grow memory here and do something,
|
|
// if you still want to process it.
|
|
break;
|
|
}
|
|
// string length plus size of the null terminator
|
|
lpCandList->dwOffset[lpCandList->dwCount] =
|
|
lpCandList->dwOffset[lpCandList->dwCount - 1] +
|
|
dwStrLen + sizeof(TCHAR);
|
|
}
|
|
}
|
|
UnmapViewOfFile(lpPhrase);
|
|
|
|
SrchPhrClosePhr:
|
|
|
|
CloseHandle(hPhrase);
|
|
}
|
|
|
|
SrchPhrUnmapPattern:
|
|
UnmapViewOfFile(lpTbl);
|
|
|
|
CloseHandle(hTbl);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CHAJEI) || defined(QUICK) || defined(WINAR30)
|
|
/**********************************************************************/
|
|
/* MatchPattern() */
|
|
/**********************************************************************/
|
|
DWORD PASCAL MatchPattern(
|
|
DWORD dwSearchPattern,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
int i;
|
|
|
|
if (lpImcP->iGhostCard == lpImeL->nMaxKey) {
|
|
#if defined(WINAR30)
|
|
} else if (lpImcP->iGhostCard == 0) {
|
|
// no order search
|
|
BYTE bSeq[8];
|
|
int j;
|
|
|
|
*(LPDWORD)bSeq = *(LPDWORD)lpImcP->bSeq;
|
|
*(LPDWORD)&bSeq[4] = *(LPDWORD)&lpImcP->bSeq[4];
|
|
// 0 out the ghost card *XYZ -> 0XYZ
|
|
bSeq[0] = 0;
|
|
|
|
for (j = 0; j < lpImeL->nMaxKey; j++,
|
|
dwSearchPattern >>= lpImeL->nSeqBits) {
|
|
DWORD dwSeqCode;
|
|
|
|
dwSeqCode = dwSearchPattern & lpImeL->dwSeqMask;
|
|
|
|
if (!dwSeqCode) {
|
|
continue;
|
|
}
|
|
|
|
for (i = 1; i < lpImcP->iInputEnd; i++) {
|
|
if (dwSeqCode == bSeq[i]) {
|
|
// find one - turn off this one not search again
|
|
bSeq[i] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (*(LPDWORD)bSeq) {
|
|
// not matched, next one
|
|
dwSearchPattern = 0;
|
|
} else if (*(LPDWORD)&bSeq[4]) {
|
|
// not matched, next one
|
|
dwSearchPattern = 0;
|
|
} else {
|
|
dwSearchPattern = lpImcP->dwPattern;
|
|
}
|
|
#endif
|
|
} else {
|
|
DWORD dwPatternTmp;
|
|
DWORD dwPrefixMask, dwPostfixMask;
|
|
int iGhostCard;
|
|
|
|
#if defined(QUICK)
|
|
if (lpImcP->iInputEnd == 1) {
|
|
// for quick the single input X can not get any mask
|
|
return (dwSearchPattern);
|
|
}
|
|
#endif
|
|
|
|
dwPatternTmp = dwSearchPattern;
|
|
|
|
// prepare prefix mask - for example XX mask of XX*Y
|
|
dwPrefixMask = lpImeL->dwPatternMask;
|
|
|
|
for (i = lpImeL->nMaxKey - 1; i >= lpImcP->iGhostCard; i--) {
|
|
dwPrefixMask <<= lpImeL->nSeqBits;
|
|
}
|
|
|
|
dwSearchPattern &= dwPrefixMask;
|
|
|
|
// prepare postfix mask - for example YY mask of X*YY
|
|
#if defined(QUICK)
|
|
// we do not have X*Y for quick IME, we use a virtual * here
|
|
iGhostCard = lpImcP->iGhostCard - 1;
|
|
#else
|
|
iGhostCard = lpImcP->iGhostCard;
|
|
#endif
|
|
// + 1 because this first mask do not need to shift
|
|
// so the shift time will be one time less
|
|
for (i = iGhostCard + 1 + 1; i < lpImeL->nMaxKey; i++,
|
|
dwPatternTmp >>= lpImeL->nSeqBits) {
|
|
if (dwPatternTmp & lpImeL->dwSeqMask) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
dwPostfixMask = 0;
|
|
|
|
for (i = iGhostCard + 1; i < lpImcP->iInputEnd; i++) {
|
|
dwPostfixMask <<= lpImeL->nSeqBits;
|
|
dwPostfixMask |= lpImeL->dwSeqMask;
|
|
}
|
|
|
|
dwPatternTmp &= dwPostfixMask;
|
|
|
|
for (; i < lpImeL->nMaxKey; i++) {
|
|
dwPatternTmp <<= lpImeL->nSeqBits;
|
|
}
|
|
|
|
dwSearchPattern |= dwPatternTmp;
|
|
}
|
|
|
|
return (dwSearchPattern);
|
|
}
|
|
#endif
|
|
|
|
#if defined(WINAR30)
|
|
/**********************************************************************/
|
|
/* WildCardSearchPattern() */
|
|
/**********************************************************************/
|
|
void PASCAL WildCardSearchPattern(
|
|
LPBYTE lpCurr,
|
|
LPBYTE lpEnd,
|
|
LPPRIVCONTEXT lpImcP,
|
|
LPCANDIDATELIST lpCandList)
|
|
{
|
|
DWORD dwRecLen;
|
|
|
|
dwRecLen = lpImeL->nSeqBytes + sizeof(WORD);
|
|
|
|
for (; lpCurr < lpEnd; lpCurr += dwRecLen) {
|
|
DWORD dwSearchPattern;
|
|
#if defined(WINAR30)
|
|
DWORD dwWildCardPattern;
|
|
#endif
|
|
UINT uCode;
|
|
|
|
// skip the first word (bank ID) of internal code
|
|
dwSearchPattern = *(LPUNADWORD)lpCurr & lpImeL->dwPatternMask;
|
|
|
|
#if defined(WINAR30)
|
|
dwWildCardPattern = dwSearchPattern;
|
|
#endif
|
|
|
|
if (lpImcP->iGhostCard != lpImeL->nMaxKey) {
|
|
dwSearchPattern = MatchPattern(dwSearchPattern, lpImcP);
|
|
}
|
|
|
|
#if defined(WINAR30)
|
|
dwSearchPattern &= lpImcP->dwWildCardMask;
|
|
#endif
|
|
|
|
if (lpImcP->dwPattern != dwSearchPattern) {
|
|
continue;
|
|
}
|
|
|
|
#if defined(WINAR30)
|
|
if (!lpImcP->dwLastWildCard) {
|
|
} else if (dwWildCardPattern & lpImcP->dwLastWildCard) {
|
|
// a ? wild card or a * ghost card must have a stroke there
|
|
} else {
|
|
// a ? wild card or a * ghost card do not have a stroke there
|
|
// - can not match
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
uCode = *(LPWSTR)(lpCurr + lpImeL->nSeqBytes);
|
|
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
|
|
if (lpCandList->dwCount >= MAXCAND) {
|
|
// Grow memory here and do something,
|
|
// if you still want to process it.
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(WINIME) && !defined(UNICDIME)
|
|
/**********************************************************************/
|
|
/* SearchPattern() */
|
|
/**********************************************************************/
|
|
#if defined(CHAJEI) || defined(QUICK)
|
|
int PASCAL SearchPattern(
|
|
LPBYTE lpTbl,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
int iLo, iMid, iHi;
|
|
#if defined(CHAJEI)
|
|
DWORD dwCompReadStrLen;
|
|
#endif
|
|
|
|
if (lpImcP->bSeq[0] > lpImeL->nSeqCode) {
|
|
return (0);
|
|
}
|
|
|
|
iMid = lpImcP->bSeq[0] * (lpImeL->nSeqCode + 1); // A1 char
|
|
|
|
#if defined(QUICK)
|
|
if (lpImcP->bSeq[1] > lpImeL->nSeqCode) {
|
|
return (0);
|
|
}
|
|
|
|
iMid += lpImcP->bSeq[1];
|
|
#endif
|
|
#if defined(CHAJEI)
|
|
if (!lpImcP->bSeq[0]) {
|
|
dwCompReadStrLen = 0;
|
|
} else if (!lpImcP->bSeq[1]) {
|
|
dwCompReadStrLen = sizeof(WORD);
|
|
} else if (!lpImcP->bSeq[2]) {
|
|
dwCompReadStrLen = 2 * sizeof(WORD);
|
|
} else if (!lpImcP->bSeq[3]) {
|
|
dwCompReadStrLen = 3 * sizeof(WORD);
|
|
} else if (!lpImcP->bSeq[4]) {
|
|
dwCompReadStrLen = 4 * sizeof(WORD);
|
|
} else {
|
|
dwCompReadStrLen = 5 * sizeof(WORD);
|
|
}
|
|
|
|
if (dwCompReadStrLen > sizeof(WORD)) {
|
|
if (lpImcP->bSeq[dwCompReadStrLen / 2 - 1] > lpImeL->nSeqCode) {
|
|
return (0);
|
|
}
|
|
|
|
iMid += lpImcP->bSeq[dwCompReadStrLen / 2 - 1];
|
|
}
|
|
#endif
|
|
|
|
iLo = *((LPWORD)lpTbl + iMid); // start WORD of A234.TBL & ACODE.TBL
|
|
iHi = *((LPWORD)lpTbl + iMid + 1); // end WORD of A234.TBL & ACODE.TBL
|
|
|
|
if (iLo < iHi) {
|
|
return (iMid);
|
|
} else {
|
|
return (0);
|
|
}
|
|
}
|
|
#else
|
|
int PASCAL SearchPattern(
|
|
#if defined(UNIIME)
|
|
LPIMEL lpImeL,
|
|
#endif
|
|
LPBYTE lpTbl,
|
|
UINT uTblIndex,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
int iLo, iMid, iHi;
|
|
BOOL fFound;
|
|
DWORD dwRecLen;
|
|
|
|
fFound = FALSE;
|
|
|
|
#if defined(PHON)
|
|
dwRecLen = lpImeL->nSeqBytes;
|
|
#else
|
|
dwRecLen = lpImeL->nSeqBytes + sizeof(WORD);
|
|
#endif
|
|
|
|
iLo = 0;
|
|
iHi = lpImeL->uTblSize[uTblIndex] / dwRecLen;
|
|
iMid = (iLo + iHi) / 2;
|
|
|
|
#if defined(WINAR30) //1996/3/3
|
|
for (; iHi >= iLo; ) {
|
|
LPUNADWORD lpCurr;
|
|
lpCurr = (LPDWORD)(lpTbl + dwRecLen * iHi);
|
|
if (lpImcP->dwPattern == (*lpCurr & lpImeL->dwPatternMask)) {
|
|
fFound = TRUE;
|
|
iMid = iHi;
|
|
break;
|
|
}
|
|
iHi = iHi - 1;
|
|
#else
|
|
for (; iLo <= iHi; ) {
|
|
LPUNADWORD lpCurr;
|
|
|
|
lpCurr = (LPDWORD)(lpTbl + dwRecLen * iMid);
|
|
|
|
if (lpImcP->dwPattern > (*lpCurr & lpImeL->dwPatternMask)) {
|
|
iLo = iMid + 1;
|
|
} else if (lpImcP->dwPattern < (*lpCurr & lpImeL->dwPatternMask)) {
|
|
iHi = iMid - 1;
|
|
} else {
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
iMid = (iLo + iHi) / 2;
|
|
#endif
|
|
}
|
|
|
|
if (fFound) {
|
|
return (iMid);
|
|
} else {
|
|
return (0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**********************************************************************/
|
|
/* FindPattern() */
|
|
/**********************************************************************/
|
|
void PASCAL FindPattern(
|
|
#if defined(UNIIME)
|
|
LPIMEL lpImeL,
|
|
#endif
|
|
LPBYTE lpTbl,
|
|
int iMid,
|
|
LPCANDIDATELIST lpCandList,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
#ifndef WINAR30
|
|
int iLo, iHi;
|
|
#endif
|
|
DWORD dwRecLen;
|
|
#if defined(CHAJEI)
|
|
HANDLE hTblA234;
|
|
LPBYTE lpTblA234, lpA234;
|
|
DWORD dwPatternA234;
|
|
#endif
|
|
#if defined(PHON) || defined(CHAJEI) || defined(QUICK)
|
|
HANDLE hTblCode;
|
|
LPBYTE lpTblCode;
|
|
#endif
|
|
LPBYTE lpStart, lpEnd;
|
|
|
|
#if defined(PHON)
|
|
dwRecLen = lpImeL->nSeqBytes;
|
|
#elif !defined(CHAJEI) && !defined(QUICK)
|
|
dwRecLen = lpImeL->nSeqBytes + sizeof(WORD);
|
|
#else
|
|
#endif
|
|
|
|
// find the lower bound
|
|
#if defined(PHON)
|
|
{
|
|
HANDLE hTable;
|
|
LPWORD lpTable;
|
|
|
|
hTable = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]);
|
|
if (!hTable) {
|
|
return;
|
|
}
|
|
|
|
lpTable = MapViewOfFile(hTable, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpTable) {
|
|
goto FndPatCloseTbl1;
|
|
}
|
|
|
|
iLo = *(lpTable + iMid);
|
|
iHi = *(lpTable + iMid + 1);
|
|
|
|
UnmapViewOfFile(lpTable);
|
|
|
|
FndPatCloseTbl1:
|
|
CloseHandle(hTable);
|
|
|
|
if (!lpTable) {
|
|
return;
|
|
}
|
|
}
|
|
#elif defined(CHAJEI) || defined(QUICK)
|
|
iLo = *((LPWORD)lpTbl + iMid);
|
|
|
|
iHi = *((LPWORD)lpTbl + iMid + 1);
|
|
|
|
if (iLo >= iHi) {
|
|
return;
|
|
}
|
|
#else
|
|
#if defined(WINAR30) //1996/3/4
|
|
lpStart = lpTbl;
|
|
lpEnd = lpTbl + dwRecLen * (iMid+1);
|
|
#else
|
|
// find the lower bound
|
|
iLo = iMid - 1;
|
|
|
|
lpStart = lpTbl + dwRecLen * iLo;
|
|
|
|
for (; lpStart >= lpTbl; lpStart -= dwRecLen) {
|
|
register DWORD dwSearchPattern;
|
|
|
|
dwSearchPattern = *(LPUNADWORD)lpStart & lpImeL->dwPatternMask;
|
|
|
|
if (lpImcP->dwPattern > dwSearchPattern) {
|
|
// previous one is the lower bound
|
|
lpStart += dwRecLen;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (lpStart <= lpTbl) {
|
|
return;
|
|
}
|
|
|
|
// offset of code
|
|
lpStart += lpImeL->nSeqBytes;
|
|
|
|
// find the higher bound
|
|
iHi = iMid + 1;
|
|
|
|
lpEnd = lpTbl + dwRecLen * iHi;
|
|
|
|
for (; ; lpEnd += dwRecLen) {
|
|
register DWORD dwSearchPattern;
|
|
|
|
dwSearchPattern = *(LPUNADWORD)lpEnd & lpImeL->dwPatternMask;
|
|
|
|
if (lpImcP->dwPattern < dwSearchPattern) {
|
|
// the one is the higher bound, not including
|
|
break;
|
|
}
|
|
}
|
|
|
|
// offset of code
|
|
lpEnd += lpImeL->nSeqBytes;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(CHAJEI)
|
|
// A234.TBL
|
|
hTblA234 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]);
|
|
if (!hTblA234) {
|
|
return;
|
|
}
|
|
|
|
lpTblA234 = MapViewOfFile(hTblA234, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpTblA234) {
|
|
goto FndPatCloseTblA234;
|
|
}
|
|
|
|
lpA234 = lpTblA234 + sizeof(WORD) * iLo;
|
|
|
|
dwPatternA234 = 0;
|
|
|
|
if (lpImcP->bSeq[2]) {
|
|
dwPatternA234 |= lpImcP->bSeq[1] << (lpImeL->nSeqBits * 2);
|
|
}
|
|
|
|
if (lpImcP->bSeq[3]) {
|
|
dwPatternA234 |= lpImcP->bSeq[2] << lpImeL->nSeqBits;
|
|
}
|
|
|
|
if (lpImcP->bSeq[4]) {
|
|
dwPatternA234 |= lpImcP->bSeq[3];
|
|
}
|
|
#endif
|
|
|
|
#if defined(PHON) || defined(CHAJEI) || defined(QUICK)
|
|
// PHONCODE.TBL ACODE.TBL
|
|
hTblCode = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[2]);
|
|
if (!hTblCode) {
|
|
return;
|
|
}
|
|
|
|
lpTblCode = MapViewOfFile(hTblCode, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpTblCode) {
|
|
goto FndPatCloseTblCode;
|
|
}
|
|
|
|
lpStart = lpTblCode + sizeof(WORD) * iLo;
|
|
|
|
lpEnd = lpTblCode + sizeof(WORD) * iHi;
|
|
|
|
dwRecLen = sizeof(WORD);
|
|
#endif
|
|
|
|
#if defined(CHAJEI)
|
|
for (; lpStart < lpEnd; lpStart += dwRecLen, lpA234 += sizeof(WORD)) {
|
|
#else
|
|
for (; lpStart < lpEnd; lpStart += dwRecLen) {
|
|
#endif
|
|
UINT uCode;
|
|
|
|
#if defined(CHAJEI)
|
|
if (lpImcP->bSeq[1] == GHOSTCARD_SEQCODE) {
|
|
if (!lpImcP->bSeq[2]) {
|
|
// if the 3rd sequence code is 0, it is not a ghost card
|
|
continue;
|
|
}
|
|
} else if (dwPatternA234 != *(LPWORD)lpA234) {
|
|
continue;
|
|
} else {
|
|
}
|
|
#endif
|
|
|
|
#if defined(WINAR30) //1996/3/4
|
|
register DWORD dwSearchPattern;
|
|
dwSearchPattern = *(LPUNADWORD)lpStart & lpImeL->dwPatternMask;
|
|
if (lpImcP->dwPattern == dwSearchPattern) {
|
|
uCode = *(LPUNAWORD)(lpStart+lpImeL->nSeqBytes);
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
}
|
|
#else
|
|
uCode = *(LPUNAWORD)lpStart;
|
|
|
|
#if defined(PHON) || defined(DAYI)
|
|
#ifdef UNICODE
|
|
if (!IsValidCode(uCode)) {
|
|
uCode = InverseEncode(uCode);
|
|
}
|
|
#else
|
|
// resolve duplicate composition for one code
|
|
if (!(uCode & 0x8000)) {
|
|
uCode |= 0x8000;
|
|
}
|
|
#endif
|
|
#endif
|
|
#if defined(UNIIME)
|
|
AddCodeIntoCand(lpImeL,lpCandList, uCode);
|
|
#else
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
#endif
|
|
|
|
#endif
|
|
if (lpCandList->dwCount >= MAXCAND) {
|
|
// Grow memory here and do something,
|
|
// if you still want to process it.
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if defined(PHON) || defined(CHAJEI) || defined(QUICK)
|
|
UnmapViewOfFile(lpTblCode);
|
|
|
|
FndPatCloseTblCode:
|
|
CloseHandle(hTblCode);
|
|
#endif
|
|
|
|
#if defined(CHAJEI)
|
|
UnmapViewOfFile(lpTblA234);
|
|
|
|
FndPatCloseTblA234:
|
|
CloseHandle(hTblA234);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
#endif // !defined(WINIME) && !defined(UNICDIME)
|
|
|
|
/**********************************************************************/
|
|
/* SearchTbl() */
|
|
/* Description: */
|
|
/* file format can be changed in different version for */
|
|
/* performance consideration, ISVs should not assume its format */
|
|
/**********************************************************************/
|
|
void PASCAL SearchTbl( // searching the standard table files
|
|
#if defined(UNIIME)
|
|
LPIMEL lpImeL,
|
|
#endif
|
|
UINT uTblIndex,
|
|
LPCANDIDATELIST lpCandList,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
#if defined(WINIME) || defined(UNICDIME)
|
|
if (!lpImcP->bSeq[0]) {
|
|
} else if (!lpImcP->bSeq[1]) {
|
|
} else if (!lpImcP->bSeq[3]) {
|
|
DWORD i;
|
|
UINT uCode;
|
|
|
|
uCode = (lpImcP->bSeq[0] - 1) << 12;
|
|
uCode |= (lpImcP->bSeq[1] - 1) << 8;
|
|
if (lpImcP->bSeq[2]) {
|
|
// we want it match with internal code here so | 0x0001
|
|
uCode |= (lpImcP->bSeq[2] - 1) << 4 | 0x0001;
|
|
} else {
|
|
uCode |= 0x0040;
|
|
}
|
|
|
|
for (i = 0; i < lpCandList->dwPageSize; i++, uCode++) {
|
|
#if defined(WINIME) && defined(UNICODE)
|
|
CHAR szCode[2];
|
|
WCHAR wCode[2];
|
|
|
|
szCode[0] = HIBYTE(uCode);
|
|
szCode[1] = LOBYTE(uCode);
|
|
|
|
wCode[0] = 0;
|
|
|
|
MultiByteToWideChar(sImeG.uAnsiCodePage, MB_PRECOMPOSED,
|
|
szCode, 2, wCode, sizeof(wCode) / sizeof(WCHAR));
|
|
|
|
uCode = wCode[0];
|
|
#endif
|
|
#if defined(UNIIME)
|
|
AddCodeIntoCand(lpImeL,lpCandList, uCode);
|
|
#else
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
#endif
|
|
}
|
|
} else if (!lpImcP->bSeq[2]) {
|
|
return;
|
|
} else {
|
|
UINT uCode;
|
|
#if defined(WINIME) && defined(UNICODE)
|
|
CHAR szCode[2];
|
|
WCHAR wCode[2];
|
|
#endif
|
|
|
|
uCode = (lpImcP->bSeq[0] - 1) << 12;
|
|
uCode |= (lpImcP->bSeq[1] - 1) << 8;
|
|
uCode |= (lpImcP->bSeq[2] - 1) << 4;
|
|
uCode |= (lpImcP->bSeq[3] - 1);
|
|
|
|
#if defined(WINIME) && defined(UNICODE)
|
|
szCode[0] = HIBYTE(uCode);
|
|
szCode[1] = LOBYTE(uCode);
|
|
|
|
wCode[0] = 0;
|
|
|
|
MultiByteToWideChar(sImeG.uAnsiCodePage, MB_PRECOMPOSED,
|
|
szCode, 2, wCode, sizeof(wCode) / sizeof(WCHAR));
|
|
|
|
uCode = wCode[0];
|
|
#endif
|
|
#if defined(UNIIME)
|
|
AddCodeIntoCand(lpImeL,lpCandList, uCode);
|
|
#else
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
#endif
|
|
}
|
|
|
|
return;
|
|
#else
|
|
HANDLE hTbl;
|
|
LPBYTE lpTbl;
|
|
|
|
if (!lpImcP->dwPattern) {
|
|
return;
|
|
}
|
|
#if defined(WINAR30) // 1996/2/5
|
|
if (lpImcP->dwCompChar==0x27)
|
|
goto SearchTblOvr;
|
|
#endif
|
|
|
|
hTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szTblFile[uTblIndex]);
|
|
if (!hTbl) {
|
|
return;
|
|
}
|
|
|
|
lpTbl = (LPBYTE)MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
|
|
if (!lpTbl) {
|
|
goto SearchTblOvr;
|
|
}
|
|
|
|
#if defined(WINAR30)
|
|
if (lpImcP->iGhostCard != lpImeL->nMaxKey) {
|
|
WildCardSearchPattern(lpTbl, lpTbl + lpImeL->uTblSize[uTblIndex],
|
|
lpImcP, lpCandList);
|
|
} else if (lpImcP->dwLastWildCard) {
|
|
WildCardSearchPattern(lpTbl, lpTbl + lpImeL->uTblSize[uTblIndex],
|
|
lpImcP, lpCandList);
|
|
} else {
|
|
#else
|
|
{
|
|
#endif // defined(WINAR30)
|
|
int iMid;
|
|
|
|
#if defined(CHAJEI) || defined(QUICK)
|
|
iMid = SearchPattern(lpTbl, lpImcP);
|
|
#else
|
|
iMid = SearchPattern(
|
|
#if defined(UNIIME)
|
|
lpImeL,
|
|
#endif
|
|
lpTbl, uTblIndex, lpImcP);
|
|
#endif
|
|
|
|
if (iMid > 0) {
|
|
FindPattern(
|
|
#if defined(UNIIME)
|
|
lpImeL,
|
|
#endif
|
|
lpTbl, iMid, lpCandList, lpImcP);
|
|
}
|
|
}
|
|
|
|
UnmapViewOfFile(lpTbl);
|
|
|
|
SearchTblOvr:
|
|
CloseHandle(hTbl);
|
|
|
|
#if defined(DAYI)
|
|
if (uTblIndex == 0) { // do not duplciate search the phrase table
|
|
SearchPhraseTbl(1, lpCandList, lpImcP->dwPattern);
|
|
}
|
|
#endif
|
|
#if defined(WINAR30) // 1996/2/5
|
|
if (uTblIndex == 0 && lpImcP->dwCompChar==0x27) { // do not duplciate search the phrase table
|
|
SearchPhraseTbl(4, lpCandList, lpImcP->dwPattern);
|
|
}
|
|
#endif
|
|
|
|
#if defined(UNIIME) // same as Dayi need to search phrase table
|
|
SearchPhraseTbl(lpImeL, 1, lpCandList, lpImcP->dwPattern);
|
|
#endif
|
|
|
|
return;
|
|
#endif // !defined(WINIME) && !defined(UNICDIME)
|
|
}
|
|
|
|
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
|
|
/**********************************************************************/
|
|
/* SearchUsrDic() */
|
|
/**********************************************************************/
|
|
void PASCAL SearchUsrDic( // searching the user dictionary
|
|
#if defined(UNIIME)
|
|
LPIMEL lpImeL,
|
|
#endif
|
|
LPCANDIDATELIST lpCandList,
|
|
LPPRIVCONTEXT lpImcP)
|
|
{
|
|
HANDLE hUsrDicMem;
|
|
LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit;
|
|
|
|
hUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
|
|
lpImeL->szUsrDicMap);
|
|
if (!hUsrDicMem) {
|
|
return;
|
|
}
|
|
|
|
lpUsrDicStart = (LPBYTE)MapViewOfFile(hUsrDicMem, FILE_MAP_READ,
|
|
0, 0, lpImeL->uUsrDicSize);
|
|
if (!lpUsrDicStart) {
|
|
goto SearchUsrDicOvr;
|
|
}
|
|
|
|
lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize;
|
|
|
|
for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit;
|
|
lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) {
|
|
DWORD dwSearchPattern;
|
|
UINT uCode;
|
|
|
|
// skip the first word (bank ID) of internal code
|
|
dwSearchPattern = *(LPUNADWORD)(lpCurr + sizeof(WORD)) &
|
|
lpImeL->dwPatternMask;
|
|
|
|
#if defined(CHAJEI) || defined(QUICK) || defined(WINAR30)
|
|
if (lpImcP->iGhostCard != lpImeL->nMaxKey) {
|
|
dwSearchPattern = MatchPattern(dwSearchPattern, lpImcP);
|
|
}
|
|
#endif
|
|
|
|
#if defined(WINAR30)
|
|
dwSearchPattern &= lpImcP->dwWildCardMask;
|
|
#endif
|
|
|
|
if (lpImcP->dwPattern != dwSearchPattern) {
|
|
continue;
|
|
}
|
|
|
|
#if defined(WINAR30)
|
|
if (!lpImcP->dwLastWildCard) {
|
|
} else if (dwSearchPattern & lpImcP->dwLastWildCard) {
|
|
// a ? wild card must have a stroke there
|
|
} else {
|
|
// a ? wild card do not have a stroke there - can not match
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
uCode = *(LPUNAWSTR)lpCurr;
|
|
|
|
#if defined(UNIIME)
|
|
AddCodeIntoCand(lpImeL,lpCandList, uCode);
|
|
#else
|
|
AddCodeIntoCand(lpCandList, uCode);
|
|
#endif
|
|
|
|
if (lpCandList->dwCount >= MAXCAND) {
|
|
// Grow memory here and do something,
|
|
// if you still want to process it.
|
|
break;
|
|
}
|
|
}
|
|
|
|
UnmapViewOfFile(lpUsrDicStart);
|
|
|
|
SearchUsrDicOvr:
|
|
CloseHandle(hUsrDicMem);
|
|
|
|
return;
|
|
}
|
|
#endif // !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
|
|
|
|
#endif // !defined(ROMANIME)
|
|
|