home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / app.cpp < prev    next >
C/C++ Source or Header  |  2003-01-03  |  36KB  |  1,262 lines

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