windows-nt/Source/XPSP1/NT/enduser/stuff/hhctrl/toc.h
2020-09-26 16:20:57 +08:00

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