some os/2 icon-bitmap fixes
[wxWidgets.git] / src / os2 / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
3 // Purpose: wxApp
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/13/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/pen.h"
21 #include "wx/brush.h"
22 #include "wx/cursor.h"
23 #include "wx/icon.h"
24 #include "wx/palette.h"
25 #include "wx/dc.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/intl.h"
29 #include "wx/dynarray.h"
30 # include "wx/wxchar.h"
31 # include "wx/icon.h"
32 #endif
33
34 #include "wx/log.h"
35 #include "wx/module.h"
36
37 #include "wx/os2/private.h"
38
39 #if wxUSE_THREADS
40 #include "wx/thread.h"
41
42 // define the array of QMSG strutures
43 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
44
45 #include "wx/arrimpl.cpp"
46
47 WX_DEFINE_OBJARRAY(wxMsgArray);
48 #endif // wxUSE_THREADS
49
50 #if wxUSE_WX_RESOURCES
51 #include "wx/resource.h"
52 #endif
53
54 #include <string.h>
55 #include <ctype.h>
56
57 // ---------------------------------------------------------------------------
58 // global variables
59 // ---------------------------------------------------------------------------
60
61 extern wxChar* wxBuffer;
62 extern wxChar* wxOsVersion;
63 extern wxList* wxWinHandleList;
64 extern wxList WXDLLEXPORT wxPendingDelete;
65 extern void wxSetKeyboardHook(bool doIt);
66 extern wxCursor* g_globalCursor;
67
68 HINSTANCE wxhInstance = 0;
69 QMSG svCurrentMsg;
70 wxApp* wxTheApp = NULL;
71 HAB vHabmain = NULL;
72
73 // FIXME why not const? and not static?
74
75 // NB: all "NoRedraw" classes must have the same names as the "normal" classes
76 // with NR suffix - wxWindow::OS2Create() supposes this
77 wxChar wxFrameClassName[] = wxT("wxFrameClass");
78 wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
79 wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
80 wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
81 wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
82 wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
83 wxChar wxPanelClassName[] = wxT("wxPanelClass");
84 wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
85
86 HICON wxSTD_FRAME_ICON = (HICON) NULL;
87 HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
88 HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
89
90 HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
91 HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
92 HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
93
94 HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
95
96 MRESULT wxWndProc(HWND, UINT, MPARAM, MPARAM);
97
98 // ===========================================================================
99 // implementation
100 // ===========================================================================
101
102 // ---------------------------------------------------------------------------
103 // wxApp
104 // ---------------------------------------------------------------------------
105
106 #if !USE_SHARED_LIBRARY
107 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
108
109 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
110 EVT_IDLE(wxApp::OnIdle)
111 EVT_END_SESSION(wxApp::OnEndSession)
112 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
113 END_EVENT_TABLE()
114 #endif
115
116 //// Initialize
117 bool wxApp::Initialize(
118 HAB vHab
119 )
120 {
121 // Some people may wish to use this, but
122 // probably it shouldn't be here by default.
123 #ifdef __WXDEBUG__
124 // wxRedirectIOToConsole();
125 #endif
126
127 wxBuffer = new wxChar[1500]; // FIXME; why?
128
129 wxClassInfo::InitializeClasses();
130
131 #if wxUSE_RESOURCES
132 wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
133 #endif
134
135 // I'm annoyed ... I don't know where to put this and I don't want to
136 // create a module for that as it's part of the core.
137 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
138 wxTheColourDatabase->Initialize();
139
140 wxInitializeStockLists();
141 wxInitializeStockObjects();
142
143 #if wxUSE_WX_RESOURCES
144 wxInitializeResourceSystem();
145 #endif
146
147 wxBitmap::InitStandardHandlers();
148
149 g_globalCursor = new wxCursor;
150
151 #if 0
152 wxSTD_FRAME_ICON = ::WinLoadFileIcon(wxT("wxSTD_FRAME"), TRUE);
153 wxSTD_MDIPARENTFRAME_ICON = ::WinLoadFileIcon(wxT("wxSTD_MDIPARENTFRAME"), TRUE);
154 wxSTD_MDICHILDFRAME_ICON = ::WinLoadFileIcon(wxT("wxSTD_MDICHILDFRAME"), TRUE);
155
156 wxDEFAULT_FRAME_ICON = ::WinLoadFileIcon(wxT("wxDEFAULT_FRAME"), TRUE);
157 wxDEFAULT_MDIPARENTFRAME_ICON = ::WinLoadFileIcon(wxT("wxDEFAULT_MDIPARENTFRAME"), TRUE);
158 wxDEFAULT_MDICHILDFRAME_ICON = ::WinLoadFileIcon(wxT("wxDEFAULT_MDICHILDFRAME"), TRUE);
159 #endif
160 RegisterWindowClasses(vHab);
161 wxWinHandleList = new wxList(wxKEY_INTEGER);
162
163 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
164 // PLEASE DO NOT ALTER THIS.
165 #if !defined(WXMAKINGDLL)
166 extern char wxDummyChar;
167 if (wxDummyChar) wxDummyChar++;
168 #endif
169
170 wxSetKeyboardHook(TRUE);
171
172 wxModule::RegisterModules();
173 if (!wxModule::InitializeModules())
174 return FALSE;
175 return TRUE;
176 }
177
178 // ---------------------------------------------------------------------------
179 // RegisterWindowClasses
180 // ---------------------------------------------------------------------------
181
182 // TODO we should only register classes really used by the app. For this it
183 // would be enough to just delay the class registration until an attempt
184 // to create a window of this class is made.
185 bool wxApp::RegisterWindowClasses(
186 HAB vHab
187 )
188 {
189 APIRET rc;
190
191 if ((rc = ::WinRegisterClass( vHab
192 ,wxFrameClassName
193 ,(PFNWP)wxWndProc
194 ,CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST | CS_CLIPCHILDREN | CS_FRAME
195 ,0
196 )) != 0)
197 {
198 wxLogLastError("RegisterClass(frame)");
199
200 return FALSE;
201 }
202
203 if (!::WinRegisterClass( vHab
204 ,wxFrameClassNameNoRedraw
205 ,(PFNWP)wxWndProc
206 ,CS_HITTEST | CS_CLIPCHILDREN | CS_FRAME
207 ,0
208 ))
209 {
210 wxLogLastError("RegisterClass(no redraw frame)");
211
212 return FALSE;
213 }
214
215 if (!::WinRegisterClass( vHab
216 ,wxMDIFrameClassName
217 ,(PFNWP)wxWndProc
218 ,CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST | CS_CLIPCHILDREN | CS_FRAME
219 ,0
220 ))
221 {
222 wxLogLastError("RegisterClass(MDI parent)");
223
224 return FALSE;
225 }
226
227 if (!::WinRegisterClass( vHab
228 ,wxMDIFrameClassNameNoRedraw
229 ,(PFNWP)wxWndProc
230 ,CS_HITTEST | CS_CLIPCHILDREN | CS_FRAME
231 ,0
232 ))
233 {
234 wxLogLastError("RegisterClass(no redraw MDI parent)");
235
236 return FALSE;
237 }
238
239 if (!::WinRegisterClass( vHab
240 ,wxMDIChildFrameClassName
241 ,(PFNWP)wxWndProc
242 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST | CS_CLIPSIBLINGS | CS_FRAME
243 ,0
244 ))
245 {
246 wxLogLastError("RegisterClass(MDI child)");
247
248 return FALSE;
249 }
250
251 if (!::WinRegisterClass( vHab
252 ,wxMDIChildFrameClassNameNoRedraw
253 ,(PFNWP)wxWndProc
254 ,CS_HITTEST | CS_CLIPSIBLINGS | CS_FRAME
255 ,0
256 ))
257 {
258 wxLogLastError("RegisterClass(no redraw MDI child)");
259
260 return FALSE;
261 }
262
263 if (!::WinRegisterClass( vHab
264 ,wxPanelClassName
265 ,(PFNWP)wxWndProc
266 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_CLIPSIBLINGS | CS_SAVEBITS | CS_SYNCPAINT
267 ,0
268 ))
269 {
270 wxLogLastError("RegisterClass(Panel)");
271
272 return FALSE;
273 }
274
275 if (!::WinRegisterClass( vHab
276 ,wxCanvasClassName
277 ,(PFNWP)wxWndProc
278 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_CLIPSIBLINGS | CS_SAVEBITS | CS_SYNCPAINT
279 ,0
280 ))
281 {
282 wxLogLastError("RegisterClass(Canvas)");
283
284 return FALSE;
285 }
286 return TRUE;
287 }
288
289 //// Cleans up any wxWindows internal structures left lying around
290
291 void wxApp::CleanUp()
292 {
293 //// COMMON CLEANUP
294
295 #if wxUSE_LOG
296 // flush the logged messages if any and install a 'safer' log target: the
297 // default one (wxLogGui) can't be used after the resources are freed just
298 // below and the user suppliedo ne might be even more unsafe (using any
299 // wxWindows GUI function is unsafe starting from now)
300 wxLog::DontCreateOnDemand();
301
302 // this will flush the old messages if any
303 delete wxLog::SetActiveTarget(new wxLogStderr);
304 #endif // wxUSE_LOG
305
306 // One last chance for pending objects to be cleaned up
307 wxTheApp->DeletePendingObjects();
308
309 wxModule::CleanUpModules();
310
311 #if wxUSE_WX_RESOURCES
312 wxCleanUpResourceSystem();
313
314 // wxDefaultResourceTable->ClearTable();
315 #endif
316
317 // Indicate that the cursor can be freed, so that cursor won't be deleted
318 // by deleting the bitmap list before g_globalCursor goes out of scope
319 // (double deletion of the cursor).
320 wxSetCursor(wxNullCursor);
321 delete g_globalCursor;
322 g_globalCursor = NULL;
323
324 wxDeleteStockObjects();
325
326 // Destroy all GDI lists, etc.
327 wxDeleteStockLists();
328
329 delete wxTheColourDatabase;
330 wxTheColourDatabase = NULL;
331
332 wxBitmap::CleanUpHandlers();
333
334 delete[] wxBuffer;
335 wxBuffer = NULL;
336
337 //// WINDOWS-SPECIFIC CLEANUP
338
339 wxSetKeyboardHook(FALSE);
340
341 if (wxSTD_FRAME_ICON)
342 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
343 if (wxSTD_MDICHILDFRAME_ICON)
344 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
345 if (wxSTD_MDIPARENTFRAME_ICON)
346 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
347
348 if (wxDEFAULT_FRAME_ICON)
349 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
350 if (wxDEFAULT_MDICHILDFRAME_ICON)
351 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
352 if (wxDEFAULT_MDIPARENTFRAME_ICON)
353 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
354
355 if ( wxDisableButtonBrush )
356 {
357 // TODO: ::DeleteObject( wxDisableButtonBrush );
358 }
359
360 if (wxWinHandleList)
361 delete wxWinHandleList;
362
363 // GL: I'm annoyed ... I don't know where to put this and I don't want to
364 // create a module for that as it's part of the core.
365 #if wxUSE_THREADS
366 delete wxPendingEvents;
367 delete wxPendingEventsLocker;
368 // If we don't do the following, we get an apparent memory leak.
369 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
370 #endif
371
372 wxClassInfo::CleanUpClasses();
373
374 delete wxTheApp;
375 wxTheApp = NULL;
376
377 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
378 // At this point we want to check if there are any memory
379 // blocks that aren't part of the wxDebugContext itself,
380 // as a special case. Then when dumping we need to ignore
381 // wxDebugContext, too.
382 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
383 {
384 wxLogDebug(wxT("There were memory leaks."));
385 wxDebugContext::Dump();
386 wxDebugContext::PrintStatistics();
387 }
388 // wxDebugContext::SetStream(NULL, NULL);
389 #endif
390
391 #if wxUSE_LOG
392 // do it as the very last thing because everything else can log messages
393 delete wxLog::SetActiveTarget(NULL);
394 #endif // wxUSE_LOG
395 }
396
397 int wxEntry(
398 int argc
399 , char* argv[]
400 )
401 {
402 HAB vHab;
403
404 if (!wxApp::Initialize(vHab))
405 return 0;
406
407 //
408 // create the application object or ensure that one already exists
409 //
410 if (!wxTheApp)
411 {
412 wxCHECK_MSG( wxApp::GetInitializerFunction()
413 ,-1
414 ,wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n")
415 );
416
417 wxAppInitializerFunction fnAppIni = wxApp::GetInitializerFunction();
418 wxObject* pTest_app = fnAppIni();
419
420 wxTheApp = (wxApp*)pTest_app;
421 }
422 wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") );
423 wxTheApp->argc = argc;
424
425 #if wxUSE_UNICODE
426 wxTheApp->argv = new wxChar*[argc+1];
427
428 int nArgc = 0;
429
430 while (nArgc < argc)
431 {
432 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
433 nArgc++;
434 }
435 wxTheApp->argv[nArgc] = (wxChar *)NULL;
436 #else
437 wxTheApp->argv = argv;
438 #endif
439
440 wxString sName(wxFileNameFromPath(argv[0]));
441
442 wxStripExtension(sName);
443 wxTheApp->SetAppName(sName);
444
445 int nRetValue = 0;
446
447 if (!wxTheApp->OnInitGui())
448 nRetValue = -1;
449
450 if (nRetValue == 0)
451 {
452 if (wxTheApp->OnInit())
453 {
454 nRetValue = -1;
455 }
456 }
457
458 if (nRetValue == 0)
459 {
460 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
461
462 if (pTopWindow)
463 {
464 // Forcibly delete the window.
465 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
466 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
467 {
468 pTopWindow->Close(TRUE);
469 wxTheApp->DeletePendingObjects();
470 }
471 else
472 {
473 delete pTopWindow;
474 wxTheApp->SetTopWindow(NULL);
475 }
476 }
477 }
478 wxTheApp->OnExit();
479 wxApp::CleanUp();
480 return(nRetValue);
481 }
482
483 bool wxApp::OnInitGui()
484 {
485 vHabmain = WinInitialize(0);
486 m_hMq = WinCreateMsgQueue(vHabmain, 0);
487
488 return TRUE;
489 }
490
491 //
492 // Static member initialization
493 //
494 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
495
496 wxApp::wxApp()
497 {
498 m_topWindow = NULL;
499 wxTheApp = this;
500 m_wantDebugOutput = TRUE;
501
502 argc = 0;
503 argv = NULL;
504 m_nPrintMode = wxPRINT_WINDOWS;
505 m_exitOnFrameDelete = TRUE;
506 m_bAuto3D = TRUE;
507 }
508
509 wxApp::~wxApp()
510 {
511 // Delete command-line args
512 int i;
513 for (i = 0; i < argc; i++)
514 {
515 delete[] argv[i];
516 }
517 delete[] argv;
518 }
519
520 bool wxApp::Initialized()
521 {
522 if (GetTopWindow())
523 return TRUE;
524 else
525 return FALSE;
526 }
527
528 //
529 // Get and process a message, returning FALSE if WM_QUIT
530 // received (and also set the flag telling the app to exit the main loop)
531 //
532 bool wxApp::DoMessage()
533 {
534 BOOL bRc = ::WinGetMsg(vHabmain, &m_vMsg, HWND(NULL), 0, 0);
535
536 if (bRc == 0)
537 {
538 // got WM_QUIT
539 m_bKeepGoing = FALSE;
540 return FALSE;
541 }
542 else if (bRc == -1)
543 {
544 // should never happen, but let's test for it nevertheless
545 wxLogLastError("GetMessage");
546 }
547 else
548 {
549 #if wxUSE_THREADS
550 wxASSERT_MSG( wxThread::IsMain()
551 ,wxT("only the main thread can process Windows messages")
552 );
553
554 static bool sbHadGuiLock = TRUE;
555 static wxMsgArray svSavedMessages;
556
557 //
558 // if a secondary thread owns is doing GUI calls, save all messages for
559 // later processing - we can't process them right now because it will
560 // lead to recursive library calls (and we're not reentrant)
561 //
562 if (!wxGuiOwnedByMainThread())
563 {
564 sbHadGuiLock = FALSE;
565
566 // leave out WM_COMMAND messages: too dangerous, sometimes
567 // the message will be processed twice
568 if ( !wxIsWaitingForThread() ||
569 svCurrentMsg.msg != WM_COMMAND )
570 {
571 svSavedMessages.Add(svCurrentMsg);
572 }
573 return TRUE;
574 }
575 else
576 {
577 //
578 // have we just regained the GUI lock? if so, post all of the saved
579 // messages
580 //
581 // FIXME of course, it's not _exactly_ the same as processing the
582 // messages normally - expect some things to break...
583 //
584 if (!sbHadGuiLock )
585 {
586 sbHadGuiLock = TRUE;
587
588 size_t nCount = svSavedMessages.Count();
589
590 for (size_t n = 0; n < nCount; n++)
591 {
592 QMSG vMsg = svSavedMessages[n];
593
594 if ( !ProcessMessage((WXMSG *)&vMsg) )
595 {
596 ::WinDispatchMsg(vHabmain, &vMsg);
597 }
598 }
599 svSavedMessages.Empty();
600 }
601 }
602 #endif // wxUSE_THREADS
603
604 // Process the message
605 if (!ProcessMessage((WXMSG *)&svCurrentMsg) )
606 {
607 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
608 }
609 }
610 return TRUE;
611 }
612
613 //////////////////////////////////////////////////////////////////////////////
614 //
615 // Keep trying to process messages until WM_QUIT
616 // received.
617 //
618 // If there are messages to be processed, they will all be
619 // processed and OnIdle will not be called.
620 // When there are no more messages, OnIdle is called.
621 // If OnIdle requests more time,
622 // it will be repeatedly called so long as there are no pending messages.
623 // A 'feature' of this is that once OnIdle has decided that no more processing
624 // is required, then it won't get processing time until further messages
625 // are processed (it'll sit in DoMessage).
626 //
627 //////////////////////////////////////////////////////////////////////////////
628 int wxApp::MainLoop()
629 {
630 m_bKeepGoing = TRUE;
631
632 while (m_bKeepGoing)
633 {
634 #if wxUSE_THREADS
635 wxMutexGuiLeaveOrEnter();
636 #endif // wxUSE_THREADS
637 while (!::WinPeekMsg(vHabmain, &svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) &&
638 ProcessIdle() )
639 {
640 }
641 DoMessage();
642 }
643 return (int)svCurrentMsg.mp1;
644 }
645
646 //
647 // Returns TRUE if more time is needed.
648 //
649 bool wxApp::ProcessIdle()
650 {
651 wxIdleEvent vEvent;
652
653 vEvent.SetEventObject(this);
654 ProcessEvent(vEvent);
655 return vEvent.MoreRequested();
656 }
657
658 #if wxUSE_THREADS
659 void wxApp::ProcessPendingEvents()
660 {
661 wxNode* pNode = wxPendingEvents->First();
662 wxCriticalSectionLocker vLocker(*wxPendingEventsLocker);
663
664 while (pNode)
665 {
666 wxEvtHandler* pHandler = (wxEvtHandler *)pNode->Data();
667 pHandler->ProcessPendingEvents();
668
669 delete pNode;
670 pNode = wxPendingEvents->First();
671 }
672 }
673 #endif
674
675 void wxApp::ExitMainLoop()
676 {
677 m_bKeepGoing = FALSE;
678 }
679
680 bool wxApp::Pending()
681 {
682 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
683 }
684
685 void wxApp::Dispatch()
686 {
687 DoMessage();
688 }
689
690 //////////////////////////////////////////////////////////////////////////////
691 //
692 // Give all windows a chance to preprocess
693 // the message. Some may have accelerator tables, or have
694 // MDI complications.
695 //
696 //////////////////////////////////////////////////////////////////////////////
697 bool wxApp::ProcessMessage(
698 WXMSG* pWxmsg
699 )
700 {
701 QMSG* vMsg = (PQMSG)pWxmsg;
702 HWND hWnd = vMsg->hwnd;
703 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
704 wxWindow* pWnd;
705
706 //
707 // for some composite controls (like a combobox), wndThis might be NULL
708 // because the subcontrol is not a wxWindow, but only the control itself
709 // is - try to catch this case
710 //
711 while (hWnd && !pWndThis)
712 {
713 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
714 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
715 }
716
717 // Anyone for a non-translation message? Try youngest descendants first.
718 for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
719 {
720 if (pWnd->OS2ProcessMessage(pWxmsg))
721 return TRUE;
722 }
723 return FALSE;
724 }
725
726 void wxApp::OnIdle(
727 wxIdleEvent& rEvent
728 )
729 {
730 static bool sbInOnIdle = FALSE;
731
732 //
733 // Avoid recursion (via ProcessEvent default case)
734 //
735 if (sbInOnIdle )
736 return;
737
738 sbInOnIdle = TRUE;
739
740 //
741 // 'Garbage' collection of windows deleted with Close().
742 //
743 DeletePendingObjects();
744
745 #if wxUSE_LOG
746 // flush the logged messages if any
747 wxLog* pLog = wxLog::GetActiveTarget();
748
749 if (pLog != NULL && pLog->HasPendingMessages())
750 pLog->Flush();
751 #endif // wxUSE_LOG
752
753 // Send OnIdle events to all windows
754 if (SendIdleEvents())
755 {
756 //
757 // SendIdleEvents() returns TRUE if at least one window requested more
758 // idle events
759 //
760 rEvent.RequestMore(TRUE);
761 }
762
763 //
764 // If they are pending events, we must process them.
765 //
766 #if wxUSE_THREADS
767 ProcessPendingEvents();
768 #endif
769 sbInOnIdle = FALSE;
770 }
771
772 void wxWakeUpIdle()
773 {
774 // **** please implement me! ****
775 // Wake up the idle handler processor, even if it is in another thread...
776 }
777
778 // Send idle event to all top-level windows
779 bool wxApp::SendIdleEvents()
780 {
781 bool bNeedMore = FALSE;
782 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
783
784 while (pNode)
785 {
786 wxWindow* pWin = pNode->GetData();
787
788 if (SendIdleEvents(pWin))
789 bNeedMore = TRUE;
790 pNode = pNode->GetNext();
791 }
792 return bNeedMore;
793 }
794
795 //
796 // Send idle event to window and all subwindows
797 //
798 bool wxApp::SendIdleEvents(
799 wxWindow* pWin
800 )
801 {
802 bool bNeedMore = FALSE;
803 wxIdleEvent vEvent;
804
805 vEvent.SetEventObject(pWin);
806 pWin->GetEventHandler()->ProcessEvent(vEvent);
807
808 if (vEvent.MoreRequested())
809 bNeedMore = TRUE;
810
811 wxNode* pNode = pWin->GetChildren().First();
812
813 while (pNode)
814 {
815 wxWindow* pWin = (wxWindow*) pNode->Data();
816
817 if (SendIdleEvents(pWin))
818 bNeedMore = TRUE;
819 pNode = pNode->Next();
820 }
821 return bNeedMore;
822 }
823
824 void wxApp::DeletePendingObjects()
825 {
826 wxNode* pNode = wxPendingDelete.First();
827
828 while (pNode)
829 {
830 wxObject* pObj = (wxObject *)pNode->Data();
831
832 delete pObj;
833
834 if (wxPendingDelete.Member(pObj))
835 delete pNode;
836
837 //
838 // Deleting one object may have deleted other pending
839 // objects, so start from beginning of list again.
840 //
841 pNode = wxPendingDelete.First();
842 }
843 }
844
845 void wxApp::OnEndSession(
846 wxCloseEvent& WXUNUSED(rEvent))
847 {
848 if (GetTopWindow())
849 GetTopWindow()->Close(TRUE);
850 }
851
852 //
853 // Default behaviour: close the application with prompts. The
854 // user can veto the close, and therefore the end session.
855 //
856 void wxApp::OnQueryEndSession(
857 wxCloseEvent& rEvent
858 )
859 {
860 if (GetTopWindow())
861 {
862 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
863 rEvent.Veto(TRUE);
864 }
865 }
866
867 void wxExit()
868 {
869 wxLogError(_("Fatal error: exiting"));
870
871 wxApp::CleanUp();
872 }
873
874 // Yield to incoming messages
875 bool wxYield()
876 {
877 HAB vHab;
878 QMSG vMsg;
879 // We want to go back to the main message loop
880 // if we see a WM_QUIT. (?)
881 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
882 {
883 if (!wxTheApp->DoMessage())
884 break;
885 }
886 // If they are pending events, we must process them.
887 #if wxUSE_THREADS
888 wxTheApp->ProcessPendingEvents();
889 #endif
890 return TRUE;
891 }
892
893 wxIcon wxApp::GetStdIcon(
894 int nWhich
895 ) const
896 {
897 switch(nWhich)
898 {
899 case wxICON_INFORMATION:
900 return wxIcon("wxICON_INFO");
901
902 case wxICON_QUESTION:
903 return wxIcon("wxICON_QUESTION");
904
905 case wxICON_EXCLAMATION:
906 return wxIcon("wxICON_WARNING");
907
908 default:
909 wxFAIL_MSG(wxT("requested non existent standard icon"));
910 // still fall through
911
912 case wxICON_HAND:
913 return wxIcon("wxICON_ERROR");
914 }
915 return wxIcon("wxICON_ERROR");
916 }
917
918 HINSTANCE wxGetInstance()
919 {
920 return wxhInstance;
921 }
922
923 void wxSetInstance(HINSTANCE hInst)
924 {
925 wxhInstance = hInst;
926 }
927