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

850 lines
21 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
Module Name:
REGWORD.C - register word into dictionary of IME
++*/
#include <windows.h>
#include <immdev.h>
#include "imeattr.h"
#include "imedefs.h"
#include "imerc.h"
#if defined(UNIIME)
#include "uniime.h"
#endif
#if !defined(ROMANIME)
/**********************************************************************/
/* ReadingToPattern */
/* Return Value: */
/* the pattern of the reading (packed sequence code) */
/**********************************************************************/
DWORD PASCAL ReadingToPattern(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
LPCTSTR lpszReading,
LPBYTE lpbSeq,
BOOL fFinalized)
{
BYTE bSeq[8];
char cIndex;
DWORD dwPattern;
int i;
#if defined(PHON)
char cOldIndex;
#endif
cIndex = 0;
#if defined(PHON)
cOldIndex = -1;
#endif
*(LPDWORD)bSeq = 0;
#if defined(CHAJEI) || defined(QUICK) || defined(WINAR30) || defined(UNIIME)
*(LPDWORD)&bSeq[4] = 0;
#endif
for (; *lpszReading; (LPBYTE)lpszReading += sizeof(WCHAR)) {
int iSeqCode;
for (iSeqCode = lpImeL->nSeqCode; iSeqCode >= 0; iSeqCode--) {
if (lpImeL->wSeq2CompTbl[iSeqCode] == *(LPWORD)lpszReading) {
break;
}
}
if (iSeqCode < 0) {
return (0);
}
#if defined(PHON) // phontic can have space between reading
if (iSeqCode == 0) {
continue;
}
#else
if (iSeqCode == 0) {
break;
}
#endif
#if defined(PHON)
cIndex = cSeq2IndexTbl[iSeqCode];
// the index is conflict with previous reading
if (cIndex <= cOldIndex) {
return (0);
}
#endif
// too many reading
if (cIndex >= lpImeL->nMaxKey) {
return (0);
}
bSeq[cIndex] = (BYTE)iSeqCode;
#if defined(PHON)
if (cIndex == 3 && cOldIndex == -1) {
return (0);
}
cOldIndex = cIndex;
#else
cIndex++;
#endif
}
#if defined(PHON)
// the index of a finalized char must be 3
if (cIndex != 3 && fFinalized) {
return (0);
}
#elif (WINIME)
// internal code must be 4 digits
if (!bSeq[3] && fFinalized) {
return (0);
}
if (bSeq[0]) {
// similar to InternalCodeRange
// 0x8??? - 0xF??? is OK
if (bSeq[0] >= 0x09 && bSeq[0] <= 0x10) {
} else {
// there is no 0x0??? - 0x7???
return (0);
}
}
if (bSeq[1]) {
if (bSeq[0] == (0x08 + 1)) {
if (bSeq[1] <= (0x00 + 1)) {
// there is no 0x80??
return (0);
} else {
}
} else if (bSeq[0] == (0x0F + 1)) {
if (bSeq[1] >= (0x0F + 1)) {
// there is no 0xFF??
return (0);
} else {
}
} else {
}
}
if (bSeq[2]) {
if (bSeq[2] < (0x04 + 1)) {
// there is no 0x??0?, 0x??1?, 0x??2?, 0x??3?
return (0);
} else if (bSeq[2] < (0x08 + 1)) {
} else if (bSeq[2] < (0x0A + 1)) {
// there is no 0x??8?, 0x??9?
return (0);
} else {
}
}
if (bSeq[3]) {
if (bSeq[2] == (0x07 + 1)) {
if (bSeq[3] >= (0x0F + 1)) {
// there is no 0x??7F
return (0);
} else {
}
} else if (bSeq[2] == (0x0A + 1)) {
if (bSeq[3] <= (0x00 + 1)) {
// there is no 0x??A0
return (0);
} else {
}
} else if (bSeq[2] == (0x0F + 1)) {
if (bSeq[3] <= (0x0F + 1)) {
// there is no 0x??FF
return (0);
} else {
}
} else {
}
}
#endif
dwPattern = 0;
for (i = 0; i < lpImeL->nMaxKey; i++) {
dwPattern <<= lpImeL->nSeqBits;
dwPattern |= bSeq[i];
}
if (lpbSeq) {
*(LPDWORD)lpbSeq = *(LPDWORD)bSeq;
#if defined(CHAJEI) || defined(QUICK) || defined(WINAR30) || defined(UNIIME)
*(LPDWORD)&lpbSeq[4] = *(LPDWORD)&bSeq[4];
#endif
}
return (dwPattern);
}
#endif
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
/**********************************************************************/
/* RegsisterWord */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
BOOL PASCAL RegisterWord(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
LPCTSTR lpszReading,
LPCTSTR lpszString,
LPBYTE lpUsrDicStart,
LPBYTE lpCurr)
{
DWORD dwPattern;
DWORD dwWriteByte;
BYTE bBuf[10];
HANDLE hUsrDicFile;
DWORD dwPos;
PSECURITY_ATTRIBUTES psa;
if (lpCurr > lpUsrDicStart + lpImeL->uUsrDicSize) {
// invalid offset
return (FALSE);
}
dwPattern = ReadingToPattern(
#if defined(UNIIME)
lpImeL,
#endif
lpszReading, &bBuf[4], TRUE);
if (!dwPattern) {
return (FALSE);
}
if (lpCurr == lpUsrDicStart + lpImeL->uUsrDicSize) {
} else if (dwPattern == (*(LPUNADWORD)(lpCurr + sizeof(WORD)) &
lpImeL->dwPatternMask)) {
// the same one as old, don't need update
return (TRUE);
}
*(LPWORD)bBuf = 1; // bank ID
#ifdef UNICODE
*(LPWORD)&bBuf[2] = *(LPWORD)lpszString;
#else
// internal code, reverve the ANSI string
bBuf[2] = *((LPBYTE)lpszString + 1);
bBuf[3] = *((LPBYTE)lpszString);
#endif
psa = CreateSecurityAttributes();
// write this word into file
hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hUsrDicFile == INVALID_HANDLE_VALUE) {
FreeSecurityAttributes(psa);
return (FALSE);
}
dwPos = (DWORD) ((lpCurr - lpUsrDicStart) / (lpImeL->nSeqBytes + 2) *
(lpImeL->nMaxKey + 4) + 256);
SetFilePointer(hUsrDicFile, dwPos, (LPLONG)NULL, FILE_BEGIN);
WriteFile(hUsrDicFile, bBuf, lpImeL->nMaxKey + 4, &dwWriteByte,
NULL);
*(LPUNAWORD)lpCurr = *(LPWORD)&bBuf[2];
CopyMemory((LPBYTE)lpCurr + sizeof(WORD), &dwPattern, lpImeL->nSeqBytes);
if (lpCurr == (lpUsrDicStart + lpImeL->uUsrDicSize)) {
// add new word
lpImeL->uUsrDicSize += lpImeL->nSeqBytes + sizeof(WORD);
*(LPDWORD)bBuf = lpImeL->uUsrDicSize / (lpImeL->nSeqBytes +
sizeof(WORD));
// offset of ulTableCount
SetFilePointer(hUsrDicFile, 0x0C, (LPLONG)NULL, FILE_BEGIN);
// write to ulTableCount
WriteFile(hUsrDicFile, bBuf, sizeof(DWORD), &dwWriteByte,
NULL);
}
CloseHandle(hUsrDicFile);
FreeSecurityAttributes(psa);
return (TRUE);
}
#endif
/**********************************************************************/
/* ImeRegsisterWord */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
#if defined(UNIIME)
BOOL WINAPI UniImeRegisterWord(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
BOOL WINAPI ImeRegisterWord(
#endif
LPCTSTR lpszReading,
DWORD dwStyle,
LPCTSTR lpszString)
{
#if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME)
return (FALSE);
#else
BOOL fRet, fNeedUnload;
HANDLE hUsrDicMem;
WORD wCode;
LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit;
fRet = FALSE;
if (!lpszString) {
return (fRet);
}
if (!lpszReading) {
return (fRet);
}
// only handle word not string now, should consider string later?
if (*(LPCTSTR)((LPBYTE)lpszString + sizeof(WORD)) != '\0') {
return (fRet);
}
if (!lpImeL->szUsrDic[0]) {
if (!UsrDicFileName(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
NULL)) {
return (fRet);
}
}
if (!lpInstL->hUsrDicMem) {
// we load here, and maybe need to unload
LoadUsrDicFile(lpInstL, lpImeL);
if (!lpInstL->hUsrDicMem) {
return (fRet);
}
}
if (lpInstL->fdwTblLoad == TBL_LOADED) {
fNeedUnload = FALSE;
} else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
// we only load dic, we will unload it
fNeedUnload = TRUE;
} else {
return (fRet);
}
hUsrDicMem = OpenFileMapping(FILE_MAP_WRITE, FALSE,
lpImeL->szUsrDicMap);
if (!hUsrDicMem) {
goto RegWordUnloadUsrDic;
}
lpUsrDicStart = MapViewOfFile(hUsrDicMem, FILE_MAP_WRITE,
0, 0, 0);
if (!lpUsrDicStart) {
goto RegWordUnloadUsrDic;
}
#ifdef UNICODE
wCode = *lpszString;
#else
wCode = ((BYTE)lpszString[0] << 8) | (BYTE)lpszString[1];
#endif
lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize;
for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit;
lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) {
// find the internal code
if (wCode == *(LPUNAWORD)lpCurr) {
break;
}
}
fRet = RegisterWord(
#if defined(UNIIME)
lpImeL,
#endif
lpszReading, lpszString, lpUsrDicStart, lpCurr);
UnmapViewOfFile(lpUsrDicStart);
CloseHandle(hUsrDicMem);
RegWordUnloadUsrDic:
if (fNeedUnload) {
if (lpInstL->hUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
}
lpInstL->hUsrDicMem = (HANDLE)NULL;
}
return (fRet);
#endif
}
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
/**********************************************************************/
/* UnregsisterWord */
/**********************************************************************/
void PASCAL UnregisterWord(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
LPBYTE lpUsrDicStart,
LPBYTE lpCurr,
LPBYTE lpUsrDicLimit)
{
LPBYTE lpMem;
HANDLE hUsrDicFile;
DWORD dwPos;
DWORD dwByte;
PSECURITY_ATTRIBUTES psa;
BOOL retVal;
MoveMemory(lpCurr, lpCurr + lpImeL->nSeqBytes + sizeof(WORD),
lpUsrDicLimit - lpCurr - lpImeL->nSeqBytes - sizeof(WORD));
lpMem = (LPBYTE)GlobalAlloc(GPTR, (LONG)(lpUsrDicLimit - lpCurr) );
if (!lpMem) {
return;
}
psa = CreateSecurityAttributes();
// delete this word from file
hUsrDicFile = CreateFile(lpImeL->szUsrDic,
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ, psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hUsrDicFile == INVALID_HANDLE_VALUE) {
FreeSecurityAttributes(psa);
GlobalFree((HGLOBAL)lpMem);
return;
}
dwPos = (DWORD) ((lpCurr - lpUsrDicStart) / (lpImeL->nSeqBytes + 2) *
(lpImeL->nMaxKey + 4) + 256);
SetFilePointer(hUsrDicFile, dwPos + lpImeL->nMaxKey + 4,
(LPLONG)NULL, FILE_BEGIN);
retVal = ReadFile(hUsrDicFile, lpMem,(DWORD)(lpUsrDicLimit-lpCurr-lpImeL->nMaxKey-4),
&dwByte, NULL);
if ( retVal == FALSE )
{
CloseHandle(hUsrDicFile);
FreeSecurityAttributes(psa);
GlobalFree((HGLOBAL)lpMem);
return;
}
SetFilePointer(hUsrDicFile, dwPos, (LPLONG)NULL, FILE_BEGIN);
WriteFile(hUsrDicFile,lpMem,(DWORD)(lpUsrDicLimit-lpCurr-lpImeL->nMaxKey-4),
&dwByte, NULL);
SetEndOfFile(hUsrDicFile);
lpImeL->uUsrDicSize -= lpImeL->nSeqBytes + sizeof(WORD);
*(LPDWORD)lpMem = lpImeL->uUsrDicSize / (lpImeL->nSeqBytes +
sizeof(WORD));
// offset of ulTableCount
SetFilePointer(hUsrDicFile, 0x0C, (LPLONG)NULL, FILE_BEGIN);
// write to ulTableCount
WriteFile(hUsrDicFile, lpMem, sizeof(DWORD), &dwByte,
NULL);
CloseHandle(hUsrDicFile);
FreeSecurityAttributes(psa);
GlobalFree((HGLOBAL)lpMem);
return;
}
#endif
/**********************************************************************/
/* ImeUnregsisterWord / UniImeUnregisterWord */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
#if defined(UNIIME)
BOOL WINAPI UniImeUnregisterWord(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
BOOL WINAPI ImeUnregisterWord(
#endif
LPCTSTR lpszReading,
DWORD dwStyle,
LPCTSTR lpszString)
{
#if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME)
return (FALSE);
#else
BOOL fRet, fNeedUnload;
HANDLE hUsrDicMem;
LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit;
DWORD dwPattern;
WORD wCode;
fRet = FALSE;
if (!lpszString) {
return (fRet);
}
if (dwStyle != IME_REGWORD_STYLE_EUDC) {
return (fRet);
}
// only handle word not string now, should consider string later?
if (*(LPCTSTR)((LPBYTE)lpszString + sizeof(WORD)) != '\0') {
return (fRet);
}
if (!lpImeL->szUsrDic[0]) {
return (fRet);
}
if (lpInstL->fdwTblLoad == TBL_LOADED) {
fNeedUnload = FALSE;
} else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
LoadUsrDicFile(lpInstL, lpImeL);
if (lpImeL->fdwErrMsg & (ERRMSG_LOAD_USRDIC|ERRMSG_MEM_USRDIC)) {
return (fRet);
}
// we only load dic, we will unload it
fNeedUnload = TRUE;
} else {
return (fRet);
}
hUsrDicMem = OpenFileMapping(FILE_MAP_WRITE, FALSE,
lpImeL->szUsrDicMap);
if (!hUsrDicMem) {
goto IUWUnloadUsrDic;
}
lpUsrDicStart = MapViewOfFile(hUsrDicMem, FILE_MAP_WRITE,
0, 0, 0);
if (!lpUsrDicStart) {
goto IUWUnloadUsrDic;
}
lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize;
dwPattern = ReadingToPattern(
#if defined(UNIIME)
lpImeL,
#endif
lpszReading, NULL, TRUE);
#ifdef UNICODE
wCode = *(LPWORD)lpszString;
#else
wCode = ((BYTE)lpszString[0] << 8) | (BYTE)lpszString[1];
#endif
for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit;
lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) {
DWORD dwDicPattern;
// find the internal code
if (wCode != *(LPUNAWORD)lpCurr) {
continue;
}
dwDicPattern = *(LPUNADWORD)(lpCurr + sizeof(WORD)) &
lpImeL->dwPatternMask;
if (!lpszReading) {
// no reading, specify internal code only
} else if (dwDicPattern == dwPattern) {
} else {
continue;
}
fRet = TRUE;
UnregisterWord(
#if defined(UNIIME)
lpImeL,
#endif
lpUsrDicStart, lpCurr, lpUsrDicLimit);
break;
}
UnmapViewOfFile(lpUsrDicStart);
CloseHandle(hUsrDicMem);
IUWUnloadUsrDic:
if (fNeedUnload) {
if (lpInstL->hUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
}
lpInstL->hUsrDicMem = (HANDLE)NULL;
}
return (fRet);
#endif
}
/**********************************************************************/
/* ImeGetRegsisterWordStyle / UniImeGetRegsisterWordStyle */
/* Return Value: */
/* number of styles copied/required */
/**********************************************************************/
#if defined(UNIIME)
UINT WINAPI UniImeGetRegisterWordStyle(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
UINT WINAPI ImeGetRegisterWordStyle(
#endif
UINT nItem,
LPSTYLEBUF lpStyleBuf)
{
#if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME)
return (FALSE);
#else
if (!nItem) {
return (1);
}
// invalid case
if (!lpStyleBuf) {
return (0);
}
lpStyleBuf->dwStyle = IME_REGWORD_STYLE_EUDC;
LoadString(hInst, IDS_EUDC, lpStyleBuf->szDescription,
sizeof(lpStyleBuf->szDescription)/sizeof(TCHAR));
return (1);
#endif
}
#if !defined(ROMANIME)
/**********************************************************************/
/* PatternToReading */
/**********************************************************************/
void PASCAL PatternToReading(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
DWORD dwPattern,
LPTSTR lpszReading)
{
int i;
i = lpImeL->nMaxKey;
*(LPTSTR)((LPBYTE)lpszReading + sizeof(WCHAR) * i) = '\0';
// delete the ending 0 sequence code
for (i--; i >= 0; i--) {
if (dwPattern & lpImeL->dwSeqMask) {
break;
}
*(LPWSTR)((LPBYTE)lpszReading + sizeof(WCHAR) * i) = '\0';
dwPattern >>= lpImeL->nSeqBits;
}
for (; i >= 0; i--) {
*(LPWORD)((LPBYTE)lpszReading + sizeof(WORD) * i) =
lpImeL->wSeq2CompTbl[dwPattern & lpImeL->dwSeqMask];
dwPattern >>= lpImeL->nSeqBits;
}
return;
}
#endif
/**********************************************************************/
/* ImeEnumRegisterWord */
/* Return Value: */
/* the last value return by the callback function */
/**********************************************************************/
#if defined(UNIIME)
UINT WINAPI UniImeEnumRegisterWord(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
UINT WINAPI ImeEnumRegisterWord(
#endif
REGISTERWORDENUMPROC lpfnRegisterWordEnumProc,
LPCTSTR lpszReading,
DWORD dwStyle,
LPCTSTR lpszString,
LPVOID lpData)
{
#if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME)
return (FALSE);
#else
HANDLE hUsrDicMem;
WORD wCode;
BOOL fNeedUnload;
LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit;
DWORD dwPattern;
UINT uRet;
uRet = 0;
if (!dwStyle) {
} else if (dwStyle == IME_REGWORD_STYLE_EUDC) {
} else {
return (uRet);
}
if (!lpszString) {
} else if (*(LPCTSTR)((LPBYTE)lpszString + sizeof(WORD)) == '\0') {
#ifdef UNICODE
wCode = *(LPWORD)lpszString;
#else
wCode = ((BYTE)lpszString[0] << 8) | (BYTE)lpszString[1];
#endif
} else {
return (uRet);
}
if (lpInstL->fdwTblLoad == TBL_LOADED) {
fNeedUnload = FALSE;
} else if (!lpImeL->szUsrDic[0]) {
return (uRet);
} else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
LoadUsrDicFile(lpInstL, lpImeL);
if (lpImeL->fdwErrMsg & (ERRMSG_LOAD_USRDIC|ERRMSG_MEM_USRDIC)) {
return (uRet);
}
// we only load dic, we will unload it
fNeedUnload = TRUE;
} else {
return (uRet);
}
hUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
lpImeL->szUsrDicMap);
if (!hUsrDicMem) {
goto IERWUnloadUsrDic;
}
lpUsrDicStart = MapViewOfFile(hUsrDicMem, FILE_MAP_READ,
0, 0, 0);
if (!lpUsrDicStart) {
goto IERWUnloadUsrDic;
}
if (lpszReading) {
dwPattern = ReadingToPattern(
#if defined(UNIIME)
lpImeL,
#endif
lpszReading, NULL, TRUE);
}
lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize;
for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit;
lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) {
DWORD dwDicPattern;
LPTSTR lpszMatchReading, lpszMatchString;
BYTE szBufReading[sizeof(WORD) * 12];
BYTE szBufString[sizeof(WORD) * 2];
// match string
if (!lpszString) {
lpszMatchString = (LPTSTR)szBufString;
*(LPWORD)lpszMatchString = *(LPUNAWORD)lpCurr;
*(LPTSTR)((LPBYTE)lpszMatchString + sizeof(WORD)) = '\0';
#ifndef UNICODE
// reverse it to ANSI string
wCode = szBufString[0];
szBufString[0] = szBufString[1];
szBufString[1] = (BYTE)wCode;
#endif
} else if (wCode == *(LPUNAWORD)lpCurr) {
lpszMatchString = (LPTSTR)lpszString;
} else {
continue; // not matched
}
// match reading
dwDicPattern = *(LPUNADWORD)(lpCurr + sizeof(WORD)) &
lpImeL->dwPatternMask;
if (!lpszReading) {
lpszMatchReading = (LPTSTR)szBufReading;
PatternToReading(
#if defined(UNIIME)
lpImeL,
#endif
dwDicPattern, lpszMatchReading);
} else if (dwDicPattern == dwPattern) {
lpszMatchReading = (LPTSTR)lpszReading;
} else {
continue; // not matched
}
uRet = (*lpfnRegisterWordEnumProc)(lpszMatchReading,
IME_REGWORD_STYLE_EUDC, lpszMatchString, lpData);
if (!uRet) {
break;
}
}
UnmapViewOfFile(lpUsrDicStart);
CloseHandle(hUsrDicMem);
IERWUnloadUsrDic:
if (fNeedUnload) {
if (lpInstL->hUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
}
lpInstL->hUsrDicMem = (HANDLE)NULL;
}
return (uRet);
#endif
}