]> git.saurik.com Git - wxWidgets.git/blob - src/x11/app.cpp
wxX11:
[wxWidgets.git] / src / x11 / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
3 // Purpose: wxApp
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "app.h"
14 #endif
15
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/icon.h"
21 #include "wx/dialog.h"
22 #include "wx/log.h"
23 #include "wx/module.h"
24 #include "wx/memory.h"
25 #include "wx/log.h"
26 #include "wx/intl.h"
27 #include "wx/evtloop.h"
28
29 #if wxUSE_THREADS
30 #include "wx/thread.h"
31 #endif
32
33 #if wxUSE_WX_RESOURCES
34 #include "wx/resource.h"
35 #endif
36
37 #ifdef __VMS__
38 #pragma message disable nosimpint
39 #endif
40 #include <X11/Xlib.h>
41 #include <X11/Xutil.h>
42 #include <X11/Xatom.h>
43
44 #ifdef __VMS__
45 #pragma message enable nosimpint
46 #endif
47
48 #include "wx/x11/private.h"
49
50 #include <string.h>
51
52 extern wxList wxPendingDelete;
53
54 wxApp *wxTheApp = NULL;
55
56 wxHashTable *wxWidgetHashTable = NULL;
57
58 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
59
60 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
61 EVT_IDLE(wxApp::OnIdle)
62 END_EVENT_TABLE()
63
64 #ifdef __WXDEBUG__
65 typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
66
67 XErrorHandlerFunc gs_pfnXErrorHandler = 0;
68
69 static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
70 {
71 // just forward to the default handler for now
72 return gs_pfnXErrorHandler(dpy, xevent);
73 }
74 #endif // __WXDEBUG__
75
76 long wxApp::sm_lastMessageTime = 0;
77 WXDisplay *wxApp::ms_display = NULL;
78
79 // This is set within wxEntryStart -- too early on
80 // to put these in wxTheApp
81 static int g_newArgc = 0;
82 static wxChar** g_newArgv = NULL;
83 static bool g_showIconic = FALSE;
84 static wxSize g_initialSize = wxDefaultSize;
85
86 bool wxApp::Initialize()
87 {
88 wxClassInfo::InitializeClasses();
89
90 // GL: I'm annoyed ... I don't know where to put this and I don't want to
91 // create a module for that as it's part of the core.
92 #if wxUSE_THREADS
93 wxPendingEventsLocker = new wxCriticalSection();
94 #endif
95
96 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
97 wxTheColourDatabase->Initialize();
98
99 wxInitializeStockLists();
100 wxInitializeStockObjects();
101
102 #if wxUSE_WX_RESOURCES
103 wxInitializeResourceSystem();
104 #endif
105
106 wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
107
108 wxModule::RegisterModules();
109 if (!wxModule::InitializeModules()) return FALSE;
110
111 return TRUE;
112 }
113
114 void wxApp::CleanUp()
115 {
116 if (g_newArgv)
117 delete[] g_newArgv;
118 g_newArgv = NULL;
119
120 delete wxWidgetHashTable;
121 wxWidgetHashTable = NULL;
122
123 wxModule::CleanUpModules();
124
125 #if wxUSE_WX_RESOURCES
126 wxCleanUpResourceSystem();
127 #endif
128
129 delete wxTheColourDatabase;
130 wxTheColourDatabase = NULL;
131
132 wxDeleteStockObjects();
133
134 wxDeleteStockLists();
135
136 delete wxTheApp;
137 wxTheApp = NULL;
138
139 wxClassInfo::CleanUpClasses();
140
141 #if wxUSE_THREADS
142 delete wxPendingEvents;
143 delete wxPendingEventsLocker;
144 #endif
145
146 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
147 // At this point we want to check if there are any memory
148 // blocks that aren't part of the wxDebugContext itself,
149 // as a special case. Then when dumping we need to ignore
150 // wxDebugContext, too.
151 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
152 {
153 wxLogDebug("There were memory leaks.");
154 wxDebugContext::Dump();
155 wxDebugContext::PrintStatistics();
156 }
157 #endif
158
159 // do it as the very last thing because everything else can log messages
160 wxLog::DontCreateOnDemand();
161 // do it as the very last thing because everything else can log messages
162 delete wxLog::SetActiveTarget(NULL);
163 }
164
165 // NB: argc and argv may be changed here, pass by reference!
166 int wxEntryStart( int& argc, char *argv[] )
167 {
168 #ifdef __WXDEBUG__
169 // install the X error handler
170 gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler );
171 #endif // __WXDEBUG__
172
173 wxString displayName;
174 bool syncDisplay = FALSE;
175
176 // Parse the arguments.
177 // We can't use wxCmdLineParser or OnInitCmdLine and friends because
178 // we have to create the Display earlier. If we can find a way to
179 // use the wxAppBase API then I'll be quite happy to change it.
180 g_newArgv = new wxChar*[argc];
181 g_newArgc = 0;
182 int i;
183 for (i = 0; i < argc; i++)
184 {
185 wxString arg(argv[i]);
186 if (arg == wxT("-display"))
187 {
188 if (i < (argc - 1))
189 {
190 i ++;
191 displayName = argv[i];
192 continue;
193 }
194 }
195 else if (arg == wxT("-geometry"))
196 {
197 if (i < (argc - 1))
198 {
199 i ++;
200 wxString windowGeometry = argv[i];
201 int w, h;
202 if (wxSscanf(windowGeometry.c_str(), _T("%dx%d"), &w, &h) != 2)
203 {
204 wxLogError(_("Invalid geometry specification '%s'"), windowGeometry.c_str());
205 }
206 else
207 {
208 g_initialSize = wxSize(w, h);
209 }
210 continue;
211 }
212 }
213 else if (arg == wxT("-sync"))
214 {
215 syncDisplay = TRUE;
216 continue;
217 }
218 else if (arg == wxT("-iconic"))
219 {
220 g_showIconic = TRUE;
221
222 continue;
223 }
224
225 // Not eaten by wxWindows, so pass through
226 g_newArgv[g_newArgc] = argv[i];
227 g_newArgc ++;
228 }
229
230 Display* xdisplay;
231 if (displayName.IsEmpty())
232 xdisplay = XOpenDisplay(NULL);
233 else
234 xdisplay = XOpenDisplay(displayName);
235
236 if (!xdisplay)
237 {
238 wxLogError( _("wxWindows could not open display. Exiting.") );
239 return -1;
240 }
241
242 if (syncDisplay)
243 {
244 XSynchronize(xdisplay, True);
245 }
246
247 wxApp::ms_display = (WXDisplay*) xdisplay;
248
249 XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask);
250
251 // wxSetDetectableAutoRepeat( TRUE );
252
253 if (!wxApp::Initialize())
254 return -1;
255
256 return 0;
257 }
258
259 int wxEntryInitGui()
260 {
261 int retValue = 0;
262
263 if ( !wxTheApp->OnInitGui() )
264 retValue = -1;
265
266 return retValue;
267 }
268
269
270 int wxEntry( int argc, char *argv[] )
271 {
272 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
273 // This seems to be necessary since there are 'rogue'
274 // objects present at this point (perhaps global objects?)
275 // Setting a checkpoint will ignore them as far as the
276 // memory checking facility is concerned.
277 // Of course you may argue that memory allocated in globals should be
278 // checked, but this is a reasonable compromise.
279 wxDebugContext::SetCheckpoint();
280 #endif
281 int err = wxEntryStart(argc, argv);
282 if (err)
283 return err;
284
285 if (!wxTheApp)
286 {
287 if (!wxApp::GetInitializerFunction())
288 {
289 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
290 return 0;
291 };
292
293 wxTheApp = (wxApp*) (* wxApp::GetInitializerFunction()) ();
294 };
295
296 if (!wxTheApp)
297 {
298 printf( "wxWindows error: wxTheApp == NULL\n" );
299 return 0;
300 };
301
302 wxTheApp->SetClassName(wxFileNameFromPath(argv[0]));
303 wxTheApp->SetAppName(wxFileNameFromPath(argv[0]));
304
305 // The command line may have been changed
306 // by stripping out -display etc.
307 if (g_newArgc > 0)
308 {
309 wxTheApp->argc = g_newArgc;
310 wxTheApp->argv = g_newArgv;
311 }
312 else
313 {
314 wxTheApp->argc = argc;
315 wxTheApp->argv = argv;
316 }
317 wxTheApp->m_showIconic = g_showIconic;
318 wxTheApp->m_initialSize = g_initialSize;
319
320 int retValue;
321 retValue = wxEntryInitGui();
322
323 // Here frames insert themselves automatically into wxTopLevelWindows by
324 // getting created in OnInit().
325 if ( retValue == 0 )
326 {
327 if ( !wxTheApp->OnInit() )
328 retValue = -1;
329 }
330
331 if ( retValue == 0 )
332 {
333 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
334 }
335
336 // flush the logged messages if any
337 wxLog *pLog = wxLog::GetActiveTarget();
338 if ( pLog != NULL && pLog->HasPendingMessages() )
339 pLog->Flush();
340
341 delete wxLog::SetActiveTarget(new wxLogStderr); // So dialog boxes aren't used
342 // for further messages
343
344 if (wxTheApp->GetTopWindow())
345 {
346 delete wxTheApp->GetTopWindow();
347 wxTheApp->SetTopWindow(NULL);
348 }
349
350 wxTheApp->DeletePendingObjects();
351
352 wxTheApp->OnExit();
353
354 wxApp::CleanUp();
355
356 return retValue;
357 };
358
359 // Static member initialization
360 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
361
362 wxApp::wxApp()
363 {
364 m_topWindow = NULL;
365 wxTheApp = this;
366 m_className = "";
367 m_wantDebugOutput = TRUE ;
368 m_appName = "";
369 argc = 0;
370 argv = NULL;
371 m_exitOnFrameDelete = TRUE;
372 m_mainColormap = (WXColormap) NULL;
373 m_topLevelWidget = (WXWindow) NULL;
374 m_maxRequestSize = 0;
375 m_mainLoop = NULL;
376 m_showIconic = FALSE;
377 m_initialSize = wxDefaultSize;
378 }
379
380 bool wxApp::Initialized()
381 {
382 if (GetTopWindow())
383 return TRUE;
384 else
385 return FALSE;
386 }
387
388 int wxApp::MainLoop()
389 {
390 int rt;
391 m_mainLoop = new wxEventLoop;
392
393 rt = m_mainLoop->Run();
394
395 delete m_mainLoop;
396 m_mainLoop = NULL;
397 return rt;
398 }
399
400 // Processes an X event.
401 void wxApp::ProcessXEvent(WXEvent* _event)
402 {
403 XEvent* event = (XEvent*) _event;
404
405 wxWindow* win = NULL;
406 Window window = event->xany.window;
407 Window actualWindow = window;
408
409 // Find the first wxWindow that corresponds to this event window
410 // Because we're receiving events after a window
411 // has been destroyed, assume a 1:1 match between
412 // Window and wxWindow, so if it's not in the table,
413 // it must have been destroyed.
414
415 win = wxGetWindowFromTable(window);
416 if (!win)
417 return;
418
419 switch (event->type)
420 {
421 case KeyPress:
422 {
423 if (win && !win->IsEnabled())
424 return;
425
426 {
427 if (win)
428 {
429 wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
430 wxTranslateKeyEvent(keyEvent, win, window, event);
431
432 wxLogDebug( "OnKey from %s", win->GetName().c_str() );
433
434 // We didn't process wxEVT_KEY_DOWN, so send
435 // wxEVT_CHAR
436 if (!win->GetEventHandler()->ProcessEvent( keyEvent ))
437 {
438 keyEvent.SetEventType(wxEVT_CHAR);
439 win->GetEventHandler()->ProcessEvent( keyEvent );
440 }
441
442 // We intercepted and processed the key down event
443 return;
444 }
445 }
446 return;
447 }
448 case KeyRelease:
449 {
450 if (win && !win->IsEnabled())
451 return;
452
453 if (win)
454 {
455 wxKeyEvent keyEvent(wxEVT_KEY_UP);
456 wxTranslateKeyEvent(keyEvent, win, window, event);
457
458 win->GetEventHandler()->ProcessEvent( keyEvent );
459 }
460 return;
461 }
462 case ConfigureNotify:
463 {
464 // Not clear if this is the same in NanoX
465 if (win)
466 {
467 wxSizeEvent sizeEvent( wxSize(event->xconfigure.width,event->xconfigure.height), win->GetId() );
468 sizeEvent.SetEventObject( win );
469
470 win->GetEventHandler()->ProcessEvent( sizeEvent );
471 }
472 }
473 #if !wxUSE_NANOX
474 case PropertyNotify:
475 {
476 HandlePropertyChange(_event);
477 return;
478 }
479 case ClientMessage:
480 {
481 if (win && !win->IsEnabled())
482 return;
483
484 Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);;
485 Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);;
486
487 if (event->xclient.message_type == wm_protocols)
488 {
489 if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
490 {
491 if (win)
492 {
493 win->Close(FALSE);
494 }
495 }
496 }
497 return;
498 }
499 case ResizeRequest:
500 {
501 /*
502 * If resize event, don't resize until the last resize event for this
503 * window is recieved. Prevents flicker as windows are resized.
504 */
505
506 Display *disp = (Display*) wxGetDisplay();
507 XEvent report;
508
509 // to avoid flicker
510 report = * event;
511 while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
512
513 if (win)
514 {
515 wxSize sz = win->GetSize();
516 wxSizeEvent sizeEvent(sz, win->GetId());
517 sizeEvent.SetEventObject(win);
518
519 win->GetEventHandler()->ProcessEvent( sizeEvent );
520 }
521
522 return;
523 }
524 #endif
525 #if wxUSE_NANOX
526 case GR_EVENT_TYPE_CLOSE_REQ:
527 {
528 if (win)
529 {
530 win->Close(FALSE);
531 }
532 break;
533 }
534 #endif
535 case Expose:
536 {
537 if (win)
538 {
539 win->GetUpdateRegion().Union( event->xexpose.x, event->xexpose.y,
540 event->xexpose.width, event->xexpose.height);
541
542 win->GetClearRegion().Union( event->xexpose.x, event->xexpose.y,
543 event->xexpose.width, event->xexpose.height);
544
545 // if (event->xexpose.count == 0)
546 // win->Update();
547 }
548
549 return;
550 }
551 case GraphicsExpose:
552 {
553 if (win)
554 {
555 wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(),
556 event->xgraphicsexpose.x, event->xgraphicsexpose.y,
557 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
558
559 win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
560 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
561
562 win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
563 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
564
565 // if (event->xgraphicsexpose.count == 0)
566 // win->Update();
567 }
568
569 return;
570 }
571 case EnterNotify:
572 case LeaveNotify:
573 case ButtonPress:
574 case ButtonRelease:
575 case MotionNotify:
576 {
577 if (win && !win->IsEnabled())
578 return;
579
580 if (win)
581 {
582 wxMouseEvent wxevent;
583 wxTranslateMouseEvent(wxevent, win, window, event);
584 win->GetEventHandler()->ProcessEvent( wxevent );
585 }
586 return;
587 }
588 case FocusIn:
589 {
590 #if !wxUSE_NANOX
591 if (win && event->xfocus.detail != NotifyPointer)
592 #endif
593 {
594 wxLogDebug( "FocusIn from %s", win->GetName().c_str() );
595
596 wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
597 focusEvent.SetEventObject(win);
598 win->GetEventHandler()->ProcessEvent(focusEvent);
599 }
600 break;
601 }
602 case FocusOut:
603 {
604 #if !wxUSE_NANOX
605 if (win && event->xfocus.detail != NotifyPointer)
606 #endif
607 {
608 wxLogDebug( "FocusOut from %s", win->GetName().c_str() );
609
610 wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
611 focusEvent.SetEventObject(win);
612 win->GetEventHandler()->ProcessEvent(focusEvent);
613 }
614 break;
615 }
616 case DestroyNotify:
617 {
618 // Do we want to process this (for top-level windows)?
619 // But we want to be able to veto closes, anyway
620 break;
621 }
622 default:
623 {
624 #ifdef __WXDEBUG__
625 //wxString eventName = wxGetXEventName(XEvent& event);
626 //wxLogDebug(wxT("Event %s not handled"), eventName.c_str());
627 #endif
628 break;
629 }
630 }
631 }
632
633 // Returns TRUE if more time is needed.
634 // Note that this duplicates wxEventLoopImpl::SendIdleEvent
635 // but ProcessIdle may be needed by apps, so is kept.
636 bool wxApp::ProcessIdle()
637 {
638 wxIdleEvent event;
639 event.SetEventObject(this);
640 ProcessEvent(event);
641
642 return event.MoreRequested();
643 }
644
645 void wxApp::ExitMainLoop()
646 {
647 if (m_mainLoop)
648 m_mainLoop->Exit(0);
649 }
650
651 // Is a message/event pending?
652 bool wxApp::Pending()
653 {
654 return wxEventLoop::GetActive()->Pending();
655 }
656
657 // Dispatch a message.
658 void wxApp::Dispatch()
659 {
660 wxEventLoop::GetActive()->Dispatch();
661 }
662
663 // This should be redefined in a derived class for
664 // handling property change events for XAtom IPC.
665 void wxApp::HandlePropertyChange(WXEvent *event)
666 {
667 // by default do nothing special
668 // TODO: what to do for X11
669 // XtDispatchEvent((XEvent*) event);
670 }
671
672 void wxApp::OnIdle(wxIdleEvent& event)
673 {
674 static bool s_inOnIdle = FALSE;
675
676 // Avoid recursion (via ProcessEvent default case)
677 if (s_inOnIdle)
678 return;
679
680 s_inOnIdle = TRUE;
681
682 // Resend in the main thread events which have been prepared in other
683 // threads
684 ProcessPendingEvents();
685
686 // 'Garbage' collection of windows deleted with Close()
687 DeletePendingObjects();
688
689 // Send OnIdle events to all windows
690 bool needMore = SendIdleEvents();
691
692 if (needMore)
693 event.RequestMore(TRUE);
694
695 s_inOnIdle = FALSE;
696 }
697
698 void wxWakeUpIdle()
699 {
700 // **** please implement me! ****
701 // Wake up the idle handler processor, even if it is in another thread...
702 }
703
704
705 // Send idle event to all top-level windows
706 bool wxApp::SendIdleEvents()
707 {
708 bool needMore = FALSE;
709
710 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
711 while (node)
712 {
713 wxWindow* win = node->GetData();
714 if (SendIdleEvents(win))
715 needMore = TRUE;
716 node = node->GetNext();
717 }
718
719 return needMore;
720 }
721
722 // Send idle event to window and all subwindows
723 bool wxApp::SendIdleEvents(wxWindow* win)
724 {
725 bool needMore = FALSE;
726
727 wxIdleEvent event;
728 event.SetEventObject(win);
729
730 win->GetEventHandler()->ProcessEvent(event);
731
732 win->OnInternalIdle();
733
734 if (event.MoreRequested())
735 needMore = TRUE;
736
737 wxNode* node = win->GetChildren().First();
738 while (node)
739 {
740 wxWindow* win = (wxWindow*) node->Data();
741 if (SendIdleEvents(win))
742 needMore = TRUE;
743
744 node = node->Next();
745 }
746
747 return needMore;
748 }
749
750 void wxApp::DeletePendingObjects()
751 {
752 wxNode *node = wxPendingDelete.First();
753 while (node)
754 {
755 wxObject *obj = (wxObject *)node->Data();
756
757 delete obj;
758
759 if (wxPendingDelete.Member(obj))
760 delete node;
761
762 // Deleting one object may have deleted other pending
763 // objects, so start from beginning of list again.
764 node = wxPendingDelete.First();
765 }
766 }
767
768 // Create display, and other initialization
769 bool wxApp::OnInitGui()
770 {
771 // Eventually this line will be removed, but for
772 // now we don't want to try popping up a dialog
773 // for error messages.
774 delete wxLog::SetActiveTarget(new wxLogStderr);
775
776 if (!wxAppBase::OnInitGui())
777 return FALSE;
778
779 GetMainColormap( wxApp::GetDisplay() );
780
781 m_maxRequestSize = XMaxRequestSize( (Display*) wxApp::GetDisplay() );
782
783 return TRUE;
784 }
785
786 WXColormap wxApp::GetMainColormap(WXDisplay* display)
787 {
788 if (!display) /* Must be called first with non-NULL display */
789 return m_mainColormap;
790
791 int defaultScreen = DefaultScreen((Display*) display);
792 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
793
794 Colormap c = DefaultColormapOfScreen(screen);
795
796 if (!m_mainColormap)
797 m_mainColormap = (WXColormap) c;
798
799 return (WXColormap) c;
800 }
801
802 Window wxGetWindowParent(Window window)
803 {
804 wxASSERT_MSG( window, "invalid window" );
805
806 return (Window) 0;
807
808 Window parent, root = 0;
809 unsigned int noChildren = 0;
810 Window* children = NULL;
811 int res = XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
812 & children, & noChildren);
813 if (children)
814 XFree(children);
815 if (res)
816 return parent;
817 else
818 return (Window) 0;
819 }
820
821 void wxExit()
822 {
823 int retValue = 0;
824 if (wxTheApp)
825 retValue = wxTheApp->OnExit();
826
827 wxApp::CleanUp();
828 /*
829 * Exit in some platform-specific way. Not recommended that the app calls this:
830 * only for emergencies.
831 */
832 exit(retValue);
833 }
834
835 // Yield to other processes
836
837 bool wxApp::Yield(bool onlyIfNeeded)
838 {
839 bool s_inYield = FALSE;
840
841 if ( s_inYield )
842 {
843 if ( !onlyIfNeeded )
844 {
845 wxFAIL_MSG( wxT("wxYield called recursively" ) );
846 }
847
848 return FALSE;
849 }
850
851 s_inYield = TRUE;
852
853 while (wxTheApp && wxTheApp->Pending())
854 wxTheApp->Dispatch();
855
856 s_inYield = FALSE;
857
858 return TRUE;
859 }
860
861 // XPM hack: make the arrays const
862 #define static static const
863
864 #include "wx/generic/info.xpm"
865 #include "wx/generic/error.xpm"
866 #include "wx/generic/question.xpm"
867 #include "wx/generic/warning.xpm"
868
869 #undef static
870
871 wxIcon
872 wxApp::GetStdIcon(int which) const
873 {
874 switch(which)
875 {
876 case wxICON_INFORMATION:
877 return wxIcon(info_xpm);
878
879 case wxICON_QUESTION:
880 return wxIcon(question_xpm);
881
882 case wxICON_EXCLAMATION:
883 return wxIcon(warning_xpm);
884
885 default:
886 wxFAIL_MSG("requested non existent standard icon");
887 // still fall through
888
889 case wxICON_HAND:
890 return wxIcon(error_xpm);
891 }
892 }
893
894 void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
895 {
896 // While the GUI isn't working that well, just print out the
897 // message.
898 #if 0
899 wxAppBase::OnAssert(file, line, msg);
900 #else
901 wxString msg2;
902 msg2.Printf("At file %s:%d: %s", file, line, msg);
903 wxLogDebug(msg2);
904 #endif
905 }
906