/* * 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. */ /* LDCONTEXT.C ----------------------------------------- * @doc * @module LDCONTEXT.C | * * Handling of CONTEXT-File * * Loads CONTEXT-File into main memory and does a qsort * of the Data by TopicOffset-Values to support * Generation of #-Footnotes * * Help Access Library Project. * *-----------------------------------------------------*/ #include #include #include #include #include #include #include "hlpacces.h" #include "top.h" void LOCAL nEnumeratePage(NPIFSFILE ifsfile, int PageCount, int CurrentLevel, int PageSize, int CurrPage, LPCONTEXTARRAY lpContextArray); int _USERENTRY ContextSort(const void *a, const void *b); /* iContextLoad * * Load the Table of Context ID Entries */ void iContextLoad(NPTOPIC topic) /* Load Fonts-Table */ { BTREEHEADER BTreeHdr; UINT PageCount; NPIFSFILE ifsfile = IFSOpenFile(topic->ifs, "|CONTEXT"); if (ifsfile) { //--------- Read Title B-Tree header ------------------ IFSReadFile(ifsfile, &BTreeHdr, sizeof(BTreeHdr)); PageCount = (UINT) (IFSSeekFile(ifsfile, 0L, 2)/leword(BTreeHdr.PageSize)); topic->ContextArray = (LPCONTEXTARRAY) Hlpcalloc(sizeof(CONTEXTARRAY),1); if (topic->ContextArray && NULL!=(topic->ContextArray->Context=Hlpmalloc(ledword(BTreeHdr.TotalBtreeEntries) * sizeof(CONTEXTREC))) ) { topic->ContextArray->ContextAllocated=ledword(BTreeHdr.TotalBtreeEntries); nEnumeratePage(ifsfile, PageCount, leword(BTreeHdr.NLevels)-1, leword(BTreeHdr.PageSize), leword(BTreeHdr.RootPage), topic->ContextArray); } IFSCloseFile(ifsfile); qsort(topic->ContextArray->Context, topic->ContextArray->ContextCount, sizeof(CONTEXTREC), ContextSort); topic->contents = iReadContentsFile(topic->ifs); } } int _USERENTRY ContextSort(const void *va, const void *vb) { CONTEXTREC FAR *a=(CONTEXTREC FAR *)va, FAR *b=(CONTEXTREC FAR *)vb; # ifdef __WIN32__ return ledword(a->TopicOffset) - ledword(b->TopicOffset); # else return ledword(a->TopicOffset) > ledword(b->TopicOffset) ? 1 : ledword(a->TopicOffset) == ledword(b->TopicOffset) ? 0 : -1 ; # endif } int _USERENTRY ContextFind(const void *va, const void *vb) { CONTEXTREC FAR *a=(CONTEXTREC FAR *)va, FAR *b=(CONTEXTREC FAR *)vb; DWORD toa = ledword(a->TopicOffset); DWORD tob = ledword(b->TopicOffset); return abs(toa-tob)<3 ? 0 : ContextSort(va, vb); } /* iContextFree * * Free up memory allocates for Context-table */ void iContextFree(NPTOPIC topic) /* Free Memory used by Fonts-Table */ { if (topic->ContextArray) { if (topic->ContextArray->Context!=NULL) Hlpfree(topic->ContextArray->Context); Hlpfree(topic->ContextArray); topic->ContextArray=NULL; if (topic->contents != NULL) { iFreeContentsFile(topic->contents); } } } #pragma pack(1) typedef struct { LEWORD PageNo; LEDWORD HashValue; } PACKED BTREEINDEXENTRY; #pragma pack() void LOCAL nEnumeratePage(NPIFSFILE ifsfile, int PageCount, int CurrentLevel, int PageSize, int CurrPage, LPCONTEXTARRAY lpContextArray) { DWORD loc = sizeof(BTREEHEADER) + PageSize * (DWORD) CurrPage; NPSTR page = (NPSTR) LocalAlloc(LPTR, PageSize); BTREENODEHEADER NodeHeader; BTREEINDEXENTRY NEAR *CurrIndexEntry; int i; if (page) { //----------- Read Page ---------------------------------------- IFSSeekFile(ifsfile, loc, 0); if (PageSize == IFSReadFile(ifsfile, page, PageSize)) { memcpy(&NodeHeader, page, sizeof(NodeHeader)); //--------- Are we in a Node or in a leaf? ------------------- if (CurrentLevel > 0) { //-- We're in a node, search for next sub-node or leaf -- for (i=0, CurrIndexEntry = (BTREEINDEXENTRY NEAR *) (page+sizeof(BTREEINDEXHEADER)); iPageNo), lpContextArray); } else { //--------- Copy Page Contents ---- -------------------------- memcpy(lpContextArray->Context + lpContextArray->ContextCount, page+sizeof(BTREENODEHEADER), leword(NodeHeader.NEntries) * sizeof(CONTEXTREC)); lpContextArray->ContextCount += leword(NodeHeader.NEntries); } } //----------- Free Page data except Header --------------------- LocalFree((HLOCAL) page); } } /* iContextFind * * Look if there is a Context-Id connected to this TopicOffset * * Returns a Pointer to a strdup-ed memory Buffer */ LPSTR iContextFind(NPTOPIC topic, DWORD TopicOffset) { CONTEXTREC FAR *lpContextRec, SearchForRec; LPSTR lpszResult=NULL; if (topic->ContextArray) { // SearchForRec.TopicOffset = TopicOffset; SearchForRec.TopicOffset.d1 = (TopicOffset >> 0) & 0xff; SearchForRec.TopicOffset.d2 = (TopicOffset >> 8) & 0xff; SearchForRec.TopicOffset.d3 = (TopicOffset >> 16) & 0xff; SearchForRec.TopicOffset.d4 = (TopicOffset >> 24) & 0xff; lpContextRec = bsearch(&SearchForRec, topic->ContextArray->Context, topic->ContextArray->ContextCount, sizeof(CONTEXTREC), ContextFind); if (lpContextRec) { /* WOW! found a Context-Record ... */ /* Try to find a context ID matching this hash value */ if (topic->contents) { lpszResult = iContentsFromHash(topic->contents, ledword(lpContextRec->HashValue)); } /* Nothing available in the .cnt file, use a generated hash-value */ if (!lpszResult) { char buf[500]; HlpCreateStringForHashValue(ledword(lpContextRec->HashValue), buf); lpszResult = Hlpstrdup(buf); } } } return lpszResult; } /* HlpTopicFindContextIdForTopicOffset * * Find a context Id matching the given Topic Offset * * @param htopic Handle to the topic file opened using the HTO_CONTEXT flag * @param TopicOffset TopicOffset we need a name for * * @return String with the context-ID retrieved. NULL if none found. * The string needs to be released with a call to Hlpfree(...) */ LPSTR WINAPI HlpTopicFindContextIdForTopicOffset(HTOPIC htopic, DWORD TopicOffset) { return iContextFind(htopic, TopicOffset); }