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