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.
 
 
 
 
 
 

439 lines
14 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:
14-JUL-1999 cslim Copied from IME98 source tree
*****************************************************************************/
#include "precomp.h"
#include "apientry.h"
#include "ui.h"
#include "debug.h"
#include "lexheader.h"
#include "hanja.h"
#include "immsec.h"
#include "winex.h"
#include "common.h"
#include <WINERROR.H>
// NT5 Globally shared memory.
const TCHAR IMEKR_LEX_SHAREDDATA_MUTEX_NAME[] = TEXT("{C5AFBBF9-8383-490c-AA9E-4FE93FA05512}");
const TCHAR IMEKR_LEX_SHAREDDATA_NAME[] = TEXT("ImeKrLexHangul2Hanja.SharedMemory");
UINT vuNumofK0=0, vuNumofK1=0;
WCHAR vwcHangul=0;
// Private data
PRIVATE BOOL vfLexOpen = fFalse;
PRIVATE HANDLE vhLex=0;
PRIVATE HANDLE vhLexIndexTbl=0;
PRIVATE UINT vuNumOfHangulEntry=0;
PRIVATE DWORD viBufferStart=0; // seek point
// Private functions
PRIVATE BOOL OpenLex();
//static VOID ClearHanjaSenseArray();
PRIVATE INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl);
/*
CHanja::CHanja()
{
vfLexOpen = fFalse;
vhLex = vhLexIndexTbl = vhLexIndexTbl = NULL;
vuNumOfHangulEntry = 0;
for (int i=0; i<MAX_CANDSTR; i++)
vprwszHanjaMeaning[i] = 0;
}
*/
BOOL EnsureHanjaLexLoaded()
{
_DictHeader *pLexHeader;
DWORD dwReadBytes;
CHAR szLexFileName[MAX_PATH], szLexPathExpanded[MAX_PATH];
HKEY hKey;
DWORD dwType, dwCb;
CIMEData ImeData;
if (vfLexOpen)
return fTrue;
// Get Lex file name with full 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);
}
DbgAssert(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)
{
DbgAssert(0);
return fFalse;
}
pLexHeader = new _DictHeader;
if (!pLexHeader)
return fFalse;
if (ReadFile(vhLex, pLexHeader, sizeof(_DictHeader), &dwReadBytes, 0) == 0 || (dwReadBytes != sizeof(_DictHeader)))
{
DbgAssert(0);
return fFalse;
}
// Set member vars
vuNumOfHangulEntry = pLexHeader->NumOfHangulEntry;
viBufferStart = pLexHeader->iBufferStart;
if (pLexHeader->Version < LEX_VERSION || pLexHeader->Version > LEX_COMPATIBLE_VERSION_LIMIT )
{
delete pLexHeader;
return fFalse;
}
if (lstrcmpA(pLexHeader->COPYRIGHT_HEADER, COPYRIGHT_STR))
{
delete pLexHeader;
return fFalse;
}
// Read Index table
SetFilePointer(vhLex, pLexHeader->Headersize, 0, FILE_BEGIN);
delete pLexHeader;
return OpenLex();
}
BOOL OpenLex()
{
BOOL fRet = fFalse;
_LexIndex *pLexIndexTbl;
HANDLE hMutex;
DWORD dwReadBytes;
///////////////////////////////////////////////////////////////////////////
// Mapping Lex file
// The dictionary index is shared data between all IME instance
hMutex=CreateMutex(GetIMESecurityAttributes(), fFalse, IMEKR_LEX_SHAREDDATA_MUTEX_NAME);
if (hMutex != NULL)
{
if (DoEnterCriticalSection(hMutex) == fFalse)
goto ExitOpenLexCritSection;
vhLexIndexTbl = OpenFileMapping(FILE_MAP_READ, fTrue, IMEKR_LEX_SHAREDDATA_NAME);
if(vhLexIndexTbl)
{
Dbg(DBGID_Hanja|DBGID_Mem, TEXT("CHanja::OpenLex() - File mapping already exists"));
fRet = fTrue;
}
else
{
// if no file mapping exist
vhLexIndexTbl = CreateFileMapping(INVALID_HANDLE_VALUE, GetIMESecurityAttributes(), PAGE_READWRITE,
0, sizeof(_LexIndex)*(vuNumOfHangulEntry),
IMEKR_LEX_SHAREDDATA_NAME);
if (vhLexIndexTbl)
{
Dbg(DBGID_Hanja|DBGID_Mem, TEXT("CHanja::OpenLex() - File mapping Created"));
pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhLexIndexTbl, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (!pLexIndexTbl)
goto ExitOpenLexCritSection;
if (ReadFile(vhLex, pLexIndexTbl, vuNumOfHangulEntry*sizeof(_LexIndex), &dwReadBytes, 0) != 0 &&
dwReadBytes == vuNumOfHangulEntry*sizeof(_LexIndex))
{
fRet = fTrue;
}
else
{
fRet = fFalse;
}
UnmapViewOfFile(pLexIndexTbl);
}
#ifdef _DEBUG
else
DbgAssert(0);
#endif
}
ExitOpenLexCritSection:
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
FreeIMESecurityAttributes();
vfLexOpen = fRet;
return fRet;
}
BOOL CloseLex()
{
//ClearHanjaSenseArray();
if (vhLexIndexTbl)
{
CloseHandle(vhLexIndexTbl);
vhLexIndexTbl = 0;
}
if (vhLex)
{
CloseHandle(vhLex);
vhLex = 0;
}
vfLexOpen = fFalse;
return fTrue;
}
///////////////////////////////////////////////////////////////////////////////
BOOL GenerateHanjaCandList(PCIMECtx pImeCtx, WCHAR wcHangul)
{
WCHAR wcCandChar;
INT iMapCandStr;
UINT uNumOfCandStr;
_LexIndex *pLexIndexTbl;
WCHAR wszMeaning[MAX_SENSE_LENGTH+1];
BYTE cchMeaning = 0;
DWORD dwReadBytes;
BOOL fRet = fFalse;
Dbg(DBGID_Hanja, "GenerateHanjaCandList");
if (!EnsureHanjaLexLoaded())
{
MessageBeep(MB_ICONEXCLAMATION);
return fFalse;
}
// Get Current composition char
if (wcHangul == 0)
wcHangul = pImeCtx->GetCompBufStr();
if (wcHangul == 0)
return fFalse;
pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhLexIndexTbl, FILE_MAP_READ, 0, 0, 0);
if (!pLexIndexTbl)
{
Dbg(DBGID_Hanja, TEXT("pLexIndexTbl==0"));
DbgAssert(0);
return fFalse;
}
if ((iMapCandStr = SearchHanjaIndex(wcHangul, pLexIndexTbl)) < 0)
MessageBeep(MB_ICONEXCLAMATION);
else
{
// Set member vars
vwcHangul = wcHangul;
vuNumofK0 = pLexIndexTbl[iMapCandStr].wNumOfK0;
// Is K1 Hanja enabled?
if (pImeCtx->GetGData() && pImeCtx->GetGData()->GetKSC5657Hanja() && (vpInstData->f16BitApps == fFalse) && !IsWin95())
vuNumofK1 = pLexIndexTbl[iMapCandStr].wNumOfK1;
else
vuNumofK1 = 0;
uNumOfCandStr = vuNumofK0 + vuNumofK1;
if (uNumOfCandStr == 0)
goto GenerateHanjaCandListExit;
Dbg(DBGID_Hanja, "Hangul = 0x%04X, K0=%d, K1=%d, iMapCandStr=%d", vwcHangul, vuNumofK0, vuNumofK1, iMapCandStr);
// Seek to mapping Hanja
SetFilePointer(vhLex, viBufferStart + pLexIndexTbl[iMapCandStr].iOffset, 0, FILE_BEGIN);
// Read all candidates
for (UINT i = 0; i < uNumOfCandStr; i++)
{
if (ReadFile(vhLex, &wcCandChar, sizeof(WCHAR), &dwReadBytes, 0) == 0)
goto GenerateHanjaCandListExit;
if (ReadFile(vhLex, &cchMeaning, sizeof(BYTE), &dwReadBytes, 0) == 0)
goto GenerateHanjaCandListExit;
if (wcCandChar && (cchMeaning < MAX_SENSE_LENGTH*sizeof(WCHAR)))
{
if (cchMeaning)
{
if (ReadFile(vhLex, wszMeaning, cchMeaning, &dwReadBytes, 0) == 0)
goto GenerateHanjaCandListExit;
}
wszMeaning[cchMeaning>>1] = L'\0';
Dbg(DBGID_Hanja, "Read Cand[%d], Hanja=0x%04X", i, wcCandChar);
pImeCtx->AppendCandidateStr(wcCandChar, wszMeaning);
}
}
pImeCtx->StoreCandidate();
fRet = fTrue;
}
GenerateHanjaCandListExit:
UnmapViewOfFile(pLexIndexTbl);
return fRet;
}
// For ImeConversionList.
DWORD GetConversionList(WCHAR wcReading, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
{
_LexIndex *pLexIndexTbl;
INT iMaxCand;
INT i, iMapCandStr;
UINT uNumOfCandStr;
DWORD dwSize, readBytes, dwStartOfCandStr;
BYTE senseLen;
WCHAR szSense[MAX_SENSE_LENGTH];
CIMEData ImeData;
if (!EnsureHanjaLexLoaded())
return (0L);
// Calculate possible maximum candidates dwBufLen can contain.
if (dwBufLen)
{
iMaxCand = dwBufLen - sizeof(CANDIDATELIST) + sizeof(DWORD); // Minus header info.(unvariable part)
iMaxCand = iMaxCand / (sizeof(DWORD) + (sizeof(WCHAR)*2)); // DWORD: offset, WCHAR*2: 1 Character + null
}
else
iMaxCand = 0;
pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhLexIndexTbl, FILE_MAP_READ, 0, 0, 0);
if (!pLexIndexTbl)
{
DbgAssert(0);
return (0L);
}
dwSize = 0;
if ((iMapCandStr = SearchHanjaIndex(wcReading, pLexIndexTbl)) < 0)
goto ConversionExit1;
else
{
vuNumofK0 = pLexIndexTbl[iMapCandStr].wNumOfK0;
if (ImeData->fKSC5657Hanja && (vpInstData->f16BitApps == fFalse) && !IsWin95())
vuNumofK1 = pLexIndexTbl[iMapCandStr].wNumOfK1;
else
vuNumofK1 = 0;
uNumOfCandStr = vuNumofK0 + vuNumofK1;
if (uNumOfCandStr == 0) // if no Hanja found
goto ConversionExit1;
dwSize = sizeof(CANDIDATELIST) + uNumOfCandStr*sizeof(DWORD)
+ uNumOfCandStr * sizeof(WCHAR) * 2;
// return required buffer size
if (dwBufLen == NULL)
goto ConversionExit1;
lpCandList->dwSize = dwSize;
lpCandList->dwStyle = IME_CAND_READ;
lpCandList->dwCount = uNumOfCandStr;
lpCandList->dwPageStart = lpCandList->dwSelection = 0;
lpCandList->dwPageSize = CAND_PAGE_SIZE;
//
SetFilePointer(vhLex, viBufferStart + pLexIndexTbl[iMapCandStr].iOffset, 0, FILE_BEGIN);
dwStartOfCandStr = sizeof(CANDIDATELIST)
+ sizeof(DWORD) * uNumOfCandStr; // for dwOffset array
for (i = 0; (i < (INT)uNumOfCandStr) && (i < iMaxCand); i++)
{
WCHAR wchHanja;
LPWSTR lpwchCand;
LPSTR lpchCand;
CHAR szCand[4] = ""; // one DBCS + one Null + one extra
lpCandList->dwOffset[i] = dwStartOfCandStr + (i<<2);
if (ReadFile(vhLex, &wchHanja, sizeof(WCHAR), &readBytes, 0) == 0)
goto ConversionExit1;
// if Unicode environment
if (vfUnicode)
{
lpwchCand = (LPWSTR)((LPSTR)lpCandList + lpCandList->dwOffset[i]);
*lpwchCand++ = wchHanja;
*lpwchCand = L'\0';
}
else
{
// Convert to ANSI
WideCharToMultiByte(CP_KOREA, 0,
&wchHanja, 1, (LPSTR)szCand, sizeof(szCand),
NULL, NULL);
lpchCand = (LPSTR)((LPSTR)lpCandList + lpCandList->dwOffset[i]);
*lpchCand++ = szCand[0];
*lpchCand++ = szCand[1];
*lpchCand = '\0';
}
// Skip meaning
if (ReadFile(vhLex, &senseLen, sizeof(BYTE), &readBytes, 0) == 0)
goto ConversionExit1;
if (senseLen < MAX_SENSE_LENGTH)
{
if (ReadFile(vhLex, szSense, senseLen, &readBytes, 0) == 0)
goto ConversionExit1;
}
}
}
// if buffer size too small to copy all conversion list info
if (i == iMaxCand && i < (INT)uNumOfCandStr)
{
lpCandList->dwSize = dwSize = (sizeof(CANDIDATELIST) - sizeof(DWORD))+ i*sizeof(DWORD) + i*sizeof(WCHAR)*2;
lpCandList->dwCount = (UINT)i;
}
ConversionExit1:
UnmapViewOfFile(pLexIndexTbl);
return (dwSize);
}
INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl)
{
int iHead = 0, iTail = vuNumOfHangulEntry-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);
}