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"
31 #include "wx/wxchar.h"
33 #include "wx/stdpaths.h"
34 #include "wx/filename.h"
38 #include "wx/module.h"
40 #include "wx/os2/private.h"
44 #include <sys/ioctl.h>
45 #include <sys/select.h>
50 #include <sys/ioctl.h>
51 #include <sys/select.h>
56 #if defined(__WATCOMC__)
60 #elif !defined(__EMX__)
62 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
63 extern "C" int _System
bsdselect(int,
71 #include "wx/thread.h"
72 #endif // wxUSE_THREADS
75 #include "wx/tooltip.h"
76 #endif // wxUSE_TOOLTIPS
81 // ---------------------------------------------------------------------------
83 // ---------------------------------------------------------------------------
85 extern wxChar
* wxBuffer
;
86 extern wxList WXDLLEXPORT wxPendingDelete
;
87 extern wxCursor
* g_globalCursor
;
89 HAB vHabmain
= NULLHANDLE
;
92 HICON wxSTD_FRAME_ICON
= (HICON
) NULL
;
93 HICON wxSTD_MDICHILDFRAME_ICON
= (HICON
) NULL
;
94 HICON wxSTD_MDIPARENTFRAME_ICON
= (HICON
) NULL
;
96 HICON wxDEFAULT_FRAME_ICON
= (HICON
) NULL
;
97 HICON wxDEFAULT_MDICHILDFRAME_ICON
= (HICON
) NULL
;
98 HICON wxDEFAULT_MDIPARENTFRAME_ICON
= (HICON
) NULL
;
100 HBRUSH wxDisableButtonBrush
= (HBRUSH
) 0;
102 MRESULT EXPENTRY
wxWndProc( HWND hWnd
,ULONG message
,MPARAM mp1
,MPARAM mp2
);
103 MRESULT EXPENTRY
wxFrameWndProc( HWND hWnd
,ULONG message
,MPARAM mp1
,MPARAM mp2
);
105 // ===========================================================================
107 // ===========================================================================
109 // ---------------------------------------------------------------------------
110 // helper struct and functions for socket handling
111 // ---------------------------------------------------------------------------
113 struct GsocketCallbackInfo
{
114 void (*proc
)(void *);
120 // These defines are used here and in gsockpm.cpp
121 #define wxSockReadMask 0x01
122 #define wxSockWriteMask 0x02
124 void wxApp::HandleSockets()
126 bool pendingEvent
= false;
128 // Check whether it's time for Gsocket operation
129 if (m_maxSocketHandles
> 0 && m_maxSocketNr
> 0)
131 fd_set readfds
= m_readfds
;
132 fd_set writefds
= m_writefds
;
133 struct timeval timeout
;
135 struct GsocketCallbackInfo
136 *CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
139 if ( select(m_maxSocketNr
, &readfds
, &writefds
, 0, &timeout
) > 0)
141 for (i
= m_lastUsedHandle
+ 1; i
!= m_lastUsedHandle
;
142 (i
< m_maxSocketNr
- 1) ? i
++ : (i
= 0))
144 if (FD_ISSET(i
, &readfds
))
147 for (r
= 0; r
< m_maxSocketHandles
; r
++){
148 if(CallbackInfo
[r
].handle
== i
&&
149 CallbackInfo
[r
].type
== wxSockReadMask
)
152 if (r
< m_maxSocketHandles
)
154 CallbackInfo
[r
].proc(CallbackInfo
[r
].gsock
);
158 if (FD_ISSET(i
, &writefds
))
161 for (r
= 0; r
< m_maxSocketHandles
; r
++)
162 if(CallbackInfo
[r
].handle
== i
&&
163 CallbackInfo
[r
].type
== wxSockWriteMask
)
165 if (r
< m_maxSocketHandles
)
167 CallbackInfo
[r
].proc(CallbackInfo
[r
].gsock
);
172 m_lastUsedHandle
= i
;
175 ProcessPendingEvents();
178 // ---------------------------------------------------------------------------
180 // ---------------------------------------------------------------------------
182 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
)
184 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
185 EVT_IDLE(wxApp::OnIdle
)
186 EVT_END_SESSION(wxApp::OnEndSession
)
187 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
)
193 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
195 if ( !wxAppBase::Initialize(argc
, argv
) )
198 #if defined(wxUSE_CONSOLEDEBUG)
199 #if wxUSE_CONSOLEDEBUG
200 /***********************************************/
201 /* Code for using stdout debug */
202 /* To use it you mast link app as "Window" - EK*/
203 /***********************************************/
208 printf("In console\n");
210 DosGetInfoBlocks(&tib
, &pib
);
211 /* Try morphing into a PM application. */
212 // if(pib->pib_ultype == 2) /* VIO */
215 /**********************************************/
216 /**********************************************/
217 #endif //wxUSE_CONSOLEDEBUG
221 // OS2 has to have an anchorblock
223 vHabmain
= WinInitialize(0);
224 wxFileName
GetPrefix(argv
[0]);
225 GetPrefix
.MakeAbsolute();
226 wxStandardPaths::SetInstallPrefix(GetPrefix
.GetPath());
229 // TODO: at least give some error message here...
230 wxAppBase::CleanUp();
235 wxBuffer
= new wxChar
[1500]; // FIXME; why?
237 // Some people may wish to use this, but
238 // probably it shouldn't be here by default.
240 // wxRedirectIOToConsole();
243 wxWinHandleHash
= new wxWinHashTable(wxKEY_INTEGER
, 100);
245 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
246 // PLEASE DO NOT ALTER THIS.
247 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
248 extern char wxDummyChar
;
249 if (wxDummyChar
) wxDummyChar
++;
252 // wxSetKeyboardHook(TRUE);
254 RegisterWindowClasses(vHabmain
);
257 } // end of wxApp::Initialize
259 const char* CANTREGISTERCLASS
= " Can't register Class ";
260 // ---------------------------------------------------------------------------
261 // RegisterWindowClasses
262 // ---------------------------------------------------------------------------
264 bool wxApp::RegisterWindowClasses( HAB vHab
)
269 if (!::WinRegisterClass( vHab
270 ,(PSZ
)wxFrameClassName
272 ,CS_SIZEREDRAW
| CS_SYNCPAINT
276 vError
= ::WinGetLastError(vHab
);
277 sError
= wxPMErrorToStr(vError
);
278 wxLogLastError(sError
.c_str());
282 if (!::WinRegisterClass( vHab
283 ,(PSZ
)wxFrameClassNameNoRedraw
289 vError
= ::WinGetLastError(vHab
);
290 sError
= wxPMErrorToStr(vError
);
291 wxLogLastError(sError
.c_str());
295 if (!::WinRegisterClass( vHab
296 ,(PSZ
)wxMDIFrameClassName
298 ,CS_SIZEREDRAW
| CS_MOVENOTIFY
| CS_SYNCPAINT
302 vError
= ::WinGetLastError(vHab
);
303 sError
= wxPMErrorToStr(vError
);
304 wxLogLastError(sError
.c_str());
308 if (!::WinRegisterClass( vHab
309 ,(PSZ
)wxMDIFrameClassNameNoRedraw
315 vError
= ::WinGetLastError(vHab
);
316 sError
= wxPMErrorToStr(vError
);
317 wxLogLastError(sError
.c_str());
321 if (!::WinRegisterClass( vHab
322 ,(PSZ
)wxMDIChildFrameClassName
324 ,CS_MOVENOTIFY
| CS_SIZEREDRAW
| CS_SYNCPAINT
| CS_HITTEST
328 vError
= ::WinGetLastError(vHab
);
329 sError
= wxPMErrorToStr(vError
);
330 wxLogLastError(sError
.c_str());
334 if (!::WinRegisterClass( vHab
335 ,(PSZ
)wxMDIChildFrameClassNameNoRedraw
341 vError
= ::WinGetLastError(vHab
);
342 sError
= wxPMErrorToStr(vError
);
343 wxLogLastError(sError
.c_str());
347 if (!::WinRegisterClass( vHab
348 ,(PSZ
)wxPanelClassName
350 ,CS_MOVENOTIFY
| CS_SIZEREDRAW
| CS_HITTEST
| CS_SAVEBITS
| CS_SYNCPAINT
354 vError
= ::WinGetLastError(vHab
);
355 sError
= wxPMErrorToStr(vError
);
356 wxLogLastError(sError
.c_str());
360 if (!::WinRegisterClass( vHab
361 ,(PSZ
)wxCanvasClassName
363 ,CS_SIZEREDRAW
| CS_HITTEST
| CS_SYNCPAINT
367 vError
= ::WinGetLastError(vHab
);
368 sError
= wxPMErrorToStr(vError
);
369 wxLogLastError(sError
.c_str());
372 if (!::WinRegisterClass( vHab
373 ,(PSZ
)wxCanvasClassNameNR
375 ,CS_HITTEST
| CS_SYNCPAINT
379 vError
= ::WinGetLastError(vHab
);
380 sError
= wxPMErrorToStr(vError
);
381 wxLogLastError(sError
.c_str());
385 } // end of wxApp::RegisterWindowClasses
388 // Cleans up any wxWidgets internal structures left lying around
390 void wxApp::CleanUp()
396 // PM-SPECIFIC CLEANUP
399 // wxSetKeyboardHook(false);
401 if (wxSTD_FRAME_ICON
)
402 ::WinFreeFileIcon(wxSTD_FRAME_ICON
);
403 if (wxSTD_MDICHILDFRAME_ICON
)
404 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON
);
405 if (wxSTD_MDIPARENTFRAME_ICON
)
406 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON
);
408 if (wxDEFAULT_FRAME_ICON
)
409 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON
);
410 if (wxDEFAULT_MDICHILDFRAME_ICON
)
411 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON
);
412 if (wxDEFAULT_MDIPARENTFRAME_ICON
)
413 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON
);
415 if ( wxDisableButtonBrush
)
417 // TODO: ::DeleteObject( wxDisableButtonBrush );
420 delete wxWinHandleHash
;
421 wxWinHandleHash
= NULL
;
423 // Delete Message queue
425 ::WinDestroyMsgQueue(wxTheApp
->m_hMq
);
427 wxAppBase::CleanUp();
428 } // end of wxApp::CleanUp
430 bool wxApp::OnInitGui()
435 if (!wxAppBase::OnInitGui())
438 m_hMq
= ::WinCreateMsgQueue(vHabmain
, 0);
441 vError
= ::WinGetLastError(vHabmain
);
442 sError
= wxPMErrorToStr(vError
);
448 } // end of wxApp::OnInitGui
454 m_nPrintMode
= wxPRINT_WINDOWS
;
456 m_maxSocketHandles
= 0;
458 m_sockCallbackInfo
= 0;
459 } // end of wxApp::wxApp
464 // Delete command-line args
469 for (i
= 0; i
< argc
; i
++)
475 } // end of wxApp::~wxApp
477 bool gbInOnIdle
= false;
479 void wxApp::OnIdle( wxIdleEvent
& rEvent
)
482 // Avoid recursion (via ProcessEvent default case)
489 wxAppBase::OnIdle(rEvent
);
491 #if wxUSE_DC_CACHEING
492 // automated DC cache management: clear the cached DCs and bitmap
493 // if it's likely that the app has finished with them, that is, we
494 // get an idle event and we're not dragging anything.
495 if (!::WinGetKeyState(HWND_DESKTOP
, VK_BUTTON1
) &&
496 !::WinGetKeyState(HWND_DESKTOP
, VK_BUTTON3
) &&
497 !::WinGetKeyState(HWND_DESKTOP
, VK_BUTTON2
))
499 #endif // wxUSE_DC_CACHEING
502 } // end of wxApp::OnIdle
504 void wxApp::OnEndSession(
505 wxCloseEvent
& WXUNUSED(rEvent
))
508 GetTopWindow()->Close(true);
509 } // end of wxApp::OnEndSession
512 // Default behaviour: close the application with prompts. The
513 // user can veto the close, and therefore the end session.
515 void wxApp::OnQueryEndSession( wxCloseEvent
& rEvent
)
519 if (!GetTopWindow()->Close(!rEvent
.CanVeto()))
522 } // end of wxApp::OnQueryEndSession
525 // Yield to incoming messages
527 bool wxApp::Yield(bool onlyIfNeeded
)
529 static bool s_inYield
= false;
535 wxFAIL_MSG( _T("wxYield() called recursively") );
545 // Disable log flushing from here because a call to wxYield() shouldn't
546 // normally result in message boxes popping up &c
553 // We want to go back to the main message loop
554 // if we see a WM_QUIT. (?)
556 while (::WinPeekMsg(vHab
, &vMsg
, (HWND
)NULL
, 0, 0, PM_NOREMOVE
) && vMsg
.msg
!= WM_QUIT
)
559 wxMutexGuiLeaveOrEnter();
560 #endif // wxUSE_THREADS
561 if (!wxTheApp
->Dispatch())
565 // If they are pending events, we must process them.
568 wxTheApp
->ProcessPendingEvents();
572 // Let the logs be flashed again
579 int wxApp::AddSocketHandler(int handle
, int mask
,
580 void (*callback
)(void*), void * gsock
)
583 struct GsocketCallbackInfo
584 *CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
586 for (find
= 0; find
< m_maxSocketHandles
; find
++)
587 if (CallbackInfo
[find
].handle
== -1)
589 if (find
== m_maxSocketHandles
)
591 // Allocate new memory
592 m_sockCallbackInfo
= realloc(m_sockCallbackInfo
,
593 (m_maxSocketHandles
+=10)*
594 sizeof(struct GsocketCallbackInfo
));
595 CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
596 for (find
= m_maxSocketHandles
- 10; find
< m_maxSocketHandles
; find
++)
597 CallbackInfo
[find
].handle
= -1;
598 find
= m_maxSocketHandles
- 10;
600 CallbackInfo
[find
].proc
= callback
;
601 CallbackInfo
[find
].type
= mask
;
602 CallbackInfo
[find
].handle
= handle
;
603 CallbackInfo
[find
].gsock
= gsock
;
604 if (mask
& wxSockReadMask
)
605 FD_SET(handle
, &m_readfds
);
606 if (mask
& wxSockWriteMask
)
607 FD_SET(handle
, &m_writefds
);
608 if (handle
>= m_maxSocketNr
)
609 m_maxSocketNr
= handle
+ 1;
613 void wxApp::RemoveSocketHandler(int handle
)
615 struct GsocketCallbackInfo
616 *CallbackInfo
= (struct GsocketCallbackInfo
*)m_sockCallbackInfo
;
617 if (handle
< m_maxSocketHandles
)
619 if (CallbackInfo
[handle
].type
& wxSockReadMask
)
620 FD_CLR(CallbackInfo
[handle
].handle
, &m_readfds
);
621 if (CallbackInfo
[handle
].type
& wxSockWriteMask
)
622 FD_CLR(CallbackInfo
[handle
].handle
, &m_writefds
);
623 CallbackInfo
[handle
].handle
= -1;
627 //-----------------------------------------------------------------------------
629 //-----------------------------------------------------------------------------
631 void wxApp::WakeUpIdle()
634 // Send the top window a dummy message so idle handler processing will
635 // start up again. Doing it this way ensures that the idle handler
636 // wakes up in the right thread (see also wxWakeUpMainThread() which does
637 // the same for the main app thread only)
639 wxWindow
* pTopWindow
= wxTheApp
->GetTopWindow();
643 if ( !::WinPostMsg(GetHwndOf(pTopWindow
), WM_NULL
, (MPARAM
)0, (MPARAM
)0))
646 // Should never happen
648 wxLogLastError(wxT("PostMessage(WM_NULL)"));
651 } // end of wxWakeUpIdle
658 void wxSetInstance( HAB vHab
)