Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1006 lines
21 KiB

/*****************************************************************************
* *
* FTSNDX.C *
* *
* Copyright (C) Microsoft Corporation 1994. *
* All Rights reserved. *
* *
******************************************************************************
* *
* Module Description: Full Text Search Index *
* *
******************************************************************************
* *
* Current Owner: JOHNHALL *
* *
******************************************************************************
*
* Revision History:
* -- Mar 94 Modified / Stripped by JohnHall
*
*****************************************************************************/
#include "help.h"
#pragma hdrstop
#include "inc\compress.h"
#include "inc\skip.h"
#include "inc\fcpriv.h"
enum {
TABTYPELEFT,
TABTYPERIGHT,
TABTYPECENTER,
TABTYPEDECIMAL
};
#define ANIMATE_COUNT 100
typedef DWORD UINT32;
typedef INT ERRORCODE;
typedef void (__stdcall *ANIMATOR)(void);
typedef LONG (STDCALL *NEWINDEX)(const PBYTE s, UINT32 ulTime1,
UINT32 ulTime2,
UINT32 iDefaultCharset,
UINT32 lcidDefault,
UINT32 ulOptions);
typedef ERRORCODE (APIENTRY *SAVEINDEX)(long lIndex, LPSTR pOutput);
typedef ERRORCODE (APIENTRY *SCANTOPICTEXT)(long lIndex, LPSTR s, UINT32 cbText, UINT32 iCharSet, UINT32 lcid);
typedef ERRORCODE (APIENTRY *SCANTOPICTITLE)(long lIndex, LPSTR s, UINT32 uicb, UINT32 ulTopic, UINT32 ulHash, UINT32 uiCharSet, UINT32 lcid);
typedef ERRORCODE (APIENTRY *DELETEINDEX)(long lIndex);
NEWINDEX pNewIndex;
SAVEINDEX pSaveIndex;
SCANTOPICTEXT pScanTopicText;
SCANTOPICTITLE pScanTopicTitle;
DELETEINDEX pDeleteIndex;
extern ERRORCODE (APIENTRY *pRegAnimate)(ANIMATOR pAnimator, HWND hwnd);
long hindex = -1;
static VA vaCurrent;
static int iCharSet;
static int lcidCopy;
static BOOL fTitleSeen;
static int cbCollect;
static PSTR pszCollect;
static BOOL fPendingSpace;
static int iLastFTErr;
static INLINE int STDCALL myforage(QDE qde);
#ifdef _X86_
static PBYTE STDCALL ScanTopic(LPSTR lpData, QFCINFO qfcinfo, MTOP* pmtop);
#else
static PBYTE STDCALL ScanTopic(LPSTR lpData, QFCINFO qfcinfo, MTOP* pmtop,QDE qde);
#endif
static BOOL STDCALL NextFTSString(QDE qde, LPSTR pszText, LPSTR *ppCmd,
int* pCharSet, PCSTR pszEnd);
static INLINE int STDCALL AppendText(LPSTR lp, int uiSize, int uiCharSet, int lcid)
{
return pScanTopicText(hindex, lp, (UINT32) uiSize, (UINT32) uiCharSet, (UINT32) lcid);
}
#define COLLECT_BUFFER ((UINT)(64 * 1024))
static void STDCALL InitForageBuffer()
{
cbCollect = 0;
fPendingSpace = FALSE;
}
static void STDCALL FlushToIndexer()
{
if (cbCollect && !iLastFTErr)
iLastFTErr= AppendText(pszCollect, cbCollect, iCharSet, lcidCopy);
cbCollect= 0;
}
static void STDCALL QueueForIndexer(PSTR *ppszText)
{
PSTR pszText = *ppszText;
UINT cbText = strlen(pszText);
if (cbText + cbCollect + (fPendingSpace? 1 : 0) > COLLECT_BUFFER)
FlushToIndexer();
if (fPendingSpace)
{
pszCollect[cbCollect++] = ' ';
fPendingSpace= FALSE;
}
while (cbText)
{
UINT cbChunk= cbText;
if (cbChunk > COLLECT_BUFFER - cbCollect)
cbChunk = COLLECT_BUFFER - cbCollect;
cbText -= cbChunk;
CopyMemory(pszCollect + cbCollect, pszText, cbChunk);
cbCollect += cbChunk;
pszText += cbChunk;
if (cbCollect == COLLECT_BUFFER)
FlushToIndexer();
}
*ppszText = pszText;
}
static BOOL bSYS;
static BOOL bSYSFirst;
static BOOL STDCALL NextFTSString(QDE qde, LPSTR pszText, LPSTR *ppCmd,
int* pCharSet, PCSTR pszEnd)
{
char chCmd;
MOBJ mobj;
MOPG mopg;
BOOL bProcessCell = FALSE;
short int iCell;
BYTE CharSetNew;
if (*pszText)
QueueForIndexer(&pszText);
ASSERT(*pszText == 0x00);
while (pszText < pszEnd) {
while (*pszText == chCommand) {
// Side by side paragraph has the following embedded structure:
// INT16 cell number;
// MOBJ;
// MOPG;
if (bSYS && bSYSFirst)
{
bSYSFirst = FALSE;
bProcessCell = TRUE;
#ifdef _X86_
iCell = *((short int *) *ppCmd);
#else
{
UNALIGNED short int *pTemp;
pTemp = (short int *)*ppCmd;
iCell = *pTemp;
}
#endif
(*ppCmd) += 2;
if (iCell < 0)
return TRUE;
#ifdef _X86_
(*ppCmd) += CbUnpackMOBJ(&mobj, *ppCmd);
(*ppCmd) += CbUnpackMOPG(qde, &mopg, *ppCmd);
#else
(*ppCmd) += CbUnpackMOBJ(&mobj, (void *) *ppCmd, QDE_ISDFFTOPIC(qde));
(*ppCmd) += CbUnpackMOPG(qde, &mopg, *ppCmd, QDE_ISDFFTOPIC(qde));
#endif
}
// do
// {
chCmd = **ppCmd;
switch((0x00FF & chCmd))
{
case bNewLine:
fPendingSpace = TRUE;
(*ppCmd)++;
break;
case bNewPara:
fPendingSpace = TRUE;
(*ppCmd)++;
break;
case bTab:
fPendingSpace = TRUE;
(*ppCmd)++;
break;
case bEndHotspot:
(*ppCmd)++;
break;
case bBlankLine:
fPendingSpace = TRUE;
*ppCmd += 3;
break;
case bWordFormat:
(*ppCmd)++;
#ifdef _X86_
CharSetNew =
GetCharset(qde, (*((INT16*)*ppCmd))) & 0x000000ff;
#else
{
UNALIGNED INT16 *pTemp;
pTemp = (INT16*) *ppCmd;
CharSetNew = GetCharset(qde, *pTemp) & 0x000000ff;
}
#endif
if (CharSetNew != *pCharSet)
{
FlushToIndexer();
*pCharSet= CharSetNew;
}
*ppCmd += 2;
break;
case bWrapObjLeft:
case bWrapObjRight:
case bInlineObject:
fPendingSpace = TRUE;
(*ppCmd)++;
#ifdef _X86_
*ppCmd += CbUnpackMOBJ(&mobj, (void *) *ppCmd);
#else
*ppCmd += CbUnpackMOBJ(&mobj, (void *) *ppCmd,
QDE_ISDFFTOPIC(qde));
#endif
*ppCmd += (INT16) mobj.lcbSize;
break;
case bEnd:
(*ppCmd)++;
// fPendingSpace= TRUE;
if (bSYS)
{
bProcessCell = TRUE;
#ifdef _X86_
iCell = *((short int *) *ppCmd);
#else
{
UNALIGNED short int *pTemp;
pTemp = (short int *)*ppCmd;
iCell = *pTemp;
}
#endif
(*ppCmd) += 2;
if (iCell < 0)
return TRUE;
#ifdef _X86_
(*ppCmd) += CbUnpackMOBJ(&mobj, *ppCmd);
(*ppCmd) += CbUnpackMOPG(qde, &mopg, *ppCmd);
#else
(*ppCmd) += CbUnpackMOBJ(&mobj, (void *) *ppCmd, QDE_ISDFFTOPIC(qde));
(*ppCmd) += CbUnpackMOPG(qde, &mopg, *ppCmd, QDE_ISDFFTOPIC(qde));
#endif
}
if (bProcessCell)
bProcessCell = FALSE;
else
return TRUE;
break;
default:
if (FShortHotspot(**ppCmd))
{
*ppCmd += 5;
}
else if (FLongHotspot(**ppCmd))
{
(*ppCmd)++;
#ifdef _X86_
*ppCmd += 2 + *((INT16*)*ppCmd);
#else
{UNALIGNED INT16 *pTemp;
pTemp = (INT16*)*ppCmd;
*ppCmd += 2 + *pTemp;
}
#endif
}
else
{
ASSERT(FALSE);
return TRUE;
}
break;
}
// } while (bProcessCell);
pszText++;
}
if (pszText) QueueForIndexer(&pszText);
}
return TRUE;
}
/***************************************************************************
*
* John
*
***************************************************************************/
#ifdef _X86_
static PBYTE STDCALL ScanTopic(LPSTR lpData, QFCINFO qfcinfo, MTOP* pmtop)
#else
static PBYTE STDCALL ScanTopic(LPSTR lpData, QFCINFO qfcinfo, MTOP* pmtop, QDE qde)
#endif
{
MOBJ mobj;
int iTopic;
PSTR pszTitle;
UINT cbTitle;
char szUntitled[100];
QMSBS qmsbs;
#ifndef _X86_
MTOP mtop;
#endif
for(;;) {
#ifdef _X86_
lpData += CbUnpackMOBJ(&mobj, (QV) lpData);
#else
lpData += CbUnpackMOBJ(&mobj, (QV) lpData,QDE_ISDFFTOPIC(qde));
#endif
iTopic = 0x00FF & mobj.bType;
bSYS = FALSE;
bSYSFirst = FALSE;
switch (iTopic)
{
case bTypeSbys:
case bTypeSbysCounted:
if (pmtop)
return lpData;
bSYS = TRUE;
bSYSFirst = TRUE;
if (!ftsFlags.fUntitled && !fTitleSeen)
return NULL; // no text unless we have a title
qmsbs = (QMSBS) lpData;
lpData += 2;
if (!qmsbs->fAbsolute)
{
lpData += 2;
}
lpData += qmsbs->bcCol * sizeof(MCOL);
return(lpData);
default:
if (pmtop)
ZeroMemory(pmtop, sizeof(MTOP));
return(NULL);
break;
case bTypeParaGroup:
case bTypeParaGroupCounted:
{
MOPG mopg;
MPFG mpfg;
LPSTR lpStart = lpData;
int iTab;
if (pmtop)
return lpData;
if (!ftsFlags.fUntitled && !fTitleSeen && !pmtop)
return NULL; // no text unless we have a title
lpData = QVSkipQGE(lpData, (QL) &(mopg.libText));
#ifdef _X86_
mpfg = *((QMPFG) lpData);
#else
MoveMemory(&mpfg, lpData, sizeof(MPFG));
#endif
lpData = (LPSTR) (((QMPFG) lpData) + 1);
if (mpfg.rgf.fMoreFlags)
{
lpData = QVSkipQGE(lpData, (QL) &(mopg.lMoreFlags));
}
if (mpfg.rgf.fSpaceOver)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI) &(mopg.ySpaceOver));
}
if (mpfg.rgf.fSpaceUnder)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI) &(mopg.ySpaceUnder));
}
if (mpfg.rgf.fLineSpacing)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI) &(mopg.yLineSpacing));
}
if (mpfg.rgf.fLeftIndent)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI) &mopg.xLeftIndent);
}
if (mpfg.rgf.fRightIndent)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI)&mopg.xRightIndent);
}
if (mpfg.rgf.fFirstIndent)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI)&mopg.xFirstIndent);
}
mopg.xTabSpacing = 72;
if (mpfg.rgf.fTabSpacing)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI)&mopg.xTabSpacing);
}
if (mpfg.rgf.fBoxed)
{
mopg.mbox = *((UNALIGNED MBOX *)lpData);
#ifdef _X86_
lpData = (LPSTR) (((QMBOX)lpData) + 1);
#else
lpData = (QB)lpData + 3;
#endif
}
if (mpfg.rgf.fTabs)
{
lpData = QVSkipQGD((LPBYTE) lpData, (QI) &mopg.cTabs);
}
else
mopg.cTabs = 0;
for (iTab = 0; iTab < mopg.cTabs; iTab++)
{
lpData = QVSkipQGA(lpData, (QI) &mopg.rgtab[iTab].x);
if (mopg.rgtab[iTab].x & 0x4000)
lpData = QVSkipQGA(lpData, (QI) &mopg.rgtab[iTab].wType);
else
mopg.rgtab[iTab].wType = TABTYPELEFT;
mopg.rgtab[iTab].x = mopg.rgtab[iTab].x & 0xBFFF;
}
}
return(lpData);
break;
case bTypeTopic:
if (pmtop) { // all we wanted was MTOP structure
MoveMemory(pmtop, lpData, sizeof(MTOP));
return NULL;
}
else
#ifdef _X86_
pmtop = (MTOP*) lpData;
#else
{
MoveMemory(&mtop, lpData, sizeof(MTOP));
pmtop = & mtop;
}
#endif
lpData += sizeof(MTOP);
#ifdef _X86_
pszTitle = (PSTR) (((PBYTE) qfcinfo) + qfcinfo->ichText);
#else
pszTitle = lpData;
#endif
/*
* If only a title is specified, it isn't null-terminated, so
* we can't do a strlen. It only gets null-terminated if there is
* also an auto-entry macro.
*/
cbTitle = 0;
while ((cbTitle < qfcinfo->lcbText) && (*pszTitle != '\0')) {
pszTitle++;
cbTitle++;
}
if (!cbTitle) {
if (!ftsFlags.fUntitled) {
fTitleSeen = FALSE;
return NULL;
}
if (!pszUntitled)
pszUntitled = LocalStrDup(GetStringResource(sidUntitled));
wsprintf(szUntitled, pszUntitled, pmtop->lTopicNo);
pszTitle = szUntitled;
cbTitle = strlen(pszTitle);
}
else {
#ifdef _X86_
pszTitle = (PSTR) (((PBYTE) qfcinfo) + qfcinfo->ichText);
#else
pszTitle = lpData; //REVIEW:Lynn
#endif
fTitleSeen = TRUE;
}
/*
* For topics without a non-scrolling region,
* mtop.vaSR.dword is the same as vaCurrent.dword. If that's
* also true for topics with a non-scrolling region, then we
* can just use that instead of vaCurrent.dword.
*/
// Flush any previous topic's data
FlushToIndexer();
InitForageBuffer();
if (!iLastFTErr)
iLastFTErr= pScanTopicTitle(hindex, pszTitle, cbTitle,
pmtop->lTopicNo,
(UINT32) vaCurrent.dword, // VA goes here.
iCharSet,
lcidCopy
);
return(NULL);
}
}
}
#define OUT_OF_MEMORY ((UINT) -6)
static INLINE int STDCALL myforage(QDE qde)
{
static DB db;
int wErr;
HFC hfc;
VA vaNext;
LPSTR lpCmd;
LPSTR lpText;
DWORD dwCmd;
int cbAnimate = 0;
QFCINFO qfcinfo;
iLastFTErr = 0;
pszCollect = lcMalloc(COLLECT_BUFFER);
if (!pszCollect)
return OUT_OF_MEMORY;
InitForageBuffer();
iCharSet = defcharset;
lcidCopy = (lcid ? lcid : GetUserDefaultLCID());
vaNext.bf.blknum = 0;
vaNext.bf.byteoff = sizeof(MBHD);
fTitleSeen = FALSE;
while ((hfc = GetQFCINFO(qde, vaNext, &wErr)) != NULL)
{
qfcinfo = (QFCINFO) PtrFromGh(hfc);
/*
* In order for WinHelp to be able to jump to this topic,
* vaCurrent must be set to vaNext. Don't ask me why -- but it works.
* Same VA is used in History and Bookmark jumps. [ralphw]
*/
vaCurrent = vaNext = qfcinfo->vaNext;
#ifdef _X86_
lpCmd = ScanTopic(((LPSTR) qfcinfo) + sizeof(FCINFO), qfcinfo, NULL);
#else
lpCmd = ScanTopic(((LPSTR) qfcinfo) + sizeof(FCINFO), qfcinfo, NULL, qde);
#endif
if (iLastFTErr)
{
FreeGh(hfc);
lcFree(pszCollect);
return iLastFTErr;
}
if (lpCmd) {
#if defined(_DEBUG)
BOOL fResult;
#endif // _DEBUG
lpText = ((LPSTR) qfcinfo) + qfcinfo->ichText;
dwCmd = lpText - lpCmd;
#if defined(_DEBUG)
fResult=
#endif // _DEBUG
NextFTSString(qde, lpText, &lpCmd, &iCharSet, lpText + qfcinfo->lcbText);
ASSERT(fResult); // NextFTSString always returns TRUE. Why?
if (iLastFTErr)
{
FreeGh(hfc);
lcFree(pszCollect);
return iLastFTErr;
}
}
FreeGh(hfc);
if (++cbAnimate == ANIMATE_COUNT)
{
NextAnimation();
cbAnimate = 0;
}
}
FlushToIndexer();
lcFree(pszCollect);
return 0;
}
#ifndef NO_PRAGMAS
#pragma data_seg(".text", "CODE")
#endif
static const char txtNewIndex[] = "NewIndex";
static const char txtSaveIndex[] = "SaveIndex";
static const char txtScanTopicText[] = "ScanTopicText";
static const char txtScanTopicTitle[] = "ScanTopicTitle";
static const char txtDeleteIndex[] = "DeleteIndex";
#ifndef NO_PRAGMAS
#pragma data_seg()
#endif
// Will return FALSE if we run out of memory, or can't initialize ftsrch.dll
int STDCALL GenerateIndex(HDE hde, PCSTR pszFile, UINT fdwOptions)
{
HLIBMOD hmod;
int iRet;
LCID lcidCopy = (lcid ? lcid : GetUserDefaultLCID());
char szFtsFile[MAX_PATH];
if (QDE_HHDR(QdeFromGh(hde)).wVersionNo == wVersion3_0) {
char szBuf[MAX_PATH + 100];
wsprintf(szBuf, GetStringResource(wERRS_NO_30_FTS), pszFile);
ErrorQch(szBuf);
return FALSE;
}
if (!pNewIndex) {
if (!(hmod = HFindDLL(GetStringResource(sidFtsDll), TRUE)))
return FALSE;
pNewIndex = (NEWINDEX ) GetProcAddress(hmod, txtNewIndex);
pSaveIndex = (SAVEINDEX ) GetProcAddress(hmod, txtSaveIndex);
pScanTopicText = (SCANTOPICTEXT) GetProcAddress(hmod, txtScanTopicText);
pScanTopicTitle = (SCANTOPICTITLE) GetProcAddress(hmod, txtScanTopicTitle);
pDeleteIndex = (DELETEINDEX) GetProcAddress(hmod, txtDeleteIndex);
if (!pNewIndex || !pSaveIndex || !pScanTopicText || !pScanTopicTitle || !pDeleteIndex || !pRegAnimate) {
ASSERT(!"Bad ftsrch.dll");
// BUGBUG: whine to the user
pNewIndex = NULL;
return FALSE;
}
}
if (hwndParent) {
char szBuf[MAX_PATH + 100];
wsprintf(szBuf, GetStringResource(sidIndexing), pszFile);
SendStringToParent(szBuf);
}
pRegAnimate(NextAnimation, hwndAnimate);
hindex = pNewIndex((const PBYTE) pszFile,
QDE_LTIMESTAMP(QdeFromGh(hde)), // time 1
0, // time2 (we don't use this)
defcharset,
lcidCopy,
fdwOptions);
if (hindex <= 0)
return FALSE;
iRet = myforage(QdeFromGh(hde));
if (iRet)
{
pDeleteIndex(hindex);
hindex = -1;
pRegAnimate(NULL, NULL);
return iRet; // FALSE probably means out of memory
}
strcpy(szFtsFile, pszFile);
ChangeExtension(szFtsFile, txtFtsExtension);
iRet= pSaveIndex(hindex, szFtsFile);
pDeleteIndex(hindex);
hindex = -1;
pRegAnimate(NULL, NULL);
return iRet; // FALSE probably means out of memory
}
/***************************************************************************
FUNCTION: JumpToTopicNumber
PURPOSE: Jump to the topic specified by the topic number
PARAMETERS:
topicnum -- topic number to jump to
RETURNS:
COMMENTS:
If we've never been called before, or our help file has changed,
then we generate an array of VAs. The topic number is simply an
index into this array that tells us where to jump to.
MODIFICATION DATES:
03-Aug-1994 [ralphw]
***************************************************************************/
static int cTopics;
static FM fmHelpFile; // the help file we have topics for
static VA* pva; // array of VA's
BOOL STDCALL JumpToTopicNumber(int topicnum)
{
HFC hfc;
QDE qde = QdeFromGh(HdeGetEnv());
int wErr;
MTOP mtop;
VA vaNext;
QFCINFO qfcinfo;
int cbAnimate = 0;
ASSERT(qde);
if (!qde)
return FALSE;
if (QDE_HHDR(qde).wVersionNo == wVersion3_0) {
OkMsgBox(GetStringResource(wERRS_NT_VERSION3));
return FALSE;
}
if (fmHelpFile && !IsSameFile(fmHelpFile, GetCurFilename())) {
RemoveFM(&fmHelpFile);
FreeLh(pva);
cTopics = 0;
}
if (!fmHelpFile) {
int cbArray = (1024 * sizeof(VA)); // size of our pva array
fmHelpFile = LocalStrDup(GetCurFilename());
pva = LhAlloc(LMEM_FIXED, cbArray);
if (!StartAnimation(sidJump)) {
Oom:
RemoveFM(&fmHelpFile);
Error(wERRS_OOM, wERRA_RETURN);
return FALSE;
}
vaNext.bf.blknum = 0;
vaNext.bf.byteoff = sizeof(MBHD);
lcHeapCheck();
while ((hfc = GetQFCINFO(qde, vaNext, &wErr)) != NULL) {
lcHeapCheck();
qfcinfo = (QFCINFO) PtrFromGh(hfc);
/*
* In order for WinHelp to be able to jump to this topic,
* vaCurrent must be set to vaNext. Don't ask me why -- but it
* works. Same VA is used in History and Bookmark jumps. [ralphw]
*/
vaCurrent = vaNext = qfcinfo->vaNext;
#ifdef _X86_
if (!ScanTopic(((LPSTR) qfcinfo) + sizeof(FCINFO), NULL, &mtop) &&
#else
if (!ScanTopic(((LPSTR) qfcinfo) + sizeof(FCINFO), NULL, &mtop, qde) &&
#endif
mtop.vaSR.dword) {
if (cTopics * (int) sizeof(VA) >= cbArray) {
cbArray += (1024 * sizeof(VA));
pva = GhResize(pva, LMEM_FIXED, cbArray);
if (!pva)
goto Oom;
}
ASSERT(cTopics == mtop.lTopicNo);
pva[cTopics++] = vaCurrent;
}
FreeGh(hfc);
if (++cbAnimate == ANIMATE_COUNT) {
NextAnimation();
cbAnimate = 0;
}
}
StopAnimation();
}
if (topicnum == -1) // special case for last topic in help file
topicnum = cTopics - 2;
if (topicnum >= 0 && topicnum <= cTopics) {
JumpVA(pva[topicnum].dword);
if (hwndSecondHelp) {
JumpLinkedWinHelp(topicnum);
}
}
else
return FALSE;
return TRUE;
}
#if 0
#ifdef DBCS
/***************************************************************************
FUNCTION: BreakDBCDLine
PURPOSE: Break a DBCS line into words
PARAMETERS:
pszLine
RETURNS:
COMMENTS:
MODIFICATION DATES:
15-Nov-1994 [ralphw]
***************************************************************************/
void STDCALL BreakDBCDLine(PSTR pszLine)
{
LPSTR qch = pszLine;
char chTNew, chTOld;
for (;;) {
for (;;) {
if (IsDBCSLeadByte(*qch) && Is2ndByte(qch[1])) {
qch += 2;
if (*qch == '\0')
return;
else
chTNew = chTSuff;
break;
}
else if (defcharset == SHIFTJIS_CHARSET) {
// yutakas New Kinsoku Routine.
PSTR ptmp;
BOOL bOiKin = FALSE;
// Check Oikomi Kinsoku Char.
ptmp = qch;
do {
ptmp = IsKinsokuChars(ptmp);
if (ptmp) {
if ((*ptmp == '\0') || (*ptmp == ' '))
ptmp = NULL;
else
qch = ptmp;
}
} while (ptmp && *ptmp);
//Check Oidashi Kinsoku Char.
ptmp = qch;
do {
ptmp = IsOiKinsokuChars(ptmp);
if (ptmp) {
if (( *ptmp == '\0' ) || (*ptmp == chSpace))
ptmp = NULL;
else
{
qch = ptmp;
bOiKin = TRUE;
}
}
} while (ptmp && *ptmp);
// Word End at next pointer of Oidashi Kinsoku.
if (bOiKin) {
if (*qch == '\0')
return;
else
chTNew = chTSuff;
chTOld = chTNew;
break;
}
/*
* DBCS Char treat as One Word. If Next of DBCS Char is
* Oidashi Kinsoku, Word End is after pointer of Oidashi
* Kinsoku. [yutakas]
*/
if (IsDBCSLeadByte(*qch) && Is2ndByte(qch[1])) {
qch += 2;
ptmp = qch;
do {
ptmp = IsOiKinsokuChars(ptmp);
if (ptmp) {
if (( *ptmp == '\0' ) || (*ptmp == chSpace))
ptmp = NULL;
else
qch = ptmp;
}
} while (ptmp && *ptmp);
if (*qch == '\0')
return;
else
chTNew = chTSuff;
chTOld = chTNew;
break;
}
else
goto DoSwitch;
}
else {
DoSwitch:
switch (*qch) {
case '\0':
return;
break;
case chSpace:
chTNew = chTSuff;
break;
default:
chTNew = chTMain;
break;
}
if (chTNew < chTOld)
break;
chTOld = chTNew;
qch++;
}
}
}
}
#endif // DBCS
#endif