]> git.saurik.com Git - wxWidgets.git/blob - src/os2/app.cpp
Better compatibility with old files when creating an image cache
[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/crt.h"
32 #include "wx/log.h"
33 #include "wx/module.h"
34 #endif
35
36 #include "wx/stdpaths.h"
37 #include "wx/filename.h"
38 #include "wx/evtloop.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 WXDLLEXPORT_DATA(wxChar*) wxBuffer;
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 // wxRedirectIOToConsole();
239
240 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
241
242 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
243 // PLEASE DO NOT ALTER THIS.
244 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
245 extern char wxDummyChar;
246 if (wxDummyChar) wxDummyChar++;
247 #endif
248
249 // wxSetKeyboardHook(TRUE);
250
251 RegisterWindowClasses(vHabmain);
252
253 return true;
254 } // end of wxApp::Initialize
255
256 const char* CANTREGISTERCLASS = " Can't register Class ";
257 // ---------------------------------------------------------------------------
258 // RegisterWindowClasses
259 // ---------------------------------------------------------------------------
260
261 bool wxApp::RegisterWindowClasses( HAB vHab )
262 {
263 ERRORID vError = 0L;
264 wxString sError;
265
266 if (!::WinRegisterClass( vHab
267 ,(PSZ)wxFrameClassName
268 ,wxFrameWndProc
269 ,CS_SIZEREDRAW | CS_SYNCPAINT
270 ,sizeof(ULONG)
271 ))
272 {
273 vError = ::WinGetLastError(vHab);
274 sError = wxPMErrorToStr(vError);
275 wxLogLastError(sError.c_str());
276 return false;
277 }
278
279 if (!::WinRegisterClass( vHab
280 ,(PSZ)wxFrameClassNameNoRedraw
281 ,wxWndProc
282 ,0
283 ,sizeof(ULONG)
284 ))
285 {
286 vError = ::WinGetLastError(vHab);
287 sError = wxPMErrorToStr(vError);
288 wxLogLastError(sError.c_str());
289 return false;
290 }
291
292 if (!::WinRegisterClass( vHab
293 ,(PSZ)wxMDIFrameClassName
294 ,wxWndProc
295 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
296 ,sizeof(ULONG)
297 ))
298 {
299 vError = ::WinGetLastError(vHab);
300 sError = wxPMErrorToStr(vError);
301 wxLogLastError(sError.c_str());
302 return false;
303 }
304
305 if (!::WinRegisterClass( vHab
306 ,(PSZ)wxMDIFrameClassNameNoRedraw
307 ,wxWndProc
308 ,0
309 ,sizeof(ULONG)
310 ))
311 {
312 vError = ::WinGetLastError(vHab);
313 sError = wxPMErrorToStr(vError);
314 wxLogLastError(sError.c_str());
315 return false;
316 }
317
318 if (!::WinRegisterClass( vHab
319 ,(PSZ)wxMDIChildFrameClassName
320 ,wxWndProc
321 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
322 ,sizeof(ULONG)
323 ))
324 {
325 vError = ::WinGetLastError(vHab);
326 sError = wxPMErrorToStr(vError);
327 wxLogLastError(sError.c_str());
328 return false;
329 }
330
331 if (!::WinRegisterClass( vHab
332 ,(PSZ)wxMDIChildFrameClassNameNoRedraw
333 ,wxWndProc
334 ,CS_HITTEST
335 ,sizeof(ULONG)
336 ))
337 {
338 vError = ::WinGetLastError(vHab);
339 sError = wxPMErrorToStr(vError);
340 wxLogLastError(sError.c_str());
341 return false;
342 }
343
344 if (!::WinRegisterClass( vHab
345 ,(PSZ)wxPanelClassName
346 ,wxWndProc
347 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
348 ,sizeof(ULONG)
349 ))
350 {
351 vError = ::WinGetLastError(vHab);
352 sError = wxPMErrorToStr(vError);
353 wxLogLastError(sError.c_str());
354 return false;
355 }
356
357 if (!::WinRegisterClass( vHab
358 ,(PSZ)wxCanvasClassName
359 ,wxWndProc
360 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
361 ,sizeof(ULONG)
362 ))
363 {
364 vError = ::WinGetLastError(vHab);
365 sError = wxPMErrorToStr(vError);
366 wxLogLastError(sError.c_str());
367 return false;
368 }
369 if (!::WinRegisterClass( vHab
370 ,(PSZ)wxCanvasClassNameNR
371 ,wxWndProc
372 ,CS_HITTEST | CS_SYNCPAINT
373 ,sizeof(ULONG)
374 ))
375 {
376 vError = ::WinGetLastError(vHab);
377 sError = wxPMErrorToStr(vError);
378 wxLogLastError(sError.c_str());
379 return false;
380 }
381 return true;
382 } // end of wxApp::RegisterWindowClasses
383
384 //
385 // Cleans up any wxWidgets internal structures left lying around
386 //
387 void wxApp::CleanUp()
388 {
389 wxDELETEA(wxBuffer);
390
391 //
392 // PM-SPECIFIC CLEANUP
393 //
394
395 // wxSetKeyboardHook(false);
396
397 if (wxSTD_FRAME_ICON)
398 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
399 if (wxSTD_MDICHILDFRAME_ICON)
400 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
401 if (wxSTD_MDIPARENTFRAME_ICON)
402 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
403
404 if (wxDEFAULT_FRAME_ICON)
405 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
406 if (wxDEFAULT_MDICHILDFRAME_ICON)
407 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
408 if (wxDEFAULT_MDIPARENTFRAME_ICON)
409 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
410
411 if ( wxDisableButtonBrush )
412 {
413 // TODO: ::DeleteObject( wxDisableButtonBrush );
414 }
415
416 wxDELETE(wxWinHandleHash);
417
418 // Delete Message queue
419 if (wxTheApp->m_hMq)
420 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
421
422 wxAppBase::CleanUp();
423 } // end of wxApp::CleanUp
424
425 bool wxApp::OnInitGui()
426 {
427 ERRORID vError;
428 wxString sError;
429
430 if (!wxAppBase::OnInitGui())
431 return false;
432
433 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
434 if (!m_hMq)
435 {
436 vError = ::WinGetLastError(vHabmain);
437 sError = wxPMErrorToStr(vError);
438 wxLogDebug(sError);
439 return false;
440 }
441
442 return true;
443 } // end of wxApp::OnInitGui
444
445 wxApp::wxApp()
446 {
447 m_nPrintMode = wxPRINT_WINDOWS;
448 m_hMq = 0;
449 m_maxSocketHandles = 0;
450 m_maxSocketNr = 0;
451 m_sockCallbackInfo = 0;
452 } // end of wxApp::wxApp
453
454 wxApp::~wxApp()
455 {
456 } // end of wxApp::~wxApp
457
458 bool gbInOnIdle = false;
459
460 void wxApp::OnIdle( wxIdleEvent& WXUNUSED(rEvent) )
461 {
462 //
463 // Avoid recursion (via ProcessEvent default case)
464 //
465 if (gbInOnIdle)
466 return;
467
468 gbInOnIdle = true;
469
470 #if wxUSE_DC_CACHEING
471 // automated DC cache management: clear the cached DCs and bitmap
472 // if it's likely that the app has finished with them, that is, we
473 // get an idle event and we're not dragging anything.
474 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
475 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
476 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
477 wxDC::ClearCache();
478 #endif // wxUSE_DC_CACHEING
479
480 gbInOnIdle = false;
481 } // end of wxApp::OnIdle
482
483 void wxApp::OnEndSession(
484 wxCloseEvent& WXUNUSED(rEvent))
485 {
486 if (GetTopWindow())
487 GetTopWindow()->Close(true);
488 } // end of wxApp::OnEndSession
489
490 //
491 // Default behaviour: close the application with prompts. The
492 // user can veto the close, and therefore the end session.
493 //
494 void wxApp::OnQueryEndSession( wxCloseEvent& rEvent )
495 {
496 if (GetTopWindow())
497 {
498 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
499 rEvent.Veto(true);
500 }
501 } // end of wxApp::OnQueryEndSession
502
503 int wxApp::AddSocketHandler(int handle, int mask,
504 void (*callback)(void*), void * gsock)
505 {
506 int find;
507 struct GsocketCallbackInfo
508 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
509
510 for (find = 0; find < m_maxSocketHandles; find++)
511 if (CallbackInfo[find].handle == -1)
512 break;
513 if (find == m_maxSocketHandles)
514 {
515 // Allocate new memory
516 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
517 (m_maxSocketHandles+=10)*
518 sizeof(struct GsocketCallbackInfo));
519 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
520 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
521 CallbackInfo[find].handle = -1;
522 find = m_maxSocketHandles - 10;
523 }
524 CallbackInfo[find].proc = callback;
525 CallbackInfo[find].type = mask;
526 CallbackInfo[find].handle = handle;
527 CallbackInfo[find].gsock = gsock;
528 if (mask & wxSockReadMask)
529 FD_SET(handle, &m_readfds);
530 if (mask & wxSockWriteMask)
531 FD_SET(handle, &m_writefds);
532 if (handle >= m_maxSocketNr)
533 m_maxSocketNr = handle + 1;
534 return find;
535 }
536
537 void wxApp::RemoveSocketHandler(int handle)
538 {
539 struct GsocketCallbackInfo
540 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
541 if (handle < m_maxSocketHandles)
542 {
543 if (CallbackInfo[handle].type & wxSockReadMask)
544 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
545 if (CallbackInfo[handle].type & wxSockWriteMask)
546 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
547 CallbackInfo[handle].handle = -1;
548 }
549 }
550
551 //-----------------------------------------------------------------------------
552 // wxWakeUpIdle
553 //-----------------------------------------------------------------------------
554
555 void wxApp::WakeUpIdle()
556 {
557 //
558 // Send the top window a dummy message so idle handler processing will
559 // start up again. Doing it this way ensures that the idle handler
560 // wakes up in the right thread (see also wxWakeUpMainThread() which does
561 // the same for the main app thread only)
562 //
563 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
564
565 if (pTopWindow)
566 {
567 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
568 {
569 //
570 // Should never happen
571 //
572 wxLogLastError(wxT("PostMessage(WM_NULL)"));
573 }
574 }
575 } // end of wxWakeUpIdle
576
577 HAB wxGetInstance()
578 {
579 return vHabmain;
580 }
581
582 void wxSetInstance( HAB vHab )
583 {
584 vHabmain = vHab;
585 }