#include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(wxHtmlBookRecArray)
+WX_DEFINE_OBJARRAY(wxHtmlHelpDataItems)
//-----------------------------------------------------------------------------
// static helper functions
-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<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;
+ 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
//-----------------------------------------------------------------------------
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)
};
{
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:
<OBJECT type="text/site properties">
<param name="Local" value="another.htm">
</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
*/
#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
//-----------------------------------------------------------------------------
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,
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
{
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())
{
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 \
bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord *book, wxInputStream *f)
{
- int i, st;
+ int i, st, newsize;
wxInt32 version;
/* load header - version info : */
// 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;
}
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('/');
}
}
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
!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;
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
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
}
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;
}
bool rtval = AddBookParam(*fi, enc,
title, contents, index, start, fsys.GetPath());
delete fi;
+
+#if WXWIN_COMPATIBILITY_2_4
+ CleanCompatibilityData();
+#endif
+
return rtval;
}
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;
}
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
//----------------------------------------------------------------------------------
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;
{
// 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:
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;
}
#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
};
+//---------------------------------------------------------------------------
+// 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
m_SearchCaseSensitive = NULL;
m_SearchWholeWords = NULL;
+ m_mergedIndex = NULL;
+
m_Config = NULL;
m_ConfigRoot = wxEmptyString;
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,
#if wxUSE_PROGRESSDLG
progress.Update(status.GetCurIndex(), foundstr);
#endif
- m_SearchList->Append(status.GetName(), status.GetContentsItem());
+ m_SearchList->Append(status.GetName(), (void*)status.GetCurItem());
}
}
if (foundcnt)
{
- wxHtmlContentsItem *it;
switch ( mode )
{
default:
// 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;
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];
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
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);
}
// ...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;
}
}
}
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()
void wxHtmlHelpFrame::RefreshLists()
{
+ // Update m_mergedIndex:
+ UpdateMergedIndex();
+ // Update the controls
CreateContents();
CreateIndex();
CreateSearch();
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();
}
}
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();
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();
}
}
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;
}
}
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);
}
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;
}
}
}
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;
}
}
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();
}
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