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