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 100 
  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 //-------------------------------------------------------------------------- 
 107 DEFINE_EVENT_TYPE(wxEVT_COMMAND_HTMLWINDOW_URL_CLICKED
) 
 108 IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindowEvent
, wxNotifyEvent
) 
 110 class wxHtmlHelpHtmlWindow 
: public wxHtmlWindow
 
 113         wxHtmlHelpHtmlWindow(wxHtmlHelpWindow 
*win
, wxWindow 
*parent
) 
 114             : wxHtmlWindow(parent
), m_Window(win
) 
 119         virtual void OnLinkClicked(const wxHtmlLinkInfo
& link
) 
 121             wxHtmlWindowEvent 
event(wxEVT_COMMAND_HTMLWINDOW_URL_CLICKED
, GetId()); 
 122             event
.SetURL(link
.GetHref()); 
 123             if (!ProcessEvent(event
)) 
 125                 wxHtmlWindow::OnLinkClicked(link
); 
 127             const wxMouseEvent 
*e 
= link
.GetEvent(); 
 128             if (e 
== NULL 
|| e
->LeftUp()) 
 129                 m_Window
->NotifyPageChanged(); 
 132         // Returns full location with anchor (helper) 
 133         static wxString 
GetOpenedPageWithAnchor(wxHtmlWindow 
*win
) 
 136                 return wxEmptyString
; 
 138             wxString an 
= win
->GetOpenedAnchor(); 
 139             wxString pg 
= win
->GetOpenedPage(); 
 149         wxHtmlHelpWindow 
*m_Window
; 
 151     DECLARE_NO_COPY_CLASS(wxHtmlHelpHtmlWindow
) 
 155 //--------------------------------------------------------------------------- 
 156 // wxHtmlHelpWindow::m_mergedIndex 
 157 //--------------------------------------------------------------------------- 
 159 WX_DEFINE_ARRAY_PTR(const wxHtmlHelpDataItem
*, wxHtmlHelpDataItemPtrArray
); 
 161 struct wxHtmlHelpMergedIndexItem
 
 163     wxHtmlHelpMergedIndexItem 
*parent
; 
 165     wxHtmlHelpDataItemPtrArray items
; 
 168 WX_DECLARE_OBJARRAY(wxHtmlHelpMergedIndexItem
, wxHtmlHelpMergedIndex
); 
 169 #include "wx/arrimpl.cpp" 
 170 WX_DEFINE_OBJARRAY(wxHtmlHelpMergedIndex
) 
 172 void wxHtmlHelpWindow::UpdateMergedIndex() 
 174     delete m_mergedIndex
; 
 175     m_mergedIndex 
= new wxHtmlHelpMergedIndex
; 
 176     wxHtmlHelpMergedIndex
& merged 
= *m_mergedIndex
; 
 178     const wxHtmlHelpDataItems
& items 
= m_Data
->GetIndexArray(); 
 179     size_t len 
= items
.size(); 
 181     wxHtmlHelpMergedIndexItem 
*history
[128] = {NULL
}; 
 183     for (size_t i 
= 0; i 
< len
; i
++) 
 185         const wxHtmlHelpDataItem
& item 
= items
[i
]; 
 186         wxASSERT_MSG( item
.level 
< 128, _T("nested index entries too deep") ); 
 188         if (history
[item
.level
] && 
 189             history
[item
.level
]->items
[0]->name 
== item
.name
) 
 191             // same index entry as previous one, update list of items 
 192             history
[item
.level
]->items
.Add(&item
); 
 197             wxHtmlHelpMergedIndexItem 
*mi 
= new wxHtmlHelpMergedIndexItem(); 
 198             mi
->name 
= item
.GetIndentedName(); 
 199             mi
->items
.Add(&item
); 
 200             mi
->parent 
= (item
.level 
== 0) ? NULL 
: history
[item
.level 
- 1]; 
 201             history
[item
.level
] = mi
; 
 207 //--------------------------------------------------------------------------- 
 209 //--------------------------------------------------------------------------- 
 211 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpWindow
, wxWindow
) 
 213 BEGIN_EVENT_TABLE(wxHtmlHelpWindow
, wxWindow
) 
 214     EVT_TOOL_RANGE(wxID_HTML_PANEL
, wxID_HTML_OPTIONS
, wxHtmlHelpWindow::OnToolbar
) 
 215     EVT_BUTTON(wxID_HTML_BOOKMARKSREMOVE
, wxHtmlHelpWindow::OnToolbar
) 
 216     EVT_BUTTON(wxID_HTML_BOOKMARKSADD
, wxHtmlHelpWindow::OnToolbar
) 
 217     EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL
, wxHtmlHelpWindow::OnContentsSel
) 
 218     EVT_LISTBOX(wxID_HTML_INDEXLIST
, wxHtmlHelpWindow::OnIndexSel
) 
 219     EVT_LISTBOX(wxID_HTML_SEARCHLIST
, wxHtmlHelpWindow::OnSearchSel
) 
 220     EVT_BUTTON(wxID_HTML_SEARCHBUTTON
, wxHtmlHelpWindow::OnSearch
) 
 221     EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT
, wxHtmlHelpWindow::OnSearch
) 
 222     EVT_BUTTON(wxID_HTML_INDEXBUTTON
, wxHtmlHelpWindow::OnIndexFind
) 
 223     EVT_TEXT_ENTER(wxID_HTML_INDEXTEXT
, wxHtmlHelpWindow::OnIndexFind
) 
 224     EVT_BUTTON(wxID_HTML_INDEXBUTTONALL
, wxHtmlHelpWindow::OnIndexAll
) 
 225     EVT_COMBOBOX(wxID_HTML_BOOKMARKSLIST
, wxHtmlHelpWindow::OnBookmarksSel
) 
 226     EVT_SIZE(wxHtmlHelpWindow::OnSize
) 
 229 wxHtmlHelpWindow::wxHtmlHelpWindow(wxWindow
* parent
, wxWindowID id
, 
 232                                     int style
, int helpStyle
, wxHtmlHelpData
* data
) 
 235     Create(parent
, id
, pos
, size
, style
, helpStyle
); 
 238 void wxHtmlHelpWindow::Init(wxHtmlHelpData
* data
) 
 243         m_DataCreated 
= false; 
 247         m_Data 
= new wxHtmlHelpData(); 
 248         m_DataCreated 
= true; 
 255     m_ContentsBox 
= NULL
; 
 257     m_IndexButton 
= NULL
; 
 258     m_IndexButtonAll 
= NULL
; 
 261     m_SearchButton 
= NULL
; 
 263     m_SearchChoice 
= NULL
; 
 264     m_IndexCountInfo 
= NULL
; 
 267     m_NavigNotebook 
= NULL
; 
 270     m_SearchCaseSensitive 
= NULL
; 
 271     m_SearchWholeWords 
= NULL
; 
 273     m_mergedIndex 
= NULL
; 
 276     m_ConfigRoot 
= wxEmptyString
; 
 278     m_Cfg
.x 
= m_Cfg
.y 
= wxDefaultCoord
; 
 282     m_Cfg
.navig_on 
= true; 
 284     m_NormalFonts 
= m_FixedFonts 
= NULL
; 
 285     m_NormalFace 
= m_FixedFace 
= wxEmptyString
; 
 292 #if wxUSE_PRINTING_ARCHITECTURE 
 297     m_UpdateContents 
= true; 
 299     m_helpController 
= (wxHtmlHelpController
*) NULL
; 
 302 // Create: builds the GUI components. 
 303 // with the style flag it's possible to toggle the toolbar, contents, index and search 
 305 // m_HtmlWin will *always* be created, but it's important to realize that 
 306 // m_ContentsBox, m_IndexList, m_SearchList, m_SearchButton, m_SearchText and 
 307 // m_SearchButton may be NULL. 
 308 // moreover, if no contents, index or searchpage is needed, m_Splitter and 
 309 // m_NavigPan will be NULL too (with m_HtmlWin directly connected to the frame) 
 311 bool wxHtmlHelpWindow::Create(wxWindow
* parent
, wxWindowID id
, 
 312                              const wxPoint
& pos
, const wxSize
& size
, 
 313                              int style
, int helpStyle
) 
 315     m_hfStyle 
= helpStyle
; 
 317     wxImageList 
*ContentsImageList 
= new wxImageList(16, 16); 
 318     ContentsImageList
->Add(wxArtProvider::GetIcon(wxART_HELP_BOOK
, 
 321     ContentsImageList
->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER
, 
 324     ContentsImageList
->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE
, 
 328     // Do the config in two steps. We read the HtmlWindow customization after we 
 329     // create the window. 
 331         ReadCustomization(m_Config
, m_ConfigRoot
); 
 333     wxWindow::Create(parent
, id
, pos
, size
, style
, wxT("wxHtmlHelp")); 
 335     SetHelpText(_("Displays help as you browse the books on the left.")); 
 337     GetPosition(&m_Cfg
.x
, &m_Cfg
.y
); 
 339     int notebook_page 
= 0; 
 341     // The sizer for the whole top-level window. 
 342     wxSizer 
*topWindowSizer 
= new wxBoxSizer(wxVERTICAL
); 
 343     SetSizer(topWindowSizer
); 
 348     if (helpStyle 
& (wxHF_TOOLBAR 
| wxHF_FLAT_TOOLBAR
)) 
 350         wxToolBar 
*toolBar 
= new wxToolBar(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 
 351                                            wxNO_BORDER 
| wxTB_HORIZONTAL 
| 
 352                                            wxTB_DOCKABLE 
| wxTB_NODIVIDER 
| 
 353                                            (helpStyle 
& wxHF_FLAT_TOOLBAR 
? wxTB_FLAT 
: 0)); 
 354         toolBar
->SetMargins( 2, 2 ); 
 355         AddToolbarButtons(toolBar
, helpStyle
); 
 357         topWindowSizer
->Add(toolBar
, 0, wxEXPAND
); 
 360 #endif //wxUSE_TOOLBAR 
 362     wxSizer 
*navigSizer 
= NULL
; 
 364     if (helpStyle 
& (wxHF_CONTENTS 
| wxHF_INDEX 
| wxHF_SEARCH
)) 
 366         // traditional help controller; splitter window with html page on the 
 367         // right and a notebook containing various pages on the left 
 368         m_Splitter 
= new wxSplitterWindow(this); 
 370         topWindowSizer
->Add(m_Splitter
, 1, wxEXPAND
); 
 372         m_HtmlWin 
= new wxHtmlHelpHtmlWindow(this, m_Splitter
); 
 373         m_NavigPan 
= new wxPanel(m_Splitter
, wxID_ANY
); 
 374         m_NavigNotebook 
= new wxNotebook(m_NavigPan
, wxID_HTML_NOTEBOOK
, 
 375                                          wxDefaultPosition
, wxDefaultSize
); 
 377         navigSizer 
= new wxBoxSizer(wxVERTICAL
); 
 378         navigSizer
->Add(m_NavigNotebook
, 1, wxEXPAND
); 
 380         m_NavigPan
->SetSizer(navigSizer
); 
 384         // only html window, no notebook with index,contents etc 
 385         m_HtmlWin 
= new wxHtmlWindow(this); 
 386         topWindowSizer
->Add(m_HtmlWin
, 1, wxEXPAND
); 
 390         m_HtmlWin
->ReadCustomization(m_Config
, m_ConfigRoot
); 
 392     // contents tree panel? 
 393     if ( helpStyle 
& wxHF_CONTENTS 
) 
 395         wxWindow 
*dummy 
= new wxPanel(m_NavigNotebook
, wxID_HTML_INDEXPAGE
); 
 396         wxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
 398         topsizer
->Add(0, 10); 
 400         dummy
->SetSizer(topsizer
); 
 402         if ( helpStyle 
& wxHF_BOOKMARKS 
) 
 404             m_Bookmarks 
= new wxComboBox(dummy
, wxID_HTML_BOOKMARKSLIST
, 
 406                                          wxDefaultPosition
, wxDefaultSize
, 
 407                                          0, NULL
, wxCB_READONLY 
| wxCB_SORT
); 
 408             m_Bookmarks
->Append(_("(bookmarks)")); 
 409             for (unsigned i 
= 0; i 
< m_BookmarksNames
.GetCount(); i
++) 
 410                 m_Bookmarks
->Append(m_BookmarksNames
[i
]); 
 411             m_Bookmarks
->SetSelection(0); 
 413             wxBitmapButton 
*bmpbt1
, *bmpbt2
; 
 414             bmpbt1 
= new wxBitmapButton(dummy
, wxID_HTML_BOOKMARKSADD
, 
 415                                  wxArtProvider::GetBitmap(wxART_ADD_BOOKMARK
, 
 417             bmpbt2 
= new wxBitmapButton(dummy
, wxID_HTML_BOOKMARKSREMOVE
, 
 418                                  wxArtProvider::GetBitmap(wxART_DEL_BOOKMARK
, 
 421             bmpbt1
->SetToolTip(_("Add current page to bookmarks")); 
 422             bmpbt2
->SetToolTip(_("Remove current page from bookmarks")); 
 423 #endif // wxUSE_TOOLTIPS 
 425             wxSizer 
*sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
 427             sizer
->Add(m_Bookmarks
, 1, wxALIGN_CENTRE_VERTICAL 
| wxRIGHT
, 5); 
 428             sizer
->Add(bmpbt1
, 0, wxALIGN_CENTRE_VERTICAL 
| wxRIGHT
, 2); 
 429             sizer
->Add(bmpbt2
, 0, wxALIGN_CENTRE_VERTICAL
, 0); 
 431             topsizer
->Add(sizer
, 0, wxEXPAND 
| wxLEFT 
| wxBOTTOM 
| wxRIGHT
, 10); 
 434         m_ContentsBox 
= new wxTreeCtrl(dummy
, wxID_HTML_TREECTRL
, 
 435                                        wxDefaultPosition
, wxDefaultSize
, 
 438                                        wxTR_HAS_BUTTONS 
| wxTR_HIDE_ROOT 
| 
 442                                        wxTR_HAS_BUTTONS 
| wxTR_HIDE_ROOT 
| 
 447         m_ContentsBox
->AssignImageList(ContentsImageList
); 
 449         topsizer
->Add(m_ContentsBox
, 1, 
 450                       wxEXPAND 
| wxLEFT 
| wxBOTTOM 
| wxRIGHT
, 
 453         m_NavigNotebook
->AddPage(dummy
, _("Contents")); 
 454         m_ContentsPage 
= notebook_page
++; 
 457     // index listbox panel? 
 458     if ( helpStyle 
& wxHF_INDEX 
) 
 460         wxWindow 
*dummy 
= new wxPanel(m_NavigNotebook
, wxID_HTML_INDEXPAGE
); 
 461         wxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
 463         dummy
->SetSizer(topsizer
); 
 465         m_IndexText 
= new wxTextCtrl(dummy
, wxID_HTML_INDEXTEXT
, wxEmptyString
, 
 466                                      wxDefaultPosition
, wxDefaultSize
, 
 468         m_IndexButton 
= new wxButton(dummy
, wxID_HTML_INDEXBUTTON
, _("Find")); 
 469         m_IndexButtonAll 
= new wxButton(dummy
, wxID_HTML_INDEXBUTTONALL
, 
 471         m_IndexCountInfo 
= new wxStaticText(dummy
, wxID_HTML_COUNTINFO
, 
 472                                             wxEmptyString
, wxDefaultPosition
, 
 474                                             wxALIGN_RIGHT 
| wxST_NO_AUTORESIZE
); 
 475         m_IndexList 
= new wxListBox(dummy
, wxID_HTML_INDEXLIST
, 
 476                                     wxDefaultPosition
, wxDefaultSize
, 
 477                                     0, NULL
, wxLB_SINGLE
); 
 480         m_IndexButton
->SetToolTip(_("Display all index items that contain given substring. Search is case insensitive.")); 
 481         m_IndexButtonAll
->SetToolTip(_("Show all items in index")); 
 482 #endif //wxUSE_TOOLTIPS 
 484         topsizer
->Add(m_IndexText
, 0, wxEXPAND 
| wxALL
, 10); 
 485         wxSizer 
*btsizer 
= new wxBoxSizer(wxHORIZONTAL
); 
 486         btsizer
->Add(m_IndexButton
, 0, wxRIGHT
, 2); 
 487         btsizer
->Add(m_IndexButtonAll
); 
 488         topsizer
->Add(btsizer
, 0, 
 489                       wxALIGN_RIGHT 
| wxLEFT 
| wxRIGHT 
| wxBOTTOM
, 10); 
 490         topsizer
->Add(m_IndexCountInfo
, 0, wxEXPAND 
| wxLEFT 
| wxRIGHT
, 2); 
 491         topsizer
->Add(m_IndexList
, 1, wxEXPAND 
| wxALL
, 2); 
 493         m_NavigNotebook
->AddPage(dummy
, _("Index")); 
 494         m_IndexPage 
= notebook_page
++; 
 497     // search list panel? 
 498     if ( helpStyle 
& wxHF_SEARCH 
) 
 500         wxWindow 
*dummy 
= new wxPanel(m_NavigNotebook
, wxID_HTML_INDEXPAGE
); 
 501         wxSizer 
*sizer 
= new wxBoxSizer(wxVERTICAL
); 
 503         dummy
->SetSizer(sizer
); 
 505         m_SearchText 
= new wxTextCtrl(dummy
, wxID_HTML_SEARCHTEXT
, 
 507                                       wxDefaultPosition
, wxDefaultSize
, 
 509         m_SearchChoice 
= new wxChoice(dummy
, wxID_HTML_SEARCHCHOICE
, 
 510                                       wxDefaultPosition
, wxSize(125,wxDefaultCoord
)); 
 511         m_SearchCaseSensitive 
= new wxCheckBox(dummy
, wxID_ANY
, _("Case sensitive")); 
 512         m_SearchWholeWords 
= new wxCheckBox(dummy
, wxID_ANY
, _("Whole words only")); 
 513         m_SearchButton 
= new wxButton(dummy
, wxID_HTML_SEARCHBUTTON
, _("Search")); 
 515         m_SearchButton
->SetToolTip(_("Search contents of help book(s) for all occurences of the text you typed above")); 
 516 #endif //wxUSE_TOOLTIPS 
 517         m_SearchList 
= new wxListBox(dummy
, wxID_HTML_SEARCHLIST
, 
 518                                      wxDefaultPosition
, wxDefaultSize
, 
 519                                      0, NULL
, wxLB_SINGLE
); 
 521         sizer
->Add(m_SearchText
, 0, wxEXPAND 
| wxALL
, 10); 
 522         sizer
->Add(m_SearchChoice
, 0, wxEXPAND 
| wxLEFT 
| wxRIGHT 
| wxBOTTOM
, 10); 
 523         sizer
->Add(m_SearchCaseSensitive
, 0, wxLEFT 
| wxRIGHT
, 10); 
 524         sizer
->Add(m_SearchWholeWords
, 0, wxLEFT 
| wxRIGHT
, 10); 
 525         sizer
->Add(m_SearchButton
, 0, wxALL 
| wxALIGN_RIGHT
, 8); 
 526         sizer
->Add(m_SearchList
, 1, wxALL 
| wxEXPAND
, 2); 
 528         m_NavigNotebook
->AddPage(dummy
, _("Search")); 
 529         m_SearchPage 
= notebook_page
; 
 538         navigSizer
->SetSizeHints(m_NavigPan
); 
 539         m_NavigPan
->Layout(); 
 543     if ( m_NavigPan 
&& m_Splitter 
) 
 545         m_Splitter
->SetMinimumPaneSize(20); 
 546         if ( m_Cfg
.navig_on 
) 
 547             m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 549         if ( m_Cfg
.navig_on 
) 
 552             m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 556             m_NavigPan
->Show(false); 
 557             m_Splitter
->Initialize(m_HtmlWin
); 
 561     // Reduce flicker by updating the splitter pane sizes before the 
 563     wxSizeEvent 
sizeEvent(GetSize(), GetId()); 
 564     ProcessEvent(sizeEvent
); 
 567         m_Splitter
->UpdateSize(); 
 572 wxHtmlHelpWindow::~wxHtmlHelpWindow() 
 574     delete m_mergedIndex
; 
 576     // PopEventHandler(); // wxhtmlhelpcontroller (not any more!) 
 579     if (m_NormalFonts
) delete m_NormalFonts
; 
 580     if (m_FixedFonts
) delete m_FixedFonts
; 
 583         WX_CLEAR_HASH_TABLE(*m_PagesHash
); 
 586 #if wxUSE_PRINTING_ARCHITECTURE 
 587     if (m_Printer
) delete m_Printer
; 
 591 void wxHtmlHelpWindow::SetController(wxHtmlHelpController
* controller
) 
 595     m_helpController 
= controller
; 
 596     m_Data 
= controller
->GetHelpData(); 
 597     m_DataCreated 
= false; 
 601 void wxHtmlHelpWindow::AddToolbarButtons(wxToolBar 
*toolBar
, int style
) 
 603     wxBitmap wpanelBitmap 
= 
 604         wxArtProvider::GetBitmap(wxART_HELP_SIDE_PANEL
, wxART_TOOLBAR
); 
 605     wxBitmap wbackBitmap 
= 
 606         wxArtProvider::GetBitmap(wxART_GO_BACK
, wxART_TOOLBAR
); 
 607     wxBitmap wforwardBitmap 
= 
 608         wxArtProvider::GetBitmap(wxART_GO_FORWARD
, wxART_TOOLBAR
); 
 609     wxBitmap wupnodeBitmap 
= 
 610         wxArtProvider::GetBitmap(wxART_GO_TO_PARENT
, wxART_TOOLBAR
); 
 612         wxArtProvider::GetBitmap(wxART_GO_UP
, wxART_TOOLBAR
); 
 613     wxBitmap wdownBitmap 
= 
 614         wxArtProvider::GetBitmap(wxART_GO_DOWN
, wxART_TOOLBAR
); 
 615     wxBitmap wopenBitmap 
= 
 616         wxArtProvider::GetBitmap(wxART_FILE_OPEN
, wxART_TOOLBAR
); 
 617     wxBitmap wprintBitmap 
= 
 618         wxArtProvider::GetBitmap(wxART_PRINT
, wxART_TOOLBAR
); 
 619     wxBitmap woptionsBitmap 
= 
 620         wxArtProvider::GetBitmap(wxART_HELP_SETTINGS
, wxART_TOOLBAR
); 
 622     wxASSERT_MSG( (wpanelBitmap
.Ok() && wbackBitmap
.Ok() && 
 623                    wforwardBitmap
.Ok() && wupnodeBitmap
.Ok() && 
 624                    wupBitmap
.Ok() && wdownBitmap
.Ok() && 
 625                    wopenBitmap
.Ok() && wprintBitmap
.Ok() && 
 626                    woptionsBitmap
.Ok()), 
 627                   wxT("One or more HTML help frame toolbar bitmap could not be loaded.")) ; 
 630     toolBar
->AddTool(wxID_HTML_PANEL
, wpanelBitmap
, wxNullBitmap
, 
 631                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 632                        _("Show/hide navigation panel")); 
 634     toolBar
->AddSeparator(); 
 635     toolBar
->AddTool(wxID_HTML_BACK
, wbackBitmap
, wxNullBitmap
, 
 636                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 638     toolBar
->AddTool(wxID_HTML_FORWARD
, wforwardBitmap
, wxNullBitmap
, 
 639                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 641     toolBar
->AddSeparator(); 
 643     toolBar
->AddTool(wxID_HTML_UPNODE
, wupnodeBitmap
, wxNullBitmap
, 
 644                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 645                        _("Go one level up in document hierarchy")); 
 646     toolBar
->AddTool(wxID_HTML_UP
, wupBitmap
, wxNullBitmap
, 
 647                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 649     toolBar
->AddTool(wxID_HTML_DOWN
, wdownBitmap
, wxNullBitmap
, 
 650                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 653     if ((style 
& wxHF_PRINT
) || (style 
& wxHF_OPEN_FILES
)) 
 654         toolBar
->AddSeparator(); 
 656     if (style 
& wxHF_OPEN_FILES
) 
 657         toolBar
->AddTool(wxID_HTML_OPENFILE
, wopenBitmap
, wxNullBitmap
, 
 658                            false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 659                            _("Open HTML document")); 
 661 #if wxUSE_PRINTING_ARCHITECTURE 
 662     if (style 
& wxHF_PRINT
) 
 663         toolBar
->AddTool(wxID_HTML_PRINT
, wprintBitmap
, wxNullBitmap
, 
 664                            false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 665                            _("Print this page")); 
 668     toolBar
->AddSeparator(); 
 669     toolBar
->AddTool(wxID_HTML_OPTIONS
, woptionsBitmap
, wxNullBitmap
, 
 670                        false, wxDefaultCoord
, wxDefaultCoord
, (wxObject 
*) NULL
, 
 671                        _("Display options dialog")); 
 673     // Allow application to add custom buttons 
 674     wxHtmlHelpFrame
* parentFrame 
= wxDynamicCast(GetParent(), wxHtmlHelpFrame
); 
 675     wxHtmlHelpDialog
* parentDialog 
= wxDynamicCast(GetParent(), wxHtmlHelpDialog
); 
 677         parentFrame
->AddToolbarButtons(toolBar
, style
); 
 679         parentDialog
->AddToolbarButtons(toolBar
, style
); 
 681 #endif //wxUSE_TOOLBAR 
 684 bool wxHtmlHelpWindow::Display(const wxString
& x
) 
 686     wxString url 
= m_Data
->FindPageByName(x
); 
 689         m_HtmlWin
->LoadPage(url
); 
 697 bool wxHtmlHelpWindow::Display(const int id
) 
 699     wxString url 
= m_Data
->FindPageById(id
); 
 702         m_HtmlWin
->LoadPage(url
); 
 710 bool wxHtmlHelpWindow::DisplayContents() 
 715     if (!m_Splitter
->IsSplit()) 
 719         m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 720         m_Cfg
.navig_on 
= true; 
 723     m_NavigNotebook
->SetSelection(m_ContentsPage
); 
 725     if (m_Data
->GetBookRecArray().GetCount() > 0) 
 727         wxHtmlBookRecord
& book 
= m_Data
->GetBookRecArray()[0]; 
 728         if (!book
.GetStart().empty()) 
 729             m_HtmlWin
->LoadPage(book
.GetFullPath(book
.GetStart())); 
 735 bool wxHtmlHelpWindow::DisplayIndex() 
 740     if (!m_Splitter
->IsSplit()) 
 744         m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 747     m_NavigNotebook
->SetSelection(m_IndexPage
); 
 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 void wxHtmlHelpWindow::DisplayIndexItem(const wxHtmlHelpMergedIndexItem 
*it
) 
 761     if (it
->items
.size() == 1) 
 763         if (!it
->items
[0]->page
.empty()) 
 765             m_HtmlWin
->LoadPage(it
->items
[0]->GetFullPath()); 
 771         wxBusyCursor busy_cursor
; 
 773         // more pages associated with this index item -- let the user choose 
 774         // which one she/he wants from a list: 
 776         size_t len 
= it
->items
.size(); 
 777         for (size_t i 
= 0; i 
< len
; i
++) 
 779             wxString page 
= it
->items
[i
]->page
; 
 780             // try to find page's title in contents: 
 781             const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
 782             size_t clen 
= contents
.size(); 
 783             for (size_t j 
= 0; j 
< clen
; j
++) 
 785                 if (contents
[j
].page 
== page
) 
 787                     page 
= contents
[j
].name
; 
 794         wxSingleChoiceDialog 
dlg(this, 
 795                                  _("Please choose the page to display:"), 
 797                                  arr
, NULL
, wxCHOICEDLG_STYLE 
& ~wxCENTRE
); 
 798         if (dlg
.ShowModal() == wxID_OK
) 
 800             m_HtmlWin
->LoadPage(it
->items
[dlg
.GetSelection()]->GetFullPath()); 
 806 bool wxHtmlHelpWindow::KeywordSearch(const wxString
& keyword
, 
 807                                     wxHelpSearchMode mode
) 
 809     if (mode 
== wxHELP_SEARCH_ALL
) 
 811         if ( !(m_SearchList 
&& 
 812                m_SearchButton 
&& m_SearchText 
&& m_SearchChoice
) ) 
 815     else if (mode 
== wxHELP_SEARCH_INDEX
) 
 817         if ( !(m_IndexList 
&& 
 818                m_IndexButton 
&& m_IndexButtonAll 
&& m_IndexText
) ) 
 824     wxString book 
= wxEmptyString
; 
 826     if (!m_Splitter
->IsSplit()) 
 830         m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
 833     if (mode 
== wxHELP_SEARCH_ALL
) 
 835         m_NavigNotebook
->SetSelection(m_SearchPage
); 
 836         m_SearchList
->Clear(); 
 837         m_SearchText
->SetValue(keyword
); 
 838         m_SearchButton
->Disable(); 
 840         if (m_SearchChoice
->GetSelection() != 0) 
 841             book 
= m_SearchChoice
->GetStringSelection(); 
 843         wxHtmlSearchStatus 
status(m_Data
, keyword
, 
 844                                   m_SearchCaseSensitive
->GetValue(), 
 845                                   m_SearchWholeWords
->GetValue(), 
 848 #if wxUSE_PROGRESSDLG 
 849         wxProgressDialog 
progress(_("Searching..."), 
 850                                   _("No matching page found yet"), 
 851                                   status
.GetMaxIndex(), this, 
 852                                   wxPD_APP_MODAL 
| wxPD_CAN_ABORT 
| wxPD_AUTO_HIDE
); 
 856         while (status
.IsActive()) 
 858             curi 
= status
.GetCurIndex(); 
 860 #if wxUSE_PROGRESSDLG 
 861                 && !progress
.Update(curi
) 
 867                 foundstr
.Printf(_("Found %i matches"), ++foundcnt
); 
 868 #if wxUSE_PROGRESSDLG 
 869                 progress
.Update(status
.GetCurIndex(), foundstr
); 
 871                 m_SearchList
->Append(status
.GetName(), (void*)status
.GetCurItem()); 
 875         m_SearchButton
->Enable(); 
 876         m_SearchText
->SetSelection(0, keyword
.length()); 
 877         m_SearchText
->SetFocus(); 
 879     else if (mode 
== wxHELP_SEARCH_INDEX
) 
 881         m_NavigNotebook
->SetSelection(m_IndexPage
); 
 882         m_IndexList
->Clear(); 
 883         m_IndexButton
->Disable(); 
 884         m_IndexButtonAll
->Disable(); 
 885         m_IndexText
->SetValue(keyword
); 
 888         m_IndexButton
->Enable(); 
 889         m_IndexButtonAll
->Enable(); 
 890         foundcnt 
= m_IndexList
->GetCount(); 
 898                 wxFAIL_MSG( _T("unknown help search mode") ); 
 901             case wxHELP_SEARCH_ALL
: 
 903                 wxHtmlHelpDataItem 
*it 
= 
 904                     (wxHtmlHelpDataItem
*) m_SearchList
->GetClientData(0); 
 907                     m_HtmlWin
->LoadPage(it
->GetFullPath()); 
 913             case wxHELP_SEARCH_INDEX
: 
 915                 wxHtmlHelpMergedIndexItem
* it 
= 
 916                     (wxHtmlHelpMergedIndexItem
*) m_IndexList
->GetClientData(0); 
 918                     DisplayIndexItem(it
); 
 928 void wxHtmlHelpWindow::CreateContents() 
 935         WX_CLEAR_HASH_TABLE(*m_PagesHash
); 
 939     const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
 941     size_t cnt 
= contents
.size(); 
 943     m_PagesHash 
= new wxHashTable(wxKEY_STRING
, 2 * cnt
); 
 945     const int MAX_ROOTS 
= 64; 
 946     wxTreeItemId roots
[MAX_ROOTS
]; 
 947     // VS: this array holds information about whether we've set item icon at 
 948     //     given level. This is necessary because m_Data has a flat structure 
 949     //     and there's no way of recognizing if some item has subitems or not. 
 950     //     We set the icon later: when we find an item with level=n, we know 
 951     //     that the last item with level=n-1 was afolder with subitems, so we 
 952     //     set its icon accordingly 
 953     bool imaged
[MAX_ROOTS
]; 
 954     m_ContentsBox
->DeleteAllItems(); 
 956     roots
[0] = m_ContentsBox
->AddRoot(_("(Help)")); 
 959     for (size_t i 
= 0; i 
< cnt
; i
++) 
 961         wxHtmlHelpDataItem 
*it 
= &contents
[i
]; 
 965             if (m_hfStyle 
& wxHF_MERGE_BOOKS
) 
 966                 // VS: we don't want book nodes, books' content should 
 967                 //    appear under tree's root. This line will create a "fake" 
 968                 //    record about book node so that the rest of this look 
 969                 //    will believe there really _is_ a book node and will 
 974                 roots
[1] = m_ContentsBox
->AppendItem(roots
[0], 
 975                                          it
->name
, IMG_Book
, -1, 
 976                                          new wxHtmlHelpTreeItemData(i
)); 
 977                 m_ContentsBox
->SetItemBold(roots
[1], true); 
 981         // ...and their contents: 
 984             roots
[it
->level 
+ 1] = m_ContentsBox
->AppendItem( 
 985                                      roots
[it
->level
], it
->name
, IMG_Page
, 
 986                                      -1, new wxHtmlHelpTreeItemData(i
)); 
 987             imaged
[it
->level 
+ 1] = false; 
 990         m_PagesHash
->Put(it
->GetFullPath(), 
 991                          new wxHtmlHelpHashData(i
, roots
[it
->level 
+ 1])); 
 993         // Set the icon for the node one level up in the hierarchy, 
 994         // unless already done (see comment above imaged[] declaration) 
 995         if (!imaged
[it
->level
]) 
 997             int image 
= IMG_Folder
; 
 998             if (m_hfStyle 
& wxHF_ICONS_BOOK
) 
1000             else if (m_hfStyle 
& wxHF_ICONS_BOOK_CHAPTER
) 
1001                 image 
= (it
->level 
== 1) ? IMG_Book 
: IMG_Folder
; 
1002             m_ContentsBox
->SetItemImage(roots
[it
->level
], image
); 
1003             m_ContentsBox
->SetItemImage(roots
[it
->level
], image
, 
1004                                         wxTreeItemIcon_Selected
); 
1005             imaged
[it
->level
] = true; 
1010 void wxHtmlHelpWindow::CreateIndex() 
1015     m_IndexList
->Clear(); 
1017     size_t cnt 
= m_mergedIndex
->size(); 
1020     if (cnt 
> INDEX_IS_SMALL
) 
1021         cnttext
.Printf(_("%i of %i"), 0, cnt
); 
1023         cnttext
.Printf(_("%i of %i"), cnt
, cnt
); 
1024     m_IndexCountInfo
->SetLabel(cnttext
); 
1025     if (cnt 
> INDEX_IS_SMALL
) 
1028     for (size_t i 
= 0; i 
< cnt
; i
++) 
1029         m_IndexList
->Append((*m_mergedIndex
)[i
].name
, 
1030                             (char*)(&(*m_mergedIndex
)[i
])); 
1033 void wxHtmlHelpWindow::CreateSearch() 
1035     if (! (m_SearchList 
&& m_SearchChoice
)) 
1037     m_SearchList
->Clear(); 
1038     m_SearchChoice
->Clear(); 
1039     m_SearchChoice
->Append(_("Search in all books")); 
1040     const wxHtmlBookRecArray
& bookrec 
= m_Data
->GetBookRecArray(); 
1041     int i
, cnt 
= bookrec
.GetCount(); 
1042     for (i 
= 0; i 
< cnt
; i
++) 
1043         m_SearchChoice
->Append(bookrec
[i
].GetTitle()); 
1044     m_SearchChoice
->SetSelection(0); 
1047 void wxHtmlHelpWindow::RefreshLists() 
1049     // Update m_mergedIndex: 
1050     UpdateMergedIndex(); 
1051     // Update the controls 
1057 void wxHtmlHelpWindow::ReadCustomization(wxConfigBase 
*cfg
, const wxString
& path
) 
1062     if (path 
!= wxEmptyString
) 
1064         oldpath 
= cfg
->GetPath(); 
1065         cfg
->SetPath(_T("/") + path
); 
1068     m_Cfg
.navig_on 
= cfg
->Read(wxT("hcNavigPanel"), m_Cfg
.navig_on
) != 0; 
1069     m_Cfg
.sashpos 
= cfg
->Read(wxT("hcSashPos"), m_Cfg
.sashpos
); 
1070     m_Cfg
.x 
= cfg
->Read(wxT("hcX"), m_Cfg
.x
); 
1071     m_Cfg
.y 
= cfg
->Read(wxT("hcY"), m_Cfg
.y
); 
1072     m_Cfg
.w 
= cfg
->Read(wxT("hcW"), m_Cfg
.w
); 
1073     m_Cfg
.h 
= cfg
->Read(wxT("hcH"), m_Cfg
.h
); 
1075     m_FixedFace 
= cfg
->Read(wxT("hcFixedFace"), m_FixedFace
); 
1076     m_NormalFace 
= cfg
->Read(wxT("hcNormalFace"), m_NormalFace
); 
1077     m_FontSize 
= cfg
->Read(wxT("hcBaseFontSize"), m_FontSize
); 
1084         cnt 
= cfg
->Read(wxT("hcBookmarksCnt"), 0L); 
1087             m_BookmarksNames
.Clear(); 
1088             m_BookmarksPages
.Clear(); 
1091                 m_Bookmarks
->Clear(); 
1092                 m_Bookmarks
->Append(_("(bookmarks)")); 
1095             for (i 
= 0; i 
< cnt
; i
++) 
1097                 val
.Printf(wxT("hcBookmark_%i"), i
); 
1099                 m_BookmarksNames
.Add(s
); 
1100                 if (m_Bookmarks
) m_Bookmarks
->Append(s
); 
1101                 val
.Printf(wxT("hcBookmark_%i_url"), i
); 
1103                 m_BookmarksPages
.Add(s
); 
1109         m_HtmlWin
->ReadCustomization(cfg
); 
1111     if (path 
!= wxEmptyString
) 
1112         cfg
->SetPath(oldpath
); 
1115 void wxHtmlHelpWindow::WriteCustomization(wxConfigBase 
*cfg
, const wxString
& path
) 
1120     if (path 
!= wxEmptyString
) 
1122         oldpath 
= cfg
->GetPath(); 
1123         cfg
->SetPath(_T("/") + path
); 
1126     cfg
->Write(wxT("hcNavigPanel"), m_Cfg
.navig_on
); 
1127     cfg
->Write(wxT("hcSashPos"), (long)m_Cfg
.sashpos
); 
1129     //  Don't write if iconized as this would make the window 
1130     //  disappear next time it is shown! 
1131     cfg
->Write(wxT("hcX"), (long)m_Cfg
.x
); 
1132     cfg
->Write(wxT("hcY"), (long)m_Cfg
.y
); 
1133     cfg
->Write(wxT("hcW"), (long)m_Cfg
.w
); 
1134     cfg
->Write(wxT("hcH"), (long)m_Cfg
.h
); 
1136     cfg
->Write(wxT("hcFixedFace"), m_FixedFace
); 
1137     cfg
->Write(wxT("hcNormalFace"), m_NormalFace
); 
1138     cfg
->Write(wxT("hcBaseFontSize"), (long)m_FontSize
); 
1143         int cnt 
= m_BookmarksNames
.GetCount(); 
1146         cfg
->Write(wxT("hcBookmarksCnt"), (long)cnt
); 
1147         for (i 
= 0; i 
< cnt
; i
++) 
1149             val
.Printf(wxT("hcBookmark_%i"), i
); 
1150             cfg
->Write(val
, m_BookmarksNames
[i
]); 
1151             val
.Printf(wxT("hcBookmark_%i_url"), i
); 
1152             cfg
->Write(val
, m_BookmarksPages
[i
]); 
1157         m_HtmlWin
->WriteCustomization(cfg
); 
1159     if (path 
!= wxEmptyString
) 
1160         cfg
->SetPath(oldpath
); 
1163 static void SetFontsToHtmlWin(wxHtmlWindow 
*win
, const wxString
& scalf
, const wxString
& fixf
, int size
) 
1166     f_sizes
[0] = int(size 
* 0.6); 
1167     f_sizes
[1] = int(size 
* 0.8); 
1169     f_sizes
[3] = int(size 
* 1.2); 
1170     f_sizes
[4] = int(size 
* 1.4); 
1171     f_sizes
[5] = int(size 
* 1.6); 
1172     f_sizes
[6] = int(size 
* 1.8); 
1174     win
->SetFonts(scalf
, fixf
, f_sizes
); 
1177 class wxHtmlHelpWindowOptionsDialog 
: public wxDialog
 
1180     wxComboBox 
*NormalFont
, *FixedFont
; 
1181     wxSpinCtrl 
*FontSize
; 
1182     wxHtmlWindow 
*TestWin
; 
1184     wxHtmlHelpWindowOptionsDialog(wxWindow 
*parent
) 
1185         : wxDialog(parent
, wxID_ANY
, wxString(_("Help Browser Options"))) 
1187         wxBoxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
1188         wxFlexGridSizer 
*sizer 
= new wxFlexGridSizer(2, 3, 2, 5); 
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:"))); 
1194         sizer
->Add(NormalFont 
= new wxComboBox(this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, 
1195                       wxSize(200, wxDefaultCoord
), 
1196                       0, NULL
, wxCB_DROPDOWN 
| wxCB_READONLY
)); 
1198         sizer
->Add(FixedFont 
= new wxComboBox(this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, 
1199                       wxSize(200, wxDefaultCoord
), 
1200                       0, NULL
, wxCB_DROPDOWN 
| wxCB_READONLY
)); 
1202         sizer
->Add(FontSize 
= new wxSpinCtrl(this, wxID_ANY
)); 
1203         FontSize
->SetRange(2, 100); 
1205         topsizer
->Add(sizer
, 0, wxLEFT
|wxRIGHT
|wxTOP
, 10); 
1207         topsizer
->Add(new wxStaticText(this, wxID_ANY
, _("Preview:")), 
1208                         0, wxLEFT 
| wxTOP
, 10); 
1209         topsizer
->Add(TestWin 
= new wxHtmlWindow(this, wxID_ANY
, wxDefaultPosition
, wxSize(20, 150), 
1210                                                  wxHW_SCROLLBAR_AUTO 
| wxSUNKEN_BORDER
), 
1211                         1, wxEXPAND 
| wxLEFT
|wxTOP
|wxRIGHT
, 10); 
1213         wxBoxSizer 
*sizer2 
= new wxBoxSizer(wxHORIZONTAL
); 
1215         sizer2
->Add(ok 
= new wxButton(this, wxID_OK
), 0, wxALL
, 10); 
1217         sizer2
->Add(new wxButton(this, wxID_CANCEL
), 0, wxALL
, 10); 
1218         topsizer
->Add(sizer2
, 0, wxALIGN_RIGHT
); 
1221         topsizer
->Fit(this); 
1226     void UpdateTestWin() 
1229         SetFontsToHtmlWin(TestWin
, 
1230                           NormalFont
->GetStringSelection(), 
1231                           FixedFont
->GetStringSelection(), 
1232                           FontSize
->GetValue()); 
1234         wxString 
content(_("font size")); 
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>") ; 
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>") + 
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>") + 
1254                   _T("</tt></td></tr></table></body></html>"); 
1256         TestWin
->SetPage( content 
); 
1259     void OnUpdate(wxCommandEvent
& WXUNUSED(event
)) 
1263     void OnUpdateSpin(wxSpinEvent
& WXUNUSED(event
)) 
1268     DECLARE_EVENT_TABLE() 
1269     DECLARE_NO_COPY_CLASS(wxHtmlHelpWindowOptionsDialog
) 
1272 BEGIN_EVENT_TABLE(wxHtmlHelpWindowOptionsDialog
, wxDialog
) 
1273     EVT_COMBOBOX(wxID_ANY
, wxHtmlHelpWindowOptionsDialog::OnUpdate
) 
1274     EVT_SPINCTRL(wxID_ANY
, wxHtmlHelpWindowOptionsDialog::OnUpdateSpin
) 
1277 void wxHtmlHelpWindow::OptionsDialog() 
1279     wxHtmlHelpWindowOptionsDialog 
dlg(this); 
1282     if (m_NormalFonts 
== NULL
) 
1284         m_NormalFonts 
= new wxArrayString(wxFontEnumerator::GetFacenames()); 
1285         m_NormalFonts
->Sort(); // ascending sort 
1287     if (m_FixedFonts 
== NULL
) 
1289         m_FixedFonts 
= new wxArrayString( 
1290                     wxFontEnumerator::GetFacenames(wxFONTENCODING_SYSTEM
, 
1291                     true /*enum fixed width only*/)); 
1292         m_FixedFonts
->Sort(); // ascending sort 
1295     // VS: We want to show the font that is actually used by wxHtmlWindow. 
1296     //     If customization dialog wasn't used yet, facenames are empty and 
1297     //     wxHtmlWindow uses default fonts -- let's find out what they 
1298     //     are so that we can pass them to the dialog: 
1299     if (m_NormalFace
.empty()) 
1301         wxFont 
fnt(m_FontSize
, wxSWISS
, wxNORMAL
, wxNORMAL
, false); 
1302         m_NormalFace 
= fnt
.GetFaceName(); 
1304     if (m_FixedFace
.empty()) 
1306         wxFont 
fnt(m_FontSize
, wxMODERN
, wxNORMAL
, wxNORMAL
, false); 
1307         m_FixedFace 
= fnt
.GetFaceName(); 
1310     for (i 
= 0; i 
< m_NormalFonts
->GetCount(); i
++) 
1311         dlg
.NormalFont
->Append((*m_NormalFonts
)[i
]); 
1312     for (i 
= 0; i 
< m_FixedFonts
->GetCount(); i
++) 
1313         dlg
.FixedFont
->Append((*m_FixedFonts
)[i
]); 
1314     if (!m_NormalFace
.empty()) 
1315         dlg
.NormalFont
->SetStringSelection(m_NormalFace
); 
1317         dlg
.NormalFont
->SetSelection(0); 
1318     if (!m_FixedFace
.empty()) 
1319         dlg
.FixedFont
->SetStringSelection(m_FixedFace
); 
1321         dlg
.FixedFont
->SetSelection(0); 
1322     dlg
.FontSize
->SetValue(m_FontSize
); 
1323     dlg
.UpdateTestWin(); 
1325     if (dlg
.ShowModal() == wxID_OK
) 
1327         m_NormalFace 
= dlg
.NormalFont
->GetStringSelection(); 
1328         m_FixedFace 
= dlg
.FixedFont
->GetStringSelection(); 
1329         m_FontSize 
= dlg
.FontSize
->GetValue(); 
1330         SetFontsToHtmlWin(m_HtmlWin
, m_NormalFace
, m_FixedFace
, m_FontSize
); 
1334 void wxHtmlHelpWindow::NotifyPageChanged() 
1336     if (m_UpdateContents 
&& m_PagesHash
) 
1338         wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1339         wxHtmlHelpHashData 
*ha 
= NULL
; 
1341             ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1345             bool olduc 
= m_UpdateContents
; 
1346             m_UpdateContents 
= false; 
1347             m_ContentsBox
->SelectItem(ha
->m_Id
); 
1348             m_ContentsBox
->EnsureVisible(ha
->m_Id
); 
1349             m_UpdateContents 
= olduc
; 
1359 void wxHtmlHelpWindow::OnToolbar(wxCommandEvent
& event
) 
1361     switch (event
.GetId()) 
1363         case wxID_HTML_BACK 
: 
1364             m_HtmlWin
->HistoryBack(); 
1365             NotifyPageChanged(); 
1368         case wxID_HTML_FORWARD 
: 
1369             m_HtmlWin
->HistoryForward(); 
1370             NotifyPageChanged(); 
1376                 wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1377                 wxHtmlHelpHashData 
*ha 
= NULL
; 
1379                     ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1380                 if (ha 
&& ha
->m_Index 
> 0) 
1382                     const wxHtmlHelpDataItem
& it 
= m_Data
->GetContentsArray()[ha
->m_Index 
- 1]; 
1383                     if (!it
.page
.empty()) 
1385                         m_HtmlWin
->LoadPage(it
.GetFullPath()); 
1386                         NotifyPageChanged(); 
1392         case wxID_HTML_UPNODE 
: 
1395                 wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1396                 wxHtmlHelpHashData 
*ha 
= NULL
; 
1398                     ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1399                 if (ha 
&& ha
->m_Index 
> 0) 
1402                         m_Data
->GetContentsArray()[ha
->m_Index
].level 
- 1; 
1403                     int ind 
= ha
->m_Index 
- 1; 
1405                     const wxHtmlHelpDataItem 
*it 
= 
1406                         &m_Data
->GetContentsArray()[ind
]; 
1407                     while (ind 
>= 0 && it
->level 
!= level
) 
1410                         it 
= &m_Data
->GetContentsArray()[ind
]; 
1414                         if (!it
->page
.empty()) 
1416                             m_HtmlWin
->LoadPage(it
->GetFullPath()); 
1417                             NotifyPageChanged(); 
1424         case wxID_HTML_DOWN 
: 
1427                 wxString page 
= wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin
); 
1428                 wxHtmlHelpHashData 
*ha 
= NULL
; 
1430                     ha 
= (wxHtmlHelpHashData
*) m_PagesHash
->Get(page
); 
1432                 const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
1433                 if (ha 
&& ha
->m_Index 
< (int)contents
.size() - 1) 
1435                     size_t idx 
= ha
->m_Index 
+ 1; 
1437                     while (contents
[idx
].GetFullPath() == page
) idx
++; 
1439                     if (!contents
[idx
].page
.empty()) 
1441                         m_HtmlWin
->LoadPage(contents
[idx
].GetFullPath()); 
1442                         NotifyPageChanged(); 
1448         case wxID_HTML_PANEL 
: 
1450                 if (! (m_Splitter 
&& m_NavigPan
)) 
1452                 if (m_Splitter
->IsSplit()) 
1454                     m_Cfg
.sashpos 
= m_Splitter
->GetSashPosition(); 
1455                     m_Splitter
->Unsplit(m_NavigPan
); 
1456                     m_Cfg
.navig_on 
= false; 
1462                     m_Splitter
->SplitVertically(m_NavigPan
, m_HtmlWin
, m_Cfg
.sashpos
); 
1463                     m_Cfg
.navig_on 
= true; 
1468         case wxID_HTML_OPTIONS 
: 
1472         case wxID_HTML_BOOKMARKSADD 
: 
1477                 item 
= m_HtmlWin
->GetOpenedPageTitle(); 
1478                 url 
= m_HtmlWin
->GetOpenedPage(); 
1479                 if (item 
== wxEmptyString
) 
1480                     item 
= url
.AfterLast(wxT('/')); 
1481                 if (m_BookmarksPages
.Index(url
) == wxNOT_FOUND
) 
1483                     m_Bookmarks
->Append(item
); 
1484                     m_BookmarksNames
.Add(item
); 
1485                     m_BookmarksPages
.Add(url
); 
1490         case wxID_HTML_BOOKMARKSREMOVE 
: 
1495                 item 
= m_Bookmarks
->GetStringSelection(); 
1496                 pos 
= m_BookmarksNames
.Index(item
); 
1497                 if (pos 
!= wxNOT_FOUND
) 
1499                     m_BookmarksNames
.RemoveAt(pos
); 
1500                     m_BookmarksPages
.RemoveAt(pos
); 
1501                     pos 
= m_Bookmarks
->GetSelection(); 
1502                     wxASSERT_MSG( pos 
!= wxNOT_FOUND 
, wxT("Unknown bookmark position") ) ; 
1503                     m_Bookmarks
->Delete((unsigned int)pos
); 
1508 #if wxUSE_PRINTING_ARCHITECTURE 
1509         case wxID_HTML_PRINT 
: 
1511                 if (m_Printer 
== NULL
) 
1512                     m_Printer 
= new wxHtmlEasyPrinting(_("Help Printing"), this); 
1513                 if (!m_HtmlWin
->GetOpenedPage()) 
1514                     wxLogWarning(_("Cannot print empty page.")); 
1516                     m_Printer
->PrintFile(m_HtmlWin
->GetOpenedPage()); 
1521         case wxID_HTML_OPENFILE 
: 
1523                 wxString filemask 
= wxString( 
1524                     _("HTML files (*.html;*.htm)|*.html;*.htm|")) + 
1525                     _("Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|") + 
1526                     _("HTML Help Project (*.hhp)|*.hhp|") + 
1528                     _("Compressed HTML Help file (*.chm)|*.chm|") + 
1530                     _("All files (*.*)|*"); 
1531                 wxString s 
= wxFileSelector(_("Open HTML document"), 
1536                                             wxFD_OPEN 
| wxFD_FILE_MUST_EXIST
, 
1540                     wxString ext 
= s
.Right(4).Lower(); 
1541                     if (ext 
== _T(".zip") || ext 
== _T(".htb") || 
1543                         ext 
== _T(".chm") || 
1552                         m_HtmlWin
->LoadPage(s
); 
1559 void wxHtmlHelpWindow::OnContentsSel(wxTreeEvent
& event
) 
1561     wxHtmlHelpTreeItemData 
*pg
; 
1563     pg 
= (wxHtmlHelpTreeItemData
*) m_ContentsBox
->GetItemData(event
.GetItem()); 
1565     if (pg 
&& m_UpdateContents
) 
1567         const wxHtmlHelpDataItems
& contents 
= m_Data
->GetContentsArray(); 
1568         m_UpdateContents 
= false; 
1569         if (!contents
[pg
->m_Id
].page
.empty()) 
1570             m_HtmlWin
->LoadPage(contents
[pg
->m_Id
].GetFullPath()); 
1571         m_UpdateContents 
= true; 
1575 void wxHtmlHelpWindow::OnIndexSel(wxCommandEvent
& WXUNUSED(event
)) 
1577     wxHtmlHelpMergedIndexItem 
*it 
= (wxHtmlHelpMergedIndexItem
*) 
1578         m_IndexList
->GetClientData(m_IndexList
->GetSelection()); 
1580         DisplayIndexItem(it
); 
1583 void wxHtmlHelpWindow::OnIndexFind(wxCommandEvent
& WXUNUSED(event
)) 
1588 void wxHtmlHelpWindow::DoIndexFind() 
1590     wxString sr 
= m_IndexText
->GetLineText(0); 
1592     if (sr 
== wxEmptyString
) 
1600         m_IndexList
->Clear(); 
1601         const wxHtmlHelpMergedIndex
& index 
= *m_mergedIndex
; 
1602         size_t cnt 
= index
.size(); 
1605         for (size_t i 
= 0; i 
< cnt
; i
++) 
1607             if (index
[i
].name
.Lower().find(sr
) != wxString::npos
) 
1609                 int pos 
= m_IndexList
->Append(index
[i
].name
, 
1610                                               (char*)(&index
[i
])); 
1614                     // don't automatically show topic selector if this 
1615                     // item points to multiple pages: 
1616                     if (index
[i
].items
.size() == 1) 
1618                         m_IndexList
->SetSelection(0); 
1619                         DisplayIndexItem(&index
[i
]); 
1623                 // if this is nested item of the index, show its parent(s) 
1624                 // as well, otherwise it would not be clear what entry is 
1626                 wxHtmlHelpMergedIndexItem 
*parent 
= index
[i
].parent
; 
1630                         (index
.Index(*(wxHtmlHelpMergedIndexItem
*)m_IndexList
->GetClientData(pos
-1))) < index
.Index(*parent
)) 
1632                         m_IndexList
->Insert(parent
->name
, 
1633                                             pos
, (char*)parent
); 
1634                         parent 
= parent
->parent
; 
1639                 // finally, it the item we just added is itself a parent for 
1640                 // other items, show them as well, because they are refinements 
1641                 // of the displayed index entry (i.e. it is implicitly contained 
1642                 // in them: "foo" with parent "bar" reads as "bar, foo"): 
1643                 int level 
= index
[i
].items
[0]->level
; 
1645                 while (i 
< cnt 
&& index
[i
].items
[0]->level 
> level
) 
1647                     m_IndexList
->Append(index
[i
].name
, (char*)(&index
[i
])); 
1655         cnttext
.Printf(_("%i of %i"), displ
, cnt
); 
1656         m_IndexCountInfo
->SetLabel(cnttext
); 
1658         m_IndexText
->SetSelection(0, sr
.length()); 
1659         m_IndexText
->SetFocus(); 
1663 void wxHtmlHelpWindow::OnIndexAll(wxCommandEvent
& WXUNUSED(event
)) 
1668 void wxHtmlHelpWindow::DoIndexAll() 
1672     m_IndexList
->Clear(); 
1673     const wxHtmlHelpMergedIndex
& index 
= *m_mergedIndex
; 
1674     size_t cnt 
= index
.size(); 
1677     for (size_t i 
= 0; i 
< cnt
; i
++) 
1679         m_IndexList
->Append(index
[i
].name
, (char*)(&index
[i
])); 
1682             // don't automatically show topic selector if this 
1683             // item points to multiple pages: 
1684             if (index
[i
].items
.size() == 1) 
1686                 DisplayIndexItem(&index
[i
]); 
1693     cnttext
.Printf(_("%i of %i"), cnt
, cnt
); 
1694     m_IndexCountInfo
->SetLabel(cnttext
); 
1697 void wxHtmlHelpWindow::OnSearchSel(wxCommandEvent
& WXUNUSED(event
)) 
1699     wxHtmlHelpDataItem 
*it 
= (wxHtmlHelpDataItem
*) m_SearchList
->GetClientData(m_SearchList
->GetSelection()); 
1702         if (!it
->page
.empty()) 
1703             m_HtmlWin
->LoadPage(it
->GetFullPath()); 
1704         NotifyPageChanged(); 
1708 void wxHtmlHelpWindow::OnSearch(wxCommandEvent
& WXUNUSED(event
)) 
1710     wxString sr 
= m_SearchText
->GetLineText(0); 
1713         KeywordSearch(sr
, wxHELP_SEARCH_ALL
); 
1716 void wxHtmlHelpWindow::OnBookmarksSel(wxCommandEvent
& WXUNUSED(event
)) 
1718     wxString str 
= m_Bookmarks
->GetStringSelection(); 
1719     int idx 
= m_BookmarksNames
.Index(str
); 
1720     if (!str
.empty() && str 
!= _("(bookmarks)") && idx 
!= wxNOT_FOUND
) 
1722        m_HtmlWin
->LoadPage(m_BookmarksPages
[(size_t)idx
]); 
1723        NotifyPageChanged(); 
1727 void wxHtmlHelpWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
1732 #endif // wxUSE_WXHTML_HELP