Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

530 lines
17 KiB

/****************************************************************************
HANJA.CPP
Owner: cslim
Copyright (c) 1997-1999 Microsoft Corporation
Hanja conversion and dictionary lookup functions. Dictionary index is
stored as globally shared memory.
History:
26-APR-1999 cslim Modified for Multibox Applet Tooltip display
14-JUL-1999 cslim Copied from IME98 source tree
*****************************************************************************/
#include "private.h"
#include "common.h"
#include "lexheader.h"
#include "hanja.h"
#include "gdata.h"
#include "immsec.h"
#include "osver.h"
#include "debug.h"
// NT5 Globally shared memory.
const TCHAR IMEKR_SHAREDDATA_MUTEX[] = TEXT("{C5AFBBF9-8383-490c-AA9E-4FE93FA05512}");
const TCHAR IMEKR_LEX_HANGUL2HANJA[] = TEXT("ImeKrLexHangul2Hanja.SharedMemory");
const TCHAR IMEKR_LEX_HANJA2HANGUL[] = TEXT("ImeKrLexHanjaToHangul.SharedMemory");
// Initial and grow clump size of HANJA_CAND_STRING_LIST's pointers
#define HANJA_LIST_PWSZ_INITIAL_SIZE 512
#define HANJA_LIST_PWSZ_CLUMP_SIZE 256
UINT vuNumofK0=0, vuNumofK1=0;
WCHAR vwcHangul=0;
// Private data
static BOOL vfLexOpen = FALSE;
static HANDLE vhLex=0;
static HANDLE vhHangul2Hanja_IndexTbl=0;
static HANDLE vhHanja2Hangul_IndexTbl=0;
static DWORD viBufferStart=0; // seek point
static _DictHeader *vpLexHeader;
// Private functions
static BOOL OpenLex();
static INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl);
static INT SearchHanjaIndex(WCHAR wHChar, HanjaToHangulIndex *pLexIndexTbl);
BOOL EnsureHanjaLexLoaded()
{
HKEY hKey;
DWORD dwReadBytes;
CHAR szLexFileName[MAX_PATH], szLexPathExpanded[MAX_PATH];
DWORD dwCb, dwType;
if (vfLexOpen)
return TRUE;
// Get Lex file path
szLexFileName[0] = 0;
szLexPathExpanded[0] = 0;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szIMERootKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwCb = sizeof(szLexFileName);
dwType = REG_SZ;
if (RegQueryValueEx(hKey, g_szDictionary, NULL, &dwType, (LPBYTE)szLexFileName, &dwCb) == ERROR_SUCCESS)
ExpandEnvironmentStrings(szLexFileName, szLexPathExpanded, sizeof(szLexPathExpanded));
RegCloseKey(hKey);
}
Assert(szLexPathExpanded[0] != 0);
if (szLexPathExpanded[0] == 0)
return fFalse;
vhLex = CreateFile(szLexPathExpanded, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
if (vhLex==INVALID_HANDLE_VALUE)
{
Assert(0);
return FALSE;
}
vpLexHeader = new _DictHeader;
Assert(vpLexHeader);
if (!vpLexHeader)
return FALSE;
if (ReadFile(vhLex, vpLexHeader, sizeof(_DictHeader), &dwReadBytes, 0) == 0
|| (dwReadBytes != sizeof(_DictHeader)))
{
Assert(0);
return FALSE;
}
// Set member vars
//vuNumOfHangulEntry = pLexHeader->NumOfHangulEntry;
//vuNumOfHanjaEntry = pLexHeader->uiNumofHanja;
//viBufferStart = pLexHeader->iBufferStart;
if (vpLexHeader->Version < LEX_VERSION || vpLexHeader->Version > LEX_COMPATIBLE_VERSION_LIMIT )
{
delete vpLexHeader;
vpLexHeader = 0;
Assert(0);
return FALSE;
}
if (lstrcmpA(vpLexHeader->COPYRIGHT_HEADER, COPYRIGHT_STR))
{
delete vpLexHeader;
vpLexHeader = 0;
Assert(0);
return FALSE;
}
return OpenLex();
}
__inline BOOL DoEnterCriticalSection(HANDLE hMutex)
{
if(WAIT_FAILED==WaitForSingleObject(hMutex, 3000)) // Wait 3 seconds
return(FALSE);
return(TRUE);
}
BOOL OpenLex()
{
BOOL fRet = FALSE;
HANDLE hMutex;
DWORD dwReadBytes;
///////////////////////////////////////////////////////////////////////////
// Mapping Lex file
// The dictionary index is shared data between all IME instance
hMutex=CreateMutex(GetIMESecurityAttributes(), FALSE, IMEKR_SHAREDDATA_MUTEX);
if (hMutex != NULL)
{
if (DoEnterCriticalSection(hMutex) == FALSE)
goto ExitOpenLexCritSection;
vhHangul2Hanja_IndexTbl = OpenFileMapping(FILE_MAP_READ, TRUE, IMEKR_LEX_HANGUL2HANJA);
vhHanja2Hangul_IndexTbl = OpenFileMapping(FILE_MAP_READ, TRUE, IMEKR_LEX_HANJA2HANGUL);
if (vhHangul2Hanja_IndexTbl && vhHanja2Hangul_IndexTbl)
{
TraceMsg(TF_GENERAL, "CHanja::OpenLex() - File mapping already exists");
fRet = TRUE;
}
else
{
// if no file mapping exist
vhHangul2Hanja_IndexTbl = CreateFileMapping(INVALID_HANDLE_VALUE,
GetIMESecurityAttributes(),
PAGE_READWRITE,
0,
sizeof(_LexIndex)*(vpLexHeader->NumOfHangulEntry),
IMEKR_LEX_HANGUL2HANJA);
vhHanja2Hangul_IndexTbl = CreateFileMapping(INVALID_HANDLE_VALUE,
GetIMESecurityAttributes(),
PAGE_READWRITE,
0,
sizeof(HanjaToHangulIndex)*(vpLexHeader->uiNumofHanja),
IMEKR_LEX_HANJA2HANGUL);
if (vhHangul2Hanja_IndexTbl && vhHanja2Hangul_IndexTbl)
{
_LexIndex *pLexIndexTbl;
HanjaToHangulIndex* pHanjaToHangulIndex;
TraceMsg(TF_GENERAL, "CHanja::OpenLex() - File mapping Created");
// Copy Hangul to Hanja index
pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhHangul2Hanja_IndexTbl, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (!pLexIndexTbl)
goto ExitOpenLexCritSection;
// Read Index table
SetFilePointer(vhLex, vpLexHeader->Headersize, 0, FILE_BEGIN);
if (ReadFile(vhLex, pLexIndexTbl, vpLexHeader->NumOfHangulEntry*sizeof(_LexIndex), &dwReadBytes, 0) == 0
|| dwReadBytes != vpLexHeader->NumOfHangulEntry*sizeof(_LexIndex))
{
UnmapViewOfFile(pLexIndexTbl);
goto ExitOpenLexCritSection;
}
UnmapViewOfFile(pLexIndexTbl);
// Copy Hanja to Hangul index
pHanjaToHangulIndex = (HanjaToHangulIndex*)MapViewOfFile(vhHanja2Hangul_IndexTbl, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (!pHanjaToHangulIndex)
goto ExitOpenLexCritSection;
// Read Hanja to Hangul Index table
SetFilePointer(vhLex, vpLexHeader->iHanjaToHangulIndex, 0, FILE_BEGIN);
if (ReadFile(vhLex, pHanjaToHangulIndex, sizeof(HanjaToHangulIndex)*(vpLexHeader->uiNumofHanja), &dwReadBytes, 0) == 0
|| dwReadBytes != sizeof(HanjaToHangulIndex)*(vpLexHeader->uiNumofHanja))
{
UnmapViewOfFile(pLexIndexTbl);
goto ExitOpenLexCritSection;
}
UnmapViewOfFile(pHanjaToHangulIndex);
fRet = TRUE;
}
#ifdef DEBUG
else
Assert(0);
#endif
}
ExitOpenLexCritSection:
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
FreeIMESecurityAttributes();
vfLexOpen = fRet;
return fRet;
}
BOOL CloseLex()
{
//ClearHanjaSenseArray();
if (vhHangul2Hanja_IndexTbl)
{
CloseHandle(vhHangul2Hanja_IndexTbl);
vhHangul2Hanja_IndexTbl = 0;
}
if (vhHanja2Hangul_IndexTbl)
{
CloseHandle(vhHanja2Hangul_IndexTbl);
vhHanja2Hangul_IndexTbl = 0;
}
if (vhLex)
{
CloseHandle(vhLex);
vhLex = 0;
}
if (vpLexHeader)
{
delete vpLexHeader;
vpLexHeader = 0;
}
vfLexOpen = FALSE;
return TRUE;
}
/*---------------------------------------------------------------------------
fInitHanjaStringList
Allocate nested pointer of HANJA_CAND_STRING_LIST and initialize it.
------------------------------------------------------------------ CSLim -*/
BOOL fInitHanjaList(HANJA_CAND_STRING_LIST *pHanjaList, UINT uiNumofHanjaStr)
{
Assert(pHanjaList != NULL);
if ((pHanjaList->pwsz = (LPWSTR)cicMemAlloc(HANJA_LIST_PWSZ_INITIAL_SIZE*sizeof(WCHAR))) == 0)
return fFalse;
if ((pHanjaList->pHanjaString = (HANJA_CAND_STRING*)cicMemAlloc(
sizeof(HANJA_CAND_STRING)*uiNumofHanjaStr)) == 0)
{
cicMemFree(pHanjaList->pwsz);
return fFalse;
}
pHanjaList->cchMac = 0; // Current chars used in pwsz (incl all trailing nulls)
pHanjaList->cchAlloc = HANJA_LIST_PWSZ_INITIAL_SIZE; // WCHAR size
pHanjaList->csz = 0;
pHanjaList->cszAlloc = uiNumofHanjaStr;
return fTrue;
}
/*---------------------------------------------------------------------------
fGrowHanjaList
Reallocate nested pointer of HANJA_CAND_STRING_LIST after increasing the size
------------------------------------------------------------------ CSLim -*/
BOOL fGrowHanjaList(HANJA_CAND_STRING_LIST *pHanjaList)
{
LPWSTR pwsz;
TBOOL(pHanjaList != NULL);
pwsz = (LPWSTR)cicMemReAlloc(pHanjaList->pwsz,
(pHanjaList->cchAlloc+HANJA_LIST_PWSZ_CLUMP_SIZE)*sizeof(WCHAR));
if (pwsz == NULL)
return fFalse;
if (pHanjaList->pwsz != pwsz)
{
INT_PTR offset = pwsz - pHanjaList->pwsz;
for (UINT i=0; i<pHanjaList->csz; i++)
pHanjaList->pHanjaString[i].wzMeaning += offset;
}
pHanjaList->pwsz = pwsz;
pHanjaList->cchAlloc += HANJA_LIST_PWSZ_CLUMP_SIZE;
return fTrue;
}
BOOL GetMeaningAndProunc(WCHAR wch, LPWSTR lpwstrTip, INT cchMax)
{
HanjaToHangulIndex* pHanjaToHangulIndex;
INT iMapHanjaInfo;
WCHAR wcHanja = 0;
BYTE cchMeaning = 0;
WCHAR wszMeaning[MAX_SENSE_LENGTH+1];
DWORD dwReadBytes;
BOOL fRet = FALSE;
TraceMsg(TF_GENERAL, "GetMeaningAndProunc");
if (!EnsureHanjaLexLoaded())
return FALSE;
pHanjaToHangulIndex = (HanjaToHangulIndex*)MapViewOfFile(vhHanja2Hangul_IndexTbl, FILE_MAP_READ, 0, 0, 0);
if (!pHanjaToHangulIndex)
{
Assert(0);
return FALSE;
}
// Search index
if ((iMapHanjaInfo = SearchHanjaIndex(wch, pHanjaToHangulIndex)) >= 0)
{
// Seek to mapping Hanja
SetFilePointer(vhLex, vpLexHeader->iBufferStart + pHanjaToHangulIndex[iMapHanjaInfo].iOffset, 0, FILE_BEGIN);
// Read Hanja Info
if (ReadFile(vhLex, &wcHanja, sizeof(WCHAR), &dwReadBytes, 0) == 0)
goto LError;
Assert(wch == wcHanja);
if (ReadFile(vhLex, &cchMeaning, sizeof(BYTE), &dwReadBytes, 0) == 0)
goto LError;
if (wcHanja && (cchMeaning < MAX_SENSE_LENGTH*sizeof(WCHAR)))
{
if (cchMeaning)
{
if (ReadFile(vhLex, wszMeaning, cchMeaning, &dwReadBytes, 0) == 0)
goto LError;
}
wszMeaning[cchMeaning>>1] = L'\0';
wsprintfW(lpwstrTip, L"%s %c\nU+%04X", wszMeaning, pHanjaToHangulIndex[iMapHanjaInfo].wchHangul, wch);
fRet = TRUE;
}
else
fRet = FALSE;
}
LError:
UnmapViewOfFile(pHanjaToHangulIndex);
return fRet;
}
// For ImeConversionList.
BOOL GetConversionList(WCHAR wcReading, HANJA_CAND_STRING_LIST *pCandList)
{
_LexIndex *pLexIndexTbl = NULL;
INT iMapCandStr;
UINT uNumOfCandStr;
DWORD cwch, readBytes;
BYTE senseLen;
WCHAR szSense[MAX_SENSE_LENGTH] = L"";
CIMEData ImeData;
BOOL fRet = fFalse;
// Chcek validity of params
Assert(wcReading != 0);
Assert(pCandList != NULL);
if (pCandList == NULL)
goto ConversionExit1;
if (!EnsureHanjaLexLoaded())
return (0L);
pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhHangul2Hanja_IndexTbl, FILE_MAP_READ, 0, 0, 0);
if (!pLexIndexTbl)
{
Assert(0);
return (0L);
}
cwch = 0;
if ((iMapCandStr = SearchHanjaIndex(wcReading, pLexIndexTbl)) < 0)
goto ConversionExit1;
else
{
vuNumofK0 = pLexIndexTbl[iMapCandStr].wNumOfK0;
if (ImeData->fKSC5657Hanja && !IsOn95())
vuNumofK1 = pLexIndexTbl[iMapCandStr].wNumOfK1;
else
vuNumofK1 = 0;
uNumOfCandStr = vuNumofK0 + vuNumofK1;
if (uNumOfCandStr == 0) // if no Hanja found
goto ConversionExit1;
if (!fInitHanjaList(pCandList, uNumOfCandStr))
goto ConversionExit1;
//cwch = uNumOfCandStr*2; // including NULL
//
SetFilePointer(vhLex, vpLexHeader->iBufferStart + pLexIndexTbl[iMapCandStr].iOffset, 0, FILE_BEGIN);
for (UINT i = 0; i < uNumOfCandStr; i++)
{
WCHAR wchHanja;
if (ReadFile(vhLex, &wchHanja, sizeof(WCHAR), &readBytes, 0) == 0)
goto ConversionExit1;
//*lpwchCand++ = wchHanja;
//*lpwchCand++ = L'\0';
// Skip meaning
if (ReadFile(vhLex, &senseLen, sizeof(BYTE), &readBytes, 0) == 0)
goto ConversionExit1;
if (senseLen && senseLen < MAX_SENSE_LENGTH*sizeof(WCHAR))
{
if (ReadFile(vhLex, szSense, senseLen, &readBytes, 0) == 0)
goto ConversionExit1;
szSense[senseLen/2] = L' ';
szSense[senseLen/2 + 1] = wcReading;
szSense[senseLen/2 + 2] = L'\0';
senseLen += 2*sizeof(WCHAR);
}
///////////////////////////////////////////////////////////////////
// Fill Hanja String List struct
// Grow memory if neccessary
if (pCandList->cchAlloc <= pCandList->cchMac + (senseLen/2))
{
TraceMsg(TF_GENERAL, "Try to grow pCandList");
if (fGrowHanjaList(pCandList) == fFalse)
{
Assert(0);
goto ConversionExit1;
}
}
pCandList->pHanjaString[pCandList->csz].wchHanja = wchHanja;
if (i < vuNumofK0)
pCandList->pHanjaString[pCandList->csz].bHanjaCat = HANJA_K0;
else
pCandList->pHanjaString[pCandList->csz].bHanjaCat = HANJA_K1;
if (senseLen)
{
pCandList->pHanjaString[pCandList->csz].wzMeaning = pCandList->pwsz + pCandList->cchMac;
wcscpy(pCandList->pwsz + pCandList->cchMac, szSense);
}
else
pCandList->pHanjaString[pCandList->csz].wzMeaning = L"";
pCandList->csz++;
pCandList->cchMac += (senseLen/2)+1;
}
fRet = fTrue;
}
ConversionExit1:
UnmapViewOfFile(pLexIndexTbl);
return fRet;
}
INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl)
{
int iHead = 0, iTail = vpLexHeader->NumOfHangulEntry-1, iMid;
while (iHead <= iTail)
{
iMid = (iHead + iTail) >> 1;
if (pLexIndexTbl[iMid].wcHangul > wHChar)
iTail = iMid - 1;
else
if (pLexIndexTbl[iMid].wcHangul < wHChar)
iHead = iMid + 1;
else
return (iMid);
}
return (-1);
}
INT SearchHanjaIndex(WCHAR wHChar, HanjaToHangulIndex *pLexIndexTbl)
{
int iHead = 0, iTail = vpLexHeader->uiNumofHanja-1, iMid;
while (iHead <= iTail)
{
iMid = (iHead + iTail) >> 1;
TraceMsg(TF_GENERAL, "SearchHanjaIndex iMid=%d, pLexIndexTbl[iMid].wchHanja = 0x%04X", iMid, pLexIndexTbl[iMid].wchHanja);
if (pLexIndexTbl[iMid].wchHanja > wHChar)
iTail = iMid - 1;
else
if (pLexIndexTbl[iMid].wchHanja < wHChar)
iHead = iMid + 1;
else
return (iMid);
}
return (-1);
}