// 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 #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