]> git.saurik.com Git - wxWidgets.git/blob - src/os2/app.cpp
Include wx/log.h according to precompiled headers of wx/wx.h (with other minor cleaning).
[wxWidgets.git] / src / os2 / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/app.cpp
3 // Purpose: wxApp
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/13/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #include "wx/app.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/dynarray.h"
19 #include "wx/frame.h"
20 #include "wx/utils.h"
21 #include "wx/gdicmn.h"
22 #include "wx/pen.h"
23 #include "wx/brush.h"
24 #include "wx/cursor.h"
25 #include "wx/icon.h"
26 #include "wx/palette.h"
27 #include "wx/dc.h"
28 #include "wx/dialog.h"
29 #include "wx/msgdlg.h"
30 #include "wx/intl.h"
31 #include "wx/wxchar.h"
32 #include "wx/icon.h"
33 #include "wx/stdpaths.h"
34 #include "wx/filename.h"
35 #include "wx/log.h"
36 #endif
37
38 #include "wx/module.h"
39
40 #include "wx/os2/private.h"
41
42 #ifdef __EMX__
43
44 #include <sys/ioctl.h>
45 #include <sys/select.h>
46
47 #else
48
49 #include <nerrno.h>
50 #include <sys/ioctl.h>
51 #include <sys/select.h>
52 #include <sys/time.h>
53
54 #endif //
55
56 #if defined(__WATCOMC__)
57
58 #include <tcpustd.h>
59
60 #elif !defined(__EMX__)
61
62 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
63 extern "C" int _System bsdselect(int,
64 struct fd_set *,
65 struct fd_set *,
66 struct fd_set *,
67 struct timeval *);
68 #endif
69
70 #if wxUSE_THREADS
71 #include "wx/thread.h"
72 #endif // wxUSE_THREADS
73
74 #if wxUSE_TOOLTIPS
75 #include "wx/tooltip.h"
76 #endif // wxUSE_TOOLTIPS
77
78 #include <string.h>
79 #include <ctype.h>
80
81 // ---------------------------------------------------------------------------
82 // global variables
83 // ---------------------------------------------------------------------------
84
85 extern wxChar* wxBuffer;
86 extern wxList WXDLLEXPORT wxPendingDelete;
87 extern wxCursor* g_globalCursor;
88
89 HAB vHabmain = NULLHANDLE;
90
91
92 HICON wxSTD_FRAME_ICON = (HICON) NULL;
93 HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
94 HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
95
96 HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
97 HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
98 HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
99
100 HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
101
102 MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
103 MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
104
105 // ===========================================================================
106 // implementation
107 // ===========================================================================
108
109 // ---------------------------------------------------------------------------
110 // helper struct and functions for socket handling
111 // ---------------------------------------------------------------------------
112
113 struct GsocketCallbackInfo{
114 void (*proc)(void *);
115 int type;
116 int handle;
117 void* gsock;
118 };
119
120 // These defines are used here and in gsockpm.cpp
121 #define wxSockReadMask 0x01
122 #define wxSockWriteMask 0x02
123
124 void wxApp::HandleSockets()
125 {
126 bool pendingEvent = false;
127
128 // Check whether it's time for Gsocket operation
129 if (m_maxSocketHandles > 0 && m_maxSocketNr > 0)
130 {
131 fd_set readfds = m_readfds;
132 fd_set writefds = m_writefds;
133 struct timeval timeout;
134 int i;
135 struct GsocketCallbackInfo
136 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
137 timeout.tv_sec = 0;
138 timeout.tv_usec = 0;
139 if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0)
140 {
141 for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle;
142 (i < m_maxSocketNr - 1) ? i++ : (i = 0))
143 {
144 if (FD_ISSET(i, &readfds))
145 {
146 int r;
147 for (r = 0; r < m_maxSocketHandles; r++){
148 if(CallbackInfo[r].handle == i &&
149 CallbackInfo[r].type == wxSockReadMask)
150 break;
151 }
152 if (r < m_maxSocketHandles)
153 {
154 CallbackInfo[r].proc(CallbackInfo[r].gsock);
155 pendingEvent = true;
156 }
157 }
158 if (FD_ISSET(i, &writefds))
159 {
160 int r;
161 for (r = 0; r < m_maxSocketHandles; r++)
162 if(CallbackInfo[r].handle == i &&
163 CallbackInfo[r].type == wxSockWriteMask)
164 break;
165 if (r < m_maxSocketHandles)
166 {
167 CallbackInfo[r].proc(CallbackInfo[r].gsock);
168 pendingEvent = true;
169 }
170 }
171 }
172 m_lastUsedHandle = i;
173 }
174 if (pendingEvent)
175 ProcessPendingEvents();
176 }
177 }
178 // ---------------------------------------------------------------------------
179 // wxApp
180 // ---------------------------------------------------------------------------
181
182 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
183
184 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
185 EVT_IDLE(wxApp::OnIdle)
186 EVT_END_SESSION(wxApp::OnEndSession)
187 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
188 END_EVENT_TABLE()
189
190 //
191 // Initialize
192 //
193 bool wxApp::Initialize(int& argc, wxChar **argv)
194 {
195 if ( !wxAppBase::Initialize(argc, argv) )
196 return false;
197
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 /***********************************************/
204 {
205 PPIB pib;
206 PTIB tib;
207
208 printf("In console\n");
209
210 DosGetInfoBlocks(&tib, &pib);
211 /* Try morphing into a PM application. */
212 // if(pib->pib_ultype == 2) /* VIO */
213 pib->pib_ultype = 3;
214 }
215 /**********************************************/
216 /**********************************************/
217 #endif //wxUSE_CONSOLEDEBUG
218 #endif
219
220 //
221 // OS2 has to have an anchorblock
222 //
223 vHabmain = WinInitialize(0);
224 wxFileName GetPrefix(argv[0]);
225 GetPrefix.MakeAbsolute();
226 wxStandardPaths::SetInstallPrefix(GetPrefix.GetPath());
227 if (!vHabmain)
228 {
229 // TODO: at least give some error message here...
230 wxAppBase::CleanUp();
231
232 return false;
233 }
234
235 wxBuffer = new wxChar[1500]; // FIXME; why?
236
237 // Some people may wish to use this, but
238 // probably it shouldn't be here by default.
239 #ifdef __WXDEBUG__
240 // wxRedirectIOToConsole();
241 #endif
242
243 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
244
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++;
250 #endif
251
252 // wxSetKeyboardHook(TRUE);
253
254 RegisterWindowClasses(vHabmain);
255
256 return true;
257 } // end of wxApp::Initialize
258
259 const char* CANTREGISTERCLASS = " Can't register Class ";
260 // ---------------------------------------------------------------------------
261 // RegisterWindowClasses
262 // ---------------------------------------------------------------------------
263
264 bool wxApp::RegisterWindowClasses( HAB vHab )
265 {
266 ERRORID vError = 0L;
267 wxString sError;
268
269 if (!::WinRegisterClass( vHab
270 ,(PSZ)wxFrameClassName
271 ,wxFrameWndProc
272 ,CS_SIZEREDRAW | CS_SYNCPAINT
273 ,sizeof(ULONG)
274 ))
275 {
276 vError = ::WinGetLastError(vHab);
277 sError = wxPMErrorToStr(vError);
278 wxLogLastError(sError.c_str());
279 return false;
280 }
281
282 if (!::WinRegisterClass( vHab
283 ,(PSZ)wxFrameClassNameNoRedraw
284 ,wxWndProc
285 ,0
286 ,sizeof(ULONG)
287 ))
288 {
289 vError = ::WinGetLastError(vHab);
290 sError = wxPMErrorToStr(vError);
291 wxLogLastError(sError.c_str());
292 return false;
293 }
294
295 if (!::WinRegisterClass( vHab
296 ,(PSZ)wxMDIFrameClassName
297 ,wxWndProc
298 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
299 ,sizeof(ULONG)
300 ))
301 {
302 vError = ::WinGetLastError(vHab);
303 sError = wxPMErrorToStr(vError);
304 wxLogLastError(sError.c_str());
305 return false;
306 }
307
308 if (!::WinRegisterClass( vHab
309 ,(PSZ)wxMDIFrameClassNameNoRedraw
310 ,wxWndProc
311 ,0
312 ,sizeof(ULONG)
313 ))
314 {
315 vError = ::WinGetLastError(vHab);
316 sError = wxPMErrorToStr(vError);
317 wxLogLastError(sError.c_str());
318 return false;
319 }
320
321 if (!::WinRegisterClass( vHab
322 ,(PSZ)wxMDIChildFrameClassName
323 ,wxWndProc
324 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
325 ,sizeof(ULONG)
326 ))
327 {
328 vError = ::WinGetLastError(vHab);
329 sError = wxPMErrorToStr(vError);
330 wxLogLastError(sError.c_str());
331 return false;
332 }
333
334 if (!::WinRegisterClass( vHab
335 ,(PSZ)wxMDIChildFrameClassNameNoRedraw
336 ,wxWndProc
337 ,CS_HITTEST
338 ,sizeof(ULONG)
339 ))
340 {
341 vError = ::WinGetLastError(vHab);
342 sError = wxPMErrorToStr(vError);
343 wxLogLastError(sError.c_str());
344 return false;
345 }
346
347 if (!::WinRegisterClass( vHab
348 ,(PSZ)wxPanelClassName
349 ,wxWndProc
350 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
351 ,sizeof(ULONG)
352 ))
353 {
354 vError = ::WinGetLastError(vHab);
355 sError = wxPMErrorToStr(vError);
356 wxLogLastError(sError.c_str());
357 return false;
358 }
359
360 if (!::WinRegisterClass( vHab
361 ,(PSZ)wxCanvasClassName
362 ,wxWndProc
363 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
364 ,sizeof(ULONG)
365 ))
366 {
367 vError = ::WinGetLastError(vHab);
368 sError = wxPMErrorToStr(vError);
369 wxLogLastError(sError.c_str());
370 return false;
371 }
372 if (!::WinRegisterClass( vHab
373 ,(PSZ)wxCanvasClassNameNR
374 ,wxWndProc
375 ,CS_HITTEST | CS_SYNCPAINT
376 ,sizeof(ULONG)
377 ))
378 {
379 vError = ::WinGetLastError(vHab);
380 sError = wxPMErrorToStr(vError);
381 wxLogLastError(sError.c_str());
382 return false;
383 }
384 return true;
385 } // end of wxApp::RegisterWindowClasses
386
387 //
388 // Cleans up any wxWidgets internal structures left lying around
389 //
390 void wxApp::CleanUp()
391 {
392 delete[] wxBuffer;
393 wxBuffer = NULL;
394
395 //
396 // PM-SPECIFIC CLEANUP
397 //
398
399 // wxSetKeyboardHook(false);
400
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);
407
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);
414
415 if ( wxDisableButtonBrush )
416 {
417 // TODO: ::DeleteObject( wxDisableButtonBrush );
418 }
419
420 delete wxWinHandleHash;
421 wxWinHandleHash = NULL;
422
423 // Delete Message queue
424 if (wxTheApp->m_hMq)
425 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
426
427 wxAppBase::CleanUp();
428 } // end of wxApp::CleanUp
429
430 bool wxApp::OnInitGui()
431 {
432 ERRORID vError;
433 wxString sError;
434
435 if (!wxAppBase::OnInitGui())
436 return false;
437
438 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
439 if (!m_hMq)
440 {
441 vError = ::WinGetLastError(vHabmain);
442 sError = wxPMErrorToStr(vError);
443 wxLogDebug(sError);
444 return false;
445 }
446
447 return true;
448 } // end of wxApp::OnInitGui
449
450 wxApp::wxApp()
451 {
452 argc = 0;
453 argv = NULL;
454 m_nPrintMode = wxPRINT_WINDOWS;
455 m_hMq = 0;
456 m_maxSocketHandles = 0;
457 m_maxSocketNr = 0;
458 m_sockCallbackInfo = 0;
459 } // end of wxApp::wxApp
460
461 wxApp::~wxApp()
462 {
463 //
464 // Delete command-line args
465 //
466 #if wxUSE_UNICODE
467 int i;
468
469 for (i = 0; i < argc; i++)
470 {
471 delete[] argv[i];
472 }
473 delete[] argv;
474 #endif
475 } // end of wxApp::~wxApp
476
477 bool gbInOnIdle = false;
478
479 void wxApp::OnIdle( wxIdleEvent& rEvent )
480 {
481 //
482 // Avoid recursion (via ProcessEvent default case)
483 //
484 if (gbInOnIdle)
485 return;
486
487 gbInOnIdle = true;
488
489 wxAppBase::OnIdle(rEvent);
490
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))
498 wxDC::ClearCache();
499 #endif // wxUSE_DC_CACHEING
500
501 gbInOnIdle = false;
502 } // end of wxApp::OnIdle
503
504 void wxApp::OnEndSession(
505 wxCloseEvent& WXUNUSED(rEvent))
506 {
507 if (GetTopWindow())
508 GetTopWindow()->Close(true);
509 } // end of wxApp::OnEndSession
510
511 //
512 // Default behaviour: close the application with prompts. The
513 // user can veto the close, and therefore the end session.
514 //
515 void wxApp::OnQueryEndSession( wxCloseEvent& rEvent )
516 {
517 if (GetTopWindow())
518 {
519 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
520 rEvent.Veto(true);
521 }
522 } // end of wxApp::OnQueryEndSession
523
524 //
525 // Yield to incoming messages
526 //
527 bool wxApp::Yield(bool onlyIfNeeded)
528 {
529 static bool s_inYield = false;
530
531 if ( s_inYield )
532 {
533 if ( !onlyIfNeeded )
534 {
535 wxFAIL_MSG( _T("wxYield() called recursively") );
536 }
537
538 return false;
539 }
540
541 HAB vHab = 0;
542 QMSG vMsg;
543
544 //
545 // Disable log flushing from here because a call to wxYield() shouldn't
546 // normally result in message boxes popping up &c
547 //
548 wxLog::Suspend();
549
550 s_inYield = true;
551
552 //
553 // We want to go back to the main message loop
554 // if we see a WM_QUIT. (?)
555 //
556 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
557 {
558 #if wxUSE_THREADS
559 wxMutexGuiLeaveOrEnter();
560 #endif // wxUSE_THREADS
561 if (!wxTheApp->Dispatch())
562 break;
563 }
564 //
565 // If they are pending events, we must process them.
566 //
567 if (wxTheApp)
568 wxTheApp->ProcessPendingEvents();
569
570 HandleSockets();
571 //
572 // Let the logs be flashed again
573 //
574 wxLog::Resume();
575 s_inYield = false;
576 return true;
577 } // end of wxYield
578
579 int wxApp::AddSocketHandler(int handle, int mask,
580 void (*callback)(void*), void * gsock)
581 {
582 int find;
583 struct GsocketCallbackInfo
584 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
585
586 for (find = 0; find < m_maxSocketHandles; find++)
587 if (CallbackInfo[find].handle == -1)
588 break;
589 if (find == m_maxSocketHandles)
590 {
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;
599 }
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;
610 return find;
611 }
612
613 void wxApp::RemoveSocketHandler(int handle)
614 {
615 struct GsocketCallbackInfo
616 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
617 if (handle < m_maxSocketHandles)
618 {
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;
624 }
625 }
626
627 //-----------------------------------------------------------------------------
628 // wxWakeUpIdle
629 //-----------------------------------------------------------------------------
630
631 void wxApp::WakeUpIdle()
632 {
633 //
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)
638 //
639 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
640
641 if (pTopWindow)
642 {
643 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
644 {
645 //
646 // Should never happen
647 //
648 wxLogLastError(wxT("PostMessage(WM_NULL)"));
649 }
650 }
651 } // end of wxWakeUpIdle
652
653 HAB wxGetInstance()
654 {
655 return vHabmain;
656 }
657
658 void wxSetInstance( HAB vHab )
659 {
660 vHabmain = vHab;
661 }