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