/* * 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. */ /* LDKW.C ---------------------------------------------- * @doc * @module LDKW.C | * * Loads all Keywords-Positioning Informations into * Main Memory and does a qsort * of the Data by TopicOffset-Values to support * Generation of K-Footnotes * * Not Based on * * Help Access Library Project. * *-----------------------------------------------------*/ #include #include #include #include #include #include #include "hlpacces.h" #include "top.h" #pragma pack(1) typedef struct { LEWORD Count; LEDWORD DataOffset; } PACKED KWTREEREC, NEAR *NPKWTREEREC; #pragma pack() void LOCAL nKeyWordLoad(HTOPIC topic, LPCSTR szTableName); BOOL LOCAL nEnumerateKeyWords(HIFSFILE hKWBTree, HIFSFILE hKWData, LPKWARRAY lpKWArry); BOOL LOCAL nEnumeratePage(HIFSFILE hKWBTree, HIFSFILE hKWData, int CurrentLevel, int PageSize, int CurrPage, LPKWARRAY lpKWArry); void LOCAL nNewKWRec(HIFSFILE hKWData, LPKWARRAY lpKWArry, NPKWTREEREC npKWRec, DWORD loc); int _USERENTRY KWSort(const void *va, const void *vb); /* iKeyWordsLoad * * Load the Table of KeyWord Positions */ void iKeyWordsLoad(NPTOPIC topic) /* Load Fonts-Table */ { int i; char szTableName[7]; for (i='A';i<='Z';++i) { wsprintf(szTableName,"%c",i); nKeyWordLoad(topic, szTableName); } for (i=0;i<9;++i) { wsprintf(szTableName,"%dK",i); nKeyWordLoad(topic, szTableName); } } void LOCAL nKeyWordLoad(HTOPIC topic, LPCSTR szTableName) { char szWBTreeName[20], szWDataName[20]; HIFSFILE hWBTree, hWData; LPKWARRAY lpKWArray; wsprintf(szWBTreeName, "|%sWBTREE", szTableName); wsprintf(szWDataName , "|%sWDATA" , szTableName); hWData = IFSOpenFile(topic->ifs, szWDataName); if (hWData) { hWBTree = IFSOpenFile(topic->ifs, szWBTreeName); if (hWBTree) { /* Table does exist, register it */ topic->KWArry = topic->KWArry ? (LPKWARRAY *) Hlprealloc(topic->KWArry, (topic->KWArryCount+1) * sizeof(LPKWARRAY)) : (LPKWARRAY *) Hlpmalloc ( (topic->KWArryCount+1) * sizeof(LPKWARRAY)); topic->KWArry[topic->KWArryCount++]=lpKWArray=(KWARRAY *) Hlpcalloc(sizeof(KWARRAY),1); lstrcpy(lpKWArray->KWTableName, szTableName); nEnumerateKeyWords(hWBTree, hWData, lpKWArray); qsort(lpKWArray->KWRec, lpKWArray->KWCount, sizeof(KWREC), KWSort); // IFSCloseFile(hWData); lpKWArray->hWBTree=hWBTree; } IFSCloseFile(hWData); } } int _USERENTRY KWSort(const void FAR *va, const void FAR *vb) { const LPKWREC a=(LPKWREC) va, b=(LPKWREC) vb; # ifdef __WIN32__ return a->TopicOffset - b->TopicOffset; # else return a->TopicOffset > b->TopicOffset ? 1 : a->TopicOffset == b->TopicOffset ? 0 : -1 ; # endif } /* iKeyWordsFree * * Free up memory allocates for font-table */ void iKeyWordsFree(NPTOPIC topic) /* Free Memory used by Fonts-Table */ { int i; if (topic->KWArry) { for (i=0;iKWArryCount; ++i) { Hlpfree (topic->KWArry[i]->KWRec); IFSCloseFile(topic->KWArry[i]->hWBTree); Hlpfree (topic->KWArry[i]); } Hlpfree(topic->KWArry); topic->KWArry=NULL; } } /* nEnumerateKeywords * * Does the bunch of Work to do enumeration */ BOOL LOCAL nEnumerateKeyWords(HIFSFILE hKWBTree, HIFSFILE hKWData, LPKWARRAY lpKWArry) { BOOL Success; BTREEHEADER BTreeHdr; //--------- Read Title B-Tree header ------------------ IFSReadFile(hKWBTree, &BTreeHdr, sizeof(BTreeHdr)); Success = nEnumeratePage(hKWBTree, hKWData, leword(BTreeHdr.NLevels)-1, leword(BTreeHdr.PageSize), leword(BTreeHdr.RootPage), lpKWArry); return Success; } BOOL LOCAL nEnumeratePage(HIFSFILE hKWBTree, HIFSFILE hKWData, int CurrentLevel, int PageSize, int CurrPage, LPKWARRAY lpKWArry) { BOOL Success = TRUE; DWORD loc = sizeof(BTREEHEADER) + PageSize * (DWORD) CurrPage; NPSTR page = (NPSTR) LocalAlloc(LPTR, PageSize), nxt; NPKWTREEREC npKWRec; BTREENODEHEADER NEAR *CurrNode = (BTREENODEHEADER NEAR *)page; /* Current Node in B-Tree */ int i; if (page) { //----------- Read Page ---------------------------------------- IFSSeekFile(hKWBTree, loc, 0); if (PageSize == IFSReadFile(hKWBTree, page, PageSize)) { if (CurrentLevel > 0) { //-- We're in a node, search for next sub-node or leaf -- for (i=0, nxt = page+sizeof(BTREEINDEXHEADER); iNEntries)+1; ++i, nxt+=lstrlen(nxt+2)+1+sizeof(WORD)) //------- We're currently in a node, so recurse down... ---- Success = nEnumeratePage(hKWBTree, hKWData, CurrentLevel-1, PageSize, CurrPage=leword(((LEWORD NEAR *) (nxt))[0]), lpKWArry); } else { //-- We're in the right leaf now, scan for Data --------- for (i=0, nxt = page+sizeof(BTREENODEHEADER); iNEntries); ++i ,nxt+=lstrlen(nxt)+1+sizeof(KWTREEREC)) { npKWRec=(NPKWTREEREC)(nxt+lstrlen(nxt)+1); nNewKWRec(hKWData, lpKWArry, npKWRec, loc+(nxt-page)); } } } else Success=FALSE; //----------- Free Page data except Header --------------------- LocalFree((HLOCAL) page); } else Success = FALSE; return Success; } /* nNewKWREc * * Add new KeyWord-Record to KeyWord Table */ void LOCAL nNewKWRec(HIFSFILE hKWData, LPKWARRAY lpKWArry, NPKWTREEREC npKWRec, DWORD KeyWordOffset) { int i; LPKWREC lpKWRec; IFSSeekFile(hKWData, ledword(npKWRec->DataOffset), SEEK_SET); for (i=0;iCount);++i) { if (lpKWArry->KWCount >= lpKWArry->KWAllocated) { lpKWArry->KWAllocated+=1000; lpKWArry->KWRec = lpKWArry->KWRec!=NULL ? (KWREC *) Hlprealloc(lpKWArry->KWRec, lpKWArry->KWAllocated * sizeof(KWREC)) : (KWREC *) Hlpmalloc ( lpKWArry->KWAllocated * sizeof(KWREC)); } lpKWRec = lpKWArry->KWRec+(lpKWArry->KWCount)++; IFSReadFile(hKWData, &lpKWRec->TopicOffset, sizeof(DWORD)); lpKWRec->KeyWordOffset = KeyWordOffset; } } /* iKeyWordsForTopic * * Transfer all Keywords of all KeyWord-Tables defined to the Topic-Enumeration function */ void iKeyWordsForTopic(HTOPIC topic, TOPICENUMPROC fnenum, DWORD TopicOffset, LPARAM lParam) { int KWTable; LPKWARRAY lpKWArry; KWREC FAR *lpKWRec, SearchForRec; LPBYTE KWBuf=Hlpmalloc(1024), p; if (topic->KWArry && KWBuf) { for (KWTable=0; KWTableKWArryCount; ++KWTable) { lpKWArry=topic->KWArry[KWTable]; SearchForRec.TopicOffset = TopicOffset; lpKWRec = bsearch(&SearchForRec, lpKWArry->KWRec, lpKWArry->KWCount, sizeof(KWREC), KWSort); if (lpKWRec) { /* Delicious, we've found a Keyword ... */ /* if there is more than one matching entry, bsearch might return any of them. Go backwards to the start of that array */ while (lpKWRec > lpKWArry->KWRec && lpKWRec[-1].TopicOffset == TopicOffset) lpKWRec--; /* Enumerate that Keyword... */ while (lpKWRec->TopicOffset == TopicOffset && (lpKWRec-lpKWArry->KWRec)KWCount) { IFSSeekFile(lpKWArry->hWBTree, lpKWRec->KeyWordOffset, SEEK_SET); wsprintf((LPSTR)KWBuf, "%s\t", lpKWArry->KWTableName); IFSReadFile(lpKWArry->hWBTree, KWBuf+lstrlen((LPSTR)KWBuf), 999); p=KWBuf; iTopicString(topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_KEYWORD); ++lpKWRec; } } } } Hlpfree(KWBuf); }