NT4/private/windows/win4help/ftsrch/ftsrch.cpp
2020-09-30 17:12:29 +02:00

580 lines
19 KiB
C++
Raw Blame History

// Ftsrch.cpp -- Main interface function
#include "stdafx.h"
// #include <strstrea.h>
#include "resource.h"
#include "dialogs.h"
#include "Globals.h"
#include "FTSIFace.h"
#include "ftsrch.h"
#include "memex.h"
#include "dict.h"
#include "vector.h"
#include "query.h"
#include "hilite.h"
#define SIZESTRING 256 // max characters in string
/*rmk-->
int cLetters = 0;
BYTE bCharTypes [256] = { 0 };
BYTE xlateCollate [256] = { 0xFF };
BYTE xlateCollateInv [256] = { 0xFF };
BYTE xlateCollateIC [256] = { 0xFF };
BYTE map_to_lower_case[256] = { 0xFF };
BYTE map_to_upper_case[256] = { 0xFF };
BYTE map_to_char_class[256] = { 0 };
static const PBYTE pbLetters = (PBYTE) &"Aa类玲骡勉匿佩奇BbCc晴Dd叙Ee辱砷赎穗FfGgHhIi天晚晤巷JjKkLlMmNn疡Oo因芋贼挣嘱伉寽PpQqRrSs姎TtUu蠃邡埯茳VvWwXxYy<59><79>蔟Zz撖";
static const PBYTE pbLetrcls = (PBYTE) &"aaaaaaaaaaaaaaaabbccccddddeeeeeeeeeeffgghhiiiiiiiiiijjkkllmmnnnnooooooooooooooooppqqrrssssttuuuuuuuuuuvvwwxxyyyyyyzz<7A>";
static const PBYTE pbUpperCase = (PBYTE)&"A懒旅呐艬C荄蠩壬仕FGHI掏蜗JKLMN袿矣哉重孭QRS奣U仝圮VWXY熭Z<E786AD>";
static const PBYTE pbAccented = (PBYTE) &"类玲骡勉匿佩晴叙辱砷赎穗天晚晤巷疡因芋贼挣嘱伉寽姎蠃邡埯茳<E59FAF><E88CB3>蔟";
static const PBYTE pbPseudoLetters = (PBYTE) &"$_<>";
static const PBYTE pbDigits = (PBYTE) &"0123456789";
static const PBYTE pbLetterImbeds = (PBYTE) &"'-";
static const PBYTE pbDigitImbeds = (PBYTE) &",.";
<--rmk*/
void InitialTables()
{
// This routine sets up the tables which TBrowse uses to parse text streams into
// symbols and punctuation. The tables are also used for collating sequence
// comparisons and for sorting.
/*rmk-->
BYTE *pb, *pb2, b, b2;
int c;
for (c= 256, pb= &bCharTypes[0]; c--; ) *pb++ = 0;
bCharTypes[ 0] = NULL_CHAR;
for (pb= pbLetters ; b= *pb++; ++cLetters) bCharTypes[b] = LETTER_CHAR;
for (pb= pbPseudoLetters; b= *pb++; ) bCharTypes[b] = LETTER_CHAR;
for (pb= pbUpperCase ; b= *pb++; ) bCharTypes[b] |= UPPER_CASE_CHAR;
for (pb= pbAccented ; b= *pb++; ) bCharTypes[b] |= ACCENTED_CHAR;
for (pb= pbDigits ; b= *pb++; ) bCharTypes[b] = DIGIT_CHAR;
for (pb= pbLetterImbeds ; b= *pb++; ) bCharTypes[b] = LETTER_IMBED;
for (pb= pbDigitImbeds ; b= *pb++; ) bCharTypes[b] = DIGIT_IMBED;
for (c= 0; c < 256; ++c)
{
map_to_lower_case[c]= c;
map_to_upper_case[c]= c;
map_to_char_class[c]= c;
xlateCollate [c]= 0xFF;
}
for (pb= pbLetters, pb2= pbLetrcls; b= *pb++; )
{
map_to_char_class[b ]= *pb2++;
map_to_lower_case[b ]= b2= *pb++;
map_to_upper_case[b2]= b;
map_to_char_class[b2]= *pb2++;
}
for (pb= pbLetters, b2=0; b= *pb++; ) xlateCollate[b]= b2++;
for (pb= pbPseudoLetters; b= *pb++; ) xlateCollate[b]= b2++;
for (pb= pbDigits ; b= *pb++; ) xlateCollate[b]= b2++;
xlateCollate[' ' ]= b2++;
xlateCollate['\t']= b2++;
for (c= 0x20; c < 0x100; ++c) if (xlateCollate[c] == 0xFF) xlateCollate[c]= b2++;
for (c= 0x01; c < 0x20 ; ++c) if (xlateCollate[c] == 0xFF) xlateCollate[c]= b2++;
for (c= 0; c < 256; c++) xlateCollateIC[c]= xlateCollate[c];
for (pb= pbLetters, pb2= pbLetrcls; b= *pb++; ) xlateCollateIC[b] = xlateCollateIC[*pb2++];
for (c= 256; c--; ) xlateCollateInv[xlateCollate[c]] = c;
<--rmk*/
}
extern "C" void __stdcall NextAnimation(void)
{
// You are calling the animation routines when the animate object in
// winhelp (or the calling app does not exist, or has not been registered
// with the RegisterAnimator call.
// ASSERT(FALSE);
}
ANIMATOR pAnimate = NextAnimation; // Put a asserting routing there to start
extern "C" HINDEX APIENTRY NewIndex(const PBYTE pbSourceName, UINT uiTime1, UINT uiTime2,
UINT iCharsetDefault, UINT lcidDefault, UINT fdwOptions
)
{
pAnimate();
UINT cbSourceName= strlen(PCHAR(pbSourceName)) + 1;
FILETIME ft;
ft. dwLowDateTime = uiTime1;
ft.dwHighDateTime = uiTime2;
HINDEX hinx= CGlobals::NewIndexGlobals(pbSourceName, cbSourceName, &ft, iCharsetDefault, lcidDefault, fdwOptions);
return hinx;
}
extern "C" ERRORCODE APIENTRY ScanTopicTitle(HINDEX hinx, PBYTE pbTitle, UINT cbTitle,
UINT iTopic, HANDLE hTopic, UINT iCharset, UINT lcid
)
{
pAnimate();
if (!CGlobals::ValidObject((CGlobals *)hinx, CGlobals::Indexer)) return NOT_INDEXER;
ERRORCODE ec= ((CGlobals *)hinx)->ScanTopicTitle(pbTitle, cbTitle, iTopic, hTopic, iCharset, lcid);
return ec;
}
extern "C" ERRORCODE APIENTRY ScanTopicText (HINDEX hinx, PBYTE pbText, UINT cbText, UINT iCharset, UINT lcid)
{
pAnimate();
if (!CGlobals::ValidObject((CGlobals *)hinx, CGlobals::Indexer)) return NOT_INDEXER;
ERRORCODE ec= ((CGlobals *)hinx)->ScanTopicText(pbText, cbText, iCharset, lcid);
return ec;
}
extern "C" ERRORCODE APIENTRY SaveIndex(HINDEX hinx, PSZ pszFileName)
{
pAnimate();
if (!CGlobals::ValidObject((CGlobals *)hinx, CGlobals::Indexer)) return NOT_INDEXER;
ERRORCODE ec= ((CGlobals *)hinx)->SaveIndex(pszFileName);
return ec;
}
extern "C" ERRORCODE APIENTRY DeleteIndex(HINDEX hinx)
{
pAnimate();
if (!CGlobals::ValidObject((CGlobals *)hinx, CGlobals::Indexer)) return NOT_INDEXER;
delete (CGlobals *)hinx;
return 0;
}
extern "C" BOOL APIENTRY IsValidIndex(PSZ pszFileName, UINT dwOptions)
{
return CPersist::IsValidIndex(pszFileName, dwOptions & (TOPIC_SEARCH | PHRASE_SEARCH | PHRASE_FEEDBACK | VECTOR_SEARCH));
}
extern "C" HSEARCHER APIENTRY NewSearcher()
{
return (HSEARCHER) (CGlobals::NewSearcherGlobals());
}
extern "C" INT APIENTRY OpenIndex(HSEARCHER hsrch, PSZ pszIndexFileName,
PBYTE pbSourceName, PUINT pcbSourceNameLimit,
PUINT pTime1, PUINT pTime2
)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NOT_SEARCHER;
FILETIME ft;
ft.dwLowDateTime = pTime1? *pTime1 : 0;
ft.dwHighDateTime = pTime2? *pTime2 : 0;
INT iResult= ((CGlobals *) hsrch)->OpenIndex(pszIndexFileName, pbSourceName, pcbSourceNameLimit, &ft);
if (pTime1) *pTime1= ft.dwLowDateTime;
if (pTime2) *pTime2= ft.dwHighDateTime;
return iResult;
}
extern "C" ERRORCODE APIENTRY DiscardIndex(HSEARCHER hsrch, INT iIndex)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NOT_SEARCHER;
return ((CGlobals *) hsrch)->DiscardIndex(iIndex);
}
extern "C" ERRORCODE APIENTRY QueryOptions (HSEARCHER hsrch, INT iIndex, PUINT pfdwOptions)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NOT_SEARCHER;
return ((CGlobals *) hsrch)->QueryOptions(iIndex, pfdwOptions);
}
extern "C" ERRORCODE APIENTRY SaveGroup(HSEARCHER hsrch, PSZ pszFileName)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NOT_SEARCHER;
return ((CGlobals *) hsrch)->SaveGroup(hsrch, pszFileName);
}
extern "C" ERRORCODE APIENTRY LoadGroup(HSEARCHER hsrch, PSZ pszFileName)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NOT_SEARCHER;
return ((CGlobals *) hsrch)->LoadGroup(hsrch, pszFileName);
}
extern "C" HWND APIENTRY OpenDialog(HSEARCHER hsrch, HWND hwndParent)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NULL;
return ((CGlobals *) hsrch)->OpenDialog(hwndParent);
}
extern "C" ERRORCODE APIENTRY DeleteSearcher(HSEARCHER hsrch)
{
if (!CGlobals::ValidObject((CGlobals *)hsrch, CGlobals::Searcher)) return NOT_SEARCHER;
delete (CGlobals *) hsrch;
return 0;
}
extern "C" HCOMPRESSOR APIENTRY NewCompressor(UINT iCharsetDefault)
{
return (HCOMPRESSOR) (CGlobals::NewCompressorGlobals(iCharsetDefault));
}
extern "C" ERRORCODE APIENTRY ScanText(HCOMPRESSOR hcmp, PBYTE pbText, UINT cbText, UINT iCharset)
{
if (!CGlobals::ValidObject((CGlobals *)hcmp, CGlobals::Compressor)) return NOT_COMPRESSOR;
return ((CGlobals *) hcmp)->ScanForStats(pbText, cbText, iCharset);
}
extern "C" ERRORCODE APIENTRY GetPhraseTable(HCOMPRESSOR hcmp, PUINT pcPhrases, PBYTE *ppbImages, PUINT pcbImages,
PBYTE *ppacbImageCompressed, PUINT pcbCompressed
)
{
if (!CGlobals::ValidObject((CGlobals *)hcmp, CGlobals::Compressor)) return NOT_COMPRESSOR;
return ((CGlobals *) hcmp)->GetPhraseTable(pcPhrases, ppbImages, pcbImages,
ppacbImageCompressed, pcbCompressed
);
}
extern "C" ERRORCODE APIENTRY SetPhraseTable(HCOMPRESSOR hcmp, PBYTE pbImages, UINT cbImages,
PBYTE pacbImageCompressed, UINT cbCompressed
)
{
if (!CGlobals::ValidObject((CGlobals *)hcmp, CGlobals::Compressor)) return NOT_COMPRESSOR;
return ((CGlobals *) hcmp)->SetPhraseTable(pbImages, cbImages,
pacbImageCompressed, cbCompressed
);
}
extern "C" INT APIENTRY CompressText(HCOMPRESSOR hcmp, PBYTE pbText, UINT cbText, PBYTE *ppbCompressed, UINT iCharset)
{
if (!CGlobals::ValidObject((CGlobals *)hcmp, CGlobals::Compressor)) return NOT_COMPRESSOR;
return ((CGlobals *) hcmp)->CompressText(pbText, cbText, ppbCompressed, iCharset);
}
extern "C" INT APIENTRY DecompressText(HCOMPRESSOR hcmp, PBYTE pbCompressed, UINT cbCompressed, PBYTE pbText)
{
if (!CGlobals::ValidObject((CGlobals *)hcmp, CGlobals::Compressor)) return NOT_COMPRESSOR;
return ((CGlobals *) hcmp)->DecompressText(pbCompressed, cbCompressed, pbText);
}
extern "C" ERRORCODE APIENTRY DeleteCompressor(HCOMPRESSOR hcmp)
{
if (!CGlobals::ValidObject((CGlobals *)hcmp, CGlobals::Compressor)) return NOT_COMPRESSOR;
delete (CGlobals *) hcmp;
return 0;
}
HINSTANCE hinstDLL = NULL;
HINSTANCE hLexLib = NULL;
HINSTANCE hMPRLib = NULL;
UINT uOpSys = NULL;
UINT uOpSysVer = NULL;
HCURSOR hcurArrow = NULL;
HCURSOR hcurBusy = NULL;
HBITMAP hbmGray50pc = NULL;
HBITMAP hbmCheckered = NULL;
PWORDBREAKW pWordBreakW = NULL;
PWORDBREAKA pWordBreakA = NULL;
PWNETADDCONNECTION2A pWNetAddConnection2 = NULL;
PWNETCANCELCONNECTION2A pWNetCancelConnection2 = NULL;
#define MAX_ERROR_STRING 256
#define MAX_TITLE 128
char szDisk_Full_Err [MAX_ERROR_STRING];
char szDisk_Full_Err2 [MAX_TITLE];
char szMem_Err [MAX_ERROR_STRING];
char szNeed_More_Memory[MAX_TITLE];
UINT cAttachedProcesses = 0;
extern "C" void InitialFTSLex();
extern "C" void ShutdownFTSLex();
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID pvReserved)
{
// BugBug! Need a Mutex Semaphore for this code...
if (!hinstDLL) hinstDLL= hInstance;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
if (!cAttachedProcesses++)
{
InitialFTSLex();
char szLexLib[20];
wsprintf(szLexLib, "ftlx%04lx.dll", GetUserDefaultLCID());
hLexLib = LoadLibrary(szLexLib); // attempt to load non-English word break
if (!hLexLib && szLexLib[4] != '0' && szLexLib[5] != '4')
{
szLexLib[4] = '0'; // not successful, search for 04XX word break
szLexLib[5] = '4';
hLexLib = LoadLibrary(szLexLib); // attempt to load non-English word break
}
if (hLexLib)
{
pWordBreakA = (PWORDBREAKA)GetProcAddress(hLexLib, "FTSWordBreakA");
pWordBreakW = (PWORDBREAKW)GetProcAddress(hLexLib, "FTSWordBreakW");
if (!pWordBreakA || !pWordBreakW)
{
// If we failed to get both proc addresses, we set the pointer variables back to NULL.
pWordBreakA = &FTSWordBreakA;
pWordBreakW = &FTSWordBreakW;
}
}
else
{
pWordBreakA = &FTSWordBreakA;
pWordBreakW = &FTSWordBreakW;
}
if ( !::LoadString(hinstDLL, IDS_DISK_FULL_ERR , szDisk_Full_Err , MAX_ERROR_STRING)
|| !::LoadString(hinstDLL, IDS_DISK_FULL_ERR2 , szDisk_Full_Err2 , MAX_TITLE )
|| !::LoadString(hinstDLL, IDS_MEM_ERR , szMem_Err , MAX_ERROR_STRING)
|| !::LoadString(hinstDLL, IDS_NEED_MORE_MEMORY, szNeed_More_Memory, MAX_TITLE )
) return FALSE;
if (!_CRT_INIT(hInstance, fdwReason, pvReserved))
return FALSE;
InitialTables();
hcurArrow = ::LoadCursor(NULL, IDC_ARROW );
hcurBusy = ::LoadCursor(NULL, IDC_WAIT );
hbmGray50pc = ::LoadBitmap(hinstDLL, "GRAY_50_PER_CENT");
hbmCheckered = ::LoadBitmap(hinstDLL, "CHECKERED" );
char map[4] = {WINNT,WIN16,WIN32S,WIN40};
DWORD dwVer = GetVersion();
#if defined (WIN32)
uOpSys = map[dwVer >> 30];
#else
uOpSys = WIN16;
#endif
uOpSysVer = LOWORD(dwVer);
if (!hcurArrow || !hcurBusy || !hbmGray50pc || !hbmCheckered)
{
if (hbmGray50pc ) DeleteObject(hbmGray50pc );
if (hbmCheckered) DeleteObject(hbmCheckered);
return FALSE;
}
}
return CFind::RegisterWndClass(hinstDLL) &&
CTextView::RegisterWndClass(hinstDLL);
break;
case DLL_PROCESS_DETACH:
CGlobals::ProcessShutdown();
ShutdownFTSLex();
LiberateHeap();
if (!--cAttachedProcesses)
{
ASSERT(!CGlobals::AnyGlobalsActive());
DeleteObject(hbmGray50pc );
DeleteObject(hbmCheckered);
if (hLexLib)
FreeLibrary(hLexLib);
if (hMPRLib)
FreeLibrary(hMPRLib);
hLexLib = NULL;
pWordBreakW = NULL;
pWordBreakA = NULL;
hMPRLib = NULL;
}
_CRT_INIT(hInstance, fdwReason, pvReserved);
break;
default:
_CRT_INIT(hInstance, fdwReason, pvReserved);
break;
}
return TRUE;
}
// WinHelp interfaces -- note WINAPI calling convention
extern "C" HWND WINAPI OpenTabDialog(HWND hwndParent, DWORD val1, DWORD val2)
{
return OpenDialog((HSEARCHER) val1, hwndParent);
}
BOOL fAnimatorExternal = FALSE;
extern "C" ERRORCODE APIENTRY RegisterAnimator(ANIMATOR pAnimator, HWND hwndAnimator)
{
if (pAnimator == NULL)
{
pAnimate = NextAnimation; // Null routine with an assert
hwndMain = NULL;
fAnimatorExternal = FALSE;
}
else
{
pAnimate = pAnimator;
hwndMain = hwndAnimator;
fAnimatorExternal = TRUE;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////
// New Hilite Functions
// "NewHiliter" creates a hiliter tied to a particular searcher.
// We also pass it a windows handle so it can notify us whenever the
// current query state (in a given hiliter) becomes outdated.
// [if you do not wish to be notified pass a null handle]
// Returns a handle to the new hiliter.
extern "C" HHILITER APIENTRY NewHiliter(HSEARCHER hSearch)
{
if (!CGlobals::ValidObject((CGlobals*)hSearch, CGlobals::Searcher)) return 0;
// make sure we have a valid searcher
HHILITER hhil = (HHILITER) (CHiliter::NewHiliter(hSearch));
// if so, go down a level
return hhil; // .. and return new handle
}
extern "C" ERRORCODE APIENTRY DeleteHiliter(HHILITER hhil)
{
pAnimate();
if (!CHiliter::ValidObject(hhil)) return NOT_HILITER;
delete (CHiliter*)hhil;
return 0;
}
// --------------------------------------------------------------------------
// "ScanDisplayText" supplies the display text for which hilite information
// is to be computed. This function may be called iteratively to pass across
// the relevant display text. This is necessary because the text may be
// composed of segments with different Charsets and/or lcid's.
extern "C" ERRORCODE APIENTRY ScanDisplayText(HHILITER hhil, PBYTE pbText, int cbText,
UINT iCharset, LCID lcid)
{
if (!CHiliter::ValidObject(hhil)) return NOT_HILITER;
// make sure we have a valid hiliter
ERRORCODE ec = ((CHiliter*)hhil)->ScanDisplayText(pbText, cbText, iCharset, lcid);
return ec; // .. and return any errors
}
// --------------------------------------------------------------------------
// ClearDisplayText discards the display text.
// It is not necessary to call this with a newly created Hiliter handle.
extern "C" ERRORCODE APIENTRY ClearDisplayText(HHILITER hhil)
{
if (!CHiliter::ValidObject(hhil)) return NOT_HILITER;
// make sure we have a valid hiliter
ERRORCODE ec = ((CHiliter*)hhil)->ClearDisplayText(); // if so, go down a level
return ec; // .. and return any errors
}
// --------------------------------------------------------------------------
// CountHilites returns the number of hilites for a specified byte offset range.
// If limit == -1 then the range will extend to the end of the buffer.
extern "C" int APIENTRY CountHilites(HHILITER hhil, int base, int limit)
{
if (!CHiliter::ValidObject(hhil)) return NOT_HILITER;
// make sure we have a valid hiliter
UINT count = ((CHiliter*)hhil)->CountHilites(base, limit);
return count; // .. and return the count
}
// --------------------------------------------------------------------------
// "QueryHilites" retrieves hilite information for the specified byte offset
// range. It returns the number of hilites for which information has been
// returned. cHilites and paHilites describe a buffer reserved for the
// returned hilite information. If limit == -1 the range will extend
// to the end of the buffer.
extern "C" int APIENTRY QueryHilites(HHILITER hhil, int base, int limit,
int cHilites, HILITE* paHilites)
{
if (!CHiliter::ValidObject(hhil)) return NOT_HILITER;
// make sure we have a valid hiliter
int count = ((CHiliter*)hhil)->QueryHilites(base, limit, cHilites, paHilites);
return count; // .. and return the count
}
// If you want to get the highlights sequentially you can use the above
// call in a loop as follows:
// while (TRUE) {
// if (QueryHilites(hhil, base, limit, 1, pHilite) != 1 ) break;
//
// // TODO -- your processing code
//
// base = pHilite->limit;
// }
///////////////////////////////////////////////////////////////////////////////