2970 lines
71 KiB
C++
2970 lines
71 KiB
C++
//*********************************************************************************************************************************************
|
|
//
|
|
// File: collect.cpp
|
|
// Author: Donald Drake
|
|
// Purpose: Implements classes to support collections
|
|
|
|
#include "header.h"
|
|
#include "string.h"
|
|
#ifdef HHCTRL
|
|
#include "parserhh.h"
|
|
#include "toc.h"
|
|
#else
|
|
#include "stdio.h"
|
|
#include "windows.h"
|
|
#include "parser.h"
|
|
extern DWORD GetTitleVersion(const CHAR *szFileName);
|
|
extern LANGID GetLangId(const CHAR *szFileName);
|
|
#endif
|
|
#include "collect.h"
|
|
|
|
// Use CRT version in hhsetup
|
|
|
|
// Instance count checking:
|
|
AUTO_CLASS_COUNT_CHECK(CFolder);
|
|
AUTO_CLASS_COUNT_CHECK(CTitle);
|
|
|
|
#ifndef HHCTRL
|
|
#define Atoi atoi
|
|
#undef _splitpath
|
|
#endif
|
|
|
|
char gszColReg[MAX_PATH];
|
|
WCHAR *CreateUnicodeFromAnsi(LPSTR psz);
|
|
|
|
class CAnsi {
|
|
public:
|
|
char *m_pszChar;
|
|
CAnsi(WCHAR *);
|
|
~CAnsi();
|
|
operator CHAR *() { return (CHAR *) m_pszChar; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Helper functions
|
|
DWORD AllocSetValue(const CHAR *value, CHAR **dest)
|
|
{
|
|
if (*dest)
|
|
delete [] *dest;
|
|
|
|
// REVIEW: confirm that len gets optimized out of existence
|
|
|
|
int len = strlen(value) + 1;
|
|
|
|
*dest = new CHAR[len];
|
|
|
|
if (*dest == NULL)
|
|
return F_MEMORY;
|
|
|
|
strcpy(*dest, value);
|
|
return F_OK;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CPointerList implementation
|
|
void foo(void)
|
|
{
|
|
|
|
}
|
|
|
|
void CPointerList::RemoveAll()
|
|
{
|
|
LISTITEM *p;
|
|
|
|
while (m_pHead)
|
|
{
|
|
p = m_pHead->Next;
|
|
delete m_pHead;
|
|
m_pHead = p;
|
|
}
|
|
}
|
|
|
|
CPointerList::~CPointerList()
|
|
{
|
|
RemoveAll();
|
|
}
|
|
|
|
LISTITEM *CPointerList::Add(void *p)
|
|
{
|
|
LISTITEM *pItem = new LISTITEM;
|
|
|
|
if (pItem)
|
|
{
|
|
pItem->pItem = p;
|
|
pItem->Next = m_pHead;
|
|
m_pHead = pItem;
|
|
return pItem;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LISTITEM *CPointerList::First()
|
|
{
|
|
return m_pHead;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CColList implementation
|
|
|
|
CColList::CColList()
|
|
{
|
|
m_dwColNo = 0;
|
|
m_szFileName = NULL;
|
|
m_pNext = NULL;
|
|
}
|
|
|
|
void CColList::SetFileName(CHAR *sz)
|
|
{
|
|
if (sz)
|
|
AllocSetValue(sz, &m_szFileName);
|
|
}
|
|
|
|
CColList::~CColList()
|
|
{
|
|
if (m_szFileName)
|
|
delete m_szFileName;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CCollection implementation
|
|
|
|
CCollection::CCollection()
|
|
{
|
|
m_bRemoved = FALSE;
|
|
m_pwcSampleLocation = NULL;
|
|
m_pwcMasterCHM = NULL;
|
|
m_bFailNoFile = FALSE;
|
|
m_bDirty = FALSE;
|
|
m_szSampleLocation = NULL;
|
|
m_szFileName = NULL;
|
|
m_pwcFileName = NULL;
|
|
m_szMasterCHM = NULL;
|
|
m_pFirstTitle = NULL;
|
|
m_pTitleTail = NULL;
|
|
m_pColListHead = NULL;
|
|
m_pColListTail = NULL;
|
|
m_pLocationTail = NULL;
|
|
m_pFirstLocation = NULL;
|
|
m_pRootFolder = NULL;
|
|
m_locationnum = 0;
|
|
m_dwNextColNo = 1;
|
|
m_dwColNo = 0;
|
|
m_dwTitleRefCount = 0;
|
|
m_dwRef = 0;
|
|
m_dwVersion = 0;
|
|
m_bFindMergedChms = FALSE;
|
|
for (int i = 0; i < MAX_LEVELS; i++)
|
|
m_pParents[i] = NULL;
|
|
|
|
m_dwCurLevel = 0;
|
|
m_dwLastLevel = 0;
|
|
m_bConfirmTitles = FALSE;
|
|
m_MasterLangId = ENGLANGID;
|
|
gszColReg[0] = NULL;
|
|
#ifdef HHSETUP
|
|
CoInitialize(NULL);
|
|
#endif
|
|
}
|
|
|
|
CCollection::~CCollection()
|
|
{
|
|
Close();
|
|
#ifdef HHSETUP
|
|
CoUninitialize();
|
|
#endif
|
|
}
|
|
|
|
DWORD CCollection::Release()
|
|
{
|
|
if (m_dwRef == 0)
|
|
return 0;
|
|
m_dwRef--;
|
|
return m_dwRef;
|
|
}
|
|
|
|
void CCollection::DeleteChildren(CFolder **p)
|
|
{
|
|
if (!p || !(*p))
|
|
return;
|
|
|
|
CFolder *pChild, *pNext;
|
|
if (pChild = (*p)->GetFirstChildFolder())
|
|
DeleteChildren(&pChild);
|
|
pNext = (*p)->GetNextFolder();
|
|
delete (*p);
|
|
*p = NULL;
|
|
do {
|
|
if (pNext)
|
|
DeleteChildren(&pNext);
|
|
} while (pNext && (pNext = pNext->GetNextFolder()));
|
|
}
|
|
|
|
void CCollection::SetSampleLocation(const CHAR *sz)
|
|
{
|
|
if (!sz)
|
|
return;
|
|
Dirty();
|
|
AllocSetValue(sz, &m_szSampleLocation);
|
|
}
|
|
|
|
CHAR *CCollection::GetSampleLocation()
|
|
{
|
|
return m_szSampleLocation;
|
|
}
|
|
|
|
|
|
BOOL CCollection::GetMasterCHM(CHAR **szName, LANGID *pLang)
|
|
{
|
|
*pLang = m_MasterLangId;
|
|
*szName = m_szMasterCHM;
|
|
if (m_szMasterCHM == NULL)
|
|
return FALSE;
|
|
return ((strlen(m_szMasterCHM) ? TRUE : FALSE));
|
|
}
|
|
|
|
void CCollection::SetMasterCHM(const CHAR *sz, LANGID lang)
|
|
{
|
|
if (!sz)
|
|
return;
|
|
Dirty();
|
|
m_MasterLangId = lang;
|
|
AllocSetValue(sz, &m_szMasterCHM);
|
|
}
|
|
|
|
// Opens and loads the contents of the file into data structures
|
|
DWORD CCollection::Open(const CHAR * FileName)
|
|
{
|
|
DWORD dw;
|
|
BOOL bOld = FALSE;
|
|
BOOL bTryAgain = FALSE;
|
|
if (m_pRootFolder == NULL)
|
|
{
|
|
m_pRootFolder = new CFolder;
|
|
if (m_pRootFolder == NULL)
|
|
return F_MEMORY;
|
|
m_pParents[0] = m_pRootFolder;
|
|
}
|
|
|
|
CHAR szBuffer[MAX_PATH];
|
|
const CHAR *sz = szBuffer;
|
|
BOOL bNewPath;
|
|
HHGetGlobalCollectionPathname(szBuffer, sizeof(szBuffer), &bNewPath);
|
|
|
|
dw = ParseFile(sz);
|
|
|
|
#ifdef HHCTRL // hhsetup should only be concerned about the good location for this file
|
|
if (dw == F_NOFILE && bNewPath)
|
|
{
|
|
// try windows dir for backward compatibity
|
|
try_again:
|
|
bNewPath=FALSE;
|
|
HHGetOldGlobalCollectionPathname(szBuffer, sizeof(szBuffer));
|
|
dw = ParseFile(sz);
|
|
bOld = TRUE;
|
|
}
|
|
#endif
|
|
|
|
if (dw != F_OK && dw != F_NOFILE)
|
|
return dw;
|
|
|
|
if (dw == F_NOFILE && m_bFailNoFile)
|
|
return F_NOFILE;
|
|
|
|
// save the hhcolreg file and path for save calls...
|
|
strcpy(gszColReg, sz);
|
|
|
|
if (bNewPath && m_dwNextColNo < STARTINGCOLNO)
|
|
m_dwNextColNo += STARTINGCOLNO;
|
|
|
|
|
|
if (FileName)
|
|
dw = ParseFile(FileName);
|
|
|
|
if (dw != F_OK && dw != F_NOFILE)
|
|
return dw;
|
|
|
|
if (dw == F_NOFILE && m_bFailNoFile)
|
|
return F_NOFILE;
|
|
|
|
// now that we moved the file, if we did not get any titles found for the collection at runtime
|
|
// and we have not looked at the old hhcolreg location let try it.
|
|
|
|
#ifdef HHCTRL // runtime only, I really hate this
|
|
if (m_RefTitles.First() == NULL && bOld == FALSE && bTryAgain == FALSE)
|
|
{
|
|
Close();
|
|
ConfirmTitles();
|
|
m_bFailNoFile = TRUE;
|
|
bTryAgain = TRUE;
|
|
if (m_pRootFolder == NULL)
|
|
{
|
|
m_pRootFolder = new CFolder;
|
|
if (m_pRootFolder == NULL)
|
|
return F_MEMORY;
|
|
m_pParents[0] = m_pRootFolder;
|
|
}
|
|
goto try_again;
|
|
}
|
|
|
|
// did we find any titles that matched
|
|
if (m_RefTitles.First() == NULL)
|
|
{
|
|
return F_REFERENCED;
|
|
}
|
|
#endif
|
|
|
|
|
|
dw = AllocSetValue(FileName, &m_szFileName);
|
|
|
|
m_bDirty = FALSE;
|
|
|
|
CColList *pCol;
|
|
|
|
if ((pCol = FindCollection(m_szFileName)) == NULL)
|
|
{
|
|
// collection has never been added
|
|
pCol = AddCollection();
|
|
pCol->SetFileName(m_szFileName);
|
|
#ifdef HHCTRL
|
|
if (m_dwColNo)
|
|
pCol->SetColNo(m_dwColNo);
|
|
else
|
|
{
|
|
pCol->SetColNo(m_dwNextColNo);
|
|
m_dwNextColNo++;
|
|
if (bNewPath && m_dwNextColNo < STARTINGCOLNO)
|
|
m_dwNextColNo += STARTINGCOLNO;
|
|
}
|
|
#else
|
|
pCol->SetColNo(m_dwNextColNo);
|
|
m_dwNextColNo++;
|
|
if (bNewPath && m_dwNextColNo < STARTINGCOLNO)
|
|
m_dwNextColNo += STARTINGCOLNO;
|
|
#endif
|
|
m_bDirty = TRUE;
|
|
}
|
|
m_dwColNo = pCol->GetColNo();
|
|
|
|
return dw;
|
|
}
|
|
|
|
CColList * CCollection::FindCollection(CHAR *szFileName)
|
|
{
|
|
CColList *p = m_pColListHead;
|
|
while (p)
|
|
{
|
|
if (stricmp(p->GetFileName(), szFileName) == 0)
|
|
return p;
|
|
p = p->GetNext();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
CColList * CCollection::AddCollection()
|
|
{
|
|
|
|
CColList *newCol = new CColList;
|
|
if (!newCol)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (m_pColListHead == NULL)
|
|
{
|
|
m_pColListHead = newCol;
|
|
}
|
|
else
|
|
{
|
|
m_pColListTail->SetNext(newCol);
|
|
}
|
|
m_pColListTail = newCol;
|
|
return newCol;
|
|
}
|
|
|
|
void CCollection::RemoveCollectionEntry(CHAR *szFileName)
|
|
{
|
|
CColList *p = m_pColListHead;
|
|
CColList *pPrev = NULL;
|
|
while (p)
|
|
{
|
|
if (stricmp(p->GetFileName(), szFileName) == 0)
|
|
{
|
|
if (pPrev)
|
|
{
|
|
pPrev->SetNext(p->GetNext());
|
|
}
|
|
else
|
|
{
|
|
m_pColListHead = p->GetNext();
|
|
}
|
|
if (m_pColListTail == p)
|
|
m_pColListTail = pPrev;
|
|
delete p;
|
|
break;
|
|
}
|
|
pPrev = p;
|
|
p = p->GetNext();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DWORD CCollection::AllocCopyValue(CParseXML *parser, CHAR *token, CHAR **dest)
|
|
{
|
|
CHAR *sz;
|
|
|
|
if (!parser || !token || !dest)
|
|
return F_NULL;
|
|
|
|
sz = parser->GetValue(token);
|
|
if (*dest)
|
|
delete [] *dest;
|
|
|
|
int len = strlen(sz) + 1;
|
|
|
|
*dest = new CHAR[len];
|
|
if (*dest == NULL)
|
|
return F_MEMORY;
|
|
|
|
strcpy(*dest, sz);
|
|
return F_OK;
|
|
}
|
|
|
|
DWORD CCollection::ParseFile(const CHAR *FileName)
|
|
{
|
|
CParseXML parser;
|
|
CHAR *token;
|
|
CHAR *sz;
|
|
DWORD dw;
|
|
|
|
if (!FileName)
|
|
return F_NULL;
|
|
|
|
if ((dw = parser.Start(FileName)) != F_OK)
|
|
return dw;
|
|
|
|
|
|
for (token = parser.GetToken(); token;)
|
|
{
|
|
if (token[0] == '/')
|
|
{
|
|
dw = m_Strings.GetTail(&sz);
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
if (strcmp(sz, &token[1]) != 0)
|
|
{
|
|
parser.End();
|
|
delete sz;
|
|
return F_TAGMISSMATCH;
|
|
}
|
|
delete sz;
|
|
if (strcmp(token, "/Folder") == 0)
|
|
m_dwCurLevel--;
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "XML") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "Collections") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "Collection") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
if ((dw = HandleCollectionEntry(&parser, token)) != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "HTMLHelpCollection") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
if ((dw = HandleCollection(&parser, token)) != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "NextCollectionId") == 0)
|
|
{
|
|
m_dwNextColNo = atoi(parser.GetValue(token));
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "Folders") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "Folder") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
if ((dw = HandleFolder(&parser, token)) != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "HTMLHelpDocInfo") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "Locations") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (stricmp(parser.GetFirstWord(token), "Location") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
if ((dw = HandleLocation(&parser, token)) != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
continue;
|
|
}
|
|
else if (strcmp(parser.GetFirstWord(token), "DocCompilations") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
continue;
|
|
}
|
|
else if (strcmp(parser.GetFirstWord(token), "DocCompilation") == 0)
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
if ((dw = HandleTitle(&parser, token)) != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
dw = m_Strings.AddTail(parser.GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
token = parser.GetToken();
|
|
}
|
|
}
|
|
|
|
// make sure all tags have been popped
|
|
dw = F_OK;
|
|
while (m_Strings.GetTail(&sz) == F_OK)
|
|
{
|
|
delete sz;
|
|
dw = F_MISSINGENDTAG;
|
|
}
|
|
parser.End();
|
|
return dw;
|
|
}
|
|
DWORD CCollection::HandleCollectionEntry(CParseXML *parser, CHAR *token)
|
|
{
|
|
if (!parser || !token)
|
|
return F_NULL;
|
|
|
|
CColList *newCol = AddCollection();
|
|
|
|
if (!newCol)
|
|
{
|
|
return F_MEMORY;
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
token = parser->GetToken();
|
|
if (stricmp(parser->GetFirstWord(token), "colname") == 0)
|
|
{
|
|
newCol->SetFileName(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "colnum") == 0)
|
|
{
|
|
newCol->SetColNo( atoi(parser->GetValue(token)));
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return F_OK;
|
|
}
|
|
|
|
DWORD CCollection::HandleCollection(CParseXML *parser, CHAR *token)
|
|
{
|
|
if (!parser || !token)
|
|
return F_NULL;
|
|
|
|
while (TRUE)
|
|
{
|
|
token = parser->GetToken();
|
|
if (stricmp(parser->GetFirstWord(token), "homepage") == 0)
|
|
{
|
|
// need to be backward compatable with this tag
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "masterchm") == 0)
|
|
{
|
|
SetMasterCHM( parser->GetValue(token), ENGLANGID);
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "samplelocation") == 0)
|
|
{
|
|
SetSampleLocation( parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "masterlangid") == 0)
|
|
{
|
|
m_MasterLangId = (LANGID)atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "refcount") == 0)
|
|
{
|
|
m_dwRef = atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "version") == 0)
|
|
{
|
|
m_dwVersion = atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "showhomepage") == 0)
|
|
{
|
|
// need to be backward compatable with this tag
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "findmergedchms") == 0)
|
|
{
|
|
m_bFindMergedChms = atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "CollectionNum") == 0)
|
|
{
|
|
m_dwColNo = atoi(parser->GetValue(token));
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return F_OK;
|
|
}
|
|
|
|
DWORD CCollection::HandleFolder(CParseXML *parser, CHAR *token)
|
|
{
|
|
if (!parser || !token)
|
|
return F_NULL;
|
|
CFolder *newFolder = new CFolder;
|
|
if (newFolder == NULL)
|
|
return F_MEMORY;
|
|
|
|
m_dwCurLevel++;
|
|
while (TRUE)
|
|
{
|
|
token = parser->GetToken();
|
|
|
|
if (stricmp(parser->GetFirstWord(token), "TitleString") == 0)
|
|
{
|
|
newFolder->SetTitle(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "FolderOrder") == 0)
|
|
{
|
|
newFolder->SetOrder(atoi(parser->GetValue(token)));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "LangId") == 0)
|
|
{
|
|
newFolder->SetLanguage((LANGID)atoi(parser->GetValue(token)));
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
CHAR *pTitle;
|
|
pTitle = newFolder->GetTitle();
|
|
if (pTitle && pTitle[0] == '=')
|
|
{
|
|
if (CheckTitleRef(pTitle, newFolder->GetLanguage()) != F_OK)
|
|
{
|
|
delete newFolder;
|
|
return F_OK;
|
|
}
|
|
AddRefedTitle(newFolder);
|
|
}
|
|
|
|
m_pParents[m_dwCurLevel - 1]->AddChildFolder(newFolder);
|
|
m_pParents[m_dwCurLevel] = newFolder;
|
|
|
|
return F_OK;
|
|
}
|
|
|
|
DWORD CCollection::AddRefedTitle(CFolder *pFolder)
|
|
{
|
|
m_dwTitleRefCount++;
|
|
m_RefTitles.Add(pFolder);
|
|
return F_OK;
|
|
}
|
|
|
|
|
|
DWORD CCollection::HandleLocation(CParseXML *parser, CHAR *token)
|
|
{
|
|
if (!parser || !token)
|
|
return F_NULL;
|
|
CLocation *newLocation = NewLocation();
|
|
|
|
if (newLocation == NULL)
|
|
return F_MEMORY;
|
|
|
|
newLocation->m_ColNum = 0;
|
|
while (TRUE)
|
|
{
|
|
token = parser->GetToken();
|
|
if (stricmp(parser->GetFirstWord(token), "LocName") == 0)
|
|
{
|
|
newLocation->SetId(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "TitleString") == 0)
|
|
{
|
|
newLocation->SetTitle(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "LocPath") == 0)
|
|
{
|
|
newLocation->SetPath(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "Volume") == 0)
|
|
{
|
|
newLocation->SetVolume(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "LocColNum") == 0)
|
|
{
|
|
newLocation->m_ColNum = atoi(parser->GetValue(token));
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
return F_OK;
|
|
}
|
|
|
|
|
|
DWORD CCollection::HandleTitle(CParseXML *parser, CHAR *token)
|
|
{
|
|
|
|
if (!parser || !token)
|
|
return F_NULL;
|
|
|
|
LOCATIONHISTORY *pNew;
|
|
CTitle *newTitle = NewTitle();
|
|
DWORD dw;
|
|
|
|
CHAR *pSampleLocation = NULL;
|
|
BOOL bMerge = FALSE;
|
|
|
|
if (newTitle == NULL)
|
|
return F_MEMORY;
|
|
|
|
while (TRUE)
|
|
{
|
|
token = parser->GetToken();
|
|
if (stricmp(parser->GetFirstWord(token), "DocCompId") == 0)
|
|
{
|
|
newTitle->SetId(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "TitleString") == 0)
|
|
{
|
|
// no longer do anything with titlestring but need to support for backward compatiblity
|
|
continue;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "TitleSampleLocation") == 0)
|
|
{
|
|
if (newTitle->m_pTail == NULL)
|
|
{
|
|
// old style global.col, save this for the locations to follow
|
|
AllocCopyValue(parser, token, &pSampleLocation);
|
|
}
|
|
else
|
|
if ((dw = AllocCopyValue(parser, token, &(newTitle->m_pTail->SampleLocation))) != F_OK)
|
|
return dw;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "DocCompLanguage") == 0)
|
|
{
|
|
newTitle->SetLanguage((LANGID)atoi(parser->GetValue(token)));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "SupportsMerge") == 0)
|
|
{
|
|
if (newTitle->m_pTail == NULL)
|
|
{
|
|
// old style global.col, save this for the locations to follow
|
|
bMerge = (BOOL)atoi(parser->GetValue(token));
|
|
}
|
|
else
|
|
newTitle->m_pTail->bSupportsMerge = (BOOL)atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "LocationHistory") == 0)
|
|
{
|
|
pNew = newTitle->NewLocationHistory();
|
|
|
|
if (pNew == NULL)
|
|
return F_MEMORY;
|
|
|
|
if (pSampleLocation)
|
|
if ((dw = AllocSetValue(pSampleLocation, &(newTitle->m_pTail->SampleLocation))) != F_OK)
|
|
return dw;
|
|
|
|
newTitle->m_pTail->bSupportsMerge = bMerge;
|
|
|
|
dw = m_Strings.AddTail(parser->GetFirstWord(token));
|
|
if (dw != F_OK)
|
|
{
|
|
return dw;
|
|
}
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "/LocationHistory") == 0)
|
|
{
|
|
CHAR *sz;
|
|
dw = m_Strings.GetTail(&sz);
|
|
if (dw != F_OK)
|
|
{
|
|
return dw;
|
|
}
|
|
|
|
if (strcmp(sz, &token[1]) != 0)
|
|
{
|
|
delete sz;
|
|
return F_TAGMISSMATCH;
|
|
}
|
|
delete sz;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "TitleLocation") == 0)
|
|
{
|
|
if ((dw = AllocCopyValue(parser, token, &(newTitle->m_pTail->FileName))) != F_OK)
|
|
return dw;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "QueryLocation") == 0)
|
|
{
|
|
if ((dw = AllocCopyValue(parser, token, &(newTitle->m_pTail->QueryFileName))) != F_OK)
|
|
return dw;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "TitleQueryLocation") == 0)
|
|
{
|
|
if ((dw = AllocCopyValue(parser, token, &(newTitle->m_pTail->QueryLocation))) != F_OK)
|
|
return dw;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "IndexLocation") == 0)
|
|
{
|
|
if ((dw = AllocCopyValue(parser, token, &(newTitle->m_pTail->IndexFileName))) != F_OK)
|
|
return dw;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "LocationRef") == 0)
|
|
{
|
|
if ((dw = AllocCopyValue(parser, token, &(newTitle->m_pTail->LocationId))) != F_OK)
|
|
return dw;
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "Version") == 0)
|
|
{
|
|
newTitle->m_pTail->Version = atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "LastPromptedVersion") == 0)
|
|
{
|
|
newTitle->m_pTail->LastPromptedVersion = atoi(parser->GetValue(token));
|
|
}
|
|
else if (stricmp(parser->GetFirstWord(token), "ColNum") == 0)
|
|
{
|
|
newTitle->m_pTail->CollectionNumber = atoi(parser->GetValue(token));
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (pSampleLocation)
|
|
delete pSampleLocation;
|
|
|
|
return F_OK;
|
|
}
|
|
|
|
// Saves any changes made to the internal data structures to the file.
|
|
DWORD CCollection::Save()
|
|
{
|
|
CHAR szBuffer[MAX_LINE_LEN];
|
|
DWORD dwWritten;
|
|
|
|
#ifdef HHSETUP // only hhsetup needs to rewrite the users .col file
|
|
// don't want the control to add any new tags to old
|
|
// collections, which would break uninstall and update
|
|
// if no root folders delete the collection file
|
|
if (m_bRemoved == TRUE)
|
|
{
|
|
DeleteFile(m_szFileName);
|
|
m_bRemoved = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ((m_fh = CreateFile(m_szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE) {
|
|
return F_NOFILE;
|
|
}
|
|
|
|
strcpy(szBuffer, "<XML>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
// write out collection information
|
|
strcpy(szBuffer, "<HTMLHelpCollection>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<masterchm value=\"%s\"/>\r\n", (m_szMasterCHM ? m_szMasterCHM : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<masterlangid value=%d/>\r\n", m_MasterLangId);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<samplelocation value=\"%s\"/>\r\n", (m_szSampleLocation ? m_szSampleLocation : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<collectionnum value=%d/>\r\n", m_dwColNo);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<refcount value=%d/>\r\n", m_dwRef);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<version value=%d/>\r\n", m_dwVersion);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<findmergedchms value=%d/>\r\n", m_bFindMergedChms);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
// write out folders
|
|
strcpy(szBuffer,"<Folders>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
m_dwCurLevel = 0;
|
|
|
|
if (WriteFolders(&m_pRootFolder) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
|
|
// close tags
|
|
strcpy(szBuffer, "</Folders>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
strcpy(szBuffer, "</HTMLHelpCollection>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
strcpy(szBuffer, "</XML>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
CloseHandle(m_fh);
|
|
}
|
|
|
|
#endif
|
|
|
|
// save the global titles and locations
|
|
// open collection file
|
|
if ((m_fh = CreateFile(gszColReg, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE) {
|
|
return F_NOFILE;
|
|
}
|
|
|
|
// write out XML tag
|
|
strcpy(szBuffer, "<XML>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
strcpy(szBuffer, "<HTMLHelpDocInfo>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
wsprintf(szBuffer, "<NextCollectionId value=%d/>\r\n", m_dwNextColNo);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
// write out the collection list
|
|
strcpy(szBuffer, "<Collections>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
CColList *pCol = m_pColListHead;
|
|
|
|
while (pCol)
|
|
{
|
|
strcpy(szBuffer, "<Collection>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<ColNum value=%d/>\r\n", pCol->GetColNo());
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<ColName value=\"%s\"/>\r\n", (pCol->GetFileName() ? pCol->GetFileName() : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
strcpy(szBuffer, "</Collection>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
pCol = pCol->GetNext();
|
|
}
|
|
strcpy(szBuffer, "</Collections>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
// write out the locations
|
|
strcpy(szBuffer, "<Locations>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
CLocation *p = FirstLocation();
|
|
|
|
while (p)
|
|
{
|
|
strcpy(szBuffer, "<Location>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<LocColNum value=%d/>\r\n", p->m_ColNum);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<LocName value=\"%s\"/>\r\n", (p->GetId() ? p->GetId() : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<TitleString value=\"%s\"/>\r\n", (p->GetTitle() ? p->GetTitle() : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<LocPath value=\"%s\"/>\r\n", (p->GetPath() ? p->GetPath() : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<Volume value=\"%s\"/>\r\n", (p->GetVolume() ? p->GetVolume() : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
strcpy(szBuffer, "</Location>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
p = p->GetNextLocation();
|
|
}
|
|
strcpy(szBuffer, "</Locations>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
|
|
// write out the titles
|
|
strcpy(szBuffer, "<DocCompilations>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
CTitle *pTitle = GetFirstTitle();
|
|
LOCATIONHISTORY *pHist;
|
|
while (pTitle)
|
|
{
|
|
strcpy(szBuffer, "<DocCompilation>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<DocCompId value=\"%s\"/>\r\n", (pTitle->GetId() ? pTitle->GetId() : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t<DocCompLanguage value=%d/>\r\n", pTitle->GetLanguage());
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
|
|
pHist = pTitle->m_pHead;
|
|
|
|
while (pHist)
|
|
{
|
|
strcpy(szBuffer, "\t<LocationHistory>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<ColNum value=%d/>\r\n", pHist->CollectionNumber);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<TitleLocation value=\"%s\"/>\r\n", (pHist->FileName ? pHist->FileName : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<IndexLocation value=\"%s\"/>\r\n", (pHist->IndexFileName ? pHist->IndexFileName : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<QueryLocation value=\"%s\"/>\r\n", (pHist->QueryFileName ? pHist->QueryFileName : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<LocationRef value=\"%s\"/>\r\n", (pHist->LocationId ? pHist->LocationId : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<Version value=%ld/>\r\n", pHist->Version);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<LastPromptedVersion value=%ld/>\r\n", pHist->LastPromptedVersion);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<TitleSampleLocation value=\"%s\"/>\r\n", (pHist->SampleLocation ? pHist->SampleLocation : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<TitleQueryLocation value=\"%s\"/>\r\n", (pHist->QueryLocation ? pHist->QueryLocation : ""));
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
wsprintf(szBuffer, "\t\t<SupportsMerge value=%d/>\r\n", pHist->bSupportsMerge);
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
strcpy(szBuffer, "\t</LocationHistory>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
pHist = pHist->pNext;
|
|
}
|
|
strcpy(szBuffer, "</DocCompilation>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
pTitle = pTitle->GetNextTitle();
|
|
}
|
|
|
|
strcpy(szBuffer, "</DocCompilations>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
strcpy(szBuffer, "</HTMLHelpDocInfo>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
strcpy(szBuffer,"</XML>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
CloseHandle(m_fh);
|
|
return F_WRITE;
|
|
}
|
|
if (CloseHandle(m_fh) == FALSE)
|
|
return F_CLOSE;
|
|
|
|
// make sure we can open this file for read
|
|
if ((m_fh = CreateFile(gszColReg, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE) {
|
|
return F_EXISTCHECK;
|
|
}
|
|
|
|
if (CloseHandle(m_fh) == FALSE)
|
|
return F_CLOSE;
|
|
|
|
return F_OK;
|
|
}
|
|
|
|
BOOL CCollection::WriteFolders(CFolder **p)
|
|
{
|
|
BOOL b = TRUE;
|
|
if (!p || !(*p))
|
|
return FALSE;
|
|
|
|
CFolder *pChild;
|
|
|
|
pChild = (*p)->GetFirstChildFolder();
|
|
|
|
if (pChild)
|
|
b = WriteFolder(&pChild);
|
|
|
|
delete *p;
|
|
*p = NULL;
|
|
return b;
|
|
}
|
|
|
|
BOOL CCollection::WriteFolder(CFolder **p)
|
|
{
|
|
if (!p || !(*p))
|
|
return FALSE;
|
|
|
|
CHAR szBuffer[MAX_LINE_LEN];
|
|
DWORD dwWritten;
|
|
|
|
CFolder *pChild, *pNext;
|
|
DWORD i;
|
|
// write this folder
|
|
// tab over the indent level
|
|
strcpy(szBuffer, "\t");
|
|
for (i = 0; i < m_dwCurLevel; i++)
|
|
{
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
strcpy(szBuffer, "<Folder>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(szBuffer, "\t");
|
|
for (i = 0; i < m_dwCurLevel+1; i++)
|
|
{
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
wsprintf(szBuffer, "<TitleString value=\"%s\"/>\r\n", (*p)->GetTitle());
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(szBuffer, "\t");
|
|
for (i = 0; i < m_dwCurLevel+1; i++)
|
|
{
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
wsprintf(szBuffer, "<FolderOrder value=%d/>\r\n", (*p)->GetOrder());
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CHAR *pTitle = (*p)->GetTitle();
|
|
if (pTitle[0] == '=')
|
|
{
|
|
strcpy(szBuffer, "\t");
|
|
for (i = 0; i < m_dwCurLevel+1; i++)
|
|
{
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
wsprintf(szBuffer, "<LangId value=%d/>\r\n", (*p)->GetLanguage());
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
m_dwCurLevel++;
|
|
if (pChild = (*p)->GetFirstChildFolder())
|
|
{
|
|
if (WriteFolder(&pChild) == FALSE)
|
|
return FALSE;
|
|
}
|
|
if (m_dwCurLevel)
|
|
m_dwCurLevel--;
|
|
|
|
strcpy(szBuffer, "\t");
|
|
for (i = 0; i < m_dwCurLevel; i++)
|
|
{
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
strcpy(szBuffer, "</Folder>\r\n");
|
|
if (WriteFile(m_fh, szBuffer, strlen(szBuffer), &dwWritten, NULL) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pNext = (*p)->GetNextFolder();
|
|
delete (*p);
|
|
*p = NULL;
|
|
do {
|
|
if (pNext)
|
|
{
|
|
if (WriteFolder(&pNext) == FALSE)
|
|
return FALSE;
|
|
}
|
|
} while (pNext && (pNext = pNext->GetNextFolder()));
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD CCollection::Close()
|
|
{
|
|
m_locationnum = 0;
|
|
gszColReg[0] = NULL;
|
|
m_dwNextColNo = 1;
|
|
m_dwColNo = 0;
|
|
m_dwTitleRefCount = 0;
|
|
m_dwRef = 0;
|
|
m_dwVersion = 0;
|
|
for (int i = 0; i < MAX_LEVELS; i++)
|
|
m_pParents[i] = NULL;
|
|
m_dwCurLevel = 0;
|
|
m_dwLastLevel = 0;
|
|
m_bConfirmTitles = FALSE;
|
|
m_MasterLangId = ENGLANGID;
|
|
m_bFindMergedChms = FALSE;
|
|
m_Strings.RemoveAll();
|
|
|
|
if (m_szFileName)
|
|
{
|
|
delete m_szFileName;
|
|
m_szFileName = NULL;
|
|
}
|
|
|
|
if (m_pwcFileName)
|
|
{
|
|
delete m_pwcFileName;
|
|
m_pwcFileName = NULL;
|
|
}
|
|
|
|
if (m_szMasterCHM)
|
|
{
|
|
delete m_szMasterCHM;
|
|
m_szMasterCHM = NULL;
|
|
}
|
|
|
|
if (m_pwcMasterCHM)
|
|
{
|
|
delete m_pwcMasterCHM;
|
|
m_pwcMasterCHM = NULL;
|
|
}
|
|
|
|
if (m_szSampleLocation)
|
|
{
|
|
delete m_szSampleLocation;
|
|
m_szSampleLocation = NULL;
|
|
}
|
|
|
|
// clean up col list
|
|
CColList *pCol, *pColNext;
|
|
for (pCol = m_pColListHead; pCol; pCol = pColNext)
|
|
{
|
|
pColNext = pCol->GetNext();
|
|
delete pCol;
|
|
}
|
|
|
|
m_pColListHead = NULL;
|
|
m_pColListTail = NULL;
|
|
|
|
// clean up locations
|
|
CLocation *p, *pNext;
|
|
for (p = m_pFirstLocation; p; p=pNext)
|
|
{
|
|
pNext = p->GetNextLocation();
|
|
delete p;
|
|
}
|
|
|
|
m_pFirstLocation=NULL;
|
|
m_pLocationTail = NULL;
|
|
// clean up titles
|
|
CTitle *pTitle, *pNextTitle;
|
|
for (pTitle = m_pFirstTitle; pTitle; pTitle=pNextTitle)
|
|
{
|
|
pNextTitle = pTitle->GetNextTitle();
|
|
delete pTitle;
|
|
}
|
|
|
|
m_pFirstTitle = NULL;
|
|
m_pTitleTail = NULL;
|
|
// clean up folder
|
|
if (m_pRootFolder)
|
|
{
|
|
DeleteChildren(&m_pRootFolder);
|
|
}
|
|
m_pRootFolder = NULL;
|
|
return F_OK;
|
|
}
|
|
|
|
// Returns the first title
|
|
CTitle * CCollection::GetFirstTitle()
|
|
{
|
|
return m_pFirstTitle;
|
|
}
|
|
|
|
// Locates a title based on id
|
|
CTitle * CCollection::FindTitle(const CHAR * Id, LANGID LangId)
|
|
{
|
|
if (!Id)
|
|
return NULL;
|
|
|
|
CTitle *p;
|
|
|
|
p = m_pFirstTitle;
|
|
|
|
while (p)
|
|
{
|
|
if (stricmp(p->GetId(), Id) == 0 &&
|
|
(LangId == 0 || p->GetLanguage() == LangId)) // Ignore LangId if its zero.
|
|
{
|
|
return p;
|
|
}
|
|
p = p->GetNextTitle();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef HHCTRL
|
|
// Try multiple LangIds before failing
|
|
CTitle * CCollection::FindTitleNonExact(const CHAR * Id, LANGID DesiredLangId)
|
|
{
|
|
CTitle* pTitle = NULL ;
|
|
|
|
CLanguageEnum* pEnum = _Module.m_Language.GetEnumerator(DesiredLangId) ;
|
|
ASSERT(pEnum) ;
|
|
LANGID langid = pEnum->start() ;
|
|
while (langid != c_LANGID_ENUM_EOF)
|
|
{
|
|
pTitle = FindTitle(Id, langid);
|
|
if (pTitle)
|
|
{
|
|
break ; //Found It!
|
|
}
|
|
|
|
langid = pEnum->next() ;
|
|
}
|
|
|
|
// Cleanup.
|
|
if (pEnum)
|
|
{
|
|
delete pEnum ;
|
|
}
|
|
|
|
return pTitle;
|
|
}
|
|
#endif // #ifdef HHCTRL
|
|
|
|
// Returns the first location
|
|
CLocation* CCollection::FirstLocation()
|
|
{
|
|
return m_pFirstLocation;
|
|
}
|
|
|
|
// Finds a location based on a name
|
|
CLocation * CCollection::FindLocation(const CHAR * Id, UINT* puiVolumeOrder )
|
|
{
|
|
if (!Id)
|
|
return NULL;
|
|
|
|
CLocation *p;
|
|
|
|
p = m_pFirstLocation;
|
|
|
|
if( puiVolumeOrder )
|
|
*puiVolumeOrder = 0;
|
|
|
|
while (p)
|
|
{
|
|
if( puiVolumeOrder )
|
|
*puiVolumeOrder = (*puiVolumeOrder)+1;
|
|
|
|
if (stricmp(p->GetId(), Id) == 0 && (p->m_ColNum == m_dwColNo|| p->m_ColNum == 0))
|
|
return p;
|
|
p = p->GetNextLocation();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
DWORD CCollection::CheckTitleRef(const CHAR *pId, const LANGID Lang)
|
|
{
|
|
if (m_bConfirmTitles == FALSE)
|
|
return F_OK;
|
|
|
|
if (pId[0] != '=')
|
|
return F_OK;
|
|
|
|
CTitle *pTitle;
|
|
if ((pTitle = FindTitle(&pId[1], Lang)) == NULL)
|
|
return F_NOTITLE;
|
|
|
|
LOCATIONHISTORY *p;
|
|
|
|
p = pTitle->m_pHead;
|
|
|
|
while (p)
|
|
{
|
|
if (p->CollectionNumber == GetColNo())
|
|
return F_OK;
|
|
p = p->pNext;
|
|
}
|
|
|
|
return F_NOTITLE;
|
|
}
|
|
|
|
//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 * CCollection::AddFolder(const CHAR * szName, DWORD Order, DWORD *pDWORD, LANGID LangId)
|
|
{
|
|
if (!szName)
|
|
{
|
|
if (pDWORD)
|
|
*pDWORD = F_NULL;
|
|
return NULL;
|
|
}
|
|
|
|
if (CheckTitleRef(szName, LangId) != F_OK)
|
|
{
|
|
if (pDWORD)
|
|
*pDWORD = F_NOTITLE;
|
|
return NULL;
|
|
}
|
|
|
|
CFolder *pNew;
|
|
|
|
pNew = new CFolder;
|
|
|
|
DWORD dwrc = F_OK;
|
|
|
|
if (pNew)
|
|
{
|
|
pNew->SetTitle(szName);
|
|
pNew->SetOrder(Order);
|
|
pNew->SetLanguage(LangId);
|
|
dwrc = m_pRootFolder->AddChildFolder(pNew);
|
|
|
|
if (dwrc != F_OK)
|
|
{
|
|
if (pDWORD)
|
|
*pDWORD = dwrc;
|
|
delete pNew;
|
|
return NULL;
|
|
}
|
|
|
|
Dirty();
|
|
return pNew;
|
|
}
|
|
|
|
if (pDWORD)
|
|
*pDWORD = F_MEMORY;
|
|
return NULL;
|
|
}
|
|
|
|
CTitle * CCollection::NewTitle()
|
|
{
|
|
CTitle *newTitle = new CTitle;
|
|
if (newTitle == NULL)
|
|
return NULL;
|
|
|
|
if (m_pFirstTitle == NULL)
|
|
{
|
|
m_pFirstTitle = newTitle;
|
|
}
|
|
else
|
|
{
|
|
m_pTitleTail->SetNextTitle(newTitle);
|
|
}
|
|
m_pTitleTail = newTitle;
|
|
|
|
return newTitle;
|
|
}
|
|
|
|
// 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 * CCollection::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, const CHAR *QueryLocation)
|
|
{
|
|
if (!Id || !FileName || !IndexFile)
|
|
return NULL;
|
|
DWORD dwrc;
|
|
|
|
CTitle *pTitle;
|
|
|
|
// check if the title exist
|
|
if (pTitle = FindTitle(Id, Lang))
|
|
{
|
|
// add location
|
|
dwrc = pTitle->AddLocationHistory(m_dwColNo, FileName, IndexFile, Query, pLocation, SampleLocation, QueryLocation, bSupportsMerge);
|
|
if (pDWORD)
|
|
*pDWORD = dwrc;
|
|
}
|
|
else
|
|
{
|
|
// just add the title then
|
|
pTitle = NewTitle();
|
|
if (pTitle == NULL)
|
|
{
|
|
if (pDWORD)
|
|
*pDWORD = F_MEMORY;
|
|
return NULL;
|
|
}
|
|
pTitle->SetId(Id);
|
|
pTitle->SetLanguage(Lang);
|
|
dwrc = pTitle->AddLocationHistory(m_dwColNo, FileName, IndexFile, Query, pLocation, SampleLocation, QueryLocation, bSupportsMerge);
|
|
if (pDWORD)
|
|
*pDWORD = dwrc;
|
|
}
|
|
Dirty();
|
|
return pTitle;
|
|
}
|
|
|
|
CLocation * CCollection::NewLocation()
|
|
{
|
|
CLocation *p = new CLocation;
|
|
if (!p)
|
|
{
|
|
return NULL;
|
|
}
|
|
if (m_pFirstLocation == NULL)
|
|
{
|
|
m_pFirstLocation = p;
|
|
}
|
|
else
|
|
{
|
|
m_pLocationTail->SetNextLocation(p);
|
|
}
|
|
m_pLocationTail = p;
|
|
return p;
|
|
}
|
|
|
|
// 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 * CCollection::AddLocation(const CHAR * Title, const CHAR * Path, const CHAR * Id, const CHAR * Volume, DWORD *pDWORD)
|
|
{
|
|
if (!Title || !Path || !Id || !Volume)
|
|
return NULL;
|
|
|
|
CLocation *p;
|
|
|
|
p = FindLocation(Id);
|
|
|
|
// if not found then add new location entry
|
|
if (!p)
|
|
p = NewLocation();
|
|
|
|
if (!p)
|
|
{
|
|
if (pDWORD)
|
|
*pDWORD = F_MEMORY;
|
|
return NULL;
|
|
}
|
|
|
|
p->SetTitle(Title);
|
|
p->SetPath(Path);
|
|
p->SetId(Id);
|
|
p->SetVolume(Volume);
|
|
p->m_ColNum = m_dwColNo;
|
|
if (pDWORD)
|
|
*pDWORD = F_OK;
|
|
Dirty();
|
|
return p;
|
|
}
|
|
|
|
|
|
// removing objects
|
|
DWORD CCollection::DeleteFolder(CFolder *pDelete)
|
|
{
|
|
|
|
if (!pDelete)
|
|
return F_NULL;
|
|
|
|
CFolder *pParent;
|
|
CFolder *pPrev = NULL;
|
|
CFolder *p;
|
|
|
|
if ((pParent = pDelete->GetParent()) == NULL)
|
|
return F_NOPARENT;
|
|
|
|
p = pParent->GetFirstChildFolder();
|
|
|
|
while (p)
|
|
{
|
|
if (p == pDelete)
|
|
{
|
|
// is this the head
|
|
if (!pPrev)
|
|
{
|
|
pParent->SetFirstChildFolder(p->GetNextFolder());
|
|
}
|
|
else
|
|
{
|
|
// fixup the list
|
|
pPrev->SetNextFolder(p->GetNextFolder());
|
|
}
|
|
|
|
DeleteChildren(&pDelete);
|
|
Dirty();
|
|
return F_OK;
|
|
|
|
}
|
|
pPrev = p;
|
|
p = p->GetNextFolder();
|
|
}
|
|
|
|
return F_NOTFOUND;
|
|
}
|
|
|
|
DWORD CCollection::DeleteTitle(CTitle *pDelete)
|
|
{
|
|
if (!pDelete)
|
|
return F_NULL;
|
|
// remove all location history entries for this collection
|
|
LOCATIONHISTORY *pHist, *pHistPrev;
|
|
pHistPrev = NULL;
|
|
pHist = pDelete->m_pHead;
|
|
|
|
while (pHist)
|
|
{
|
|
if (pHist->CollectionNumber == m_dwColNo)
|
|
{
|
|
// head
|
|
if (pHist == pDelete->m_pHead)
|
|
{
|
|
// and tail
|
|
if (pHist == pDelete->m_pTail)
|
|
{
|
|
pDelete->m_pHead = NULL;
|
|
pDelete->m_pTail = NULL;
|
|
DeleteLocalFiles(pHist, pDelete);
|
|
delete pHist;
|
|
break;
|
|
}
|
|
pDelete->m_pHead = pHist->pNext;
|
|
DeleteLocalFiles(pHist, pDelete);
|
|
delete pHist;
|
|
pHist = pDelete->m_pHead;
|
|
pHistPrev = NULL;
|
|
continue;
|
|
}
|
|
|
|
// tail
|
|
if (pHist == pDelete->m_pTail)
|
|
{
|
|
pDelete->m_pTail = pHistPrev;
|
|
if (pHistPrev)
|
|
pHistPrev->pNext = NULL;
|
|
DeleteLocalFiles(pHist, pDelete);
|
|
delete pHist;
|
|
break;
|
|
}
|
|
|
|
pHistPrev->pNext = pHist->pNext;
|
|
DeleteLocalFiles(pHist, pDelete);
|
|
delete pHist;
|
|
pHist = pHistPrev->pNext;
|
|
}
|
|
else
|
|
{
|
|
pHistPrev = pHist;
|
|
pHist = pHist->pNext;
|
|
}
|
|
}
|
|
Dirty();
|
|
|
|
// if no history remains remove the title
|
|
if (pDelete->m_pHead != NULL)
|
|
return F_OK;
|
|
|
|
CTitle *p, *pPrev;
|
|
|
|
p = m_pFirstTitle;
|
|
pPrev = NULL;
|
|
|
|
if (p== NULL)
|
|
return F_NOTFOUND;
|
|
|
|
while (p)
|
|
{
|
|
if (p == pDelete)
|
|
{
|
|
// is this the head
|
|
if (!pPrev)
|
|
{
|
|
m_pFirstTitle = p->GetNextTitle();
|
|
}
|
|
// is this the tail
|
|
else if (p == m_pTitleTail)
|
|
{
|
|
m_pTitleTail = pPrev;
|
|
pPrev->SetNextTitle(p->GetNextTitle());
|
|
}
|
|
else
|
|
{
|
|
// fixup the list
|
|
pPrev->SetNextTitle(p->GetNextTitle());
|
|
}
|
|
|
|
delete p;
|
|
return F_OK;
|
|
}
|
|
pPrev = p;
|
|
p = p->GetNextTitle();
|
|
}
|
|
return F_NOTFOUND;
|
|
}
|
|
|
|
void CCollection::DeleteLocalFiles(LOCATIONHISTORY *pThisHist, CTitle *pTitle)
|
|
{
|
|
if (m_bRemoveLocalFiles == FALSE)
|
|
return;
|
|
|
|
LOCATIONHISTORY *pHist;
|
|
pHist = pTitle->m_pHead;
|
|
|
|
// if the chm or chi is in use don't delete
|
|
while (pHist)
|
|
{
|
|
if (strcmp(pHist->FileName, pThisHist->FileName) == 0)
|
|
return;
|
|
if (strcmp(pHist->IndexFileName, pThisHist->IndexFileName) == 0)
|
|
return;
|
|
pHist = pHist->pNext;
|
|
}
|
|
|
|
// if these are local files delete them
|
|
char drive[_MAX_DRIVE+1];
|
|
char dir[_MAX_DIR];
|
|
char fname[_MAX_FNAME];
|
|
char ext[_MAX_EXT];
|
|
|
|
_splitpath( pThisHist->FileName, drive, dir, fname, ext );
|
|
|
|
if(drive[1] == ':')
|
|
{
|
|
drive[2] = '\\';
|
|
drive[3] = 0;
|
|
}
|
|
|
|
if (GetDriveType(drive) == DRIVE_FIXED)
|
|
{
|
|
// delete the title
|
|
if (DeleteFile(pThisHist->FileName) == FALSE)
|
|
m_bAllFilesDeleted = FALSE;
|
|
// could need to check for and delete samples stuff here
|
|
}
|
|
|
|
// if files are different
|
|
if (strcmp(pThisHist->IndexFileName, pThisHist->FileName))
|
|
{
|
|
_splitpath( pThisHist->IndexFileName, drive, dir, fname, ext );
|
|
|
|
if(drive[1] == ':')
|
|
{
|
|
drive[2] = '\\';
|
|
drive[3] = 0;
|
|
}
|
|
|
|
if (GetDriveType(drive) == DRIVE_FIXED)
|
|
{
|
|
// delete the index
|
|
if (DeleteFile(pThisHist->IndexFileName) == FALSE)
|
|
m_bAllFilesDeleted = FALSE;
|
|
// could need to check for and delete samples stuff here
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// only used from HHSETUP
|
|
LANGID CCollection::GetLangId(const CHAR *szFileName)
|
|
{
|
|
#ifdef HHSETUP
|
|
return ::GetLangId(szFileName);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
DWORD CCollection::DeleteLocation(CLocation *pDelete)
|
|
{
|
|
if (!pDelete)
|
|
return F_NULL;
|
|
CLocation *p, *pPrev;
|
|
|
|
p = m_pFirstLocation;
|
|
pPrev = NULL;
|
|
|
|
if (p== NULL)
|
|
return F_NOTFOUND;
|
|
|
|
while (p)
|
|
{
|
|
if (p == pDelete)
|
|
{
|
|
// is this the head
|
|
if (!pPrev)
|
|
{
|
|
m_pFirstLocation = p->GetNextLocation();
|
|
}
|
|
// is this the tail
|
|
else if (p == m_pLocationTail)
|
|
{
|
|
m_pLocationTail = pPrev;
|
|
pPrev->SetNextLocation(NULL);
|
|
}
|
|
else
|
|
{
|
|
// fixup the list
|
|
pPrev->SetNextLocation(p->GetNextLocation());
|
|
}
|
|
|
|
delete p;
|
|
Dirty();
|
|
return F_OK;
|
|
}
|
|
pPrev = p;
|
|
p = p->GetNextLocation();
|
|
}
|
|
return F_NOTFOUND;
|
|
}
|
|
|
|
|
|
DWORD CCollection::RemoveCollection(BOOL bRemoveLocalFiles)
|
|
{
|
|
// if release returns a positive ref count then don't delete
|
|
if (Release())
|
|
return F_OK;
|
|
|
|
m_bRemoveLocalFiles = bRemoveLocalFiles;
|
|
m_bAllFilesDeleted = TRUE;
|
|
m_bRemoved = TRUE;
|
|
|
|
CTitle *pT = GetFirstTitle();
|
|
CTitle *pNext;
|
|
while (pT)
|
|
{
|
|
pNext = pT->GetNextTitle();
|
|
DeleteTitle(pT);
|
|
pT = pNext;
|
|
}
|
|
|
|
// delete locations for this collection
|
|
CLocation *pL = FirstLocation();
|
|
CLocation *pNextLoc;
|
|
|
|
while (pL)
|
|
{
|
|
pNextLoc = pL->GetNextLocation();
|
|
if (pL->m_ColNum == m_dwColNo)
|
|
DeleteLocation(pL);
|
|
pL = pNextLoc;
|
|
}
|
|
|
|
RemoveCollectionEntry(m_szFileName);
|
|
|
|
Dirty();
|
|
if (m_bRemoveLocalFiles == TRUE && m_bAllFilesDeleted == FALSE)
|
|
return F_DELETE;
|
|
return F_OK;
|
|
}
|
|
|
|
void CCollection::DeleteFolders(CFolder **p)
|
|
{
|
|
CFolder *pChild, *pNext;
|
|
if (pChild = (*p)->GetFirstChildFolder())
|
|
DeleteFolders(&pChild);
|
|
pNext = (*p)->GetNextFolder();
|
|
|
|
// check if this is a title
|
|
const CHAR *pTitle = (*p)->GetTitle();
|
|
|
|
if (pTitle && pTitle[0] == '=') // if so delete it.
|
|
{
|
|
CTitle *pT;
|
|
|
|
pT = FindTitle(&pTitle[1], (*p)->GetLanguage());
|
|
if (pT)
|
|
DeleteTitle(pT);
|
|
}
|
|
|
|
delete (*p);
|
|
*p = NULL;
|
|
do {
|
|
if (pNext)
|
|
DeleteFolders(&pNext);
|
|
} while (pNext && (pNext = pNext->GetNextFolder()));
|
|
}
|
|
|
|
|
|
// Merges the currently installed titles for the collection into the specified filename (path determined internally)
|
|
BOOL CCollection::MergeKeywords(CHAR * pwzFilename )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CFolder implementation
|
|
|
|
CFolder::CFolder()
|
|
{
|
|
Title = NULL;
|
|
pwcTitle = NULL;
|
|
Order = 0;
|
|
LangId = ENGLANGID;
|
|
pNext = NULL;
|
|
pKid = NULL;
|
|
pParent = NULL;
|
|
iLevel = 0;
|
|
f_HasHash = 0;
|
|
f_IsOrphan = 1; // Assume the worst.
|
|
}
|
|
|
|
CFolder::~CFolder()
|
|
{
|
|
if (Title)
|
|
delete Title;
|
|
if(pwcTitle)
|
|
delete pwcTitle;
|
|
}
|
|
|
|
void CFolder::SetTitle(const CHAR *sz)
|
|
{
|
|
AllocSetValue(sz, &Title);
|
|
}
|
|
|
|
void CFolder::SetExTitlePtr(CExTitle* pTitle)
|
|
{
|
|
CFolder* pTmp;
|
|
|
|
pExTitle = pTitle;
|
|
f_IsOrphan = 0;
|
|
|
|
pTmp = pParent;
|
|
while ( pTmp )
|
|
{
|
|
pTmp->f_IsOrphan = 0;
|
|
pTmp = pTmp->pParent;
|
|
}
|
|
}
|
|
|
|
void CFolder::SetOrder(DWORD newOrder)
|
|
{
|
|
Order = newOrder;
|
|
}
|
|
|
|
DWORD CFolder::GetOrder()
|
|
{
|
|
return Order;
|
|
}
|
|
|
|
// Returns the next sibling folder given a folder entry
|
|
CFolder * CFolder::GetNextFolder()
|
|
{
|
|
return pNext;
|
|
}
|
|
|
|
// Returns the first child of a given folder if it exists
|
|
CFolder * CFolder::GetFirstChildFolder()
|
|
{
|
|
return pKid;
|
|
}
|
|
|
|
CFolder * CFolder::AddChildFolder(const CHAR *szName, DWORD Order, DWORD *pError, LANGID LangId)
|
|
{
|
|
CFolder *pFolder = new CFolder;
|
|
|
|
if (pFolder == NULL)
|
|
return NULL;
|
|
|
|
pFolder->SetTitle(szName);
|
|
pFolder->SetOrder(Order);
|
|
pFolder->SetLanguage(LangId);
|
|
|
|
DWORD dwrc = AddChildFolder(pFolder);
|
|
if (pError)
|
|
*pError = dwrc;
|
|
return pFolder;
|
|
}
|
|
|
|
DWORD CFolder::AddChildFolder(CFolder *newFolder)
|
|
{
|
|
CFolder* pTmp;
|
|
newFolder->SetParent(this);
|
|
if (pKid == NULL)
|
|
{
|
|
pKid = newFolder;
|
|
}
|
|
else
|
|
{
|
|
if (newFolder->GetOrder() < pKid->GetOrder())
|
|
{
|
|
// make this the first child
|
|
newFolder->pNext = pKid;
|
|
pKid = newFolder;
|
|
}
|
|
else
|
|
{
|
|
// search for an insertion point
|
|
CFolder *pNext = pKid->pNext;
|
|
CFolder *pPrev = pKid;
|
|
while (pNext)
|
|
{
|
|
if (newFolder->GetOrder() < pNext->GetOrder())
|
|
{
|
|
newFolder->pNext = pNext;
|
|
break;
|
|
}
|
|
pPrev = pNext;
|
|
pNext = pNext->pNext;
|
|
}
|
|
pPrev->pNext = newFolder;
|
|
}
|
|
}
|
|
//
|
|
// Setup members to facilitate subsetting...
|
|
//
|
|
if ( newFolder->Title && newFolder->Title[0] == '=' )
|
|
{
|
|
newFolder->f_HasHash = 1;
|
|
//
|
|
// Leaf nodes will be rendered as open books in the subset dialog.
|
|
//
|
|
newFolder->f_A_Open = 1;
|
|
newFolder->f_F_Open = 1;
|
|
}
|
|
pTmp = newFolder->pParent;
|
|
while ( pTmp )
|
|
{
|
|
newFolder->iLevel++;
|
|
pTmp = pTmp->pParent;
|
|
}
|
|
newFolder->iLevel--;
|
|
return F_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CTitle implementation
|
|
|
|
void CTitle::SetId(const CHAR *sz)
|
|
{
|
|
AllocSetValue(sz, &Id);
|
|
}
|
|
|
|
void CTitle::SetLanguage(LANGID l)
|
|
{
|
|
Language = l;
|
|
}
|
|
|
|
CHAR *CTitle::GetId()
|
|
{
|
|
return Id;
|
|
}
|
|
|
|
LANGID CTitle::GetLanguage()
|
|
{
|
|
return Language;
|
|
}
|
|
|
|
LOCATIONHISTORY *CTitle::NewLocationHistory()
|
|
{
|
|
LOCATIONHISTORY *p;
|
|
|
|
p = new LOCATIONHISTORY;
|
|
|
|
if (p == NULL)
|
|
return NULL;
|
|
|
|
p->SampleLocation = NULL;
|
|
p->QueryLocation = NULL;
|
|
p->FileName = NULL;
|
|
p->IndexFileName = NULL;
|
|
p->QueryFileName = NULL;
|
|
p->LocationId = NULL;
|
|
p->Version = 0;
|
|
p->LastPromptedVersion = 0;
|
|
p->bSupportsMerge = FALSE;
|
|
p->pNext = NULL;
|
|
|
|
if (m_pHead == NULL)
|
|
{
|
|
m_pHead = p;
|
|
}
|
|
else
|
|
{
|
|
m_pTail->pNext = p;
|
|
}
|
|
m_pTail = p;
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
DWORD CTitle::AddLocationHistory(DWORD ColNo, const CHAR *FileName, const CHAR *IndexFile, const CHAR *Query, const CLocation *pLocation, const CHAR *SampleLocation, const CHAR *QueryLocation, BOOL bSupportsMerge)
|
|
{
|
|
LOCATIONHISTORY *p;
|
|
// get version information
|
|
DWORD dwNewVersion;
|
|
#ifdef HHSETUP
|
|
if (IndexFile)
|
|
dwNewVersion = GetTitleVersion(IndexFile);
|
|
else if (FileName)
|
|
dwNewVersion = GetTitleVersion(FileName);
|
|
else
|
|
dwNewVersion = 0;
|
|
#else
|
|
dwNewVersion = 0;
|
|
#endif
|
|
|
|
// see of any current entries match is new one if so update the existing item.
|
|
if (m_pHead)
|
|
{
|
|
p = m_pHead;
|
|
|
|
while (p)
|
|
{
|
|
if (p->CollectionNumber == ColNo &&
|
|
((FileName == NULL && p->FileName[0] == NULL) || (FileName &&strcmp(p->FileName, FileName) == 0)) &&
|
|
((IndexFile == NULL && p->IndexFileName[0] == NULL) || (IndexFile &&strcmp(p->IndexFileName, IndexFile) == 0)) &&
|
|
((Query == NULL && p->QueryFileName[0] == NULL) || (Query &&strcmp(p->QueryFileName, Query) == 0)) &&
|
|
((SampleLocation == NULL && p->SampleLocation[0] == NULL) || (SampleLocation &&strcmp(p->SampleLocation, SampleLocation) == 0)) &&
|
|
((QueryLocation == NULL && p->QueryLocation[0] == NULL) || (QueryLocation &&strcmp(p->QueryLocation, QueryLocation) == 0)) &&
|
|
p->bSupportsMerge == bSupportsMerge)
|
|
{
|
|
if (pLocation && strcmp(pLocation->GetId(), p->LocationId) != 0)
|
|
{
|
|
p = p->pNext;
|
|
continue;
|
|
}
|
|
// everything matches just update the version number
|
|
p->Version = dwNewVersion;
|
|
return F_OK;
|
|
}
|
|
p = p->pNext;
|
|
}
|
|
}
|
|
|
|
// see if we already have this version if so update to location
|
|
if (m_pHead)
|
|
{
|
|
p = m_pHead;
|
|
|
|
while (p)
|
|
{
|
|
if (p->Version == dwNewVersion && p->CollectionNumber == ColNo)
|
|
{
|
|
// same version update location
|
|
p->bSupportsMerge = bSupportsMerge;
|
|
if (FileName)
|
|
AllocSetValue(FileName, &p->FileName);
|
|
else
|
|
p->FileName = NULL;
|
|
|
|
if (IndexFile)
|
|
AllocSetValue(IndexFile, &p->IndexFileName);
|
|
else
|
|
p->IndexFileName = NULL;
|
|
|
|
if (SampleLocation)
|
|
AllocSetValue(SampleLocation, &p->SampleLocation);
|
|
else
|
|
p->SampleLocation = NULL;
|
|
|
|
if (QueryLocation)
|
|
AllocSetValue(QueryLocation, &p->QueryLocation);
|
|
else
|
|
p->QueryLocation = NULL;
|
|
|
|
if (Query)
|
|
AllocSetValue(Query, &p->QueryFileName);
|
|
else
|
|
p->QueryFileName = NULL;
|
|
|
|
if (pLocation)
|
|
AllocSetValue(pLocation->GetId() , &p->LocationId);
|
|
else
|
|
p->LocationId = NULL;
|
|
|
|
return F_OK;
|
|
}
|
|
p = p->pNext;
|
|
}
|
|
}
|
|
|
|
p = NewLocationHistory();
|
|
|
|
if (p == NULL)
|
|
return F_MEMORY;
|
|
|
|
p->Version = dwNewVersion;
|
|
p->CollectionNumber = ColNo;
|
|
p->bSupportsMerge = bSupportsMerge;
|
|
if (FileName)
|
|
AllocSetValue(FileName, &p->FileName);
|
|
if (IndexFile)
|
|
AllocSetValue(IndexFile, &p->IndexFileName);
|
|
if (SampleLocation)
|
|
AllocSetValue(SampleLocation, &p->SampleLocation);
|
|
if (QueryLocation)
|
|
AllocSetValue(QueryLocation, &p->QueryLocation);
|
|
else
|
|
AllocSetValue("", &p->QueryLocation);
|
|
|
|
if (Query)
|
|
AllocSetValue(Query, &p->QueryFileName);
|
|
else
|
|
AllocSetValue("", &p->QueryFileName);
|
|
|
|
if (pLocation)
|
|
AllocSetValue(pLocation->GetId() , &p->LocationId);
|
|
|
|
return F_OK;
|
|
}
|
|
|
|
LOCATIONHISTORY * CTitle::GetLocation(DWORD Index)
|
|
{
|
|
LOCATIONHISTORY *p;
|
|
|
|
p = m_pHead;
|
|
for (DWORD i = 0; p && i < Index; i++)
|
|
p++;
|
|
|
|
return p;
|
|
}
|
|
|
|
CTitle* CTitle::GetNextTitle()
|
|
{
|
|
return NextTitle;
|
|
}
|
|
|
|
CTitle::~CTitle()
|
|
{
|
|
if (Id) delete Id;
|
|
if (pwcId)
|
|
delete pwcId;
|
|
|
|
// clean up location history
|
|
LOCATIONHISTORY *p, *pNext;
|
|
for (p = m_pHead; p; p=pNext)
|
|
{
|
|
pNext = p->pNext;
|
|
if (p->FileName) delete p->FileName;
|
|
if (p->IndexFileName) delete p->IndexFileName;
|
|
if (p->QueryFileName) delete p->QueryFileName;
|
|
if (p->LocationId) delete p->LocationId;
|
|
if (p->SampleLocation) delete p->SampleLocation;
|
|
if (p->QueryLocation) delete p->QueryLocation;
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
CTitle::CTitle()
|
|
{
|
|
Id = NULL;
|
|
pwcId = NULL;
|
|
Language = 0;
|
|
NextTitle = NULL;
|
|
m_pHead = NULL;
|
|
m_pTail = NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CLocation implementation
|
|
|
|
// BUGBUG: 29-May-1997 [ralphw] This is a lot of code overhead to call
|
|
// functions that do nothing but return a value or exectue a single line
|
|
// of code. These should all be inlined, at least for the OCX version
|
|
// to cut down code size.
|
|
|
|
void CLocation::SetId(const CHAR *sz)
|
|
{
|
|
AllocSetValue(sz, &Id);
|
|
}
|
|
|
|
void CLocation::SetTitle(const CHAR *sz)
|
|
{
|
|
AllocSetValue(sz, &Title);
|
|
}
|
|
|
|
void CLocation::SetPath(const CHAR *sz)
|
|
{
|
|
AllocSetValue(sz, &Path);
|
|
}
|
|
|
|
void CLocation::SetVolume(const CHAR *sz)
|
|
{
|
|
AllocSetValue(sz, &Volume);
|
|
}
|
|
|
|
CHAR * CLocation::GetId() const
|
|
{
|
|
return Id;
|
|
}
|
|
|
|
CHAR * CLocation::GetTitle()
|
|
{
|
|
return Title;
|
|
}
|
|
|
|
CHAR * CLocation::GetPath()
|
|
{
|
|
return Path;
|
|
}
|
|
|
|
CHAR * CLocation::GetVolume()
|
|
{
|
|
return Volume;
|
|
}
|
|
|
|
// Returns the next location
|
|
CLocation * CLocation::GetNextLocation()
|
|
{
|
|
return NextLocation;
|
|
}
|
|
|
|
// UNICODE APIs /////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
void CFolder::SetTitle(const WCHAR *pTitle)
|
|
{
|
|
CAnsi cszTemp((WCHAR *)pTitle);
|
|
SetTitle((char *)cszTemp);
|
|
}
|
|
|
|
const WCHAR * CFolder::GetTitleW()
|
|
{
|
|
if(pwcTitle)
|
|
delete [] pwcTitle;
|
|
|
|
pwcTitle = CreateUnicodeFromAnsi(Title);
|
|
|
|
return pwcTitle;
|
|
}
|
|
|
|
CFolder * CFolder::AddChildFolder(const WCHAR *szName, DWORD Order, DWORD *pError, LANGID LangId)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)szName);
|
|
return AddChildFolder((CHAR *)cszTemp1,Order,pError,LangId);
|
|
}
|
|
|
|
|
|
const WCHAR * CTitle::GetIdW()
|
|
{
|
|
if(pwcId)
|
|
delete [] pwcId;
|
|
|
|
pwcId = CreateUnicodeFromAnsi(Id);
|
|
|
|
return pwcId;
|
|
}
|
|
|
|
void CTitle::SetId(const WCHAR *pszId)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pszId);
|
|
SetId((CHAR *)cszTemp1);
|
|
}
|
|
|
|
DWORD CTitle::AddLocationHistory(DWORD ColNo, const WCHAR *FileName, const WCHAR *IndexFile, const WCHAR *Query, const CLocation *pLocation, const WCHAR *Sample, const WCHAR *QueryLocation, BOOL bSupportsMerge)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)FileName);
|
|
CAnsi cszTemp2((WCHAR *)IndexFile);
|
|
CAnsi cszTemp3((WCHAR *)Query);
|
|
CAnsi cszTemp4((WCHAR *)Sample);
|
|
CAnsi cszTemp5((WCHAR *)QueryLocation);
|
|
return AddLocationHistory(ColNo, (CHAR *)cszTemp1, (CHAR *)cszTemp2, (CHAR *)cszTemp3, pLocation, (CHAR *)cszTemp4, (CHAR *)cszTemp5, bSupportsMerge);
|
|
}
|
|
|
|
void CLocation::SetId(const WCHAR *pwcTemp)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pwcTemp);
|
|
SetId((CHAR *)cszTemp1);
|
|
}
|
|
|
|
void CLocation::SetTitle(const WCHAR *pwcTemp)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pwcTemp);
|
|
SetTitle((CHAR *)cszTemp1);
|
|
}
|
|
|
|
void CLocation::SetPath(const WCHAR *pwcTemp)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pwcTemp);
|
|
SetPath((CHAR *)cszTemp1);
|
|
}
|
|
|
|
void CLocation::SetVolume(const WCHAR *pwcTemp)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pwcTemp);
|
|
SetVolume((CHAR *)cszTemp1);
|
|
}
|
|
|
|
const WCHAR * CLocation::GetIdW()
|
|
{
|
|
if(pwcId)
|
|
delete [] pwcId;
|
|
|
|
pwcId = CreateUnicodeFromAnsi(Id);
|
|
|
|
return pwcId;
|
|
}
|
|
|
|
const WCHAR * CLocation::GetTitleW()
|
|
{
|
|
if(pwcTitle)
|
|
delete [] pwcTitle;
|
|
|
|
pwcTitle = CreateUnicodeFromAnsi(Title);
|
|
|
|
return pwcTitle;
|
|
}
|
|
|
|
const WCHAR * CLocation::GetPathW()
|
|
{
|
|
if(pwcPath)
|
|
delete [] pwcPath;
|
|
|
|
pwcPath = CreateUnicodeFromAnsi(Path);
|
|
|
|
return pwcPath;
|
|
}
|
|
|
|
const WCHAR * CLocation::GetVolumeW()
|
|
{
|
|
if(pwcVolume)
|
|
delete [] pwcVolume;
|
|
|
|
pwcVolume = CreateUnicodeFromAnsi(Volume);
|
|
|
|
return pwcVolume;
|
|
}
|
|
|
|
DWORD CCollection::CheckTitleRef(const WCHAR *pId, const LANGID Lang)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pId);
|
|
return CheckTitleRef(cszTemp1, Lang);
|
|
}
|
|
|
|
void CCollection::SetSampleLocation(const WCHAR *pwcItem1)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pwcItem1);
|
|
SetSampleLocation(cszTemp1);
|
|
}
|
|
|
|
const WCHAR * CCollection::GetSampleLocationW()
|
|
{
|
|
if(m_pwcSampleLocation)
|
|
delete [] m_pwcSampleLocation;
|
|
|
|
m_pwcSampleLocation = CreateUnicodeFromAnsi(m_szSampleLocation);
|
|
|
|
return m_pwcSampleLocation;
|
|
}
|
|
|
|
void CCollection::SetMasterCHM(const WCHAR *szName, LANGID Lang)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)szName);
|
|
SetMasterCHM(cszTemp1, Lang);
|
|
}
|
|
|
|
BOOL CCollection::GetMasterCHM(WCHAR ** szName, LANGID *pLang)
|
|
{
|
|
*pLang = m_MasterLangId;
|
|
*szName = NULL;
|
|
if (m_szMasterCHM == NULL)
|
|
return FALSE;
|
|
|
|
if(m_pwcMasterCHM)
|
|
delete [] m_pwcMasterCHM;
|
|
|
|
m_pwcMasterCHM = CreateUnicodeFromAnsi(m_szMasterCHM);
|
|
|
|
*szName = m_pwcMasterCHM;
|
|
|
|
return ((strlen(m_szMasterCHM) ? TRUE : FALSE));
|
|
}
|
|
|
|
DWORD CCollection::Open(const WCHAR * FileName)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)FileName);
|
|
return Open(cszTemp1);
|
|
}
|
|
|
|
CTitle * CCollection::FindTitle(const WCHAR * Id, LANGID LangId)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)Id);
|
|
return FindTitle(cszTemp1, LangId);
|
|
}
|
|
|
|
CLocation * CCollection::FindLocation(const WCHAR * Name, UINT* puiVolumeOrder)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)Name);
|
|
return FindLocation(cszTemp1,puiVolumeOrder);
|
|
}
|
|
|
|
CFolder * CCollection::AddFolder(const WCHAR * szName, DWORD Order, DWORD *pDWORD, LANGID LangId)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)szName);
|
|
return AddFolder(cszTemp1, Order, pDWORD, LangId);
|
|
}
|
|
|
|
CTitle * CCollection::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,
|
|
const WCHAR *QueryLocation)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)Id);
|
|
CAnsi cszTemp2((WCHAR *)FileName);
|
|
CAnsi cszTemp3((WCHAR *)IndexFile);
|
|
CAnsi cszTemp4((WCHAR *)Query);
|
|
CAnsi cszTemp5((WCHAR *)SampleLocation);
|
|
CAnsi cszTemp6((WCHAR *)QueryLocation);
|
|
return AddTitle(cszTemp1, cszTemp2, cszTemp3, cszTemp4,cszTemp5, Lang, uiFlags, pLocation, pDWORD, bSupportsMerge, cszTemp6);
|
|
}
|
|
|
|
CLocation * CCollection::AddLocation(const WCHAR * Title, const WCHAR * Path, const WCHAR * Id, const WCHAR * Volume, DWORD *pDWORD)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)Title);
|
|
CAnsi cszTemp2((WCHAR *)Path);
|
|
CAnsi cszTemp3((WCHAR *)Id);
|
|
CAnsi cszTemp4((WCHAR *)Volume);
|
|
return AddLocation(cszTemp1, cszTemp2,cszTemp3,cszTemp4,pDWORD);
|
|
}
|
|
|
|
|
|
BOOL CCollection::MergeKeywords(WCHAR * pwzFilename )
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)pwzFilename);
|
|
return MergeKeywords(cszTemp1);
|
|
}
|
|
|
|
const WCHAR *CCollection::GetCollectionFileNameW(void)
|
|
{
|
|
if(m_pwcFileName)
|
|
delete [] m_pwcFileName;
|
|
|
|
m_pwcFileName = CreateUnicodeFromAnsi(m_szFileName);
|
|
|
|
return m_pwcFileName;
|
|
}
|
|
|
|
LANGID CCollection::GetLangId(const WCHAR *FileName)
|
|
{
|
|
CAnsi cszTemp1((WCHAR *)FileName);
|
|
return GetLangId(cszTemp1);
|
|
}
|
|
|
|
WCHAR *CreateUnicodeFromAnsi(LPSTR psz)
|
|
{
|
|
LPWSTR pwsz;
|
|
int i;
|
|
|
|
if(!psz)
|
|
return NULL;
|
|
|
|
i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
|
|
if (i <= 0)
|
|
return NULL;
|
|
|
|
pwsz = (LPWSTR) new WCHAR[i];
|
|
|
|
if (!pwsz)
|
|
return NULL;
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i * sizeof(WCHAR));
|
|
return pwsz;
|
|
}
|
|
|
|
|
|
CAnsi::CAnsi(WCHAR *pwcString)
|
|
{
|
|
m_pszChar = NULL;
|
|
|
|
int i;
|
|
|
|
i = WideCharToMultiByte(CP_ACP, 0, pwcString, -1, NULL, 0, NULL, NULL);
|
|
|
|
if (i <= 0)
|
|
return;
|
|
|
|
m_pszChar = (CHAR *) new CHAR[i];
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, pwcString, -1, m_pszChar, i, NULL, NULL);
|
|
m_pszChar[i - 1] = 0;
|
|
}
|
|
|
|
CAnsi::~CAnsi()
|
|
{
|
|
if(m_pszChar)
|
|
delete [] m_pszChar;
|
|
}
|
|
|
|
|
|
#ifdef HHCTRL
|
|
|
|
//
|
|
// CSlotLookupTable implementation...
|
|
//
|
|
|
|
int FASTCALL CSlotLookupTable::ltqs_callback(const void *elem1, const void *elem2)
|
|
{
|
|
struct _slt* p1 = (struct _slt*)elem1;
|
|
struct _slt* p2 = (struct _slt*)elem2;
|
|
|
|
if ( p1->hash > p2->hash )
|
|
return 1;
|
|
else if ( p2->hash > p1->hash )
|
|
return -1;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
CSlotLookupTable::CSlotLookupTable()
|
|
{
|
|
m_pSLT = NULL;
|
|
m_uiTotalCnt = m_uiHashCnt = m_uiTotalAllocated = 0;
|
|
}
|
|
|
|
CSlotLookupTable::~CSlotLookupTable()
|
|
{
|
|
if ( m_pSLT )
|
|
lcFree(m_pSLT);
|
|
}
|
|
|
|
void CSlotLookupTable::AddValue(CFolder* pFolder)
|
|
{
|
|
if ( (m_uiTotalCnt && (!(m_uiTotalCnt % 8))) || (m_uiTotalAllocated == 0) )
|
|
{
|
|
m_uiTotalAllocated += 8;
|
|
m_pSLT = (struct _slt*)lcReAlloc(m_pSLT, sizeof(struct _slt) * m_uiTotalAllocated);
|
|
}
|
|
m_pSLT[m_uiTotalCnt].pCFolder = pFolder;
|
|
if ( pFolder->f_HasHash )
|
|
{
|
|
m_pSLT[m_uiTotalCnt].hash = pFolder->pExTitle->m_dwHash;
|
|
m_uiHashCnt++;
|
|
}
|
|
else
|
|
m_pSLT[m_uiTotalCnt].hash = (unsigned)(-1);
|
|
m_uiTotalCnt++;
|
|
}
|
|
|
|
void CSlotLookupTable::SortAndAssignSlots(void)
|
|
{
|
|
unsigned i;
|
|
|
|
// First, sort by hash.
|
|
//
|
|
qsort(m_pSLT, m_uiTotalCnt, sizeof(struct _slt), ltqs_callback);
|
|
//
|
|
// Next, run through the table and assign the slots back to the CFolders.
|
|
//
|
|
for (i = 0; i < m_uiTotalCnt; i++)
|
|
m_pSLT[i].pCFolder->dwSlot = i;
|
|
}
|
|
|
|
CFolder* CSlotLookupTable::HashToCFolder(HASH hash)
|
|
{
|
|
if (! m_pSLT )
|
|
return NULL;
|
|
|
|
int mid,low = 0;
|
|
int high = m_uiHashCnt - 1;
|
|
|
|
while ( low <= high )
|
|
{
|
|
mid = ((low + high) / 2);
|
|
if ( m_pSLT[mid].hash == hash )
|
|
return m_pSLT[mid].pCFolder; // Found it!
|
|
else if ( m_pSLT[mid].hash > hash )
|
|
high = mid - 1;
|
|
else
|
|
low = mid + 1;
|
|
}
|
|
return NULL; // Oh bad!
|
|
}
|
|
|
|
#endif
|