///////////////////////////////////////////////////////////////////////////// // Name: src/os2/app.cpp // Purpose: wxApp // Author: David Webster // Modified by: // Created: 10/13/99 // RCS-ID: $Id: app.cpp 53612 2008-05-17 09:28:05Z SN $ // Copyright: (c) David Webster // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #include "wx/app.h" #ifndef WX_PRECOMP #include "wx/dynarray.h" #include "wx/frame.h" #include "wx/utils.h" #include "wx/gdicmn.h" #include "wx/pen.h" #include "wx/brush.h" #include "wx/cursor.h" #include "wx/icon.h" #include "wx/palette.h" #include "wx/dc.h" #include "wx/dialog.h" #include "wx/msgdlg.h" #include "wx/intl.h" #include "wx/wxchar.h" #include "wx/log.h" #include "wx/module.h" #endif #include "wx/stdpaths.h" #include "wx/filename.h" #include "wx/evtloop.h" #include "wx/os2/private.h" #ifdef __EMX__ #include #include #else #include #include #include #include #endif // #if defined(__WATCOMC__) #include #elif !defined(__EMX__) #define select(a,b,c,d,e) bsdselect(a,b,c,d,e) extern "C" int _System bsdselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *); #endif #if wxUSE_THREADS #include "wx/thread.h" #endif // wxUSE_THREADS #if wxUSE_TOOLTIPS #include "wx/tooltip.h" #endif // wxUSE_TOOLTIPS #include #include // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- WXDLLEXPORT_DATA(wxChar*) wxBuffer; extern wxCursor* g_globalCursor; HAB vHabmain = NULLHANDLE; HICON wxSTD_FRAME_ICON = (HICON) NULL; HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL; HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL; HICON wxDEFAULT_FRAME_ICON = (HICON) NULL; HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL; HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL; HBRUSH wxDisableButtonBrush = (HBRUSH) 0; MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2); MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2); // =========================================================================== // implementation // =========================================================================== // --------------------------------------------------------------------------- // helper struct and functions for socket handling // --------------------------------------------------------------------------- struct GsocketCallbackInfo{ void (*proc)(void *); int type; int handle; void* gsock; }; // These defines are used here and in gsockpm.cpp #define wxSockReadMask 0x01 #define wxSockWriteMask 0x02 void wxApp::HandleSockets() { bool pendingEvent = false; // Check whether it's time for Gsocket operation if (m_maxSocketHandles > 0 && m_maxSocketNr > 0) { fd_set readfds = m_readfds; fd_set writefds = m_writefds; struct timeval timeout; int i; struct GsocketCallbackInfo *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo; timeout.tv_sec = 0; timeout.tv_usec = 0; if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0) { for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle; (i < m_maxSocketNr - 1) ? i++ : (i = 0)) { if (FD_ISSET(i, &readfds)) { int r; for (r = 0; r < m_maxSocketHandles; r++){ if(CallbackInfo[r].handle == i && CallbackInfo[r].type == wxSockReadMask) break; } if (r < m_maxSocketHandles) { CallbackInfo[r].proc(CallbackInfo[r].gsock); pendingEvent = true; } } if (FD_ISSET(i, &writefds)) { int r; for (r = 0; r < m_maxSocketHandles; r++) if(CallbackInfo[r].handle == i && CallbackInfo[r].type == wxSockWriteMask) break; if (r < m_maxSocketHandles) { CallbackInfo[r].proc(CallbackInfo[r].gsock); pendingEvent = true; } } } m_lastUsedHandle = i; } if (pendingEvent) ProcessPendingEvents(); } } // --------------------------------------------------------------------------- // wxApp // --------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) EVT_IDLE(wxApp::OnIdle) EVT_END_SESSION(wxApp::OnEndSession) EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession) END_EVENT_TABLE() // // Initialize // bool wxApp::Initialize(int& argc, wxChar **argv) { if ( !wxAppBase::Initialize(argc, argv) ) return false; #if defined(wxUSE_CONSOLEDEBUG) #if wxUSE_CONSOLEDEBUG /***********************************************/ /* Code for using stdout debug */ /* To use it you mast link app as "Window" - EK*/ /***********************************************/ { PPIB pib; PTIB tib; printf("In console\n"); DosGetInfoBlocks(&tib, &pib); /* Try morphing into a PM application. */ // if(pib->pib_ultype == 2) /* VIO */ pib->pib_ultype = 3; } /**********************************************/ /**********************************************/ #endif //wxUSE_CONSOLEDEBUG #endif // // OS2 has to have an anchorblock // vHabmain = WinInitialize(0); wxFileName GetPrefix(argv[0]); GetPrefix.MakeAbsolute(); wxStandardPaths::SetInstallPrefix(GetPrefix.GetPath()); if (!vHabmain) { // TODO: at least give some error message here... wxAppBase::CleanUp(); return false; } wxBuffer = new wxChar[1500]; // FIXME; why? // Some people may wish to use this, but // probably it shouldn't be here by default. #ifdef __WXDEBUG__ // wxRedirectIOToConsole(); #endif wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100); // This is to foil optimizations in Visual C++ that throw out dummy.obj. // PLEASE DO NOT ALTER THIS. #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__) extern char wxDummyChar; if (wxDummyChar) wxDummyChar++; #endif // wxSetKeyboardHook(TRUE); RegisterWindowClasses(vHabmain); return true; } // end of wxApp::Initialize const char* CANTREGISTERCLASS = " Can't register Class "; // --------------------------------------------------------------------------- // RegisterWindowClasses // --------------------------------------------------------------------------- bool wxApp::RegisterWindowClasses( HAB vHab ) { ERRORID vError = 0L; wxString sError; if (!::WinRegisterClass( vHab ,(PSZ)wxFrameClassName ,wxFrameWndProc ,CS_SIZEREDRAW | CS_SYNCPAINT ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxFrameClassNameNoRedraw ,wxWndProc ,0 ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxMDIFrameClassName ,wxWndProc ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxMDIFrameClassNameNoRedraw ,wxWndProc ,0 ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxMDIChildFrameClassName ,wxWndProc ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxMDIChildFrameClassNameNoRedraw ,wxWndProc ,CS_HITTEST ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxPanelClassName ,wxWndProc ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxCanvasClassName ,wxWndProc ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } if (!::WinRegisterClass( vHab ,(PSZ)wxCanvasClassNameNR ,wxWndProc ,CS_HITTEST | CS_SYNCPAINT ,sizeof(ULONG) )) { vError = ::WinGetLastError(vHab); sError = wxPMErrorToStr(vError); wxLogLastError(sError.c_str()); return false; } return true; } // end of wxApp::RegisterWindowClasses // // Cleans up any wxWidgets internal structures left lying around // void wxApp::CleanUp() { delete[] wxBuffer; wxBuffer = NULL; // // PM-SPECIFIC CLEANUP // // wxSetKeyboardHook(false); if (wxSTD_FRAME_ICON) ::WinFreeFileIcon(wxSTD_FRAME_ICON); if (wxSTD_MDICHILDFRAME_ICON) ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON); if (wxSTD_MDIPARENTFRAME_ICON) ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON); if (wxDEFAULT_FRAME_ICON) ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON); if (wxDEFAULT_MDICHILDFRAME_ICON) ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON); if (wxDEFAULT_MDIPARENTFRAME_ICON) ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON); if ( wxDisableButtonBrush ) { // TODO: ::DeleteObject( wxDisableButtonBrush ); } delete wxWinHandleHash; wxWinHandleHash = NULL; // Delete Message queue if (wxTheApp->m_hMq) ::WinDestroyMsgQueue(wxTheApp->m_hMq); wxAppBase::CleanUp(); } // end of wxApp::CleanUp bool wxApp::OnInitGui() { ERRORID vError; wxString sError; if (!wxAppBase::OnInitGui()) return false; m_hMq = ::WinCreateMsgQueue(vHabmain, 0); if (!m_hMq) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); wxLogDebug(sError); return false; } return true; } // end of wxApp::OnInitGui wxApp::wxApp() { argc = 0; argv = NULL; m_nPrintMode = wxPRINT_WINDOWS; m_hMq = 0; m_maxSocketHandles = 0; m_maxSocketNr = 0; m_sockCallbackInfo = 0; } // end of wxApp::wxApp wxApp::~wxApp() { // // Delete command-line args // #if wxUSE_UNICODE int i; for (i = 0; i < argc; i++) { delete[] argv[i]; } delete[] argv; #endif } // end of wxApp::~wxApp bool gbInOnIdle = false; void wxApp::OnIdle( wxIdleEvent& rEvent ) { // // Avoid recursion (via ProcessEvent default case) // if (gbInOnIdle) return; gbInOnIdle = true; wxAppBase::OnIdle(rEvent); #if wxUSE_DC_CACHEING // automated DC cache management: clear the cached DCs and bitmap // if it's likely that the app has finished with them, that is, we // get an idle event and we're not dragging anything. if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) && !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) && !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2)) wxDC::ClearCache(); #endif // wxUSE_DC_CACHEING gbInOnIdle = false; } // end of wxApp::OnIdle void wxApp::OnEndSession( wxCloseEvent& WXUNUSED(rEvent)) { if (GetTopWindow()) GetTopWindow()->Close(true); } // end of wxApp::OnEndSession // // Default behaviour: close the application with prompts. The // user can veto the close, and therefore the end session. // void wxApp::OnQueryEndSession( wxCloseEvent& rEvent ) { if (GetTopWindow()) { if (!GetTopWindow()->Close(!rEvent.CanVeto())) rEvent.Veto(true); } } // end of wxApp::OnQueryEndSession // // Yield to incoming messages // bool wxApp::Yield(bool onlyIfNeeded) { static bool s_inYield = false; if ( s_inYield ) { if ( !onlyIfNeeded ) { wxFAIL_MSG( _T("wxYield() called recursively") ); } return false; } HAB vHab = 0; QMSG vMsg; // // Disable log flushing from here because a call to wxYield() shouldn't // normally result in message boxes popping up &c // wxLog::Suspend(); s_inYield = true; // // We want to go back to the main message loop // if we see a WM_QUIT. (?) // wxEventLoopGuarantor dummyLoopIfNeeded; while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT) { #if wxUSE_THREADS wxMutexGuiLeaveOrEnter(); #endif // wxUSE_THREADS if (!wxTheApp->Dispatch()) break; } // // If they are pending events, we must process them. // if (wxTheApp) wxTheApp->ProcessPendingEvents(); HandleSockets(); // // Let the logs be flashed again // wxLog::Resume(); s_inYield = false; return true; } // end of wxYield int wxApp::AddSocketHandler(int handle, int mask, void (*callback)(void*), void * gsock) { int find; struct GsocketCallbackInfo *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo; for (find = 0; find < m_maxSocketHandles; find++) if (CallbackInfo[find].handle == -1) break; if (find == m_maxSocketHandles) { // Allocate new memory m_sockCallbackInfo = realloc(m_sockCallbackInfo, (m_maxSocketHandles+=10)* sizeof(struct GsocketCallbackInfo)); CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo; for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++) CallbackInfo[find].handle = -1; find = m_maxSocketHandles - 10; } CallbackInfo[find].proc = callback; CallbackInfo[find].type = mask; CallbackInfo[find].handle = handle; CallbackInfo[find].gsock = gsock; if (mask & wxSockReadMask) FD_SET(handle, &m_readfds); if (mask & wxSockWriteMask) FD_SET(handle, &m_writefds); if (handle >= m_maxSocketNr) m_maxSocketNr = handle + 1; return find; } void wxApp::RemoveSocketHandler(int handle) { struct GsocketCallbackInfo *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo; if (handle < m_maxSocketHandles) { if (CallbackInfo[handle].type & wxSockReadMask) FD_CLR(CallbackInfo[handle].handle, &m_readfds); if (CallbackInfo[handle].type & wxSockWriteMask) FD_CLR(CallbackInfo[handle].handle, &m_writefds); CallbackInfo[handle].handle = -1; } } //----------------------------------------------------------------------------- // wxWakeUpIdle //----------------------------------------------------------------------------- void wxApp::WakeUpIdle() { // // Send the top window a dummy message so idle handler processing will // start up again. Doing it this way ensures that the idle handler // wakes up in the right thread (see also wxWakeUpMainThread() which does // the same for the main app thread only) // wxWindow* pTopWindow = wxTheApp->GetTopWindow(); if (pTopWindow) { if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0)) { // // Should never happen // wxLogLastError(wxT("PostMessage(WM_NULL)")); } } } // end of wxWakeUpIdle HAB wxGetInstance() { return vHabmain; } void wxSetInstance( HAB vHab ) { vHabmain = vHab; }