]> git.saurik.com Git - wxWidgets.git/blob - src/html/htmlhelp.cpp
Applied patch [ 1409971 ] wxX11: fix for DoDrawBitmap() when scaling is set
[wxWidgets.git] / src / html / htmlhelp.cpp
1 // Name:        htmlhelp.cpp
2 // Purpose:     Help controller
3 // Author:      Vaclav Slavik
4 // Copyright:   (c) 1999 Vaclav Slavik
5 // Licence:     wxWindows Licence
6 /////////////////////////////////////////////////////////////////////////////
7
8 #error This file should not be compiled! Update your build system! \
9 (configure users, rerun configure to get a new Makefile) \
10 Instead of htmlhelp[_io], use helpdata, helpfrm and helpctrl. This \
11 file is only left to point out the problem and will be removed r.s.n.
12
13 #ifdef __GNUG__
14 #pragma implementation "htmlhelp.h"
15 #endif
16
17 #include "wx/wxprec.h"
18
19 #if wxUSE_HTML
20
21 #ifdef __BORDLANDC__
22 #pragma hdrstop
23 #endif
24
25 #ifndef WXPRECOMP
26 #endif
27
28 #include <wx/notebook.h>
29 #include <wx/imaglist.h>
30 #include <wx/treectrl.h>
31 #include <wx/tokenzr.h>
32 #include <wx/wfstream.h>
33 #include <wx/html/htmlwin.h>
34 #include <wx/html/htmlhelp.h>
35 #include <wx/busyinfo.h>
36
37 #if !((wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7)))
38 #include <wx/progdlg.h>
39 #endif
40
41
42 // Bitmaps:
43
44 #ifndef __WXMSW__
45     // XPM hack: make the arrays const
46     #define static static const
47
48     #include "bitmaps/panel.xpm"
49     #include "bitmaps/back.xpm"
50     #include "bitmaps/forward.xpm"
51     #include "bitmaps/book.xpm"
52     #include "bitmaps/folder.xpm"
53     #include "bitmaps/page.xpm"
54
55     #undef static
56 #endif
57
58 #include "search.h"
59
60
61
62
63 #include <wx/arrimpl.cpp>
64 WX_DEFINE_OBJARRAY(HtmlBookRecArray)
65
66
67
68
69
70
71
72
73
74 //-----------------------------------------------------------------------------
75 // wxHtmlHelpController
76 //-----------------------------------------------------------------------------
77
78
79 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpController, wxEvtHandler)
80
81
82 wxHtmlHelpController::wxHtmlHelpController() : wxEvtHandler()
83 {
84     m_Frame = NULL;
85     m_Config = NULL;
86     m_ConfigRoot = wxEmptyString;
87     m_TitleFormat = _("Help : %s");
88     m_TempPath = wxEmptyString;
89
90     m_Cfg.x = m_Cfg.y = 0;
91     m_Cfg.w = 700; m_Cfg.h = 480;
92     m_Cfg.sashpos = 240;
93     m_Cfg.navig_on = TRUE;
94
95     m_ContentsImageList = new wxImageList(12, 12);
96     m_ContentsImageList -> Add(wxICON(book));
97     m_ContentsImageList -> Add(wxICON(folder));
98     m_ContentsImageList -> Add(wxICON(page));
99
100     m_Contents = NULL;
101     m_ContentsCnt = 0;
102     m_Index = NULL;
103     m_IndexCnt = 0;
104
105     m_IndexBox = NULL;
106     m_ContentsBox = NULL;
107     m_SearchList = NULL;
108     m_SearchText = NULL;
109     m_SearchButton = NULL;
110     m_HtmlWin = NULL;
111     m_Splitter = NULL;
112     m_NavigPan = NULL;
113 }
114
115
116
117 wxHtmlHelpController::~wxHtmlHelpController()
118 {
119     int i;
120
121     m_BookRecords.Empty();
122     delete m_ContentsImageList;
123     if (m_Contents) {
124         for (i = 0; i < m_ContentsCnt; i++) {
125             delete[] m_Contents[i].m_Page;
126             delete[] m_Contents[i].m_Name;
127         }
128         free(m_Contents);
129     }
130     if (m_Index) {
131         for (i = 0; i < m_IndexCnt; i++) {
132             delete[] m_Index[i].m_Page;
133             delete[] m_Index[i].m_Name;
134         }
135         free(m_Index);
136     }
137 }
138
139
140
141 void wxHtmlHelpController::SetTempDir(const wxString& path)
142 {
143     if (path == wxEmptyString) m_TempPath = path;
144     else {
145         if (wxIsAbsolutePath(path)) m_TempPath = path;
146         else m_TempPath = wxGetCwd() + "/" + path;
147
148         if (m_TempPath[m_TempPath.Length() - 1] != '/')
149             m_TempPath << "/";
150     }
151 }
152
153
154
155
156 // Reads one line, stores it into buf and returns pointer to new line or NULL.
157 static char* ReadLine(char *line, char *buf)
158 {
159     char *writeptr = buf, *readptr = line;
160
161     while (*readptr != 0 && *readptr != '\r' && *readptr != '\n') *(writeptr++) = *(readptr++);
162     *writeptr = 0;
163     while (*readptr == '\r' || *readptr == '\n') readptr++;
164     if (*readptr == 0) return NULL;
165     else return readptr;
166 }
167
168
169 static wxString SafeFileName(const wxString& s)
170 {
171     wxString res = s;
172     res.Replace(_T(":"), _T("_"), TRUE);
173     res.Replace(_T(" "), _T("_"), TRUE);
174     res.Replace(_T("/"), _T("_"), TRUE);
175     res.Replace(_T("\\"), _T("_"), TRUE);
176     res.Replace(_T("#"), _T("_"), TRUE);
177     res.Replace(_T("."), _T("_"), TRUE);
178     return res;
179 }
180
181
182 static int IndexCompareFunc(const void *a, const void *b)
183 {
184     return strcmp(((HtmlContentsItem*)a) -> m_Name, ((HtmlContentsItem*)b) -> m_Name);
185 }
186
187
188
189 bool wxHtmlHelpController::AddBook(const wxString& book, bool show_wait_msg)
190 {
191     wxFSFile *fi;
192     wxFileSystem fsys;
193     wxInputStream *s;
194     HtmlBookRecord *bookr;
195     wxString bookFull;
196
197     int sz;
198     char *buff, *lineptr;
199     char linebuf[300];
200
201     wxString title = _("noname"),
202              safetitle,
203              start = wxEmptyString,
204              contents = wxEmptyString, index = wxEmptyString;
205
206     if (wxIsAbsolutePath(book)) bookFull = book;
207     else bookFull = wxGetCwd() + "/" + book;
208
209     fi = fsys.OpenFile(bookFull);
210     if (fi == NULL) return FALSE;
211     fsys.ChangePathTo(bookFull);
212     s = fi -> GetStream();
213     sz = s -> GetSize();
214     buff = new char[sz+1];
215     buff[sz] = 0;
216     s -> Read(buff, sz);
217     lineptr = buff;
218     delete fi;
219
220     while ((lineptr = ReadLine(lineptr, linebuf)) != NULL) {
221         if (strstr(linebuf, "Title=") == linebuf)
222             title = linebuf + strlen("Title=");
223         if (strstr(linebuf, "Default topic=") == linebuf)
224             start = linebuf + strlen("Default topic=");
225         if (strstr(linebuf, "Index file=") == linebuf)
226             index = linebuf + strlen("Index file=");
227         if (strstr(linebuf, "Contents file=") == linebuf)
228             contents = linebuf + strlen("Contents file=");
229     }
230     delete[] buff;
231
232     bookr = new HtmlBookRecord(fsys.GetPath(), title, start);
233
234     if (m_ContentsCnt % HTML_REALLOC_STEP == 0)
235         m_Contents = (HtmlContentsItem*) realloc(m_Contents, (m_ContentsCnt + HTML_REALLOC_STEP) * sizeof(HtmlContentsItem));
236     m_Contents[m_ContentsCnt].m_Level = 0;
237     m_Contents[m_ContentsCnt].m_ID = 0;
238     m_Contents[m_ContentsCnt].m_Page = new char[start.Length() + 1];
239     strcpy(m_Contents[m_ContentsCnt].m_Page, start.c_str());
240     m_Contents[m_ContentsCnt].m_Name = new char [title.Length() + 1];
241     strcpy(m_Contents[m_ContentsCnt].m_Name, title.c_str());
242     m_Contents[m_ContentsCnt].m_Book = bookr;
243     m_ContentsCnt++;
244
245     // Try to find cached binary versions:
246     safetitle = SafeFileName(title);
247     fi = fsys.OpenFile(safetitle + ".cached");
248     if (fi == NULL) fi = fsys.OpenFile(m_TempPath + safetitle + ".cached");
249     if ((fi == NULL) || (m_TempPath == wxEmptyString)) {
250         LoadMSProject(bookr, fsys, index, contents, show_wait_msg);
251         if (m_TempPath != wxEmptyString) {
252                 wxFileOutputStream *outs = new wxFileOutputStream(m_TempPath + safetitle + ".cached");
253             SaveCachedBook(bookr, outs);
254             delete outs;
255         }
256     }
257     else {
258         LoadCachedBook(bookr, fi -> GetStream());
259         delete fi;
260     }
261
262     m_BookRecords.Add(bookr);
263     if (m_IndexCnt > 0)
264         qsort(m_Index, m_IndexCnt, sizeof(HtmlContentsItem), IndexCompareFunc);
265
266     return TRUE;
267 }
268
269
270
271
272 void wxHtmlHelpController::Display(const wxString& x)
273 {
274     int cnt;
275     int i;
276     wxFileSystem fsys;
277     wxFSFile *f;
278
279     CreateHelpWindow();
280
281     /* 1. try to open given file: */
282
283     cnt = m_BookRecords.GetCount();
284     for (i = 0; i < cnt; i++) {
285         f = fsys.OpenFile(m_BookRecords[i].GetBasePath() + x);
286         if (f) {
287             m_HtmlWin -> LoadPage(m_BookRecords[i].GetBasePath() + x);
288             delete f;
289             return;
290         }
291     }
292
293
294     /* 2. try to find a book: */
295
296     for (i = 0; i < cnt; i++) {
297         if (m_BookRecords[i].GetTitle() == x) {
298             m_HtmlWin -> LoadPage(m_BookRecords[i].GetBasePath() + m_BookRecords[i].GetStart());
299             return;
300         }
301     }
302
303     /* 3. try to find in contents: */
304
305     cnt = m_ContentsCnt;
306     for (i = 0; i < cnt; i++) {
307         if (strcmp(m_Contents[i].m_Name, x) == 0) {
308             m_HtmlWin -> LoadPage(m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page);
309             return;
310         }
311     }
312
313
314     /* 4. try to find in index: */
315
316     cnt = m_IndexCnt;
317     for (i = 0; i < cnt; i++) {
318         if (strcmp(m_Index[i].m_Name, x) == 0) {
319             m_HtmlWin -> LoadPage(m_Index[i].m_Book -> GetBasePath() + m_Index[i].m_Page);
320             return;
321         }
322     }
323
324
325     /* 5. if everything failed, search the documents: */
326
327     KeywordSearch(x);
328 }
329
330
331
332 void wxHtmlHelpController::Display(const int id)
333 {
334     CreateHelpWindow();
335
336     for (int i = 0; i < m_ContentsCnt; i++) {
337         if (m_Contents[i].m_ID == id) {
338             m_HtmlWin -> LoadPage(m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page);
339             return;
340         }
341     }
342 }
343
344
345
346 void wxHtmlHelpController::DisplayContents()
347 {
348     CreateHelpWindow();
349     m_Frame -> Raise();
350     if (!m_Splitter -> IsSplit()) {
351        m_NavigPan -> Show(TRUE);
352        m_HtmlWin -> Show(TRUE);
353        m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
354     }
355     m_NavigPan -> SetSelection(0);
356 }
357
358
359
360 void wxHtmlHelpController::DisplayIndex()
361 {
362     CreateHelpWindow();
363     m_Frame -> Raise();
364     if (!m_Splitter -> IsSplit()) {
365        m_NavigPan -> Show(TRUE);
366        m_HtmlWin -> Show(TRUE);
367        m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
368     }
369     m_NavigPan -> SetSelection(1);
370 }
371
372
373
374
375 #if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7))
376
377 class MyProgressDlg : public wxDialog
378 {
379     public:
380         bool m_Canceled;
381
382         MyProgressDlg(wxWindow *parent) : wxDialog(parent, -1,
383                       _("Searching..."),
384                       wxPoint(0, 0),
385 #ifdef __WXGTK__
386                       wxSize(300, 110)
387 #else
388                       wxSize(300, 130)
389 #endif
390               )
391                       {m_Canceled = FALSE;}
392         void OnCancel(wxCommandEvent& event) {m_Canceled = TRUE;}
393         DECLARE_EVENT_TABLE()
394 };
395 BEGIN_EVENT_TABLE(MyProgressDlg, wxDialog)
396     EVT_BUTTON(wxID_CANCEL, MyProgressDlg::OnCancel)
397 END_EVENT_TABLE()
398
399 #endif
400
401
402 bool wxHtmlHelpController::KeywordSearch(const wxString& keyword)
403 {
404     int foundcnt = 0;
405     CreateHelpWindow();
406     // if these are not set, we can't continue
407     if (! (m_SearchList && m_HtmlWin))
408        return FALSE;
409     m_Frame -> Raise();
410     if (m_Splitter && m_NavigPan && m_SearchButton) {
411        if (!m_Splitter -> IsSplit()) {
412           m_NavigPan -> Show(TRUE);
413           m_HtmlWin -> Show(TRUE);
414           m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
415        }
416        m_NavigPan -> SetSelection(2);
417        m_SearchList -> Clear();
418        m_SearchText -> SetValue(keyword);
419        m_SearchButton -> Enable(FALSE);
420     }
421     {
422         int cnt = m_ContentsCnt;
423         wxSearchEngine engine;
424         wxFileSystem fsys;
425         wxFSFile *file;
426         wxString lastpage = wxEmptyString;
427         wxString foundstr;
428
429 #if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7))
430         MyProgressDlg progress(m_Frame);
431
432         wxStaticText *prompt = new wxStaticText(&progress, -1, "", wxPoint(20, 50), wxSize(260, 25), wxALIGN_CENTER);
433         wxGauge *gauge = new wxGauge(&progress, -1, cnt, wxPoint(20, 20), wxSize(260, 25));
434         wxButton *btn = new wxButton(&progress, wxID_CANCEL, _("Cancel"), wxPoint(110, 70), wxSize(80, 25));
435         btn = btn; /* fool compiler :-) */
436         prompt -> SetLabel(_("No matching page found yet"));
437
438         progress.Centre(wxBOTH);
439         progress.Show(TRUE);
440 #else
441         wxProgressDialog progress(_("Searching..."), _("No matching page found yet"), cnt, m_Frame, wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
442 #endif
443
444         engine.LookFor(keyword);
445
446         for (int i = 0; i < cnt; i++) {
447 #if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7))
448             gauge -> SetValue(i);
449             if (progress.m_Canceled) break;
450 #else
451             if (progress.Update(i) == FALSE) break;
452 #endif
453             wxYield();
454
455             file = fsys.OpenFile(m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page);
456             if (file) {
457                 if (lastpage != file -> GetLocation()) {
458                     lastpage = file -> GetLocation();
459                     if (engine.Scan(file -> GetStream())) {
460                         foundstr.Printf(_("Found %i matches"), ++foundcnt);
461 #if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7))
462                         prompt -> SetLabel(foundstr);
463 #else
464                         progress.Update(i, foundstr);
465 #endif
466                         wxYield();
467                         m_SearchList -> Append(m_Contents[i].m_Name, (char*)(m_Contents + i));
468                     }
469                 }
470                 delete file;
471             }
472         }
473
474 #if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7))
475         progress.Close(TRUE);
476 #endif
477     }
478     if (m_SearchButton)
479         m_SearchButton -> Enable(TRUE);
480     if (m_SearchText) {
481         m_SearchText -> SetSelection(0, keyword.Length());
482         m_SearchText -> SetFocus();
483     }
484     if (foundcnt) {
485         HtmlContentsItem *it = (HtmlContentsItem*) m_SearchList -> GetClientData(0);
486         if (it) m_HtmlWin -> LoadPage(it -> m_Book -> GetBasePath() + it -> m_Page);
487     }
488     return (foundcnt > 0);
489 }
490
491
492
493
494
495
496 void wxHtmlHelpController::CreateHelpWindow()
497 {
498     wxBusyCursor cur;
499     wxString oldpath;
500     wxStatusBar *sbar;
501
502     if (m_Frame) {
503         m_Frame -> Raise();
504         m_Frame -> Show(TRUE);
505         return;
506     }
507
508 #if wxUSE_BUSYINFO
509     wxBusyInfo busyinfo(_("Preparing help window..."));
510 #endif
511
512     if (m_Config) ReadCustomization(m_Config, m_ConfigRoot);
513
514     m_Frame = new wxFrame(NULL, -1, "", wxPoint(m_Cfg.x, m_Cfg.y), wxSize(m_Cfg.w, m_Cfg.h));
515     m_Frame -> PushEventHandler(this);
516     sbar = m_Frame -> CreateStatusBar();
517
518     {
519         wxToolBar *toolBar;
520         toolBar = m_Frame -> CreateToolBar(wxNO_BORDER | wxTB_HORIZONTAL | wxTB_FLAT | wxTB_DOCKABLE);
521         toolBar -> SetMargins(2, 2);
522         wxBitmap* toolBarBitmaps[3];
523
524 #ifdef __WXMSW__
525         toolBarBitmaps[0] = new wxBitmap("panel");
526         toolBarBitmaps[1] = new wxBitmap("back");
527         toolBarBitmaps[2] = new wxBitmap("forward");
528         int width = 24;
529 #else
530         toolBarBitmaps[0] = new wxBitmap(panel_xpm);
531         toolBarBitmaps[1] = new wxBitmap(back_xpm);
532         toolBarBitmaps[2] = new wxBitmap(forward_xpm);
533         int width = 16;
534 #endif
535
536         int currentX = 5;
537
538         toolBar -> AddTool(wxID_HTML_PANEL, *(toolBarBitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, _("Show/hide navigation panel"));
539         currentX += width + 5;
540         toolBar -> AddSeparator();
541         toolBar -> AddTool(wxID_HTML_BACK, *(toolBarBitmaps[1]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, _("Go back to the previous HTML page"));
542         currentX += width + 5;
543         toolBar -> AddTool(wxID_HTML_FORWARD, *(toolBarBitmaps[2]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, _("Go forward to the next HTML page"));
544         currentX += width + 5;
545
546         toolBar -> Realize();
547
548         // Can delete the bitmaps since they're reference counted
549         for (int i = 0; i < 3; i++) delete toolBarBitmaps[i];
550     }
551
552
553     {
554         m_Splitter = new wxSplitterWindow(m_Frame);
555
556         m_HtmlWin = new wxHtmlWindow(m_Splitter);
557         m_HtmlWin -> SetRelatedFrame(m_Frame, m_TitleFormat);
558         m_HtmlWin -> SetRelatedStatusBar(0);
559         if (m_Config) m_HtmlWin -> ReadCustomization(m_Config, m_ConfigRoot);
560
561         m_NavigPan = new wxNotebook(m_Splitter, wxID_HTML_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
562         {
563             m_ContentsBox = new wxTreeCtrl(m_NavigPan, wxID_HTML_TREECTRL, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSUNKEN_BORDER);
564             m_ContentsBox -> SetImageList(m_ContentsImageList);
565             m_NavigPan -> AddPage(m_ContentsBox, _("Contents"));
566         }
567
568         {
569             wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_INDEXPAGE);
570             wxLayoutConstraints *b1 = new wxLayoutConstraints;
571             b1 -> top.SameAs        (dummy, wxTop, 0);
572             b1 -> left.SameAs       (dummy, wxLeft, 0);
573             b1 -> width.PercentOf   (dummy, wxWidth, 100);
574             b1 -> bottom.SameAs     (dummy, wxBottom, 0);
575             m_IndexBox = new wxListBox(dummy, wxID_HTML_INDEXLIST, wxDefaultPosition, wxDefaultSize, 0);
576             m_IndexBox -> SetConstraints(b1);
577             dummy -> SetAutoLayout(TRUE);
578             m_NavigPan -> AddPage(dummy, _("Index"));
579         }
580
581         {
582             wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_SEARCHPAGE);
583
584             wxLayoutConstraints *b1 = new wxLayoutConstraints;
585             m_SearchText = new wxTextCtrl(dummy, wxID_HTML_SEARCHTEXT);
586             b1 -> top.SameAs        (dummy, wxTop, 0);
587             b1 -> left.SameAs       (dummy, wxLeft, 0);
588             b1 -> right.SameAs      (dummy, wxRight, 0);
589             b1 -> height.AsIs();
590             m_SearchText -> SetConstraints(b1);
591
592             wxLayoutConstraints *b2 = new wxLayoutConstraints;
593             m_SearchButton = new wxButton(dummy, wxID_HTML_SEARCHBUTTON, _("Search!"));
594             b2 -> top.Below         (m_SearchText, 10);
595             b2 -> right.SameAs      (dummy, wxRight, 10);
596             b2 -> width.AsIs();
597             b2 -> height.AsIs();
598             m_SearchButton -> SetConstraints(b2);
599
600             wxLayoutConstraints *b3 = new wxLayoutConstraints;
601             m_SearchList = new wxListBox(dummy, wxID_HTML_SEARCHLIST, wxDefaultPosition, wxDefaultSize, 0);
602             b3 -> top.Below         (m_SearchButton, 10);
603             b3 -> left.SameAs       (dummy, wxLeft, 0);
604             b3 -> right.SameAs      (dummy, wxRight, 0);
605             b3 -> bottom.SameAs     (dummy, wxBottom, 0);
606             m_SearchList -> SetConstraints(b3);
607
608             dummy -> SetAutoLayout(TRUE);
609             dummy -> Layout();
610             m_NavigPan -> AddPage(dummy, _("Search"));
611         }
612
613         RefreshLists();
614         m_NavigPan -> Show(TRUE);
615         m_HtmlWin -> Show(TRUE);
616         m_Splitter -> SetMinimumPaneSize(20);
617         m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
618         if (!m_Cfg.navig_on) m_Splitter -> Unsplit(m_NavigPan);
619         wxYield();
620     }
621
622     m_Frame -> Show(TRUE);
623     wxYield();
624 }
625
626
627
628 #define MAX_ROOTS 64
629
630 void wxHtmlHelpController::CreateContents()
631 {
632     HtmlContentsItem *it;
633     wxTreeItemId roots[MAX_ROOTS];
634     bool imaged[MAX_ROOTS];
635     int count = m_ContentsCnt;
636
637     m_ContentsBox -> DeleteAllItems();
638     roots[0] = m_ContentsBox -> AddRoot(_("(Help)"));
639     imaged[0] = TRUE;
640
641     for (int i = 0; i < count; i++) {
642         it = m_Contents + i;
643         roots[it -> m_Level + 1] = m_ContentsBox -> AppendItem(roots[it -> m_Level], it -> m_Name, IMG_Page, -1, new wxHtmlHelpTreeItemData(it));
644         if (it -> m_Level == 0) {
645             m_ContentsBox -> SetItemBold(roots[1], TRUE);
646             m_ContentsBox -> SetItemImage(roots[1], IMG_Book);
647             m_ContentsBox -> SetItemSelectedImage(roots[1], IMG_Book);
648             imaged[1] = TRUE;
649         }
650         else imaged[it -> m_Level + 1] = FALSE;
651
652         if (!imaged[it -> m_Level]) {
653             m_ContentsBox -> SetItemImage(roots[it -> m_Level], IMG_Folder);
654             m_ContentsBox -> SetItemSelectedImage(roots[it -> m_Level], IMG_Folder);
655             imaged[it -> m_Level] = TRUE;
656         }
657     }
658
659     m_ContentsBox -> Expand(roots[0]);
660 }
661
662
663
664
665 void wxHtmlHelpController::CreateIndex()
666 {
667     m_IndexBox -> Clear();
668
669     for (int i = 0; i < m_IndexCnt; i++)
670         m_IndexBox -> Append(m_Index[i].m_Name, (char*)(m_Index + i));
671 }
672
673
674
675 void wxHtmlHelpController::RefreshLists()
676 {
677     if (m_Frame) {
678         CreateContents();
679         CreateIndex();
680         m_SearchList -> Clear();
681     }
682 }
683
684
685
686
687
688
689
690 void wxHtmlHelpController::ReadCustomization(wxConfigBase *cfg, wxString path)
691 {
692     wxString oldpath;
693     wxString tmp;
694
695     if (path != wxEmptyString) {
696         oldpath = cfg -> GetPath();
697         cfg -> SetPath(path);
698     }
699
700     m_Cfg.navig_on = cfg -> Read("hcNavigPanel", m_Cfg.navig_on) != 0;
701     m_Cfg.sashpos = cfg -> Read("hcSashPos", m_Cfg.sashpos);
702     m_Cfg.x = cfg -> Read("hcX", m_Cfg.x);
703     m_Cfg.y = cfg -> Read("hcY", m_Cfg.y);
704     m_Cfg.w = cfg -> Read("hcW", m_Cfg.w);
705     m_Cfg.h = cfg -> Read("hcH", m_Cfg.h);
706
707     if (path != wxEmptyString)
708         cfg -> SetPath(oldpath);
709 }
710
711
712
713 void wxHtmlHelpController::WriteCustomization(wxConfigBase *cfg, wxString path)
714 {
715     wxString oldpath;
716     wxString tmp;
717
718     if (path != wxEmptyString) {
719         oldpath = cfg -> GetPath();
720         cfg -> SetPath(path);
721     }
722
723     cfg -> Write("hcNavigPanel", m_Cfg.navig_on);
724     cfg -> Write("hcSashPos", (long)m_Cfg.sashpos);
725     cfg -> Write("hcX", (long)m_Cfg.x);
726     cfg -> Write("hcY", (long)m_Cfg.y);
727     cfg -> Write("hcW", (long)m_Cfg.w);
728     cfg -> Write("hcH", (long)m_Cfg.h);
729
730     if (path != wxEmptyString)
731         cfg -> SetPath(oldpath);
732 }
733
734
735
736
737
738 /*
739 EVENT HANDLING :
740 */
741
742
743 void wxHtmlHelpController::OnToolbar(wxCommandEvent& event)
744 {
745     switch (event.GetId()) {
746         case wxID_HTML_BACK :
747             m_HtmlWin -> HistoryBack();
748             break;
749         case wxID_HTML_FORWARD :
750             m_HtmlWin -> HistoryForward();
751             break;
752         case wxID_HTML_PANEL :
753             if (m_Splitter -> IsSplit()) {
754                 m_Cfg.sashpos = m_Splitter -> GetSashPosition();
755                 m_Splitter -> Unsplit(m_NavigPan);
756             }
757             else {
758                 m_NavigPan -> Show(TRUE);
759                 m_HtmlWin -> Show(TRUE);
760                 m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
761             }
762             break;
763     }
764 }
765
766
767
768 void wxHtmlHelpController::OnContentsSel(wxTreeEvent& event)
769 {
770     wxHtmlHelpTreeItemData *pg;
771
772     pg = (wxHtmlHelpTreeItemData*) m_ContentsBox -> GetItemData(event.GetItem());
773     if (pg) m_HtmlWin -> LoadPage(pg -> GetPage());
774 }
775
776
777
778 void wxHtmlHelpController::OnIndexSel(wxCommandEvent& event)
779 {
780     HtmlContentsItem *it = (HtmlContentsItem*) m_IndexBox -> GetClientData(m_IndexBox -> GetSelection());
781     if (it) m_HtmlWin -> LoadPage(it -> m_Book -> GetBasePath() + it -> m_Page);
782 }
783
784
785
786 void wxHtmlHelpController::OnSearchSel(wxCommandEvent& event)
787 {
788     HtmlContentsItem *it = (HtmlContentsItem*) m_SearchList -> GetClientData(m_SearchList -> GetSelection());
789     if (it) m_HtmlWin -> LoadPage(it -> m_Book -> GetBasePath() + it -> m_Page);
790 }
791
792
793
794 void wxHtmlHelpController::OnCloseWindow(wxCloseEvent& event)
795 {
796     int a, b;
797
798     m_Cfg.navig_on = m_Splitter -> IsSplit();
799     if (m_Cfg.navig_on)
800         m_Cfg.sashpos = m_Splitter -> GetSashPosition();
801     m_Frame -> GetPosition(&a, &b);
802     m_Cfg.x = a, m_Cfg.y = b;
803     m_Frame -> GetSize(&a, &b);
804     m_Cfg.w = a, m_Cfg.h = b;
805
806     if (m_Config) {
807         WriteCustomization(m_Config, m_ConfigRoot);
808         m_HtmlWin -> WriteCustomization(m_Config, m_ConfigRoot);
809     }
810     m_Frame = NULL;
811
812     event.Skip();
813 }
814
815
816
817 void wxHtmlHelpController::OnSearch(wxCommandEvent& event)
818 {
819     wxString sr = m_SearchText -> GetLineText(0);
820
821     if (sr != wxEmptyString) KeywordSearch(sr);
822 }
823
824
825
826 BEGIN_EVENT_TABLE(wxHtmlHelpController, wxEvtHandler)
827     EVT_TOOL_RANGE(wxID_HTML_PANEL, wxID_HTML_FORWARD, wxHtmlHelpController::OnToolbar)
828     EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL, wxHtmlHelpController::OnContentsSel)
829     EVT_LISTBOX(wxID_HTML_INDEXLIST, wxHtmlHelpController::OnIndexSel)
830     EVT_LISTBOX(wxID_HTML_SEARCHLIST, wxHtmlHelpController::OnSearchSel)
831     EVT_CLOSE(wxHtmlHelpController::OnCloseWindow)
832     EVT_BUTTON(wxID_HTML_SEARCHBUTTON, wxHtmlHelpController::OnSearch)
833     EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT, wxHtmlHelpController::OnSearch)
834 END_EVENT_TABLE()
835
836
837
838 #endif
839