OS/2 Statusbar fixes, and class interface 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 #if wxUSE_TOOLTIPS
55 #include "wx/tooltip.h"
56 #endif // wxUSE_TOOLTIPS
57
58 #include <string.h>
59 #include <ctype.h>
60
61 // ---------------------------------------------------------------------------
62 // global variables
63 // ---------------------------------------------------------------------------
64
65 extern wxChar* wxBuffer;
66 extern wxList* wxWinHandleList;
67 extern wxList WXDLLEXPORT wxPendingDelete;
68 extern wxCursor* g_globalCursor;
69
70 HAB vHabmain = NULLHANDLE;
71 QMSG svCurrentMsg;
72 wxApp* wxTheApp = NULL;
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 // ===========================================================================
96 // implementation
97 // ===========================================================================
98
99 // ---------------------------------------------------------------------------
100 // wxApp
101 // ---------------------------------------------------------------------------
102
103 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
104
105 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
106 EVT_IDLE(wxApp::OnIdle)
107 EVT_END_SESSION(wxApp::OnEndSession)
108 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
109 END_EVENT_TABLE()
110
111 //
112 // Initialize
113 //
114 bool wxApp::Initialize(
115 HAB vHab
116 )
117 {
118 //
119 // OS2 has to have an anchorblock
120 //
121 vHab = WinInitialize(0);
122
123 if (!vHab)
124 return FALSE;
125 else
126 vHabmain = vHab;
127
128 // Some people may wish to use this, but
129 // probably it shouldn't be here by default.
130 #ifdef __WXDEBUG__
131 // wxRedirectIOToConsole();
132 #endif
133
134 wxBuffer = new wxChar[1500]; // FIXME; why?
135
136 wxClassInfo::InitializeClasses();
137
138 #if wxUSE_THREADS
139 wxPendingEventsLocker = new wxCriticalSection;
140 #endif
141
142 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
143 wxTheColourDatabase->Initialize();
144
145 wxInitializeStockLists();
146 wxInitializeStockObjects();
147
148 #if wxUSE_WX_RESOURCES
149 wxInitializeResourceSystem();
150 #endif
151
152 wxBitmap::InitStandardHandlers();
153
154 RegisterWindowClasses(vHab);
155 wxWinHandleList = new wxList(wxKEY_INTEGER);
156
157 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
158 // PLEASE DO NOT ALTER THIS.
159 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
160 extern char wxDummyChar;
161 if (wxDummyChar) wxDummyChar++;
162 #endif
163
164 // wxSetKeyboardHook(TRUE);
165
166 wxModule::RegisterModules();
167 if (!wxModule::InitializeModules())
168 return FALSE;
169 return TRUE;
170 } // end of wxApp::Initialize
171
172 // ---------------------------------------------------------------------------
173 // RegisterWindowClasses
174 // ---------------------------------------------------------------------------
175
176 bool wxApp::RegisterWindowClasses(
177 HAB vHab
178 )
179 {
180 APIRET rc;
181 ERRORID vError = 0L;
182 wxString sError;
183
184 if (!::WinRegisterClass( vHab
185 ,wxFrameClassName
186 ,NULL
187 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
188 ,sizeof(ULONG)
189 ))
190 {
191 vError = ::WinGetLastError(vHab);
192 sError = wxPMErrorToStr(vError);
193 wxLogLastError(sError);
194 return FALSE;
195 }
196
197 if (!::WinRegisterClass( vHab
198 ,wxFrameClassNameNoRedraw
199 ,NULL
200 ,0
201 ,0
202 ))
203 {
204 vError = ::WinGetLastError(vHab);
205 sError = wxPMErrorToStr(vError);
206 wxLogLastError(sError);
207 return FALSE;
208 }
209
210 if (!::WinRegisterClass( vHab
211 ,wxMDIFrameClassName
212 ,NULL
213 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
214 ,0
215 ))
216 {
217 vError = ::WinGetLastError(vHab);
218 sError = wxPMErrorToStr(vError);
219 wxLogLastError(sError);
220 return FALSE;
221 }
222
223 if (!::WinRegisterClass( vHab
224 ,wxMDIFrameClassNameNoRedraw
225 ,NULL
226 ,0
227 ,0
228 ))
229 {
230 vError = ::WinGetLastError(vHab);
231 sError = wxPMErrorToStr(vError);
232 wxLogLastError(sError);
233 return FALSE;
234 }
235
236 if (!::WinRegisterClass( vHab
237 ,wxMDIChildFrameClassName
238 ,NULL
239 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
240 ,0
241 ))
242 {
243 vError = ::WinGetLastError(vHab);
244 sError = wxPMErrorToStr(vError);
245 wxLogLastError(sError);
246 return FALSE;
247 }
248
249 if (!::WinRegisterClass( vHab
250 ,wxMDIChildFrameClassNameNoRedraw
251 ,NULL
252 ,CS_HITTEST
253 ,0
254 ))
255 {
256 vError = ::WinGetLastError(vHab);
257 sError = wxPMErrorToStr(vError);
258 wxLogLastError(sError);
259 return FALSE;
260 }
261
262 if (!::WinRegisterClass( vHab
263 ,wxPanelClassName
264 ,NULL
265 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
266 ,0
267 ))
268 {
269 vError = ::WinGetLastError(vHab);
270 sError = wxPMErrorToStr(vError);
271 wxLogLastError(sError);
272 return FALSE;
273 }
274
275 if (!::WinRegisterClass( vHab
276 ,wxCanvasClassName
277 ,NULL
278 ,0 // CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
279 ,0
280 ))
281 {
282 vError = ::WinGetLastError(vHab);
283 sError = wxPMErrorToStr(vError);
284 wxLogLastError(sError);
285 return FALSE;
286 }
287 return TRUE;
288 } // end of wxApp::RegisterWindowClasses
289
290 //
291 // Cleans up any wxWindows internal structures left lying around
292 //
293 void wxApp::CleanUp()
294 {
295 //
296 // COMMON CLEANUP
297 //
298
299 #if wxUSE_LOG
300
301 //
302 // Flush the logged messages if any and install a 'safer' log target: the
303 // default one (wxLogGui) can't be used after the resources are freed just
304 // below and the user suppliedo ne might be even more unsafe (using any
305 // wxWindows GUI function is unsafe starting from now)
306 //
307 wxLog::DontCreateOnDemand();
308
309 //
310 // This will flush the old messages if any
311 //
312 delete wxLog::SetActiveTarget(new wxLogStderr);
313 #endif // wxUSE_LOG
314
315 //
316 // One last chance for pending objects to be cleaned up
317 //
318 wxTheApp->DeletePendingObjects();
319
320 wxModule::CleanUpModules();
321
322 #if wxUSE_WX_RESOURCES
323 wxCleanUpResourceSystem();
324 #endif
325
326 wxDeleteStockObjects();
327
328 //
329 // Destroy all GDI lists, etc.
330 //
331 wxDeleteStockLists();
332
333 delete wxTheColourDatabase;
334 wxTheColourDatabase = NULL;
335
336 wxBitmap::CleanUpHandlers();
337
338 delete[] wxBuffer;
339 wxBuffer = NULL;
340
341 //
342 // PM-SPECIFIC CLEANUP
343 //
344
345 // wxSetKeyboardHook(FALSE);
346
347 if (wxSTD_FRAME_ICON)
348 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
349 if (wxSTD_MDICHILDFRAME_ICON)
350 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
351 if (wxSTD_MDIPARENTFRAME_ICON)
352 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
353
354 if (wxDEFAULT_FRAME_ICON)
355 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
356 if (wxDEFAULT_MDICHILDFRAME_ICON)
357 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
358 if (wxDEFAULT_MDIPARENTFRAME_ICON)
359 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
360
361 if ( wxDisableButtonBrush )
362 {
363 // TODO: ::DeleteObject( wxDisableButtonBrush );
364 }
365
366 if (wxWinHandleList)
367 delete wxWinHandleList;
368
369 delete wxPendingEvents;
370 #if wxUSE_THREADS
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 Message queue
379 if (wxTheApp->m_hMq)
380 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
381
382 delete wxTheApp;
383 wxTheApp = NULL;
384
385 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
386 // At this point we want to check if there are any memory
387 // blocks that aren't part of the wxDebugContext itself,
388 // as a special case. Then when dumping we need to ignore
389 // wxDebugContext, too.
390 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
391 {
392 wxLogDebug(wxT("There were memory leaks."));
393 wxDebugContext::Dump();
394 wxDebugContext::PrintStatistics();
395 }
396 // wxDebugContext::SetStream(NULL, NULL);
397 #endif
398
399 #if wxUSE_LOG
400 // do it as the very last thing because everything else can log messages
401 delete wxLog::SetActiveTarget(NULL);
402 #endif // wxUSE_LOG
403 } // end of wxApp::CleanUp
404
405 int wxEntry(
406 int argc
407 , char* argv[]
408 )
409 {
410 HAB vHab = 0;
411
412 if (!wxApp::Initialize(vHab))
413 return 0;
414
415 //
416 // create the application object or ensure that one already exists
417 //
418 if (!wxTheApp)
419 {
420 // The app may have declared a global application object, but we recommend
421 // the IMPLEMENT_APP macro is used instead, which sets an initializer
422 // function for delayed, dynamic app object construction.
423 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
424 wxT("No initializer - use IMPLEMENT_APP macro.") );
425 wxTheApp = (*wxApp::GetInitializerFunction()) ();
426 }
427 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
428 wxTheApp->argc = argc;
429
430 #if wxUSE_UNICODE
431 wxTheApp->argv = new wxChar*[argc+1];
432
433 int nArgc = 0;
434
435 while (nArgc < argc)
436 {
437 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
438 nArgc++;
439 }
440 wxTheApp->argv[nArgc] = (wxChar *)NULL;
441 #else
442 wxTheApp->argv = argv;
443 #endif
444
445 wxString sName(wxFileNameFromPath(argv[0]));
446
447 wxStripExtension(sName);
448 wxTheApp->SetAppName(sName);
449
450 int nRetValue = 0;
451
452 if (!wxTheApp->OnInitGui())
453 nRetValue = -1;
454
455 if (nRetValue == 0)
456 {
457 if (wxTheApp->OnInit())
458 {
459 nRetValue = wxTheApp->OnRun();
460 // nRetValue = -1;
461 }
462 }
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 wxTheApp->OnExit();
482 wxApp::CleanUp();
483 return(nRetValue);
484 } // end of wxEntry
485
486 bool wxApp::OnInitGui()
487 {
488 ERRORID vError;
489 wxString sError;
490
491 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
492 if (!m_hMq)
493 {
494 vError = ::WinGetLastError(vHabmain);
495 sError = wxPMErrorToStr(vError);
496 wxLogDebug(sError);
497 return FALSE;
498 }
499 return TRUE;
500 } // end of wxApp::OnInitGui
501
502 //
503 // Static member initialization
504 //
505 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
506
507 wxApp::wxApp()
508 {
509 m_topWindow = NULL;
510 wxTheApp = this;
511 m_wantDebugOutput = TRUE;
512
513 argc = 0;
514 argv = NULL;
515 m_nPrintMode = wxPRINT_WINDOWS;
516 m_exitOnFrameDelete = TRUE;
517 m_bAuto3D = TRUE;
518 m_hMq = 0;
519 } // end of wxApp::wxApp
520
521 wxApp::~wxApp()
522 {
523 //
524 // Delete command-line args
525 //
526 #if wxUSE_UNICODE
527 int i;
528
529 for (i = 0; i < argc; i++)
530 {
531 delete[] argv[i];
532 }
533 delete[] argv;
534 #endif
535 } // end of wxApp::~wxApp
536
537 bool wxApp::Initialized()
538 {
539 if (GetTopWindow())
540 return TRUE;
541 else
542 return FALSE;
543 } // end of wxApp::Initialized
544
545 //
546 // Get and process a message, returning FALSE if WM_QUIT
547 // received (and also set the flag telling the app to exit the main loop)
548 //
549 bool wxApp::DoMessage()
550 {
551 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
552
553 // wxUsleep(1000);
554 if (bRc == 0)
555 {
556 // got WM_QUIT
557 m_bKeepGoing = FALSE;
558 return FALSE;
559 }
560 else if (bRc == -1)
561 {
562 // should never happen, but let's test for it nevertheless
563 wxLogLastError("GetMessage");
564 }
565 else
566 {
567 #if wxUSE_THREADS
568 wxASSERT_MSG( wxThread::IsMain()
569 ,wxT("only the main thread can process Windows messages")
570 );
571
572 static bool sbHadGuiLock = TRUE;
573 static wxMsgArray svSavedMessages;
574
575 //
576 // If a secondary thread owns is doing GUI calls, save all messages for
577 // later processing - we can't process them right now because it will
578 // lead to recursive library calls (and we're not reentrant)
579 //
580 if (!wxGuiOwnedByMainThread())
581 {
582 sbHadGuiLock = FALSE;
583
584 //
585 // Leave out WM_COMMAND messages: too dangerous, sometimes
586 // the message will be processed twice
587 //
588 if ( !wxIsWaitingForThread() ||
589 svCurrentMsg.msg != WM_COMMAND )
590 {
591 svSavedMessages.Add(svCurrentMsg);
592 }
593 return TRUE;
594 }
595 else
596 {
597 //
598 // Have we just regained the GUI lock? if so, post all of the saved
599 // messages
600 //
601 if (!sbHadGuiLock )
602 {
603 sbHadGuiLock = TRUE;
604
605 size_t nCount = svSavedMessages.Count();
606
607 for (size_t n = 0; n < nCount; n++)
608 {
609 QMSG vMsg = svSavedMessages[n];
610
611 if ( !ProcessMessage((WXMSG *)&vMsg) )
612 {
613 ::WinDispatchMsg(vHabmain, &vMsg);
614 }
615 }
616 svSavedMessages.Empty();
617 }
618 }
619 #endif // wxUSE_THREADS
620
621 // Process the message
622 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
623 {
624 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
625 }
626 }
627 return TRUE;
628 } // end of wxApp::DoMessage
629
630 //////////////////////////////////////////////////////////////////////////////
631 //
632 // Keep trying to process messages until WM_QUIT
633 // received.
634 //
635 // If there are messages to be processed, they will all be
636 // processed and OnIdle will not be called.
637 // When there are no more messages, OnIdle is called.
638 // If OnIdle requests more time,
639 // it will be repeatedly called so long as there are no pending messages.
640 // A 'feature' of this is that once OnIdle has decided that no more processing
641 // is required, then it won't get processing time until further messages
642 // are processed (it'll sit in DoMessage).
643 //
644 //////////////////////////////////////////////////////////////////////////////
645 int wxApp::MainLoop()
646 {
647 m_bKeepGoing = TRUE;
648
649 while (m_bKeepGoing)
650 {
651 #if wxUSE_THREADS
652 wxMutexGuiLeaveOrEnter();
653 #endif // wxUSE_THREADS
654 while (/*Pending() &&*/ ProcessIdle())
655 {
656 // wxUsleep(10000);
657 }
658 DoMessage();
659 }
660 return (int)svCurrentMsg.mp1;
661 } // end of wxApp::MainLoop
662
663 //
664 // Returns TRUE if more time is needed.
665 //
666 bool wxApp::ProcessIdle()
667 {
668 wxIdleEvent vEvent;
669
670 vEvent.SetEventObject(this);
671 ProcessEvent(vEvent);
672 return vEvent.MoreRequested();
673 } // end of wxApp::ProcessIdle
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* pMsg = (PQMSG)pWxmsg;
702 HWND hWnd = pMsg->hwnd;
703 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
704 wxWindow* pWnd;
705
706 #if wxUSE_TOOLTIPS
707 //
708 // We must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
709 // popup the tooltip bubbles
710 //
711 if (pWndThis && (pMsg->msg == WM_MOUSEMOVE))
712 {
713 wxToolTip* pToolTip = pWndThis->GetToolTip();
714 if (pToolTip)
715 {
716 pToolTip->RelayEvent(pWxmsg);
717 }
718 }
719 #endif // wxUSE_TOOLTIPS
720
721 //
722 // For some composite controls (like a combobox), wndThis might be NULL
723 // because the subcontrol is not a wxWindow, but only the control itself
724 // is - try to catch this case
725 //
726 while (hWnd && !pWndThis)
727 {
728 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
729 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
730 }
731
732 //
733 // Try translations first; find the youngest window with
734 // a translation table. OS/2 has case sensative accels, so
735 // this block, coded by BK, removes that and helps make them
736 // case insensative.
737 //
738 if(pMsg->msg == WM_CHAR)
739 {
740 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
741 USHORT uSch = CHARMSG(pChmsg)->chr;
742 bool bRc;
743
744 //
745 // Do not process keyup events
746 //
747 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
748 {
749 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
750 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
751
752
753 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
754 {
755 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
756 break;
757 }
758
759 if(!bRc) // untranslated, should restore original value
760 CHARMSG(pChmsg)->chr = uSch;
761 }
762 }
763 //
764 // Anyone for a non-translation message? Try youngest descendants first.
765 //
766 // for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
767 // {
768 // if (pWnd->OS2ProcessMessage(pWxmsg))
769 // return TRUE;
770 // }
771 return FALSE;
772 } // end of wxApp::ProcessMessage
773
774 void wxApp::OnIdle(
775 wxIdleEvent& rEvent
776 )
777 {
778 static bool sbInOnIdle = FALSE;
779
780 //
781 // Avoid recursion (via ProcessEvent default case)
782 //
783 if (sbInOnIdle)
784 return;
785
786 sbInOnIdle = TRUE;
787
788 //
789 // If there are pending events, we must process them: pending events
790 // are either events to the threads other than main or events posted
791 // with wxPostEvent() functions
792 //
793 ProcessPendingEvents();
794
795 //
796 // 'Garbage' collection of windows deleted with Close().
797 //
798 DeletePendingObjects();
799
800 #if wxUSE_LOG
801 //
802 // Flush the logged messages if any
803 //
804 wxLog::FlushActive();
805 #endif // wxUSE_LOG
806
807 //
808 // Send OnIdle events to all windows
809 //
810 if (SendIdleEvents())
811 {
812 //
813 // SendIdleEvents() returns TRUE if at least one window requested more
814 // idle events
815 //
816 rEvent.RequestMore(TRUE);
817 }
818 sbInOnIdle = FALSE;
819 } // end of wxApp::OnIdle
820
821 // Send idle event to all top-level windows
822 bool wxApp::SendIdleEvents()
823 {
824 bool bNeedMore = FALSE;
825 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
826
827 while (pNode)
828 {
829 wxWindow* pWin = pNode->GetData();
830
831 if (SendIdleEvents(pWin))
832 bNeedMore = TRUE;
833 pNode = pNode->GetNext();
834 }
835 return bNeedMore;
836 } // end of wxApp::SendIdleEvents
837
838 //
839 // Send idle event to window and all subwindows
840 //
841 bool wxApp::SendIdleEvents(
842 wxWindow* pWin
843 )
844 {
845 bool bNeedMore = FALSE;
846 wxIdleEvent vEvent;
847
848 vEvent.SetEventObject(pWin);
849 pWin->GetEventHandler()->ProcessEvent(vEvent);
850
851 if (vEvent.MoreRequested())
852 bNeedMore = TRUE;
853
854 wxNode* pNode = pWin->GetChildren().First();
855
856 while (pNode)
857 {
858 wxWindow* pWin = (wxWindow*) pNode->Data();
859
860 if (SendIdleEvents(pWin))
861 bNeedMore = TRUE;
862 pNode = pNode->Next();
863 }
864 return bNeedMore;
865 } // end of wxApp::SendIdleEvents
866
867 void wxApp::DeletePendingObjects()
868 {
869 wxNode* pNode = wxPendingDelete.First();
870
871 while (pNode)
872 {
873 wxObject* pObj = (wxObject *)pNode->Data();
874
875 delete pObj;
876
877 if (wxPendingDelete.Member(pObj))
878 delete pNode;
879
880 //
881 // Deleting one object may have deleted other pending
882 // objects, so start from beginning of list again.
883 //
884 pNode = wxPendingDelete.First();
885 }
886 } // end of wxApp::DeletePendingObjects
887
888 void wxApp::OnEndSession(
889 wxCloseEvent& WXUNUSED(rEvent))
890 {
891 if (GetTopWindow())
892 GetTopWindow()->Close(TRUE);
893 } // end of wxApp::OnEndSession
894
895 //
896 // Default behaviour: close the application with prompts. The
897 // user can veto the close, and therefore the end session.
898 //
899 void wxApp::OnQueryEndSession(
900 wxCloseEvent& rEvent
901 )
902 {
903 if (GetTopWindow())
904 {
905 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
906 rEvent.Veto(TRUE);
907 }
908 } // end of wxApp::OnQueryEndSession
909
910 void wxExit()
911 {
912 wxLogError(_("Fatal error: exiting"));
913
914 wxApp::CleanUp();
915 } // end of wxExit
916
917 //
918 // Yield to incoming messages
919 //
920 bool wxYield()
921 {
922 HAB vHab = 0;
923 QMSG vMsg;
924
925 //
926 // Disable log flushing from here because a call to wxYield() shouldn't
927 // normally result in message boxes popping up &c
928 //
929 wxLog::Suspend();
930
931 //
932 // We want to go back to the main message loop
933 // if we see a WM_QUIT. (?)
934 //
935 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
936 {
937 #if wxUSE_THREADS
938 wxMutexGuiLeaveOrEnter();
939 #endif // wxUSE_THREADS
940 if (!wxTheApp->DoMessage())
941 break;
942 }
943 //
944 // If they are pending events, we must process them.
945 //
946 if (wxTheApp)
947 wxTheApp->ProcessPendingEvents();
948
949 //
950 // Let the logs be flashed again
951 //
952 wxLog::Resume();
953 return TRUE;
954 } // end of wxYield
955
956 wxIcon wxApp::GetStdIcon(
957 int nWhich
958 ) const
959 {
960 switch(nWhich)
961 {
962 case wxICON_INFORMATION:
963 return wxIcon("wxICON_INFO");
964
965 case wxICON_QUESTION:
966 return wxIcon("wxICON_QUESTION");
967
968 case wxICON_EXCLAMATION:
969 return wxIcon("wxICON_WARNING");
970
971 default:
972 wxFAIL_MSG(wxT("requested non existent standard icon"));
973 // still fall through
974
975 case wxICON_HAND:
976 return wxIcon("wxICON_ERROR");
977 }
978 return wxIcon("wxICON_ERROR");
979 } // end of wxApp::GetStdIcon
980
981 //-----------------------------------------------------------------------------
982 // wxWakeUpIdle
983 //-----------------------------------------------------------------------------
984
985 void wxWakeUpIdle()
986 {
987 //
988 // Send the top window a dummy message so idle handler processing will
989 // start up again. Doing it this way ensures that the idle handler
990 // wakes up in the right thread (see also wxWakeUpMainThread() which does
991 // the same for the main app thread only)
992 //
993 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
994
995 if (pTopWindow)
996 {
997 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
998 {
999 //
1000 // Should never happen
1001 //
1002 wxLogLastError("PostMessage(WM_NULL)");
1003 }
1004 }
1005 } // end of wxWakeUpIdle
1006
1007 HAB wxGetInstance()
1008 {
1009 return vHabmain;
1010 }
1011
1012 void wxSetInstance(
1013 HAB vHab
1014 )
1015 {
1016 vHabmain = vHab;
1017 }
1018