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