520 lines
15 KiB
C
520 lines
15 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)
|