1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/html/helpwnd.cpp 
   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 
   8 // Copyright:   (c) Harm van der Heijden and Vaclav Slavik 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h" 
  14 #include "wx/wxprec.h" 
  23     #include "wx/object.h" 
  24     #include "wx/dynarray.h" 
  28         #include "wx/stream.h" 
  33     #include "wx/bmpbuttn.h" 
  34     #include "wx/statbox.h" 
  35     #include "wx/radiobox.h" 
  37     #include "wx/settings.h" 
  38     #include "wx/msgdlg.h" 
  39     #include "wx/textctrl.h" 
  40     #include "wx/toolbar.h" 
  41     #include "wx/choicdlg.h" 
  42     #include "wx/filedlg.h" 
  45 #include "wx/html/helpfrm.h" 
  46 #include "wx/html/helpdlg.h" 
  47 #include "wx/html/helpctrl.h" 
  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" 
  56 #include "wx/fontenum.h" 
  57 #include "wx/artprov.h" 
  58 #include "wx/spinctrl.h" 
  60 // what is considered "small index"? 
  61 #define INDEX_IS_SMALL 1000 
  63 /* Motif defines this as a macro */ 
  68 //-------------------------------------------------------------------------- 
  69 // wxHtmlHelpTreeItemData (private) 
  70 //-------------------------------------------------------------------------- 
  72 class wxHtmlHelpTreeItemData 
: public wxTreeItemData
 
  75 #if defined(__VISAGECPP__) 
  76 //  VA needs a default ctor for some reason.... 
  77         wxHtmlHelpTreeItemData() : wxTreeItemData() 
  80         wxHtmlHelpTreeItemData(int id
) : wxTreeItemData() 
  87 //-------------------------------------------------------------------------- 
  88 // wxHtmlHelpHashData (private) 
  89 //-------------------------------------------------------------------------- 
  91 class wxHtmlHelpHashData 
: public wxObject
 
  94         wxHtmlHelpHashData(int index
, wxTreeItemId id
) : wxObject() 
  95             { m_Index 
= index
; m_Id 
= id
;} 
  96         virtual ~wxHtmlHelpHashData() {} 
 103 //-------------------------------------------------------------------------- 
 104 // wxHtmlHelpHtmlWindow (private) 
 105 //-------------------------------------------------------------------------- 
 108 class wxHtmlHelpHtmlWindow 
: public wxHtmlWindow
 
 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
) 
 118     void OnLink(wxHtmlLinkEvent
& ev
) 
 120         const wxMouseEvent 
*e 
= ev
.GetLinkInfo().GetEvent(); 
 121         if (e 
== NULL 
|| e
->LeftUp()) 
 122             m_Window
->NotifyPageChanged(); 
 124         // skip the event so that normal processing (i.e. following the link) 
 129     // Returns full location with anchor (helper) 
 130     static wxString 
GetOpenedPageWithAnchor(wxHtmlWindow 
*win
) 
 133             return wxEmptyString
; 
 135         wxString an 
= win
->GetOpenedAnchor(); 
 136         wxString pg 
= win
->GetOpenedPage(); 
 139             pg 
<< wxT("#") << an
; 
 145     wxHtmlHelpWindow 
*m_Window
; 
 147     wxDECLARE_NO_COPY_CLASS(wxHtmlHelpHtmlWindow
); 
 148     DECLARE_EVENT_TABLE() 
 151 BEGIN_EVENT_TABLE(wxHtmlHelpHtmlWindow
, wxHtmlWindow
) 
 152     EVT_HTML_LINK_CLICKED(wxID_ANY
, wxHtmlHelpHtmlWindow::OnLink
) 
 156 //--------------------------------------------------------------------------- 
 157 // wxHtmlHelpWindow::m_mergedIndex 
 158 //--------------------------------------------------------------------------- 
 160 WX_DEFINE_ARRAY_PTR(const wxHtmlHelpDataItem
*, wxHtmlHelpDataItemPtrArray
); 
 162 struct wxHtmlHelpMergedIndexItem
 
 164     wxHtmlHelpMergedIndexItem 
*parent
; 
 166     wxHtmlHelpDataItemPtrArray items
; 
 169 WX_DECLARE_OBJARRAY(wxHtmlHelpMergedIndexItem
, wxHtmlHelpMergedIndex
); 
 170 #include "wx/arrimpl.cpp" 
 171 WX_DEFINE_OBJARRAY(wxHtmlHelpMergedIndex
) 
 173 void wxHtmlHelpWindow::UpdateMergedIndex() 
 175     delete m_mergedIndex
; 
 176     m_mergedIndex 
= new wxHtmlHelpMergedIndex
; 
 177     wxHtmlHelpMergedIndex
& merged 
= *m_mergedIndex
; 
 179     const wxHtmlHelpDataItems
& items 
= m_Data
->GetIndexArray(); 
 180     size_t len 
= items
.size(); 
 182     wxHtmlHelpMergedIndexItem 
*history
[128] = {NULL
}; 
 184     for (size_t i 
= 0; i 
< len
; i
++) 
 186         const wxHtmlHelpDataItem
& item 
= items
[i
]; 
 187         wxASSERT_MSG( item
.level 
< 128, wxT("nested index entries too deep") ); 
 189         if (history
[item
.level
] && 
 190             history
[item
.level
]->items
[0]->name 
== item
.name
) 
 192             // same index entry as previous one, update list of items 
 193             history
[item
.level
]->items
.Add(&item
); 
 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
; 
 208 //--------------------------------------------------------------------------- 
 210 //--------------------------------------------------------------------------- 
 212 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpWindow
, wxWindow
) 
 214 BEGIN_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
) 
 230 wxHtmlHelpWindow::wxHtmlHelpWindow(wxWindow
* parent
, wxWindowID id
, 
 233                                     int style
, int helpStyle
, wxHtmlHelpData
* data
) 
 236     Create(parent
, id
, pos
, size
, style
, helpStyle
); 
 239 void wxHtmlHelpWindow::Init(wxHtmlHelpData
* data
) 
 244         m_DataCreated 
= false; 
 248         m_Data 
= new wxHtmlHelpData(); 
 249         m_DataCreated 
= true; 
 256     m_ContentsBox 
= NULL
; 
 258     m_IndexButton 
= NULL
; 
 259     m_IndexButtonAll 
= NULL
; 
 262     m_SearchButton 
= NULL
; 
 264     m_SearchChoice 
= NULL
; 
 265     m_IndexCountInfo 
= NULL
; 
 268     m_NavigNotebook 
= NULL
; 
 271     m_SearchCaseSensitive 
= NULL
; 
 272     m_SearchWholeWords 
= NULL
; 
 274     m_mergedIndex 
= NULL
; 
 278     m_ConfigRoot 
= wxEmptyString
; 
 279 #endif // wxUSE_CONFIG 
 281     m_Cfg
.x 
= m_Cfg
.y 
= wxDefaultCoord
; 
 285     m_Cfg
.navig_on 
= true; 
 287     m_NormalFonts 
= m_FixedFonts 
= NULL
; 
 288     m_NormalFace 
= m_FixedFace 
= wxEmptyString
; 
 295 #if wxUSE_PRINTING_ARCHITECTURE 
 300     m_UpdateContents 
= true; 
 302     m_helpController 
= NULL
; 
 305 // Create: builds the GUI components. 
 306 // with the style flag it's possible to toggle the toolbar, contents, index and search 
 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) 
 314 bool wxHtmlHelpWindow::Create(wxWindow
* parent
, wxWindowID id
, 
 315                              const wxPoint
& pos
, const wxSize
& size
, 
 316                              int style
, int helpStyle
) 
 318     m_hfStyle 
= helpStyle
; 
 321     // Do the config in two steps. We read the HtmlWindow customization after we 
 322     // create the window. 
 324         ReadCustomization(m_Config
, m_ConfigRoot
); 
 325 #endif // wxUSE_CONFIG 
 327     wxWindow::Create(parent
, id
, pos
, size
, style
, wxT("wxHtmlHelp")); 
 329     SetHelpText(_("Displays help as you browse the books on the left.")); 
 331     GetPosition(&m_Cfg
.x
, &m_Cfg
.y
); 
 333     int notebook_page 
= 0; 
 335     // The sizer for the whole top-level window. 
 336     wxSizer 
*topWindowSizer 
= new wxBoxSizer(wxVERTICAL
); 
 337     SetSizer(topWindowSizer
); 
 342     if (helpStyle 
& (wxHF_TOOLBAR 
| wxHF_FLAT_TOOLBAR
)) 
 344         wxToolBar 
*toolBar 
= new wxToolBar(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 
 345                                            wxNO_BORDER 
| wxTB_HORIZONTAL 
| 
 346                                            wxTB_DOCKABLE 
| wxTB_NODIVIDER 
| 
 347                                            (helpStyle 
& wxHF_FLAT_TOOLBAR 
? wxTB_FLAT 
: 0)); 
 348         toolBar
->SetMargins( 2, 2 ); 
 349         toolBar
->SetToolBitmapSize( wxSize(22,22) ); 
 350         AddToolbarButtons(toolBar
, helpStyle
); 
 352         topWindowSizer
->Add(toolBar
, 0, wxEXPAND
); 
 355 #endif //wxUSE_TOOLBAR 
 357     wxSizer 
*navigSizer 
= NULL
; 
 360     wxBorder htmlWindowBorder 
= GetDefaultBorder(); 
 361     htmlWindowBorder 
= wxBORDER_THEME
; 
 363     wxBorder htmlWindowBorder 
= wxBORDER_SUNKEN
; 
 366     if (helpStyle 
& (wxHF_CONTENTS 
| wxHF_INDEX 
| wxHF_SEARCH
)) 
 368         // traditional help controller; splitter window with html page on the 
 369         // right and a notebook containing various pages on the left 
 370         long splitterStyle 
= wxSP_3D
; 
 371         // Drawing moving sash can cause problems on wxMac 
 373         splitterStyle 
|= wxSP_LIVE_UPDATE
; 
 375         m_Splitter 
= new wxSplitterWindow(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, splitterStyle
); 
 377         topWindowSizer
->Add(m_Splitter
, 1, wxEXPAND
); 
 379         m_HtmlWin 
= new wxHtmlHelpHtmlWindow(this, m_Splitter
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxHW_DEFAULT_STYLE
|htmlWindowBorder
); 
 380         m_NavigPan 
= new wxPanel(m_Splitter
, wxID_ANY
); 
 381         m_NavigNotebook 
= new wxNotebook(m_NavigPan
, wxID_HTML_NOTEBOOK
, 
 382                                          wxDefaultPosition
, wxDefaultSize
); 
 384         m_NavigNotebook
->SetWindowVariant(wxWINDOW_VARIANT_SMALL
); 
 387         navigSizer 
= new wxBoxSizer(wxVERTICAL
); 
 388         navigSizer
->Add(m_NavigNotebook
, 1, wxEXPAND
); 
 390         m_NavigPan
->SetSizer(navigSizer
); 
 394         // only html window, no notebook with index,contents etc 
 395         m_HtmlWin 
= new wxHtmlWindow(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxHW_DEFAULT_STYLE
|htmlWindowBorder
); 
 396         topWindowSizer
->Add(m_HtmlWin
, 1, wxEXPAND
); 
 401         m_HtmlWin
->ReadCustomization(m_Config
, m_ConfigRoot
); 
 402 #endif // wxUSE_CONFIG 
 404     // contents tree panel? 
 405     if ( helpStyle 
& wxHF_CONTENTS 
) 
 407         wxWindow 
*dummy 
= new wxPanel(m_NavigNotebook
, wxID_HTML_INDEXPAGE
); 
 409         dummy
->SetWindowVariant(wxWINDOW_VARIANT_NORMAL
); 
 411         wxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
 413         topsizer
->Add(0, 10); 
 415         dummy
->SetSizer(topsizer
); 
 417         if ( helpStyle 
& wxHF_BOOKMARKS 
) 
 419             long comboStyle 
= wxCB_READONLY
; 
 421             // Not supported on OSX/Cocoa presently 
 422             comboStyle 
|= wxCB_SORT
; 
 425             m_Bookmarks 
= new wxComboBox(dummy
, wxID_HTML_BOOKMARKSLIST
, 
 427                                          wxDefaultPosition
, wxDefaultSize
, 
 428                                          0, NULL
, comboStyle
); 
 429             m_Bookmarks
->Append(_("(bookmarks)")); 
 430             for (unsigned i 
= 0; i 
< m_BookmarksNames
.GetCount(); i
++) 
 431                 m_Bookmarks
->Append(m_BookmarksNames
[i
]); 
 432             m_Bookmarks
->SetSelection(0); 
 434             wxBitmapButton 
*bmpbt1
, *bmpbt2
; 
 435             bmpbt1 
= new wxBitmapButton(dummy
, wxID_HTML_BOOKMARKSADD
, 
 436                                  wxArtProvider::GetBitmap(wxART_ADD_BOOKMARK
, 
 438             bmpbt2 
= new wxBitmapButton(dummy
, wxID_HTML_BOOKMARKSREMOVE
, 
 439                                  wxArtProvider::GetBitmap(wxART_DEL_BOOKMARK
, 
 442             bmpbt1
->SetToolTip(_("Add current page to bookmarks")); 
 443             bmpbt2
->SetToolTip(_("Remove current page from bookmarks")); 
 444 #endif // wxUSE_TOOLTIPS 
 446             wxSizer 
*sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
 448             sizer
->Add(m_Bookmarks
, 1, wxALIGN_CENTRE_VERTICAL 
| wxRIGHT
, 5); 
 449             sizer
->Add(bmpbt1
, 0, wxALIGN_CENTRE_VERTICAL 
| wxRIGHT
, 2); 
 450             sizer
->Add(bmpbt2
, 0, wxALIGN_CENTRE_VERTICAL
, 0); 
 452             topsizer
->Add(sizer
, 0, wxEXPAND 
| wxLEFT 
| wxBOTTOM 
| wxRIGHT
, 10); 
 455         m_ContentsBox 
= new wxTreeCtrl(dummy
, wxID_HTML_TREECTRL
, 
 456                                        wxDefaultPosition
, wxDefaultSize
, 
 457 #if defined(__WXGTK20__) || defined(__WXMAC__) 
 459                                        wxTR_HAS_BUTTONS 
| wxTR_HIDE_ROOT 
| 
 463                                        wxTR_HAS_BUTTONS 
| wxTR_HIDE_ROOT 
| 
 468         wxImageList 
*ContentsImageList 
= new wxImageList(16, 16); 
 469         ContentsImageList
->Add(wxArtProvider::GetIcon(wxART_HELP_BOOK
, 
 472         ContentsImageList
->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER
, 
 475         ContentsImageList
->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE
, 
 479         m_ContentsBox
->AssignImageList(ContentsImageList
); 
 481         topsizer
->Add(m_ContentsBox
, 1, 
 482                       wxEXPAND 
| wxLEFT 
| wxBOTTOM 
| wxRIGHT
, 
 485         m_NavigNotebook
->AddPage(dummy
, _("Contents")); 
 486         m_ContentsPage 
= notebook_page
++; 
 489     // index listbox panel? 
 490     if ( helpStyle 
& wxHF_INDEX 
) 
 492         wxWindow 
*dummy 
= new wxPanel(m_NavigNotebook
, wxID_HTML_INDEXPAGE
); 
 494         dummy
->SetWindowVariant(wxWINDOW_VARIANT_NORMAL
); 
 496         wxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
 498         dummy
->SetSizer(topsizer
); 
 500         m_IndexText 
= new wxTextCtrl(dummy
, wxID_HTML_INDEXTEXT
, wxEmptyString
, 
 501                                      wxDefaultPosition
, wxDefaultSize
, 
 503         m_IndexButton 
= new wxButton(dummy
, wxID_HTML_INDEXBUTTON
, _("Find")); 
 504         m_IndexButtonAll 
= new wxButton(dummy
, wxID_HTML_INDEXBUTTONALL
, 
 506         m_IndexCountInfo 
= new wxStaticText(dummy
, wxID_HTML_COUNTINFO
, 
 507                                             wxEmptyString
, wxDefaultPosition
, 
 509                                             wxALIGN_RIGHT 
| wxST_NO_AUTORESIZE
); 
 510         m_IndexList 
= new wxListBox(dummy
, wxID_HTML_INDEXLIST
, 
 511                                     wxDefaultPosition
, wxDefaultSize
, 
 512                                     0, NULL
, wxLB_SINGLE
); 
 515         m_IndexButton
->SetToolTip(_("Display all index items that contain given substring. Search is case insensitive.")); 
 516         m_IndexButtonAll
->SetToolTip(_("Show all items in index")); 
 517 #endif //wxUSE_TOOLTIPS 
 519         topsizer
->Add(m_IndexText
, 0, wxEXPAND 
| wxALL
, 10); 
 520         wxSizer 
*btsizer 
= new wxBoxSizer(wxHORIZONTAL
); 
 521         btsizer
->Add(m_IndexButton
, 0, wxRIGHT
, 2); 
 522         btsizer
->Add(m_IndexButtonAll
); 
 523         topsizer
->Add(btsizer
, 0, 
 524                       wxALIGN_RIGHT 
| wxLEFT 
| wxRIGHT 
| wxBOTTOM
, 10); 
 525         topsizer
->Add(m_IndexCountInfo
, 0, wxEXPAND 
| wxLEFT 
| wxRIGHT
, 2); 
 526         topsizer
->Add(m_IndexList
, 1, wxEXPAND 
| wxALL
, 2); 
 528         m_NavigNotebook
->AddPage(dummy
, _("Index")); 
 529         m_IndexPage 
= notebook_page
++; 
 532     // search list panel? 
 533     if ( helpStyle 
& wxHF_SEARCH 
) 
 535         wxWindow 
*dummy 
= new wxPanel(m_NavigNotebook
, wxID_HTML_INDEXPAGE
); 
 537         dummy
->SetWindowVariant(wxWINDOW_VARIANT_NORMAL
); 
 539         wxSizer 
*sizer 
= new wxBoxSizer(wxVERTICAL
); 
 541         dummy
->SetSizer(sizer
); 
 543         m_SearchText 
= new wxTextCtrl(dummy
, wxID_HTML_SEARCHTEXT
, 
 545                                       wxDefaultPosition
, wxDefaultSize
, 
 547         m_SearchChoice 
= new wxChoice(dummy
, wxID_HTML_SEARCHCHOICE
, 
 548                                       wxDefaultPosition
, wxSize(125,wxDefaultCoord
)); 
 549         m_SearchCaseSensitive 
= new wxCheckBox(dummy
, wxID_ANY
, _("Case sensitive")); 
 550         m_SearchWholeWords 
= new wxCheckBox(dummy
, wxID_ANY
, _("Whole words only")); 
 551         m_SearchButton 
= new wxButton(dummy
, wxID_HTML_SEARCHBUTTON
, _("Search")); 
 553         m_SearchButton
->SetToolTip(_("Search contents of help book(s) for all occurrences of the text you typed above")); 
 554 #endif //wxUSE_TOOLTIPS 
 555         m_SearchList 
= new wxListBox(dummy
, wxID_HTML_SEARCHLIST
, 
 556                                      wxDefaultPosition
, wxDefaultSize
, 
 557                                      0, NULL
, wxLB_SINGLE
); 
 559         sizer
->Add(m_SearchText
, 0, wxEXPAND 
| wxALL
, 10); 
 560         sizer
->Add(m_SearchChoice
, 0, wxEXPAND 
| wxLEFT 
| wxRIGHT 
| wxBOTTOM
, 10); 
 561         sizer
->Add(m_SearchCaseSensitive
, 0, wxLEFT 
| wxRIGHT
, 10); 
 562         sizer
->Add(m_SearchWholeWords
, 0, wxLEFT 
| wxRIGHT
, 10); 
 563         sizer
->Add(m_SearchButton
, 0, wxALL 
| wxALIGN_RIGHT
, 8); 
 564         sizer
->Add(m_SearchList
, 1, wxALL 
| wxEXPAND
, 2); 
 566         m_NavigNotebook
->AddPage(dummy
, _("Search")); 
 567         m_SearchPage 
= notebook_page
; 
 576         navigSizer
->SetSizeHints(m_NavigPan
); 
 577         m_NavigPan
->Layout(); 
 581     if ( m_NavigPan 
&& m_Splitter 
) 
 583         // The panel will have its own min size which the splitter 
 586         //    m_Splitter->SetMinimumPaneSize(m_NavigPan->GetBestSize().x); 
 588         m_Splitter
->SetMinimumPaneSize(20); 
 590         if ( m_Cfg
.navig_on 
) 
 593             m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 597             m_NavigPan
->Show(false); 
 598             m_Splitter
->Initialize(m_HtmlWin
); 
 602     // Reduce flicker by updating the splitter pane sizes before the 
 604     wxSizeEvent 
sizeEvent(GetSize(), GetId()); 
 605     GetEventHandler()->ProcessEvent(sizeEvent
); 
 608         m_Splitter
->UpdateSize(); 
 613 wxHtmlHelpWindow::~wxHtmlHelpWindow() 
 615     if ( m_helpController 
) 
 616         m_helpController
->SetHelpWindow(NULL
); 
 618     delete m_mergedIndex
; 
 620     // PopEventHandler(); // wxhtmlhelpcontroller (not any more!) 
 623     if (m_NormalFonts
) delete m_NormalFonts
; 
 624     if (m_FixedFonts
) delete m_FixedFonts
; 
 627         WX_CLEAR_HASH_TABLE(*m_PagesHash
); 
 630 #if wxUSE_PRINTING_ARCHITECTURE 
 631     if (m_Printer
) delete m_Printer
; 
 635 void wxHtmlHelpWindow::SetController(wxHtmlHelpController
* controller
) 
 639     m_helpController 
= controller
; 
 640     m_Data 
= controller
->GetHelpData(); 
 641     m_DataCreated 
= false; 
 645 void wxHtmlHelpWindow::AddToolbarButtons(wxToolBar 
*toolBar
, int style
) 
 647     wxBitmap wpanelBitmap 
= 
 648         wxArtProvider::GetBitmap(wxART_HELP_SIDE_PANEL
, wxART_TOOLBAR
); 
 649     wxBitmap wbackBitmap 
= 
 650         wxArtProvider::GetBitmap(wxART_GO_BACK
, wxART_TOOLBAR
); 
 651     wxBitmap wforwardBitmap 
= 
 652         wxArtProvider::GetBitmap(wxART_GO_FORWARD
, wxART_TOOLBAR
); 
 653     wxBitmap wupnodeBitmap 
= 
 654         wxArtProvider::GetBitmap(wxART_GO_TO_PARENT
, wxART_TOOLBAR
); 
 656         wxArtProvider::GetBitmap(wxART_GO_UP
, wxART_TOOLBAR
); 
 657     wxBitmap wdownBitmap 
= 
 658         wxArtProvider::GetBitmap(wxART_GO_DOWN
, wxART_TOOLBAR
); 
 659     wxBitmap wopenBitmap 
= 
 660         wxArtProvider::GetBitmap(wxART_FILE_OPEN
, wxART_TOOLBAR
); 
 661     wxBitmap wprintBitmap 
= 
 662         wxArtProvider::GetBitmap(wxART_PRINT
, wxART_TOOLBAR
); 
 663     wxBitmap woptionsBitmap 
= 
 664         wxArtProvider::GetBitmap(wxART_HELP_SETTINGS
, wxART_TOOLBAR
); 
 666     wxASSERT_MSG( (wpanelBitmap
.IsOk() && wbackBitmap
.IsOk() && 
 667                    wforwardBitmap
.IsOk() && wupnodeBitmap
.IsOk() && 
 668                    wupBitmap
.IsOk() && wdownBitmap
.IsOk() && 
 669                    wopenBitmap
.IsOk() && wprintBitmap
.IsOk() && 
 670                    woptionsBitmap
.IsOk()), 
 671                   wxT("One or more HTML help frame toolbar bitmap could not be loaded.")) ; 
 674     toolBar
->AddTool(wxID_HTML_PANEL
, wxEmptyString
, wpanelBitmap
, _("Show/hide navigation panel")); 
 675     toolBar
->AddSeparator(); 
 676     toolBar
->AddTool(wxID_HTML_BACK
, wxEmptyString
, wbackBitmap
, _("Go back")); 
 677     toolBar
->AddTool(wxID_HTML_FORWARD
, wxEmptyString
, wforwardBitmap
, _("Go forward")); 
 678     toolBar
->AddSeparator(); 
 679     toolBar
->AddTool(wxID_HTML_UPNODE
, wxEmptyString
, wupnodeBitmap
, _("Go one level up in document hierarchy")); 
 680     toolBar
->AddTool(wxID_HTML_UP
, wxEmptyString
, wupBitmap
, _("Previous page")); 
 681     toolBar
->AddTool(wxID_HTML_DOWN
, wxEmptyString
, wdownBitmap
, _("Next page")); 
 683     if ((style 
& wxHF_PRINT
) || (style 
& wxHF_OPEN_FILES
)) 
 684         toolBar
->AddSeparator(); 
 686     if (style 
& wxHF_OPEN_FILES
) 
 687         toolBar
->AddTool(wxID_HTML_OPENFILE
, wxEmptyString
, wopenBitmap
, _("Open HTML document")); 
 689 #if wxUSE_PRINTING_ARCHITECTURE 
 690     if (style 
& wxHF_PRINT
) 
 691         toolBar
->AddTool(wxID_HTML_PRINT
, wxEmptyString
, wprintBitmap
, _("Print this page")); 
 694     toolBar
->AddSeparator(); 
 695     toolBar
->AddTool(wxID_HTML_OPTIONS
, wxEmptyString
, woptionsBitmap
, _("Display options dialog")); 
 697     // Allow application to add custom buttons 
 698     wxHtmlHelpFrame
* parentFrame 
= wxDynamicCast(GetParent(), wxHtmlHelpFrame
); 
 699     wxHtmlHelpDialog
* parentDialog 
= wxDynamicCast(GetParent(), wxHtmlHelpDialog
); 
 701         parentFrame
->AddToolbarButtons(toolBar
, style
); 
 703         parentDialog
->AddToolbarButtons(toolBar
, style
); 
 705 #endif //wxUSE_TOOLBAR 
 708 bool wxHtmlHelpWindow::Display(const wxString
& x
) 
 710     wxString url 
= m_Data
->FindPageByName(x
); 
 713         m_HtmlWin
->LoadPage(url
); 
 721 bool wxHtmlHelpWindow::Display(const int id
) 
 723     wxString url 
= m_Data
->FindPageById(id
); 
 726         m_HtmlWin
->LoadPage(url
); 
 734 bool wxHtmlHelpWindow::DisplayContents() 
 739     if (!m_Splitter
->IsSplit()) 
 743         m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 744         m_Cfg
.navig_on 
= true; 
 747     m_NavigNotebook
->SetSelection(m_ContentsPage
); 
 749     if (m_Data
->GetBookRecArray().GetCount() > 0) 
 751         wxHtmlBookRecord
& book 
= m_Data
->GetBookRecArray()[0]; 
 752         if (!book
.GetStart().empty()) 
 753             m_HtmlWin
->LoadPage(book
.GetFullPath(book
.GetStart())); 
 759 bool wxHtmlHelpWindow::DisplayIndex() 
 764     if (!m_Splitter
->IsSplit()) 
 768         m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 771     m_NavigNotebook
->SetSelection(m_IndexPage
); 
 773     if (m_Data
->GetBookRecArray().GetCount() > 0) 
 775         wxHtmlBookRecord
& book 
= m_Data
->GetBookRecArray()[0]; 
 776         if (!book
.GetStart().empty()) 
 777             m_HtmlWin
->LoadPage(book
.GetFullPath(book
.GetStart())); 
 783 void wxHtmlHelpWindow::DisplayIndexItem(const wxHtmlHelpMergedIndexItem 
*it
) 
 785     if (it
->items
.size() == 1) 
 787         if (!it
->items
[0]->page
.empty()) 
 789             m_HtmlWin
->LoadPage(it
->items
[0]->GetFullPath()); 
 795         wxBusyCursor busy_cursor
; 
 797         // more pages associated with this index item -- let the user choose 
 798         // which one she/he wants from a list: 
 800         size_t len 
= it
->items
.size(); 
 801         for (size_t i 
= 0; i 
< len
; i
++) 
 803             wxString page 
= it
->items
[i
]->page
; 
 804             // try to find page's title in contents: 
 805             const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
 806             size_t clen 
= contents
.size(); 
 807             for (size_t j 
= 0; j 
< clen
; j
++) 
 809                 if (contents
[j
].page 
== page
) 
 811                     page 
= contents
[j
].name
; 
 818         wxSingleChoiceDialog 
dlg(this, 
 819                                  _("Please choose the page to display:"), 
 822                                  (void**)NULL
, // No client data 
 823                                  wxCHOICEDLG_STYLE 
& ~wxCENTRE
); 
 824         if (dlg
.ShowModal() == wxID_OK
) 
 826             m_HtmlWin
->LoadPage(it
->items
[dlg
.GetSelection()]->GetFullPath()); 
 832 bool wxHtmlHelpWindow::KeywordSearch(const wxString
& keyword
, 
 833                                     wxHelpSearchMode mode
) 
 835     wxCHECK_MSG( !keyword
.empty(), false, "must have a non empty keyword" ); 
 837     if (mode 
== wxHELP_SEARCH_ALL
) 
 839         if ( !(m_SearchList 
&& 
 840                m_SearchButton 
&& m_SearchText 
&& m_SearchChoice
) ) 
 843     else if (mode 
== wxHELP_SEARCH_INDEX
) 
 845         if ( !(m_IndexList 
&& 
 846                m_IndexButton 
&& m_IndexButtonAll 
&& m_IndexText
) ) 
 852     wxString book 
= wxEmptyString
; 
 854     if (!m_Splitter
->IsSplit()) 
 858         m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 861     if (mode 
== wxHELP_SEARCH_ALL
) 
 863         m_NavigNotebook
->SetSelection(m_SearchPage
); 
 864         m_SearchList
->Clear(); 
 865         m_SearchText
->SetValue(keyword
); 
 866         m_SearchButton
->Disable(); 
 868         if (m_SearchChoice
->GetSelection() != 0) 
 869             book 
= m_SearchChoice
->GetStringSelection(); 
 871         wxHtmlSearchStatus 
status(m_Data
, keyword
, 
 872                                   m_SearchCaseSensitive
->GetValue(), 
 873                                   m_SearchWholeWords
->GetValue(), 
 876 #if wxUSE_PROGRESSDLG 
 877         wxProgressDialog 
progress(_("Searching..."), 
 878                                   _("No matching page found yet"), 
 879                                   status
.GetMaxIndex(), this, 
 880                                   wxPD_APP_MODAL 
| wxPD_CAN_ABORT 
| wxPD_AUTO_HIDE
); 
 884         while (status
.IsActive()) 
 886             curi 
= status
.GetCurIndex(); 
 888 #if wxUSE_PROGRESSDLG 
 889                 && !progress
.Update(curi
) 
 895                 foundstr
.Printf(_("Found %i matches"), ++foundcnt
); 
 896 #if wxUSE_PROGRESSDLG 
 897                 progress
.Update(status
.GetCurIndex(), foundstr
); 
 899                 m_SearchList
->Append(status
.GetName(), (void*)status
.GetCurItem()); 
 903         m_SearchButton
->Enable(); 
 904         m_SearchText
->SetSelection(0, keyword
.length()); 
 905         m_SearchText
->SetFocus(); 
 907     else if (mode 
== wxHELP_SEARCH_INDEX
) 
 909         m_NavigNotebook
->SetSelection(m_IndexPage
); 
 910         m_IndexList
->Clear(); 
 911         m_IndexButton
->Disable(); 
 912         m_IndexButtonAll
->Disable(); 
 913         m_IndexText
->SetValue(keyword
); 
 916         m_IndexButton
->Enable(); 
 917         m_IndexButtonAll
->Enable(); 
 918         foundcnt 
= m_IndexList
->GetCount(); 
 926                 wxFAIL_MSG( wxT("unknown help search mode") ); 
 929             case wxHELP_SEARCH_ALL
: 
 931                 wxHtmlHelpDataItem 
*it 
= 
 932                     (wxHtmlHelpDataItem
*) m_SearchList
->GetClientData(0); 
 935                     m_HtmlWin
->LoadPage(it
->GetFullPath()); 
 941             case wxHELP_SEARCH_INDEX
: 
 943                 wxHtmlHelpMergedIndexItem
* it 
= 
 944                     (wxHtmlHelpMergedIndexItem
*) m_IndexList
->GetClientData(0); 
 946                     DisplayIndexItem(it
); 
 956 void wxHtmlHelpWindow::CreateContents() 
 963         WX_CLEAR_HASH_TABLE(*m_PagesHash
); 
 967     const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
 969     size_t cnt 
= contents
.size(); 
 971     m_PagesHash 
= new wxHashTable(wxKEY_STRING
, 2 * cnt
); 
 973     const int MAX_ROOTS 
= 64; 
 974     wxTreeItemId roots
[MAX_ROOTS
]; 
 975     // VS: this array holds information about whether we've set item icon at 
 976     //     given level. This is necessary because m_Data has a flat structure 
 977     //     and there's no way of recognizing if some item has subitems or not. 
 978     //     We set the icon later: when we find an item with level=n, we know 
 979     //     that the last item with level=n-1 was afolder with subitems, so we 
 980     //     set its icon accordingly 
 981     bool imaged
[MAX_ROOTS
]; 
 982     m_ContentsBox
->DeleteAllItems(); 
 984     roots
[0] = m_ContentsBox
->AddRoot(_("(Help)")); 
 987     for (size_t i 
= 0; i 
< cnt
; i
++) 
 989         wxHtmlHelpDataItem 
*it 
= &contents
[i
]; 
 993             if (m_hfStyle 
& wxHF_MERGE_BOOKS
) 
 994                 // VS: we don't want book nodes, books' content should 
 995                 //    appear under tree's root. This line will create a "fake" 
 996                 //    record about book node so that the rest of this look 
 997                 //    will believe there really _is_ a book node and will 
1002                 roots
[1] = m_ContentsBox
->AppendItem(roots
[0], 
1003                                          it
->name
, IMG_Book
, -1, 
1004                                          new wxHtmlHelpTreeItemData(i
)); 
1005                 m_ContentsBox
->SetItemBold(roots
[1], true); 
1009         // ...and their contents: 
1012             roots
[it
->level 
+ 1] = m_ContentsBox
->AppendItem( 
1013                                      roots
[it
->level
], it
->name
, IMG_Page
, 
1014                                      -1, new wxHtmlHelpTreeItemData(i
)); 
1015             imaged
[it
->level 
+ 1] = false; 
1018         m_PagesHash
->Put(it
->GetFullPath(), 
1019                          new wxHtmlHelpHashData(i
, roots
[it
->level 
+ 1])); 
1021         // Set the icon for the node one level up in the hierarchy, 
1022         // unless already done (see comment above imaged[] declaration) 
1023         if (!imaged
[it
->level
]) 
1025             int image 
= IMG_Folder
; 
1026             if (m_hfStyle 
& wxHF_ICONS_BOOK
) 
1028             else if (m_hfStyle 
& wxHF_ICONS_BOOK_CHAPTER
) 
1029                 image 
= (it
->level 
== 1) ? IMG_Book 
: IMG_Folder
; 
1030             m_ContentsBox
->SetItemImage(roots
[it
->level
], image
); 
1031             m_ContentsBox
->SetItemImage(roots
[it
->level
], image
, 
1032                                         wxTreeItemIcon_Selected
); 
1033             imaged
[it
->level
] = true; 
1038 void wxHtmlHelpWindow::CreateIndex() 
1043     m_IndexList
->Clear(); 
1045     unsigned long cnt 
= m_mergedIndex
->size(); 
1048     if (cnt 
> INDEX_IS_SMALL
) 
1049         cnttext
.Printf(_("%d of %lu"), 0, cnt
); 
1051         cnttext
.Printf(_("%lu of %lu"), cnt
, cnt
); 
1052     m_IndexCountInfo
->SetLabel(cnttext
); 
1053     if (cnt 
> INDEX_IS_SMALL
) 
1056     for (size_t i 
= 0; i 
< cnt
; i
++) 
1057         m_IndexList
->Append((*m_mergedIndex
)[i
].name
, 
1058                             (char*)(&(*m_mergedIndex
)[i
])); 
1061 void wxHtmlHelpWindow::CreateSearch() 
1063     if (! (m_SearchList 
&& m_SearchChoice
)) 
1065     m_SearchList
->Clear(); 
1066     m_SearchChoice
->Clear(); 
1067     m_SearchChoice
->Append(_("Search in all books")); 
1068     const wxHtmlBookRecArray
& bookrec 
= m_Data
->GetBookRecArray(); 
1069     int i
, cnt 
= bookrec
.GetCount(); 
1070     for (i 
= 0; i 
< cnt
; i
++) 
1071         m_SearchChoice
->Append(bookrec
[i
].GetTitle()); 
1072     m_SearchChoice
->SetSelection(0); 
1075 void wxHtmlHelpWindow::RefreshLists() 
1077     // Update m_mergedIndex: 
1078     UpdateMergedIndex(); 
1079     // Update the controls 
1086 void wxHtmlHelpWindow::ReadCustomization(wxConfigBase 
*cfg
, const wxString
& path
) 
1091     if (path 
!= wxEmptyString
) 
1093         oldpath 
= cfg
->GetPath(); 
1094         cfg
->SetPath(wxT("/") + path
); 
1097     m_Cfg
.navig_on 
= cfg
->Read(wxT("hcNavigPanel"), m_Cfg
.navig_on
) != 0; 
1098     m_Cfg
.sashpos 
= cfg
->Read(wxT("hcSashPos"), m_Cfg
.sashpos
); 
1099     m_Cfg
.x 
= cfg
->Read(wxT("hcX"), m_Cfg
.x
); 
1100     m_Cfg
.y 
= cfg
->Read(wxT("hcY"), m_Cfg
.y
); 
1101     m_Cfg
.w 
= cfg
->Read(wxT("hcW"), m_Cfg
.w
); 
1102     m_Cfg
.h 
= cfg
->Read(wxT("hcH"), m_Cfg
.h
); 
1104     m_FixedFace 
= cfg
->Read(wxT("hcFixedFace"), m_FixedFace
); 
1105     m_NormalFace 
= cfg
->Read(wxT("hcNormalFace"), m_NormalFace
); 
1106     m_FontSize 
= cfg
->Read(wxT("hcBaseFontSize"), m_FontSize
); 
1113         cnt 
= cfg
->Read(wxT("hcBookmarksCnt"), 0L); 
1116             m_BookmarksNames
.Clear(); 
1117             m_BookmarksPages
.Clear(); 
1120                 m_Bookmarks
->Clear(); 
1121                 m_Bookmarks
->Append(_("(bookmarks)")); 
1124             for (i 
= 0; i 
< cnt
; i
++) 
1126                 val
.Printf(wxT("hcBookmark_%i"), i
); 
1128                 m_BookmarksNames
.Add(s
); 
1129                 if (m_Bookmarks
) m_Bookmarks
->Append(s
); 
1130                 val
.Printf(wxT("hcBookmark_%i_url"), i
); 
1132                 m_BookmarksPages
.Add(s
); 
1138         m_HtmlWin
->ReadCustomization(cfg
); 
1140     if (path 
!= wxEmptyString
) 
1141         cfg
->SetPath(oldpath
); 
1144 void wxHtmlHelpWindow::WriteCustomization(wxConfigBase 
*cfg
, const wxString
& path
) 
1149     if (path 
!= wxEmptyString
) 
1151         oldpath 
= cfg
->GetPath(); 
1152         cfg
->SetPath(wxT("/") + path
); 
1155     cfg
->Write(wxT("hcNavigPanel"), m_Cfg
.navig_on
); 
1156     cfg
->Write(wxT("hcSashPos"), (long)m_Cfg
.sashpos
); 
1158     //  Don't write if iconized as this would make the window 
1159     //  disappear next time it is shown! 
1160     cfg
->Write(wxT("hcX"), (long)m_Cfg
.x
); 
1161     cfg
->Write(wxT("hcY"), (long)m_Cfg
.y
); 
1162     cfg
->Write(wxT("hcW"), (long)m_Cfg
.w
); 
1163     cfg
->Write(wxT("hcH"), (long)m_Cfg
.h
); 
1165     cfg
->Write(wxT("hcFixedFace"), m_FixedFace
); 
1166     cfg
->Write(wxT("hcNormalFace"), m_NormalFace
); 
1167     cfg
->Write(wxT("hcBaseFontSize"), (long)m_FontSize
); 
1172         int cnt 
= m_BookmarksNames
.GetCount(); 
1175         cfg
->Write(wxT("hcBookmarksCnt"), (long)cnt
); 
1176         for (i 
= 0; i 
< cnt
; i
++) 
1178             val
.Printf(wxT("hcBookmark_%i"), i
); 
1179             cfg
->Write(val
, m_BookmarksNames
[i
]); 
1180             val
.Printf(wxT("hcBookmark_%i_url"), i
); 
1181             cfg
->Write(val
, m_BookmarksPages
[i
]); 
1186         m_HtmlWin
->WriteCustomization(cfg
); 
1188     if (path 
!= wxEmptyString
) 
1189         cfg
->SetPath(oldpath
); 
1191 #endif // wxUSE_CONFIG 
1193 static void SetFontsToHtmlWin(wxHtmlWindow 
*win
, const wxString
& scalf
, const wxString
& fixf
, int size
) 
1196     f_sizes
[0] = int(size 
* 0.6); 
1197     f_sizes
[1] = int(size 
* 0.8); 
1199     f_sizes
[3] = int(size 
* 1.2); 
1200     f_sizes
[4] = int(size 
* 1.4); 
1201     f_sizes
[5] = int(size 
* 1.6); 
1202     f_sizes
[6] = int(size 
* 1.8); 
1204     win
->SetFonts(scalf
, fixf
, f_sizes
); 
1207 class wxHtmlHelpWindowOptionsDialog 
: public wxDialog
 
1210     wxComboBox 
*NormalFont
, *FixedFont
; 
1211     wxSpinCtrl 
*FontSize
; 
1212     wxHtmlWindow 
*TestWin
; 
1214     wxHtmlHelpWindowOptionsDialog(wxWindow 
*parent
) 
1215         : wxDialog(parent
, wxID_ANY
, wxString(_("Help Browser Options"))) 
1217         wxBoxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
1218         wxFlexGridSizer 
*sizer 
= new wxFlexGridSizer(2, 3, 2, 5); 
1220         sizer
->Add(new wxStaticText(this, wxID_ANY
, _("Normal font:"))); 
1221         sizer
->Add(new wxStaticText(this, wxID_ANY
, _("Fixed font:"))); 
1222         sizer
->Add(new wxStaticText(this, wxID_ANY
, _("Font size:"))); 
1224         sizer
->Add(NormalFont 
= new wxComboBox(this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, 
1225                       wxSize(200, wxDefaultCoord
), 
1226                       0, NULL
, wxCB_DROPDOWN 
| wxCB_READONLY
)); 
1228         sizer
->Add(FixedFont 
= new wxComboBox(this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, 
1229                       wxSize(200, wxDefaultCoord
), 
1230                       0, NULL
, wxCB_DROPDOWN 
| wxCB_READONLY
)); 
1232         sizer
->Add(FontSize 
= new wxSpinCtrl(this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, 
1233                       wxDefaultSize
, wxSP_ARROW_KEYS
, 2, 100, 2, wxT("wxSpinCtrl"))); 
1235         topsizer
->Add(sizer
, 0, wxLEFT
|wxRIGHT
|wxTOP
, 10); 
1237         topsizer
->Add(new wxStaticText(this, wxID_ANY
, _("Preview:")), 
1238                         0, wxLEFT 
| wxTOP
, 10); 
1240         topsizer
->AddSpacer(5); 
1242         topsizer
->Add(TestWin 
= new wxHtmlWindow(this, wxID_ANY
, wxDefaultPosition
, wxSize(20, 150), 
1243                                                  wxHW_SCROLLBAR_AUTO
|wxBORDER_THEME
), 
1244                         1, wxEXPAND 
| wxLEFT 
| wxRIGHT
, 10); 
1246         wxBoxSizer 
*sizer2 
= new wxBoxSizer(wxHORIZONTAL
); 
1248         sizer2
->Add(ok 
= new wxButton(this, wxID_OK
), 0, wxALL
, 10); 
1250         sizer2
->Add(new wxButton(this, wxID_CANCEL
), 0, wxALL
, 10); 
1251         topsizer
->Add(sizer2
, 0, wxALIGN_RIGHT
); 
1254         topsizer
->Fit(this); 
1259     void UpdateTestWin() 
1262         SetFontsToHtmlWin(TestWin
, 
1263                           NormalFont
->GetStringSelection(), 
1264                           FixedFont
->GetStringSelection(), 
1265                           FontSize
->GetValue()); 
1267         wxString 
content(_("font size")); 
1269         content 
= wxT("<font size=-2>") + content 
+ wxT(" -2</font><br>") 
1270                   wxT("<font size=-1>") + content 
+ wxT(" -1</font><br>") 
1271                   wxT("<font size=+0>") + content 
+ wxT(" +0</font><br>") 
1272                   wxT("<font size=+1>") + content 
+ wxT(" +1</font><br>") 
1273                   wxT("<font size=+2>") + content 
+ wxT(" +2</font><br>") 
1274                   wxT("<font size=+3>") + content 
+ wxT(" +3</font><br>") 
1275                   wxT("<font size=+4>") + content 
+ wxT(" +4</font><br>") ; 
1277         content 
= wxString( wxT("<html><body><table><tr><td>") ) + 
1278                   _("Normal face<br>and <u>underlined</u>. ") + 
1279                   _("<i>Italic face.</i> ") + 
1280                   _("<b>Bold face.</b> ") + 
1281                   _("<b><i>Bold italic face.</i></b><br>") + 
1283                   wxString( wxT("</td><td><tt>") ) + 
1284                   _("Fixed size face.<br> <b>bold</b> <i>italic</i> ") + 
1285                   _("<b><i>bold italic <u>underlined</u></i></b><br>") + 
1287                   wxT("</tt></td></tr></table></body></html>"); 
1289         TestWin
->SetPage( content 
); 
1292     void OnUpdate(wxCommandEvent
& WXUNUSED(event
)) 
1296     void OnUpdateSpin(wxSpinEvent
& WXUNUSED(event
)) 
1301     DECLARE_EVENT_TABLE() 
1302     wxDECLARE_NO_COPY_CLASS(wxHtmlHelpWindowOptionsDialog
); 
1305 BEGIN_EVENT_TABLE(wxHtmlHelpWindowOptionsDialog
, wxDialog
) 
1306     EVT_COMBOBOX(wxID_ANY
, wxHtmlHelpWindowOptionsDialog::OnUpdate
) 
1307     EVT_SPINCTRL(wxID_ANY
, wxHtmlHelpWindowOptionsDialog::OnUpdateSpin
) 
1310 void wxHtmlHelpWindow::OptionsDialog() 
1312     wxHtmlHelpWindowOptionsDialog 
dlg(this); 
1315     if (m_NormalFonts 
== NULL
) 
1317         m_NormalFonts 
= new wxArrayString(wxFontEnumerator::GetFacenames()); 
1318         m_NormalFonts
->Sort(); // ascending sort 
1320     if (m_FixedFonts 
== NULL
) 
1322         m_FixedFonts 
= new wxArrayString( 
1323                     wxFontEnumerator::GetFacenames(wxFONTENCODING_SYSTEM
, 
1324                     true /*enum fixed width only*/)); 
1325         m_FixedFonts
->Sort(); // ascending sort 
1328     // VS: We want to show the font that is actually used by wxHtmlWindow. 
1329     //     If customization dialog wasn't used yet, facenames are empty and 
1330     //     wxHtmlWindow uses default fonts -- let's find out what they 
1331     //     are so that we can pass them to the dialog: 
1332     if (m_NormalFace
.empty()) 
1334         wxFont 
fnt(m_FontSize
, wxSWISS
, wxNORMAL
, wxNORMAL
, false); 
1335         m_NormalFace 
= fnt
.GetFaceName(); 
1337     if (m_FixedFace
.empty()) 
1339         wxFont 
fnt(m_FontSize
, wxMODERN
, wxNORMAL
, wxNORMAL
, false); 
1340         m_FixedFace 
= fnt
.GetFaceName(); 
1343     for (i 
= 0; i 
< m_NormalFonts
->GetCount(); i
++) 
1344         dlg
.NormalFont
->Append((*m_NormalFonts
)[i
]); 
1345     for (i 
= 0; i 
< m_FixedFonts
->GetCount(); i
++) 
1346         dlg
.FixedFont
->Append((*m_FixedFonts
)[i
]); 
1347     if (!m_NormalFace
.empty()) 
1348         dlg
.NormalFont
->SetStringSelection(m_NormalFace
); 
1350         dlg
.NormalFont
->SetSelection(0); 
1351     if (!m_FixedFace
.empty()) 
1352         dlg
.FixedFont
->SetStringSelection(m_FixedFace
); 
1354         dlg
.FixedFont
->SetSelection(0); 
1355     dlg
.FontSize
->SetValue(m_FontSize
); 
1356     dlg
.UpdateTestWin(); 
1358     if (dlg
.ShowModal() == wxID_OK
) 
1360         m_NormalFace 
= dlg
.NormalFont
->GetStringSelection(); 
1361         m_FixedFace 
= dlg
.FixedFont
->GetStringSelection(); 
1362         m_FontSize 
= dlg
.FontSize
->GetValue(); 
1363         SetFontsToHtmlWin(m_HtmlWin
, m_NormalFace
, m_FixedFace
, m_FontSize
); 
1367 void wxHtmlHelpWindow::NotifyPageChanged() 
1369     if (m_UpdateContents 
&& m_PagesHash
) 
1371         wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1372         wxHtmlHelpHashData 
*ha 
= NULL
; 
1374             ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1378             bool olduc 
= m_UpdateContents
; 
1379             m_UpdateContents 
= false; 
1380             m_ContentsBox
->SelectItem(ha
->m_Id
); 
1381             m_ContentsBox
->EnsureVisible(ha
->m_Id
); 
1382             m_UpdateContents 
= olduc
; 
1392 void wxHtmlHelpWindow::OnToolbar(wxCommandEvent
& event
) 
1394     switch (event
.GetId()) 
1396         case wxID_HTML_BACK 
: 
1397             m_HtmlWin
->HistoryBack(); 
1398             NotifyPageChanged(); 
1401         case wxID_HTML_FORWARD 
: 
1402             m_HtmlWin
->HistoryForward(); 
1403             NotifyPageChanged(); 
1409                 wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1410                 wxHtmlHelpHashData 
*ha 
= NULL
; 
1412                     ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1413                 if (ha 
&& ha
->m_Index 
> 0) 
1415                     const wxHtmlHelpDataItem
& it 
= m_Data
->GetContentsArray()[ha
->m_Index 
- 1]; 
1416                     if (!it
.page
.empty()) 
1418                         m_HtmlWin
->LoadPage(it
.GetFullPath()); 
1419                         NotifyPageChanged(); 
1425         case wxID_HTML_UPNODE 
: 
1428                 wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1429                 wxHtmlHelpHashData 
*ha 
= NULL
; 
1431                     ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1432                 if (ha 
&& ha
->m_Index 
> 0) 
1435                         m_Data
->GetContentsArray()[ha
->m_Index
].level 
- 1; 
1436                     int ind 
= ha
->m_Index 
- 1; 
1438                     const wxHtmlHelpDataItem 
*it 
= 
1439                         &m_Data
->GetContentsArray()[ind
]; 
1440                     while (ind 
>= 0 && it
->level 
!= level
) 
1443                         it 
= &m_Data
->GetContentsArray()[ind
]; 
1447                         if (!it
->page
.empty()) 
1449                             m_HtmlWin
->LoadPage(it
->GetFullPath()); 
1450                             NotifyPageChanged(); 
1457         case wxID_HTML_DOWN 
: 
1460                 wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1461                 wxHtmlHelpHashData 
*ha 
= NULL
; 
1463                     ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1465                 const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
1466                 if (ha 
&& ha
->m_Index 
< (int)contents
.size() - 1) 
1468                     size_t idx 
= ha
->m_Index 
+ 1; 
1470                     while (contents
[idx
].GetFullPath() == page
) idx
++; 
1472                     if (!contents
[idx
].page
.empty()) 
1474                         m_HtmlWin
->LoadPage(contents
[idx
].GetFullPath()); 
1475                         NotifyPageChanged(); 
1481         case wxID_HTML_PANEL 
: 
1483                 if (! (m_Splitter 
&& m_NavigPan
)) 
1485                 if (m_Splitter
->IsSplit()) 
1487                     m_Cfg
.sashpos 
= m_Splitter
->GetSashPosition(); 
1488                     m_Splitter
->Unsplit(m_NavigPan
); 
1489                     m_Cfg
.navig_on 
= false; 
1495                     m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
1496                     m_Cfg
.navig_on 
= true; 
1501         case wxID_HTML_OPTIONS 
: 
1505         case wxID_HTML_BOOKMARKSADD 
: 
1510                 item 
= m_HtmlWin
->GetOpenedPageTitle(); 
1511                 url 
= m_HtmlWin
->GetOpenedPage(); 
1512                 if (item 
== wxEmptyString
) 
1513                     item 
= url
.AfterLast(wxT('/')); 
1514                 if (m_BookmarksPages
.Index(url
) == wxNOT_FOUND
) 
1516                     m_Bookmarks
->Append(item
); 
1517                     m_BookmarksNames
.Add(item
); 
1518                     m_BookmarksPages
.Add(url
); 
1523         case wxID_HTML_BOOKMARKSREMOVE 
: 
1528                 item 
= m_Bookmarks
->GetStringSelection(); 
1529                 pos 
= m_BookmarksNames
.Index(item
); 
1530                 if (pos 
!= wxNOT_FOUND
) 
1532                     m_BookmarksNames
.RemoveAt(pos
); 
1533                     m_BookmarksPages
.RemoveAt(pos
); 
1534                     pos 
= m_Bookmarks
->GetSelection(); 
1535                     wxASSERT_MSG( pos 
!= wxNOT_FOUND 
, wxT("Unknown bookmark position") ) ; 
1536                     m_Bookmarks
->Delete((unsigned int)pos
); 
1541 #if wxUSE_PRINTING_ARCHITECTURE 
1542         case wxID_HTML_PRINT 
: 
1544                 if (m_Printer 
== NULL
) 
1545                     m_Printer 
= new wxHtmlEasyPrinting(_("Help Printing"), this); 
1546                 if (!m_HtmlWin
->GetOpenedPage()) 
1548                     wxLogWarning(_("Cannot print empty page.")); 
1552                     m_Printer
->PrintFile(m_HtmlWin
->GetOpenedPage()); 
1558         case wxID_HTML_OPENFILE 
: 
1560                 wxString filemask 
= wxString( 
1561                     _("HTML files (*.html;*.htm)|*.html;*.htm|")) + 
1562                     _("Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|") + 
1563                     _("HTML Help Project (*.hhp)|*.hhp|") + 
1565                     _("Compressed HTML Help file (*.chm)|*.chm|") + 
1568                 wxString s 
= wxFileSelector(_("Open HTML document"), 
1573                                             wxFD_OPEN 
| wxFD_FILE_MUST_EXIST
, 
1577                     wxString ext 
= s
.Right(4).Lower(); 
1578                     if (ext 
== wxT(".zip") || ext 
== wxT(".htb") || 
1580                         ext 
== wxT(".chm") || 
1589                         m_HtmlWin
->LoadPage(s
); 
1596 void wxHtmlHelpWindow::OnContentsSel(wxTreeEvent
& event
) 
1598     wxHtmlHelpTreeItemData 
*pg
; 
1600     pg 
= (wxHtmlHelpTreeItemData
*) m_ContentsBox
->GetItemData(event
.GetItem()); 
1602     if (pg 
&& m_UpdateContents
) 
1604         const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
1605         m_UpdateContents 
= false; 
1606         if (!contents
[pg
->m_Id
].page
.empty()) 
1607             m_HtmlWin
->LoadPage(contents
[pg
->m_Id
].GetFullPath()); 
1608         m_UpdateContents 
= true; 
1612 void wxHtmlHelpWindow::OnIndexSel(wxCommandEvent
& WXUNUSED(event
)) 
1614     wxHtmlHelpMergedIndexItem 
*it 
= (wxHtmlHelpMergedIndexItem
*) 
1615         m_IndexList
->GetClientData(m_IndexList
->GetSelection()); 
1617         DisplayIndexItem(it
); 
1620 void wxHtmlHelpWindow::OnIndexFind(wxCommandEvent
& WXUNUSED(event
)) 
1625 void wxHtmlHelpWindow::DoIndexFind() 
1627     wxString sr 
= m_IndexText
->GetLineText(0); 
1629     if (sr 
== wxEmptyString
) 
1637         m_IndexList
->Clear(); 
1638         const wxHtmlHelpMergedIndex
& index 
= *m_mergedIndex
; 
1639         size_t cnt 
= index
.size(); 
1642         for (size_t i 
= 0; i 
< cnt
; i
++) 
1644             if (index
[i
].name
.Lower().find(sr
) != wxString::npos
) 
1646                 int pos 
= m_IndexList
->Append(index
[i
].name
, 
1647                                               (char*)(&index
[i
])); 
1651                     // don't automatically show topic selector if this 
1652                     // item points to multiple pages: 
1653                     if (index
[i
].items
.size() == 1) 
1655                         m_IndexList
->SetSelection(0); 
1656                         DisplayIndexItem(&index
[i
]); 
1660                 // if this is nested item of the index, show its parent(s) 
1661                 // as well, otherwise it would not be clear what entry is 
1663                 wxHtmlHelpMergedIndexItem 
*parent 
= index
[i
].parent
; 
1667                         (index
.Index(*(wxHtmlHelpMergedIndexItem
*)m_IndexList
->GetClientData(pos
-1))) < index
.Index(*parent
)) 
1669                         m_IndexList
->Insert(parent
->name
, 
1670                                             pos
, (char*)parent
); 
1671                         parent 
= parent
->parent
; 
1676                 // finally, it the item we just added is itself a parent for 
1677                 // other items, show them as well, because they are refinements 
1678                 // of the displayed index entry (i.e. it is implicitly contained 
1679                 // in them: "foo" with parent "bar" reads as "bar, foo"): 
1680                 int level 
= index
[i
].items
[0]->level
; 
1682                 while (i 
< cnt 
&& index
[i
].items
[0]->level 
> level
) 
1684                     m_IndexList
->Append(index
[i
].name
, (char*)(&index
[i
])); 
1692         cnttext
.Printf(_("%i of %i"), displ
, cnt
); 
1693         m_IndexCountInfo
->SetLabel(cnttext
); 
1695         m_IndexText
->SetSelection(0, sr
.length()); 
1696         m_IndexText
->SetFocus(); 
1700 void wxHtmlHelpWindow::OnIndexAll(wxCommandEvent
& WXUNUSED(event
)) 
1705 void wxHtmlHelpWindow::DoIndexAll() 
1709     m_IndexList
->Clear(); 
1710     const wxHtmlHelpMergedIndex
& index 
= *m_mergedIndex
; 
1711     size_t cnt 
= index
.size(); 
1714     for (size_t i 
= 0; i 
< cnt
; i
++) 
1716         m_IndexList
->Append(index
[i
].name
, (char*)(&index
[i
])); 
1719             // don't automatically show topic selector if this 
1720             // item points to multiple pages: 
1721             if (index
[i
].items
.size() == 1) 
1723                 DisplayIndexItem(&index
[i
]); 
1730     cnttext
.Printf(_("%i of %i"), cnt
, cnt
); 
1731     m_IndexCountInfo
->SetLabel(cnttext
); 
1734 void wxHtmlHelpWindow::OnSearchSel(wxCommandEvent
& WXUNUSED(event
)) 
1736     wxHtmlHelpDataItem 
*it 
= (wxHtmlHelpDataItem
*) m_SearchList
->GetClientData(m_SearchList
->GetSelection()); 
1739         if (!it
->page
.empty()) 
1740             m_HtmlWin
->LoadPage(it
->GetFullPath()); 
1741         NotifyPageChanged(); 
1745 void wxHtmlHelpWindow::OnSearch(wxCommandEvent
& WXUNUSED(event
)) 
1747     wxString sr 
= m_SearchText
->GetLineText(0); 
1750         KeywordSearch(sr
, wxHELP_SEARCH_ALL
); 
1753 void wxHtmlHelpWindow::OnBookmarksSel(wxCommandEvent
& WXUNUSED(event
)) 
1755     wxString str 
= m_Bookmarks
->GetStringSelection(); 
1756     int idx 
= m_BookmarksNames
.Index(str
); 
1757     if (!str
.empty() && str 
!= _("(bookmarks)") && idx 
!= wxNOT_FOUND
) 
1759        m_HtmlWin
->LoadPage(m_BookmarksPages
[(size_t)idx
]); 
1760        NotifyPageChanged(); 
1764 void wxHtmlHelpWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
1769 #endif // wxUSE_WXHTML_HELP