From 91fa114d88972cdfe698343560f3ef5d17b4eac1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Mon, 28 Jun 2004 21:45:30 +0000 Subject: [PATCH] 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 --- docs/changes.txt | 5 + docs/latex/wx/hthlpdat.tex | 24 +- include/wx/html/helpdata.h | 81 ++++-- src/html/helpdata.cpp | 529 +++++++++++++++++++++++-------------- src/html/helpfrm.cpp | 294 +++++++++++++++------ 5 files changed, 623 insertions(+), 310 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index e4eb229532..ecbf2662fb 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -151,6 +151,11 @@ wxWinCE: - 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 ----- diff --git a/docs/latex/wx/hthlpdat.tex b/docs/latex/wx/hthlpdat.tex index b92bb0e826..4d1d51bf5b 100644 --- a/docs/latex/wx/hthlpdat.tex +++ b/docs/latex/wx/hthlpdat.tex @@ -53,29 +53,17 @@ Returns page's URL based on its (file)name. 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. - -\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. +Returns reference to array with index entries. \membersection{wxHtmlHelpData::SetTempDir}\label{wxhtmlhelpdatasettempdir} diff --git a/include/wx/html/helpdata.h b/include/wx/html/helpdata.h index 28c73e4da7..62cb773938 100644 --- a/include/wx/html/helpdata.h +++ b/include/wx/html/helpdata.h @@ -80,18 +80,50 @@ protected: WX_DECLARE_USER_EXPORTED_OBJARRAY(wxHtmlBookRecord, wxHtmlBookRecArray, 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 { + wxHtmlContentsItem(); + wxHtmlContentsItem(const wxHtmlHelpDataItem& d); + wxHtmlContentsItem& operator=(const wxHtmlContentsItem& d); + ~wxHtmlContentsItem(); + short int m_Level; int m_ID; - wxString m_Name; - wxString m_Page; + wxChar *m_Name; + wxChar *m_Page; wxHtmlBookRecord *m_Book; // returns full filename of m_Page, i.e. with book's basePath prepended wxString GetFullPath() const { return m_Book->GetFullPath(m_Page); } + +private: + bool m_autofree; }; +#endif + //------------------------------------------------------------------------------ // wxHtmlSearchEngine @@ -138,14 +170,18 @@ public: int GetCurIndex() { return m_CurIndex; } int GetMaxIndex() { return m_MaxIndex; } 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: wxHtmlHelpData* m_Data; wxHtmlSearchEngine m_Engine; wxString m_Keyword, m_Name; wxString m_LastPage; - wxHtmlContentsItem* m_ContentsItem; + wxHtmlHelpDataItem* m_CurItem; bool m_Active; // search is not finished int m_CurIndex; // where we are now int m_MaxIndex; // number of files we search @@ -186,21 +222,36 @@ public: // returns URL of page on basis of MS id wxString FindPageById(int id); - const wxHtmlBookRecArray& GetBookRecArray() { return m_BookRecords; } - wxHtmlContentsItem* GetContents() { return m_Contents; } - int GetContentsCnt() { return m_ContentsCnt; } - wxHtmlContentsItem* GetIndex() { return m_Index; } - int GetIndexCnt() { return m_IndexCnt; } + const wxHtmlBookRecArray& GetBookRecArray() const { return m_bookRecords; } + + const wxHtmlHelpDataItems& GetContentsArray() const { return m_contents; } + const wxHtmlHelpDataItems& GetIndexArray() const { return m_index; } + +#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: - wxString m_TempPath; + wxString m_tempPath; - wxHtmlBookRecArray m_BookRecords; // each book has one record in this array: - wxHtmlContentsItem* m_Contents; - int m_ContentsCnt; - wxHtmlContentsItem* m_Index; // list of all available books and pages. - int m_IndexCnt; // list of index items + wxHtmlBookRecArray m_bookRecords; + + wxHtmlHelpDataItems m_contents; // list of all available books and pages + 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: // Imports .hhp files (MS HTML Help Workshop) diff --git a/src/html/helpdata.cpp b/src/html/helpdata.cpp index 1b89735338..32aad95196 100644 --- a/src/html/helpdata.cpp +++ b/src/html/helpdata.cpp @@ -45,6 +45,7 @@ #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxHtmlBookRecArray) +WX_DEFINE_OBJARRAY(wxHtmlHelpDataItems) //----------------------------------------------------------------------------- // static helper functions @@ -71,23 +72,46 @@ static const wxChar* ReadLine(const wxChar *line, wxChar *buf, size_t bufsize) -extern "C" int LINKAGEMODE -wxHtmlHelpIndexCompareFunc(const void *a, const void *b) +static int +wxHtmlHelpIndexCompareFunc(wxHtmlHelpDataItem **a, wxHtmlHelpDataItem **b) { - return ((wxHtmlContentsItem*)a)->m_Name.CmpNoCase(((wxHtmlContentsItem*)b)->m_Name); -} - + wxHtmlHelpDataItem *ia = *a; + wxHtmlHelpDataItem *ib = *b; -template -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; + 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; + } } - //----------------------------------------------------------------------------- // HP_Parser //----------------------------------------------------------------------------- @@ -116,22 +140,37 @@ protected: class HP_TagHandler : public wxHtmlTagHandler { private: - wxString m_Name, m_Page; - int m_Level; - int m_ID; - int m_Index; - wxHtmlContentsItem *m_Items; - int m_ItemsCnt; - wxHtmlBookRecord *m_Book; + wxString m_name, m_page; + int m_level; + int m_id; + int m_index; + int m_count; + wxHtmlHelpDataItem *m_parentItem; + wxHtmlBookRecord *m_book; + + wxHtmlHelpDataItems *m_data; public: 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"); } 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) }; @@ -141,18 +180,21 @@ bool HP_TagHandler::HandleTag(const wxHtmlTag& tag) { 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); - m_Level--; - return TRUE; + m_level--; + m_parentItem = oldparent; + return true; } else if (tag.GetName() == wxT("OBJECT")) { - m_Name = m_Page = wxEmptyString; + m_name = m_page = wxEmptyString; ParseInner(tag); #if 0 - if (!m_Page.IsEmpty()) + if (!page.IsEmpty()) /* Valid HHW's file may contain only two object tags: @@ -166,57 +208,39 @@ bool HP_TagHandler::HandleTag(const wxHtmlTag& tag) - 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 */ #endif if (tag.GetParam(wxT("TYPE")) == wxT("text/sitemap")) { - if (m_ItemsCnt % wxHTML_REALLOC_STEP == 0) - m_Items = ReallocArray(m_Items, m_ItemsCnt, - m_ItemsCnt + wxHTML_REALLOC_STEP); - - m_Items[m_ItemsCnt].m_Level = m_Level; - m_Items[m_ItemsCnt].m_ID = m_ID; - m_Items[m_ItemsCnt].m_Page = m_Page; - m_Items[m_ItemsCnt].m_Name = m_Name; - m_Items[m_ItemsCnt].m_Book = m_Book; - m_ItemsCnt++; + wxHtmlHelpDataItem *item = new wxHtmlHelpDataItem(); + item->parent = m_parentItem; + item->level = m_level; + item->id = m_id; + item->page = m_page; + item->name = m_name; + + item->book = m_book; + m_data->Add(item); + m_count++; } - return TRUE; + return true; } else { // "PARAM" - if (m_Name == wxEmptyString && tag.GetParam(wxT("NAME")) == wxT("Name")) - m_Name = tag.GetParam(wxT("VALUE")); + if (m_name.empty() && tag.GetParam(wxT("NAME")) == wxT("Name")) + m_name = tag.GetParam(wxT("VALUE")); 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")) - tag.GetParamAsInt(wxT("VALUE"), &m_ID); - return FALSE; + tag.GetParamAsInt(wxT("VALUE"), &m_id); + 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 //----------------------------------------------------------------------------- @@ -229,25 +253,31 @@ wxString wxHtmlBookRecord::GetFullPath(const wxString &page) const 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) wxHtmlHelpData::wxHtmlHelpData() { - m_TempPath = wxEmptyString; - - m_Contents = NULL; - m_ContentsCnt = 0; - m_Index = NULL; - m_IndexCnt = 0; +#if WXWIN_COMPATIBILITY_2_4 + m_cacheContents = NULL; + m_cacheIndex = NULL; +#endif } wxHtmlHelpData::~wxHtmlHelpData() { - m_BookRecords.Empty(); - delete[] m_Contents; - delete[] m_Index; +#if WXWIN_COMPATIBILITY_2_4 + CleanCompatibilityData(); +#endif } bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys, @@ -269,9 +299,8 @@ bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys, buf.clear(); buf = filter.ReadFile(*f); delete f; - handler->ReadIn(m_Contents, m_ContentsCnt); + handler->Reset(m_contents); parser.Parse(buf); - handler->WriteOut(m_Contents, m_ContentsCnt); } else { @@ -284,9 +313,8 @@ bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys, buf.clear(); buf = filter.ReadFile(*f); delete f; - handler->ReadIn(m_Index, m_IndexCnt); + handler->Reset(m_index); parser.Parse(buf); - handler->WriteOut(m_Index, m_IndexCnt); } else if (!indexfile.IsEmpty()) { @@ -324,7 +352,7 @@ inline static wxString CacheReadString(wxInputStream *f) 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: #define CACHED_BOOK_FORMAT_FLAGS \ @@ -333,7 +361,7 @@ inline static wxString CacheReadString(wxInputStream *f) bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord *book, wxInputStream *f) { - int i, st; + int i, st, newsize; wxInt32 version; /* 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 // absence of (properly versioned) .cached file and automatically // create new .cached file immediately afterward. - return FALSE; + return false; } if (CacheReadInt32(f) != CACHED_BOOK_FORMAT_FLAGS) - return FALSE; + return false; /* load contents : */ - st = m_ContentsCnt; - m_ContentsCnt += CacheReadInt32(f); - m_Contents = ReallocArray(m_Contents, st, - (m_ContentsCnt / wxHTML_REALLOC_STEP + 1) * - wxHTML_REALLOC_STEP); - for (i = st; i < m_ContentsCnt; i++) + st = m_contents.size(); + newsize = st + CacheReadInt32(f); + m_contents.Alloc(newsize); + for (i = st; i < newsize; i++) { - m_Contents[i].m_Level = CacheReadInt32(f); - m_Contents[i].m_ID = CacheReadInt32(f); - m_Contents[i].m_Name = CacheReadString(f); - m_Contents[i].m_Page = CacheReadString(f); - m_Contents[i].m_Book = book; + wxHtmlHelpDataItem *item = new wxHtmlHelpDataItem; + item->level = CacheReadInt32(f); + item->id = CacheReadInt32(f); + item->name = CacheReadString(f); + item->page = CacheReadString(f); + item->book = book; + m_contents.Add(item); } /* load index : */ - st = m_IndexCnt; - m_IndexCnt += CacheReadInt32(f); - m_Index = ReallocArray(m_Index, st, - (m_IndexCnt / wxHTML_REALLOC_STEP + 1) * - wxHTML_REALLOC_STEP); - for (i = st; i < m_IndexCnt; i++) + st = m_index.size(); + newsize = st + CacheReadInt32(f); + m_index.Alloc(newsize); + for (i = st; i < newsize; i++) { - m_Index[i].m_Name = CacheReadString(f); - m_Index[i].m_Page = CacheReadString(f); - m_Index[i].m_Book = book; + wxHtmlHelpDataItem *item = new wxHtmlHelpDataItem; + item->name = CacheReadString(f); + 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); /* save contents : */ - for (cnt = 0, i = 0; i < m_ContentsCnt; i++) - if (m_Contents[i].m_Book == book && m_Contents[i].m_Level > 0) + int len = m_contents.size(); + for (cnt = 0, i = 0; i < len; i++) + if (m_contents[i].book == book && m_contents[i].level > 0) 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; - CacheWriteInt32(f, m_Contents[i].m_Level); - CacheWriteInt32(f, m_Contents[i].m_ID); - CacheWriteString(f, m_Contents[i].m_Name); - CacheWriteString(f, m_Contents[i].m_Page); + CacheWriteInt32(f, m_contents[i].level); + CacheWriteInt32(f, m_contents[i].id); + CacheWriteString(f, m_contents[i].name); + CacheWriteString(f, m_contents[i].page); } /* save index : */ - for (cnt = 0, i = 0; i < m_IndexCnt; i++) - if (m_Index[i].m_Book == book && m_Index[i].m_Level > 0) + len = m_index.size(); + for (cnt = 0, i = 0; i < len; i++) + if (m_index[i].book == book && m_index[i].level > 0) 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; - CacheWriteString(f, m_Index[i].m_Name); - CacheWriteString(f, m_Index[i].m_Page); + CacheWriteString(f, m_index[i].name); + 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) { - if (path == wxEmptyString) m_TempPath = path; + if (path.empty()) + m_tempPath = path; else { - if (wxIsAbsolutePath(path)) m_TempPath = path; - else m_TempPath = wxGetCwd() + _T("/") + path; + if (wxIsAbsolutePath(path)) m_tempPath = path; + else m_tempPath = wxGetCwd() + _T("/") + path; - if (m_TempPath[m_TempPath.Length() - 1] != _T('/')) - m_TempPath << _T('/'); + if (m_tempPath[m_tempPath.Length() - 1] != _T('/')) + m_tempPath << _T('/'); } } @@ -459,32 +514,32 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile, wxFSFile *fi; wxHtmlBookRecord *bookr; - int IndexOld = m_IndexCnt, - ContentsOld = m_ContentsCnt; + int IndexOld = m_index.size(), + ContentsOld = m_contents.size(); if (!path.IsEmpty()) fsys.ChangePathTo(path, TRUE); - size_t booksCnt = m_BookRecords.GetCount(); + size_t booksCnt = m_bookRecords.GetCount(); for (size_t i = 0; i < booksCnt; i++) { - if ( m_BookRecords[i].GetBookFile() == bookfile.GetLocation() ) - return TRUE; // book is (was) loaded + if ( m_bookRecords[i].GetBookFile() == bookfile.GetLocation() ) + return true; // book is (was) loaded } bookr = new wxHtmlBookRecord(bookfile.GetLocation(), fsys.GetPath(), title, deftopic); - if (m_ContentsCnt % wxHTML_REALLOC_STEP == 0) - m_Contents = ReallocArray(m_Contents, m_ContentsCnt, - m_ContentsCnt + wxHTML_REALLOC_STEP); - m_Contents[m_ContentsCnt].m_Level = 0; - m_Contents[m_ContentsCnt].m_ID = 0; - m_Contents[m_ContentsCnt].m_Page = deftopic; - m_Contents[m_ContentsCnt].m_Name = title; - m_Contents[m_ContentsCnt].m_Book = bookr; + wxHtmlHelpDataItem *bookitem = new wxHtmlHelpDataItem; + bookitem->level = 0; + bookitem->id = 0; + bookitem->page = deftopic; + bookitem->name = title; + bookitem->book = bookr; // 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: // 1. save file as book, but with .hhp.cached extension @@ -500,17 +555,17 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile, !LoadCachedBook(bookr, fi->GetStream())) { if (fi != NULL) delete fi; - fi = fsys.OpenFile(m_TempPath + wxFileNameFromPath(bookfile.GetLocation()) + wxT(".cached")); - if (m_TempPath == wxEmptyString || fi == NULL || + fi = fsys.OpenFile(m_tempPath + wxFileNameFromPath(bookfile.GetLocation()) + wxT(".cached")); + if (m_tempPath.empty() || fi == NULL || #if wxUSE_DATETIME fi->GetModificationTime() < bookfile.GetModificationTime() || #endif // wxUSE_DATETIME !LoadCachedBook(bookr, fi->GetStream())) { 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")); SaveCachedBook(bookr, outs); delete outs; @@ -521,7 +576,7 @@ bool wxHtmlHelpData::AddBookParam(const wxFSFile& bookfile, if (fi != NULL) delete fi; // Now store the contents range - bookr->SetContentsRange(cont_start, m_ContentsCnt); + bookr->SetContentsRange(cont_start, m_contents.size()); #if wxUSE_WCHAR_T // 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) #endif wxCSConv conv(encoding); - int i; - for (i = IndexOld; i < m_IndexCnt; i++) + size_t IndexCnt = m_index.size(); + 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 } @@ -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")); #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T - m_BookRecords.Add(bookr); - if (m_IndexCnt > 0) - qsort(m_Index, m_IndexCnt, sizeof(wxHtmlContentsItem), wxHtmlHelpIndexCompareFunc); + m_bookRecords.Add(bookr); + if (!m_index.empty()) + { + m_index.Sort(wxHtmlHelpIndexCompareFunc); + } - return TRUE; + return true; } @@ -643,6 +702,11 @@ bool wxHtmlHelpData::AddBook(const wxString& book) bool rtval = AddBookParam(*fi, enc, title, contents, index, start, fsys.GetPath()); delete fi; + +#if WXWIN_COMPATIBILITY_2_4 + CleanCompatibilityData(); +#endif + return rtval; } @@ -652,17 +716,16 @@ wxString wxHtmlHelpData::FindPageByName(const wxString& x) int i; wxFileSystem fsys; wxFSFile *f; - wxString url(wxEmptyString); /* 1. try to open given file: */ - cnt = m_BookRecords.GetCount(); + cnt = m_bookRecords.GetCount(); for (i = 0; i < cnt; i++) { - f = fsys.OpenFile(m_BookRecords[i].GetFullPath(x)); + f = fsys.OpenFile(m_bookRecords[i].GetFullPath(x)); if (f) { - url = m_BookRecords[i].GetFullPath(x); + wxString url = m_bookRecords[i].GetFullPath(x); delete f; return url; } @@ -673,58 +736,131 @@ wxString wxHtmlHelpData::FindPageByName(const wxString& x) for (i = 0; i < cnt; i++) { - if (m_BookRecords[i].GetTitle() == x) - { - url = m_BookRecords[i].GetFullPath(m_BookRecords[i].GetStart()); - return url; - } + if (m_bookRecords[i].GetTitle() == x) + return m_bookRecords[i].GetFullPath(m_bookRecords[i].GetStart()); } /* 3. try to find in contents: */ - cnt = m_ContentsCnt; + cnt = m_contents.size(); for (i = 0; i < cnt; i++) { - if (m_Contents[i].m_Name == x) - { - url = m_Contents[i].GetFullPath(); - return url; - } + if (m_contents[i].name == x) + return m_contents[i].GetFullPath(); } /* 4. try to find in index: */ - cnt = m_IndexCnt; + cnt = m_index.size(); for (i = 0; i < cnt; i++) { - if (m_Index[i].m_Name == x) - { - url = m_Index[i].GetFullPath(); - return url; - } + if (m_index[i].name == x) + return m_index[i].GetFullPath(); } - return url; + return wxEmptyString; } wxString wxHtmlHelpData::FindPageById(int id) { - int i; - wxString url(wxEmptyString); - - for (i = 0; i < m_ContentsCnt; i++) + size_t cnt = m_contents.size(); + for (size_t i = 0; i < cnt; i++) { - if (m_Contents[i].m_ID == id) + if (m_contents[i].id == id) { - url = m_Contents[i].GetFullPath(); - return url; + return m_contents[i].GetFullPath(); } } - 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 //---------------------------------------------------------------------------------- @@ -739,11 +875,11 @@ wxHtmlSearchStatus::wxHtmlSearchStatus(wxHtmlHelpData* data, const wxString& key if (book != wxEmptyString) { // 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++) - 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_MaxIndex = bookr->GetContentsEnd(); break; @@ -755,29 +891,38 @@ wxHtmlSearchStatus::wxHtmlSearchStatus(wxHtmlHelpData* data, const wxString& key { // no book specified; search all books 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_Active = (m_CurIndex < m_MaxIndex); } +#if WXWIN_COMPATIBILITY_2_4 +wxHtmlContentsItem* wxHtmlSearchStatus::GetContentsItem() +{ + static wxHtmlContentsItem it; + it = wxHtmlContentsItem(*m_CurItem); + return ⁢ +} +#endif + bool wxHtmlSearchStatus::Search() { wxFSFile *file; int i = m_CurIndex; // shortcut - bool found = FALSE; + bool found = false; wxString thepage; if (!m_Active) { // sanity check. Illegal use, but we'll try to prevent a crash anyway wxASSERT(m_Active); - return FALSE; + return false; } m_Name = wxEmptyString; - m_ContentsItem = NULL; - thepage = m_Data->m_Contents[i].m_Page; + m_CurItem = NULL; + thepage = m_Data->m_contents[i].page; m_Active = (++m_CurIndex < m_MaxIndex); // check if it is same page with different anchor: @@ -795,14 +940,14 @@ bool wxHtmlSearchStatus::Search() else m_LastPage = thepage; 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 (m_Engine.Scan(*file)) { - m_Name = m_Data->m_Contents[i].m_Name; - m_ContentsItem = m_Data->m_Contents + i; - found = TRUE; + m_Name = m_Data->m_contents[i].name; + m_CurItem = &m_Data->m_contents[i]; + found = true; } delete file; } diff --git a/src/html/helpfrm.cpp b/src/html/helpfrm.cpp index 98162cf3bc..d0e25f3765 100644 --- a/src/html/helpfrm.cpp +++ b/src/html/helpfrm.cpp @@ -57,6 +57,8 @@ #include "wx/filedlg.h" #include "wx/artprov.h" #include "wx/spinctrl.h" +#include "wx/dynarray.h" +#include "wx/choicdlg.h" // what is considered "small index"? #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 @@ -201,6 +255,8 @@ void wxHtmlHelpFrame::Init(wxHtmlHelpData* data) m_SearchCaseSensitive = NULL; m_SearchWholeWords = NULL; + m_mergedIndex = NULL; + m_Config = NULL; m_ConfigRoot = wxEmptyString; @@ -675,7 +731,53 @@ bool wxHtmlHelpFrame::DisplayIndex() return true; } +#include +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, @@ -743,7 +845,7 @@ bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword, #if wxUSE_PROGRESSDLG progress.Update(status.GetCurIndex(), foundstr); #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) { - wxHtmlContentsItem *it; switch ( mode ) { default: @@ -776,19 +877,27 @@ bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword, // fall back 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; + } case wxHELP_SEARCH_INDEX: - it = (wxHtmlContentsItem*) m_IndexList->GetClientData(0); + { + wxHtmlHelpMergedIndexItem* it = + (wxHtmlHelpMergedIndexItem*) m_IndexList->GetClientData(0); + if (it) + DisplayIndexItem(it); break; + } } - if (it) - { - m_HtmlWin->LoadPage(it->GetFullPath()); - NotifyPageChanged(); - } } return foundcnt > 0; @@ -804,12 +913,12 @@ void wxHtmlHelpFrame::CreateContents() WX_CLEAR_HASH_TABLE(*m_PagesHash); delete m_PagesHash; } - m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * m_Data->GetContentsCnt()); - - int cnt = m_Data->GetContentsCnt(); - int i; + + const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray(); + + size_t cnt = contents.size(); - wxHtmlContentsItem *it; + m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * cnt); const int MAX_ROOTS = 64; wxTreeItemId roots[MAX_ROOTS]; @@ -825,10 +934,11 @@ void wxHtmlHelpFrame::CreateContents() roots[0] = m_ContentsBox->AddRoot(_("(Help)")); 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: - if (it->m_Level == 0) + if (it->level == 0) { if (m_hfStyle & wxHF_MERGE_BOOKS) // VS: we don't want book nodes, books' content should @@ -840,7 +950,7 @@ void wxHtmlHelpFrame::CreateContents() else { roots[1] = m_ContentsBox->AppendItem(roots[0], - it->m_Name, IMG_Book, -1, + it->name, IMG_Book, -1, new wxHtmlHelpTreeItemData(i)); m_ContentsBox->SetItemBold(roots[1], true); } @@ -849,28 +959,28 @@ void wxHtmlHelpFrame::CreateContents() // ...and their contents: else { - roots[it->m_Level + 1] = m_ContentsBox->AppendItem( - roots[it->m_Level], it->m_Name, IMG_Page, + roots[it->level + 1] = m_ContentsBox->AppendItem( + roots[it->level], it->name, IMG_Page, -1, new wxHtmlHelpTreeItemData(i)); - imaged[it->m_Level + 1] = false; + imaged[it->level + 1] = false; } 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, // unless already done (see comment above imaged[] declaration) - if (!imaged[it->m_Level]) + if (!imaged[it->level]) { int image = IMG_Folder; if (m_hfStyle & wxHF_ICONS_BOOK) image = IMG_Book; else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER) - image = (it->m_Level == 1) ? IMG_Book : IMG_Folder; - m_ContentsBox->SetItemImage(roots[it->m_Level], image); - m_ContentsBox->SetItemImage(roots[it->m_Level], image, + image = (it->level == 1) ? IMG_Book : IMG_Folder; + m_ContentsBox->SetItemImage(roots[it->level], image); + m_ContentsBox->SetItemImage(roots[it->level], image, wxTreeItemIcon_Selected); - imaged[it->m_Level] = true; + imaged[it->level] = true; } } } @@ -883,18 +993,20 @@ void wxHtmlHelpFrame::CreateIndex() m_IndexList->Clear(); - int cnt = m_Data->GetIndexCnt(); + size_t cnt = m_mergedIndex->size(); wxString cnttext; - if (cnt > INDEX_IS_SMALL) cnttext.Printf(_("%i of %i"), 0, cnt); - else cnttext.Printf(_("%i of %i"), cnt, cnt); + if (cnt > INDEX_IS_SMALL) + cnttext.Printf(_("%i of %i"), 0, cnt); + else + cnttext.Printf(_("%i of %i"), cnt, cnt); m_IndexCountInfo->SetLabel(cnttext); - if (cnt > INDEX_IS_SMALL) return; - - wxHtmlContentsItem* index = m_Data->GetIndex(); + if (cnt > INDEX_IS_SMALL) + return; - for (int i = 0; i < cnt; i++) - m_IndexList->Append(index[i].m_Name, (char*)(index + i)); + for (size_t i = 0; i < cnt; i++) + m_IndexList->Append((*m_mergedIndex)[i].name, + (char*)(&(*m_mergedIndex)[i])); } void wxHtmlHelpFrame::CreateSearch() @@ -914,6 +1026,9 @@ void wxHtmlHelpFrame::CreateSearch() void wxHtmlHelpFrame::RefreshLists() { + // Update m_mergedIndex: + UpdateMergedIndex(); + // Update the controls CreateContents(); CreateIndex(); CreateSearch(); @@ -1275,10 +1390,10 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event) ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an); if (ha && ha->m_Index > 0) { - wxHtmlContentsItem *it = m_Data->GetContents() + (ha->m_Index - 1); - if (!it->m_Page.empty()) + const wxHtmlHelpDataItem& it = m_Data->GetContentsArray()[ha->m_Index - 1]; + if (!it.page.empty()) { - m_HtmlWin->LoadPage(it->GetFullPath()); + m_HtmlWin->LoadPage(it.GetFullPath()); NotifyPageChanged(); } } @@ -1296,15 +1411,20 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event) ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an); if (ha && ha->m_Index > 0) { - int level = m_Data->GetContents()[ha->m_Index].m_Level - 1; - wxHtmlContentsItem *it; + int level = + m_Data->GetContentsArray()[ha->m_Index].level - 1; int ind = ha->m_Index - 1; - it = m_Data->GetContents() + ind; - while (ind >= 0 && it->m_Level != level) ind--, it--; + const wxHtmlHelpDataItem *it = + &m_Data->GetContentsArray()[ind]; + while (ind >= 0 && it->level != level) + { + ind--, it--; + it = &m_Data->GetContentsArray()[ind]; + } if (ind >= 0) { - if (!it->m_Page.empty()) + if (!it->page.empty()) { m_HtmlWin->LoadPage(it->GetFullPath()); NotifyPageChanged(); @@ -1326,15 +1446,16 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event) 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(); } } @@ -1455,16 +1576,15 @@ void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event) void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event) { wxHtmlHelpTreeItemData *pg; - wxHtmlContentsItem *it; pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem()); if (pg && m_UpdateContents) { - it = m_Data->GetContents() + (pg->m_Id); + const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray(); m_UpdateContents = false; - if (!it->m_Page.empty()) - m_HtmlWin->LoadPage(it->GetFullPath()); + if (!contents[pg->m_Id].page.empty()) + m_HtmlWin->LoadPage(contents[pg->m_Id].GetFullPath()); m_UpdateContents = true; } } @@ -1473,10 +1593,10 @@ void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event) void wxHtmlHelpFrame::OnIndexSel(wxCommandEvent& WXUNUSED(event)) { - wxHtmlContentsItem *it = (wxHtmlContentsItem*) m_IndexList->GetClientData(m_IndexList->GetSelection()); - if (!it->m_Page.empty()) - m_HtmlWin->LoadPage(it->GetFullPath()); - NotifyPageChanged(); + wxHtmlHelpMergedIndexItem *it = (wxHtmlHelpMergedIndexItem*) + m_IndexList->GetClientData(m_IndexList->GetSelection()); + if (it) + DisplayIndexItem(it); } @@ -1491,33 +1611,39 @@ void wxHtmlHelpFrame::OnIndexFind(wxCommandEvent& event) else { wxBusyCursor bcur; - const wxChar *cstr = sr.c_str(); - wxChar mybuff[512]; - wxChar *ptr; - bool first = true; m_IndexList->Clear(); - int cnt = m_Data->GetIndexCnt(); - wxHtmlContentsItem* index = m_Data->GetIndex(); + const wxHtmlHelpMergedIndex& index = *m_mergedIndex; + size_t cnt = index.size(); 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); - 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) + if (index[i].name.Lower().find(sr) != wxString::npos) { - m_IndexList->Append(index[i].m_Name, (char*)(index + i)); - displ++; - if (first) + int pos = m_IndexList->Append(index[i].name, + (char*)(&index[i])); + + if (displ++ == 0) { - if (!index[i].m_Page.empty()) - m_HtmlWin->LoadPage(index[i].GetFullPath()); - NotifyPageChanged(); - first = false; + m_IndexList->SetSelection(0); + DisplayIndexItem(&index[i]); + } + + // 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; m_IndexList->Clear(); - int cnt = m_Data->GetIndexCnt(); + const wxHtmlHelpMergedIndex& index = *m_mergedIndex; + size_t cnt = index.size(); 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 (!index[i].m_Page.empty()) - m_HtmlWin->LoadPage(index[i].GetFullPath()); - NotifyPageChanged(); + DisplayIndexItem(&index[i]); first = false; } } @@ -1560,10 +1684,10 @@ void wxHtmlHelpFrame::OnIndexAll(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->m_Page.empty()) + if (!it->page.empty()) m_HtmlWin->LoadPage(it->GetFullPath()); NotifyPageChanged(); } @@ -1621,7 +1745,7 @@ void wxHtmlHelpFrame::OnClose(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); } #endif -- 2.47.2