]> git.saurik.com Git - wxWidgets.git/blob - src/os2/app.cpp
Deallocate wxThreadSpecificInfo when wxThread ends.
[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 // Copyright: (c) David Webster
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #include "wx/app.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/dynarray.h"
18 #include "wx/frame.h"
19 #include "wx/utils.h"
20 #include "wx/gdicmn.h"
21 #include "wx/pen.h"
22 #include "wx/brush.h"
23 #include "wx/cursor.h"
24 #include "wx/icon.h"
25 #include "wx/palette.h"
26 #include "wx/dc.h"
27 #include "wx/dialog.h"
28 #include "wx/msgdlg.h"
29 #include "wx/intl.h"
30 #include "wx/crt.h"
31 #include "wx/log.h"
32 #include "wx/module.h"
33 #endif
34
35 #include "wx/stdpaths.h"
36 #include "wx/filename.h"
37 #include "wx/evtloop.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 WXDLLEXPORT_DATA(wxChar*) wxBuffer;
85 extern wxCursor* g_globalCursor;
86
87 HAB vHabmain = NULLHANDLE;
88
89
90 HICON wxSTD_FRAME_ICON = (HICON) NULL;
91 HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
92 HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
93
94 HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
95 HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
96 HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
97
98 HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
99
100 MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
101 MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
102
103 // ===========================================================================
104 // implementation
105 // ===========================================================================
106
107 // ---------------------------------------------------------------------------
108 // helper struct and functions for socket handling
109 // ---------------------------------------------------------------------------
110
111 struct GsocketCallbackInfo{
112 void (*proc)(void *);
113 int type;
114 int handle;
115 void* gsock;
116 };
117
118 // These defines are used here and in gsockpm.cpp
119 #define wxSockReadMask 0x01
120 #define wxSockWriteMask 0x02
121
122 void wxApp::HandleSockets()
123 {
124 bool pendingEvent = false;
125
126 // Check whether it's time for Gsocket operation
127 if (m_maxSocketHandles > 0 && m_maxSocketNr > 0)
128 {
129 fd_set readfds = m_readfds;
130 fd_set writefds = m_writefds;
131 struct timeval timeout;
132 int i;
133 struct GsocketCallbackInfo
134 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
135 timeout.tv_sec = 0;
136 timeout.tv_usec = 0;
137 if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0)
138 {
139 for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle;
140 (i < m_maxSocketNr - 1) ? i++ : (i = 0))
141 {
142 if (FD_ISSET(i, &readfds))
143 {
144 int r;
145 for (r = 0; r < m_maxSocketHandles; r++){
146 if(CallbackInfo[r].handle == i &&
147 CallbackInfo[r].type == wxSockReadMask)
148 break;
149 }
150 if (r < m_maxSocketHandles)
151 {
152 CallbackInfo[r].proc(CallbackInfo[r].gsock);
153 pendingEvent = true;
154 }
155 }
156 if (FD_ISSET(i, &writefds))
157 {
158 int r;
159 for (r = 0; r < m_maxSocketHandles; r++)
160 if(CallbackInfo[r].handle == i &&
161 CallbackInfo[r].type == wxSockWriteMask)
162 break;
163 if (r < m_maxSocketHandles)
164 {
165 CallbackInfo[r].proc(CallbackInfo[r].gsock);
166 pendingEvent = true;
167 }
168 }
169 }
170 m_lastUsedHandle = i;
171 }
172 if (pendingEvent)
173 ProcessPendingEvents();
174 }
175 }
176 // ---------------------------------------------------------------------------
177 // wxApp
178 // ---------------------------------------------------------------------------
179
180 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
181
182 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
183 EVT_IDLE(wxApp::OnIdle)
184 EVT_END_SESSION(wxApp::OnEndSession)
185 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
186 END_EVENT_TABLE()
187
188 //
189 // Initialize
190 //
191 bool wxApp::Initialize(int& argc, wxChar **argv)
192 {
193 if ( !wxAppBase::Initialize(argc, argv) )
194 return false;
195
196 #if defined(wxUSE_CONSOLEDEBUG)
197 #if wxUSE_CONSOLEDEBUG
198 /***********************************************/
199 /* Code for using stdout debug */
200 /* To use it you mast link app as "Window" - EK*/
201 /***********************************************/
202 {
203 PPIB pib;
204 PTIB tib;
205
206 printf("In console\n");
207
208 DosGetInfoBlocks(&tib, &pib);
209 /* Try morphing into a PM application. */
210 // if(pib->pib_ultype == 2) /* VIO */
211 pib->pib_ultype = 3;
212 }
213 /**********************************************/
214 /**********************************************/
215 #endif //wxUSE_CONSOLEDEBUG
216 #endif
217
218 //
219 // OS2 has to have an anchorblock
220 //
221 vHabmain = WinInitialize(0);
222 wxFileName GetPrefix(argv[0]);
223 GetPrefix.MakeAbsolute();
224 wxStandardPaths::SetInstallPrefix(GetPrefix.GetPath());
225 if (!vHabmain)
226 {
227 // TODO: at least give some error message here...
228 wxAppBase::CleanUp();
229
230 return false;
231 }
232
233 wxBuffer = new wxChar[1500]; // FIXME; why?
234
235 // Some people may wish to use this, but
236 // probably it shouldn't be here by default.
237 // wxRedirectIOToConsole();
238
239 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
240
241 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
242 // PLEASE DO NOT ALTER THIS.
243 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
244 extern char wxDummyChar;
245 if (wxDummyChar) wxDummyChar++;
246 #endif
247
248 // wxSetKeyboardHook(TRUE);
249
250 RegisterWindowClasses(vHabmain);
251
252 return true;
253 } // end of wxApp::Initialize
254
255 const char* CANTREGISTERCLASS = " Can't register Class ";
256 // ---------------------------------------------------------------------------
257 // RegisterWindowClasses
258 // ---------------------------------------------------------------------------
259
260 bool wxApp::RegisterWindowClasses( HAB vHab )
261 {
262 ERRORID vError = 0L;
263 wxString sError;
264
265 if (!::WinRegisterClass( vHab
266 ,(PSZ)wxFrameClassName
267 ,wxFrameWndProc
268 ,CS_SIZEREDRAW | CS_SYNCPAINT
269 ,sizeof(ULONG)
270 ))
271 {
272 vError = ::WinGetLastError(vHab);
273 sError = wxPMErrorToStr(vError);
274 wxLogLastError(sError.c_str());
275 return false;
276 }
277
278 if (!::WinRegisterClass( vHab
279 ,(PSZ)wxFrameClassNameNoRedraw
280 ,wxWndProc
281 ,0
282 ,sizeof(ULONG)
283 ))
284 {
285 vError = ::WinGetLastError(vHab);
286 sError = wxPMErrorToStr(vError);
287 wxLogLastError(sError.c_str());
288 return false;
289 }
290
291 if (!::WinRegisterClass( vHab
292 ,(PSZ)wxMDIFrameClassName
293 ,wxWndProc
294 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
295 ,sizeof(ULONG)
296 ))
297 {
298 vError = ::WinGetLastError(vHab);
299 sError = wxPMErrorToStr(vError);
300 wxLogLastError(sError.c_str());
301 return false;
302 }
303
304 if (!::WinRegisterClass( vHab
305 ,(PSZ)wxMDIFrameClassNameNoRedraw
306 ,wxWndProc
307 ,0
308 ,sizeof(ULONG)
309 ))
310 {
311 vError = ::WinGetLastError(vHab);
312 sError = wxPMErrorToStr(vError);
313 wxLogLastError(sError.c_str());
314 return false;
315 }
316
317 if (!::WinRegisterClass( vHab
318 ,(PSZ)wxMDIChildFrameClassName
319 ,wxWndProc
320 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
321 ,sizeof(ULONG)
322 ))
323 {
324 vError = ::WinGetLastError(vHab);
325 sError = wxPMErrorToStr(vError);
326 wxLogLastError(sError.c_str());
327 return false;
328 }
329
330 if (!::WinRegisterClass( vHab
331 ,(PSZ)wxMDIChildFrameClassNameNoRedraw
332 ,wxWndProc
333 ,CS_HITTEST
334 ,sizeof(ULONG)
335 ))
336 {
337 vError = ::WinGetLastError(vHab);
338 sError = wxPMErrorToStr(vError);
339 wxLogLastError(sError.c_str());
340 return false;
341 }
342
343 if (!::WinRegisterClass( vHab
344 ,(PSZ)wxPanelClassName
345 ,wxWndProc
346 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
347 ,sizeof(ULONG)
348 ))
349 {
350 vError = ::WinGetLastError(vHab);
351 sError = wxPMErrorToStr(vError);
352 wxLogLastError(sError.c_str());
353 return false;
354 }
355
356 if (!::WinRegisterClass( vHab
357 ,(PSZ)wxCanvasClassName
358 ,wxWndProc
359 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
360 ,sizeof(ULONG)
361 ))
362 {
363 vError = ::WinGetLastError(vHab);
364 sError = wxPMErrorToStr(vError);
365 wxLogLastError(sError.c_str());
366 return false;
367 }
368 if (!::WinRegisterClass( vHab
369 ,(PSZ)wxCanvasClassNameNR
370 ,wxWndProc
371 ,CS_HITTEST | CS_SYNCPAINT
372 ,sizeof(ULONG)
373 ))
374 {
375 vError = ::WinGetLastError(vHab);
376 sError = wxPMErrorToStr(vError);
377 wxLogLastError(sError.c_str());
378 return false;
379 }
380 return true;
381 } // end of wxApp::RegisterWindowClasses
382
383 //
384 // Cleans up any wxWidgets internal structures left lying around
385 //
386 void wxApp::CleanUp()
387 {
388 wxDELETEA(wxBuffer);
389
390 //
391 // PM-SPECIFIC CLEANUP
392 //
393
394 // wxSetKeyboardHook(false);
395
396 if (wxSTD_FRAME_ICON)
397 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
398 if (wxSTD_MDICHILDFRAME_ICON)
399 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
400 if (wxSTD_MDIPARENTFRAME_ICON)
401 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
402
403 if (wxDEFAULT_FRAME_ICON)
404 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
405 if (wxDEFAULT_MDICHILDFRAME_ICON)
406 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
407 if (wxDEFAULT_MDIPARENTFRAME_ICON)
408 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
409
410 if ( wxDisableButtonBrush )
411 {
412 // TODO: ::DeleteObject( wxDisableButtonBrush );
413 }
414
415 wxDELETE(wxWinHandleHash);
416
417 // Delete Message queue
418 if (wxTheApp->m_hMq)
419 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
420
421 wxAppBase::CleanUp();
422 } // end of wxApp::CleanUp
423
424 bool wxApp::OnInitGui()
425 {
426 ERRORID vError;
427 wxString sError;
428
429 if (!wxAppBase::OnInitGui())
430 return false;
431
432 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
433 if (!m_hMq)
434 {
435 vError = ::WinGetLastError(vHabmain);
436 sError = wxPMErrorToStr(vError);
437 wxLogDebug(sError);
438 return false;
439 }
440
441 return true;
442 } // end of wxApp::OnInitGui
443
444 wxApp::wxApp()
445 {
446 m_nPrintMode = wxPRINT_WINDOWS;
447 m_hMq = 0;
448 m_maxSocketHandles = 0;
449 m_maxSocketNr = 0;
450 m_sockCallbackInfo = 0;
451 } // end of wxApp::wxApp
452
453 wxApp::~wxApp()
454 {
455 } // end of wxApp::~wxApp
456
457 bool gbInOnIdle = false;
458
459 void wxApp::OnIdle( wxIdleEvent& WXUNUSED(rEvent) )
460 {
461 //
462 // Avoid recursion (via ProcessEvent default case)
463 //
464 if (gbInOnIdle)
465 return;
466
467 gbInOnIdle = true;
468
469 #if wxUSE_DC_CACHEING
470 // automated DC cache management: clear the cached DCs and bitmap
471 // if it's likely that the app has finished with them, that is, we
472 // get an idle event and we're not dragging anything.
473 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
474 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
475 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
476 wxDC::ClearCache();
477 #endif // wxUSE_DC_CACHEING
478
479 gbInOnIdle = false;
480 } // end of wxApp::OnIdle
481
482 void wxApp::OnEndSession(
483 wxCloseEvent& WXUNUSED(rEvent))
484 {
485 if (GetTopWindow())
486 GetTopWindow()->Close(true);
487 } // end of wxApp::OnEndSession
488
489 //
490 // Default behaviour: close the application with prompts. The
491 // user can veto the close, and therefore the end session.
492 //
493 void wxApp::OnQueryEndSession( wxCloseEvent& rEvent )
494 {
495 if (GetTopWindow())
496 {
497 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
498 rEvent.Veto(true);
499 }
500 } // end of wxApp::OnQueryEndSession
501
502 int wxApp::AddSocketHandler(int handle, int mask,
503 void (*callback)(void*), void * gsock)
504 {
505 int find;
506 struct GsocketCallbackInfo
507 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
508
509 for (find = 0; find < m_maxSocketHandles; find++)
510 if (CallbackInfo[find].handle == -1)
511 break;
512 if (find == m_maxSocketHandles)
513 {
514 // Allocate new memory
515 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
516 (m_maxSocketHandles+=10)*
517 sizeof(struct GsocketCallbackInfo));
518 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
519 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
520 CallbackInfo[find].handle = -1;
521 find = m_maxSocketHandles - 10;
522 }
523 CallbackInfo[find].proc = callback;
524 CallbackInfo[find].type = mask;
525 CallbackInfo[find].handle = handle;
526 CallbackInfo[find].gsock = gsock;
527 if (mask & wxSockReadMask)
528 FD_SET(handle, &m_readfds);
529 if (mask & wxSockWriteMask)
530 FD_SET(handle, &m_writefds);
531 if (handle >= m_maxSocketNr)
532 m_maxSocketNr = handle + 1;
533 return find;
534 }
535
536 void wxApp::RemoveSocketHandler(int handle)
537 {
538 struct GsocketCallbackInfo
539 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
540 if (handle < m_maxSocketHandles)
541 {
542 if (CallbackInfo[handle].type & wxSockReadMask)
543 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
544 if (CallbackInfo[handle].type & wxSockWriteMask)
545 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
546 CallbackInfo[handle].handle = -1;
547 }
548 }
549
550 //-----------------------------------------------------------------------------
551 // wxWakeUpIdle
552 //-----------------------------------------------------------------------------
553
554 void wxApp::WakeUpIdle()
555 {
556 //
557 // Send the top window a dummy message so idle handler processing will
558 // start up again. Doing it this way ensures that the idle handler
559 // wakes up in the right thread (see also wxWakeUpMainThread() which does
560 // the same for the main app thread only)
561 //
562 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
563
564 if (pTopWindow)
565 {
566 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
567 {
568 //
569 // Should never happen
570 //
571 wxLogLastError(wxT("PostMessage(WM_NULL)"));
572 }
573 }
574 } // end of wxWakeUpIdle
575
576 HAB wxGetInstance()
577 {
578 return vHabmain;
579 }
580
581 void wxSetInstance( HAB vHab )
582 {
583 vHabmain = vHab;
584 }