Added wxStandardPaths implementation for OS/2.
[wxWidgets.git] / src / os2 / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 #ifdef __GNUG__
13 #pragma implementation "app.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/frame.h"
21 #include "wx/app.h"
22 #include "wx/utils.h"
23 #include "wx/gdicmn.h"
24 #include "wx/pen.h"
25 #include "wx/brush.h"
26 #include "wx/cursor.h"
27 #include "wx/icon.h"
28 #include "wx/palette.h"
29 #include "wx/dc.h"
30 #include "wx/dialog.h"
31 #include "wx/msgdlg.h"
32 #include "wx/intl.h"
33 #include "wx/dynarray.h"
34 #include "wx/wxchar.h"
35 #include "wx/icon.h"
36 #include "wx/stdpaths.h"
37 #include "wx/filename.h"
38 #endif
39
40 #include "wx/log.h"
41 #include "wx/module.h"
42
43 #include "wx/os2/private.h"
44
45 #ifdef __EMX__
46
47 #include <sys/ioctl.h>
48 #include <sys/select.h>
49
50 #else
51
52 #include <nerrno.h>
53 #include <sys/ioctl.h>
54 #include <sys/select.h>
55 #include <sys/time.h>
56
57 #endif //
58
59 #ifndef __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* wxWinHandleList;
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 wxWinHandleList = new wxList(wxKEY_INTEGER);
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(
265 HAB vHab
266 )
267 {
268 ERRORID vError = 0L;
269 wxString sError;
270
271 if (!::WinRegisterClass( vHab
272 ,wxFrameClassName
273 ,wxFrameWndProc
274 ,CS_SIZEREDRAW | CS_SYNCPAINT
275 ,sizeof(ULONG)
276 ))
277 {
278 vError = ::WinGetLastError(vHab);
279 sError = wxPMErrorToStr(vError);
280 wxLogLastError(sError.c_str());
281 return FALSE;
282 }
283
284 if (!::WinRegisterClass( vHab
285 ,wxFrameClassNameNoRedraw
286 ,wxWndProc
287 ,0
288 ,sizeof(ULONG)
289 ))
290 {
291 vError = ::WinGetLastError(vHab);
292 sError = wxPMErrorToStr(vError);
293 wxLogLastError(sError.c_str());
294 return FALSE;
295 }
296
297 if (!::WinRegisterClass( vHab
298 ,wxMDIFrameClassName
299 ,wxWndProc
300 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
301 ,sizeof(ULONG)
302 ))
303 {
304 vError = ::WinGetLastError(vHab);
305 sError = wxPMErrorToStr(vError);
306 wxLogLastError(sError.c_str());
307 return FALSE;
308 }
309
310 if (!::WinRegisterClass( vHab
311 ,wxMDIFrameClassNameNoRedraw
312 ,wxWndProc
313 ,0
314 ,sizeof(ULONG)
315 ))
316 {
317 vError = ::WinGetLastError(vHab);
318 sError = wxPMErrorToStr(vError);
319 wxLogLastError(sError.c_str());
320 return FALSE;
321 }
322
323 if (!::WinRegisterClass( vHab
324 ,wxMDIChildFrameClassName
325 ,wxWndProc
326 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
327 ,sizeof(ULONG)
328 ))
329 {
330 vError = ::WinGetLastError(vHab);
331 sError = wxPMErrorToStr(vError);
332 wxLogLastError(sError.c_str());
333 return FALSE;
334 }
335
336 if (!::WinRegisterClass( vHab
337 ,wxMDIChildFrameClassNameNoRedraw
338 ,wxWndProc
339 ,CS_HITTEST
340 ,sizeof(ULONG)
341 ))
342 {
343 vError = ::WinGetLastError(vHab);
344 sError = wxPMErrorToStr(vError);
345 wxLogLastError(sError.c_str());
346 return FALSE;
347 }
348
349 if (!::WinRegisterClass( vHab
350 ,wxPanelClassName
351 ,wxWndProc
352 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
353 ,sizeof(ULONG)
354 ))
355 {
356 vError = ::WinGetLastError(vHab);
357 sError = wxPMErrorToStr(vError);
358 wxLogLastError(sError.c_str());
359 return FALSE;
360 }
361
362 if (!::WinRegisterClass( vHab
363 ,wxCanvasClassName
364 ,wxWndProc
365 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
366 ,sizeof(ULONG)
367 ))
368 {
369 vError = ::WinGetLastError(vHab);
370 sError = wxPMErrorToStr(vError);
371 wxLogLastError(sError.c_str());
372 return FALSE;
373 }
374 if (!::WinRegisterClass( vHab
375 ,wxCanvasClassNameNR
376 ,wxWndProc
377 ,CS_HITTEST | CS_SYNCPAINT
378 ,sizeof(ULONG)
379 ))
380 {
381 vError = ::WinGetLastError(vHab);
382 sError = wxPMErrorToStr(vError);
383 wxLogLastError(sError.c_str());
384 return FALSE;
385 }
386 return TRUE;
387 } // end of wxApp::RegisterWindowClasses
388
389 //
390 // Cleans up any wxWidgets internal structures left lying around
391 //
392 void wxApp::CleanUp()
393 {
394 delete[] wxBuffer;
395 wxBuffer = NULL;
396
397 //
398 // PM-SPECIFIC CLEANUP
399 //
400
401 // wxSetKeyboardHook(FALSE);
402
403 if (wxSTD_FRAME_ICON)
404 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
405 if (wxSTD_MDICHILDFRAME_ICON)
406 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
407 if (wxSTD_MDIPARENTFRAME_ICON)
408 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
409
410 if (wxDEFAULT_FRAME_ICON)
411 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
412 if (wxDEFAULT_MDICHILDFRAME_ICON)
413 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
414 if (wxDEFAULT_MDIPARENTFRAME_ICON)
415 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
416
417 if ( wxDisableButtonBrush )
418 {
419 // TODO: ::DeleteObject( wxDisableButtonBrush );
420 }
421
422 if (wxWinHandleList)
423 delete wxWinHandleList;
424
425 // Delete Message queue
426 if (wxTheApp->m_hMq)
427 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
428
429 wxAppBase::CleanUp();
430 } // end of wxApp::CleanUp
431
432 bool wxApp::OnInitGui()
433 {
434 ERRORID vError;
435 wxString sError;
436
437 if (!wxAppBase::OnInitGui())
438 return FALSE;
439
440 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
441 if (!m_hMq)
442 {
443 vError = ::WinGetLastError(vHabmain);
444 sError = wxPMErrorToStr(vError);
445 wxLogDebug(sError);
446 return FALSE;
447 }
448
449 return TRUE;
450 } // end of wxApp::OnInitGui
451
452 wxApp::wxApp()
453 {
454 argc = 0;
455 argv = NULL;
456 m_nPrintMode = wxPRINT_WINDOWS;
457 m_hMq = 0;
458 m_maxSocketHandles = 0;
459 m_maxSocketNr = 0;
460 m_sockCallbackInfo = 0;
461 } // end of wxApp::wxApp
462
463 wxApp::~wxApp()
464 {
465 //
466 // Delete command-line args
467 //
468 #if wxUSE_UNICODE
469 int i;
470
471 for (i = 0; i < argc; i++)
472 {
473 delete[] argv[i];
474 }
475 delete[] argv;
476 #endif
477 } // end of wxApp::~wxApp
478
479 bool gbInOnIdle = FALSE;
480
481 void wxApp::OnIdle(
482 wxIdleEvent& rEvent
483 )
484 {
485
486 //
487 // Avoid recursion (via ProcessEvent default case)
488 //
489 if (gbInOnIdle)
490 return;
491
492 gbInOnIdle = TRUE;
493
494 wxAppBase::OnIdle(rEvent);
495
496 #if wxUSE_DC_CACHEING
497 // automated DC cache management: clear the cached DCs and bitmap
498 // if it's likely that the app has finished with them, that is, we
499 // get an idle event and we're not dragging anything.
500 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
501 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
502 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
503 wxDC::ClearCache();
504 #endif // wxUSE_DC_CACHEING
505
506 gbInOnIdle = FALSE;
507 } // end of wxApp::OnIdle
508
509 void wxApp::OnEndSession(
510 wxCloseEvent& WXUNUSED(rEvent))
511 {
512 if (GetTopWindow())
513 GetTopWindow()->Close(TRUE);
514 } // end of wxApp::OnEndSession
515
516 //
517 // Default behaviour: close the application with prompts. The
518 // user can veto the close, and therefore the end session.
519 //
520 void wxApp::OnQueryEndSession(
521 wxCloseEvent& rEvent
522 )
523 {
524 if (GetTopWindow())
525 {
526 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
527 rEvent.Veto(TRUE);
528 }
529 } // end of wxApp::OnQueryEndSession
530
531 //
532 // Yield to incoming messages
533 //
534 bool wxApp::Yield(bool onlyIfNeeded)
535 {
536 static bool s_inYield = FALSE;
537
538 if ( s_inYield )
539 {
540 if ( !onlyIfNeeded )
541 {
542 wxFAIL_MSG( _T("wxYield() called recursively") );
543 }
544
545 return FALSE;
546 }
547
548 HAB vHab = 0;
549 QMSG vMsg;
550
551 //
552 // Disable log flushing from here because a call to wxYield() shouldn't
553 // normally result in message boxes popping up &c
554 //
555 wxLog::Suspend();
556
557 s_inYield = TRUE;
558
559 //
560 // We want to go back to the main message loop
561 // if we see a WM_QUIT. (?)
562 //
563 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
564 {
565 #if wxUSE_THREADS
566 wxMutexGuiLeaveOrEnter();
567 #endif // wxUSE_THREADS
568 if (!wxTheApp->Dispatch())
569 break;
570 }
571 //
572 // If they are pending events, we must process them.
573 //
574 if (wxTheApp)
575 wxTheApp->ProcessPendingEvents();
576
577 HandleSockets();
578 //
579 // Let the logs be flashed again
580 //
581 wxLog::Resume();
582 s_inYield = FALSE;
583 return TRUE;
584 } // end of wxYield
585
586 int wxApp::AddSocketHandler(int handle, int mask,
587 void (*callback)(void*), void * gsock)
588 {
589 int find;
590 struct GsocketCallbackInfo
591 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
592
593 for (find = 0; find < m_maxSocketHandles; find++)
594 if (CallbackInfo[find].handle == -1)
595 break;
596 if (find == m_maxSocketHandles)
597 {
598 // Allocate new memory
599 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
600 (m_maxSocketHandles+=10)*
601 sizeof(struct GsocketCallbackInfo));
602 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
603 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
604 CallbackInfo[find].handle = -1;
605 find = m_maxSocketHandles - 10;
606 }
607 CallbackInfo[find].proc = callback;
608 CallbackInfo[find].type = mask;
609 CallbackInfo[find].handle = handle;
610 CallbackInfo[find].gsock = gsock;
611 if (mask & wxSockReadMask)
612 FD_SET(handle, &m_readfds);
613 if (mask & wxSockWriteMask)
614 FD_SET(handle, &m_writefds);
615 if (handle >= m_maxSocketNr)
616 m_maxSocketNr = handle + 1;
617 return find;
618 }
619
620 void wxApp::RemoveSocketHandler(int handle)
621 {
622 struct GsocketCallbackInfo
623 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
624 if (handle < m_maxSocketHandles)
625 {
626 if (CallbackInfo[handle].type & wxSockReadMask)
627 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
628 if (CallbackInfo[handle].type & wxSockWriteMask)
629 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
630 CallbackInfo[handle].handle = -1;
631 }
632 }
633
634 //-----------------------------------------------------------------------------
635 // wxWakeUpIdle
636 //-----------------------------------------------------------------------------
637
638 void wxApp::WakeUpIdle()
639 {
640 //
641 // Send the top window a dummy message so idle handler processing will
642 // start up again. Doing it this way ensures that the idle handler
643 // wakes up in the right thread (see also wxWakeUpMainThread() which does
644 // the same for the main app thread only)
645 //
646 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
647
648 if (pTopWindow)
649 {
650 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
651 {
652 //
653 // Should never happen
654 //
655 wxLogLastError("PostMessage(WM_NULL)");
656 }
657 }
658 } // end of wxWakeUpIdle
659
660 HAB wxGetInstance()
661 {
662 return vHabmain;
663 }
664
665 void wxSetInstance(
666 HAB vHab
667 )
668 {
669 vHabmain = vHab;
670 }
671