//********************************************************************************************************************************************* // // File: collect.h // Author: Donald Drake // Purpose: Defines classes to support titles, collections, locations and folders #ifndef _COLLECT_H #define _COLLECT_H #undef CLASS_IMPORT_EXPORT #ifdef HHCTRL // define this only when building the HHCtrl DLL #define CLASS_IMPORT_EXPORT /**/ #else #ifdef HHSETUP // define this only when building the HHSetup DLL #define CLASS_IMPORT_EXPORT __declspec( dllexport ) #else #define CLASS_IMPORT_EXPORT __declspec( dllimport ) #endif #endif #ifndef HHCTRL #undef COUNT #define COUNT(x) #undef MI_COUNT #define MI_COUNT(x) #undef SI_COUNT #define SI_COUNT(x) #undef MI2_COUNT #define MI2_COUNT(x) #undef AUTO_CLASS_COUNT_CHECK #define AUTO_CLASS_COUNT_CHECK(x) #undef CHECK_CLASS_COUNT #define CHECK_CLASS_COUNT(x) #undef DUMP_CLASS_COUNT #define DUMP_CLASS_COUNT(x) #endif #ifdef HHCTRL #include "parserhh.h" #else #include "parser.h" #endif #define F_MSDN 0x0001 #define F_TITLELOCAL 0x0002 #define F_INDEXLOCAL 0x0004 #define STARTINGCOLNO 10000 #define ENGLANGID 1033 #define MAX_LEVELS 100 typedef struct LocationHistory { CHAR * SampleLocation; CHAR * FileName; CHAR * IndexFileName; CHAR * QueryFileName; CHAR * LocationId; DWORD CollectionNumber; DWORD Version; DWORD LastPromptedVersion; BOOL bSupportsMerge; LocationHistory *pNext; CHAR * QueryLocation; } LOCATIONHISTORY; DWORD CLASS_IMPORT_EXPORT AllocSetValue(const CHAR *value, CHAR **dest); // forward declarations class CLocation; class CTitle; class CCollection; class CFolder; class CSlotLookupTable; class CExTitle; class CColList; typedef struct ListItem { void *pItem; ListItem *Next; } LISTITEM; class CLASS_IMPORT_EXPORT CPointerList { private: LISTITEM *m_pHead; public: CPointerList() { m_pHead = NULL; } ~CPointerList(); void RemoveAll(); LISTITEM *Add(void *); LISTITEM *First(); LISTITEM *Next(LISTITEM *p) { return p->Next; } }; #ifdef HHCTRL // define this only when building the HHCtrl DLL // // // This lookup table will facilitate a quick translation of a "slot" number into a CFolder* as well as a // HASH value into a CFolder*. This will be done using two DWORDS per CFolder object, one for the HASH value // and one for the CFolder*. After ALL the CFolders for a given collection have been created and this lookup // table is fully populated the SortAndAssignSlots() member will be called. This will sort the table by HASH // value and will assign the slot values back to the CFolders according to the sorted order. This will make // slot --> CFolder* lookup a simple array index and will also allow us to use a bsearch for the // HASH --> CFolder* lookup. Note that only leaf level CFolders have useful hash values, for the non leaf // CFolders we will assign a hash of -1, these items in the table will then appear at the end of the table // and will not interfear with a bsearch operation when translating a hash into a pSLT. // // class CSlotLookupTable { public: CSlotLookupTable(); ~CSlotLookupTable(); static int FASTCALL ltqs_callback(const void *elem1, const void *elem2); void AddValue(CFolder* pFolder); void SortAndAssignSlots(void); CFolder* HashToCFolder(HASH hash); CFolder* SlotToCFolder(DWORD dwSlot) { if ( dwSlot > 0 && dwSlot <= m_uiTotalCnt ) // Slot 0 reserved for error case. return m_pSLT[dwSlot].pCFolder; else return NULL; } private: struct _slt { HASH hash; CFolder* pCFolder; }; struct _slt* m_pSLT; unsigned m_uiTotalAllocated; unsigned m_uiTotalCnt; unsigned m_uiHashCnt; }; #endif class CLASS_IMPORT_EXPORT CFolder SI_COUNT(CFolder) { private: CHAR *Title; // name of the folder WCHAR *pwcTitle; DWORD Order; LANGID LangId; DWORD dwSlot; CExTitle* pExTitle; CFolder *pNext, *pKid, *pParent; // // This DWORD value is being added to support .CHM level subsetting. // WORD iLevel; WORD f_Filter: 1; // render into filter LB. WORD f_Available: 1; // render into Available LB. WORD f_F_Open: 1; // Expanded or closed ? WORD f_A_Open: 1; // Expanded or closed ? WORD f_HasHash: 1; // Does Node have a prefix hash ? WORD f_IsOrphan: 1; // Is this node an orphane ? WORD f_IsVisable: 1; // Indicates membership in the currently selected TOC subset. public: CFolder(); ~CFolder(); BOOL bIsVisable() { return (BOOL)f_IsVisable; } void SetTitle(const CHAR *); void SetTitle(const WCHAR *); void SetExTitlePtr(CExTitle* pTitle); CHAR *GetTitle() { return Title; } const WCHAR *GetTitleW(); void SetLanguage(LANGID Id) { LangId = Id; } LANGID GetLanguage() { return LangId; } void SetOrder(DWORD); DWORD GetOrder(); // Returns the next sibling folder given a folder entry CFolder * GetNextFolder(); void SetNextFolder(CFolder *p) { pNext = p; } // Returns the first child of a given folder if it exists CFolder * GetFirstChildFolder(); void SetFirstChildFolder(CFolder *p) { pKid = p; } // Add a new folder as child of a given folder CFolder * AddChildFolder(const CHAR *szName, DWORD Order, DWORD *pError, LANGID LangId = ENGLANGID); CFolder * AddChildFolder(const WCHAR *szName, DWORD Order, DWORD *pError, LANGID LangId = ENGLANGID); DWORD AddChildFolder(CFolder *newFolder); void SetParent(CFolder *p) { pParent = p; } CFolder * GetParent() { return pParent; } friend class CSlotLookupTable; friend class CDefineSS; friend class CStructuralSubset; }; class CLASS_IMPORT_EXPORT CCollection SI_COUNT(CCollection) { public: CCollection(); ~CCollection(); void ConfirmTitles() { m_bConfirmTitles = TRUE; } void SetSampleLocation(const CHAR *); CHAR *GetSampleLocation(); void SetMasterCHM(const CHAR *szName, LANGID Lang); BOOL GetMasterCHM(CHAR ** szName, LANGID *Lang); // Opens and loads the contents of the file into data structures DWORD Open(const CHAR * FileName); void SetSampleLocation(const WCHAR *); void SetFindMergedCHMS(BOOL bFind) { m_bFindMergedChms = bFind; } BOOL GetFindMergedCHMS() { return m_bFindMergedChms; } const WCHAR *GetSampleLocationW(); void SetMasterCHM(const WCHAR *szName, LANGID Lang); BOOL GetMasterCHM(WCHAR ** szName, LANGID *Lang); // Opens and loads the contents of the file into data structures DWORD Open(const WCHAR * FileName); // Saves any changes made to the internal data structures to the file. DWORD Save(); DWORD Close(); void AddRef() { m_dwRef++; } DWORD GetVersion() { return m_dwVersion; } void SetVersion(DWORD dw) { m_dwVersion = dw; } // navigating the collection // Returns the first folder in the collection CFolder * GetRootFolder() { return m_pRootFolder; } CFolder * GetVisableRootFolder() { return m_pRootFolder->GetFirstChildFolder(); } // Returns the visable root. // Returns the first title CTitle * GetFirstTitle(); // Locates a title based on id CTitle * FindTitle(const CHAR * Id, LANGID LangId = ENGLANGID); CTitle * FindTitle(const WCHAR * Id, LANGID LangId = ENGLANGID); // Try multiple LangIds, before failing. #ifdef HHCTRL CTitle * FindTitleNonExact(const CHAR * Id, LANGID LangId) ; #endif // #ifdef HHCTRL // Returns the first location CLocation* FirstLocation(); // Finds a location based on a name CLocation * FindLocation(const CHAR * Name, UINT* puiVolumeOrder = NULL ); // collection entry management CColList * FindCollection(CHAR *szFileName); CColList * AddCollection(); void RemoveCollectionEntry(CHAR *szFileName); //Adds a new folder to the top level of the table of contents, with the given name and order and returns a pointer to that folder object. A return of NULL indicates a failure and pDWORD will be populated with one of above DWORD codes. CFolder * AddFolder(const CHAR * szName, DWORD Order, DWORD *pDWORD, LANGID LangId = ENGLANGID); DWORD DeleteFolder(CFolder *); //Adds a title based on the provided information. //A return of NULL indicates a failure and pDWORD will be //populated with one of above DWORD codes. Note: you must add or //find a CLocation object or pass null to indication no location is in // use (local file). CTitle * AddTitle(const CHAR * Id, const CHAR * FileName, const CHAR * IndexFile, const CHAR * Query, const CHAR *SampleLocation, LANGID Lang, UINT uiFlags, CLocation *pLocation, DWORD *pDWORD, BOOL bSupportsMerge = FALSE, const CHAR *QueryLocation = NULL); // Adds location based on the given information. A return of NULL indicates a failure and pDWORD will be populated with one of above DWORD codes. CLocation * AddLocation(const CHAR * Title, const CHAR * Path, const CHAR * Id, const CHAR * Volume, DWORD *pDWORD); CLocation * FindLocation(const WCHAR * Name, UINT* puiVolumeOrder = NULL ); CFolder * AddFolder(const WCHAR * szName, DWORD Order, DWORD *pDWORD, LANGID LangId = ENGLANGID); CTitle * AddTitle(const WCHAR * Id, const WCHAR * FileName, const WCHAR * IndexFile, const WCHAR * Query, const WCHAR *SampleLocation, LANGID Lang, UINT uiFlags, CLocation *pLocation, DWORD *pDWORD, BOOL bSupportsMerge = FALSE, const WCHAR *QueryLocation = NULL); CLocation * AddLocation(const WCHAR * Title, const WCHAR * Path, const WCHAR * Id, const WCHAR * Volume, DWORD *pDWORD); DWORD RemoveCollection(BOOL bRemoveLocalFiles = FALSE); DWORD GetRefTitleCount() { return m_dwTitleRefCount; } // Merges the currently installed titles for the collection into the specified filename (path determined internally) BOOL MergeKeywords(CHAR * pwzFilename ); BOOL MergeKeywords(WCHAR * pwzFilename ); DWORD GetColNo() { return m_dwColNo; } PCSTR GetCollectionFileName(void) { return m_szFileName; } const WCHAR *GetCollectionFileNameW(void); BOOL IsDirty() { return m_bDirty;} void IncrementRefTitleCount() { m_dwTitleRefCount++; } void DecrementRefTitleCount() { m_dwTitleRefCount--; } void Dirty() { m_bDirty = TRUE; } LANGID GetLangId(const CHAR *FileName); LANGID GetLangId(const WCHAR *FileName); private: // functions DWORD AddRefedTitle(CFolder *pFolder); // removing objects DWORD DeleteTitle(CTitle *); void DeleteLocalFiles(LOCATIONHISTORY *pHist, CTitle *pTitle); DWORD DeleteLocation(CLocation *); DWORD CheckTitleRef(const CHAR *pId, const LANGID Lang); DWORD CheckTitleRef(const WCHAR *pId, const LANGID Lang); DWORD ParseFile(const CHAR *FileName); DWORD HandleCollection(CParseXML *parser, CHAR *sz); DWORD HandleCollectionEntry(CParseXML *parser, CHAR *sz); DWORD HandleFolder(CParseXML *parser, CHAR *token); DWORD HandleLocation(CParseXML *parser, CHAR *token); DWORD HandleTitle(CParseXML *parser, CHAR *token); void DeleteChildren(CFolder **p); void DeleteFolders(CFolder **p); BOOL WriteFolders(CFolder **p); BOOL WriteFolder(CFolder **p); DWORD AllocCopyValue(CParseXML *parser, CHAR *token, CHAR **dest); CTitle *NewTitle(); CLocation *NewLocation(); private: BOOL m_bRemoveLocalFiles; BOOL m_bRemoved; DWORD Release(); CHAR * m_szFileName; WCHAR * m_pwcFileName; CHAR * m_szMasterCHM; WCHAR * m_pwcMasterCHM; CHAR * m_szSampleLocation; WCHAR * m_pwcSampleLocation; LANGID m_MasterLangId; CTitle * m_pFirstTitle; CTitle * m_pTitleTail; CLocation * m_pFirstLocation; CLocation * m_pLocationTail; CFolder *m_pRootFolder; DWORD m_locationnum; CFIFOString m_Strings; CFolder *m_pParents[MAX_LEVELS]; DWORD m_dwCurLevel; DWORD m_dwLastLevel; DWORD m_dwNextColNo; DWORD m_dwColNo; DWORD m_dwTitleRefCount; BOOL m_bConfirmTitles; BOOL m_bFindMergedChms; DWORD m_dwRef; DWORD m_dwVersion; HANDLE m_fh; BOOL m_bDirty; CColList *m_pColListHead; CColList *m_pColListTail; public: CPointerList m_RefTitles; BOOL m_bFailNoFile; BOOL m_bAllFilesDeleted; }; class CColList { private: DWORD m_dwColNo; CHAR * m_szFileName; CColList *m_pNext; public: CColList(); ~CColList(); void SetColNo(DWORD dw) { m_dwColNo = dw; } void SetFileName(CHAR *szFileName); DWORD GetColNo() { return m_dwColNo; } CHAR *GetFileName() { return m_szFileName; } CColList *GetNext() { return m_pNext; } void SetNext(CColList *p) { m_pNext = p; } }; class CLASS_IMPORT_EXPORT CTitle SI_COUNT(CTitle) { private: CHAR * Id; // Title identifier WCHAR *pwcId; LANGID Language; // language identifier CTitle *NextTitle; // pointer to the next title public: LOCATIONHISTORY *m_pHead, *m_pTail; void SetId(const CHAR *); void SetId(const WCHAR *); void SetLanguage(LANGID); CHAR * GetId(); const WCHAR * GetIdW(); LANGID GetLanguage(); LOCATIONHISTORY *GetLocation(DWORD Index); CTitle* GetNextTitle(); ~CTitle(); CTitle(); LOCATIONHISTORY *NewLocationHistory(); DWORD AddLocationHistory(DWORD ColNo, const CHAR *FileName, const CHAR *IndexFile, const CHAR *Query, const CLocation *pLocation, const CHAR *Sample, const CHAR *QueryLocation, BOOL bSupportsMerge); DWORD AddLocationHistory(DWORD ColNo, const WCHAR *FileName, const WCHAR *IndexFile, const WCHAR *Query, const CLocation *pLocation, const WCHAR *Sample, const WCHAR *QueryLocation, BOOL bSupportsMerge); void SetNextTitle(CTitle *p) { NextTitle = p; } }; class CLASS_IMPORT_EXPORT CLocation SI_COUNT(CLocation) { private: CHAR * Id; CHAR * Title; // Friendly name for the title CHAR * Path; // location of the device CHAR * Volume; WCHAR * pwcId; WCHAR * pwcTitle; // Friendly name for the title WCHAR * pwcPath; // location of the device WCHAR * pwcVolume; CLocation *NextLocation; // pointer to the next location if it exists public: DWORD m_ColNum; CLocation() { Id = NULL; Title = NULL; Path = NULL; Volume = NULL; NextLocation = NULL; pwcId = NULL; pwcTitle = NULL; pwcPath = NULL; pwcVolume = NULL; } ~CLocation() { if (Id) delete Id; if (Title) delete Title; if (Path) delete Path; if (Volume) delete Volume; if (pwcId) delete pwcId; if (pwcTitle) delete pwcTitle; if (pwcPath) delete pwcPath; if (pwcVolume) delete pwcVolume; } void SetNextLocation(CLocation *p) { NextLocation = p; } void SetId(const CHAR *); void SetTitle(const CHAR *); void SetPath(const CHAR *); void SetVolume(const CHAR *); CHAR * GetId() const; CHAR * GetTitle(); CHAR * GetPath(); CHAR * GetVolume(); void SetId(const WCHAR *); void SetTitle(const WCHAR *); void SetPath(const WCHAR *); void SetVolume(const WCHAR *); const WCHAR * GetIdW(); const WCHAR * GetTitleW(); const WCHAR * GetPathW(); const WCHAR * GetVolumeW(); // Returns the next location CLocation *GetNextLocation(); }; #endif