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