implemented nested index entries and index entries pointing to multiple documents in wxHtmlHelpController; modified wxHtmlHelpData API to make it possible

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28065 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2004-06-28 21:45:30 +00:00
parent 5f7358f0fb
commit 91fa114d88
5 changed files with 624 additions and 311 deletions

View File

@@ -151,6 +151,11 @@ wxWinCE:
- added automatized but customizable handling of native SmartPhone menus - added automatized but customizable handling of native SmartPhone menus
wxHTML:
- added support for nested index entries and index entries pointing to more
than one page to wxHtmlHelpController
2.5.2 2.5.2
----- -----

View File

@@ -53,29 +53,17 @@ Returns page's URL based on its (file)name.
Returns array with help books info. Returns array with help books info.
\membersection{wxHtmlHelpData::GetContents}\label{wxhtmlhelpdatagetcontents} \membersection{wxHtmlHelpData::GetContentsArray}\label{wxhtmlhelpdatagetcontentsarray}
\func{wxHtmlContentsItem*}{GetContents}{\void} \func{const wxHtmlHelpDataItems\&}{GetContentsArray}{\void}
Returns contents lists pointer. Returns reference to array with contents entries.
\membersection{wxHtmlHelpData::GetContentsCnt}\label{wxhtmlhelpdatagetcontentscnt} \membersection{wxHtmlHelpData::GetIndexArray}\label{wxhtmlhelpdatagetindexarray}
\func{int}{GetContentsCnt}{\void} \func{const wxHtmlHelpDataItems\&}{GetIndexArray}{\void}
Returns size of contents list. Returns reference to array with index entries.
\membersection{wxHtmlHelpData::GetIndex}\label{wxhtmlhelpdatagetindex}
\func{wxHtmlContentsItem*}{GetIndex}{\void}
Returns pointer to index items list.
\membersection{wxHtmlHelpData::GetIndexCnt}\label{wxhtmlhelpdatagetindexcnt}
\func{int}{GetIndexCnt}{\void}
Returns size of index list.
\membersection{wxHtmlHelpData::SetTempDir}\label{wxhtmlhelpdatasettempdir} \membersection{wxHtmlHelpData::SetTempDir}\label{wxhtmlhelpdatasettempdir}

View File

@@ -80,18 +80,50 @@ protected:
WX_DECLARE_USER_EXPORTED_OBJARRAY(wxHtmlBookRecord, wxHtmlBookRecArray, WX_DECLARE_USER_EXPORTED_OBJARRAY(wxHtmlBookRecord, wxHtmlBookRecArray,
WXDLLIMPEXP_HTML); WXDLLIMPEXP_HTML);
struct WXDLLIMPEXP_HTML wxHtmlHelpDataItem
{
wxHtmlHelpDataItem() : level(0), parent(NULL), id(-1), book(NULL) {}
short int level;
wxHtmlHelpDataItem *parent;
int id;
wxString name;
wxString page;
wxHtmlBookRecord *book;
// returns full filename of m_Page, i.e. with book's basePath prepended
wxString GetFullPath() const { return book->GetFullPath(page); }
// returns item indented with spaces if it has level>1:
wxString GetIndentedName() const;
};
WX_DECLARE_USER_EXPORTED_OBJARRAY(wxHtmlHelpDataItem, wxHtmlHelpDataItems,
WXDLLIMPEXP_HTML);
#if WXWIN_COMPATIBILITY_2_4
// old interface to contents and index:
struct wxHtmlContentsItem struct wxHtmlContentsItem
{ {
wxHtmlContentsItem();
wxHtmlContentsItem(const wxHtmlHelpDataItem& d);
wxHtmlContentsItem& operator=(const wxHtmlContentsItem& d);
~wxHtmlContentsItem();
short int m_Level; short int m_Level;
int m_ID; int m_ID;
wxString m_Name; wxChar *m_Name;
wxString m_Page; wxChar *m_Page;
wxHtmlBookRecord *m_Book; wxHtmlBookRecord *m_Book;
// returns full filename of m_Page, i.e. with book's basePath prepended // returns full filename of m_Page, i.e. with book's basePath prepended
wxString GetFullPath() const { return m_Book->GetFullPath(m_Page); } wxString GetFullPath() const { return m_Book->GetFullPath(m_Page); }
private:
bool m_autofree;
}; };
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// wxHtmlSearchEngine // wxHtmlSearchEngine
@@ -138,14 +170,18 @@ public:
int GetCurIndex() { return m_CurIndex; } int GetCurIndex() { return m_CurIndex; }
int GetMaxIndex() { return m_MaxIndex; } int GetMaxIndex() { return m_MaxIndex; }
const wxString& GetName() { return m_Name; } const wxString& GetName() { return m_Name; }
wxHtmlContentsItem* GetContentsItem() { return m_ContentsItem; }
const wxHtmlHelpDataItem *GetCurItem() const { return m_CurItem; }
#if WXWIN_COMPATIBILITY_2_4
wxDEPRECATED( wxHtmlContentsItem* GetContentsItem() );
#endif
private: private:
wxHtmlHelpData* m_Data; wxHtmlHelpData* m_Data;
wxHtmlSearchEngine m_Engine; wxHtmlSearchEngine m_Engine;
wxString m_Keyword, m_Name; wxString m_Keyword, m_Name;
wxString m_LastPage; wxString m_LastPage;
wxHtmlContentsItem* m_ContentsItem; wxHtmlHelpDataItem* m_CurItem;
bool m_Active; // search is not finished bool m_Active; // search is not finished
int m_CurIndex; // where we are now int m_CurIndex; // where we are now
int m_MaxIndex; // number of files we search int m_MaxIndex; // number of files we search
@@ -186,21 +222,36 @@ public:
// returns URL of page on basis of MS id // returns URL of page on basis of MS id
wxString FindPageById(int id); wxString FindPageById(int id);
const wxHtmlBookRecArray& GetBookRecArray() { return m_BookRecords; } const wxHtmlBookRecArray& GetBookRecArray() const { return m_bookRecords; }
wxHtmlContentsItem* GetContents() { return m_Contents; }
int GetContentsCnt() { return m_ContentsCnt; } const wxHtmlHelpDataItems& GetContentsArray() const { return m_contents; }
wxHtmlContentsItem* GetIndex() { return m_Index; } const wxHtmlHelpDataItems& GetIndexArray() const { return m_index; }
int GetIndexCnt() { return m_IndexCnt; }
#if WXWIN_COMPATIBILITY_2_4
// deprecated interface, new interface is arrays-based (see above)
wxDEPRECATED( wxHtmlContentsItem* GetContents() );
wxDEPRECATED( int GetContentsCnt() );
wxDEPRECATED( wxHtmlContentsItem* GetIndex() );
wxDEPRECATED( int GetIndexCnt() );
#endif
protected: protected:
wxString m_TempPath; wxString m_tempPath;
wxHtmlBookRecArray m_BookRecords;
// each book has one record in this array: // each book has one record in this array:
wxHtmlContentsItem* m_Contents; wxHtmlBookRecArray m_bookRecords;
int m_ContentsCnt;
wxHtmlContentsItem* m_Index; // list of all available books and pages. wxHtmlHelpDataItems m_contents; // list of all available books and pages
int m_IndexCnt; // list of index items wxHtmlHelpDataItems m_index; // list of index itesm
#if WXWIN_COMPATIBILITY_2_4
// deprecated data structures, set only if GetContents(), GetIndex()
// called
wxHtmlContentsItem* m_cacheContents;
wxHtmlContentsItem* m_cacheIndex;
private:
void CleanCompatibilityData();
#endif
protected: protected:
// Imports .hhp files (MS HTML Help Workshop) // Imports .hhp files (MS HTML Help Workshop)

View File

@@ -45,6 +45,7 @@
#include "wx/arrimpl.cpp" #include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(wxHtmlBookRecArray) WX_DEFINE_OBJARRAY(wxHtmlBookRecArray)
WX_DEFINE_OBJARRAY(wxHtmlHelpDataItems)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// static helper functions // static helper functions
@@ -71,23 +72,46 @@ static const wxChar* ReadLine(const wxChar *line, wxChar *buf, size_t bufsize)
extern "C" int LINKAGEMODE static int
wxHtmlHelpIndexCompareFunc(const void *a, const void *b) wxHtmlHelpIndexCompareFunc(wxHtmlHelpDataItem **a, wxHtmlHelpDataItem **b)
{ {
return ((wxHtmlContentsItem*)a)->m_Name.CmpNoCase(((wxHtmlContentsItem*)b)->m_Name); wxHtmlHelpDataItem *ia = *a;
wxHtmlHelpDataItem *ib = *b;
if (ia->parent == ib->parent)
{
return ia->name.CmpNoCase(ib->name);
}
else if (ia->level == ib->level)
{
return wxHtmlHelpIndexCompareFunc(&ia->parent, &ib->parent);
}
else
{
wxHtmlHelpDataItem *ia2 = ia;
wxHtmlHelpDataItem *ib2 = ib;
while (ia2->level > ib2->level)
{
ia2 = ia2->parent;
}
while (ib2->level > ia2->level)
{
ib2 = ib2->parent;
}
wxASSERT(ia2);
wxASSERT(ib2);
int res = wxHtmlHelpIndexCompareFunc(&ia2, &ib2);
if (res != 0)
return res;
else if (ia->level > ib->level)
return 1;
else
return -1;
}
} }
template<typename T>
static T* ReallocArray(T *arr, size_t oldsize, size_t newsize)
{
T *newarr = new T[newsize];
for (size_t i = 0; i < oldsize; i++)
newarr[i] = arr[i];
return newarr;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// HP_Parser // HP_Parser
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -116,22 +140,37 @@ protected:
class HP_TagHandler : public wxHtmlTagHandler class HP_TagHandler : public wxHtmlTagHandler
{ {
private: private:
wxString m_Name, m_Page; wxString m_name, m_page;
int m_Level; int m_level;
int m_ID; int m_id;
int m_Index; int m_index;
wxHtmlContentsItem *m_Items; int m_count;
int m_ItemsCnt; wxHtmlHelpDataItem *m_parentItem;
wxHtmlBookRecord *m_Book; wxHtmlBookRecord *m_book;
wxHtmlHelpDataItems *m_data;
public: public:
HP_TagHandler(wxHtmlBookRecord *b) : wxHtmlTagHandler() HP_TagHandler(wxHtmlBookRecord *b) : wxHtmlTagHandler()
{ m_Book = b; m_Items = NULL; m_ItemsCnt = 0; m_Name = m_Page = wxEmptyString; {
m_Level = 0; m_ID = -1; } m_data = NULL;
m_book = b;
m_name = m_page = wxEmptyString;
m_level = 0;
m_id = -1;
m_count = 0;
m_parentItem = NULL;
}
wxString GetSupportedTags() { return wxT("UL,OBJECT,PARAM"); } wxString GetSupportedTags() { return wxT("UL,OBJECT,PARAM"); }
bool HandleTag(const wxHtmlTag& tag); bool HandleTag(const wxHtmlTag& tag);
void WriteOut(wxHtmlContentsItem*& array, int& size);
void ReadIn(wxHtmlContentsItem* array, int size); void Reset(wxHtmlHelpDataItems& data)
{
m_data = &data;
m_count = 0;
m_level = 0;
m_parentItem = NULL;
}
DECLARE_NO_COPY_CLASS(HP_TagHandler) DECLARE_NO_COPY_CLASS(HP_TagHandler)
}; };
@@ -141,18 +180,21 @@ bool HP_TagHandler::HandleTag(const wxHtmlTag& tag)
{ {
if (tag.GetName() == wxT("UL")) if (tag.GetName() == wxT("UL"))
{ {
m_Level++; wxHtmlHelpDataItem *oldparent = m_parentItem;
m_level++;
m_parentItem = (m_count > 0) ? &(*m_data)[m_data->size()-1] : NULL;
ParseInner(tag); ParseInner(tag);
m_Level--; m_level--;
return TRUE; m_parentItem = oldparent;
return true;
} }
else if (tag.GetName() == wxT("OBJECT")) else if (tag.GetName() == wxT("OBJECT"))
{ {
m_Name = m_Page = wxEmptyString; m_name = m_page = wxEmptyString;
ParseInner(tag); ParseInner(tag);
#if 0 #if 0
if (!m_Page.IsEmpty()) if (!page.IsEmpty())
/* Valid HHW's file may contain only two object tags: /* Valid HHW's file may contain only two object tags:
<OBJECT type="text/site properties"> <OBJECT type="text/site properties">
@@ -166,57 +208,39 @@ bool HP_TagHandler::HandleTag(const wxHtmlTag& tag)
<param name="Local" value="another.htm"> <param name="Local" value="another.htm">
</OBJECT> </OBJECT>
We're interested in the latter. !m_Page.IsEmpty() is valid We're interested in the latter. !page.IsEmpty() is valid
condition because text/site properties does not contain Local param condition because text/site properties does not contain Local param
*/ */
#endif #endif
if (tag.GetParam(wxT("TYPE")) == wxT("text/sitemap")) if (tag.GetParam(wxT("TYPE")) == wxT("text/sitemap"))
{ {
if (m_ItemsCnt % wxHTML_REALLOC_STEP == 0) wxHtmlHelpDataItem *item = new wxHtmlHelpDataItem();
m_Items = ReallocArray(m_Items, m_ItemsCnt, item->parent = m_parentItem;
m_ItemsCnt + wxHTML_REALLOC_STEP); item->level = m_level;
item->id = m_id;
m_Items[m_ItemsCnt].m_Level = m_Level; item->page = m_page;
m_Items[m_ItemsCnt].m_ID = m_ID; item->name = m_name;
m_Items[m_ItemsCnt].m_Page = m_Page;
m_Items[m_ItemsCnt].m_Name = m_Name; item->book = m_book;
m_Items[m_ItemsCnt].m_Book = m_Book; m_data->Add(item);
m_ItemsCnt++; m_count++;
} }
return TRUE; return true;
} }
else else
{ // "PARAM" { // "PARAM"
if (m_Name == wxEmptyString && tag.GetParam(wxT("NAME")) == wxT("Name")) if (m_name.empty() && tag.GetParam(wxT("NAME")) == wxT("Name"))
m_Name = tag.GetParam(wxT("VALUE")); m_name = tag.GetParam(wxT("VALUE"));
if (tag.GetParam(wxT("NAME")) == wxT("Local")) if (tag.GetParam(wxT("NAME")) == wxT("Local"))
m_Page = tag.GetParam(wxT("VALUE")); m_page = tag.GetParam(wxT("VALUE"));
if (tag.GetParam(wxT("NAME")) == wxT("ID")) if (tag.GetParam(wxT("NAME")) == wxT("ID"))
tag.GetParamAsInt(wxT("VALUE"), &m_ID); tag.GetParamAsInt(wxT("VALUE"), &m_id);
return FALSE; return false;
} }
} }
void HP_TagHandler::WriteOut(wxHtmlContentsItem*& array, int& size)
{
array = m_Items;
size = m_ItemsCnt;
m_Items = NULL;
m_ItemsCnt = 0;
}
void HP_TagHandler::ReadIn(wxHtmlContentsItem* array, int size)
{
m_Items = array;
m_ItemsCnt = size;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxHtmlHelpData // wxHtmlHelpData
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -229,25 +253,31 @@ wxString wxHtmlBookRecord::GetFullPath(const wxString &page) const
return m_BasePath + page; return m_BasePath + page;
} }
wxString wxHtmlHelpDataItem::GetIndentedName() const
{
wxString s;
for (int i = 1; i < level; i++)
s << _T(" ");
s << name;
return s;
}
IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpData, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpData, wxObject)
wxHtmlHelpData::wxHtmlHelpData() wxHtmlHelpData::wxHtmlHelpData()
{ {
m_TempPath = wxEmptyString; #if WXWIN_COMPATIBILITY_2_4
m_cacheContents = NULL;
m_Contents = NULL; m_cacheIndex = NULL;
m_ContentsCnt = 0; #endif
m_Index = NULL;
m_IndexCnt = 0;
} }
wxHtmlHelpData::~wxHtmlHelpData() wxHtmlHelpData::~wxHtmlHelpData()
{ {
m_BookRecords.Empty(); #if WXWIN_COMPATIBILITY_2_4
delete[] m_Contents; CleanCompatibilityData();
delete[] m_Index; #endif
} }
bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys, bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys,
@@ -269,9 +299,8 @@ bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys,
buf.clear(); buf.clear();
buf = filter.ReadFile(*f); buf = filter.ReadFile(*f);
delete f; delete f;
handler->ReadIn(m_Contents, m_ContentsCnt); handler->Reset(m_contents);
parser.Parse(buf); parser.Parse(buf);
handler->WriteOut(m_Contents, m_ContentsCnt);
} }
else else
{ {
@@ -284,9 +313,8 @@ bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys,
buf.clear(); buf.clear();
buf = filter.ReadFile(*f); buf = filter.ReadFile(*f);
delete f; delete f;
handler->ReadIn(m_Index, m_IndexCnt); handler->Reset(m_index);
parser.Parse(buf); parser.Parse(buf);
handler->WriteOut(m_Index, m_IndexCnt);
} }
else if (!indexfile.IsEmpty()) else if (!indexfile.IsEmpty())
{ {
@@ -324,7 +352,7 @@ inline static wxString CacheReadString(wxInputStream *f)
return wxString(str, wxConvUTF8); return wxString(str, wxConvUTF8);
} }
#define CURRENT_CACHED_BOOK_VERSION 4 #define CURRENT_CACHED_BOOK_VERSION 5
// Additional flags to detect incompatibilities of the runtime environment: // Additional flags to detect incompatibilities of the runtime environment:
#define CACHED_BOOK_FORMAT_FLAGS \ #define CACHED_BOOK_FORMAT_FLAGS \
@@ -333,7 +361,7 @@ inline static wxString CacheReadString(wxInputStream *f)
bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord *book, wxInputStream *f) bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord *book, wxInputStream *f)
{ {
int i, st; int i, st, newsize;
wxInt32 version; wxInt32 version;
/* load header - version info : */ /* load header - version info : */
@@ -345,40 +373,44 @@ bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord *book, wxInputStream *f)
// it anymore, because AddBookParam will load the MS project in // it anymore, because AddBookParam will load the MS project in
// absence of (properly versioned) .cached file and automatically // absence of (properly versioned) .cached file and automatically
// create new .cached file immediately afterward. // create new .cached file immediately afterward.
return FALSE; return false;
} }
if (CacheReadInt32(f) != CACHED_BOOK_FORMAT_FLAGS) if (CacheReadInt32(f) != CACHED_BOOK_FORMAT_FLAGS)
return FALSE; return false;
/* load contents : */ /* load contents : */
st = m_ContentsCnt; st = m_contents.size();
m_ContentsCnt += CacheReadInt32(f); newsize = st + CacheReadInt32(f);
m_Contents = ReallocArray(m_Contents, st, m_contents.Alloc(newsize);
(m_ContentsCnt / wxHTML_REALLOC_STEP + 1) * for (i = st; i < newsize; i++)
wxHTML_REALLOC_STEP);
for (i = st; i < m_ContentsCnt; i++)
{ {
m_Contents[i].m_Level = CacheReadInt32(f); wxHtmlHelpDataItem *item = new wxHtmlHelpDataItem;
m_Contents[i].m_ID = CacheReadInt32(f); item->level = CacheReadInt32(f);
m_Contents[i].m_Name = CacheReadString(f); item->id = CacheReadInt32(f);
m_Contents[i].m_Page = CacheReadString(f); item->name = CacheReadString(f);
m_Contents[i].m_Book = book; item->page = CacheReadString(f);
item->book = book;
m_contents.Add(item);
} }
/* load index : */ /* load index : */
st = m_IndexCnt; st = m_index.size();
m_IndexCnt += CacheReadInt32(f); newsize = st + CacheReadInt32(f);
m_Index = ReallocArray(m_Index, st, m_index.Alloc(newsize);
(m_IndexCnt / wxHTML_REALLOC_STEP + 1) * for (i = st; i < newsize; i++)
wxHTML_REALLOC_STEP);
for (i = st; i < m_IndexCnt; i++)
{ {
m_Index[i].m_Name = CacheReadString(f); wxHtmlHelpDataItem *item = new wxHtmlHelpDataItem;
m_Index[i].m_Page = CacheReadString(f); item->name = CacheReadString(f);
m_Index[i].m_Book = book; item->page = CacheReadString(f);
item->level = CacheReadInt32(f);
item->book = book;
int parentShift = CacheReadInt32(f);
if (parentShift != 0)
item->parent = &m_index[m_index.size() - parentShift];
m_index.Add(item);
} }
return TRUE; return true;
} }
@@ -392,48 +424,71 @@ bool wxHtmlHelpData::SaveCachedBook(wxHtmlBookRecord *book, wxOutputStream *f)
CacheWriteInt32(f, CACHED_BOOK_FORMAT_FLAGS); CacheWriteInt32(f, CACHED_BOOK_FORMAT_FLAGS);
/* save contents : */ /* save contents : */
for (cnt = 0, i = 0; i < m_ContentsCnt; i++) int len = m_contents.size();
if (m_Contents[i].m_Book == book && m_Contents[i].m_Level > 0) for (cnt = 0, i = 0; i < len; i++)
if (m_contents[i].book == book && m_contents[i].level > 0)
cnt++; cnt++;
CacheWriteInt32(f, cnt); CacheWriteInt32(f, cnt);
for (i = 0; i < m_ContentsCnt; i++) for (i = 0; i < len; i++)
{ {
if (m_Contents[i].m_Book != book || m_Contents[i].m_Level == 0) if (m_contents[i].book != book || m_contents[i].level == 0)
continue; continue;
CacheWriteInt32(f, m_Contents[i].m_Level); CacheWriteInt32(f, m_contents[i].level);
CacheWriteInt32(f, m_Contents[i].m_ID); CacheWriteInt32(f, m_contents[i].id);
CacheWriteString(f, m_Contents[i].m_Name); CacheWriteString(f, m_contents[i].name);
CacheWriteString(f, m_Contents[i].m_Page); CacheWriteString(f, m_contents[i].page);
} }
/* save index : */ /* save index : */
for (cnt = 0, i = 0; i < m_IndexCnt; i++) len = m_index.size();
if (m_Index[i].m_Book == book && m_Index[i].m_Level > 0) for (cnt = 0, i = 0; i < len; i++)
if (m_index[i].book == book && m_index[i].level > 0)
cnt++; cnt++;
CacheWriteInt32(f, cnt); CacheWriteInt32(f, cnt);
for (i = 0; i < m_IndexCnt; i++) for (i = 0; i < len; i++)
{ {
if (m_Index[i].m_Book != book || m_Index[i].m_Level == 0) if (m_index[i].book != book || m_index[i].level == 0)
continue; continue;
CacheWriteString(f, m_Index[i].m_Name); CacheWriteString(f, m_index[i].name);
CacheWriteString(f, m_Index[i].m_Page); CacheWriteString(f, m_index[i].page);
CacheWriteInt32(f, m_index[i].level);
// save distance to parent item, if any:
if (m_index[i].parent == NULL)
{
CacheWriteInt32(f, 0);
}
else
{
int cnt = 0;
wxHtmlHelpDataItem *parent = m_index[i].parent;
for (int j = i-1; j >= 0; j--)
{
if (m_index[j].book == book && m_index[j].level > 0)
cnt++;
if (&m_index[j] == parent)
break;
}
wxASSERT(cnt > 0);
CacheWriteInt32(f, cnt);
}
} }
return TRUE; return true;
} }
void wxHtmlHelpData::SetTempDir(const wxString& path) void wxHtmlHelpData::SetTempDir(const wxString& path)
{ {
if (path == wxEmptyString) m_TempPath = path; if (path.empty())
m_tempPath = path;
else else
{ {
if (wxIsAbsolutePath(path)) m_TempPath = path; if (wxIsAbsolutePath(path)) m_tempPath = path;
else m_TempPath = wxGetCwd() + _T("/") + path; else m_tempPath = wxGetCwd() + _T("/") + path;
if (m_TempPath[m_TempPath.Length() - 1] != _T('/')) if (m_tempPath[m_tempPath.Length() - 1] != _T('/'))
m_TempPath << _T('/'); m_tempPath << _T('/');
} }
} }
@@ -459,32 +514,32 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile,
wxFSFile *fi; wxFSFile *fi;
wxHtmlBookRecord *bookr; wxHtmlBookRecord *bookr;
int IndexOld = m_IndexCnt, int IndexOld = m_index.size(),
ContentsOld = m_ContentsCnt; ContentsOld = m_contents.size();
if (!path.IsEmpty()) if (!path.IsEmpty())
fsys.ChangePathTo(path, TRUE); fsys.ChangePathTo(path, TRUE);
size_t booksCnt = m_BookRecords.GetCount(); size_t booksCnt = m_bookRecords.GetCount();
for (size_t i = 0; i < booksCnt; i++) for (size_t i = 0; i < booksCnt; i++)
{ {
if ( m_BookRecords[i].GetBookFile() == bookfile.GetLocation() ) if ( m_bookRecords[i].GetBookFile() == bookfile.GetLocation() )
return TRUE; // book is (was) loaded return true; // book is (was) loaded
} }
bookr = new wxHtmlBookRecord(bookfile.GetLocation(), fsys.GetPath(), title, deftopic); bookr = new wxHtmlBookRecord(bookfile.GetLocation(), fsys.GetPath(), title, deftopic);
if (m_ContentsCnt % wxHTML_REALLOC_STEP == 0) wxHtmlHelpDataItem *bookitem = new wxHtmlHelpDataItem;
m_Contents = ReallocArray(m_Contents, m_ContentsCnt, bookitem->level = 0;
m_ContentsCnt + wxHTML_REALLOC_STEP); bookitem->id = 0;
m_Contents[m_ContentsCnt].m_Level = 0; bookitem->page = deftopic;
m_Contents[m_ContentsCnt].m_ID = 0; bookitem->name = title;
m_Contents[m_ContentsCnt].m_Page = deftopic; bookitem->book = bookr;
m_Contents[m_ContentsCnt].m_Name = title;
m_Contents[m_ContentsCnt].m_Book = bookr;
// store the contents index for later // store the contents index for later
int cont_start = m_ContentsCnt++; int cont_start = m_contents.size();
m_contents.Add(bookitem);
// Try to find cached binary versions: // Try to find cached binary versions:
// 1. save file as book, but with .hhp.cached extension // 1. save file as book, but with .hhp.cached extension
@@ -500,17 +555,17 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile,
!LoadCachedBook(bookr, fi->GetStream())) !LoadCachedBook(bookr, fi->GetStream()))
{ {
if (fi != NULL) delete fi; if (fi != NULL) delete fi;
fi = fsys.OpenFile(m_TempPath + wxFileNameFromPath(bookfile.GetLocation()) + wxT(".cached")); fi = fsys.OpenFile(m_tempPath + wxFileNameFromPath(bookfile.GetLocation()) + wxT(".cached"));
if (m_TempPath == wxEmptyString || fi == NULL || if (m_tempPath.empty() || fi == NULL ||
#if wxUSE_DATETIME #if wxUSE_DATETIME
fi->GetModificationTime() < bookfile.GetModificationTime() || fi->GetModificationTime() < bookfile.GetModificationTime() ||
#endif // wxUSE_DATETIME #endif // wxUSE_DATETIME
!LoadCachedBook(bookr, fi->GetStream())) !LoadCachedBook(bookr, fi->GetStream()))
{ {
LoadMSProject(bookr, fsys, indexfile, contfile); LoadMSProject(bookr, fsys, indexfile, contfile);
if (m_TempPath != wxEmptyString) if (!m_tempPath.empty())
{ {
wxFileOutputStream *outs = new wxFileOutputStream(m_TempPath + wxFileOutputStream *outs = new wxFileOutputStream(m_tempPath +
SafeFileName(wxFileNameFromPath(bookfile.GetLocation())) + wxT(".cached")); SafeFileName(wxFileNameFromPath(bookfile.GetLocation())) + wxT(".cached"));
SaveCachedBook(bookr, outs); SaveCachedBook(bookr, outs);
delete outs; delete outs;
@@ -521,7 +576,7 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile,
if (fi != NULL) delete fi; if (fi != NULL) delete fi;
// Now store the contents range // Now store the contents range
bookr->SetContentsRange(cont_start, m_ContentsCnt); bookr->SetContentsRange(cont_start, m_contents.size());
#if wxUSE_WCHAR_T #if wxUSE_WCHAR_T
// MS HTML Help files [written by MS HTML Help Workshop] are broken // MS HTML Help files [written by MS HTML Help Workshop] are broken
@@ -538,14 +593,16 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile,
str = wxString((str).wc_str(conv), wxConvLocal) str = wxString((str).wc_str(conv), wxConvLocal)
#endif #endif
wxCSConv conv(encoding); wxCSConv conv(encoding);
int i; size_t IndexCnt = m_index.size();
for (i = IndexOld; i < m_IndexCnt; i++) size_t ContentsCnt = m_contents.size();
size_t i;
for (i = IndexOld; i < IndexCnt; i++)
{ {
CORRECT_STR(m_Index[i].m_Name, conv); CORRECT_STR(m_index[i].name, conv);
} }
for (i = ContentsOld; i < m_ContentsCnt; i++) for (i = ContentsOld; i < ContentsCnt; i++)
{ {
CORRECT_STR(m_Contents[i].m_Name, conv); CORRECT_STR(m_contents[i].name, conv);
} }
#undef CORRECT_STR #undef CORRECT_STR
} }
@@ -555,11 +612,13 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile,
wxASSERT_MSG(encoding == wxFONTENCODING_SYSTEM, wxT("Help files need charset conversion, but wxUSE_WCHAR_T is 0")); wxASSERT_MSG(encoding == wxFONTENCODING_SYSTEM, wxT("Help files need charset conversion, but wxUSE_WCHAR_T is 0"));
#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T
m_BookRecords.Add(bookr); m_bookRecords.Add(bookr);
if (m_IndexCnt > 0) if (!m_index.empty())
qsort(m_Index, m_IndexCnt, sizeof(wxHtmlContentsItem), wxHtmlHelpIndexCompareFunc); {
m_index.Sort(wxHtmlHelpIndexCompareFunc);
}
return TRUE; return true;
} }
@@ -643,6 +702,11 @@ bool wxHtmlHelpData::AddBook(const wxString& book)
bool rtval = AddBookParam(*fi, enc, bool rtval = AddBookParam(*fi, enc,
title, contents, index, start, fsys.GetPath()); title, contents, index, start, fsys.GetPath());
delete fi; delete fi;
#if WXWIN_COMPATIBILITY_2_4
CleanCompatibilityData();
#endif
return rtval; return rtval;
} }
@@ -652,17 +716,16 @@ wxString wxHtmlHelpData::FindPageByName(const wxString& x)
int i; int i;
wxFileSystem fsys; wxFileSystem fsys;
wxFSFile *f; wxFSFile *f;
wxString url(wxEmptyString);
/* 1. try to open given file: */ /* 1. try to open given file: */
cnt = m_BookRecords.GetCount(); cnt = m_bookRecords.GetCount();
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
{ {
f = fsys.OpenFile(m_BookRecords[i].GetFullPath(x)); f = fsys.OpenFile(m_bookRecords[i].GetFullPath(x));
if (f) if (f)
{ {
url = m_BookRecords[i].GetFullPath(x); wxString url = m_bookRecords[i].GetFullPath(x);
delete f; delete f;
return url; return url;
} }
@@ -673,58 +736,131 @@ wxString wxHtmlHelpData::FindPageByName(const wxString& x)
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
{ {
if (m_BookRecords[i].GetTitle() == x) if (m_bookRecords[i].GetTitle() == x)
{ return m_bookRecords[i].GetFullPath(m_bookRecords[i].GetStart());
url = m_BookRecords[i].GetFullPath(m_BookRecords[i].GetStart());
return url;
}
} }
/* 3. try to find in contents: */ /* 3. try to find in contents: */
cnt = m_ContentsCnt; cnt = m_contents.size();
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
{ {
if (m_Contents[i].m_Name == x) if (m_contents[i].name == x)
{ return m_contents[i].GetFullPath();
url = m_Contents[i].GetFullPath();
return url;
}
} }
/* 4. try to find in index: */ /* 4. try to find in index: */
cnt = m_IndexCnt; cnt = m_index.size();
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
{ {
if (m_Index[i].m_Name == x) if (m_index[i].name == x)
{ return m_index[i].GetFullPath();
url = m_Index[i].GetFullPath();
return url;
}
} }
return url; return wxEmptyString;
} }
wxString wxHtmlHelpData::FindPageById(int id) wxString wxHtmlHelpData::FindPageById(int id)
{ {
int i; size_t cnt = m_contents.size();
wxString url(wxEmptyString); for (size_t i = 0; i < cnt; i++)
for (i = 0; i < m_ContentsCnt; i++)
{ {
if (m_Contents[i].m_ID == id) if (m_contents[i].id == id)
{ {
url = m_Contents[i].GetFullPath(); return m_contents[i].GetFullPath();
return url;
} }
} }
return url; return wxEmptyString;
} }
#if WXWIN_COMPATIBILITY_2_4
wxHtmlContentsItem::wxHtmlContentsItem()
: m_Level(0), m_ID(-1), m_Name(NULL), m_Page(NULL), m_Book(NULL),
m_autofree(false)
{
}
wxHtmlContentsItem::wxHtmlContentsItem(const wxHtmlHelpDataItem& d)
{
m_autofree = true;
m_Level = d.level;
m_ID = d.id;
m_Name = wxStrdup(d.name.c_str());
m_Page = wxStrdup(d.page.c_str());
m_Book = d.book;
}
wxHtmlContentsItem& wxHtmlContentsItem::operator=(const wxHtmlContentsItem& d)
{
if (m_autofree)
{
free(m_Name);
free(m_Page);
}
m_autofree = true;
m_Level = d.m_Level;
m_ID = d.m_ID;
m_Name = d.m_Name ? wxStrdup(d.m_Name) : NULL;
m_Page = d.m_Page ? wxStrdup(d.m_Page) : NULL;
m_Book = d.m_Book;
return *this;
}
wxHtmlContentsItem::~wxHtmlContentsItem()
{
if (m_autofree)
{
free(m_Name);
free(m_Page);
}
}
wxHtmlContentsItem* wxHtmlHelpData::GetContents()
{
if (!m_cacheContents && !m_contents.empty())
{
size_t len = m_contents.size();
m_cacheContents = new wxHtmlContentsItem[len];
for (size_t i = 0; i < len; i++)
m_cacheContents[i] = m_contents[i];
}
return m_cacheContents;
}
int wxHtmlHelpData::GetContentsCnt()
{
return m_contents.size();
}
wxHtmlContentsItem* wxHtmlHelpData::GetIndex()
{
if (!m_cacheContents && !m_index.empty())
{
size_t len = m_index.size();
m_cacheContents = new wxHtmlContentsItem[len];
for (size_t i = 0; i < len; i++)
m_cacheContents[i] = m_index[i];
}
return m_cacheContents;
}
int wxHtmlHelpData::GetIndexCnt()
{
return m_index.size();
}
void wxHtmlHelpData::CleanCompatibilityData()
{
delete[] m_cacheContents;
m_cacheContents = NULL;
delete[] m_cacheIndex;
m_cacheIndex = NULL;
}
#endif // WXWIN_COMPATIBILITY_2_4
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// wxHtmlSearchStatus functions // wxHtmlSearchStatus functions
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@@ -739,11 +875,11 @@ wxHtmlSearchStatus::wxHtmlSearchStatus(wxHtmlHelpData* data, const wxString& key
if (book != wxEmptyString) if (book != wxEmptyString)
{ {
// we have to search in a specific book. Find it first // we have to search in a specific book. Find it first
int i, cnt = data->m_BookRecords.GetCount(); int i, cnt = data->m_bookRecords.GetCount();
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
if (data->m_BookRecords[i].GetTitle() == book) if (data->m_bookRecords[i].GetTitle() == book)
{ {
bookr = &(data->m_BookRecords[i]); bookr = &(data->m_bookRecords[i]);
m_CurIndex = bookr->GetContentsStart(); m_CurIndex = bookr->GetContentsStart();
m_MaxIndex = bookr->GetContentsEnd(); m_MaxIndex = bookr->GetContentsEnd();
break; break;
@@ -755,29 +891,38 @@ wxHtmlSearchStatus::wxHtmlSearchStatus(wxHtmlHelpData* data, const wxString& key
{ {
// no book specified; search all books // no book specified; search all books
m_CurIndex = 0; m_CurIndex = 0;
m_MaxIndex = m_Data->m_ContentsCnt; m_MaxIndex = m_Data->m_contents.size();
} }
m_Engine.LookFor(keyword, case_sensitive, whole_words_only); m_Engine.LookFor(keyword, case_sensitive, whole_words_only);
m_Active = (m_CurIndex < m_MaxIndex); m_Active = (m_CurIndex < m_MaxIndex);
} }
#if WXWIN_COMPATIBILITY_2_4
wxHtmlContentsItem* wxHtmlSearchStatus::GetContentsItem()
{
static wxHtmlContentsItem it;
it = wxHtmlContentsItem(*m_CurItem);
return &it;
}
#endif
bool wxHtmlSearchStatus::Search() bool wxHtmlSearchStatus::Search()
{ {
wxFSFile *file; wxFSFile *file;
int i = m_CurIndex; // shortcut int i = m_CurIndex; // shortcut
bool found = FALSE; bool found = false;
wxString thepage; wxString thepage;
if (!m_Active) if (!m_Active)
{ {
// sanity check. Illegal use, but we'll try to prevent a crash anyway // sanity check. Illegal use, but we'll try to prevent a crash anyway
wxASSERT(m_Active); wxASSERT(m_Active);
return FALSE; return false;
} }
m_Name = wxEmptyString; m_Name = wxEmptyString;
m_ContentsItem = NULL; m_CurItem = NULL;
thepage = m_Data->m_Contents[i].m_Page; thepage = m_Data->m_contents[i].page;
m_Active = (++m_CurIndex < m_MaxIndex); m_Active = (++m_CurIndex < m_MaxIndex);
// check if it is same page with different anchor: // check if it is same page with different anchor:
@@ -795,14 +940,14 @@ bool wxHtmlSearchStatus::Search()
else m_LastPage = thepage; else m_LastPage = thepage;
wxFileSystem fsys; wxFileSystem fsys;
file = fsys.OpenFile(m_Data->m_Contents[i].m_Book->GetFullPath(thepage)); file = fsys.OpenFile(m_Data->m_contents[i].book->GetFullPath(thepage));
if (file) if (file)
{ {
if (m_Engine.Scan(*file)) if (m_Engine.Scan(*file))
{ {
m_Name = m_Data->m_Contents[i].m_Name; m_Name = m_Data->m_contents[i].name;
m_ContentsItem = m_Data->m_Contents + i; m_CurItem = &m_Data->m_contents[i];
found = TRUE; found = true;
} }
delete file; delete file;
} }

View File

@@ -57,6 +57,8 @@
#include "wx/filedlg.h" #include "wx/filedlg.h"
#include "wx/artprov.h" #include "wx/artprov.h"
#include "wx/spinctrl.h" #include "wx/spinctrl.h"
#include "wx/dynarray.h"
#include "wx/choicdlg.h"
// what is considered "small index"? // what is considered "small index"?
#define INDEX_IS_SMALL 100 #define INDEX_IS_SMALL 100
@@ -125,6 +127,58 @@ class wxHtmlHelpHtmlWindow : public wxHtmlWindow
}; };
//---------------------------------------------------------------------------
// wxHtmlHelpFrame::m_mergedIndex
//---------------------------------------------------------------------------
WX_DEFINE_ARRAY(const wxHtmlHelpDataItem*, wxHtmlHelpDataItemPtrArray);
struct wxHtmlHelpMergedIndexItem
{
wxHtmlHelpMergedIndexItem *parent;
wxString name;
wxHtmlHelpDataItemPtrArray items;
};
WX_DECLARE_OBJARRAY(wxHtmlHelpMergedIndexItem, wxHtmlHelpMergedIndex);
#include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(wxHtmlHelpMergedIndex)
void wxHtmlHelpFrame::UpdateMergedIndex()
{
delete m_mergedIndex;
m_mergedIndex = new wxHtmlHelpMergedIndex;
wxHtmlHelpMergedIndex& merged = *m_mergedIndex;
const wxHtmlHelpDataItems& items = m_Data->GetIndexArray();
size_t len = items.size();
wxHtmlHelpMergedIndexItem *history[128] = {NULL};
for (size_t i = 0; i < len; i++)
{
const wxHtmlHelpDataItem& item = items[i];
wxASSERT_MSG( item.level < 128, _T("nested index entries too deep") );
if (history[item.level] &&
history[item.level]->items[0]->name == item.name)
{
// same index entry as previous one, update list of items
history[item.level]->items.Add(&item);
}
else
{
// new index entry
wxHtmlHelpMergedIndexItem *mi = new wxHtmlHelpMergedIndexItem();
mi->name = item.GetIndentedName();
mi->items.Add(&item);
mi->parent = (item.level == 0) ? NULL : history[item.level - 1];
history[item.level] = mi;
merged.Add(mi);
}
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// wxHtmlHelpFrame // wxHtmlHelpFrame
@@ -201,6 +255,8 @@ void wxHtmlHelpFrame::Init(wxHtmlHelpData* data)
m_SearchCaseSensitive = NULL; m_SearchCaseSensitive = NULL;
m_SearchWholeWords = NULL; m_SearchWholeWords = NULL;
m_mergedIndex = NULL;
m_Config = NULL; m_Config = NULL;
m_ConfigRoot = wxEmptyString; m_ConfigRoot = wxEmptyString;
@@ -675,7 +731,53 @@ bool wxHtmlHelpFrame::DisplayIndex()
return true; return true;
} }
#include <gtk/gtk.h>
void wxHtmlHelpFrame::DisplayIndexItem(const wxHtmlHelpMergedIndexItem *it)
{
if (it->items.size() == 1)
{
if (!it->items[0]->page.empty())
{
m_HtmlWin->LoadPage(it->items[0]->GetFullPath());
NotifyPageChanged();
}
}
else
{
wxBusyCursor busy_cursor;
// more pages associated with this index item -- let the user choose
// which one she/he wants from a list:
wxArrayString arr;
size_t len = it->items.size();
for (size_t i = 0; i < len; i++)
{
wxString page = it->items[i]->page;
// try to find page's title in contents:
const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
size_t clen = contents.size();
for (size_t j = 0; j < clen; j++)
{
if (contents[j].page == page)
{
page = contents[j].name;
break;
}
}
arr.push_back(page);
}
wxSingleChoiceDialog dlg(this,
_("Please choose the page to display:"),
_("Help Topics"),
arr, NULL, wxCHOICEDLG_STYLE & ~wxCENTRE);
if (dlg.ShowModal() == wxID_OK)
{
m_HtmlWin->LoadPage(it->items[dlg.GetSelection()]->GetFullPath());
NotifyPageChanged();
}
}
}
bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword, bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword,
@@ -743,7 +845,7 @@ bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword,
#if wxUSE_PROGRESSDLG #if wxUSE_PROGRESSDLG
progress.Update(status.GetCurIndex(), foundstr); progress.Update(status.GetCurIndex(), foundstr);
#endif #endif
m_SearchList->Append(status.GetName(), status.GetContentsItem()); m_SearchList->Append(status.GetName(), (void*)status.GetCurItem());
} }
} }
@@ -768,7 +870,6 @@ bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword,
if (foundcnt) if (foundcnt)
{ {
wxHtmlContentsItem *it;
switch ( mode ) switch ( mode )
{ {
default: default:
@@ -776,19 +877,27 @@ bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword,
// fall back // fall back
case wxHELP_SEARCH_ALL: case wxHELP_SEARCH_ALL:
it = (wxHtmlContentsItem*) m_SearchList->GetClientData(0); {
wxHtmlHelpDataItem *it =
(wxHtmlHelpDataItem*) m_SearchList->GetClientData(0);
if (it)
{
m_HtmlWin->LoadPage(it->GetFullPath());
NotifyPageChanged();
}
break; break;
}
case wxHELP_SEARCH_INDEX: case wxHELP_SEARCH_INDEX:
it = (wxHtmlContentsItem*) m_IndexList->GetClientData(0); {
wxHtmlHelpMergedIndexItem* it =
(wxHtmlHelpMergedIndexItem*) m_IndexList->GetClientData(0);
if (it)
DisplayIndexItem(it);
break; break;
}
} }
if (it)
{
m_HtmlWin->LoadPage(it->GetFullPath());
NotifyPageChanged();
}
} }
return foundcnt > 0; return foundcnt > 0;
@@ -804,12 +913,12 @@ void wxHtmlHelpFrame::CreateContents()
WX_CLEAR_HASH_TABLE(*m_PagesHash); WX_CLEAR_HASH_TABLE(*m_PagesHash);
delete m_PagesHash; delete m_PagesHash;
} }
m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * m_Data->GetContentsCnt());
const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
size_t cnt = contents.size();
int cnt = m_Data->GetContentsCnt(); m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * cnt);
int i;
wxHtmlContentsItem *it;
const int MAX_ROOTS = 64; const int MAX_ROOTS = 64;
wxTreeItemId roots[MAX_ROOTS]; wxTreeItemId roots[MAX_ROOTS];
@@ -825,10 +934,11 @@ void wxHtmlHelpFrame::CreateContents()
roots[0] = m_ContentsBox->AddRoot(_("(Help)")); roots[0] = m_ContentsBox->AddRoot(_("(Help)"));
imaged[0] = true; imaged[0] = true;
for (it = m_Data->GetContents(), i = 0; i < cnt; i++, it++) for (size_t i = 0; i < cnt; i++)
{ {
wxHtmlHelpDataItem *it = &contents[i];
// Handle books: // Handle books:
if (it->m_Level == 0) if (it->level == 0)
{ {
if (m_hfStyle & wxHF_MERGE_BOOKS) if (m_hfStyle & wxHF_MERGE_BOOKS)
// VS: we don't want book nodes, books' content should // VS: we don't want book nodes, books' content should
@@ -840,7 +950,7 @@ void wxHtmlHelpFrame::CreateContents()
else else
{ {
roots[1] = m_ContentsBox->AppendItem(roots[0], roots[1] = m_ContentsBox->AppendItem(roots[0],
it->m_Name, IMG_Book, -1, it->name, IMG_Book, -1,
new wxHtmlHelpTreeItemData(i)); new wxHtmlHelpTreeItemData(i));
m_ContentsBox->SetItemBold(roots[1], true); m_ContentsBox->SetItemBold(roots[1], true);
} }
@@ -849,28 +959,28 @@ void wxHtmlHelpFrame::CreateContents()
// ...and their contents: // ...and their contents:
else else
{ {
roots[it->m_Level + 1] = m_ContentsBox->AppendItem( roots[it->level + 1] = m_ContentsBox->AppendItem(
roots[it->m_Level], it->m_Name, IMG_Page, roots[it->level], it->name, IMG_Page,
-1, new wxHtmlHelpTreeItemData(i)); -1, new wxHtmlHelpTreeItemData(i));
imaged[it->m_Level + 1] = false; imaged[it->level + 1] = false;
} }
m_PagesHash->Put(it->GetFullPath(), m_PagesHash->Put(it->GetFullPath(),
new wxHtmlHelpHashData(i, roots[it->m_Level + 1])); new wxHtmlHelpHashData(i, roots[it->level + 1]));
// Set the icon for the node one level up in the hiearachy, // Set the icon for the node one level up in the hiearachy,
// unless already done (see comment above imaged[] declaration) // unless already done (see comment above imaged[] declaration)
if (!imaged[it->m_Level]) if (!imaged[it->level])
{ {
int image = IMG_Folder; int image = IMG_Folder;
if (m_hfStyle & wxHF_ICONS_BOOK) if (m_hfStyle & wxHF_ICONS_BOOK)
image = IMG_Book; image = IMG_Book;
else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER) else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER)
image = (it->m_Level == 1) ? IMG_Book : IMG_Folder; image = (it->level == 1) ? IMG_Book : IMG_Folder;
m_ContentsBox->SetItemImage(roots[it->m_Level], image); m_ContentsBox->SetItemImage(roots[it->level], image);
m_ContentsBox->SetItemImage(roots[it->m_Level], image, m_ContentsBox->SetItemImage(roots[it->level], image,
wxTreeItemIcon_Selected); wxTreeItemIcon_Selected);
imaged[it->m_Level] = true; imaged[it->level] = true;
} }
} }
} }
@@ -883,18 +993,20 @@ void wxHtmlHelpFrame::CreateIndex()
m_IndexList->Clear(); m_IndexList->Clear();
int cnt = m_Data->GetIndexCnt(); size_t cnt = m_mergedIndex->size();
wxString cnttext; wxString cnttext;
if (cnt > INDEX_IS_SMALL) cnttext.Printf(_("%i of %i"), 0, cnt); if (cnt > INDEX_IS_SMALL)
else cnttext.Printf(_("%i of %i"), cnt, cnt); cnttext.Printf(_("%i of %i"), 0, cnt);
else
cnttext.Printf(_("%i of %i"), cnt, cnt);
m_IndexCountInfo->SetLabel(cnttext); m_IndexCountInfo->SetLabel(cnttext);
if (cnt > INDEX_IS_SMALL) return; if (cnt > INDEX_IS_SMALL)
return;
wxHtmlContentsItem* index = m_Data->GetIndex(); for (size_t i = 0; i < cnt; i++)
m_IndexList->Append((*m_mergedIndex)[i].name,
for (int i = 0; i < cnt; i++) (char*)(&(*m_mergedIndex)[i]));
m_IndexList->Append(index[i].m_Name, (char*)(index + i));
} }
void wxHtmlHelpFrame::CreateSearch() void wxHtmlHelpFrame::CreateSearch()
@@ -914,6 +1026,9 @@ void wxHtmlHelpFrame::CreateSearch()
void wxHtmlHelpFrame::RefreshLists() void wxHtmlHelpFrame::RefreshLists()
{ {
// Update m_mergedIndex:
UpdateMergedIndex();
// Update the controls
CreateContents(); CreateContents();
CreateIndex(); CreateIndex();
CreateSearch(); CreateSearch();
@@ -1275,10 +1390,10 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event)
ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an); ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
if (ha && ha->m_Index > 0) if (ha && ha->m_Index > 0)
{ {
wxHtmlContentsItem *it = m_Data->GetContents() + (ha->m_Index - 1); const wxHtmlHelpDataItem& it = m_Data->GetContentsArray()[ha->m_Index - 1];
if (!it->m_Page.empty()) if (!it.page.empty())
{ {
m_HtmlWin->LoadPage(it->GetFullPath()); m_HtmlWin->LoadPage(it.GetFullPath());
NotifyPageChanged(); NotifyPageChanged();
} }
} }
@@ -1296,15 +1411,20 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event)
ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an); ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
if (ha && ha->m_Index > 0) if (ha && ha->m_Index > 0)
{ {
int level = m_Data->GetContents()[ha->m_Index].m_Level - 1; int level =
wxHtmlContentsItem *it; m_Data->GetContentsArray()[ha->m_Index].level - 1;
int ind = ha->m_Index - 1; int ind = ha->m_Index - 1;
it = m_Data->GetContents() + ind; const wxHtmlHelpDataItem *it =
while (ind >= 0 && it->m_Level != level) ind--, it--; &m_Data->GetContentsArray()[ind];
while (ind >= 0 && it->level != level)
{
ind--, it--;
it = &m_Data->GetContentsArray()[ind];
}
if (ind >= 0) if (ind >= 0)
{ {
if (!it->m_Page.empty()) if (!it->page.empty())
{ {
m_HtmlWin->LoadPage(it->GetFullPath()); m_HtmlWin->LoadPage(it->GetFullPath());
NotifyPageChanged(); NotifyPageChanged();
@@ -1326,15 +1446,16 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event)
ha = (wxHtmlHelpHashData*) m_PagesHash->Get(adr); ha = (wxHtmlHelpHashData*) m_PagesHash->Get(adr);
if (ha && ha->m_Index < m_Data->GetContentsCnt() - 1) const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
if (ha && ha->m_Index < (int)contents.size() - 1)
{ {
wxHtmlContentsItem *it = m_Data->GetContents() + (ha->m_Index + 1); size_t idx = ha->m_Index + 1;
while (it->GetFullPath() == adr) it++; while (contents[idx].GetFullPath() == adr) idx++;
if (!it->m_Page.empty()) if (!contents[idx].page.empty())
{ {
m_HtmlWin->LoadPage(it->GetFullPath()); m_HtmlWin->LoadPage(contents[idx].GetFullPath());
NotifyPageChanged(); NotifyPageChanged();
} }
} }
@@ -1455,16 +1576,15 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event)
void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event) void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event)
{ {
wxHtmlHelpTreeItemData *pg; wxHtmlHelpTreeItemData *pg;
wxHtmlContentsItem *it;
pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem()); pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem());
if (pg && m_UpdateContents) if (pg && m_UpdateContents)
{ {
it = m_Data->GetContents() + (pg->m_Id); const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
m_UpdateContents = false; m_UpdateContents = false;
if (!it->m_Page.empty()) if (!contents[pg->m_Id].page.empty())
m_HtmlWin->LoadPage(it->GetFullPath()); m_HtmlWin->LoadPage(contents[pg->m_Id].GetFullPath());
m_UpdateContents = true; m_UpdateContents = true;
} }
} }
@@ -1473,10 +1593,10 @@ void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event)
void wxHtmlHelpFrame::OnIndexSel(wxCommandEvent& WXUNUSED(event)) void wxHtmlHelpFrame::OnIndexSel(wxCommandEvent& WXUNUSED(event))
{ {
wxHtmlContentsItem *it = (wxHtmlContentsItem*) m_IndexList->GetClientData(m_IndexList->GetSelection()); wxHtmlHelpMergedIndexItem *it = (wxHtmlHelpMergedIndexItem*)
if (!it->m_Page.empty()) m_IndexList->GetClientData(m_IndexList->GetSelection());
m_HtmlWin->LoadPage(it->GetFullPath()); if (it)
NotifyPageChanged(); DisplayIndexItem(it);
} }
@@ -1491,33 +1611,39 @@ void wxHtmlHelpFrame::OnIndexFind(wxCommandEvent& event)
else else
{ {
wxBusyCursor bcur; wxBusyCursor bcur;
const wxChar *cstr = sr.c_str();
wxChar mybuff[512];
wxChar *ptr;
bool first = true;
m_IndexList->Clear(); m_IndexList->Clear();
int cnt = m_Data->GetIndexCnt(); const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
wxHtmlContentsItem* index = m_Data->GetIndex(); size_t cnt = index.size();
int displ = 0; int displ = 0;
for (int i = 0; i < cnt; i++) for (size_t i = 0; i < cnt; i++)
{ {
wxStrncpy(mybuff, index[i].m_Name, 512); if (index[i].name.Lower().find(sr) != wxString::npos)
mybuff[511] = _T('\0');
for (ptr = mybuff; *ptr != 0; ptr++)
if (*ptr >= _T('A') && *ptr <= _T('Z'))
*ptr -= (wxChar)(_T('A') - _T('a'));
if (wxStrstr(mybuff, cstr) != NULL)
{ {
m_IndexList->Append(index[i].m_Name, (char*)(index + i)); int pos = m_IndexList->Append(index[i].name,
displ++; (char*)(&index[i]));
if (first)
if (displ++ == 0)
{ {
if (!index[i].m_Page.empty()) m_IndexList->SetSelection(0);
m_HtmlWin->LoadPage(index[i].GetFullPath()); DisplayIndexItem(&index[i]);
NotifyPageChanged(); }
first = false;
// if this is nested item of the index, show its parent(s)
// as well, otherwise it would not be clear what entry is
// shown:
wxHtmlHelpMergedIndexItem *parent = index[i].parent;
while (parent)
{
if (pos == 0 ||
(index.Index(*(wxHtmlHelpMergedIndexItem*)m_IndexList->GetClientData(pos-1))) < index.Index(*parent))
{
m_IndexList->Insert(parent->name,
pos, (char*)parent);
parent = parent->parent;
}
else break;
} }
} }
} }
@@ -1536,18 +1662,16 @@ void wxHtmlHelpFrame::OnIndexAll(wxCommandEvent& WXUNUSED(event))
wxBusyCursor bcur; wxBusyCursor bcur;
m_IndexList->Clear(); m_IndexList->Clear();
int cnt = m_Data->GetIndexCnt(); const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
size_t cnt = index.size();
bool first = true; bool first = true;
wxHtmlContentsItem* index = m_Data->GetIndex();
for (int i = 0; i < cnt; i++) for (size_t i = 0; i < cnt; i++)
{ {
m_IndexList->Append(index[i].m_Name, (char*)(index + i)); m_IndexList->Append(index[i].name, (char*)(&index[i]));
if (first) if (first)
{ {
if (!index[i].m_Page.empty()) DisplayIndexItem(&index[i]);
m_HtmlWin->LoadPage(index[i].GetFullPath());
NotifyPageChanged();
first = false; first = false;
} }
} }
@@ -1560,10 +1684,10 @@ void wxHtmlHelpFrame::OnIndexAll(wxCommandEvent& WXUNUSED(event))
void wxHtmlHelpFrame::OnSearchSel(wxCommandEvent& WXUNUSED(event)) void wxHtmlHelpFrame::OnSearchSel(wxCommandEvent& WXUNUSED(event))
{ {
wxHtmlContentsItem *it = (wxHtmlContentsItem*) m_SearchList->GetClientData(m_SearchList->GetSelection()); wxHtmlHelpDataItem *it = (wxHtmlHelpDataItem*) m_SearchList->GetClientData(m_SearchList->GetSelection());
if (it) if (it)
{ {
if (!it->m_Page.empty()) if (!it->page.empty())
m_HtmlWin->LoadPage(it->GetFullPath()); m_HtmlWin->LoadPage(it->GetFullPath());
NotifyPageChanged(); NotifyPageChanged();
} }
@@ -1621,7 +1745,7 @@ void wxHtmlHelpFrame::OnClose(wxCommandEvent& event)
void wxHtmlHelpFrame::OnAbout(wxCommandEvent& event) void wxHtmlHelpFrame::OnAbout(wxCommandEvent& event)
{ {
wxMessageBox(wxT("wxWidgets HTML Help Viewer (c) 1998-2003, Vaclav Slavik et al"), wxT("HelpView"), wxMessageBox(wxT("wxWidgets HTML Help Viewer (c) 1998-2004, Vaclav Slavik et al"), wxT("HelpView"),
wxICON_INFORMATION|wxOK, this); wxICON_INFORMATION|wxOK, this);
} }
#endif #endif