]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/app.cpp
Doc corrections,
[wxWidgets.git] / src / gtk / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "appbase.h"
12 #pragma implementation "app.h"
13 #endif
14
15 #include "wx/app.h"
16 #include "wx/gdicmn.h"
17 #include "wx/utils.h"
18 #include "wx/intl.h"
19 #include "wx/log.h"
20 #include "wx/memory.h"
21 #include "wx/font.h"
22 #include "wx/settings.h"
23 #include "wx/dialog.h"
24
25 #if wxUSE_WX_RESOURCES
26 #include "wx/resource.h"
27 #endif
28
29 #include "wx/module.h"
30 #include "wx/image.h"
31
32 #if wxUSE_THREADS
33 #include "wx/thread.h"
34 #endif
35
36 #include "unistd.h"
37
38 #include "glib.h"
39 #include "gdk/gdk.h"
40 #include "gtk/gtk.h"
41
42 #include "wx/gtk/win_gtk.h"
43
44 //-----------------------------------------------------------------------------
45 // global data
46 //-----------------------------------------------------------------------------
47
48 wxApp *wxTheApp = (wxApp *) NULL;
49 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
50
51 #if wxUSE_THREADS
52 extern wxList *wxPendingEvents;
53 extern wxCriticalSection *wxPendingEventsLocker;
54 #endif
55 extern wxResourceCache *wxTheResourceCache;
56 extern bool g_isIdle;
57
58 unsigned char g_palette[64*3] =
59 {
60 0x0, 0x0, 0x0,
61 0xff, 0xff, 0xff,
62 0xff, 0x0, 0x0,
63 0xff, 0xff, 0x0,
64 0x0, 0xff, 0x0,
65 0x0, 0x0, 0xff,
66 0x0, 0xff, 0xff,
67 0x99, 0x99, 0x99,
68 0xff, 0x88, 0x0,
69 0x88, 0x0, 0x0,
70 0x0, 0x88, 0x88,
71 0x88, 0x88, 0x0,
72 0xff, 0xcc, 0x97,
73 0xbb, 0xbb, 0xbb,
74 0x9f, 0x6b, 0x42,
75 0x55, 0x55, 0x55,
76 0xdd, 0xdd, 0xdd,
77 0x77, 0x77, 0x77,
78 0x33, 0x33, 0x33,
79 0xcc, 0x0, 0x0,
80 0xff, 0x44, 0x0,
81 0xff, 0xcc, 0x0,
82 0xcc, 0xcc, 0x0,
83 0x60, 0x60, 0x0,
84 0x0, 0x43, 0x0,
85 0x0, 0x7f, 0x0,
86 0x0, 0xcc, 0x0,
87 0x0, 0x44, 0x44,
88 0x0, 0x0, 0x44,
89 0x0, 0x0, 0x88,
90 0xef, 0xb1, 0x7b,
91 0xdf, 0x98, 0x5f,
92 0xbf, 0x87, 0x56,
93 0x7f, 0x57, 0x26,
94 0x5f, 0x39, 0xc,
95 0x3f, 0x1c, 0x0,
96 0x21, 0x0, 0x0,
97 0x0, 0x43, 0x87,
98 0x2d, 0x70, 0xaf,
99 0x5a, 0x9e, 0xd7,
100 0x87, 0xcc, 0xff,
101 0xff, 0xe0, 0xba,
102 0x21, 0x43, 0xf,
103 0x3d, 0x5d, 0x25,
104 0x59, 0x78, 0x3a,
105 0x75, 0x93, 0x4f,
106 0x91, 0xae, 0x64,
107 0xad, 0xc8, 0x7a,
108 0xf0, 0xa8, 0xef,
109 0xd0, 0x88, 0xd0,
110 0xaf, 0x66, 0xaf,
111 0x8e, 0x44, 0x8e,
112 0x6d, 0x22, 0x6d,
113 0x4b, 0x0, 0x4b,
114 0xff, 0xc0, 0xbc,
115 0xff, 0x93, 0x91,
116 0xff, 0x66, 0x67,
117 0xd8, 0xf2, 0xbf,
118 0xff, 0xc9, 0x68,
119 0xff, 0x96, 0x67,
120 0xa5, 0x60, 0xff,
121 0x51, 0xff, 0x99,
122 0x3f, 0xa5, 0x63,
123 0x98, 0x90, 0x67
124 };
125
126 //-----------------------------------------------------------------------------
127 // local functions
128 //-----------------------------------------------------------------------------
129
130 extern void wxFlushResources(void);
131
132 //-----------------------------------------------------------------------------
133 // global functions
134 //-----------------------------------------------------------------------------
135
136 void wxExit()
137 {
138 gtk_main_quit();
139 }
140
141 /* forward declaration */
142 gint wxapp_idle_callback( gpointer WXUNUSED(data) );
143
144 bool wxYield()
145 {
146 /* it's necessary to call ProcessIdle() to update the frames sizes which
147 might have been changed (it also will update other things set from
148 OnUpdateUI() which is a nice (and desired) side effect) */
149 while (wxTheApp->ProcessIdle()) { }
150
151 #if 0
152 for ( wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
153 node;
154 node = node->GetNext() )
155 {
156 wxWindow *win = node->GetData();
157 win->OnInternalIdle();
158 }
159 #endif
160
161 if (wxTheApp->m_idleTag)
162 {
163 /* We need to temporarily remove idle callbacks or the loop will
164 never finish. */
165 gtk_idle_remove( wxTheApp->m_idleTag );
166 wxTheApp->m_idleTag = 0;
167
168 while (gtk_events_pending())
169 gtk_main_iteration();
170
171 /* re-add idle handler */
172 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
173 }
174 else
175 {
176 while (gtk_events_pending())
177 gtk_main_iteration();
178 }
179
180 return TRUE;
181 }
182
183 gint wxapp_idle_callback( gpointer WXUNUSED(data) )
184 {
185 if (!wxTheApp) return TRUE;
186
187 #if (GTK_MINOR_VERSION > 0)
188 /* when getting called from GDK's idle handler we
189 are no longer within GDK's grab on the GUI
190 thread so we must lock it here ourselves */
191 GDK_THREADS_ENTER ();
192 #endif
193
194 /* sent idle event to all who request them */
195 while (wxTheApp->ProcessIdle()) { }
196
197 /* we don't want any more idle events until the next event is
198 sent to wxGTK */
199 gtk_idle_remove( wxTheApp->m_idleTag );
200 wxTheApp->m_idleTag = 0;
201
202 /* indicate that we are now in idle mode - even so deeply
203 in idle mode that we don't get any idle events anymore.
204 this is like wxMSW where an idle event is sent only
205 once each time after the event queue has been completely
206 emptied */
207 g_isIdle = TRUE;
208
209 #if (GTK_MINOR_VERSION > 0)
210 /* release lock again */
211 GDK_THREADS_LEAVE ();
212 #endif
213
214 return TRUE;
215 }
216
217 void wxapp_install_idle_handler()
218 {
219 wxASSERT_MSG( wxTheApp->m_idleTag == 0, _T("attempt to install idle handler twice") );
220
221 /* this routine gets called by all event handlers
222 indicating that the idle is over. */
223
224 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
225
226 g_isIdle = FALSE;
227 }
228
229 #if wxUSE_THREADS
230
231 /* forward declaration */
232 static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) );
233
234 void wxapp_install_thread_wakeup()
235 {
236 if (wxTheApp->m_wakeUpTimerTag) return;
237
238 wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 100, wxapp_wakeup_timerout_callback, (gpointer) NULL );
239 }
240
241 void wxapp_uninstall_thread_wakeup()
242 {
243 if (!wxTheApp->m_wakeUpTimerTag) return;
244
245 gtk_timeout_remove( wxTheApp->m_wakeUpTimerTag );
246 wxTheApp->m_wakeUpTimerTag = 0;
247 }
248
249 static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
250 {
251 wxapp_uninstall_thread_wakeup();
252
253 #if (GTK_MINOR_VERSION > 0)
254 // when getting called from GDK's time-out handler
255 // we are no longer within GDK's grab on the GUI
256 // thread so we must lock it here ourselves
257 GDK_THREADS_ENTER ();
258 #endif
259
260 // unblock other threads wishing to do some GUI things
261 wxMutexGuiLeave();
262
263 // wake up other threads
264 wxUsleep( 1 );
265
266 // block other thread again
267 wxMutexGuiEnter();
268
269 #if (GTK_MINOR_VERSION > 0)
270 // release lock again
271 GDK_THREADS_LEAVE ();
272 #endif
273
274 wxapp_install_thread_wakeup();
275
276 return TRUE;
277 }
278 #endif
279
280 //-----------------------------------------------------------------------------
281 // wxApp
282 //-----------------------------------------------------------------------------
283
284 IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
285
286 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
287 EVT_IDLE(wxApp::OnIdle)
288 END_EVENT_TABLE()
289
290 wxApp::wxApp()
291 {
292 wxTheApp = this;
293
294 m_topWindow = (wxWindow *) NULL;
295 m_exitOnFrameDelete = TRUE;
296
297 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
298
299 #if wxUSE_THREADS
300 m_wakeUpTimerTag = 0;
301 wxapp_install_thread_wakeup();
302 #endif
303
304 m_colorCube = (unsigned char*) NULL;
305 }
306
307 wxApp::~wxApp()
308 {
309 if (m_idleTag) gtk_idle_remove( m_idleTag );
310
311 #if wxUSE_THREADS
312 wxapp_uninstall_thread_wakeup();
313 #endif
314
315 if (m_colorCube) free(m_colorCube);
316 }
317
318 bool wxApp::OnInitGui()
319 {
320 GdkVisual *visual = gdk_visual_get_system();
321
322 /* on some machines, the default visual is just 256 colours, so
323 we make sure we get the best. this can sometimes be wasteful,
324 of course, but what do these guys pay $30.000 for? */
325 /*
326 if (gdk_visual_get_best() != gdk_visual_get_system())
327 {
328 GdkVisual* vis = gdk_visual_get_best();
329 gtk_widget_set_default_visual( vis );
330
331 GdkColormap *colormap = gdk_colormap_new( vis, FALSE );
332 gtk_widget_set_default_colormap( colormap );
333
334 visual = vis;
335 }
336 */
337
338 /* Nothing to do for 15, 16, 24, 32 bit displays */
339 if (visual->depth > 8) return TRUE;
340
341 /* this initiates the standard palette as defined by GdkImlib
342 in the GNOME libraries. it ensures that all GNOME applications
343 use the same 64 colormap entries on 8-bit displays so you
344 can use several rather graphics-heavy applications at the
345 same time.
346 NOTE: this doesn't really seem to work this way... */
347
348 /*
349 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
350
351 for (int i = 0; i < 64; i++)
352 {
353 GdkColor col;
354 col.red = g_palette[i*3 + 0] << 8;
355 col.green = g_palette[i*3 + 1] << 8;
356 col.blue = g_palette[i*3 + 2] << 8;
357 col.pixel = 0;
358
359 gdk_color_alloc( cmap, &col );
360 }
361
362 gtk_widget_set_default_colormap( cmap );
363 */
364
365 /* initialize color cube for 8-bit color reduction dithering */
366
367 GdkColormap *cmap = gtk_widget_get_default_colormap();
368
369 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
370
371 for (int r = 0; r < 32; r++)
372 {
373 for (int g = 0; g < 32; g++)
374 {
375 for (int b = 0; b < 32; b++)
376 {
377 int rr = (r << 3) | (r >> 2);
378 int gg = (g << 3) | (g >> 2);
379 int bb = (b << 3) | (b >> 2);
380
381 int index = -1;
382
383 GdkColor *colors = cmap->colors;
384 if (colors)
385 {
386 int max = 3 * 65536;
387
388 for (int i = 0; i < cmap->size; i++)
389 {
390 int rdiff = ((rr << 8) - colors[i].red);
391 int gdiff = ((gg << 8) - colors[i].green);
392 int bdiff = ((bb << 8) - colors[i].blue);
393 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
394 if (sum < max)
395 {
396 index = i; max = sum;
397 }
398 }
399 }
400 else
401 {
402 #if (GTK_MINOR_VERSION > 0)
403 /* assume 8-bit true or static colors. this really
404 exists. */
405 GdkVisual* vis = gdk_colormap_get_visual( cmap );
406 index = (r >> (5 - vis->red_prec)) << vis->red_shift;
407 index |= (g >> (5 - vis->green_prec)) << vis->green_shift;
408 index |= (b >> (5 - vis->blue_prec)) << vis->blue_shift;
409 #else
410 wxFAIL_MSG( _T("Unsupported graphics hardware") );
411 #endif
412 }
413 m_colorCube[ (r*1024) + (g*32) + b ] = index;
414 }
415 }
416 }
417
418 return TRUE;
419 }
420
421 bool wxApp::ProcessIdle()
422 {
423 wxIdleEvent event;
424 event.SetEventObject( this );
425 ProcessEvent( event );
426
427 return event.MoreRequested();
428 }
429
430 void wxApp::OnIdle( wxIdleEvent &event )
431 {
432 static bool inOnIdle = FALSE;
433
434 /* Avoid recursion (via ProcessEvent default case) */
435 if (inOnIdle)
436 return;
437
438 inOnIdle = TRUE;
439
440 #if wxUSE_THREADS
441 /* Resend in the main thread events which have been prepared in other
442 threads */
443 ProcessPendingEvents();
444 #endif
445
446 /* 'Garbage' collection of windows deleted with Close(). */
447 DeletePendingObjects();
448
449 /* flush the logged messages if any */
450 #if wxUSE_LOG
451 wxLog *log = wxLog::GetActiveTarget();
452 if (log != NULL && log->HasPendingMessages())
453 log->Flush();
454 #endif // wxUSE_LOG
455
456 /* Send OnIdle events to all windows */
457 bool needMore = SendIdleEvents();
458
459 if (needMore)
460 event.RequestMore(TRUE);
461
462 inOnIdle = FALSE;
463 }
464
465 bool wxApp::SendIdleEvents()
466 {
467 bool needMore = FALSE;
468
469 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
470 while (node)
471 {
472 wxWindow* win = node->GetData();
473 if (SendIdleEvents(win))
474 needMore = TRUE;
475 node = node->GetNext();
476 }
477
478 return needMore;
479 }
480
481 bool wxApp::SendIdleEvents( wxWindow* win )
482 {
483 bool needMore = FALSE;
484
485 wxIdleEvent event;
486 event.SetEventObject(win);
487
488 win->OnInternalIdle();
489
490 win->ProcessEvent(event);
491
492 if (event.MoreRequested())
493 needMore = TRUE;
494
495 wxNode* node = win->GetChildren().First();
496 while (node)
497 {
498 wxWindow* win = (wxWindow*) node->Data();
499 if (SendIdleEvents(win))
500 needMore = TRUE;
501
502 node = node->Next();
503 }
504 return needMore ;
505 }
506
507 int wxApp::MainLoop()
508 {
509 gtk_main();
510 return 0;
511 }
512
513 void wxApp::ExitMainLoop()
514 {
515 gtk_main_quit();
516 }
517
518 bool wxApp::Initialized()
519 {
520 return m_initialized;
521 }
522
523 bool wxApp::Pending()
524 {
525 return (gtk_events_pending() > 0);
526 }
527
528 void wxApp::Dispatch()
529 {
530 gtk_main_iteration();
531 }
532
533 #if wxUSE_THREADS
534 void wxApp::ProcessPendingEvents()
535 {
536 wxNode *node = wxPendingEvents->First();
537 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
538
539 while (node)
540 {
541 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
542
543 handler->ProcessPendingEvents();
544
545 delete node;
546
547 node = wxPendingEvents->First();
548 }
549 }
550 #endif // wxUSE_THREADS
551
552 void wxApp::DeletePendingObjects()
553 {
554 wxNode *node = wxPendingDelete.First();
555 while (node)
556 {
557 wxObject *obj = (wxObject *)node->Data();
558
559 delete obj;
560
561 if (wxPendingDelete.Find(obj))
562 delete node;
563
564 node = wxPendingDelete.First();
565 }
566 }
567
568 bool wxApp::Initialize()
569 {
570 wxBuffer = new wxChar[BUFSIZ + 512];
571
572 wxClassInfo::InitializeClasses();
573
574 wxSystemSettings::Init();
575
576 // GL: I'm annoyed ... I don't know where to put this and I don't want to
577 // create a module for that as it's part of the core.
578 #if wxUSE_THREADS
579 wxPendingEvents = new wxList();
580 wxPendingEventsLocker = new wxCriticalSection();
581 #endif
582
583 /*
584 wxTheFontNameDirectory = new wxFontNameDirectory;
585 wxTheFontNameDirectory->Initialize();
586 */
587
588 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
589 wxTheColourDatabase->Initialize();
590
591 wxInitializeStockLists();
592 wxInitializeStockObjects();
593
594 #if wxUSE_WX_RESOURCES
595 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
596
597 wxInitializeResourceSystem();
598 #endif
599
600 wxImage::InitStandardHandlers();
601
602 wxModule::RegisterModules();
603 if (!wxModule::InitializeModules()) return FALSE;
604
605 return TRUE;
606 }
607
608 void wxApp::CleanUp()
609 {
610 wxModule::CleanUpModules();
611
612 #if wxUSE_WX_RESOURCES
613 wxFlushResources();
614
615 if (wxTheResourceCache)
616 delete wxTheResourceCache;
617 wxTheResourceCache = (wxResourceCache*) NULL;
618
619 wxCleanUpResourceSystem();
620 #endif
621
622 if (wxTheColourDatabase)
623 delete wxTheColourDatabase;
624 wxTheColourDatabase = (wxColourDatabase*) NULL;
625
626 /*
627 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
628 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
629 */
630
631 wxDeleteStockObjects();
632
633 wxDeleteStockLists();
634
635 wxImage::CleanUpHandlers();
636
637 delete wxTheApp;
638 wxTheApp = (wxApp*) NULL;
639
640 // GL: I'm annoyed ... I don't know where to put this and I don't want to
641 // create a module for that as it's part of the core.
642 #if wxUSE_THREADS
643 delete wxPendingEvents;
644 delete wxPendingEventsLocker;
645 #endif
646
647 wxSystemSettings::Done();
648
649 delete[] wxBuffer;
650
651 wxClassInfo::CleanUpClasses();
652
653 // check for memory leaks
654 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
655 if (wxDebugContext::CountObjectsLeft() > 0)
656 {
657 wxLogDebug(_T("There were memory leaks.\n"));
658 wxDebugContext::Dump();
659 wxDebugContext::PrintStatistics();
660 }
661 #endif // Debug
662
663 #if wxUSE_LOG
664 // do this as the very last thing because everything else can log messages
665 wxLog::DontCreateOnDemand();
666
667 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
668 if (oldLog)
669 delete oldLog;
670 }
671
672 #endif // wxUSE_LOG
673
674 //-----------------------------------------------------------------------------
675 // wxEntry
676 //-----------------------------------------------------------------------------
677
678 int wxEntry( int argc, char *argv[] )
679 {
680 gtk_set_locale();
681
682 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
683
684 gtk_init( &argc, &argv );
685
686 wxSetDetectableAutoRepeat( TRUE );
687
688 if (!wxApp::Initialize())
689 return -1;
690
691 if (!wxTheApp)
692 {
693 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
694 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
695
696 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
697
698 wxObject *test_app = app_ini();
699
700 wxTheApp = (wxApp*) test_app;
701 }
702
703 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
704
705 wxTheApp->argc = argc;
706 #if wxUSE_UNICODE
707 wxTheApp->argv = new wxChar*[argc+1];
708 int mb_argc = 0;
709 while (mb_argc < argc) {
710 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
711 mb_argc++;
712 }
713 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
714 #else
715 wxTheApp->argv = argv;
716 #endif
717
718 wxString name(wxFileNameFromPath(argv[0]));
719 wxStripExtension( name );
720 wxTheApp->SetAppName( name );
721
722 int retValue = 0;
723
724 if ( !wxTheApp->OnInitGui() )
725 retValue = -1;
726
727 // Here frames insert themselves automatically into wxTopLevelWindows by
728 // getting created in OnInit().
729 if ( retValue == 0 )
730 {
731 if ( !wxTheApp->OnInit() )
732 retValue = -1;
733 }
734
735 if ( retValue == 0 )
736 {
737 /* delete pending toplevel windows (typically a single
738 dialog) so that, if there isn't any left, we don't
739 call OnRun() */
740 wxTheApp->DeletePendingObjects();
741
742 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
743
744 if (wxTheApp->Initialized())
745 {
746 retValue = wxTheApp->OnRun();
747
748 wxWindow *topWindow = wxTheApp->GetTopWindow();
749 if (topWindow)
750 {
751 /* Forcibly delete the window. */
752 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
753 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
754 {
755 topWindow->Close( TRUE );
756 wxTheApp->DeletePendingObjects();
757 }
758 else
759 {
760 delete topWindow;
761 wxTheApp->SetTopWindow( (wxWindow*) NULL );
762 }
763 }
764 wxTheApp->OnExit();
765 }
766 }
767
768 #if wxUSE_LOG
769 // flush the logged messages if any
770 wxLog *log = wxLog::GetActiveTarget();
771 if (log != NULL && log->HasPendingMessages())
772 log->Flush();
773
774 // continuing to use user defined log target is unsafe from now on because
775 // some resources may be already unavailable, so replace it by something
776 // more safe
777 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
778 if ( oldlog )
779 delete oldlog;
780 #endif // wxUSE_LOG
781
782 wxApp::CleanUp();
783
784 return retValue;
785 }
786
787 #include "wx/gtk/info.xpm"
788 #include "wx/gtk/error.xpm"
789 #include "wx/gtk/question.xpm"
790 #include "wx/gtk/warning.xpm"
791
792 wxIcon
793 wxApp::GetStdIcon(int which) const
794 {
795 switch(which)
796 {
797 case wxICON_INFORMATION:
798 return wxIcon(info_xpm);
799
800 case wxICON_QUESTION:
801 return wxIcon(question_xpm);
802
803 case wxICON_EXCLAMATION:
804 return wxIcon(warning_xpm);
805
806 default:
807 wxFAIL_MSG(_T("requested non existent standard icon"));
808 // still fall through
809
810 case wxICON_HAND:
811 return wxIcon(error_xpm);
812 }
813 }