]> git.saurik.com Git - wxWidgets.git/blame - src/html/helpwnd.cpp
Fix item selection/focus drawing in generic wxListCtrl.
[wxWidgets.git] / src / html / helpwnd.cpp
CommitLineData
3755cfa6 1/////////////////////////////////////////////////////////////////////////////
548b5377 2// Name: src/html/helpwnd.cpp
3755cfa6
JS
3// Purpose: wxHtmlHelpWindow
4// Notes: Based on htmlhelp.cpp, implementing a monolithic
5// HTML Help controller class, by Vaclav Slavik
6// Author: Harm van der Heijden and Vaclav Slavik
7// RCS-ID: $Id$
8// Copyright: (c) Harm van der Heijden and Vaclav Slavik
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h"
13
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
8e3f3880 17 #pragma hdrstop
3755cfa6
JS
18#endif
19
20#if wxUSE_WXHTML_HELP
21
b4f4d3dd 22#ifndef WX_PRECOMP
8e3f3880 23 #include "wx/object.h"
ad9835c9 24 #include "wx/dynarray.h"
3755cfa6
JS
25 #include "wx/intl.h"
26 #include "wx/log.h"
530ecef0
WS
27 #if wxUSE_STREAMS
28 #include "wx/stream.h"
29 #endif
3755cfa6 30
3755cfa6
JS
31 #include "wx/sizer.h"
32
33 #include "wx/bmpbuttn.h"
34 #include "wx/statbox.h"
35 #include "wx/radiobox.h"
3b3dc801 36 #include "wx/menu.h"
9eddec69 37 #include "wx/settings.h"
3755cfa6 38 #include "wx/msgdlg.h"
fec9cc08 39 #include "wx/textctrl.h"
4e3e485b 40 #include "wx/toolbar.h"
949c9f74
WS
41 #include "wx/choicdlg.h"
42 #include "wx/filedlg.h"
b4f4d3dd 43#endif // WX_PRECOMP
3755cfa6
JS
44
45#include "wx/html/helpfrm.h"
46#include "wx/html/helpdlg.h"
47#include "wx/html/helpctrl.h"
3755cfa6
JS
48#include "wx/notebook.h"
49#include "wx/imaglist.h"
50#include "wx/treectrl.h"
51#include "wx/tokenzr.h"
52#include "wx/wfstream.h"
53#include "wx/html/htmlwin.h"
54#include "wx/busyinfo.h"
55#include "wx/progdlg.h"
3755cfa6 56#include "wx/fontenum.h"
3755cfa6
JS
57#include "wx/artprov.h"
58#include "wx/spinctrl.h"
3755cfa6
JS
59
60// what is considered "small index"?
61#define INDEX_IS_SMALL 100
62
63/* Motif defines this as a macro */
64#ifdef Below
65#undef Below
66#endif
67
68//--------------------------------------------------------------------------
69// wxHtmlHelpTreeItemData (private)
70//--------------------------------------------------------------------------
71
72class wxHtmlHelpTreeItemData : public wxTreeItemData
73{
74 public:
75#if defined(__VISAGECPP__)
76// VA needs a default ctor for some reason....
77 wxHtmlHelpTreeItemData() : wxTreeItemData()
78 { m_Id = 0; }
79#endif
80 wxHtmlHelpTreeItemData(int id) : wxTreeItemData()
81 { m_Id = id;}
82
83 int m_Id;
84};
85
86
87//--------------------------------------------------------------------------
88// wxHtmlHelpHashData (private)
89//--------------------------------------------------------------------------
90
91class wxHtmlHelpHashData : public wxObject
92{
93 public:
94 wxHtmlHelpHashData(int index, wxTreeItemId id) : wxObject()
95 { m_Index = index; m_Id = id;}
d3c7fc99 96 virtual ~wxHtmlHelpHashData() {}
3755cfa6
JS
97
98 int m_Index;
99 wxTreeItemId m_Id;
100};
101
102
103//--------------------------------------------------------------------------
104// wxHtmlHelpHtmlWindow (private)
105//--------------------------------------------------------------------------
106
3755cfa6
JS
107
108class wxHtmlHelpHtmlWindow : public wxHtmlWindow
109{
630906de 110public:
6f3f9b50
JS
111 wxHtmlHelpHtmlWindow(wxHtmlHelpWindow *win, wxWindow *parent, wxWindowID id = wxID_ANY,
112 const wxPoint& pos = wxDefaultPosition, const wxSize& sz = wxDefaultSize, long style = wxHW_DEFAULT_STYLE)
113 : wxHtmlWindow(parent, id, pos, sz, style), m_Window(win)
630906de
VZ
114 {
115 SetStandardFonts();
116 }
117
118 void OnLink(wxHtmlLinkEvent& ev)
119 {
120 const wxMouseEvent *e = ev.GetLinkInfo().GetEvent();
121 if (e == NULL || e->LeftUp())
122 m_Window->NotifyPageChanged();
325219cb
VS
123
124 // skip the event so that normal processing (i.e. following the link)
125 // is done:
126 ev.Skip();
630906de
VZ
127 }
128
129 // Returns full location with anchor (helper)
130 static wxString GetOpenedPageWithAnchor(wxHtmlWindow *win)
131 {
132 if(!win)
133 return wxEmptyString;
134
135 wxString an = win->GetOpenedAnchor();
136 wxString pg = win->GetOpenedPage();
137 if(!an.empty())
3755cfa6 138 {
630906de 139 pg << wxT("#") << an;
3755cfa6 140 }
630906de
VZ
141 return pg;
142 }
3755cfa6 143
630906de
VZ
144private:
145 wxHtmlHelpWindow *m_Window;
3755cfa6 146
c0c133e1 147 wxDECLARE_NO_COPY_CLASS(wxHtmlHelpHtmlWindow);
a1c3cdc4 148 DECLARE_EVENT_TABLE()
3755cfa6
JS
149};
150
a1c3cdc4 151BEGIN_EVENT_TABLE(wxHtmlHelpHtmlWindow, wxHtmlWindow)
630906de 152 EVT_HTML_LINK_CLICKED(wxID_ANY, wxHtmlHelpHtmlWindow::OnLink)
a1c3cdc4
VS
153END_EVENT_TABLE()
154
3755cfa6
JS
155
156//---------------------------------------------------------------------------
157// wxHtmlHelpWindow::m_mergedIndex
158//---------------------------------------------------------------------------
159
160WX_DEFINE_ARRAY_PTR(const wxHtmlHelpDataItem*, wxHtmlHelpDataItemPtrArray);
161
162struct wxHtmlHelpMergedIndexItem
163{
164 wxHtmlHelpMergedIndexItem *parent;
165 wxString name;
166 wxHtmlHelpDataItemPtrArray items;
167};
168
169WX_DECLARE_OBJARRAY(wxHtmlHelpMergedIndexItem, wxHtmlHelpMergedIndex);
170#include "wx/arrimpl.cpp"
171WX_DEFINE_OBJARRAY(wxHtmlHelpMergedIndex)
172
173void wxHtmlHelpWindow::UpdateMergedIndex()
174{
175 delete m_mergedIndex;
176 m_mergedIndex = new wxHtmlHelpMergedIndex;
177 wxHtmlHelpMergedIndex& merged = *m_mergedIndex;
178
179 const wxHtmlHelpDataItems& items = m_Data->GetIndexArray();
180 size_t len = items.size();
181
182 wxHtmlHelpMergedIndexItem *history[128] = {NULL};
183
184 for (size_t i = 0; i < len; i++)
185 {
186 const wxHtmlHelpDataItem& item = items[i];
9a83f860 187 wxASSERT_MSG( item.level < 128, wxT("nested index entries too deep") );
3755cfa6
JS
188
189 if (history[item.level] &&
190 history[item.level]->items[0]->name == item.name)
191 {
192 // same index entry as previous one, update list of items
193 history[item.level]->items.Add(&item);
194 }
195 else
196 {
197 // new index entry
198 wxHtmlHelpMergedIndexItem *mi = new wxHtmlHelpMergedIndexItem();
199 mi->name = item.GetIndentedName();
200 mi->items.Add(&item);
201 mi->parent = (item.level == 0) ? NULL : history[item.level - 1];
202 history[item.level] = mi;
203 merged.Add(mi);
204 }
205 }
206}
207
208//---------------------------------------------------------------------------
209// wxHtmlHelpWindow
210//---------------------------------------------------------------------------
211
3755cfa6
JS
212IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpWindow, wxWindow)
213
214BEGIN_EVENT_TABLE(wxHtmlHelpWindow, wxWindow)
215 EVT_TOOL_RANGE(wxID_HTML_PANEL, wxID_HTML_OPTIONS, wxHtmlHelpWindow::OnToolbar)
216 EVT_BUTTON(wxID_HTML_BOOKMARKSREMOVE, wxHtmlHelpWindow::OnToolbar)
217 EVT_BUTTON(wxID_HTML_BOOKMARKSADD, wxHtmlHelpWindow::OnToolbar)
218 EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL, wxHtmlHelpWindow::OnContentsSel)
219 EVT_LISTBOX(wxID_HTML_INDEXLIST, wxHtmlHelpWindow::OnIndexSel)
220 EVT_LISTBOX(wxID_HTML_SEARCHLIST, wxHtmlHelpWindow::OnSearchSel)
221 EVT_BUTTON(wxID_HTML_SEARCHBUTTON, wxHtmlHelpWindow::OnSearch)
222 EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT, wxHtmlHelpWindow::OnSearch)
223 EVT_BUTTON(wxID_HTML_INDEXBUTTON, wxHtmlHelpWindow::OnIndexFind)
224 EVT_TEXT_ENTER(wxID_HTML_INDEXTEXT, wxHtmlHelpWindow::OnIndexFind)
225 EVT_BUTTON(wxID_HTML_INDEXBUTTONALL, wxHtmlHelpWindow::OnIndexAll)
226 EVT_COMBOBOX(wxID_HTML_BOOKMARKSLIST, wxHtmlHelpWindow::OnBookmarksSel)
227 EVT_SIZE(wxHtmlHelpWindow::OnSize)
228END_EVENT_TABLE()
229
230wxHtmlHelpWindow::wxHtmlHelpWindow(wxWindow* parent, wxWindowID id,
231 const wxPoint& pos,
232 const wxSize& size,
233 int style, int helpStyle, wxHtmlHelpData* data)
234{
235 Init(data);
236 Create(parent, id, pos, size, style, helpStyle);
237}
238
239void wxHtmlHelpWindow::Init(wxHtmlHelpData* data)
240{
241 if (data)
242 {
243 m_Data = data;
244 m_DataCreated = false;
245 }
246 else
247 {
248 m_Data = new wxHtmlHelpData();
249 m_DataCreated = true;
250 }
251
252 m_ContentsPage = 0;
253 m_IndexPage = 0;
254 m_SearchPage = 0;
255
256 m_ContentsBox = NULL;
257 m_IndexList = NULL;
258 m_IndexButton = NULL;
259 m_IndexButtonAll = NULL;
260 m_IndexText = NULL;
261 m_SearchList = NULL;
262 m_SearchButton = NULL;
263 m_SearchText = NULL;
264 m_SearchChoice = NULL;
265 m_IndexCountInfo = NULL;
266 m_Splitter = NULL;
267 m_NavigPan = NULL;
268 m_NavigNotebook = NULL;
269 m_HtmlWin = NULL;
270 m_Bookmarks = NULL;
271 m_SearchCaseSensitive = NULL;
272 m_SearchWholeWords = NULL;
273
274 m_mergedIndex = NULL;
275
b4246849 276#if wxUSE_CONFIG
3755cfa6
JS
277 m_Config = NULL;
278 m_ConfigRoot = wxEmptyString;
b4246849 279#endif // wxUSE_CONFIG
3755cfa6
JS
280
281 m_Cfg.x = m_Cfg.y = wxDefaultCoord;
282 m_Cfg.w = 700;
283 m_Cfg.h = 480;
284 m_Cfg.sashpos = 240;
285 m_Cfg.navig_on = true;
286
287 m_NormalFonts = m_FixedFonts = NULL;
288 m_NormalFace = m_FixedFace = wxEmptyString;
289#ifdef __WXMSW__
290 m_FontSize = 10;
291#else
292 m_FontSize = 14;
293#endif
294
295#if wxUSE_PRINTING_ARCHITECTURE
296 m_Printer = NULL;
297#endif
298
299 m_PagesHash = NULL;
300 m_UpdateContents = true;
301 m_toolBar = NULL;
d3b9f782 302 m_helpController = NULL;
3755cfa6
JS
303}
304
305// Create: builds the GUI components.
306// with the style flag it's possible to toggle the toolbar, contents, index and search
307// controls.
308// m_HtmlWin will *always* be created, but it's important to realize that
309// m_ContentsBox, m_IndexList, m_SearchList, m_SearchButton, m_SearchText and
310// m_SearchButton may be NULL.
311// moreover, if no contents, index or searchpage is needed, m_Splitter and
312// m_NavigPan will be NULL too (with m_HtmlWin directly connected to the frame)
313
314bool wxHtmlHelpWindow::Create(wxWindow* parent, wxWindowID id,
315 const wxPoint& pos, const wxSize& size,
316 int style, int helpStyle)
317{
318 m_hfStyle = helpStyle;
319
b4246849 320#if wxUSE_CONFIG
3755cfa6
JS
321 // Do the config in two steps. We read the HtmlWindow customization after we
322 // create the window.
323 if (m_Config)
324 ReadCustomization(m_Config, m_ConfigRoot);
b4246849 325#endif // wxUSE_CONFIG
3755cfa6
JS
326
327 wxWindow::Create(parent, id, pos, size, style, wxT("wxHtmlHelp"));
328
329 SetHelpText(_("Displays help as you browse the books on the left."));
330
331 GetPosition(&m_Cfg.x, &m_Cfg.y);
332
333 int notebook_page = 0;
334
335 // The sizer for the whole top-level window.
336 wxSizer *topWindowSizer = new wxBoxSizer(wxVERTICAL);
337 SetSizer(topWindowSizer);
548b5377 338 SetAutoLayout(true);
3755cfa6
JS
339
340#if wxUSE_TOOLBAR
341 // toolbar?
342 if (helpStyle & (wxHF_TOOLBAR | wxHF_FLAT_TOOLBAR))
343 {
548b5377 344 wxToolBar *toolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
3755cfa6
JS
345 wxNO_BORDER | wxTB_HORIZONTAL |
346 wxTB_DOCKABLE | wxTB_NODIVIDER |
347 (helpStyle & wxHF_FLAT_TOOLBAR ? wxTB_FLAT : 0));
348 toolBar->SetMargins( 2, 2 );
4e0d4206 349 toolBar->SetToolBitmapSize( wxSize(22,22) );
3755cfa6
JS
350 AddToolbarButtons(toolBar, helpStyle);
351 toolBar->Realize();
352 topWindowSizer->Add(toolBar, 0, wxEXPAND);
353 m_toolBar = toolBar;
354 }
355#endif //wxUSE_TOOLBAR
356
357 wxSizer *navigSizer = NULL;
358
6f3f9b50
JS
359#ifdef __WXMSW__
360 wxBorder htmlWindowBorder = GetDefaultBorder();
361 if (htmlWindowBorder == wxBORDER_SUNKEN)
51cd3519 362 htmlWindowBorder = wxBORDER_SIMPLE;
6f3f9b50
JS
363#else
364 wxBorder htmlWindowBorder = wxBORDER_SIMPLE;
365#endif
366
3755cfa6
JS
367 if (helpStyle & (wxHF_CONTENTS | wxHF_INDEX | wxHF_SEARCH))
368 {
369 // traditional help controller; splitter window with html page on the
370 // right and a notebook containing various pages on the left
8e7da426
JS
371 long splitterStyle = wxSP_3D;
372 // Drawing moving sash can cause problems on wxMac
373#ifdef __WXMAC__
374 splitterStyle |= wxSP_LIVE_UPDATE;
375#endif
376 m_Splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, splitterStyle);
3755cfa6
JS
377
378 topWindowSizer->Add(m_Splitter, 1, wxEXPAND);
379
6f3f9b50 380 m_HtmlWin = new wxHtmlHelpHtmlWindow(this, m_Splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_DEFAULT_STYLE|htmlWindowBorder);
3755cfa6
JS
381 m_NavigPan = new wxPanel(m_Splitter, wxID_ANY);
382 m_NavigNotebook = new wxNotebook(m_NavigPan, wxID_HTML_NOTEBOOK,
383 wxDefaultPosition, wxDefaultSize);
1f5cd20e
JS
384#ifdef __WXMAC__
385 m_NavigNotebook->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
386#endif
3755cfa6
JS
387
388 navigSizer = new wxBoxSizer(wxVERTICAL);
389 navigSizer->Add(m_NavigNotebook, 1, wxEXPAND);
390
391 m_NavigPan->SetSizer(navigSizer);
392 }
393 else
394 {
395 // only html window, no notebook with index,contents etc
6f3f9b50 396 m_HtmlWin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_DEFAULT_STYLE|htmlWindowBorder);
3755cfa6
JS
397 topWindowSizer->Add(m_HtmlWin, 1, wxEXPAND);
398 }
399
b4246849 400#if wxUSE_CONFIG
3755cfa6
JS
401 if ( m_Config )
402 m_HtmlWin->ReadCustomization(m_Config, m_ConfigRoot);
b4246849 403#endif // wxUSE_CONFIG
3755cfa6
JS
404
405 // contents tree panel?
406 if ( helpStyle & wxHF_CONTENTS )
407 {
408 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
1f5cd20e
JS
409#ifdef __WXMAC__
410 dummy->SetWindowVariant(wxWINDOW_VARIANT_NORMAL);
411#endif
3755cfa6
JS
412 wxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
413
414 topsizer->Add(0, 10);
415
416 dummy->SetSizer(topsizer);
417
418 if ( helpStyle & wxHF_BOOKMARKS )
419 {
420 m_Bookmarks = new wxComboBox(dummy, wxID_HTML_BOOKMARKSLIST,
421 wxEmptyString,
422 wxDefaultPosition, wxDefaultSize,
423 0, NULL, wxCB_READONLY | wxCB_SORT);
424 m_Bookmarks->Append(_("(bookmarks)"));
425 for (unsigned i = 0; i < m_BookmarksNames.GetCount(); i++)
426 m_Bookmarks->Append(m_BookmarksNames[i]);
427 m_Bookmarks->SetSelection(0);
428
429 wxBitmapButton *bmpbt1, *bmpbt2;
430 bmpbt1 = new wxBitmapButton(dummy, wxID_HTML_BOOKMARKSADD,
431 wxArtProvider::GetBitmap(wxART_ADD_BOOKMARK,
432 wxART_BUTTON));
433 bmpbt2 = new wxBitmapButton(dummy, wxID_HTML_BOOKMARKSREMOVE,
434 wxArtProvider::GetBitmap(wxART_DEL_BOOKMARK,
435 wxART_BUTTON));
436#if wxUSE_TOOLTIPS
437 bmpbt1->SetToolTip(_("Add current page to bookmarks"));
438 bmpbt2->SetToolTip(_("Remove current page from bookmarks"));
439#endif // wxUSE_TOOLTIPS
440
441 wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
442
443 sizer->Add(m_Bookmarks, 1, wxALIGN_CENTRE_VERTICAL | wxRIGHT, 5);
444 sizer->Add(bmpbt1, 0, wxALIGN_CENTRE_VERTICAL | wxRIGHT, 2);
445 sizer->Add(bmpbt2, 0, wxALIGN_CENTRE_VERTICAL, 0);
446
447 topsizer->Add(sizer, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 10);
448 }
449
450 m_ContentsBox = new wxTreeCtrl(dummy, wxID_HTML_TREECTRL,
451 wxDefaultPosition, wxDefaultSize,
4e0d4206 452#if defined(__WXGTK20__) || defined(__WXMAC__)
3755cfa6
JS
453 wxSUNKEN_BORDER |
454 wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT |
455 wxTR_NO_LINES
456#else
457 wxSUNKEN_BORDER |
458 wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT |
459 wxTR_LINES_AT_ROOT
460#endif
461 );
462
51cd3519
VZ
463 wxImageList *ContentsImageList = new wxImageList(16, 16);
464 ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_BOOK,
465 wxART_HELP_BROWSER,
466 wxSize(16, 16)));
467 ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER,
468 wxART_HELP_BROWSER,
469 wxSize(16, 16)));
470 ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE,
471 wxART_HELP_BROWSER,
472 wxSize(16, 16)));
473
3755cfa6
JS
474 m_ContentsBox->AssignImageList(ContentsImageList);
475
476 topsizer->Add(m_ContentsBox, 1,
477 wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,
478 2);
479
480 m_NavigNotebook->AddPage(dummy, _("Contents"));
481 m_ContentsPage = notebook_page++;
482 }
483
484 // index listbox panel?
485 if ( helpStyle & wxHF_INDEX )
486 {
487 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
1f5cd20e
JS
488#ifdef __WXMAC__
489 dummy->SetWindowVariant(wxWINDOW_VARIANT_NORMAL);
490#endif
3755cfa6
JS
491 wxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
492
493 dummy->SetSizer(topsizer);
494
495 m_IndexText = new wxTextCtrl(dummy, wxID_HTML_INDEXTEXT, wxEmptyString,
496 wxDefaultPosition, wxDefaultSize,
497 wxTE_PROCESS_ENTER);
498 m_IndexButton = new wxButton(dummy, wxID_HTML_INDEXBUTTON, _("Find"));
499 m_IndexButtonAll = new wxButton(dummy, wxID_HTML_INDEXBUTTONALL,
500 _("Show all"));
501 m_IndexCountInfo = new wxStaticText(dummy, wxID_HTML_COUNTINFO,
502 wxEmptyString, wxDefaultPosition,
503 wxDefaultSize,
504 wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
505 m_IndexList = new wxListBox(dummy, wxID_HTML_INDEXLIST,
506 wxDefaultPosition, wxDefaultSize,
507 0, NULL, wxLB_SINGLE);
508
509#if wxUSE_TOOLTIPS
510 m_IndexButton->SetToolTip(_("Display all index items that contain given substring. Search is case insensitive."));
511 m_IndexButtonAll->SetToolTip(_("Show all items in index"));
512#endif //wxUSE_TOOLTIPS
513
514 topsizer->Add(m_IndexText, 0, wxEXPAND | wxALL, 10);
515 wxSizer *btsizer = new wxBoxSizer(wxHORIZONTAL);
516 btsizer->Add(m_IndexButton, 0, wxRIGHT, 2);
517 btsizer->Add(m_IndexButtonAll);
518 topsizer->Add(btsizer, 0,
519 wxALIGN_RIGHT | wxLEFT | wxRIGHT | wxBOTTOM, 10);
520 topsizer->Add(m_IndexCountInfo, 0, wxEXPAND | wxLEFT | wxRIGHT, 2);
521 topsizer->Add(m_IndexList, 1, wxEXPAND | wxALL, 2);
522
523 m_NavigNotebook->AddPage(dummy, _("Index"));
524 m_IndexPage = notebook_page++;
525 }
526
527 // search list panel?
528 if ( helpStyle & wxHF_SEARCH )
529 {
530 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
1f5cd20e
JS
531#ifdef __WXMAC__
532 dummy->SetWindowVariant(wxWINDOW_VARIANT_NORMAL);
533#endif
3755cfa6
JS
534 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
535
536 dummy->SetSizer(sizer);
537
538 m_SearchText = new wxTextCtrl(dummy, wxID_HTML_SEARCHTEXT,
539 wxEmptyString,
540 wxDefaultPosition, wxDefaultSize,
541 wxTE_PROCESS_ENTER);
542 m_SearchChoice = new wxChoice(dummy, wxID_HTML_SEARCHCHOICE,
543 wxDefaultPosition, wxSize(125,wxDefaultCoord));
544 m_SearchCaseSensitive = new wxCheckBox(dummy, wxID_ANY, _("Case sensitive"));
545 m_SearchWholeWords = new wxCheckBox(dummy, wxID_ANY, _("Whole words only"));
546 m_SearchButton = new wxButton(dummy, wxID_HTML_SEARCHBUTTON, _("Search"));
547#if wxUSE_TOOLTIPS
7929902d 548 m_SearchButton->SetToolTip(_("Search contents of help book(s) for all occurrences of the text you typed above"));
3755cfa6
JS
549#endif //wxUSE_TOOLTIPS
550 m_SearchList = new wxListBox(dummy, wxID_HTML_SEARCHLIST,
551 wxDefaultPosition, wxDefaultSize,
552 0, NULL, wxLB_SINGLE);
553
554 sizer->Add(m_SearchText, 0, wxEXPAND | wxALL, 10);
555 sizer->Add(m_SearchChoice, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
556 sizer->Add(m_SearchCaseSensitive, 0, wxLEFT | wxRIGHT, 10);
557 sizer->Add(m_SearchWholeWords, 0, wxLEFT | wxRIGHT, 10);
558 sizer->Add(m_SearchButton, 0, wxALL | wxALIGN_RIGHT, 8);
559 sizer->Add(m_SearchList, 1, wxALL | wxEXPAND, 2);
560
561 m_NavigNotebook->AddPage(dummy, _("Search"));
562 m_SearchPage = notebook_page;
563 }
564
565 m_HtmlWin->Show();
566
567 RefreshLists();
568
569 if ( navigSizer )
570 {
571 navigSizer->SetSizeHints(m_NavigPan);
572 m_NavigPan->Layout();
573 }
574
575 // showtime
576 if ( m_NavigPan && m_Splitter )
577 {
6738c472
JS
578 // The panel will have its own min size which the splitter
579 // should respect
580 //if (m_NavigPan)
581 // m_Splitter->SetMinimumPaneSize(m_NavigPan->GetBestSize().x);
582 //else
583 m_Splitter->SetMinimumPaneSize(20);
3755cfa6
JS
584
585 if ( m_Cfg.navig_on )
586 {
587 m_NavigPan->Show();
588 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
589 }
590 else
591 {
592 m_NavigPan->Show(false);
593 m_Splitter->Initialize(m_HtmlWin);
594 }
595 }
596
597 // Reduce flicker by updating the splitter pane sizes before the
598 // frame is shown
599 wxSizeEvent sizeEvent(GetSize(), GetId());
004867db 600 GetEventHandler()->ProcessEvent(sizeEvent);
3755cfa6
JS
601
602 if (m_Splitter)
603 m_Splitter->UpdateSize();
604
605 return true;
606}
607
608wxHtmlHelpWindow::~wxHtmlHelpWindow()
609{
664d1729
VS
610 if ( m_helpController )
611 m_helpController->SetHelpWindow(NULL);
612
3755cfa6
JS
613 delete m_mergedIndex;
614
615 // PopEventHandler(); // wxhtmlhelpcontroller (not any more!)
616 if (m_DataCreated)
617 delete m_Data;
618 if (m_NormalFonts) delete m_NormalFonts;
619 if (m_FixedFonts) delete m_FixedFonts;
620 if (m_PagesHash)
621 {
622 WX_CLEAR_HASH_TABLE(*m_PagesHash);
623 delete m_PagesHash;
624 }
625#if wxUSE_PRINTING_ARCHITECTURE
626 if (m_Printer) delete m_Printer;
627#endif
628}
629
630void wxHtmlHelpWindow::SetController(wxHtmlHelpController* controller)
631{
632 if (m_DataCreated)
633 delete m_Data;
634 m_helpController = controller;
635 m_Data = controller->GetHelpData();
636 m_DataCreated = false;
637}
638
639#if wxUSE_TOOLBAR
640void wxHtmlHelpWindow::AddToolbarButtons(wxToolBar *toolBar, int style)
641{
642 wxBitmap wpanelBitmap =
643 wxArtProvider::GetBitmap(wxART_HELP_SIDE_PANEL, wxART_TOOLBAR);
644 wxBitmap wbackBitmap =
645 wxArtProvider::GetBitmap(wxART_GO_BACK, wxART_TOOLBAR);
646 wxBitmap wforwardBitmap =
647 wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_TOOLBAR);
648 wxBitmap wupnodeBitmap =
649 wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_TOOLBAR);
650 wxBitmap wupBitmap =
651 wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR);
652 wxBitmap wdownBitmap =
653 wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR);
654 wxBitmap wopenBitmap =
655 wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR);
656 wxBitmap wprintBitmap =
657 wxArtProvider::GetBitmap(wxART_PRINT, wxART_TOOLBAR);
658 wxBitmap woptionsBitmap =
659 wxArtProvider::GetBitmap(wxART_HELP_SETTINGS, wxART_TOOLBAR);
660
661 wxASSERT_MSG( (wpanelBitmap.Ok() && wbackBitmap.Ok() &&
662 wforwardBitmap.Ok() && wupnodeBitmap.Ok() &&
663 wupBitmap.Ok() && wdownBitmap.Ok() &&
664 wopenBitmap.Ok() && wprintBitmap.Ok() &&
665 woptionsBitmap.Ok()),
666 wxT("One or more HTML help frame toolbar bitmap could not be loaded.")) ;
667
668
bbe28fbb 669 toolBar->AddTool(wxID_HTML_PANEL, wxEmptyString, wpanelBitmap, _("Show/hide navigation panel"));
3755cfa6 670 toolBar->AddSeparator();
bbe28fbb
PC
671 toolBar->AddTool(wxID_HTML_BACK, wxEmptyString, wbackBitmap, _("Go back"));
672 toolBar->AddTool(wxID_HTML_FORWARD, wxEmptyString, wforwardBitmap, _("Go forward"));
3755cfa6 673 toolBar->AddSeparator();
bbe28fbb
PC
674 toolBar->AddTool(wxID_HTML_UPNODE, wxEmptyString, wupnodeBitmap, _("Go one level up in document hierarchy"));
675 toolBar->AddTool(wxID_HTML_UP, wxEmptyString, wupBitmap, _("Previous page"));
676 toolBar->AddTool(wxID_HTML_DOWN, wxEmptyString, wdownBitmap, _("Next page"));
3755cfa6
JS
677
678 if ((style & wxHF_PRINT) || (style & wxHF_OPEN_FILES))
679 toolBar->AddSeparator();
680
681 if (style & wxHF_OPEN_FILES)
bbe28fbb 682 toolBar->AddTool(wxID_HTML_OPENFILE, wxEmptyString, wopenBitmap, _("Open HTML document"));
3755cfa6
JS
683
684#if wxUSE_PRINTING_ARCHITECTURE
685 if (style & wxHF_PRINT)
bbe28fbb 686 toolBar->AddTool(wxID_HTML_PRINT, wxEmptyString, wprintBitmap, _("Print this page"));
3755cfa6
JS
687#endif
688
689 toolBar->AddSeparator();
bbe28fbb 690 toolBar->AddTool(wxID_HTML_OPTIONS, wxEmptyString, woptionsBitmap, _("Display options dialog"));
3755cfa6
JS
691
692 // Allow application to add custom buttons
693 wxHtmlHelpFrame* parentFrame = wxDynamicCast(GetParent(), wxHtmlHelpFrame);
694 wxHtmlHelpDialog* parentDialog = wxDynamicCast(GetParent(), wxHtmlHelpDialog);
695 if (parentFrame)
696 parentFrame->AddToolbarButtons(toolBar, style);
697 if (parentDialog)
698 parentDialog->AddToolbarButtons(toolBar, style);
699}
700#endif //wxUSE_TOOLBAR
701
702
703bool wxHtmlHelpWindow::Display(const wxString& x)
704{
705 wxString url = m_Data->FindPageByName(x);
706 if (!url.empty())
707 {
708 m_HtmlWin->LoadPage(url);
709 NotifyPageChanged();
710 return true;
711 }
712
713 return false;
714}
715
716bool wxHtmlHelpWindow::Display(const int id)
717{
718 wxString url = m_Data->FindPageById(id);
719 if (!url.empty())
720 {
721 m_HtmlWin->LoadPage(url);
722 NotifyPageChanged();
723 return true;
724 }
725
726 return false;
727}
728
729bool wxHtmlHelpWindow::DisplayContents()
730{
731 if (! m_ContentsBox)
732 return false;
733
734 if (!m_Splitter->IsSplit())
735 {
736 m_NavigPan->Show();
737 m_HtmlWin->Show();
738 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
739 m_Cfg.navig_on = true;
740 }
741
742 m_NavigNotebook->SetSelection(m_ContentsPage);
743
744 if (m_Data->GetBookRecArray().GetCount() > 0)
745 {
746 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
747 if (!book.GetStart().empty())
748 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
749 }
750
751 return true;
752}
753
754bool wxHtmlHelpWindow::DisplayIndex()
755{
756 if (! m_IndexList)
757 return false;
758
759 if (!m_Splitter->IsSplit())
760 {
761 m_NavigPan->Show();
762 m_HtmlWin->Show();
763 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
764 }
765
766 m_NavigNotebook->SetSelection(m_IndexPage);
767
768 if (m_Data->GetBookRecArray().GetCount() > 0)
769 {
770 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
771 if (!book.GetStart().empty())
772 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
773 }
774
775 return true;
776}
777
778void wxHtmlHelpWindow::DisplayIndexItem(const wxHtmlHelpMergedIndexItem *it)
779{
780 if (it->items.size() == 1)
781 {
782 if (!it->items[0]->page.empty())
783 {
784 m_HtmlWin->LoadPage(it->items[0]->GetFullPath());
785 NotifyPageChanged();
786 }
787 }
788 else
789 {
790 wxBusyCursor busy_cursor;
791
792 // more pages associated with this index item -- let the user choose
793 // which one she/he wants from a list:
794 wxArrayString arr;
795 size_t len = it->items.size();
796 for (size_t i = 0; i < len; i++)
797 {
798 wxString page = it->items[i]->page;
799 // try to find page's title in contents:
800 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
801 size_t clen = contents.size();
802 for (size_t j = 0; j < clen; j++)
803 {
804 if (contents[j].page == page)
805 {
806 page = contents[j].name;
807 break;
808 }
809 }
810 arr.push_back(page);
811 }
812
813 wxSingleChoiceDialog dlg(this,
814 _("Please choose the page to display:"),
815 _("Help Topics"),
816 arr, NULL, wxCHOICEDLG_STYLE & ~wxCENTRE);
817 if (dlg.ShowModal() == wxID_OK)
818 {
819 m_HtmlWin->LoadPage(it->items[dlg.GetSelection()]->GetFullPath());
820 NotifyPageChanged();
821 }
822 }
823}
824
825bool wxHtmlHelpWindow::KeywordSearch(const wxString& keyword,
826 wxHelpSearchMode mode)
827{
ed8c374d
VZ
828 wxCHECK_MSG( !keyword.empty(), false, "must have a non empty keyword" );
829
3755cfa6
JS
830 if (mode == wxHELP_SEARCH_ALL)
831 {
832 if ( !(m_SearchList &&
833 m_SearchButton && m_SearchText && m_SearchChoice) )
834 return false;
835 }
836 else if (mode == wxHELP_SEARCH_INDEX)
837 {
838 if ( !(m_IndexList &&
839 m_IndexButton && m_IndexButtonAll && m_IndexText) )
840 return false;
841 }
842
843 int foundcnt = 0;
844 wxString foundstr;
845 wxString book = wxEmptyString;
846
847 if (!m_Splitter->IsSplit())
848 {
849 m_NavigPan->Show();
850 m_HtmlWin->Show();
851 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
852 }
853
854 if (mode == wxHELP_SEARCH_ALL)
855 {
856 m_NavigNotebook->SetSelection(m_SearchPage);
857 m_SearchList->Clear();
858 m_SearchText->SetValue(keyword);
859 m_SearchButton->Disable();
860
861 if (m_SearchChoice->GetSelection() != 0)
862 book = m_SearchChoice->GetStringSelection();
863
864 wxHtmlSearchStatus status(m_Data, keyword,
865 m_SearchCaseSensitive->GetValue(),
866 m_SearchWholeWords->GetValue(),
867 book);
868
869#if wxUSE_PROGRESSDLG
870 wxProgressDialog progress(_("Searching..."),
871 _("No matching page found yet"),
872 status.GetMaxIndex(), this,
873 wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
874#endif
875
876 int curi;
877 while (status.IsActive())
878 {
879 curi = status.GetCurIndex();
880 if (curi % 32 == 0
881#if wxUSE_PROGRESSDLG
882 && !progress.Update(curi)
883#endif
884 )
885 break;
886 if (status.Search())
887 {
888 foundstr.Printf(_("Found %i matches"), ++foundcnt);
889#if wxUSE_PROGRESSDLG
890 progress.Update(status.GetCurIndex(), foundstr);
891#endif
892 m_SearchList->Append(status.GetName(), (void*)status.GetCurItem());
893 }
894 }
895
896 m_SearchButton->Enable();
548b5377 897 m_SearchText->SetSelection(0, keyword.length());
3755cfa6
JS
898 m_SearchText->SetFocus();
899 }
900 else if (mode == wxHELP_SEARCH_INDEX)
901 {
902 m_NavigNotebook->SetSelection(m_IndexPage);
903 m_IndexList->Clear();
904 m_IndexButton->Disable();
905 m_IndexButtonAll->Disable();
906 m_IndexText->SetValue(keyword);
907
548b5377 908 DoIndexFind();
3755cfa6
JS
909 m_IndexButton->Enable();
910 m_IndexButtonAll->Enable();
911 foundcnt = m_IndexList->GetCount();
912 }
913
914 if (foundcnt)
915 {
916 switch ( mode )
917 {
918 default:
9a83f860 919 wxFAIL_MSG( wxT("unknown help search mode") );
3755cfa6
JS
920 // fall back
921
922 case wxHELP_SEARCH_ALL:
923 {
924 wxHtmlHelpDataItem *it =
925 (wxHtmlHelpDataItem*) m_SearchList->GetClientData(0);
926 if (it)
927 {
928 m_HtmlWin->LoadPage(it->GetFullPath());
929 NotifyPageChanged();
930 }
931 break;
932 }
933
934 case wxHELP_SEARCH_INDEX:
935 {
936 wxHtmlHelpMergedIndexItem* it =
937 (wxHtmlHelpMergedIndexItem*) m_IndexList->GetClientData(0);
938 if (it)
939 DisplayIndexItem(it);
940 break;
941 }
942 }
943
944 }
945
946 return foundcnt > 0;
947}
948
949void wxHtmlHelpWindow::CreateContents()
950{
951 if (! m_ContentsBox)
952 return ;
953
954 if (m_PagesHash)
955 {
956 WX_CLEAR_HASH_TABLE(*m_PagesHash);
957 delete m_PagesHash;
958 }
959
960 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
961
962 size_t cnt = contents.size();
963
964 m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * cnt);
965
966 const int MAX_ROOTS = 64;
967 wxTreeItemId roots[MAX_ROOTS];
968 // VS: this array holds information about whether we've set item icon at
969 // given level. This is necessary because m_Data has a flat structure
970 // and there's no way of recognizing if some item has subitems or not.
971 // We set the icon later: when we find an item with level=n, we know
972 // that the last item with level=n-1 was afolder with subitems, so we
973 // set its icon accordingly
974 bool imaged[MAX_ROOTS];
975 m_ContentsBox->DeleteAllItems();
976
977 roots[0] = m_ContentsBox->AddRoot(_("(Help)"));
978 imaged[0] = true;
979
980 for (size_t i = 0; i < cnt; i++)
981 {
982 wxHtmlHelpDataItem *it = &contents[i];
983 // Handle books:
984 if (it->level == 0)
985 {
986 if (m_hfStyle & wxHF_MERGE_BOOKS)
987 // VS: we don't want book nodes, books' content should
988 // appear under tree's root. This line will create a "fake"
989 // record about book node so that the rest of this look
990 // will believe there really _is_ a book node and will
991 // behave correctly.
992 roots[1] = roots[0];
993 else
994 {
995 roots[1] = m_ContentsBox->AppendItem(roots[0],
996 it->name, IMG_Book, -1,
997 new wxHtmlHelpTreeItemData(i));
998 m_ContentsBox->SetItemBold(roots[1], true);
999 }
1000 imaged[1] = true;
1001 }
1002 // ...and their contents:
1003 else
1004 {
1005 roots[it->level + 1] = m_ContentsBox->AppendItem(
1006 roots[it->level], it->name, IMG_Page,
1007 -1, new wxHtmlHelpTreeItemData(i));
1008 imaged[it->level + 1] = false;
1009 }
1010
1011 m_PagesHash->Put(it->GetFullPath(),
1012 new wxHtmlHelpHashData(i, roots[it->level + 1]));
1013
1014 // Set the icon for the node one level up in the hierarchy,
1015 // unless already done (see comment above imaged[] declaration)
1016 if (!imaged[it->level])
1017 {
1018 int image = IMG_Folder;
1019 if (m_hfStyle & wxHF_ICONS_BOOK)
1020 image = IMG_Book;
1021 else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER)
1022 image = (it->level == 1) ? IMG_Book : IMG_Folder;
1023 m_ContentsBox->SetItemImage(roots[it->level], image);
1024 m_ContentsBox->SetItemImage(roots[it->level], image,
1025 wxTreeItemIcon_Selected);
1026 imaged[it->level] = true;
1027 }
1028 }
1029}
1030
1031void wxHtmlHelpWindow::CreateIndex()
1032{
1033 if (! m_IndexList)
1034 return ;
1035
1036 m_IndexList->Clear();
1037
1038 size_t cnt = m_mergedIndex->size();
1039
1040 wxString cnttext;
1041 if (cnt > INDEX_IS_SMALL)
1042 cnttext.Printf(_("%i of %i"), 0, cnt);
1043 else
1044 cnttext.Printf(_("%i of %i"), cnt, cnt);
1045 m_IndexCountInfo->SetLabel(cnttext);
1046 if (cnt > INDEX_IS_SMALL)
1047 return;
1048
1049 for (size_t i = 0; i < cnt; i++)
1050 m_IndexList->Append((*m_mergedIndex)[i].name,
1051 (char*)(&(*m_mergedIndex)[i]));
1052}
1053
1054void wxHtmlHelpWindow::CreateSearch()
1055{
1056 if (! (m_SearchList && m_SearchChoice))
1057 return ;
1058 m_SearchList->Clear();
1059 m_SearchChoice->Clear();
1060 m_SearchChoice->Append(_("Search in all books"));
1061 const wxHtmlBookRecArray& bookrec = m_Data->GetBookRecArray();
1062 int i, cnt = bookrec.GetCount();
1063 for (i = 0; i < cnt; i++)
1064 m_SearchChoice->Append(bookrec[i].GetTitle());
1065 m_SearchChoice->SetSelection(0);
1066}
1067
1068void wxHtmlHelpWindow::RefreshLists()
1069{
1070 // Update m_mergedIndex:
1071 UpdateMergedIndex();
1072 // Update the controls
1073 CreateContents();
1074 CreateIndex();
1075 CreateSearch();
1076}
1077
b4246849 1078#if wxUSE_CONFIG
3755cfa6
JS
1079void wxHtmlHelpWindow::ReadCustomization(wxConfigBase *cfg, const wxString& path)
1080{
1081 wxString oldpath;
1082 wxString tmp;
1083
1084 if (path != wxEmptyString)
1085 {
1086 oldpath = cfg->GetPath();
9a83f860 1087 cfg->SetPath(wxT("/") + path);
3755cfa6
JS
1088 }
1089
1090 m_Cfg.navig_on = cfg->Read(wxT("hcNavigPanel"), m_Cfg.navig_on) != 0;
1091 m_Cfg.sashpos = cfg->Read(wxT("hcSashPos"), m_Cfg.sashpos);
1092 m_Cfg.x = cfg->Read(wxT("hcX"), m_Cfg.x);
1093 m_Cfg.y = cfg->Read(wxT("hcY"), m_Cfg.y);
1094 m_Cfg.w = cfg->Read(wxT("hcW"), m_Cfg.w);
1095 m_Cfg.h = cfg->Read(wxT("hcH"), m_Cfg.h);
1096
1097 m_FixedFace = cfg->Read(wxT("hcFixedFace"), m_FixedFace);
1098 m_NormalFace = cfg->Read(wxT("hcNormalFace"), m_NormalFace);
1099 m_FontSize = cfg->Read(wxT("hcBaseFontSize"), m_FontSize);
1100
1101 {
1102 int i;
1103 int cnt;
1104 wxString val, s;
1105
1106 cnt = cfg->Read(wxT("hcBookmarksCnt"), 0L);
1107 if (cnt != 0)
1108 {
1109 m_BookmarksNames.Clear();
1110 m_BookmarksPages.Clear();
1111 if (m_Bookmarks)
1112 {
1113 m_Bookmarks->Clear();
1114 m_Bookmarks->Append(_("(bookmarks)"));
1115 }
1116
1117 for (i = 0; i < cnt; i++)
1118 {
1119 val.Printf(wxT("hcBookmark_%i"), i);
1120 s = cfg->Read(val);
1121 m_BookmarksNames.Add(s);
1122 if (m_Bookmarks) m_Bookmarks->Append(s);
1123 val.Printf(wxT("hcBookmark_%i_url"), i);
1124 s = cfg->Read(val);
1125 m_BookmarksPages.Add(s);
1126 }
1127 }
1128 }
1129
1130 if (m_HtmlWin)
1131 m_HtmlWin->ReadCustomization(cfg);
1132
1133 if (path != wxEmptyString)
1134 cfg->SetPath(oldpath);
1135}
1136
1137void wxHtmlHelpWindow::WriteCustomization(wxConfigBase *cfg, const wxString& path)
1138{
1139 wxString oldpath;
1140 wxString tmp;
1141
1142 if (path != wxEmptyString)
1143 {
1144 oldpath = cfg->GetPath();
9a83f860 1145 cfg->SetPath(wxT("/") + path);
3755cfa6
JS
1146 }
1147
1148 cfg->Write(wxT("hcNavigPanel"), m_Cfg.navig_on);
1149 cfg->Write(wxT("hcSashPos"), (long)m_Cfg.sashpos);
1150
1151 // Don't write if iconized as this would make the window
1152 // disappear next time it is shown!
1153 cfg->Write(wxT("hcX"), (long)m_Cfg.x);
1154 cfg->Write(wxT("hcY"), (long)m_Cfg.y);
1155 cfg->Write(wxT("hcW"), (long)m_Cfg.w);
1156 cfg->Write(wxT("hcH"), (long)m_Cfg.h);
1157
1158 cfg->Write(wxT("hcFixedFace"), m_FixedFace);
1159 cfg->Write(wxT("hcNormalFace"), m_NormalFace);
1160 cfg->Write(wxT("hcBaseFontSize"), (long)m_FontSize);
1161
1162 if (m_Bookmarks)
1163 {
1164 int i;
1165 int cnt = m_BookmarksNames.GetCount();
1166 wxString val;
1167
1168 cfg->Write(wxT("hcBookmarksCnt"), (long)cnt);
1169 for (i = 0; i < cnt; i++)
1170 {
1171 val.Printf(wxT("hcBookmark_%i"), i);
1172 cfg->Write(val, m_BookmarksNames[i]);
1173 val.Printf(wxT("hcBookmark_%i_url"), i);
1174 cfg->Write(val, m_BookmarksPages[i]);
1175 }
1176 }
1177
1178 if (m_HtmlWin)
1179 m_HtmlWin->WriteCustomization(cfg);
1180
1181 if (path != wxEmptyString)
1182 cfg->SetPath(oldpath);
1183}
b4246849 1184#endif // wxUSE_CONFIG
3755cfa6
JS
1185
1186static void SetFontsToHtmlWin(wxHtmlWindow *win, const wxString& scalf, const wxString& fixf, int size)
1187{
1188 int f_sizes[7];
1189 f_sizes[0] = int(size * 0.6);
1190 f_sizes[1] = int(size * 0.8);
1191 f_sizes[2] = size;
1192 f_sizes[3] = int(size * 1.2);
1193 f_sizes[4] = int(size * 1.4);
1194 f_sizes[5] = int(size * 1.6);
1195 f_sizes[6] = int(size * 1.8);
1196
1197 win->SetFonts(scalf, fixf, f_sizes);
1198}
1199
1200class wxHtmlHelpWindowOptionsDialog : public wxDialog
1201{
1202public:
1203 wxComboBox *NormalFont, *FixedFont;
1204 wxSpinCtrl *FontSize;
1205 wxHtmlWindow *TestWin;
1206
1207 wxHtmlHelpWindowOptionsDialog(wxWindow *parent)
1208 : wxDialog(parent, wxID_ANY, wxString(_("Help Browser Options")))
1209 {
1210 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
1211 wxFlexGridSizer *sizer = new wxFlexGridSizer(2, 3, 2, 5);
1212
1213 sizer->Add(new wxStaticText(this, wxID_ANY, _("Normal font:")));
1214 sizer->Add(new wxStaticText(this, wxID_ANY, _("Fixed font:")));
1215 sizer->Add(new wxStaticText(this, wxID_ANY, _("Font size:")));
1216
1217 sizer->Add(NormalFont = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1218 wxSize(200, wxDefaultCoord),
1219 0, NULL, wxCB_DROPDOWN | wxCB_READONLY));
1220
1221 sizer->Add(FixedFont = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1222 wxSize(200, wxDefaultCoord),
1223 0, NULL, wxCB_DROPDOWN | wxCB_READONLY));
1224
50415ad7 1225 sizer->Add(FontSize = new wxSpinCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
9a83f860 1226 wxDefaultSize, wxSP_ARROW_KEYS, 2, 100, 2, wxT("wxSpinCtrl")));
3755cfa6
JS
1227
1228 topsizer->Add(sizer, 0, wxLEFT|wxRIGHT|wxTOP, 10);
1229
1230 topsizer->Add(new wxStaticText(this, wxID_ANY, _("Preview:")),
1231 0, wxLEFT | wxTOP, 10);
6e47d216
JS
1232
1233 topsizer->AddSpacer(5);
1234
3755cfa6 1235 topsizer->Add(TestWin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxSize(20, 150),
6e47d216
JS
1236 wxHW_SCROLLBAR_AUTO|wxBORDER_THEME),
1237 1, wxEXPAND | wxLEFT | wxRIGHT, 10);
3755cfa6
JS
1238
1239 wxBoxSizer *sizer2 = new wxBoxSizer(wxHORIZONTAL);
1240 wxButton *ok;
1241 sizer2->Add(ok = new wxButton(this, wxID_OK), 0, wxALL, 10);
1242 ok->SetDefault();
1243 sizer2->Add(new wxButton(this, wxID_CANCEL), 0, wxALL, 10);
1244 topsizer->Add(sizer2, 0, wxALIGN_RIGHT);
1245
1246 SetSizer(topsizer);
1247 topsizer->Fit(this);
1248 Centre(wxBOTH);
1249 }
1250
1251
1252 void UpdateTestWin()
1253 {
1254 wxBusyCursor bcur;
1255 SetFontsToHtmlWin(TestWin,
1256 NormalFont->GetStringSelection(),
1257 FixedFont->GetStringSelection(),
1258 FontSize->GetValue());
1259
1260 wxString content(_("font size"));
1261
9a83f860
VZ
1262 content = wxT("<font size=-2>") + content + wxT(" -2</font><br>")
1263 wxT("<font size=-1>") + content + wxT(" -1</font><br>")
1264 wxT("<font size=+0>") + content + wxT(" +0</font><br>")
1265 wxT("<font size=+1>") + content + wxT(" +1</font><br>")
1266 wxT("<font size=+2>") + content + wxT(" +2</font><br>")
1267 wxT("<font size=+3>") + content + wxT(" +3</font><br>")
1268 wxT("<font size=+4>") + content + wxT(" +4</font><br>") ;
3755cfa6 1269
9a83f860 1270 content = wxString( wxT("<html><body><table><tr><td>") ) +
3755cfa6
JS
1271 _("Normal face<br>and <u>underlined</u>. ") +
1272 _("<i>Italic face.</i> ") +
1273 _("<b>Bold face.</b> ") +
1274 _("<b><i>Bold italic face.</i></b><br>") +
1275 content +
9a83f860 1276 wxString( wxT("</td><td><tt>") ) +
3755cfa6
JS
1277 _("Fixed size face.<br> <b>bold</b> <i>italic</i> ") +
1278 _("<b><i>bold italic <u>underlined</u></i></b><br>") +
1279 content +
9a83f860 1280 wxT("</tt></td></tr></table></body></html>");
3755cfa6
JS
1281
1282 TestWin->SetPage( content );
1283 }
1284
1285 void OnUpdate(wxCommandEvent& WXUNUSED(event))
1286 {
1287 UpdateTestWin();
1288 }
1289 void OnUpdateSpin(wxSpinEvent& WXUNUSED(event))
1290 {
1291 UpdateTestWin();
1292 }
1293
1294 DECLARE_EVENT_TABLE()
c0c133e1 1295 wxDECLARE_NO_COPY_CLASS(wxHtmlHelpWindowOptionsDialog);
3755cfa6
JS
1296};
1297
1298BEGIN_EVENT_TABLE(wxHtmlHelpWindowOptionsDialog, wxDialog)
1299 EVT_COMBOBOX(wxID_ANY, wxHtmlHelpWindowOptionsDialog::OnUpdate)
1300 EVT_SPINCTRL(wxID_ANY, wxHtmlHelpWindowOptionsDialog::OnUpdateSpin)
1301END_EVENT_TABLE()
1302
1303void wxHtmlHelpWindow::OptionsDialog()
1304{
1305 wxHtmlHelpWindowOptionsDialog dlg(this);
1306 unsigned i;
1307
1308 if (m_NormalFonts == NULL)
1309 {
6540132f 1310 m_NormalFonts = new wxArrayString(wxFontEnumerator::GetFacenames());
3755cfa6
JS
1311 m_NormalFonts->Sort(); // ascending sort
1312 }
1313 if (m_FixedFonts == NULL)
1314 {
6540132f
VZ
1315 m_FixedFonts = new wxArrayString(
1316 wxFontEnumerator::GetFacenames(wxFONTENCODING_SYSTEM,
1317 true /*enum fixed width only*/));
3755cfa6
JS
1318 m_FixedFonts->Sort(); // ascending sort
1319 }
1320
1321 // VS: We want to show the font that is actually used by wxHtmlWindow.
1322 // If customization dialog wasn't used yet, facenames are empty and
1323 // wxHtmlWindow uses default fonts -- let's find out what they
1324 // are so that we can pass them to the dialog:
1325 if (m_NormalFace.empty())
1326 {
1327 wxFont fnt(m_FontSize, wxSWISS, wxNORMAL, wxNORMAL, false);
1328 m_NormalFace = fnt.GetFaceName();
1329 }
1330 if (m_FixedFace.empty())
1331 {
1332 wxFont fnt(m_FontSize, wxMODERN, wxNORMAL, wxNORMAL, false);
1333 m_FixedFace = fnt.GetFaceName();
1334 }
1335
1336 for (i = 0; i < m_NormalFonts->GetCount(); i++)
1337 dlg.NormalFont->Append((*m_NormalFonts)[i]);
1338 for (i = 0; i < m_FixedFonts->GetCount(); i++)
1339 dlg.FixedFont->Append((*m_FixedFonts)[i]);
1340 if (!m_NormalFace.empty())
1341 dlg.NormalFont->SetStringSelection(m_NormalFace);
1342 else
1343 dlg.NormalFont->SetSelection(0);
1344 if (!m_FixedFace.empty())
1345 dlg.FixedFont->SetStringSelection(m_FixedFace);
1346 else
1347 dlg.FixedFont->SetSelection(0);
1348 dlg.FontSize->SetValue(m_FontSize);
1349 dlg.UpdateTestWin();
1350
1351 if (dlg.ShowModal() == wxID_OK)
1352 {
1353 m_NormalFace = dlg.NormalFont->GetStringSelection();
1354 m_FixedFace = dlg.FixedFont->GetStringSelection();
1355 m_FontSize = dlg.FontSize->GetValue();
1356 SetFontsToHtmlWin(m_HtmlWin, m_NormalFace, m_FixedFace, m_FontSize);
1357 }
1358}
1359
1360void wxHtmlHelpWindow::NotifyPageChanged()
1361{
1362 if (m_UpdateContents && m_PagesHash)
1363 {
1364 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1365 wxHtmlHelpHashData *ha = NULL;
1366 if (!page.empty())
1367 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1368
1369 if (ha)
1370 {
1371 bool olduc = m_UpdateContents;
1372 m_UpdateContents = false;
1373 m_ContentsBox->SelectItem(ha->m_Id);
1374 m_ContentsBox->EnsureVisible(ha->m_Id);
1375 m_UpdateContents = olduc;
1376 }
1377 }
1378}
1379
1380/*
1381EVENT HANDLING :
1382*/
1383
1384
1385void wxHtmlHelpWindow::OnToolbar(wxCommandEvent& event)
1386{
1387 switch (event.GetId())
1388 {
1389 case wxID_HTML_BACK :
1390 m_HtmlWin->HistoryBack();
1391 NotifyPageChanged();
1392 break;
1393
1394 case wxID_HTML_FORWARD :
1395 m_HtmlWin->HistoryForward();
1396 NotifyPageChanged();
1397 break;
1398
1399 case wxID_HTML_UP :
1400 if (m_PagesHash)
1401 {
1402 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1403 wxHtmlHelpHashData *ha = NULL;
1404 if (!page.empty())
1405 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1406 if (ha && ha->m_Index > 0)
1407 {
1408 const wxHtmlHelpDataItem& it = m_Data->GetContentsArray()[ha->m_Index - 1];
1409 if (!it.page.empty())
1410 {
1411 m_HtmlWin->LoadPage(it.GetFullPath());
1412 NotifyPageChanged();
1413 }
1414 }
1415 }
1416 break;
1417
1418 case wxID_HTML_UPNODE :
1419 if (m_PagesHash)
1420 {
1421 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1422 wxHtmlHelpHashData *ha = NULL;
1423 if (!page.empty())
1424 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1425 if (ha && ha->m_Index > 0)
1426 {
1427 int level =
1428 m_Data->GetContentsArray()[ha->m_Index].level - 1;
1429 int ind = ha->m_Index - 1;
1430
1431 const wxHtmlHelpDataItem *it =
1432 &m_Data->GetContentsArray()[ind];
1433 while (ind >= 0 && it->level != level)
1434 {
1435 ind--;
1436 it = &m_Data->GetContentsArray()[ind];
1437 }
1438 if (ind >= 0)
1439 {
1440 if (!it->page.empty())
1441 {
1442 m_HtmlWin->LoadPage(it->GetFullPath());
1443 NotifyPageChanged();
1444 }
1445 }
1446 }
1447 }
1448 break;
1449
1450 case wxID_HTML_DOWN :
1451 if (m_PagesHash)
1452 {
1453 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1454 wxHtmlHelpHashData *ha = NULL;
1455 if (!page.empty())
1456 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1457
1458 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
1459 if (ha && ha->m_Index < (int)contents.size() - 1)
1460 {
1461 size_t idx = ha->m_Index + 1;
1462
1463 while (contents[idx].GetFullPath() == page) idx++;
1464
1465 if (!contents[idx].page.empty())
1466 {
1467 m_HtmlWin->LoadPage(contents[idx].GetFullPath());
1468 NotifyPageChanged();
1469 }
1470 }
1471 }
1472 break;
1473
1474 case wxID_HTML_PANEL :
1475 {
1476 if (! (m_Splitter && m_NavigPan))
1477 return ;
1478 if (m_Splitter->IsSplit())
1479 {
1480 m_Cfg.sashpos = m_Splitter->GetSashPosition();
1481 m_Splitter->Unsplit(m_NavigPan);
1482 m_Cfg.navig_on = false;
1483 }
1484 else
1485 {
1486 m_NavigPan->Show();
1487 m_HtmlWin->Show();
1488 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
1489 m_Cfg.navig_on = true;
1490 }
1491 }
1492 break;
1493
1494 case wxID_HTML_OPTIONS :
1495 OptionsDialog();
1496 break;
1497
1498 case wxID_HTML_BOOKMARKSADD :
1499 {
1500 wxString item;
1501 wxString url;
1502
1503 item = m_HtmlWin->GetOpenedPageTitle();
1504 url = m_HtmlWin->GetOpenedPage();
1505 if (item == wxEmptyString)
1506 item = url.AfterLast(wxT('/'));
1507 if (m_BookmarksPages.Index(url) == wxNOT_FOUND)
1508 {
1509 m_Bookmarks->Append(item);
1510 m_BookmarksNames.Add(item);
1511 m_BookmarksPages.Add(url);
1512 }
1513 }
1514 break;
1515
1516 case wxID_HTML_BOOKMARKSREMOVE :
1517 {
1518 wxString item;
1519 int pos;
1520
1521 item = m_Bookmarks->GetStringSelection();
1522 pos = m_BookmarksNames.Index(item);
1523 if (pos != wxNOT_FOUND)
1524 {
1525 m_BookmarksNames.RemoveAt(pos);
1526 m_BookmarksPages.RemoveAt(pos);
a8b9c344
WS
1527 pos = m_Bookmarks->GetSelection();
1528 wxASSERT_MSG( pos != wxNOT_FOUND , wxT("Unknown bookmark position") ) ;
1529 m_Bookmarks->Delete((unsigned int)pos);
3755cfa6
JS
1530 }
1531 }
1532 break;
1533
1534#if wxUSE_PRINTING_ARCHITECTURE
1535 case wxID_HTML_PRINT :
1536 {
1537 if (m_Printer == NULL)
1538 m_Printer = new wxHtmlEasyPrinting(_("Help Printing"), this);
1539 if (!m_HtmlWin->GetOpenedPage())
43b2d5e7 1540 {
3755cfa6 1541 wxLogWarning(_("Cannot print empty page."));
43b2d5e7 1542 }
3755cfa6 1543 else
43b2d5e7 1544 {
3755cfa6 1545 m_Printer->PrintFile(m_HtmlWin->GetOpenedPage());
43b2d5e7 1546 }
3755cfa6
JS
1547 }
1548 break;
1549#endif
1550
1551 case wxID_HTML_OPENFILE :
1552 {
1553 wxString filemask = wxString(
1554 _("HTML files (*.html;*.htm)|*.html;*.htm|")) +
1555 _("Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|") +
1556 _("HTML Help Project (*.hhp)|*.hhp|") +
1557#if wxUSE_LIBMSPACK
1558 _("Compressed HTML Help file (*.chm)|*.chm|") +
1559#endif
1560 _("All files (*.*)|*");
1561 wxString s = wxFileSelector(_("Open HTML document"),
1562 wxEmptyString,
1563 wxEmptyString,
1564 wxEmptyString,
1565 filemask,
ff3e84ff 1566 wxFD_OPEN | wxFD_FILE_MUST_EXIST,
3755cfa6
JS
1567 this);
1568 if (!s.empty())
1569 {
1570 wxString ext = s.Right(4).Lower();
9a83f860 1571 if (ext == wxT(".zip") || ext == wxT(".htb") ||
3755cfa6 1572#if wxUSE_LIBMSPACK
9a83f860 1573 ext == wxT(".chm") ||
3755cfa6 1574#endif
9a83f860 1575 ext == wxT(".hhp"))
3755cfa6
JS
1576 {
1577 wxBusyCursor bcur;
1578 m_Data->AddBook(s);
1579 RefreshLists();
1580 }
1581 else
1582 m_HtmlWin->LoadPage(s);
1583 }
1584 }
1585 break;
1586 }
1587}
1588
1589void wxHtmlHelpWindow::OnContentsSel(wxTreeEvent& event)
1590{
1591 wxHtmlHelpTreeItemData *pg;
1592
1593 pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem());
1594
1595 if (pg && m_UpdateContents)
1596 {
1597 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
1598 m_UpdateContents = false;
1599 if (!contents[pg->m_Id].page.empty())
1600 m_HtmlWin->LoadPage(contents[pg->m_Id].GetFullPath());
1601 m_UpdateContents = true;
1602 }
1603}
1604
1605void wxHtmlHelpWindow::OnIndexSel(wxCommandEvent& WXUNUSED(event))
1606{
1607 wxHtmlHelpMergedIndexItem *it = (wxHtmlHelpMergedIndexItem*)
1608 m_IndexList->GetClientData(m_IndexList->GetSelection());
1609 if (it)
1610 DisplayIndexItem(it);
1611}
1612
548b5377
WS
1613void wxHtmlHelpWindow::OnIndexFind(wxCommandEvent& WXUNUSED(event))
1614{
1615 DoIndexFind();
1616}
1617
1618void wxHtmlHelpWindow::DoIndexFind()
3755cfa6
JS
1619{
1620 wxString sr = m_IndexText->GetLineText(0);
1621 sr.MakeLower();
1622 if (sr == wxEmptyString)
1623 {
548b5377 1624 DoIndexAll();
3755cfa6
JS
1625 }
1626 else
1627 {
1628 wxBusyCursor bcur;
1629
1630 m_IndexList->Clear();
1631 const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
1632 size_t cnt = index.size();
1633
1634 int displ = 0;
1635 for (size_t i = 0; i < cnt; i++)
1636 {
1637 if (index[i].name.Lower().find(sr) != wxString::npos)
1638 {
1639 int pos = m_IndexList->Append(index[i].name,
1640 (char*)(&index[i]));
1641
1642 if (displ++ == 0)
1643 {
1644 // don't automatically show topic selector if this
1645 // item points to multiple pages:
1646 if (index[i].items.size() == 1)
1647 {
1648 m_IndexList->SetSelection(0);
1649 DisplayIndexItem(&index[i]);
1650 }
1651 }
1652
1653 // if this is nested item of the index, show its parent(s)
1654 // as well, otherwise it would not be clear what entry is
1655 // shown:
1656 wxHtmlHelpMergedIndexItem *parent = index[i].parent;
1657 while (parent)
1658 {
1659 if (pos == 0 ||
1660 (index.Index(*(wxHtmlHelpMergedIndexItem*)m_IndexList->GetClientData(pos-1))) < index.Index(*parent))
1661 {
1662 m_IndexList->Insert(parent->name,
1663 pos, (char*)parent);
1664 parent = parent->parent;
1665 }
1666 else break;
1667 }
1668
1669 // finally, it the item we just added is itself a parent for
1670 // other items, show them as well, because they are refinements
1671 // of the displayed index entry (i.e. it is implicitly contained
1672 // in them: "foo" with parent "bar" reads as "bar, foo"):
1673 int level = index[i].items[0]->level;
1674 i++;
1675 while (i < cnt && index[i].items[0]->level > level)
1676 {
1677 m_IndexList->Append(index[i].name, (char*)(&index[i]));
1678 i++;
1679 }
1680 i--;
1681 }
1682 }
1683
1684 wxString cnttext;
1685 cnttext.Printf(_("%i of %i"), displ, cnt);
1686 m_IndexCountInfo->SetLabel(cnttext);
1687
548b5377 1688 m_IndexText->SetSelection(0, sr.length());
3755cfa6
JS
1689 m_IndexText->SetFocus();
1690 }
1691}
1692
1693void wxHtmlHelpWindow::OnIndexAll(wxCommandEvent& WXUNUSED(event))
548b5377
WS
1694{
1695 DoIndexAll();
1696}
1697
1698void wxHtmlHelpWindow::DoIndexAll()
3755cfa6
JS
1699{
1700 wxBusyCursor bcur;
1701
1702 m_IndexList->Clear();
1703 const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
1704 size_t cnt = index.size();
1705 bool first = true;
1706
1707 for (size_t i = 0; i < cnt; i++)
1708 {
1709 m_IndexList->Append(index[i].name, (char*)(&index[i]));
1710 if (first)
1711 {
1712 // don't automatically show topic selector if this
1713 // item points to multiple pages:
1714 if (index[i].items.size() == 1)
1715 {
1716 DisplayIndexItem(&index[i]);
1717 }
1718 first = false;
1719 }
1720 }
1721
1722 wxString cnttext;
1723 cnttext.Printf(_("%i of %i"), cnt, cnt);
1724 m_IndexCountInfo->SetLabel(cnttext);
1725}
1726
1727void wxHtmlHelpWindow::OnSearchSel(wxCommandEvent& WXUNUSED(event))
1728{
1729 wxHtmlHelpDataItem *it = (wxHtmlHelpDataItem*) m_SearchList->GetClientData(m_SearchList->GetSelection());
1730 if (it)
1731 {
1732 if (!it->page.empty())
1733 m_HtmlWin->LoadPage(it->GetFullPath());
1734 NotifyPageChanged();
1735 }
1736}
1737
1738void wxHtmlHelpWindow::OnSearch(wxCommandEvent& WXUNUSED(event))
1739{
1740 wxString sr = m_SearchText->GetLineText(0);
1741
1742 if (!sr.empty())
1743 KeywordSearch(sr, wxHELP_SEARCH_ALL);
1744}
1745
1746void wxHtmlHelpWindow::OnBookmarksSel(wxCommandEvent& WXUNUSED(event))
1747{
9f322c6d
WS
1748 wxString str = m_Bookmarks->GetStringSelection();
1749 int idx = m_BookmarksNames.Index(str);
1750 if (!str.empty() && str != _("(bookmarks)") && idx != wxNOT_FOUND)
3755cfa6 1751 {
9f322c6d 1752 m_HtmlWin->LoadPage(m_BookmarksPages[(size_t)idx]);
3755cfa6
JS
1753 NotifyPageChanged();
1754 }
1755}
1756
1757void wxHtmlHelpWindow::OnSize(wxSizeEvent& WXUNUSED(event))
1758{
1759 Layout();
1760}
1761
1762#endif // wxUSE_WXHTML_HELP