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