1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  19     #include "wx/gdicmn.h" 
  22     #include "wx/cursor.h" 
  24     #include "wx/palette.h" 
  26     #include "wx/dialog.h" 
  27     #include "wx/msgdlg.h" 
  29     #include "wx/dynarray.h" 
  30     #include "wx/wxchar.h" 
  36 #include "wx/module.h" 
  38 #include "wx/os2/private.h" 
  42 #include <sys\ioctl.h> 
  43 #include <sys\select.h> 
  51 #endif // ndef for __EMX__ 
  55 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e) 
  56 int _System 
bsdselect(int, 
  65     #include "wx/thread.h" 
  67     // define the array of QMSG strutures 
  68     WX_DECLARE_OBJARRAY(QMSG
, wxMsgArray
); 
  70     #include "wx/arrimpl.cpp" 
  72     WX_DEFINE_OBJARRAY(wxMsgArray
); 
  73 #endif // wxUSE_THREADS 
  75 #if wxUSE_WX_RESOURCES 
  76     #include "wx/resource.h" 
  80     #include "wx/tooltip.h" 
  81 #endif // wxUSE_TOOLTIPS 
  86 // --------------------------------------------------------------------------- 
  88 // --------------------------------------------------------------------------- 
  90 extern wxChar
*                      wxBuffer
; 
  91 extern wxList
*                      wxWinHandleList
; 
  92 extern wxList WXDLLEXPORT           wxPendingDelete
; 
  93 extern wxCursor
*                    g_globalCursor
; 
  95 HAB                                 vHabmain 
= NULLHANDLE
; 
  97 wxApp
*                              wxTheApp 
= NULL
; 
  99 // NB: all "NoRedraw" classes must have the same names as the "normal" classes 
 100 //     with NR suffix - wxWindow::OS2Create() supposes this 
 101 wxChar wxFrameClassName
[]                 = wxT("wxFrameClass"); 
 102 wxChar wxFrameClassNameNoRedraw
[]         = wxT("wxFrameClassNR"); 
 103 wxChar wxMDIFrameClassName
[]              = wxT("wxMDIFrameClass"); 
 104 wxChar wxMDIFrameClassNameNoRedraw
[]      = wxT("wxMDIFrameClassNR"); 
 105 wxChar wxMDIChildFrameClassName
[]         = wxT("wxMDIChildFrameClass"); 
 106 wxChar wxMDIChildFrameClassNameNoRedraw
[] = wxT("wxMDIChildFrameClassNR"); 
 107 wxChar wxPanelClassName
[]                 = wxT("wxPanelClass"); 
 108 wxChar wxCanvasClassName
[]                = wxT("wxCanvasClass"); 
 110 HICON wxSTD_FRAME_ICON          
= (HICON
) NULL
; 
 111 HICON wxSTD_MDICHILDFRAME_ICON  
= (HICON
) NULL
; 
 112 HICON wxSTD_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
 114 HICON wxDEFAULT_FRAME_ICON           
= (HICON
) NULL
; 
 115 HICON wxDEFAULT_MDICHILDFRAME_ICON   
= (HICON
) NULL
; 
 116 HICON wxDEFAULT_MDIPARENTFRAME_ICON  
= (HICON
) NULL
; 
 118 HBRUSH wxDisableButtonBrush 
= (HBRUSH
) 0; 
 120 MRESULT EXPENTRY 
wxWndProc( HWND hWnd
,ULONG message
,MPARAM mp1
,MPARAM mp2
); 
 121 MRESULT EXPENTRY 
wxFrameWndProc( HWND hWnd
,ULONG message
,MPARAM mp1
,MPARAM mp2
); 
 123 // =========================================================================== 
 125 // =========================================================================== 
 127 // --------------------------------------------------------------------------- 
 128 // helper struct and functions for socket handling 
 129 // --------------------------------------------------------------------------- 
 131 struct GsocketCallbackInfo
{ 
 132     void (*proc
)(void *); 
 138 // These defines and wrapper functions are used here and in gsockpm.c 
 139 #define wxSockReadMask  0x01 
 140 #define wxSockWriteMask 0x02 
 144 int wxAppAddSocketHandler(int handle
, int mask
, 
 145                            void (*callback
)(void*), void * gsock
) 
 147     return wxTheApp
->AddSocketHandler(handle
, mask
, callback
, gsock
); 
 150 void wxAppRemoveSocketHandler(int handle
) 
 152     wxTheApp
->RemoveSocketHandler(handle
); 
 155 //  Linkage mode problems using callbacks with extern C in a .cpp module 
 156 int wxAppAddSocketHandler(int handle
, int mask
, 
 157                            void (*callback
)(void*), void * gsock
) 
 159     return wxTheApp
->AddSocketHandler(handle
, mask
, callback
, gsock
); 
 161 void wxAppRemoveSocketHandler(int handle
) 
 163     wxTheApp
->RemoveSocketHandler(handle
); 
 167 void wxApp::HandleSockets() 
 169     bool pendingEvent 
= FALSE
; 
 171     // Check whether it's time for Gsocket operation 
 172     if (m_maxSocketHandles 
> 0 && m_maxSocketNr 
> 0) 
 174         fd_set readfds 
= m_readfds
; 
 175         fd_set writefds 
= m_writefds
; 
 176         struct timeval timeout
; 
 178         struct GsocketCallbackInfo
 
 179           *CallbackInfo 
= (struct GsocketCallbackInfo 
*)m_sockCallbackInfo
; 
 183         if ( select(m_maxSocketNr
, &readfds
, &writefds
, 0, &timeout
) > 0) 
 185             for (i 
= m_lastUsedHandle 
+ 1; i 
!= m_lastUsedHandle
; i
++) 
 187                 if (i 
== m_maxSocketNr
) 
 189                 if (FD_ISSET(i
, &readfds
)) 
 192                     for (r 
= 0; r 
< m_maxSocketHandles
; r
++){ 
 193                         if(CallbackInfo
[r
].handle 
== i 
&& 
 194                            CallbackInfo
[r
].type 
== wxSockReadMask
) 
 197                     if (r 
< m_maxSocketHandles
) 
 199                         CallbackInfo
[r
].proc(CallbackInfo
[r
].gsock
); 
 204                 if (FD_ISSET(i
, &writefds
)) 
 207                     for (r 
= 0; r 
< m_maxSocketHandles
; r
++) 
 208                         if(CallbackInfo
[r
].handle 
== i 
&& 
 209                            CallbackInfo
[r
].type 
== wxSockWriteMask
) 
 211                     if (r 
< m_maxSocketHandles
) 
 213                         CallbackInfo
[r
].proc(CallbackInfo
[r
].gsock
); 
 219             m_lastUsedHandle 
= i
; 
 225 // --------------------------------------------------------------------------- 
 227 // --------------------------------------------------------------------------- 
 229     IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
) 
 231     BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
 232         EVT_IDLE(wxApp::OnIdle
) 
 233         EVT_END_SESSION(wxApp::OnEndSession
) 
 234         EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
) 
 240 bool wxApp::Initialize( 
 244 #if defined(wxUSE_CONSOLEDEBUG) 
 245   #if wxUSE_CONSOLEDEBUG 
 246 /***********************************************/ 
 247 /* Code for using stdout debug                 */ 
 248 /* To use it you mast link app as "Window" - EK*/ 
 249 /***********************************************/ 
 254     printf("In console\n"); 
 256   DosGetInfoBlocks(&tib
, &pib
); 
 257 /* Try morphing into a PM application. */ 
 258 //  if(pib->pib_ultype == 2)    /* VIO */ 
 261 /**********************************************/ 
 262 /**********************************************/ 
 263   #endif //wxUSE_CONSOLEDEBUG 
 267     // OS2 has to have an anchorblock 
 269     vHab 
= WinInitialize(0); 
 276     // Some people may wish to use this, but 
 277     // probably it shouldn't be here by default. 
 279     //    wxRedirectIOToConsole(); 
 282     wxBuffer 
= new wxChar
[1500]; // FIXME; why? 
 284     wxClassInfo::InitializeClasses(); 
 287     wxPendingEventsLocker 
= new wxCriticalSection
; 
 290     wxTheColourDatabase 
= new wxColourDatabase(wxKEY_STRING
); 
 291     wxTheColourDatabase
->Initialize(); 
 293     wxInitializeStockLists(); 
 294     wxInitializeStockObjects(); 
 296 #if wxUSE_WX_RESOURCES 
 297     wxInitializeResourceSystem(); 
 300     wxBitmap::InitStandardHandlers(); 
 302     RegisterWindowClasses(vHab
); 
 303     wxWinHandleList 
= new wxList(wxKEY_INTEGER
); 
 305     // This is to foil optimizations in Visual C++ that throw out dummy.obj. 
 306     // PLEASE DO NOT ALTER THIS. 
 307 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__) 
 308     extern char wxDummyChar
; 
 309     if (wxDummyChar
) wxDummyChar
++; 
 312     // wxSetKeyboardHook(TRUE); 
 314     wxModule::RegisterModules(); 
 315     if (!wxModule::InitializeModules()) 
 318 } // end of wxApp::Initialize 
 320 const char*                         CANTREGISTERCLASS 
= " Can't register Class "; 
 321 // --------------------------------------------------------------------------- 
 322 // RegisterWindowClasses 
 323 // --------------------------------------------------------------------------- 
 325 bool wxApp::RegisterWindowClasses( 
 333     if (!::WinRegisterClass( vHab
 
 336                             ,CS_SIZEREDRAW 
| CS_MOVENOTIFY 
| CS_SYNCPAINT  
| CS_CLIPCHILDREN
 
 340         vError 
= ::WinGetLastError(vHab
); 
 341         sError 
= wxPMErrorToStr(vError
); 
 342         wxLogLastError(sError
); 
 346     if (!::WinRegisterClass( vHab
 
 347                             ,wxFrameClassNameNoRedraw
 
 353         vError 
= ::WinGetLastError(vHab
); 
 354         sError 
= wxPMErrorToStr(vError
); 
 355         wxLogLastError(sError
); 
 359     if (!::WinRegisterClass( vHab
 
 362                             ,CS_SIZEREDRAW 
| CS_MOVENOTIFY 
| CS_SYNCPAINT
 
 366         vError 
= ::WinGetLastError(vHab
); 
 367         sError 
= wxPMErrorToStr(vError
); 
 368         wxLogLastError(sError
); 
 372     if (!::WinRegisterClass( vHab
 
 373                             ,wxMDIFrameClassNameNoRedraw
 
 379         vError 
= ::WinGetLastError(vHab
); 
 380         sError 
= wxPMErrorToStr(vError
); 
 381         wxLogLastError(sError
); 
 385     if (!::WinRegisterClass( vHab
 
 386                             ,wxMDIChildFrameClassName
 
 388                             ,CS_MOVENOTIFY 
| CS_SIZEREDRAW 
| CS_SYNCPAINT 
| CS_HITTEST
 
 392         vError 
= ::WinGetLastError(vHab
); 
 393         sError 
= wxPMErrorToStr(vError
); 
 394         wxLogLastError(sError
); 
 398     if (!::WinRegisterClass( vHab
 
 399                             ,wxMDIChildFrameClassNameNoRedraw
 
 405         vError 
= ::WinGetLastError(vHab
); 
 406         sError 
= wxPMErrorToStr(vError
); 
 407         wxLogLastError(sError
); 
 411     if (!::WinRegisterClass( vHab
 
 414                             ,CS_MOVENOTIFY 
| CS_SIZEREDRAW 
| CS_HITTEST 
| CS_SAVEBITS 
| CS_SYNCPAINT
 
 418         vError 
= ::WinGetLastError(vHab
); 
 419         sError 
= wxPMErrorToStr(vError
); 
 420         wxLogLastError(sError
); 
 424     if (!::WinRegisterClass( vHab
 
 427                             ,CS_MOVENOTIFY 
| CS_SIZEREDRAW 
| CS_HITTEST 
| CS_SAVEBITS 
| CS_SYNCPAINT 
| CS_CLIPCHILDREN
 
 431         vError 
= ::WinGetLastError(vHab
); 
 432         sError 
= wxPMErrorToStr(vError
); 
 433         wxLogLastError(sError
); 
 437 } // end of wxApp::RegisterWindowClasses 
 440 // Cleans up any wxWindows internal structures left lying around 
 442 void wxApp::CleanUp() 
 451     // Flush the logged messages if any and install a 'safer' log target: the 
 452     // default one (wxLogGui) can't be used after the resources are freed just 
 453     // below and the user suppliedo ne might be even more unsafe (using any 
 454     // wxWindows GUI function is unsafe starting from now) 
 456     wxLog::DontCreateOnDemand(); 
 459     // This will flush the old messages if any 
 461     delete wxLog::SetActiveTarget(new wxLogStderr
); 
 465     // One last chance for pending objects to be cleaned up 
 467     wxTheApp
->DeletePendingObjects(); 
 469     wxModule::CleanUpModules(); 
 471 #if wxUSE_WX_RESOURCES 
 472     wxCleanUpResourceSystem(); 
 475     wxDeleteStockObjects(); 
 478     // Destroy all GDI lists, etc. 
 480     wxDeleteStockLists(); 
 482     delete wxTheColourDatabase
; 
 483     wxTheColourDatabase 
= NULL
; 
 485     wxBitmap::CleanUpHandlers(); 
 491     // PM-SPECIFIC CLEANUP 
 494     // wxSetKeyboardHook(FALSE); 
 496     if (wxSTD_FRAME_ICON
) 
 497         ::WinFreeFileIcon(wxSTD_FRAME_ICON
); 
 498     if (wxSTD_MDICHILDFRAME_ICON
) 
 499         ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON
); 
 500     if (wxSTD_MDIPARENTFRAME_ICON
) 
 501         ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON
); 
 503     if (wxDEFAULT_FRAME_ICON
) 
 504         ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON
); 
 505     if (wxDEFAULT_MDICHILDFRAME_ICON
) 
 506         ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON
); 
 507     if (wxDEFAULT_MDIPARENTFRAME_ICON
) 
 508         ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON
); 
 510     if ( wxDisableButtonBrush 
) 
 512 // TODO:        ::DeleteObject( wxDisableButtonBrush ); 
 516         delete wxWinHandleList
; 
 518     delete wxPendingEvents
; 
 520     delete wxPendingEventsLocker
; 
 521     // If we don't do the following, we get an apparent memory leak. 
 522     ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker(); 
 525     wxClassInfo::CleanUpClasses(); 
 527     // Delete Message queue 
 529         ::WinDestroyMsgQueue(wxTheApp
->m_hMq
); 
 534 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 535     // At this point we want to check if there are any memory 
 536     // blocks that aren't part of the wxDebugContext itself, 
 537     // as a special case. Then when dumping we need to ignore 
 538     // wxDebugContext, too. 
 539     if (wxDebugContext::CountObjectsLeft(TRUE
) > 0) 
 541         wxLogDebug(wxT("There were memory leaks.")); 
 542         wxDebugContext::Dump(); 
 543         wxDebugContext::PrintStatistics(); 
 545     //  wxDebugContext::SetStream(NULL, NULL); 
 549     // do it as the very last thing because everything else can log messages 
 550     delete wxLog::SetActiveTarget(NULL
); 
 552 } // end of wxApp::CleanUp 
 554 //---------------------------------------------------------------------- 
 555 // Main wxWindows entry point 
 556 //---------------------------------------------------------------------- 
 564     if (!wxApp::Initialize(vHab
)) 
 568     // create the application object or ensure that one already exists 
 572         // The app may have declared a global application object, but we recommend 
 573         // the IMPLEMENT_APP macro is used instead, which sets an initializer 
 574         // function for delayed, dynamic app object construction. 
 575         wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 576                      wxT("No initializer - use IMPLEMENT_APP macro.") ); 
 577         wxTheApp 
= (*wxApp::GetInitializerFunction()) (); 
 579     wxCHECK_MSG( wxTheApp
, 0, wxT("You have to define an instance of wxApp!") ); 
 580     wxTheApp
->argc 
= argc
; 
 583     wxTheApp
->argv 
= new wxChar
*[argc
+1]; 
 589           wxTheApp
->argv
[nArgc
] = wxStrdup(wxConvLibc
.cMB2WX(argv
[nArgc
])); 
 592     wxTheApp
->argv
[nArgc
] = (wxChar 
*)NULL
; 
 594     wxTheApp
->argv 
= argv
; 
 597     wxString                        
sName(wxFileNameFromPath(argv
[0])); 
 599     wxStripExtension(sName
); 
 600     wxTheApp
->SetAppName(sName
); 
 604     if (!wxTheApp
->OnInitGui()) 
 609         if (wxTheApp
->OnInit()) 
 611             nRetValue 
= wxTheApp
->OnRun(); 
 614         wxWindow
*                   pTopWindow 
= wxTheApp
->GetTopWindow(); 
 617             // Forcibly delete the window. 
 618             if (pTopWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 619                 pTopWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 621                 pTopWindow
->Close(TRUE
); 
 622                 wxTheApp
->DeletePendingObjects(); 
 627                 wxTheApp
->SetTopWindow(NULL
); 
 631     else // app initialization failed 
 633         wxLogLastError(" Gui initialization failed, exitting"); 
 635 #if wxUSE_CONSOLEDEBUG 
 636     printf("wxTheApp->OnExit "); 
 640 #if wxUSE_CONSOLEDEBUG 
 641     printf("wxApp::CleanUp "); 
 645 #if wxUSE_CONSOLEDEBUG 
 646     printf("return %i ", nRetValue
); 
 652 bool wxApp::OnInitGui() 
 657     m_hMq 
= ::WinCreateMsgQueue(vHabmain
, 0); 
 660         vError 
= ::WinGetLastError(vHabmain
); 
 661         sError 
= wxPMErrorToStr(vError
); 
 666 } // end of wxApp::OnInitGui 
 669 // Static member initialization 
 671 wxAppInitializerFunction 
wxAppBase::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
 677     m_wantDebugOutput 
= TRUE
; 
 681     m_nPrintMode 
= wxPRINT_WINDOWS
; 
 682     m_exitOnFrameDelete 
= TRUE
; 
 685     m_maxSocketHandles 
= 0; 
 687     m_sockCallbackInfo 
= 0; 
 688 } // end of wxApp::wxApp 
 693     // Delete command-line args 
 698     for (i 
= 0; i 
< argc
; i
++) 
 704 } // end of wxApp::~wxApp 
 706 bool wxApp::Initialized() 
 712 } // end of wxApp::Initialized 
 715 // Get and process a message, returning FALSE if WM_QUIT 
 716 // received (and also set the flag telling the app to exit the main loop) 
 719 bool wxApp::DoMessage() 
 721     BOOL                            bRc 
= ::WinGetMsg(vHabmain
, &svCurrentMsg
, HWND(NULL
), 0, 0); 
 726         m_bKeepGoing 
= FALSE
; 
 731         // should never happen, but let's test for it nevertheless 
 732         wxLogLastError("GetMessage"); 
 737         wxASSERT_MSG( wxThread::IsMain() 
 738                      ,wxT("only the main thread can process Windows messages") 
 741         static bool                 sbHadGuiLock 
= TRUE
; 
 742         static wxMsgArray           svSavedMessages
; 
 745         // If a secondary thread owns is doing GUI calls, save all messages for 
 746         // later processing - we can't process them right now because it will 
 747         // lead to recursive library calls (and we're not reentrant) 
 749         if (!wxGuiOwnedByMainThread()) 
 751             sbHadGuiLock 
= FALSE
; 
 754             // Leave out WM_COMMAND messages: too dangerous, sometimes 
 755             // the message will be processed twice 
 757             if ( !wxIsWaitingForThread() || 
 758                     svCurrentMsg
.msg 
!= WM_COMMAND 
) 
 760                 svSavedMessages
.Add(svCurrentMsg
); 
 767             // Have we just regained the GUI lock? if so, post all of the saved 
 774                 size_t             nCount 
= svSavedMessages
.Count(); 
 776                 for (size_t n 
= 0; n 
< nCount
; n
++) 
 778                     QMSG            vMsg 
= svSavedMessages
[n
]; 
 780                     if ( !ProcessMessage((WXMSG 
*)&vMsg
) ) 
 782                         ::WinDispatchMsg(vHabmain
, &vMsg
); 
 785                 svSavedMessages
.Empty(); 
 788 #endif // wxUSE_THREADS 
 791         // Process the message 
 793         DoMessage((WXMSG 
*)&svCurrentMsg
); 
 796 } // end of wxApp::DoMessage 
 798 void wxApp::DoMessage( 
 802     if (!ProcessMessage((WXMSG 
*)&svCurrentMsg
)) 
 804         ::WinDispatchMsg(vHabmain
, (PQMSG
)&svCurrentMsg
); 
 806 } // end of wxApp::DoMessage 
 808 ////////////////////////////////////////////////////////////////////////////// 
 810 // Keep trying to process messages until WM_QUIT 
 813 // If there are messages to be processed, they will all be 
 814 // processed and OnIdle will not be called. 
 815 // When there are no more messages, OnIdle is called. 
 816 // If OnIdle requests more time, 
 817 // it will be repeatedly called so long as there are no pending messages. 
 818 // A 'feature' of this is that once OnIdle has decided that no more processing 
 819 // is required, then it won't get processing time until further messages 
 820 // are processed (it'll sit in DoMessage). 
 822 ////////////////////////////////////////////////////////////////////////////// 
 823 int wxApp::MainLoop() 
 830         wxMutexGuiLeaveOrEnter(); 
 831 #endif // wxUSE_THREADS 
 832         while (!Pending() && ProcessIdle()) 
 844     return (int)svCurrentMsg
.mp1
; 
 845 } // end of wxApp::MainLoop 
 848 // Returns TRUE if more time is needed. 
 850 bool wxApp::ProcessIdle() 
 854     vEvent
.SetEventObject(this); 
 855     ProcessEvent(vEvent
); 
 856     return vEvent
.MoreRequested(); 
 857 } // end of wxApp::ProcessIdle 
 859 void wxApp::ExitMainLoop() 
 861     m_bKeepGoing 
= FALSE
; 
 864 bool wxApp::Pending() 
 866     return (::WinPeekMsg(vHabmain
, (PQMSG
)&svCurrentMsg
, (HWND
)NULL
, 0, 0, PM_NOREMOVE
) != 0); 
 869 void wxApp::Dispatch() 
 874 ////////////////////////////////////////////////////////////////////////////// 
 876 // Give all windows a chance to preprocess 
 877 // the message. Some may have accelerator tables, or have 
 878 // MDI complications. 
 880 ////////////////////////////////////////////////////////////////////////////// 
 881 bool wxApp::ProcessMessage( 
 885     QMSG
*                           pMsg 
= (PQMSG
)pWxmsg
; 
 886     HWND                            hWnd 
= pMsg
->hwnd
; 
 887     wxWindow
*                       pWndThis 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
 892     // We must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to 
 893     // popup the tooltip bubbles 
 895     if (pWndThis 
&& (pMsg
->msg 
== WM_MOUSEMOVE
)) 
 897         wxToolTip
*                  pToolTip 
= pWndThis
->GetToolTip(); 
 900             pToolTip
->RelayEvent(pWxmsg
); 
 903 #endif // wxUSE_TOOLTIPS 
 906     // We must relay Timer events to wxTimer's processing function 
 908     if (pMsg
->msg 
== WM_TIMER
) 
 909         wxTimerProc(NULL
, 0, (int)pMsg
->mp1
, 0); 
 912     // For some composite controls (like a combobox), wndThis might be NULL 
 913     // because the subcontrol is not a wxWindow, but only the control itself 
 914     // is - try to catch this case 
 916     while (hWnd 
&& !pWndThis
) 
 918         hWnd 
= ::WinQueryWindow(hWnd
, QW_PARENT
); 
 919         pWndThis 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
 923     // Try translations first; find the youngest window with 
 924     // a translation table. OS/2 has case sensative accels, so 
 925     // this block, coded by BK, removes that and helps make them 
 928     if(pMsg
->msg 
== WM_CHAR
) 
 930        PBYTE                        pChmsg 
= (PBYTE
)&(pMsg
->msg
); 
 931        USHORT                       uSch  
= CHARMSG(pChmsg
)->chr
; 
 935        // Do not process keyup events 
 937        if(!(CHARMSG(pChmsg
)->fs 
& KC_KEYUP
)) 
 939            if((CHARMSG(pChmsg
)->fs 
& (KC_ALT 
| KC_CTRL
)) && CHARMSG(pChmsg
)->chr 
!= 0) 
 940                 CHARMSG(pChmsg
)->chr 
= (USHORT
)wxToupper((UCHAR
)uSch
); 
 943            for(pWnd 
= pWndThis
; pWnd
; pWnd 
= pWnd
->GetParent() ) 
 945                if((bRc 
= pWnd
->OS2TranslateMessage(pWxmsg
)) == TRUE
) 
 949             if(!bRc
)    // untranslated, should restore original value 
 950                 CHARMSG(pChmsg
)->chr 
= uSch
; 
 954     // Anyone for a non-translation message? Try youngest descendants first. 
 956 //  for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent()) 
 958 //      if (pWnd->OS2ProcessMessage(pWxmsg)) 
 962 } // end of wxApp::ProcessMessage 
 968     static bool                     sbInOnIdle 
= FALSE
; 
 971     // Avoid recursion (via ProcessEvent default case) 
 979     // If there are pending events, we must process them: pending events 
 980     // are either events to the threads other than main or events posted 
 981     // with wxPostEvent() functions 
 983     ProcessPendingEvents(); 
 986     // 'Garbage' collection of windows deleted with Close(). 
 988     DeletePendingObjects(); 
 992     // Flush the logged messages if any 
 994     wxLog::FlushActive(); 
 997 #if wxUSE_DC_CACHEING 
 998     // automated DC cache management: clear the cached DCs and bitmap 
 999     // if it's likely that the app has finished with them, that is, we 
1000     // get an idle event and we're not dragging anything. 
1001     if (!::WinGetKeyState(MK_LBUTTON
) && 
1002         !::WinGetKeyState(MK_MBUTTON
) && 
1003         !::WinGetKeyState(MK_RBUTTON
)) 
1005 #endif // wxUSE_DC_CACHEING 
1008     // Send OnIdle events to all windows 
1010     if (SendIdleEvents()) 
1013         // SendIdleEvents() returns TRUE if at least one window requested more 
1016         rEvent
.RequestMore(TRUE
); 
1019 } // end of wxApp::OnIdle 
1021 // Send idle event to all top-level windows 
1022 bool wxApp::SendIdleEvents() 
1024     bool                            bNeedMore 
= FALSE
; 
1025     wxWindowList::Node
*             pNode 
= wxTopLevelWindows
.GetFirst(); 
1029         wxWindow
*                   pWin 
= pNode
->GetData(); 
1031         if (SendIdleEvents(pWin
)) 
1033         pNode 
= pNode
->GetNext(); 
1036 } // end of wxApp::SendIdleEvents 
1039 // Send idle event to window and all subwindows 
1041 bool wxApp::SendIdleEvents( 
1045     bool                            bNeedMore 
= FALSE
; 
1048     vEvent
.SetEventObject(pWin
); 
1049     pWin
->GetEventHandler()->ProcessEvent(vEvent
); 
1051     if (vEvent
.MoreRequested()) 
1054     wxNode
*                         pNode 
= pWin
->GetChildren().First(); 
1058         wxWindow
*                   pWin 
= (wxWindow
*) pNode
->Data(); 
1060         if (SendIdleEvents(pWin
)) 
1062         pNode 
= pNode
->Next(); 
1065 } // end of wxApp::SendIdleEvents 
1067 void wxApp::DeletePendingObjects() 
1069     wxNode
*                         pNode 
= wxPendingDelete
.First(); 
1073         wxObject
*                   pObj 
= (wxObject 
*)pNode
->Data(); 
1077         if (wxPendingDelete
.Member(pObj
)) 
1081         // Deleting one object may have deleted other pending 
1082         // objects, so start from beginning of list again. 
1084         pNode 
= wxPendingDelete
.First(); 
1086 } // end of wxApp::DeletePendingObjects 
1088 void wxApp::OnEndSession( 
1089   wxCloseEvent
&                     WXUNUSED(rEvent
)) 
1092         GetTopWindow()->Close(TRUE
); 
1093 } // end of wxApp::OnEndSession 
1096 // Default behaviour: close the application with prompts. The 
1097 // user can veto the close, and therefore the end session. 
1099 void wxApp::OnQueryEndSession( 
1100   wxCloseEvent
&                     rEvent
 
1105         if (!GetTopWindow()->Close(!rEvent
.CanVeto())) 
1108 } // end of wxApp::OnQueryEndSession 
1112     wxLogError(_("Fatal error: exiting")); 
1117 static bool gs_inYield 
= FALSE
; 
1120 // Yield to incoming messages 
1128     // Disable log flushing from here because a call to wxYield() shouldn't 
1129     // normally result in message boxes popping up &c 
1136     // We want to go back to the main message loop 
1137     // if we see a WM_QUIT. (?) 
1139     while (::WinPeekMsg(vHab
, &vMsg
, (HWND
)NULL
, 0, 0, PM_NOREMOVE
) && vMsg
.msg 
!= WM_QUIT
) 
1142         wxMutexGuiLeaveOrEnter(); 
1143 #endif // wxUSE_THREADS 
1144         if (!wxTheApp
->DoMessage()) 
1148     // If they are pending events, we must process them. 
1151         wxTheApp
->ProcessPendingEvents(); 
1154     // Let the logs be flashed again 
1161 // Yield to incoming messages; but fail silently if recursion is detected. 
1162 bool wxYieldIfNeeded() 
1170 wxIcon 
wxApp::GetStdIcon( 
1176         case wxICON_INFORMATION
: 
1177             return wxIcon("wxICON_INFO"); 
1179         case wxICON_QUESTION
: 
1180             return wxIcon("wxICON_QUESTION"); 
1182         case wxICON_EXCLAMATION
: 
1183             return wxIcon("wxICON_WARNING"); 
1186             wxFAIL_MSG(wxT("requested non existent standard icon")); 
1187             // still fall through 
1190             return wxIcon("wxICON_ERROR"); 
1192     return wxIcon("wxICON_ERROR"); 
1193 } // end of wxApp::GetStdIcon 
1195 int wxApp::AddSocketHandler(int handle
, int mask
, 
1196                             void (*callback
)(void*), void * gsock
) 
1199     struct GsocketCallbackInfo
 
1200         *CallbackInfo 
= (struct GsocketCallbackInfo 
*)m_sockCallbackInfo
; 
1202     for (find 
= 0; find 
< m_maxSocketHandles
; find
++) 
1203         if (CallbackInfo
[find
].handle 
== -1) 
1205     if (find 
== m_maxSocketHandles
) 
1207         // Allocate new memory 
1208         m_sockCallbackInfo 
= realloc(m_sockCallbackInfo
, 
1209                                      (m_maxSocketHandles
+=10)* 
1210                                      sizeof(struct GsocketCallbackInfo
)); 
1211         CallbackInfo 
= (struct GsocketCallbackInfo 
*)m_sockCallbackInfo
; 
1212         for (find 
= m_maxSocketHandles 
- 10; find 
< m_maxSocketHandles
; find
++) 
1213             CallbackInfo
[find
].handle 
= -1; 
1214         find 
= m_maxSocketHandles 
- 10; 
1216     CallbackInfo
[find
].proc 
= callback
; 
1217     CallbackInfo
[find
].type 
= mask
; 
1218     CallbackInfo
[find
].handle 
= handle
; 
1219     CallbackInfo
[find
].gsock 
= gsock
; 
1220     if (mask 
& wxSockReadMask
) 
1221         FD_SET(handle
, &m_readfds
); 
1222     if (mask 
& wxSockWriteMask
) 
1223         FD_SET(handle
, &m_writefds
); 
1224     if (handle 
>= m_maxSocketNr
) 
1225         m_maxSocketNr 
= handle 
+ 1; 
1229 void wxApp::RemoveSocketHandler(int handle
) 
1231     struct GsocketCallbackInfo
 
1232         *CallbackInfo 
= (struct GsocketCallbackInfo 
*)m_sockCallbackInfo
; 
1233     if (handle 
< m_maxSocketHandles
) 
1235         if (CallbackInfo
[handle
].type 
& wxSockReadMask
) 
1236             FD_CLR(CallbackInfo
[handle
].handle
, &m_readfds
); 
1237         if (CallbackInfo
[handle
].type 
& wxSockWriteMask
) 
1238             FD_CLR(CallbackInfo
[handle
].handle
, &m_writefds
); 
1239         CallbackInfo
[handle
].handle 
= -1; 
1243 //----------------------------------------------------------------------------- 
1245 //----------------------------------------------------------------------------- 
1250     // Send the top window a dummy message so idle handler processing will 
1251     // start up again.  Doing it this way ensures that the idle handler 
1252     // wakes up in the right thread (see also wxWakeUpMainThread() which does 
1253     // the same for the main app thread only) 
1255     wxWindow
*                       pTopWindow 
= wxTheApp
->GetTopWindow(); 
1259         if ( !::WinPostMsg(GetHwndOf(pTopWindow
), WM_NULL
, (MPARAM
)0, (MPARAM
)0)) 
1262             // Should never happen 
1264             wxLogLastError("PostMessage(WM_NULL)"); 
1267 } // end of wxWakeUpIdle