427 lines
14 KiB
C
427 lines
14 KiB
C
|
// Copyright (C) Microsoft Corporation 1996-1997, All Rights reserved.
|
||
|
|
||
|
//*********************************************************************************************************************************************
|
||
|
//
|
||
|
// File: toc.h
|
||
|
// Author: Donald Drake
|
||
|
// Purpose: Defines classes to support populating the table of contents
|
||
|
|
||
|
#if _MSC_VER > 1000
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
#ifndef _TOC_H
|
||
|
#define _TOC_H
|
||
|
#include "cinfotyp.h"
|
||
|
#include "system.h"
|
||
|
#include "collect.h"
|
||
|
#include "hhtypes.h"
|
||
|
#include "fs.h"
|
||
|
#include "subfile.h"
|
||
|
#include "state.h"
|
||
|
|
||
|
#include "csubset.h"
|
||
|
//#include "subset.h" // Structural subsets
|
||
|
#include "hhfinder.h"
|
||
|
|
||
|
#define MAX_OPEN_TITLES 25
|
||
|
|
||
|
//#define DUMPTOC 1
|
||
|
#ifdef DUMPTOC
|
||
|
#include <stdio.h>
|
||
|
#endif
|
||
|
|
||
|
// Persist keys. Declared in toc.cpp
|
||
|
//
|
||
|
extern const char g_szFTSKey[];
|
||
|
extern const char g_szIndexKey[];
|
||
|
extern const char g_szTOCKey[];
|
||
|
|
||
|
class CExTitle;
|
||
|
class CExFolderNode;
|
||
|
class CExTitleNode;
|
||
|
class CExMergedTitleNode;
|
||
|
class CExNode;
|
||
|
class CTreeNode;
|
||
|
class CFullTextSearch;
|
||
|
class CTitleFTS;
|
||
|
class CSearchHighlight;
|
||
|
class CPagedSubfile;
|
||
|
class CTitleDatabase;
|
||
|
class CSSList;
|
||
|
|
||
|
extern CExCollection* g_pCurrentCollection;
|
||
|
|
||
|
//[ZERO IDXHDR] The IDX Header subfile may be zero length, because some early version of HHCTRL
|
||
|
// didn't write it out. We need to make sure that we have an IDX header before we try to use it.
|
||
|
// If we don't we will crash.
|
||
|
#define IDXHEADER_UNINITIALIZED (0xFFFFFFFF)
|
||
|
|
||
|
//class CExTitle: public CSubfileGroupList
|
||
|
class CExTitle SI_COUNT(CExTitle)
|
||
|
{
|
||
|
friend class CPagedSubfile;
|
||
|
|
||
|
public:
|
||
|
void _CExTitle();
|
||
|
CExTitle(CTitle* p, DWORD ColNo, CExCollection* pCollection);
|
||
|
CExTitle(const CHAR* pszFileName, CExCollection* pCollection);
|
||
|
~CExTitle();
|
||
|
|
||
|
inline BOOL Init() { int bReturn = TRUE; if( !isOpen() ) bReturn = OpenTitle(); return bReturn; }
|
||
|
inline CTitleInformation* GetInfo() { if( Init() ) return m_pInfo; else return NULL; }
|
||
|
inline CTitleInformation2* GetInfo2() { return m_pInfo2; }
|
||
|
inline BOOL isOpen(void) { return m_bOpen; }
|
||
|
inline CFileSystem* GetTitleIdxFileSystem(void) { if(!m_bOpen) OpenTitle(); return m_pCFileSystem; }
|
||
|
inline void SetNodeOffsetInParentTitle(DWORD dw) { m_dwNodeOffsetInParentTitle = dw;}
|
||
|
inline DWORD GetNodeOffsetInParentTitle() { return m_dwNodeOffsetInParentTitle; }
|
||
|
inline CExTitle* GetNext() { return m_pNext; }
|
||
|
inline void SetNext(CExTitle* p) { m_pNext = p; }
|
||
|
|
||
|
IDXHEADER* GetIdxHeaderStruct() { ASSERT(IsIdxHeaderValid()); return m_pIdxHeader;}
|
||
|
DWORD GetTopicCount() { ASSERT(IsIdxHeaderValid()); return m_pIdxHeader->cTopics;}
|
||
|
BOOL IsIdxHeaderValid() { if(m_pIdxHeader) return (BOOL)m_pIdxHeader->cTopics; else return FALSE; }
|
||
|
CTitle* GetCTitle() { return m_pTitle; }
|
||
|
CFileSystem* GetFileSystem(void) { return m_pCFileSystem; }
|
||
|
LOCATIONHISTORY* GetUsedLocation() { return m_pUsedLocation; }
|
||
|
BOOL isChiFile(void) { return m_fIsChiFile; }
|
||
|
|
||
|
const unsigned int* GetITBits(DWORD dwOffsBits);
|
||
|
BOOL OpenTitle();
|
||
|
void CloseTitle();
|
||
|
BOOL exOpenFile(const CHAR* pszContent, const CHAR* pszIndex = NULL);
|
||
|
BOOL InfoTypeFilter(CSubSet* pSubSet, DWORD dwTopic);
|
||
|
|
||
|
const unsigned int* GetTopicITBits(DWORD dwTN);
|
||
|
|
||
|
HRESULT GetRootNode(TOC_FOLDERNODE* pNode);
|
||
|
DWORD GetRootSlot(void);
|
||
|
HRESULT GetNode(DWORD iNode, TOC_FOLDERNODE* pNode);
|
||
|
const CHAR* GetFileName();
|
||
|
const CHAR* GetPathName();
|
||
|
const CHAR* GetQueryName();
|
||
|
const CHAR* GetIndexFileName();
|
||
|
const CHAR* GetCurrentAttachmentName();
|
||
|
const CHAR* SetCurrentAttachmentName( const CHAR* pszAttachmentPathName );
|
||
|
|
||
|
HRESULT GetTopicName( DWORD dwTopic, CHAR* pszTitle, int cb );
|
||
|
HRESULT GetTopicName( DWORD dwTopic, WCHAR* pwszTitle, int cch );
|
||
|
|
||
|
HRESULT GetTopicLocation(DWORD dwTopic, CHAR* pszLocation, int cb);
|
||
|
HRESULT GetTopicLocation(DWORD dwTopic, WCHAR* pwszLocation, int cch);
|
||
|
|
||
|
HRESULT GetUrlTocSlot(const CHAR* pszURL, DWORD* pdwSlot, DWORD* pdwTopicNumber);
|
||
|
HRESULT GetTopicURL(DWORD dwTopic, CHAR* pszURL, int cb, BOOL bFull = TRUE );
|
||
|
|
||
|
const CHAR* GetString( DWORD dwOffset );
|
||
|
HRESULT GetString( DWORD dwOffset, CStr* pcsz );
|
||
|
HRESULT GetString( DWORD dwOffset, CHAR* psz, int cb );
|
||
|
HRESULT GetString( DWORD dwOffset, CWStr* pcsz );
|
||
|
HRESULT GetString( DWORD dwOffset, WCHAR* pwsz, int cb );
|
||
|
|
||
|
HRESULT GetURLTreeNode(const CHAR* pszURL, CTreeNode** ppTreeNode, BOOL b = TRUE);
|
||
|
HRESULT GetVolumeOrder( UINT* puiVolumeOrder, UINT uiFileType = HHRMS_TYPE_TITLE );
|
||
|
|
||
|
HRESULT ConvertURL( const CHAR* pszURLIn, CHAR* pszURLOut );
|
||
|
HRESULT Slot2TreeNode(DWORD dwSlot, CTreeNode** ppTreeNode);
|
||
|
HRESULT URL2Topic(const CHAR* pszURL, TOC_TOPIC* pTopic, DWORD* pdwTN = NULL);
|
||
|
BOOL FindUsedLocation();
|
||
|
BOOL EnsureChmChiMatch( CHAR* pszChm = NULL );
|
||
|
HRESULT ResolveContextId(DWORD id, CHAR** ppszURL);
|
||
|
|
||
|
inline CStr& GetContentFileName() { return m_ContentFileName; }
|
||
|
|
||
|
// data members should always be private!
|
||
|
|
||
|
CTitleFTS* m_pTitleFTS;
|
||
|
CTitle* m_pTitle;
|
||
|
CExCollection* m_pCollection;
|
||
|
HASH m_dwHash;
|
||
|
int m_ITCnt;
|
||
|
//
|
||
|
// Support for VB style "super chms"
|
||
|
//
|
||
|
CExTitle* m_pKid;
|
||
|
CExTitle* m_pNextKid;
|
||
|
CExTitle* m_pParent;
|
||
|
|
||
|
private:
|
||
|
HRESULT GetTopicData(DWORD dwTopic, TOC_TOPIC* pTopicData);
|
||
|
|
||
|
CStr m_ContentFileName;
|
||
|
CStr m_IndexFileName;
|
||
|
|
||
|
TOCIDX_HDR* m_pHeader; // Header of #TOCIDX system subfile.
|
||
|
IDXHEADER* m_pIdxHeader; // Global header information for entire .CHM/.CHI file.
|
||
|
LOCATIONHISTORY* m_pUsedLocation;
|
||
|
BOOL m_bOpen;
|
||
|
CExTitle* m_pNext;
|
||
|
DWORD m_dwColNo;
|
||
|
DWORD m_dwNodeOffsetInParentTitle;
|
||
|
BOOL m_fIsChiFile;
|
||
|
BOOL m_bIsValidTitle;
|
||
|
BOOL m_bChiChmChecked;
|
||
|
MAPPED_ID* m_pMapIds;
|
||
|
int m_cMapIds;
|
||
|
//
|
||
|
// Tome FS object (.chm/.chi) and Cached subfile objects.
|
||
|
//
|
||
|
CFileSystem* m_pCFileSystem;
|
||
|
CPagedSubfile* m_pTocNodes;
|
||
|
CPagedSubfile* m_pTopics;
|
||
|
CPagedSubfile* m_pStrTbl;
|
||
|
CPagedSubfile* m_pUrlTbl;
|
||
|
CPagedSubfile* m_pUrlStrings;
|
||
|
CPagedSubfile* m_pITBits;
|
||
|
|
||
|
CTitleInformation* m_pInfo;
|
||
|
CTitleInformation2* m_pInfo2;
|
||
|
|
||
|
UINT m_uiVolumeOrder;
|
||
|
char m_szAttachmentPathName[MAX_PATH];
|
||
|
|
||
|
};
|
||
|
|
||
|
class CExCollection SI_COUNT(CExCollection)
|
||
|
{
|
||
|
public:
|
||
|
CExCollection(CHmData* phmData, const CHAR* pszFile, BOOL bSingleTitle = TRUE);
|
||
|
virtual ~CExCollection();
|
||
|
|
||
|
BOOL InitCollection();
|
||
|
#ifdef CHIINDEX
|
||
|
BOOL InitCollection( const TCHAR * FullPath, const TCHAR * szMasterChmFn );
|
||
|
#endif
|
||
|
BOOL InitFTSKeyword();
|
||
|
CHmData* m_phmData;
|
||
|
DWORD GetRefedTitleCount();
|
||
|
|
||
|
BOOL IsBinaryTOC(const CHAR* pszToc);
|
||
|
void GetOpenSlot(CExTitle* p);
|
||
|
CTreeNode* GetRootNode();
|
||
|
CTreeNode* GetPrev(CTreeNode* pTreeNode, DWORD* pdwSlot = NULL);
|
||
|
CTreeNode* GetNext(CTreeNode* pTreeNode, DWORD* pdwSlot = NULL);
|
||
|
CTreeNode* GetNextTopicNode(CTreeNode* pTreeNode, DWORD* pdwSlot = NULL);
|
||
|
HRESULT Sync(CPointerList* pHier, const CHAR* pszURL = NULL);
|
||
|
HRESULT GetCurrentTocNode(CTreeNode** ppTreeNode) { if (m_pCurrTitle) return m_pCurrTitle->Slot2TreeNode(m_dwCurrSlot, ppTreeNode); else return E_FAIL ;}
|
||
|
CExTitle* GetFirstTitle() { return m_pHeadTitles; }
|
||
|
CExTitle* GetMasterTitle() { return m_pMasterTitle; }
|
||
|
CExTitle* GetCurSyncExTitle() { return m_pCurrTitle; }
|
||
|
CExTitle* FindTitle(const CHAR* pszId, LANGID LangId);
|
||
|
|
||
|
// Try multiple LangIds before failing
|
||
|
CExTitle* FindTitleNonExact(const CHAR* pszId, LANGID LangId);
|
||
|
|
||
|
CLocation* FindLocation(CHAR* pszId);
|
||
|
void CheckForTitleChild(CFolder* p, BOOL *pbFound);
|
||
|
CTreeNode* CheckForTitleNode(CFolder* );
|
||
|
void GetMergedTitles(CExTitle* );
|
||
|
BOOL IsSingleTitle() { return m_bSingleTitle; }
|
||
|
CFolder* FindTitleFolder(CExTitle* pTitle);
|
||
|
const CHAR* GetPathName() const {
|
||
|
return m_phmData->GetCompiledFile(); }
|
||
|
HRESULT URL2ExTitle(const CHAR* pszURL, CExTitle** ppTitle);
|
||
|
|
||
|
const CHAR* GetUserCHSLocalStoragePathnameByLanguage();
|
||
|
const CHAR* GetUserCHSLocalStoragePathname();
|
||
|
const CHAR* GetLocalStoragePathname( const CHAR* pszExt );
|
||
|
BOOL UpdateLocation( const CHAR* pszLocId, const CHAR* pszNewPath, const CHAR* pszNewVolume = NULL, const CHAR* pszNewTitle = NULL);
|
||
|
void GetChildURLS(CTreeNode* pNode, CTable *pTable);
|
||
|
void UpdateTopicSlot(DWORD dwSlot, DWORD dwTN, CExTitle* pTitle);
|
||
|
void SetTopicSlot(DWORD dwSlot, DWORD dwTN, CExTitle* pTitle) { m_dwCurrSlot = (dwSlot ? dwSlot : m_dwCurrSlot), m_dwCurrTN = dwTN, m_pCurrTitle = pTitle ? pTitle : m_pCurrTitle; }
|
||
|
CExTitle* TitleFromChmName(const CHAR* pszChmName);
|
||
|
void InitStructuralSubsets(void);
|
||
|
|
||
|
//
|
||
|
// State API's
|
||
|
//
|
||
|
CState* GetState(void) { return m_pstate; }
|
||
|
HRESULT OpenState(const CHAR* pszName, DWORD dwAccess = (STGM_READWRITE | STGM_SHARE_DENY_WRITE)) { return m_pstate->Open(pszName, dwAccess); }
|
||
|
void CloseState(void) { m_pstate->Close(); }
|
||
|
HRESULT ReadState(void* pData, DWORD cb, DWORD* pcbRead) { return m_pstate->Read(pData, cb, pcbRead); }
|
||
|
DWORD WriteState(const void* pData, DWORD cb) { return m_pstate->Write(pData, cb); }
|
||
|
|
||
|
// data members should always be private!
|
||
|
|
||
|
CFullTextSearch* m_pFullTextSearch;
|
||
|
CSearchHighlight* m_pSearchHighlight;
|
||
|
CTitleDatabase* m_pDatabase;
|
||
|
CSubSets *m_pSubSets; // SubSets of information types, instantiated in system.cpp::ReadSystemFiles()
|
||
|
CSSList* m_pSSList; // List of structural subsets.
|
||
|
CSlotLookupTable* m_pCSlt; // Pointer to the slot lookup table.
|
||
|
CCollection m_Collection;
|
||
|
CStr m_csFile;
|
||
|
|
||
|
private:
|
||
|
const CHAR* SetWordWheelPathname( const CHAR* pszWordWheelPathname );
|
||
|
CTreeNode* GetLastChild(CTreeNode* pTreeNode, DWORD* pdwSlot = NULL);
|
||
|
BOOL ValidateTitle(CExTitle* pExTitle, BOOL bDupCheckOnly = FALSE);
|
||
|
|
||
|
CExTitle* m_pHeadTitles;
|
||
|
CExTitle* m_pMasterTitle;
|
||
|
BOOL m_bSingleTitle;
|
||
|
CHAR* m_szWordWheelPathname;
|
||
|
CExTitle* m_MaxOpenTitles[MAX_OPEN_TITLES];
|
||
|
DWORD m_dwLastSlot;
|
||
|
//
|
||
|
// Topic centricity work below. !!!! Don't ever even consider relying on m_pCurrTitle for any thing !!!!
|
||
|
// this is only here to make make topic centricity work more robustly.
|
||
|
//
|
||
|
DWORD m_dwCurrSlot;
|
||
|
DWORD m_dwCurrTN;
|
||
|
CExTitle* m_pCurrTitle;
|
||
|
//
|
||
|
// Support for persistance via hh.dat
|
||
|
//
|
||
|
CState* m_pstate;
|
||
|
|
||
|
#ifdef DUMPTOC
|
||
|
void DumpNode(CTreeNode**);
|
||
|
|
||
|
FILE* m_fh;
|
||
|
BOOL m_bRoot;
|
||
|
DWORD m_dwLevel;
|
||
|
#endif
|
||
|
|
||
|
};
|
||
|
|
||
|
class CSubSet;
|
||
|
|
||
|
#define EXFOLDERNODE 1
|
||
|
#define EXTITLENODE 2
|
||
|
#define EXNODE 3
|
||
|
#define EXMERGEDNODE 4
|
||
|
|
||
|
class CTreeNode SI_COUNT(CTreeNode)
|
||
|
{
|
||
|
public:
|
||
|
CTreeNode();
|
||
|
virtual ~CTreeNode();
|
||
|
|
||
|
BYTE GetObjType() { return m_ObjType; }
|
||
|
void SetObjType(BYTE x) { m_ObjType = x; }
|
||
|
virtual DWORD GetType() = 0;
|
||
|
|
||
|
virtual HRESULT GetTopicName( CHAR* pszTitle, int cb ) = 0;
|
||
|
virtual HRESULT GetTopicName( WCHAR* pwszTitle, int cch ) = 0;
|
||
|
|
||
|
virtual CTreeNode* GetFirstChild(DWORD* pdwSlot = NULL) = 0;
|
||
|
virtual CTreeNode* GetNextSibling(TOC_FOLDERNODE* pAltNode = NULL, DWORD* pdwSlot = NULL) = 0;
|
||
|
virtual CTreeNode* GetParent(DWORD* pdwSlot = NULL, BOOL bDirectParent = FALSE) = 0;
|
||
|
virtual BOOL HasChildren() = 0;
|
||
|
inline virtual BOOL IsNew() { return FALSE; }
|
||
|
virtual BOOL GetURL(CHAR* pszURL, unsigned cb, BOOL bFull = TRUE);
|
||
|
DWORD GetLastError();
|
||
|
CTreeNode* GetExNode(TOC_FOLDERNODE* pNode, CExTitle* pTitle);
|
||
|
BOOL Compare(CTreeNode* pOtherNode);
|
||
|
|
||
|
// data members should always be private!
|
||
|
|
||
|
BYTE m_Expanded;
|
||
|
|
||
|
private:
|
||
|
void SetError(DWORD dw);
|
||
|
|
||
|
BYTE m_ObjType;
|
||
|
DWORD m_Error;
|
||
|
};
|
||
|
|
||
|
//The GetType function can return one of the follow defines:
|
||
|
#define VIRTUALROOT 0 // a node that contains the top level nodes of the tree, not part of the tree
|
||
|
#define XMLFOLDER 1 // a folder defined in the collection file
|
||
|
#define TITLE 2 // a title which is leaf node of the xml tree
|
||
|
#define FOLDER 3 // a folder defined in a title
|
||
|
#define CONTAINER 4 // a folder that is also a topic
|
||
|
#define TOPIC 5 // a topic
|
||
|
#define BOGUS_FOLDER 6 // a folder that is not a topic and has no kids. Bogus!
|
||
|
|
||
|
class CExFolderNode : MI_COUNT(CExFolderNode)
|
||
|
public CTreeNode
|
||
|
{
|
||
|
public:
|
||
|
CExFolderNode( CFolder*, CExCollection* );
|
||
|
virtual ~CExFolderNode();
|
||
|
|
||
|
inline virtual DWORD GetType() { return XMLFOLDER; }
|
||
|
|
||
|
virtual HRESULT GetTopicName( CHAR* pszTitle, int cb );
|
||
|
virtual HRESULT GetTopicName( WCHAR* pwszTitle, int cch );
|
||
|
|
||
|
inline virtual BOOL HasChildren() { return TRUE; }
|
||
|
virtual CTreeNode* GetFirstChild(DWORD* pdwSlot);
|
||
|
virtual CTreeNode* GetNextSibling(TOC_FOLDERNODE* pAltNode = NULL, DWORD* pdwSlot = NULL);
|
||
|
virtual CTreeNode* GetParent(DWORD* pdwSlot = NULL, BOOL bDirectParent = FALSE);
|
||
|
inline CFolder* GetFolder() { return m_pFolder; }
|
||
|
|
||
|
private:
|
||
|
CFolder* m_pFolder;
|
||
|
CExCollection* m_pCollection;
|
||
|
};
|
||
|
|
||
|
class CExTitleNode : // MI_COUNT(CExTitleNode)
|
||
|
public CTreeNode
|
||
|
{
|
||
|
public:
|
||
|
CExTitleNode( CExTitle* , CFolder* );
|
||
|
// virtual ~CExTitleNode();
|
||
|
|
||
|
inline virtual DWORD GetType() { return TITLE; }
|
||
|
|
||
|
inline virtual HRESULT GetTopicName( CHAR* pszTitle, int cb ) { return NULL; }
|
||
|
inline virtual HRESULT GetTopicName( WCHAR* pwszTitle, int cch ) { return NULL; }
|
||
|
|
||
|
virtual CTreeNode* GetFirstChild(DWORD* pdwSlot = NULL);
|
||
|
virtual CTreeNode* GetNextSibling(TOC_FOLDERNODE* pAltNode = NULL, DWORD* pdwSlot = NULL);
|
||
|
virtual CTreeNode* GetParent(DWORD* pdwSlot = NULL, BOOL bDirectParent = FALSE);
|
||
|
inline virtual BOOL HasChildren() { return TRUE; }
|
||
|
CExTitle* GetTitle() { return m_pTitle; }
|
||
|
CFolder* GetFolder() { return m_pFolder; }
|
||
|
|
||
|
private:
|
||
|
CFolder* m_pFolder;
|
||
|
CExTitle* m_pTitle;
|
||
|
};
|
||
|
|
||
|
class CExNode : MI_COUNT(CExNode)
|
||
|
public CTreeNode
|
||
|
{
|
||
|
public:
|
||
|
CExNode(TOC_FOLDERNODE* p, CExTitle* pTitle);
|
||
|
// virtual ~CExNode();
|
||
|
|
||
|
virtual BOOL GetURL(CHAR* pszURL, unsigned cb, BOOL bFull = TRUE);
|
||
|
virtual DWORD GetType();
|
||
|
|
||
|
virtual HRESULT GetTopicName( CHAR* pszTitle, int cb );
|
||
|
virtual HRESULT GetTopicName( WCHAR* pwszTitle, int cch );
|
||
|
|
||
|
virtual CTreeNode* GetFirstChild(DWORD* pdwSlot = NULL);
|
||
|
virtual CTreeNode* GetNextSibling(TOC_FOLDERNODE* pAltNode = NULL, DWORD* pdwSlot = NULL);
|
||
|
virtual CTreeNode* GetParent(DWORD* pdwSlot = NULL, BOOL bDirectParent = FALSE);
|
||
|
inline virtual BOOL HasChildren() { return m_Node.dwFlags & TOC_HAS_CHILDREN; }
|
||
|
inline virtual BOOL IsNew() { return m_Node.dwFlags & TOC_NEW_NODE; }
|
||
|
inline CExTitle* GetTitle() { return m_pTitle; }
|
||
|
|
||
|
// data members should always be private!
|
||
|
|
||
|
TOC_FOLDERNODE m_Node;
|
||
|
|
||
|
private:
|
||
|
CExTitle* m_pTitle;
|
||
|
};
|
||
|
|
||
|
class CExMergedTitleNode : MI_COUNT(CExMergedTitleNode)
|
||
|
public CExNode
|
||
|
{
|
||
|
public:
|
||
|
CExMergedTitleNode( TOC_FOLDERNODE* pFolderNode, CExTitle* pTitle );
|
||
|
virtual ~CExMergedTitleNode();
|
||
|
|
||
|
inline virtual DWORD GetType() { return TITLE; }
|
||
|
virtual CTreeNode* GetFirstChild( DWORD* pdwSlot = NULL );
|
||
|
};
|
||
|
|
||
|
// Helper functions
|
||
|
|
||
|
#endif // _TOC_H
|