1///////////////////////////////////////////////////////////////////////////// 2// Name: helpview.h 3// Purpose: HelpView application 4// A standalone viewer for wxHTML Help (.htb) files 5// Author: Vaclav Slavik, Julian Smart 6// Modified by: 7// Created: 2002-07-09 8// RCS-ID: $Id: helpview.cpp 44611 2007-03-05 11:34:19Z JS $ 9// Copyright: (c) 2002 Vaclav Slavik, Julian Smart and others 10// Licence: wxWindows licence 11///////////////////////////////////////////////////////////////////////////// 12 13// For compilers that support precompilation, includes "wx/wx.h". 14#include "wx/wxprec.h" 15 16#ifdef __BORLANDC__ 17#pragma hdrstop 18#endif 19 20// for all others, include the necessary headers (this file is usually all you 21// need because it includes almost all "standard" wxWidgets headers 22#ifndef WX_PRECOMP 23#include "wx/wx.h" 24#endif 25 26#include "wx/filename.h" 27#include "wx/image.h" 28#include "wx/wxhtml.h" 29#include "wx/fs_zip.h" 30#include "wx/log.h" 31#include "wx/artprov.h" 32#include "wx/filedlg.h" 33 34#include "helpview.h" 35 36class AlternateArtProvider : public wxArtProvider 37{ 38protected: 39 virtual wxBitmap CreateBitmap(const wxArtID& id, const wxArtClient& client, 40 const wxSize& size); 41}; 42 43IMPLEMENT_APP(hvApp) 44 45BEGIN_EVENT_TABLE(hvApp, wxApp) 46 EVT_IDLE(hvApp::OnIdle) 47END_EVENT_TABLE() 48 49hvApp::hvApp() 50{ 51#if wxUSE_IPC 52 m_server = NULL; 53#endif 54 m_exitIfNoMainWindow = false; 55} 56 57bool hvApp::OnInit() 58{ 59#ifdef __WXMOTIF__ 60 delete wxLog::SetActiveTarget(new wxLogStderr); // So dialog boxes aren't used 61#endif 62 63 // Don't exit on frame deletion, since the help window is programmed 64 // to cause the app to exit even if it is still open. We need to have the app 65 // close by other means. 66 SetExitOnFrameDelete(false); 67 68 wxArtProvider::Push(new AlternateArtProvider); 69 70#ifdef __WXMAC__ 71 wxApp::s_macAboutMenuItemId = wxID_ABOUT; 72 wxFileName::MacRegisterDefaultTypeAndCreator( wxT("htb") , 'HTBD' , 'HTBA' ) ; 73#endif 74 75 int istyle = wxHF_DEFAULT_STYLE|wxHF_OPEN_FILES; 76 77 wxString service, windowName, titleFormat, argStr; 78 wxString book[10]; 79 int bookCount = 0; 80 int i; 81 bool hasService = false; 82 bool hasWindowName = false; 83 bool createServer = false; 84 85#if wxUSE_IPC 86 m_server = NULL; 87#endif 88 89 // Help books are recognized by extension ".hhp" ".htb" or ".zip". 90 // Service and window_name can occur anywhere in arguments, 91 // but service must be first 92 // Other arguments (topic?) could be added 93 94 // modes of operation: 95 // 1) no arguments - stand alone, prompt user for book 96 // 2) books only - stand alone, open books 97 // 3) "--server" as (any) arg - start connection with default service; 98 // also open any books passed as other arguments 99 // 4) at least one argument which is not book, and not "--server" - take first 100 // such argument as service, second (if present) as window name, 101 // start service, open any books 102 103 for( i=1; i<argc; i++ ) 104 { 105 argStr = argv[i]; 106 107 if ( argStr.Find( wxT(".hhp") ) >= 0 108 || argStr.Find( wxT(".htb") ) >= 0 109 || argStr.Find( wxT(".zip") ) >= 0 ) 110 { 111 book[bookCount] = argStr; 112 bookCount++; 113 } 114 else if ( argStr == wxT("--server") ) 115 { 116 createServer = true; 117#if defined(__WXMSW__) 118 service = wxT("generic_helpservice"); 119#elif defined(__UNIX__) 120 service = wxT("/tmp/") + wxString(wxT("generic_helpservice")); 121#else 122 service = wxT("4242"); 123#endif 124 } 125 else if ( !hasService ) 126 { 127 service = argStr; 128 hasService = true; 129 createServer = true; 130 } 131 else if ( !hasWindowName ) 132 { 133 windowName = argStr; 134 hasWindowName = true; 135 } 136 else if ( argStr.Find( wxT("--Style") ) >= 0 ) 137 { 138 long i; 139 wxString numb = argStr.AfterLast(wxT('e')); 140 if ( !(numb.ToLong(&i) ) ) 141 { 142 wxLogError( wxT("Integer conversion failed for --Style") ); 143 } 144 else 145 { 146 istyle = i; 147 } 148 } 149 else 150 { 151 //unknown - could be topic? 152 } 153 } 154 155 // No book - query user; but not on Mac, since there 156 // may be an AppleEvent to open a document on the way 157#ifndef __WXMAC__ 158 if ( bookCount < 1 ) 159 { 160 wxString s = wxFileSelector( wxT("Open help file"), 161 wxGetCwd(), 162 wxEmptyString, 163 wxEmptyString, 164 wxT("Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|HTML Help Project (*.hhp)|*.hhp"), 165 wxFD_OPEN | wxFD_FILE_MUST_EXIST, 166 NULL); 167 168 if (!s.empty()) 169 { 170 book[0] = s; 171 bookCount = 1; 172 } 173 } 174#endif 175 176#if wxUSE_IPC 177 178 if ( createServer ) 179 { 180 // Create a new server 181 m_server = new hvServer; 182 183 if ( !m_server->Create(service) ) 184 { 185 wxString wxm = wxT("Server Create failed - service: "); 186 wxString xxm = wxm << service; 187 wxLogError( xxm ); 188 //if MSW quits here, probably another copy already exists 189 return false; 190 } 191 createServer = false; 192 wxUnusedVar(createServer); 193 } 194 195#endif // wxUSE_IPC 196 197 //now add help 198 wxInitAllImageHandlers(); 199 wxFileSystem::AddHandler(new wxZipFSHandler); 200 201 SetVendorName(wxT("wxWidgets") ); 202 SetAppName(wxT("wxHTMLHelpServer") ); 203 wxConfig::Get(); // create an instance 204 205 m_helpController = new wxHtmlHelpController( istyle ); 206 207 if ( !hasWindowName ) 208 { 209 titleFormat = wxT("Help: %s") ; 210 } 211 else 212 { 213 //remove underscores 214 windowName.Replace( wxT("_"), wxT(" ") ); 215 titleFormat = windowName; 216 } 217 218 m_helpController->SetTitleFormat( titleFormat ); 219 220 for( i=0; i<bookCount; i++ ) 221 { 222 wxFileName fileName(book[i]); 223 m_helpController->AddBook(fileName); 224 } 225 226#ifdef __WXMOTIF__ 227 delete wxLog::SetActiveTarget(new wxLogGui); 228#endif 229 230 m_helpController->DisplayContents(); 231 SetTopWindow(m_helpController->GetFrame()); 232 m_exitIfNoMainWindow = true; 233 234 return true; 235} 236 237void hvApp::OnIdle(wxIdleEvent& event) 238{ 239 if (m_exitIfNoMainWindow && !GetTopWindow()) 240 ExitMainLoop(); 241 242 event.Skip(); 243 event.RequestMore(); 244} 245 246int hvApp::OnExit() 247{ 248#if wxUSE_IPC 249 wxObjectList::compatibility_iterator node = m_connections.GetFirst(); 250 while (node) 251 { 252 wxObjectList::compatibility_iterator next = node->GetNext(); 253 hvConnection* connection = (hvConnection*) node->GetData(); 254 connection->Disconnect(); 255 delete connection; 256 node = next; 257 } 258 m_connections.Clear(); 259 260 if (m_server) 261 { 262 delete m_server; 263 m_server = NULL; 264 } 265#endif 266 267 delete m_helpController; 268 delete wxConfig::Set(NULL); 269 270 return 0; 271} 272 273bool hvApp::OpenBook(wxHtmlHelpController* controller) 274{ 275 wxString s = wxFileSelector(_("Open help file"), 276 wxGetCwd(), 277 wxEmptyString, 278 wxEmptyString, 279 _( 280 "Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|\ 281 HTML Help Project (*.hhp)|*.hhp"), 282 wxFD_OPEN | wxFD_FILE_MUST_EXIST, 283 NULL); 284 285 if ( !s.empty() ) 286 { 287 wxString ext = s.Right(4).Lower(); 288 if (ext == _T(".zip") || ext == _T(".htb") || ext == _T(".hhp")) 289 { 290 wxBusyCursor bcur; 291 wxFileName fileName(s); 292 controller->AddBook(fileName); 293 return true; 294 } 295 } 296 297 return false; 298} 299 300#ifdef __WXMAC__ 301/// Respond to Apple Event for opening a document 302void hvApp::MacOpenFile(const wxString& filename) 303{ 304 wxBusyCursor bcur; 305 wxFileName fileName(filename); 306 m_helpController->AddBook(fileName); 307 m_helpController->DisplayContents(); 308} 309#endif 310 311 312/* 313* Art provider class 314*/ 315 316// --------------------------------------------------------------------- 317// helper macros 318// --------------------------------------------------------------------- 319 320// Standard macro for getting a resource from XPM file: 321#define ART(artId, xpmRc) \ 322if ( id == artId ) return wxBitmap(xpmRc##_xpm); 323 324#define GET_STD_ICON_FROM_APP(iconId) 325 326// There are two ways of getting the standard icon: either via XPMs or via 327// wxIcon ctor. This depends on the platform: 328#if defined(__WXUNIVERSAL__) 329#define CREATE_STD_ICON(iconId, xpmRc) return wxNullBitmap; 330#elif defined(__WXGTK__) || defined(__WXMOTIF__) 331#define CREATE_STD_ICON(iconId, xpmRc) return wxBitmap(xpmRc##_xpm); 332#else 333#define CREATE_STD_ICON(iconId, xpmRc) \ 334{ \ 335 wxIcon icon(_T(iconId)); \ 336 wxBitmap bmp; \ 337 bmp.CopyFromIcon(icon); \ 338 return bmp; \ 339} 340#endif 341 342// Macro used in CreateBitmap to get wxICON_FOO icons: 343#define ART_MSGBOX(artId, iconId, xpmRc) \ 344 if ( id == artId ) \ 345{ \ 346 GET_STD_ICON_FROM_APP(iconId) \ 347 CREATE_STD_ICON(#iconId, xpmRc) \ 348} 349 350// --------------------------------------------------------------------- 351// XPMs with the art 352// --------------------------------------------------------------------- 353 354// XPM hack: make the arrays const 355//#define static static const 356 357#include "bitmaps/helpback.xpm" 358#include "bitmaps/helpbook.xpm" 359#include "bitmaps/helpdown.xpm" 360#include "bitmaps/helpforward.xpm" 361#include "bitmaps/helpoptions.xpm" 362#include "bitmaps/helppage.xpm" 363#include "bitmaps/helpsidepanel.xpm" 364#include "bitmaps/helpup.xpm" 365#include "bitmaps/helpuplevel.xpm" 366#include "bitmaps/helpicon.xpm" 367#include "bitmaps/helpopen.xpm" 368 369//#undef static 370 371// --------------------------------------------------------------------- 372// CreateBitmap routine 373// --------------------------------------------------------------------- 374 375wxBitmap AlternateArtProvider::CreateBitmap(const wxArtID& id, 376 const wxArtClient& client, 377 const wxSize& WXUNUSED(size)) 378{ 379 ART(wxART_HELP_SIDE_PANEL, helpsidepanel) 380 ART(wxART_HELP_SETTINGS, helpoptions) 381 ART(wxART_HELP_BOOK, helpbook) 382 ART(wxART_HELP_FOLDER, helpbook) 383 ART(wxART_HELP_PAGE, helppage) 384 //ART(wxART_ADD_BOOKMARK, addbookm) 385 //ART(wxART_DEL_BOOKMARK, delbookm) 386 ART(wxART_GO_BACK, helpback) 387 ART(wxART_GO_FORWARD, helpforward) 388 ART(wxART_GO_UP, helpup) 389 ART(wxART_GO_DOWN, helpdown) 390 ART(wxART_GO_TO_PARENT, helpuplevel) 391 ART(wxART_FILE_OPEN, helpopen) 392 if (client == wxART_HELP_BROWSER) 393 { 394 //ART(wxART_FRAME_ICON, helpicon) 395 ART(wxART_HELP, helpicon) 396 } 397 398 //ART(wxART_GO_HOME, home) 399 400 // Any wxWidgets icons not implemented here 401 // will be provided by the default art provider. 402 return wxNullBitmap; 403} 404 405#if wxUSE_IPC 406 407wxConnectionBase *hvServer::OnAcceptConnection(const wxString& topic) 408{ 409 if (topic == wxT("HELP")) 410 return new hvConnection(); 411 else 412 return NULL; 413} 414 415// ---------------------------------------------------------------------------- 416// hvConnection 417// ---------------------------------------------------------------------------- 418 419hvConnection::hvConnection() 420: wxConnection() 421{ 422 wxGetApp().GetConnections().Append(this); 423} 424 425hvConnection::~hvConnection() 426{ 427 wxGetApp().GetConnections().DeleteObject(this); 428} 429 430bool hvConnection::OnExecute(const wxString& WXUNUSED(topic), 431 wxChar *data, 432 int WXUNUSED(size), 433 wxIPCFormat WXUNUSED(format)) 434{ 435 // wxLogStatus("Execute command: %s", data); 436 437 if ( !wxStrncmp( data, wxT("--intstring"), 11 ) ) 438 { 439 long i; 440 wxString argStr = data; 441 wxString numb = argStr.AfterLast(wxT('g')); 442 if ( !(numb.ToLong(&i) ) ) 443 { 444 wxLogError( wxT("Integer conversion failed for --intstring") ); 445 } 446 else 447 { 448 wxGetApp().GetHelpController()->Display(int(i)); 449 } 450 } 451 else 452 { 453 wxGetApp().GetHelpController()->Display(data); 454 } 455 456 return true; 457} 458 459bool hvConnection::OnPoke(const wxString& WXUNUSED(topic), 460 const wxString& item, 461 wxChar *data, 462 int WXUNUSED(size), 463 wxIPCFormat WXUNUSED(format)) 464{ 465 // wxLogStatus("Poke command: %s = %s", item.c_str(), data); 466 //topic is not tested 467 468 if ( wxGetApp().GetHelpController() ) 469 { 470 if ( item == wxT("--AddBook") ) 471 { 472 wxGetApp().GetHelpController()->AddBook(data); 473 } 474 else if ( item == wxT("--DisplayContents") ) 475 { 476 wxGetApp().GetHelpController()->DisplayContents(); 477 } 478 else if ( item == wxT("--DisplayIndex") ) 479 { 480 wxGetApp().GetHelpController()->DisplayIndex(); 481 } 482 else if ( item == wxT("--KeywordSearch") ) 483 { 484 wxGetApp().GetHelpController()->KeywordSearch(data); 485 } 486 else if ( item == wxT("--SetTitleFormat") ) 487 { 488 wxString newname = data; 489 newname.Replace( wxT("_"), wxT(" ") ); 490 wxGetApp().GetHelpController()->SetTitleFormat(newname); 491 //does not redraw title bar? 492 //wxGetApp().GetHelpController()->ReFresh(); - or something 493 } 494 else if ( item == wxT("--SetTempDir") ) 495 { 496 wxGetApp().GetHelpController()->SetTempDir(data); 497 } 498 else if ( item == wxT("--YouAreDead") ) 499 { 500 // don't really know how to kill app from down here... 501 // use wxKill from client instead 502 //wxWindow *win = wxTheApp->GetTopWindow(); 503 //if ( win ) 504 // win->Destroy(); 505 } 506 } 507 508 return true; 509} 510 511wxChar *hvConnection::OnRequest(const wxString& WXUNUSED(topic), 512 const wxString& WXUNUSED(item), 513 int * WXUNUSED(size), 514 wxIPCFormat WXUNUSED(format)) 515{ 516 return NULL; 517} 518 519bool hvConnection::OnStartAdvise(const wxString& WXUNUSED(topic), 520 const wxString& WXUNUSED(item)) 521{ 522 return true; 523} 524 525#endif // #if wxUSE_IPC 526