windows-nt/Source/XPSP1/NT/windows/feime/cht/convlist.c
2020-09-26 16:20:57 +08:00

634 lines
16 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
Module Name:
CONVLIST.c
++*/
#include <windows.h>
#include <immdev.h>
#include "imeattr.h"
#include "imedefs.h"
#if defined(UNIIME)
#include "uniime.h"
#endif
#if !defined(ROMANIME)
/**********************************************************************/
/* Conversion() */
/**********************************************************************/
DWORD PASCAL Conversion(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
LPCTSTR lpszReading,
LPCANDIDATELIST lpCandList,
DWORD dwBufLen)
{
UINT uMaxCand;
DWORD dwSize = // similar to ClearCand
// header length
sizeof(CANDIDATELIST) +
// candidate string pointers
sizeof(DWORD) * MAXCAND +
// string plus NULL terminator
(sizeof(WCHAR) + sizeof(TCHAR)) * MAXCAND;
DWORD dwPattern;
PRIVCONTEXT ImcP;
#if !defined(WINIME) && !defined(UNICDIME)
BOOL fNeedUnload;
#endif
if (!dwBufLen) {
return (dwSize);
}
uMaxCand = dwBufLen - sizeof(CANDIDATELIST);
uMaxCand /= sizeof(DWORD) + sizeof(WCHAR) + sizeof(TCHAR);
if (!uMaxCand) {
// can not even put one string
return (0);
}
lpCandList->dwSize = dwSize;
lpCandList->dwStyle = IME_CAND_READ; // candidate having same reading
lpCandList->dwCount = 0;
lpCandList->dwSelection = 0;
lpCandList->dwPageStart = 0;
lpCandList->dwPageSize = CANDPERPAGE;
lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) + sizeof(DWORD) *
(uMaxCand - 1);
dwPattern = ReadingToPattern(
#if defined(UNIIME)
lpImeL,
#endif
lpszReading, ImcP.bSeq, TRUE);
if (!dwPattern) {
return (0);
}
#if !defined(WINIME) && !defined(UNICDIME)
if (lpInstL->fdwTblLoad == TBL_LOADED) {
fNeedUnload = FALSE;
} else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
LoadTable(lpInstL, lpImeL);
fNeedUnload = TRUE;
} else {
return (0);
}
#endif
if (!ConvertSeqCode2Pattern(
#if defined(UNIIME)
lpImeL,
#endif
ImcP.bSeq, &ImcP)) {
return (0);
}
SearchTbl(
#if defined(UNIIME)
lpImeL,
#endif
0, lpCandList, &ImcP);
#if defined(WINAR30)
if (!lpCandList->dwCount) {
SearchTbl(3, lpCandList, &ImcP);
}
#endif
#if !defined(WINIME) && !defined(UNICDIME)
if (lpInstL->hUsrDicMem) {
SearchUsrDic(
#if defined(UNIIME)
lpImeL,
#endif
lpCandList, &ImcP);
}
if (fNeedUnload) {
FreeTable(lpInstL);
}
#endif
return (dwSize);
}
/**********************************************************************/
/* SearchOffset() */
/* Return Value : */
/* the offset in table file which include this uOffset */
/**********************************************************************/
UINT PASCAL SearchOffset(
LPBYTE lpTbl,
UINT uTblSize,
UINT uOffset)
{
int iLo, iMid, iHi;
LPWORD lpwPtr;
iLo = 0;
iHi = uTblSize / sizeof(WORD);
iMid = (iLo + iHi) / 2;
// binary search
for (; iLo <= iHi; ) {
lpwPtr = (LPWORD)lpTbl + iMid;
if (uOffset > *lpwPtr) {
iLo = iMid + 1;
} else if (uOffset < *lpwPtr) {
iHi = iMid - 1;
} else {
break;
}
iMid = (iLo + iHi) / 2;
}
if (iMid > 0) {
iLo = iMid - 1;
} else {
iLo = 0;
}
iHi = uTblSize / sizeof(WORD);
lpwPtr = (LPWORD)lpTbl + iLo;
for (; iLo < iHi; iLo++, lpwPtr++) {
if (*lpwPtr > uOffset) {
return (iLo - 1);
}
}
return (0);
}
/**********************************************************************/
/* ReverseConversion() */
/**********************************************************************/
#if defined(PHON)
typedef struct {
BYTE szTmpBuf[sizeof(WORD) * 4 + sizeof(TCHAR)];
} PHONREVERSEBUF;
typedef PHONREVERSEBUF FAR *LPPHONREVERSEBUF;
#endif
DWORD PASCAL ReverseConversion(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
UINT uCode,
LPCANDIDATELIST lpCandList,
DWORD dwBufLen)
{
UINT uMaxCand;
DWORD dwSize = // similar to ClearCand
// header length
sizeof(CANDIDATELIST) +
// candidate string pointers
sizeof(DWORD) * MAX_COMP +
// string plus NULL terminator
#if defined(QUICK)
(sizeof(WCHAR) * 2 + sizeof(TCHAR)) * MAX_COMP;
#elif defined(WINIME) || defined(UNICDIME)
(sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR));
#else
(sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)) * MAX_COMP;
#endif
#if defined(WINIME) || defined(UNICDIME)
UINT uTmpCode;
int i;
#else
BOOL fNeedUnload;
HANDLE hTbl;
LPBYTE lpTbl, lpStart, lpEnd;
#endif
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
HANDLE hTbl0;
LPBYTE lpTbl0;
#endif
#if defined(CHAJEI) || defined(PHON)
HANDLE hTbl1;
LPBYTE lpTbl1;
#endif
if (!dwBufLen) {
return (dwSize);
}
uMaxCand = dwBufLen - sizeof(CANDIDATELIST);
#if defined(QUICK)
uMaxCand /= sizeof(DWORD) +
(sizeof(WCHAR) * 2 + sizeof(TCHAR));
#else
uMaxCand /= sizeof(DWORD) +
(sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR));
#endif
if (uMaxCand == 0) {
// can not put one string
return (0);
}
lpCandList->dwSize = sizeof(CANDIDATELIST) +
sizeof(DWORD) * uMaxCand +
#if defined(QUICK)
(sizeof(WCHAR) * 2 + sizeof(TCHAR)) * uMaxCand;
#elif defined(WINIME) || defined(UNICDIME)
(sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR));
#else
(sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)) * uMaxCand;
#endif
lpCandList->dwStyle = IME_CAND_READ;
lpCandList->dwCount = 0;
lpCandList->dwSelection = 0;
lpCandList->dwPageSize = CANDPERPAGE;
lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) + sizeof(DWORD) *
(uMaxCand - 1);
#if defined(WINIME) || defined(UNICDIME)
#if defined(WINIME) && defined(UNICODE)
{
int iChars;
CHAR szCode[4];
iChars = WideCharToMultiByte(sImeG.uAnsiCodePage, WC_COMPOSITECHECK,
(LPCWSTR)&uCode, 1, szCode, sizeof(szCode), NULL, NULL);
if (iChars >= 2) {
uTmpCode = ((UINT)(BYTE)szCode[0] << 8) | (BYTE)szCode[1];
} else {
uTmpCode = (BYTE)szCode[0];
}
if (uCode == 0x003F) {
} else if (uTmpCode == 0x003F) {
// no cooresponding BIG5 code
return (0);
} else {
}
uCode = uTmpCode;
}
#endif
uTmpCode = uCode;
for (i = lpImeL->nMaxKey - 1; i >= 0; i--) {
UINT uCompChar;
uCompChar = lpImeL->wSeq2CompTbl[(uTmpCode & 0xF) + 1];
*(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
lpCandList->dwCount] + sizeof(WCHAR) * i) = (WCHAR)uCompChar;
uTmpCode >>= 4;
}
// null terminator
*(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
lpCandList->dwCount] + sizeof(WCHAR) * lpImeL->nMaxKey) = '\0';
// string count ++
lpCandList->dwCount++;
#else
if (lpInstL->fdwTblLoad == TBL_LOADED) {
fNeedUnload = FALSE;
} else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
LoadTable(lpInstL, lpImeL);
fNeedUnload = TRUE;
} else {
return (0);
}
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
hTbl = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[2]);
#else
hTbl = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[0]);
#endif
if (!hTbl) {
return (0);
}
lpTbl = MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
if (!lpTbl) {
dwSize = 0;
goto RevConvCloseCodeTbl;
}
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
hTbl0 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[0]);
if (!hTbl0) {
dwSize = 0;
goto RevConvUnmapCodeTbl;
}
lpTbl0 = MapViewOfFile(hTbl0, FILE_MAP_READ, 0, 0, 0);
if (!lpTbl0) {
dwSize = 0;
goto RevConvCloseTbl0;
}
#endif
#if defined(CHAJEI) || defined(PHON)
hTbl1 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]);
if (!hTbl1) {
dwSize = 0;
goto RevConvUnmapTbl0;
}
lpTbl1 = MapViewOfFile(hTbl1, FILE_MAP_READ, 0, 0, 0);
if (!lpTbl1) {
dwSize = 0;
goto RevConvCloseTbl1;
}
#endif
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
lpStart = lpTbl;
lpEnd = lpTbl + lpImeL->uTblSize[2];
#else
lpStart = lpTbl + lpImeL->nSeqBytes;
lpEnd = lpTbl + lpImeL->uTblSize[0];
#endif
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
for (; lpStart < lpEnd; lpStart += sizeof(WORD)) {
#else
for (; lpStart < lpEnd; lpStart += lpImeL->nSeqBytes + sizeof(WORD)) {
#endif
DWORD dwPattern;
int i;
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
UINT uOffset;
#endif
#if defined(CHAJEI) || defined(QUICK)
DWORD dwSeqA1, dwSeqA5;
#endif
#if defined(PHON)
UINT uPhoneticCode;
#endif
#if defined(PHON)
uPhoneticCode = *(LPUNAWORD)lpStart;
#ifdef UNICODE
if (IsValidCode(uPhoneticCode)) {
if (uPhoneticCode != uCode) {
continue;
}
} else {
if (InverseEncode(uPhoneticCode) != uCode) {
continue;
}
}
#else
if ((uPhoneticCode | 0x8000) != uCode) {
continue;
}
#endif
#else
if (*(LPUNAWORD)lpStart != uCode) {
continue;
}
#endif
// find the code
#if defined(CHAJEI) || defined(QUICK)
uOffset = SearchOffset(lpTbl0, lpImeL->uTblSize[0],
(UINT)(lpStart - lpTbl) / sizeof(WORD));
dwSeqA1 = uOffset / 27; // seq code of A1
dwSeqA5 = uOffset % 27; // seq code of A5
#endif
#if defined(PHON)
uOffset = SearchOffset(lpTbl1, lpImeL->uTblSize[1],
(UINT)(lpStart - lpTbl) / sizeof(WORD));
#endif
#if defined(CHAJEI)
// pattern of A234
dwPattern = *(LPWORD)(lpTbl1 + (lpStart - lpTbl)) << lpImeL->nSeqBits;
// sequence code of A1
dwPattern |= dwSeqA1 << (lpImeL->nSeqBits * 4);
// test if 0 for A234 pattern
dwSeqA1 = lpImeL->dwSeqMask << (lpImeL->nSeqBits * 3);
// sequence code of A5
for (i = 1; i < lpImeL->nMaxKey; i++) {
if (!(dwPattern & dwSeqA1)) {
dwPattern |= dwSeqA5 <<
(lpImeL->nSeqBits * (lpImeL->nMaxKey - i - 1));
break;
} else {
dwSeqA1 >>= lpImeL->nSeqBits;
}
}
#elif defined(PHON)
dwPattern = *(LPUNADWORD)(lpTbl0 + uOffset * lpImeL->nSeqBytes) &
lpImeL->dwPatternMask;
#elif defined(QUICK)
dwPattern = (DWORD)dwSeqA1 << lpImeL->nSeqBits;
dwPattern |= dwSeqA5;
#else
dwPattern = *(LPUNADWORD)(lpStart - lpImeL->nSeqBytes) &
lpImeL->dwPatternMask;
#endif
#if defined(QUICK)
for (i = 2 - 1; i >= 0; i--) {
#else
for (i = lpImeL->nMaxKey - 1; i >= 0; i--) {
#endif
WORD wCompChar;
wCompChar = lpImeL->wSeq2CompTbl[dwPattern & lpImeL->dwSeqMask];
*(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
lpCandList->dwCount] + sizeof(WORD) * i) = wCompChar;
dwPattern >>= lpImeL->nSeqBits;
}
// null terminator
#if defined(QUICK)
*(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
lpCandList->dwCount] + sizeof(WCHAR) * 2) = '\0';
#else
*(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
lpCandList->dwCount] + sizeof(WCHAR) * lpImeL->nMaxKey) = '\0';
#endif
#if defined(PHON)
if (!lpCandList->dwCount) {
#ifdef UNICODE
} else if (IsValidCode(uPhoneticCode)) {
#else
} else if (uPhoneticCode & 0x8000) {
#endif
PHONREVERSEBUF phTmpBuf;
phTmpBuf = *(LPPHONREVERSEBUF)((LPBYTE)
lpCandList + lpCandList->dwOffset[lpCandList->dwCount]);
*(LPPHONREVERSEBUF)((LPBYTE)lpCandList +
lpCandList->dwOffset[lpCandList->dwCount]) =
*(LPPHONREVERSEBUF)((LPBYTE)lpCandList +
lpCandList->dwOffset[0]);
*(LPPHONREVERSEBUF)((LPBYTE)lpCandList +
lpCandList->dwOffset[0]) = phTmpBuf;
} else {
}
#endif
// string count ++
lpCandList->dwCount++;
#if defined(CHAJEI) || defined(WINAR30) || defined(DAYI)
// do not need to search more canidate
break;
#endif
if (lpCandList->dwCount >= (DWORD)uMaxCand) {
break;
}
#if defined(QUICK)
lpCandList->dwOffset[lpCandList->dwCount] =
lpCandList->dwOffset[lpCandList->dwCount - 1] +
sizeof(WCHAR) * 2 + sizeof(TCHAR);
#else
lpCandList->dwOffset[lpCandList->dwCount] =
lpCandList->dwOffset[lpCandList->dwCount - 1] +
sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR);
#endif
}
if (!lpCandList->dwCount) {
dwSize = 0;
}
#if defined(CHAJEI) || defined(PHON)
UnmapViewOfFile(lpTbl1);
RevConvCloseTbl1:
CloseHandle(hTbl1);
RevConvUnmapTbl0:
#endif
#if defined(CHAJEI) || defined(PHON) || defined(QUICK)
UnmapViewOfFile(lpTbl0);
RevConvCloseTbl0:
CloseHandle(hTbl0);
RevConvUnmapCodeTbl:
#endif
UnmapViewOfFile(lpTbl);
RevConvCloseCodeTbl:
CloseHandle(hTbl);
if (fNeedUnload) {
FreeTable(lpInstL);
}
#endif
return (dwSize);
}
#endif
/**********************************************************************/
/* ImeConversionList() / UniImeConversionList() */
/**********************************************************************/
#if defined(UNIIME)
DWORD WINAPI UniImeConversionList(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
DWORD WINAPI ImeConversionList(
#endif
HIMC hIMC,
LPCTSTR lpszSrc,
LPCANDIDATELIST lpCandList,
DWORD dwBufLen,
UINT uFlag)
{
#if defined(ROMANIME)
return (0);
#else
UINT uCode;
if (!dwBufLen) {
} else if (!lpszSrc) {
return (0);
} else if (!*lpszSrc) {
return (0);
} else if (!lpCandList) {
return (0);
} else if (dwBufLen <= sizeof(CANDIDATELIST)) {
// buffer size can not even put the header information
return (0);
} else {
}
switch (uFlag) {
case GCL_CONVERSION:
return Conversion(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
lpszSrc, lpCandList, dwBufLen);
break;
case GCL_REVERSECONVERSION:
if (!dwBufLen) {
return ReverseConversion(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
0, lpCandList, dwBufLen);
}
// only support one DBCS char reverse conversion
if (*(LPTSTR)((LPBYTE)lpszSrc + sizeof(WORD)) != '\0') {
return (0);
}
uCode = *(LPUNAWORD)lpszSrc;
#ifndef UNICODE
// swap lead byte & second byte, UNICODE don't need it
uCode = HIBYTE(uCode) | (LOBYTE(uCode) << 8);
#endif
return ReverseConversion(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
uCode, lpCandList, dwBufLen);
break;
case GCL_REVERSE_LENGTH:
return sizeof(WCHAR);
break;
default:
return (0);
break;
}
#endif
}