WindowsXP-SP1/windows/feime/cht/dic.c
2020-09-30 16:53:49 +02:00

520 lines
16 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
Module Name:
DIC.c
++*/
#include <windows.h>
#include <winerror.h>
#include <immdev.h>
#include "imeattr.h"
#include "imedefs.h"
#include "imerc.h"
#if !defined(ROMANIME)
#if !defined(WINIME) && !defined(UNICDIME)
/**********************************************************************/
/* MemoryLess() */
/**********************************************************************/
void PASCAL MemoryLess(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
DWORD fdwErrMsg)
{
TCHAR szErrMsg[64];
if (lpImeL->fdwErrMsg & fdwErrMsg) {
// message already prompted
return;
}
LoadString(hInst, IDS_MEM_LESS_ERR, szErrMsg, sizeof(szErrMsg)/sizeof(TCHAR));
lpImeL->fdwErrMsg |= fdwErrMsg;
MessageBeep((UINT)-1);
MessageBox((HWND)NULL, szErrMsg, lpImeL->szIMEName,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
return;
}
/**********************************************************************/
/* ReadUsrDicToMem() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
BOOL PASCAL ReadUsrDicToMem(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HANDLE hUsrDicFile,
DWORD dwUsrDicSize,
UINT uUsrDicSize,
UINT uRecLen,
UINT uReadLen,
UINT uWriteLen)
{
LPBYTE lpUsrDicMem, lpMem, lpMemLimit;
DWORD dwPos, dwReadByte;
if (dwUsrDicSize < 258) { // no char in this dictionary
return (TRUE);
}
lpUsrDicMem = MapViewOfFile(lpInstL->hUsrDicMem, FILE_MAP_WRITE, 0, 0,
uUsrDicSize + 20);
if (!lpUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
MemoryLess(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
ERRMSG_MEM_USRDIC);
lpInstL->hUsrDicMem = NULL;
return (FALSE);
}
lpMemLimit = lpUsrDicMem + uUsrDicSize;
// read in data, skip header - two headers are similiar
dwPos = SetFilePointer(hUsrDicFile, 258, (LPLONG)NULL, FILE_BEGIN);
for (lpMem = lpUsrDicMem; dwPos < dwUsrDicSize; lpMem += uWriteLen) {
short i;
DWORD dwPattern;
BOOL retVal;
if (lpMem >= lpMemLimit) {
break;
}
retVal = ReadFile(hUsrDicFile, lpMem, uReadLen, &dwReadByte,
(LPOVERLAPPED)NULL);
if ( retVal == FALSE )
{
UnmapViewOfFile(lpUsrDicMem);
CloseHandle(lpInstL->hUsrDicMem);
MemoryLess(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
ERRMSG_MEM_USRDIC);
lpInstL->hUsrDicMem = NULL;
return (FALSE);
}
// Compress the sequence code and put the first char most significant.
// Limitation - 32 bits only
dwPattern = 0;
for (i = 0; i < lpImeL->nMaxKey; i++) {
dwPattern <<= lpImeL->nSeqBits;
dwPattern |= *(lpMem + 2 + i);
}
*(LPUNADWORD)(lpMem + 2) = dwPattern;
// go to next record
dwPos = SetFilePointer(hUsrDicFile, dwPos + uRecLen, (LPLONG)NULL,
FILE_BEGIN);
}
UnmapViewOfFile(lpUsrDicMem);
return (TRUE);
}
/**********************************************************************/
/* LoadUsrDicFile() */
/* Description: */
/* try to convert to sequence code format, compression and */
/* don't use two way to search */
/**********************************************************************/
void PASCAL LoadUsrDicFile( // load user dic file into memory
LPINSTDATAL lpInstL,
LPIMEL lpImeL)
{
HANDLE hReadUsrDicMem;
HANDLE hUsrDicFile;
DWORD dwUsrDicFileSize;
UINT uRecLen, uReadLen, uWriteLen;
UINT uUsrDicSize;
BOOL fRet;
PSECURITY_ATTRIBUTES psa;
// no user dictionary
if (!lpImeL->szUsrDicMap[0]) {
lpImeL->uUsrDicSize = 0;
CloseHandle(lpInstL->hUsrDicMem);
lpInstL->hUsrDicMem = NULL;
lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_USRDIC | ERRMSG_MEM_USRDIC);
return;
}
psa = CreateSecurityAttributes();
if (lpInstL->hUsrDicMem) {
// the memory is already here
goto LoadUsrDicErrMsg;
}
hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
lpImeL->szUsrDicMap);
if (hReadUsrDicMem) {
// another process already create a mapping file, we will use it
goto LoadUsrDicMem;
}
// read the user dic file into memory
hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hUsrDicFile != INVALID_HANDLE_VALUE) { // OK
goto OpenUsrDicFile;
}
// if the work station version, SHARE_WRITE may fail
hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_READ,
FILE_SHARE_READ,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
OpenUsrDicFile:
if (hUsrDicFile != INVALID_HANDLE_VALUE) { // OK
lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_USRDIC);
} else if (lpImeL->fdwErrMsg & ERRMSG_LOAD_USRDIC) {
// already prompt error message before, no more
FreeSecurityAttributes(psa);
return;
} else {
TCHAR szFmtStr[64];
TCHAR szErrMsg[2 * MAX_PATH];
// temp use szIMEName as format string buffer of error message
LoadString(hInst, IDS_FILE_OPEN_ERR, szFmtStr, sizeof(szFmtStr)/sizeof(TCHAR));
wsprintf(szErrMsg, szFmtStr, lpImeL->szUsrDic);
lpImeL->fdwErrMsg |= ERRMSG_LOAD_USRDIC;
MessageBeep((UINT)-1);
MessageBox((HWND)NULL, szErrMsg, lpImeL->szIMEName,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
FreeSecurityAttributes(psa);
return;
}
// one record length - only sequence code, now
uRecLen = lpImeL->nMaxKey + 4;
// read sequence code and internal code
uReadLen = lpImeL->nMaxKey + 2;
// length write into memory handle
uWriteLen = lpImeL->nSeqBytes + 2;
// get the length of the file
dwUsrDicFileSize = GetFileSize(hUsrDicFile, (LPDWORD)NULL);
uUsrDicSize = (UINT)(dwUsrDicFileSize - 256) / uRecLen * uWriteLen;
// max EUDC chars
lpInstL->hUsrDicMem = CreateFileMapping(INVALID_HANDLE_VALUE,
psa, PAGE_READWRITE, 0, MAX_EUDC_CHARS * uWriteLen + 20,
lpImeL->szUsrDicMap);
if (!lpInstL->hUsrDicMem) {
MemoryLess(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
ERRMSG_MEM_USRDIC);
fRet = FALSE;
} else if (GetLastError() == ERROR_ALREADY_EXISTS) {
// another process also create another one, we will use it
hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
lpImeL->szUsrDicMap);
CloseHandle(lpInstL->hUsrDicMem);
CloseHandle(hUsrDicFile);
if (hReadUsrDicMem != NULL) { // OK
lpInstL->hUsrDicMem = hReadUsrDicMem;
lpImeL->uUsrDicSize = uUsrDicSize;
lpImeL->fdwErrMsg &= ~(ERRMSG_MEM_USRDIC);
} else {
MemoryLess(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
ERRMSG_MEM_USRDIC);
lpInstL->hUsrDicMem = NULL;
}
FreeSecurityAttributes(psa);
return;
} else {
fRet = ReadUsrDicToMem(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
hUsrDicFile, dwUsrDicFileSize, uUsrDicSize, uRecLen,
uReadLen, uWriteLen);
}
CloseHandle(hUsrDicFile);
if (!fRet) {
if (lpInstL->hUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
lpInstL->hUsrDicMem = NULL;
}
FreeSecurityAttributes(psa);
return;
}
// open a read only memory for EUDC table
hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
lpImeL->szUsrDicMap);
// reopen a read file and close the original write file
CloseHandle(lpInstL->hUsrDicMem);
lpImeL->uUsrDicSize = uUsrDicSize;
LoadUsrDicMem:
lpInstL->hUsrDicMem = hReadUsrDicMem;
LoadUsrDicErrMsg:
lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_USRDIC | ERRMSG_MEM_USRDIC);
FreeSecurityAttributes(psa);
return;
}
/**********************************************************************/
/* LoadOneTable() */
/* Description: */
/* memory handle & size of .TBL file will be assigned to */
/* lpImeL */
/* Eeturn Value: */
/* length of directory of the .TBL file */
/**********************************************************************/
UINT PASCAL LoadOneTable( // load one of table file
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
LPTSTR szTable, // file name of .TBL
UINT uIndex, // the index of array to store memory handle
UINT uLen, // length of the directory
LPTSTR szPath) // buffer for directory
{
HANDLE hTblFile;
HGLOBAL hMap;
DWORD dwFileSize;
PSECURITY_ATTRIBUTES psa;
if (lpInstL->hMapTbl[uIndex]) { // already loaded
CloseHandle(lpInstL->hMapTbl[uIndex]);
lpInstL->hMapTbl[uIndex] = (HANDLE)NULL;
}
psa = CreateSecurityAttributes();
if (uLen) {
lstrcpy((LPTSTR)&szPath[uLen], szTable);
hTblFile = CreateFile(szPath, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hTblFile != INVALID_HANDLE_VALUE) {
goto OpenDicFile;
}
// if the work station version, SHARE_WRITE will fail
hTblFile = CreateFile(szPath, GENERIC_READ,
FILE_SHARE_READ, psa,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
} else {
// try system directory next
uLen = GetSystemDirectory(szPath, MAX_PATH);
if (szPath[uLen - 1] != '\\') { // consider N:\ ;
szPath[uLen++] = '\\';
}
lstrcpy((LPTSTR)&szPath[uLen], szTable);
hTblFile = CreateFile(szPath, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hTblFile != INVALID_HANDLE_VALUE) {
goto OpenDicFile;
}
// if the work station version, SHARE_WRITE will fail
hTblFile = CreateFile(szPath, GENERIC_READ,
FILE_SHARE_READ, psa,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
}
OpenDicFile:
// can not find the table file
if (hTblFile != INVALID_HANDLE_VALUE) { // OK
} else if (lpImeL->fdwErrMsg & (ERRMSG_LOAD_0 << uIndex)) {
// already prompt error message before, no more
FreeSecurityAttributes(psa);
return (0);
} else { // prompt error message
TCHAR szFmtStr[64];
TCHAR szErrMsg[2 * MAX_PATH];
#if defined(WINAR30)
if(uIndex==4 || uIndex==5)
{
return (uLen);
}
#endif
// temp use szIMEName as format string buffer of error message
LoadString(hInst, IDS_FILE_OPEN_ERR, szFmtStr, sizeof(szFmtStr)/sizeof(TCHAR));
wsprintf(szErrMsg, szFmtStr, szTable);
lpImeL->fdwErrMsg |= ERRMSG_LOAD_0 << uIndex;
MessageBeep((UINT)-1);
MessageBox((HWND)NULL, szErrMsg, lpImeL->szIMEName,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
FreeSecurityAttributes(psa);
return (0);
}
lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_0 << uIndex);
// create file mapping for IME tables
hMap = CreateFileMapping((HANDLE)hTblFile, psa, PAGE_READONLY,
0, 0, szTable);
dwFileSize = GetFileSize(hTblFile, (LPDWORD)NULL);
CloseHandle(hTblFile);
FreeSecurityAttributes(psa);
if (!hMap) {
MemoryLess(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
ERRMSG_MEM_0 << uIndex);
return (0);
}
lpImeL->fdwErrMsg &= ~(ERRMSG_MEM_0 << uIndex);
lpInstL->hMapTbl[uIndex] = hMap;
// get file length
lpImeL->uTblSize[uIndex] = dwFileSize;
return (uLen);
}
#endif
/**********************************************************************/
/* LoadTable() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
BOOL PASCAL LoadTable( // check the table files of IME, include user
// defined dictionary
LPINSTDATAL lpInstL,
LPIMEL lpImeL)
{
#if !defined(WINIME) && !defined(UNICDIME)
int i;
UINT uLen;
TCHAR szBuf[MAX_PATH];
#endif
if (lpInstL->fdwTblLoad == TBL_LOADED) {
return (TRUE);
}
#if !defined(WINIME) && !defined(UNICDIME)
uLen = 0;
// A15.TBL, A234.TBL, ACODE.TBL, / PHON.TBL, PHONPTR.TBL, PHONCODE.TBL,
for (i = 0; i < MAX_IME_TABLES; i++) {
if (!*lpImeL->szTblFile[i]) {
} else if (uLen = LoadOneTable(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
lpImeL->szTblFile[i], i, uLen, szBuf)) {
} else {
int j;
for (j = 0; j < i; j++) {
if (lpInstL->hMapTbl[j]) {
CloseHandle(lpInstL->hMapTbl[j]);
lpInstL->hMapTbl[j] = (HANDLE)NULL;
}
}
lpInstL->fdwTblLoad = TBL_LOADERR;
return (FALSE);
}
}
#endif
lpInstL->fdwTblLoad = TBL_LOADED;
#if !defined(WINIME) && !defined(UNICDIME)
if (lpImeL->szUsrDic[0]) {
LoadUsrDicFile(lpInstL, lpImeL);
}
#endif
return (TRUE);
}
/**********************************************************************/
/* FreeTable() */
/**********************************************************************/
void PASCAL FreeTable(
LPINSTDATAL lpInstL)
{
#if !defined(WINIME) && !defined(UNICDIME)
int i;
// A15.TBL, A234.TBL, ACODE.TBL, / PHON.TBL, PHONPTR.TBL, PHONCODE.TBL,
for (i = 0; i < MAX_IME_TABLES; i++) {
if (lpInstL->hMapTbl[i]) {
CloseHandle(lpInstL->hMapTbl[i]);
lpInstL->hMapTbl[i] = (HANDLE)NULL;
}
}
// do not need to free phrase data base, maybe next IME will use it
// uniime.dll will free it on library detach time
if (lpInstL->hUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
lpInstL->hUsrDicMem = (HANDLE)NULL;
}
#endif
lpInstL->fdwTblLoad = TBL_NOTLOADED;
return;
}
#endif // !defined(ROMANIME)