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