1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/app.cpp
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"
18 #include "wx/dynarray.h"
21 #include "wx/gdicmn.h"
24 #include "wx/cursor.h"
26 #include "wx/palette.h"
28 #include "wx/dialog.h"
29 #include "wx/msgdlg.h"
33 #include "wx/module.h"
36 #include "wx/stdpaths.h"
37 #include "wx/filename.h"
39 #include "wx/os2/private.h"
43 #include <sys/ioctl.h>
44 #include <sys/select.h>
49 #include <sys/ioctl.h>
50 #include <sys/select.h>
55 #if defined(__WATCOMC__)
59 #elif !defined(__EMX__)
61 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
62 extern "C" int _System
bsdselect(int,
70 #include "wx/thread.h"
71 #endif // wxUSE_THREADS
74 #include "wx/tooltip.h"
75 #endif // wxUSE_TOOLTIPS
80 // ---------------------------------------------------------------------------
82 // ---------------------------------------------------------------------------
84 WXDLLEXPORT_DATA(wxChar
*) wxBuffer
;
85 extern wxCursor
* g_globalCursor
;
87 HAB vHabmain
= NULLHANDLE
;
90 HICON wxSTD_FRAME_ICON
= (HICON
) NULL
;
91 HICON wxSTD_MDICHILDFRAME_ICON
= (HICON
) NULL
;
92 HICON wxSTD_MDIPARENTFRAME_ICON
= (HICON
) NULL
;
94 HICON wxDEFAULT_FRAME_ICON
= (HICON
) NULL
;
95 HICON wxDEFAULT_MDICHILDFRAME_ICON
= (HICON
) NULL
;
96 HICON wxDEFAULT_MDIPARENTFRAME_ICON
= (HICON
) NULL
;
98 HBRUSH wxDisableButtonBrush
= (HBRUSH
) 0;
100 MRESULT EXPENTRY
wxWndProc( HWND hWnd
,ULONG message
,MPARAM mp1
,MPARAM mp2
);
101 MRESULT EXPENTRY
wxFrameWndProc( HWND hWnd
,ULONG message
,MPARAM mp1
,MPARAM mp2
);
103 // ===========================================================================
105 // ===========================================================================
107 // ---------------------------------------------------------------------------
108 // helper struct and functions for socket handling
109 // ---------------------------------------------------------------------------
111 struct GsocketCallbackInfo
{
112 void (*proc
)(void *);
118 // These defines are used here and in gsockpm.cpp
119 #define wxSockReadMask 0x01
120 #define wxSockWriteMask 0x02
122 void wxApp::HandleSockets()
124 bool pendingEvent
= false;
126 // Check whether it's time for Gsocket operation
127 if (m_maxSocketHandles
> 0 && m_maxSocketNr
> 0)
129 fd_set readfds
= m_readfds
;
130 fd_set writefds
= m_writefds
;
131 struct timeval timeout
;
133 struct GsocketCallbackInfo
134 *CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
137 if ( select(m_maxSocketNr
, &readfds
, &writefds
, 0, &timeout
) > 0)
139 for (i
= m_lastUsedHandle
+ 1; i
!= m_lastUsedHandle
;
140 (i
< m_maxSocketNr
- 1) ? i
++ : (i
= 0))
142 if (FD_ISSET(i
, &readfds
))
145 for (r
= 0; r
< m_maxSocketHandles
; r
++){
146 if(CallbackInfo
[r
].handle
== i
&&
147 CallbackInfo
[r
].type
== wxSockReadMask
)
150 if (r
< m_maxSocketHandles
)
152 CallbackInfo
[r
].proc(CallbackInfo
[r
].gsock
);
156 if (FD_ISSET(i
, &writefds
))
159 for (r
= 0; r
< m_maxSocketHandles
; r
++)
160 if(CallbackInfo
[r
].handle
== i
&&
161 CallbackInfo
[r
].type
== wxSockWriteMask
)
163 if (r
< m_maxSocketHandles
)
165 CallbackInfo
[r
].proc(CallbackInfo
[r
].gsock
);
170 m_lastUsedHandle
= i
;
173 ProcessPendingEvents();
176 // ---------------------------------------------------------------------------
178 // ---------------------------------------------------------------------------
180 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
)
182 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
183 EVT_IDLE(wxApp::OnIdle
)
184 EVT_END_SESSION(wxApp::OnEndSession
)
185 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
)
191 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
193 if ( !wxAppBase::Initialize(argc
, argv
) )
196 #if defined(wxUSE_CONSOLEDEBUG)
197 #if wxUSE_CONSOLEDEBUG
198 /***********************************************/
199 /* Code for using stdout debug */
200 /* To use it you mast link app as "Window" - EK*/
201 /***********************************************/
206 printf("In console\n");
208 DosGetInfoBlocks(&tib
, &pib
);
209 /* Try morphing into a PM application. */
210 // if(pib->pib_ultype == 2) /* VIO */
213 /**********************************************/
214 /**********************************************/
215 #endif //wxUSE_CONSOLEDEBUG
219 // OS2 has to have an anchorblock
221 vHabmain
= WinInitialize(0);
222 wxFileName
GetPrefix(argv
[0]);
223 GetPrefix
.MakeAbsolute();
224 wxStandardPaths::SetInstallPrefix(GetPrefix
.GetPath());
227 // TODO: at least give some error message here...
228 wxAppBase::CleanUp();
233 wxBuffer
= new wxChar
[1500]; // FIXME; why?
235 // Some people may wish to use this, but
236 // probably it shouldn't be here by default.
238 // wxRedirectIOToConsole();
241 wxWinHandleHash
= new wxWinHashTable(wxKEY_INTEGER
, 100);
243 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
244 // PLEASE DO NOT ALTER THIS.
245 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
246 extern char wxDummyChar
;
247 if (wxDummyChar
) wxDummyChar
++;
250 // wxSetKeyboardHook(TRUE);
252 RegisterWindowClasses(vHabmain
);
255 } // end of wxApp::Initialize
257 const char* CANTREGISTERCLASS
= " Can't register Class ";
258 // ---------------------------------------------------------------------------
259 // RegisterWindowClasses
260 // ---------------------------------------------------------------------------
262 bool wxApp::RegisterWindowClasses( HAB vHab
)
267 if (!::WinRegisterClass( vHab
268 ,(PSZ
)wxFrameClassName
270 ,CS_SIZEREDRAW
| CS_SYNCPAINT
274 vError
= ::WinGetLastError(vHab
);
275 sError
= wxPMErrorToStr(vError
);
276 wxLogLastError(sError
.c_str());
280 if (!::WinRegisterClass( vHab
281 ,(PSZ
)wxFrameClassNameNoRedraw
287 vError
= ::WinGetLastError(vHab
);
288 sError
= wxPMErrorToStr(vError
);
289 wxLogLastError(sError
.c_str());
293 if (!::WinRegisterClass( vHab
294 ,(PSZ
)wxMDIFrameClassName
296 ,CS_SIZEREDRAW
| CS_MOVENOTIFY
| CS_SYNCPAINT
300 vError
= ::WinGetLastError(vHab
);
301 sError
= wxPMErrorToStr(vError
);
302 wxLogLastError(sError
.c_str());
306 if (!::WinRegisterClass( vHab
307 ,(PSZ
)wxMDIFrameClassNameNoRedraw
313 vError
= ::WinGetLastError(vHab
);
314 sError
= wxPMErrorToStr(vError
);
315 wxLogLastError(sError
.c_str());
319 if (!::WinRegisterClass( vHab
320 ,(PSZ
)wxMDIChildFrameClassName
322 ,CS_MOVENOTIFY
| CS_SIZEREDRAW
| CS_SYNCPAINT
| CS_HITTEST
326 vError
= ::WinGetLastError(vHab
);
327 sError
= wxPMErrorToStr(vError
);
328 wxLogLastError(sError
.c_str());
332 if (!::WinRegisterClass( vHab
333 ,(PSZ
)wxMDIChildFrameClassNameNoRedraw
339 vError
= ::WinGetLastError(vHab
);
340 sError
= wxPMErrorToStr(vError
);
341 wxLogLastError(sError
.c_str());
345 if (!::WinRegisterClass( vHab
346 ,(PSZ
)wxPanelClassName
348 ,CS_MOVENOTIFY
| CS_SIZEREDRAW
| CS_HITTEST
| CS_SAVEBITS
| CS_SYNCPAINT
352 vError
= ::WinGetLastError(vHab
);
353 sError
= wxPMErrorToStr(vError
);
354 wxLogLastError(sError
.c_str());
358 if (!::WinRegisterClass( vHab
359 ,(PSZ
)wxCanvasClassName
361 ,CS_SIZEREDRAW
| CS_HITTEST
| CS_SYNCPAINT
365 vError
= ::WinGetLastError(vHab
);
366 sError
= wxPMErrorToStr(vError
);
367 wxLogLastError(sError
.c_str());
370 if (!::WinRegisterClass( vHab
371 ,(PSZ
)wxCanvasClassNameNR
373 ,CS_HITTEST
| CS_SYNCPAINT
377 vError
= ::WinGetLastError(vHab
);
378 sError
= wxPMErrorToStr(vError
);
379 wxLogLastError(sError
.c_str());
383 } // end of wxApp::RegisterWindowClasses
386 // Cleans up any wxWidgets internal structures left lying around
388 void wxApp::CleanUp()
394 // PM-SPECIFIC CLEANUP
397 // wxSetKeyboardHook(false);
399 if (wxSTD_FRAME_ICON
)
400 ::WinFreeFileIcon(wxSTD_FRAME_ICON
);
401 if (wxSTD_MDICHILDFRAME_ICON
)
402 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON
);
403 if (wxSTD_MDIPARENTFRAME_ICON
)
404 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON
);
406 if (wxDEFAULT_FRAME_ICON
)
407 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON
);
408 if (wxDEFAULT_MDICHILDFRAME_ICON
)
409 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON
);
410 if (wxDEFAULT_MDIPARENTFRAME_ICON
)
411 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON
);
413 if ( wxDisableButtonBrush
)
415 // TODO: ::DeleteObject( wxDisableButtonBrush );
418 delete wxWinHandleHash
;
419 wxWinHandleHash
= NULL
;
421 // Delete Message queue
423 ::WinDestroyMsgQueue(wxTheApp
->m_hMq
);
425 wxAppBase::CleanUp();
426 } // end of wxApp::CleanUp
428 bool wxApp::OnInitGui()
433 if (!wxAppBase::OnInitGui())
436 m_hMq
= ::WinCreateMsgQueue(vHabmain
, 0);
439 vError
= ::WinGetLastError(vHabmain
);
440 sError
= wxPMErrorToStr(vError
);
446 } // end of wxApp::OnInitGui
452 m_nPrintMode
= wxPRINT_WINDOWS
;
454 m_maxSocketHandles
= 0;
456 m_sockCallbackInfo
= 0;
457 } // end of wxApp::wxApp
462 // Delete command-line args
467 for (i
= 0; i
< argc
; i
++)
473 } // end of wxApp::~wxApp
475 bool gbInOnIdle
= false;
477 void wxApp::OnIdle( wxIdleEvent
& rEvent
)
480 // Avoid recursion (via ProcessEvent default case)
487 wxAppBase::OnIdle(rEvent
);
489 #if wxUSE_DC_CACHEING
490 // automated DC cache management: clear the cached DCs and bitmap
491 // if it's likely that the app has finished with them, that is, we
492 // get an idle event and we're not dragging anything.
493 if (!::WinGetKeyState(HWND_DESKTOP
, VK_BUTTON1
) &&
494 !::WinGetKeyState(HWND_DESKTOP
, VK_BUTTON3
) &&
495 !::WinGetKeyState(HWND_DESKTOP
, VK_BUTTON2
))
497 #endif // wxUSE_DC_CACHEING
500 } // end of wxApp::OnIdle
502 void wxApp::OnEndSession(
503 wxCloseEvent
& WXUNUSED(rEvent
))
506 GetTopWindow()->Close(true);
507 } // end of wxApp::OnEndSession
510 // Default behaviour: close the application with prompts. The
511 // user can veto the close, and therefore the end session.
513 void wxApp::OnQueryEndSession( wxCloseEvent
& rEvent
)
517 if (!GetTopWindow()->Close(!rEvent
.CanVeto()))
520 } // end of wxApp::OnQueryEndSession
523 // Yield to incoming messages
525 bool wxApp::Yield(bool onlyIfNeeded
)
527 static bool s_inYield
= false;
533 wxFAIL_MSG( _T("wxYield() called recursively") );
543 // Disable log flushing from here because a call to wxYield() shouldn't
544 // normally result in message boxes popping up &c
551 // We want to go back to the main message loop
552 // if we see a WM_QUIT. (?)
554 while (::WinPeekMsg(vHab
, &vMsg
, (HWND
)NULL
, 0, 0, PM_NOREMOVE
) && vMsg
.msg
!= WM_QUIT
)
557 wxMutexGuiLeaveOrEnter();
558 #endif // wxUSE_THREADS
559 if (!wxTheApp
->Dispatch())
563 // If they are pending events, we must process them.
566 wxTheApp
->ProcessPendingEvents();
570 // Let the logs be flashed again
577 int wxApp::AddSocketHandler(int handle
, int mask
,
578 void (*callback
)(void*), void * gsock
)
581 struct GsocketCallbackInfo
582 *CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
584 for (find
= 0; find
< m_maxSocketHandles
; find
++)
585 if (CallbackInfo
[find
].handle
== -1)
587 if (find
== m_maxSocketHandles
)
589 // Allocate new memory
590 m_sockCallbackInfo
= realloc(m_sockCallbackInfo
,
591 (m_maxSocketHandles
+=10)*
592 sizeof(struct GsocketCallbackInfo
));
593 CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
594 for (find
= m_maxSocketHandles
- 10; find
< m_maxSocketHandles
; find
++)
595 CallbackInfo
[find
].handle
= -1;
596 find
= m_maxSocketHandles
- 10;
598 CallbackInfo
[find
].proc
= callback
;
599 CallbackInfo
[find
].type
= mask
;
600 CallbackInfo
[find
].handle
= handle
;
601 CallbackInfo
[find
].gsock
= gsock
;
602 if (mask
& wxSockReadMask
)
603 FD_SET(handle
, &m_readfds
);
604 if (mask
& wxSockWriteMask
)
605 FD_SET(handle
, &m_writefds
);
606 if (handle
>= m_maxSocketNr
)
607 m_maxSocketNr
= handle
+ 1;
611 void wxApp::RemoveSocketHandler(int handle
)
613 struct GsocketCallbackInfo
614 *CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
615 if (handle
< m_maxSocketHandles
)
617 if (CallbackInfo
[handle
].type
& wxSockReadMask
)
618 FD_CLR(CallbackInfo
[handle
].handle
, &m_readfds
);
619 if (CallbackInfo
[handle
].type
& wxSockWriteMask
)
620 FD_CLR(CallbackInfo
[handle
].handle
, &m_writefds
);
621 CallbackInfo
[handle
].handle
= -1;
625 //-----------------------------------------------------------------------------
627 //-----------------------------------------------------------------------------
629 void wxApp::WakeUpIdle()
632 // Send the top window a dummy message so idle handler processing will
633 // start up again. Doing it this way ensures that the idle handler
634 // wakes up in the right thread (see also wxWakeUpMainThread() which does
635 // the same for the main app thread only)
637 wxWindow
* pTopWindow
= wxTheApp
->GetTopWindow();
641 if ( !::WinPostMsg(GetHwndOf(pTopWindow
), WM_NULL
, (MPARAM
)0, (MPARAM
)0))
644 // Should never happen
646 wxLogLastError(wxT("PostMessage(WM_NULL)"));
649 } // end of wxWakeUpIdle
656 void wxSetInstance( HAB vHab
)