windows-nt/Source/XPSP1/NT/inetsrv/intlwb/cht2/srcs/lexmgr.cpp
2020-09-26 16:20:57 +08:00

622 lines
22 KiB
C++

#include <windows.h>
#include "lexicon.h"
#include "lexmgr.h"
#include "PropNoun.h"
#include <stdio.h>
#include <imm.h>
#include <stdio.h>
CCHTLexicon::CCHTLexicon()
{
m_psLexiconHeader = NULL;
m_pbLexiconBase = NULL;
#ifdef CHINESE_PROP_NAME
m_pcPropName = NULL;
#endif
m_sAddInLexicon.dwMaxWordNumber = 0;
m_sAddInLexicon.dwWordNumber = 0;
m_sAddInLexicon.psWordData = NULL;
FillMemory(m_sAddInLexicon.wWordBeginIndex,
sizeof(m_sAddInLexicon.wWordBeginIndex), 0);
}
CCHTLexicon::~CCHTLexicon()
{
DWORD i;
// Do not build one char word signature
if (m_psLexiconHeader) {
for (i = 0 ; i < m_psLexiconHeader->dwMaxCharPerWord; ++i) {
if (m_sWordInfo[i].pbFirstCharSignature) {
delete m_sWordInfo[i].pbFirstCharSignature;
}
if (m_sWordInfo[i].pbLastCharSignature) {
delete m_sWordInfo[i].pbLastCharSignature;
}
}
}
#ifdef CHINESE_PROP_NAME
if (m_pcPropName) {
delete m_pcPropName;
}
#endif
// Free add in lexicon
if (m_sAddInLexicon.psWordData) {
for (i = 0; i < m_sAddInLexicon.dwWordNumber; ++i) {
delete m_sAddInLexicon.psWordData[i].lpwszWordStr;
m_sAddInLexicon.psWordData[i].lpwszWordStr = NULL;
}
delete m_sAddInLexicon.psWordData;
m_sAddInLexicon.psWordData = NULL;
}
m_sAddInLexicon.dwMaxWordNumber = 0;
m_sAddInLexicon.dwWordNumber = 0;
}
BOOL CCHTLexicon::InitData(
HINSTANCE hInstance)
{
HRSRC hResInfo;
HGLOBAL hResData;
BOOL fRet = FALSE;
TCHAR tszLexiconResName[MAX_PATH];
DWORD i;
// Init main lexicon
lstrcpy(tszLexiconResName, TEXT("LEXICON"));
if (!(hResInfo = FindResource(hInstance, tszLexiconResName, TEXT("BIN")))) {
} else if (!(hResData = LoadResource(hInstance, hResInfo))) {
} else if (!(m_pbLexiconBase = (LPBYTE)LockResource(hResData))) {
} else {
m_psLexiconHeader = (PSLexFileHeader)m_pbLexiconBase;
for (i = 0 ; i < m_psLexiconHeader->dwMaxCharPerWord; ++i) {
m_sWordInfo[i].lpwWordString = (LPWSTR)(m_pbLexiconBase +
m_psLexiconHeader->sLexInfo[i].dwWordStringOffset);
m_sWordInfo[i].pbAttribute = (LPBYTE)(m_pbLexiconBase +
m_psLexiconHeader->sLexInfo[i].dwWordAttribOffset);
m_sWordInfo[i].pwUnicount = (PWORD)(m_pbLexiconBase +
m_psLexiconHeader->sLexInfo[i].dwWordCountOffset);
m_sWordInfo[i].pbTerminalCode = (LPBYTE)(m_pbLexiconBase +
m_psLexiconHeader->sLexInfo[i].dwTerminalCodeOffset);
}
BuildSignatureData();
fRet = TRUE;
}
// Init alt lexicon
lstrcpy(tszLexiconResName, TEXT("ALTWORD"));
if (!(hResInfo = FindResource(hInstance, tszLexiconResName, TEXT("BIN")))) {
} else if (!(hResData = LoadResource(hInstance, hResInfo))) {
} else if (!(m_pbAltWordBase = (LPBYTE)LockResource(hResData))) {
} else {
m_psAltWordHeader = (PSAltLexFileHeader)m_pbAltWordBase;
for (i = 0 ; i < m_psAltWordHeader->dwMaxCharPerWord; ++i) {
m_sAltWordInfo[i].lpwWordString = (LPWSTR)(m_pbAltWordBase +
m_psAltWordHeader->sAltWordInfo[i].dwWordStringOffset);
m_sAltWordInfo[i].pdwGroupID = (PDWORD)(m_pbAltWordBase +
m_psAltWordHeader->sAltWordInfo[i].dwWordGroupOffset);
}
fRet = TRUE;
}
#ifdef CHINESE_PROP_NAME
m_pcPropName = new CProperNoun(hInstance);
if (m_pcPropName) {
m_pcPropName->InitData();
}
#endif
#ifdef _DEBUG
FILE *fp;
DWORD j;
WCHAR wUnicodeString[MAX_CHAR_PER_WORD + 1];
CHAR cANSIString[MAX_CHAR_PER_WORD * 2 + 1];
WORD wCount;
fp = fopen("DM.dmp", "wt");
for (i = 0 ; i < m_psLexiconHeader->dwMaxCharPerWord; ++i) {
for (j = 0; j < m_psLexiconHeader->sLexInfo[i].dwWordNumber; ++j) {
if (m_sWordInfo[i].pbAttribute[j] & ATTR_DM) {
wCount = m_sWordInfo[i].pwUnicount[j];
if (i == 0) {
wUnicodeString[0] = (WORD)(CHT_UNICODE_BEGIN + j);
} else {
CopyMemory(wUnicodeString, &(m_sWordInfo[i].lpwWordString[j * (i + 1)]),
sizeof(WCHAR) * (i + 1));
}
wUnicodeString[i + 1] = '\0';
WideCharToMultiByte(950, WC_COMPOSITECHECK, wUnicodeString, i + 1 + 1,
cANSIString, sizeof(cANSIString), NULL, NULL);
fprintf(fp, "%s %d\n", cANSIString, wCount);
}
}
}
fclose(fp);
fp = fopen("COMPOUND.dmp", "wt");
for (i = 0 ; i < m_psLexiconHeader->dwMaxCharPerWord; ++i) {
for (j = 0; j < m_psLexiconHeader->sLexInfo[i].dwWordNumber; ++j) {
if (m_sWordInfo[i].pbAttribute[j] & ATTR_COMPOUND) {
wCount = m_sWordInfo[i].pwUnicount[j];
if (i == 0) {
wUnicodeString[0] = (WORD)(CHT_UNICODE_BEGIN + j);
} else {
CopyMemory(wUnicodeString, &(m_sWordInfo[i].lpwWordString[j * (i + 1)]),
sizeof(WCHAR) * (i + 1));
}
wUnicodeString[i + 1] = '\0';
WideCharToMultiByte(950, WC_COMPOSITECHECK, wUnicodeString, i + 1 + 1,
cANSIString, sizeof(cANSIString), NULL, NULL);
fprintf(fp, "%s %d\n", cANSIString, wCount);
}
}
}
fclose(fp);
#endif
// Init EUDP to special word
LoadEUDP();
return fRet;
}
void CCHTLexicon::BuildSignatureData(void)
{
DWORD i, j, dwWordNumber;
WORD wFirstChar, wLastChar;
for (i = 0; i < MAX_CHAR_PER_WORD; ++i) {
m_sWordInfo[i].pbFirstCharSignature = NULL;
m_sWordInfo[i].pbLastCharSignature = NULL;
}
// Do not build one char word signature
for (i = 0 ; i < m_psLexiconHeader->dwMaxCharPerWord; ++i) {
dwWordNumber = m_psLexiconHeader->sLexInfo[i].dwWordNumber;
if (i != 0 && dwWordNumber > WORD_NUM_TO_BUILD_SIGNATURE) {
m_sWordInfo[i].pbFirstCharSignature = new BYTE[(CHT_UNICODE_END - CHT_UNICODE_BEGIN + 1) / 8 + 1];
if (NULL == m_sWordInfo[i].pbFirstCharSignature) { continue; }
FillMemory(m_sWordInfo[i].pbFirstCharSignature, (CHT_UNICODE_END - CHT_UNICODE_BEGIN + 1) / 8, 0);
for (j = 0; j < dwWordNumber; ++j) {
wFirstChar = m_sWordInfo[i].lpwWordString[(i + 1) * j];
if (wFirstChar >= CHT_UNICODE_BEGIN) {
m_sWordInfo[i].pbFirstCharSignature[(wFirstChar - CHT_UNICODE_BEGIN) / 8] |=
(0x00000001 << ((wFirstChar - CHT_UNICODE_BEGIN) % 8));
}
}
m_sWordInfo[i].pbLastCharSignature = new BYTE[(CHT_UNICODE_END - CHT_UNICODE_BEGIN + 1) / 8 + 1];
if (NULL == m_sWordInfo[i].pbLastCharSignature) { continue; }
FillMemory(m_sWordInfo[i].pbLastCharSignature, (CHT_UNICODE_END - CHT_UNICODE_BEGIN + 1) / 8, 0);
for (j = 0; j < dwWordNumber; ++j) {
wLastChar = m_sWordInfo[i].lpwWordString[(i + 1) * (j + 1) - 1];
if (wLastChar >= CHT_UNICODE_BEGIN) {
m_sWordInfo[i].pbLastCharSignature[(wLastChar - CHT_UNICODE_BEGIN) / 8] |=
(0x00000001 << ((wLastChar - CHT_UNICODE_BEGIN) % 8));
}
}
} else {
m_sWordInfo[i].pbFirstCharSignature = NULL;
m_sWordInfo[i].pbLastCharSignature = NULL;
}
}
}
BOOL CCHTLexicon::GetWordInfo(
LPCWSTR lpcwString,
DWORD dwLength,
PWORD pwUnicount,
PWORD pwAttrib,
PBYTE pbTerminalCode)
{
BOOL fRet;
BYTE bMainLexAttrib;
fRet = GetMainLexiconWordInfo(lpcwString, dwLength, pwUnicount,
&bMainLexAttrib, pbTerminalCode);
*pwAttrib = bMainLexAttrib;
if (fRet) { goto _exit; }
#ifdef CHINESE_PROP_NAME
if (dwLength == 3) {
if (m_pcPropName->IsAChineseName(lpcwString, dwLength)) {
*pbTerminalCode = ' ';
*pwAttrib = ATTR_RULE_WORD;
*pwUnicount = 100;
fRet = TRUE;
goto _exit;
}
}
#endif
fRet = GetAddInWordInfo(lpcwString, dwLength, pwUnicount,
pwAttrib, pbTerminalCode);
_exit:
return fRet;
}
BOOL CCHTLexicon::GetMainLexiconWordInfo(
LPCWSTR lpcwString,
DWORD dwLength,
PWORD pwUnicount,
PBYTE pbAttrib,
PBYTE pbTerminalCode)
{
INT nBegin, nEnd, nMid;
INT nCmp;
BOOL fRet = FALSE;
LPWSTR lpwLexString;
DWORD dwFirstCharIndex, dwLastCharIndex;
if (dwLength > m_psLexiconHeader->dwMaxCharPerWord) { goto _exit; }
if (lpcwString[0] < CHT_UNICODE_BEGIN || lpcwString[0] > CHT_UNICODE_END) {
goto _exit;
}
dwFirstCharIndex = lpcwString[0] - CHT_UNICODE_BEGIN;
if (dwLength == 1) {
*pwUnicount = m_sWordInfo[dwLength - 1].pwUnicount[dwFirstCharIndex];
*pbAttrib = m_sWordInfo[dwLength - 1].pbAttribute[dwFirstCharIndex];
*pbTerminalCode = m_sWordInfo[dwLength - 1].pbTerminalCode[dwFirstCharIndex];
fRet = TRUE;
} else {
// Check signature first
if (m_sWordInfo[dwLength - 1].pbFirstCharSignature) {
if (!(m_sWordInfo[dwLength - 1].pbFirstCharSignature[dwFirstCharIndex / 8] &
(0x00000001 << (dwFirstCharIndex % 8)))) { goto _exit; }
}
if (lpcwString[dwLength - 1] >= CHT_UNICODE_BEGIN && lpcwString[dwLength - 1] <= CHT_UNICODE_END) {
if (m_sWordInfo[dwLength - 1].pbLastCharSignature) {
dwLastCharIndex = lpcwString[dwLength - 1] - CHT_UNICODE_BEGIN;
if (!(m_sWordInfo[dwLength - 1].pbLastCharSignature[dwLastCharIndex / 8] &
(0x00000001 << (dwLastCharIndex % 8)))) { goto _exit; }
}
}
nBegin = 0;
nEnd = m_psLexiconHeader->sLexInfo[dwLength - 1].dwWordNumber - 1;
lpwLexString = m_sWordInfo[dwLength - 1].lpwWordString;
DWORD dwCompByteNum = sizeof(WCHAR) * dwLength;
while (nBegin <= nEnd) {
nMid = (nBegin + nEnd) / 2;
nCmp = memcmp(&(lpwLexString[nMid * dwLength]), lpcwString, dwCompByteNum);
if (nCmp > 0) {
nEnd = nMid - 1;
} else if (nCmp < 0) {
nBegin = nMid + 1;
} else {
*pwUnicount = m_sWordInfo[dwLength - 1].pwUnicount[nMid];
*pbAttrib = m_sWordInfo[dwLength - 1].pbAttribute[nMid];
*pbTerminalCode = m_sWordInfo[dwLength - 1].pbTerminalCode[nMid];
fRet = TRUE;
break;
}
}
}
_exit:
if (!fRet) {
*pwUnicount = 0;
*pbAttrib = 0;
*pbTerminalCode = ' ';
}
return fRet;
}
// Load EUDP
int CALLBACK EUDPCountA(
LPCSTR lpcszReading,
DWORD dwStyle,
LPCSTR lpcszString,
LPVOID lpvData)
{
PSAddInLexicon psAddInLexicon;
if (lstrlenA(lpcszString) / sizeof(WCHAR) <= MAX_CHAR_PER_WORD) {
psAddInLexicon = (PSAddInLexicon)lpvData;
++psAddInLexicon->dwWordNumber;
}
return 1;
}
int CALLBACK EUDPCountW(
LPCWSTR lpcwszReading,
DWORD dwStyle,
LPCWSTR lpcwszString,
LPVOID lpvData)
{
PSAddInLexicon psAddInLexicon;
if (lstrlenW(lpcwszString) <= MAX_CHAR_PER_WORD) {
psAddInLexicon = (PSAddInLexicon)lpvData;
++psAddInLexicon->dwWordNumber;
}
return 1;
}
int CALLBACK EUDPLoadA(
LPCSTR lpcszReading,
DWORD dwStyle,
LPCSTR lpcszString,
LPVOID lpvData)
{
PSAddInLexicon psAddInLexicon;
WORD wStrLen;
wStrLen = (WORD)lstrlenA(lpcszString);
if (wStrLen / sizeof(WCHAR) <= MAX_CHAR_PER_WORD) {
psAddInLexicon = (PSAddInLexicon)lpvData;
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].lpwszWordStr =
new WORD[wStrLen / sizeof(WCHAR) + 1]; // zero end
MultiByteToWideChar(950, MB_PRECOMPOSED, lpcszString, wStrLen + 1,
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].lpwszWordStr,
wStrLen / sizeof(WCHAR) + 1);
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].wAttrib = ATTR_EUDP_WORD;
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].wLen = wStrLen / sizeof(WCHAR);
++psAddInLexicon->dwWordNumber;
}
return 1;
}
int CALLBACK EUDPLoadW(
LPCWSTR lpcwszReading,
DWORD dwStyle,
LPCWSTR lpcwszString,
LPVOID lpvData)
{
PSAddInLexicon psAddInLexicon;
WORD wStrLen;
wStrLen = (WORD)lstrlenW(lpcwszString);
if (wStrLen <= MAX_CHAR_PER_WORD) {
psAddInLexicon = (PSAddInLexicon)lpvData;
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].lpwszWordStr =
new WORD[wStrLen + 1];
CopyMemory(psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].lpwszWordStr,
lpcwszString, (wStrLen + 1) * sizeof(WCHAR));
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].wAttrib = ATTR_EUDP_WORD;
psAddInLexicon->psWordData[psAddInLexicon->dwWordNumber].wLen = wStrLen;
++psAddInLexicon->dwWordNumber;
}
return 1;
}
int __cdecl CompSWordData(
const void *arg1,
const void *arg2)
{
PSWordData psWordData1, psWordData2;
psWordData1 = (PSWordData)arg1;
psWordData2 = (PSWordData)arg2;
if (psWordData1->wLen < psWordData2->wLen) {
return -1;
} else if (psWordData1->wLen > psWordData2->wLen) {
return 1;
} else {
return memcmp(psWordData1->lpwszWordStr,
psWordData2->lpwszWordStr, psWordData1->wLen * sizeof(WCHAR));
}
}
void CCHTLexicon::LoadEUDP(void)
{
DWORD i;
m_sAddInLexicon.dwWordNumber = 0;
m_sAddInLexicon.dwMaxWordNumber = 0;
m_sAddInLexicon.psWordData = NULL;
OSVERSIONINFOA OSVerInfo;
OSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionExA(&OSVerInfo);
if (OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
ImmEnumRegisterWordW(HKL((ULONG_PTR) 0xE0080404), EUDPCountW, NULL,
IME_REGWORD_STYLE_USER_PHRASE, NULL, &m_sAddInLexicon);
} else {
ImmEnumRegisterWordA(HKL((ULONG_PTR) 0xE0080404), EUDPCountA, NULL,
IME_REGWORD_STYLE_USER_PHRASE, NULL, &m_sAddInLexicon);
}
if (m_sAddInLexicon.dwWordNumber) {
m_sAddInLexicon.dwMaxWordNumber = m_sAddInLexicon.dwWordNumber + EUDP_GROW_NUMBER;
m_sAddInLexicon.psWordData = new SWordData[m_sAddInLexicon.dwMaxWordNumber];
m_sAddInLexicon.dwWordNumber = 0;
if (OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
ImmEnumRegisterWordW(HKL((ULONG_PTR) 0xE0080404), EUDPLoadW, NULL,
IME_REGWORD_STYLE_USER_PHRASE, NULL, &m_sAddInLexicon);
} else {
ImmEnumRegisterWordA(HKL((ULONG_PTR) 0xE0080404), EUDPLoadA, NULL,
IME_REGWORD_STYLE_USER_PHRASE, NULL, &m_sAddInLexicon);
}
qsort(m_sAddInLexicon.psWordData, m_sAddInLexicon.dwWordNumber,
sizeof(SWordData), CompSWordData);
for (i = 0; i < m_sAddInLexicon.dwWordNumber; ++i) {
++m_sAddInLexicon.wWordBeginIndex[m_sAddInLexicon.psWordData[i].wLen - 1];
}
WORD wCount = m_sAddInLexicon.wWordBeginIndex[0];
for (i = 1; i <= MAX_CHAR_PER_WORD; ++i) {
WORD wTemp = m_sAddInLexicon.wWordBeginIndex[i];
m_sAddInLexicon.wWordBeginIndex[i] = wCount;
wCount += wTemp;
}
} else {
m_sAddInLexicon.dwMaxWordNumber = 0;
}
}
// Add AP word
BOOL CCHTLexicon::AddInLexiconInsert(
LPCWSTR lpcwszWordStr,
WORD wAttrib)
{
BOOL fRet = FALSE;
WORD wStrLen, i, j;
INT nIndex;
wStrLen = (WORD)lstrlenW(lpcwszWordStr);
if (wStrLen > MAX_CHAR_PER_WORD) { goto _exit; }
// if exit, just change it's attrib;
// Be carefully, EUDP > Error word
if ((nIndex = GetAddInWordInfoIndex(lpcwszWordStr, wStrLen)) != -1) {
if (m_sAddInLexicon.psWordData[nIndex].wAttrib == ATTR_EUDP_WORD) {
} else {
m_sAddInLexicon.psWordData[nIndex].wAttrib = wAttrib;
}
goto _exit;
}
// Enlarge space
if (m_sAddInLexicon.dwMaxWordNumber == m_sAddInLexicon.dwWordNumber) {
PSWordData psTempWordData;
psTempWordData = new SWordData [m_sAddInLexicon.dwMaxWordNumber + EUDP_GROW_NUMBER];
if (!psTempWordData) { goto _exit; }
CopyMemory(psTempWordData, m_sAddInLexicon.psWordData,
m_sAddInLexicon.dwWordNumber * sizeof(SWordData));
delete [] m_sAddInLexicon.psWordData;
m_sAddInLexicon.psWordData = psTempWordData;
m_sAddInLexicon.dwMaxWordNumber += EUDP_GROW_NUMBER;
}
// Insert word
for (i = m_sAddInLexicon.wWordBeginIndex[wStrLen - 1]; i < m_sAddInLexicon.wWordBeginIndex[wStrLen]; ++i) {
if (memcmp(lpcwszWordStr, m_sAddInLexicon.psWordData[i].lpwszWordStr,
wStrLen * sizeof(WCHAR)) < 0) {
break;
}
}
for (j = (WORD)m_sAddInLexicon.dwWordNumber; j > i; --j) {
m_sAddInLexicon.psWordData[j] = m_sAddInLexicon.psWordData[j - 1];
}
m_sAddInLexicon.psWordData[i].lpwszWordStr = new WORD[wStrLen + 1];
CopyMemory(m_sAddInLexicon.psWordData[i].lpwszWordStr, lpcwszWordStr,
(wStrLen + 1) * sizeof(WORD));
m_sAddInLexicon.psWordData[i].wAttrib = wAttrib;
m_sAddInLexicon.psWordData[i].wLen = wStrLen;
++m_sAddInLexicon.dwWordNumber;
for (i = wStrLen; i <= MAX_CHAR_PER_WORD; ++i) {
++m_sAddInLexicon.wWordBeginIndex[i];
}
fRet = TRUE;
_exit:
#ifdef _DEBUG
for (i = 1; i <= MAX_CHAR_PER_WORD; ++i) {
for (j = m_sAddInLexicon.wWordBeginIndex[i - 1]; j < m_sAddInLexicon.wWordBeginIndex[i]; ++j) {
if (m_sAddInLexicon.psWordData[j].wLen != i) {
MessageBox(0, TEXT("Error string length"), TEXT("Error"), MB_OK);
}
if (j == m_sAddInLexicon.wWordBeginIndex[i] - 1) {
} else if (memcmp(m_sAddInLexicon.psWordData[j].lpwszWordStr,
m_sAddInLexicon.psWordData[j + 1].lpwszWordStr,
m_sAddInLexicon.psWordData[j].wLen * sizeof(WORD)) >= 0) {
MessageBox(0, TEXT("Error string order"), TEXT("Error"), MB_OK);
} else {
}
}
}
#endif
return fRet;
}
BOOL CCHTLexicon::GetAddInWordInfo(
LPCWSTR lpcwString,
DWORD dwLength,
PWORD pwUnicount,
PWORD pwAttrib,
PBYTE pbTerminalCode)
{
BOOL fRet = FALSE;
INT nIndex;
if (dwLength > MAX_CHAR_PER_WORD) { goto _exit; }
nIndex = GetAddInWordInfoIndex(lpcwString, dwLength);
if (nIndex == -1) { goto _exit; }
if (pwUnicount) {
*pwUnicount = 10000;
}
if (pwAttrib) {
*pwAttrib = m_sAddInLexicon.psWordData[nIndex].wAttrib;
}
if (pbTerminalCode) {
*pbTerminalCode = ' ';
}
fRet = TRUE;
_exit:
return fRet;
}
// return -1 if not find
INT CCHTLexicon::GetAddInWordInfoIndex(
LPCWSTR lpcwString,
DWORD dwLength)
{
INT nRet = -1;
INT nBegin, nEnd, nMid;
INT nCmp;
if (dwLength > MAX_CHAR_PER_WORD) { goto _exit; }
if (m_sAddInLexicon.wWordBeginIndex[dwLength - 1] == m_sAddInLexicon.wWordBeginIndex[dwLength]) {
goto _exit;
}
nBegin = m_sAddInLexicon.wWordBeginIndex[dwLength - 1];
nEnd = m_sAddInLexicon.wWordBeginIndex[dwLength] - 1;
while (nBegin <= nEnd) {
nMid = (nBegin + nEnd) / 2;
nCmp = memcmp(m_sAddInLexicon.psWordData[nMid].lpwszWordStr,
lpcwString, dwLength * sizeof(WCHAR));
if (nCmp > 0) {
nEnd = nMid - 1;
} else if (nCmp < 0) {
nBegin = nMid + 1;
} else {
nRet = nMid;
break;
}
}
_exit:
return nRet;
}
DWORD CCHTLexicon::GetAltWord(
LPCWSTR lpcwString,
DWORD dwLength,
LPWSTR* lppwAltWordBuf)
{
INT nBegin, nEnd, nMid;
INT nCmp;
DWORD dwRet = 0;
LPWSTR lpwAltWordString;
DWORD dwGroupID;
if (dwLength > m_psAltWordHeader->dwMaxCharPerWord) { goto _exit; }
nBegin = 0;
nEnd = m_psAltWordHeader->sAltWordInfo[dwLength - 1].dwWordNumber - 1;
lpwAltWordString = m_sAltWordInfo[dwLength - 1].lpwWordString;
DWORD dwCompByteNum;
dwCompByteNum = sizeof(WCHAR) * dwLength;
while (nBegin <= nEnd) {
nMid = (nBegin + nEnd) / 2;
nCmp = memcmp(&(lpwAltWordString[nMid * dwLength]), lpcwString, dwCompByteNum);
if (nCmp > 0) {
nEnd = nMid - 1;
} else if (nCmp < 0) {
nBegin = nMid + 1;
} else {
dwGroupID = m_sAltWordInfo[dwLength - 1].pdwGroupID[nMid];
// Fill AltWord
*lppwAltWordBuf = new WCHAR[dwLength + 1];
if (*lppwAltWordBuf) {
for (DWORD i = 0; i < m_psAltWordHeader->sAltWordInfo[dwLength - 1].dwWordNumber; ++i) {
if (i != (DWORD)nMid && m_sAltWordInfo[dwLength - 1].pdwGroupID[i] == dwGroupID) {
CopyMemory((LPVOID)*lppwAltWordBuf,
(LPVOID)&(m_sAltWordInfo[dwLength - 1].lpwWordString[i * dwLength]),
sizeof(WCHAR) * dwLength);
(*lppwAltWordBuf)[dwLength] = NULL;
++dwRet;
goto _exit;
}
}
}
break;
}
}
_exit:
return dwRet;
}