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