/* * Help Access Library * A Library to access the contents of Windows Help files. * * Copyright (C) 1995-2000 Bernd Herd, http://www.herdsoft.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* IFS.C ---------------------------------------------- * @doc * @module istopic.c | * Code to search for the Existence of a specified * Context-String in the CONTEXT internal help file. * * Help Access Library Project. * *-----------------------------------------------------*/ #include #include #include #include #include "hlpacces.h" DWORD LOCAL nFindHash(NPIFSFILE ifsfile, LONG HashCode); /* @func BOOL | HlpIsTopic | * * Tests if the given Hash-Code is in the list * of hash-Codes in the given File. * * Hash-Codes are 32-Bit values generated from Context-Strings (#-Footnotes) * by a call to * * The hash-Codes are to be found in the internal * CONTEXT-File which is organized as a simple B-Tree * * @rdesc TopicOffset Value, or 0xffffffff if not found. * @xref , , */ DWORD WINAPI DLLEXP HlpIsTopic( HIFS ifs, // @parm Handle of an open File-System returned by DWORD HashCode) // @parm Hash-Code for a contextr string, retrieved by { NPIFSFILE ifsfile = IFSOpenFile(ifs, "|CONTEXT"); DWORD rtn = 0xffffffffL; if (ifsfile) { rtn = nFindHash(ifsfile, HashCode); IFSCloseFile(ifsfile); } return rtn; } #ifdef OBSOLETE BOOL LOCAL nFindHash(NPIFSFILE ifsfile, LONG HashCode) { NPSTR buf; BTREEHEADER BTreeHdr; BTREENODEHEADER NEAR *CurrNode; BOOL found = FALSE; LONG near * nxt; int Direction = 1; int CurrPage, i; //------------ Read in the BTREEHEADER so we know the Page size ------------ IFSReadFile(ifsfile, &BTreeHdr, sizeof(BTreeHdr)); buf = (NPSTR) LocalAlloc(LPTR, BTreeHdr.PageSize); // Buffer for one Page CurrNode = (BTREENODEHEADER NEAR *)buf; /* Current Node in B-Tree */ CurrPage = BTreeHdr.RootPage; if (buf) { //---------- First we have to scan for the right Page -------- while (!found && Direction && CurrPage>=0 ) { //-------- Read in a Page ---------------------------------- IFSSeekFile(ifsfile, sizeof(BTREEHEADER)+CurrPage * BTreeHdr.PageSize, SEEK_SET); IFSReadFile(ifsfile, buf, BTreeHdr.PageSize); //-------- Search for our Data in the Page ----------------- nxt = (LONG near *) (buf+sizeof(BTREENODEHEADER)); nxt++; nxt--; Direction = HashCompare(*nxt, HashCode); if (Direction>0) { CurrPage=CurrNode->PreviousPage; } else { for (i=0; iNEntries && Direction<0; ++i) { Direction = HashCompare(*nxt, HashCode); nxt+=2; // LONG, not bytes ;-) } if (!Direction) found = TRUE; else if (Direction>0) CurrPage=-1; else CurrPage=CurrNode->NextPage; } } LocalFree((HLOCAL) buf); } return found; } #endif /* @func BOOL | IsTopic | * * Tests if a given Help file contains a given Context-String * (#-Footnote). * * @rdesc Indicates if the Context-String * @flag TRUE | The file contains such a Topic * @flag FALSE| The file does not exist, is no help file or does not contain such a topic * @comm Lower/Upper case do not care. * @comm The context-String might either be defined in a popup or topic, * in the middle of a Topic or at the start of a topic... * @xref */ BOOL WINAPI DLLEXP IsTopic( LPCSTR FileName, // @parm Pointer to Filename of the help file LPCSTR ContextString) // @parm Pointer to Context-String, i.e. IDH_CONTENTS { NPIFS ifs; BOOL rtn=FALSE; ifs = IFSOpen(FileName); if (ifs) { rtn = HlpIsTopic(ifs, HlpGenerateHashValue(ContextString))!=0xffffffffL; IFSClose(ifs); } return rtn; } #pragma pack(1) typedef struct { LEWORD PageNo; LEDWORD HashCode; } PACKED BTREEINDEXENTRY; typedef struct { LEDWORD HashCode; LEDWORD TopicOffset; } PACKED BTREELEAFENTRY; #pragma pack() /* nFindHash * * Scans B-Tree Data for a givem Context-String */ DWORD LOCAL nFindHash(NPIFSFILE ifsfile, LONG HashCode) { NPSTR buf; BTREEHEADER BTreeHdr; BTREENODEHEADER NEAR *CurrNode; BTREEINDEXENTRY NEAR *CurrIndexEntry; BTREELEAFENTRY NEAR *CurrLeafEntry; DWORD found = 0xffffffffL; int CurrPage, NLevels, i; //------------ Read in the BTREEHEADER so we know the Page size ------------ IFSReadFile(ifsfile, &BTreeHdr, sizeof(BTreeHdr)); buf = (NPSTR) LocalAlloc(LPTR, leword(BTreeHdr.PageSize)); // Buffer for one Page CurrNode = (BTREENODEHEADER NEAR *)buf; /* Current Node in B-Tree */ CurrPage = leword(BTreeHdr.RootPage); if (buf) { NLevels = leword(BTreeHdr.NLevels); while (NLevels-->=0 && CurrPage>=0 ) { //-------- Read in a Page ---------------------------------- IFSSeekFile(ifsfile, sizeof(BTREEHEADER)+CurrPage * leword(BTreeHdr.PageSize), SEEK_SET); IFSReadFile(ifsfile, buf, leword(BTreeHdr.PageSize)); //-------- In node or leaf ? ------------------------------- if (NLevels>0) { //-- We're in a node, search for next sub-node or leaf -- for (i=0, CurrIndexEntry = (BTREEINDEXENTRY NEAR *) (buf+sizeof(BTREEINDEXHEADER)); iNEntries)&&ledword(CurrIndexEntry->HashCode) < HashCode; ++i ,++CurrIndexEntry) ; CurrPage=leword(CurrIndexEntry->PageNo); } else { //-- We're in the right leaf now, scan for Data --------- for (i=0, CurrLeafEntry = (BTREELEAFENTRY NEAR *) (buf+sizeof(BTREENODEHEADER)); iNEntries)&&ledword(CurrLeafEntry->HashCode) < HashCode; ++i ,++CurrLeafEntry) ; found = ledword(CurrLeafEntry->HashCode) == HashCode ? ledword(CurrLeafEntry->TopicOffset) : 0xffffffffL; } } LocalFree((HLOCAL) buf); } return found; }