]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/app.cpp
Fix for crash when opening empty node
[wxWidgets.git] / src / os2 / app.cpp
... / ...
CommitLineData
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
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)
62extern "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
84WXDLLEXPORT_DATA(wxChar*) wxBuffer;
85extern wxCursor* g_globalCursor;
86
87HAB vHabmain = NULLHANDLE;
88
89
90HICON wxSTD_FRAME_ICON = (HICON) NULL;
91HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
92HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
93
94HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
95HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
96HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
97
98HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
99
100MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
101MRESULT 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
111struct 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
122void 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//
191bool 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#ifdef __WXDEBUG__
238 // wxRedirectIOToConsole();
239#endif
240
241 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
242
243 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
244 // PLEASE DO NOT ALTER THIS.
245#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
246 extern char wxDummyChar;
247 if (wxDummyChar) wxDummyChar++;
248#endif
249
250 // wxSetKeyboardHook(TRUE);
251
252 RegisterWindowClasses(vHabmain);
253
254 return true;
255} // end of wxApp::Initialize
256
257const char* CANTREGISTERCLASS = " Can't register Class ";
258// ---------------------------------------------------------------------------
259// RegisterWindowClasses
260// ---------------------------------------------------------------------------
261
262bool wxApp::RegisterWindowClasses( HAB vHab )
263{
264 ERRORID vError = 0L;
265 wxString sError;
266
267 if (!::WinRegisterClass( vHab
268 ,(PSZ)wxFrameClassName
269 ,wxFrameWndProc
270 ,CS_SIZEREDRAW | CS_SYNCPAINT
271 ,sizeof(ULONG)
272 ))
273 {
274 vError = ::WinGetLastError(vHab);
275 sError = wxPMErrorToStr(vError);
276 wxLogLastError(sError.c_str());
277 return false;
278 }
279
280 if (!::WinRegisterClass( vHab
281 ,(PSZ)wxFrameClassNameNoRedraw
282 ,wxWndProc
283 ,0
284 ,sizeof(ULONG)
285 ))
286 {
287 vError = ::WinGetLastError(vHab);
288 sError = wxPMErrorToStr(vError);
289 wxLogLastError(sError.c_str());
290 return false;
291 }
292
293 if (!::WinRegisterClass( vHab
294 ,(PSZ)wxMDIFrameClassName
295 ,wxWndProc
296 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
297 ,sizeof(ULONG)
298 ))
299 {
300 vError = ::WinGetLastError(vHab);
301 sError = wxPMErrorToStr(vError);
302 wxLogLastError(sError.c_str());
303 return false;
304 }
305
306 if (!::WinRegisterClass( vHab
307 ,(PSZ)wxMDIFrameClassNameNoRedraw
308 ,wxWndProc
309 ,0
310 ,sizeof(ULONG)
311 ))
312 {
313 vError = ::WinGetLastError(vHab);
314 sError = wxPMErrorToStr(vError);
315 wxLogLastError(sError.c_str());
316 return false;
317 }
318
319 if (!::WinRegisterClass( vHab
320 ,(PSZ)wxMDIChildFrameClassName
321 ,wxWndProc
322 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
323 ,sizeof(ULONG)
324 ))
325 {
326 vError = ::WinGetLastError(vHab);
327 sError = wxPMErrorToStr(vError);
328 wxLogLastError(sError.c_str());
329 return false;
330 }
331
332 if (!::WinRegisterClass( vHab
333 ,(PSZ)wxMDIChildFrameClassNameNoRedraw
334 ,wxWndProc
335 ,CS_HITTEST
336 ,sizeof(ULONG)
337 ))
338 {
339 vError = ::WinGetLastError(vHab);
340 sError = wxPMErrorToStr(vError);
341 wxLogLastError(sError.c_str());
342 return false;
343 }
344
345 if (!::WinRegisterClass( vHab
346 ,(PSZ)wxPanelClassName
347 ,wxWndProc
348 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
349 ,sizeof(ULONG)
350 ))
351 {
352 vError = ::WinGetLastError(vHab);
353 sError = wxPMErrorToStr(vError);
354 wxLogLastError(sError.c_str());
355 return false;
356 }
357
358 if (!::WinRegisterClass( vHab
359 ,(PSZ)wxCanvasClassName
360 ,wxWndProc
361 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
362 ,sizeof(ULONG)
363 ))
364 {
365 vError = ::WinGetLastError(vHab);
366 sError = wxPMErrorToStr(vError);
367 wxLogLastError(sError.c_str());
368 return false;
369 }
370 if (!::WinRegisterClass( vHab
371 ,(PSZ)wxCanvasClassNameNR
372 ,wxWndProc
373 ,CS_HITTEST | CS_SYNCPAINT
374 ,sizeof(ULONG)
375 ))
376 {
377 vError = ::WinGetLastError(vHab);
378 sError = wxPMErrorToStr(vError);
379 wxLogLastError(sError.c_str());
380 return false;
381 }
382 return true;
383} // end of wxApp::RegisterWindowClasses
384
385//
386// Cleans up any wxWidgets internal structures left lying around
387//
388void wxApp::CleanUp()
389{
390 delete[] wxBuffer;
391 wxBuffer = NULL;
392
393 //
394 // PM-SPECIFIC CLEANUP
395 //
396
397 // wxSetKeyboardHook(false);
398
399 if (wxSTD_FRAME_ICON)
400 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
401 if (wxSTD_MDICHILDFRAME_ICON)
402 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
403 if (wxSTD_MDIPARENTFRAME_ICON)
404 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
405
406 if (wxDEFAULT_FRAME_ICON)
407 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
408 if (wxDEFAULT_MDICHILDFRAME_ICON)
409 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
410 if (wxDEFAULT_MDIPARENTFRAME_ICON)
411 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
412
413 if ( wxDisableButtonBrush )
414 {
415// TODO: ::DeleteObject( wxDisableButtonBrush );
416 }
417
418 delete wxWinHandleHash;
419 wxWinHandleHash = NULL;
420
421 // Delete Message queue
422 if (wxTheApp->m_hMq)
423 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
424
425 wxAppBase::CleanUp();
426} // end of wxApp::CleanUp
427
428bool wxApp::OnInitGui()
429{
430 ERRORID vError;
431 wxString sError;
432
433 if (!wxAppBase::OnInitGui())
434 return false;
435
436 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
437 if (!m_hMq)
438 {
439 vError = ::WinGetLastError(vHabmain);
440 sError = wxPMErrorToStr(vError);
441 wxLogDebug(sError);
442 return false;
443 }
444
445 return true;
446} // end of wxApp::OnInitGui
447
448wxApp::wxApp()
449{
450 argc = 0;
451 argv = NULL;
452 m_nPrintMode = wxPRINT_WINDOWS;
453 m_hMq = 0;
454 m_maxSocketHandles = 0;
455 m_maxSocketNr = 0;
456 m_sockCallbackInfo = 0;
457} // end of wxApp::wxApp
458
459wxApp::~wxApp()
460{
461 //
462 // Delete command-line args
463 //
464#if wxUSE_UNICODE
465 int i;
466
467 for (i = 0; i < argc; i++)
468 {
469 delete[] argv[i];
470 }
471 delete[] argv;
472#endif
473} // end of wxApp::~wxApp
474
475bool gbInOnIdle = false;
476
477void wxApp::OnIdle( wxIdleEvent& rEvent )
478{
479 //
480 // Avoid recursion (via ProcessEvent default case)
481 //
482 if (gbInOnIdle)
483 return;
484
485 gbInOnIdle = true;
486
487#if wxUSE_DC_CACHEING
488 // automated DC cache management: clear the cached DCs and bitmap
489 // if it's likely that the app has finished with them, that is, we
490 // get an idle event and we're not dragging anything.
491 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
492 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
493 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
494 wxDC::ClearCache();
495#endif // wxUSE_DC_CACHEING
496
497 gbInOnIdle = false;
498} // end of wxApp::OnIdle
499
500void wxApp::OnEndSession(
501 wxCloseEvent& WXUNUSED(rEvent))
502{
503 if (GetTopWindow())
504 GetTopWindow()->Close(true);
505} // end of wxApp::OnEndSession
506
507//
508// Default behaviour: close the application with prompts. The
509// user can veto the close, and therefore the end session.
510//
511void wxApp::OnQueryEndSession( wxCloseEvent& rEvent )
512{
513 if (GetTopWindow())
514 {
515 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
516 rEvent.Veto(true);
517 }
518} // end of wxApp::OnQueryEndSession
519
520//
521// Yield to incoming messages
522//
523bool wxApp::Yield(bool onlyIfNeeded)
524{
525 static bool s_inYield = false;
526
527 if ( s_inYield )
528 {
529 if ( !onlyIfNeeded )
530 {
531 wxFAIL_MSG( _T("wxYield() called recursively") );
532 }
533
534 return false;
535 }
536
537 HAB vHab = 0;
538 QMSG vMsg;
539
540 //
541 // Disable log flushing from here because a call to wxYield() shouldn't
542 // normally result in message boxes popping up &c
543 //
544 wxLog::Suspend();
545
546 s_inYield = true;
547
548 //
549 // We want to go back to the main message loop
550 // if we see a WM_QUIT. (?)
551 //
552 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
553 {
554#if wxUSE_THREADS
555 wxMutexGuiLeaveOrEnter();
556#endif // wxUSE_THREADS
557 if (!wxTheApp->Dispatch())
558 break;
559 }
560 //
561 // If they are pending events, we must process them.
562 //
563 if (wxTheApp)
564 wxTheApp->ProcessPendingEvents();
565
566 HandleSockets();
567 //
568 // Let the logs be flashed again
569 //
570 wxLog::Resume();
571 s_inYield = false;
572 return true;
573} // end of wxYield
574
575int wxApp::AddSocketHandler(int handle, int mask,
576 void (*callback)(void*), void * gsock)
577{
578 int find;
579 struct GsocketCallbackInfo
580 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
581
582 for (find = 0; find < m_maxSocketHandles; find++)
583 if (CallbackInfo[find].handle == -1)
584 break;
585 if (find == m_maxSocketHandles)
586 {
587 // Allocate new memory
588 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
589 (m_maxSocketHandles+=10)*
590 sizeof(struct GsocketCallbackInfo));
591 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
592 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
593 CallbackInfo[find].handle = -1;
594 find = m_maxSocketHandles - 10;
595 }
596 CallbackInfo[find].proc = callback;
597 CallbackInfo[find].type = mask;
598 CallbackInfo[find].handle = handle;
599 CallbackInfo[find].gsock = gsock;
600 if (mask & wxSockReadMask)
601 FD_SET(handle, &m_readfds);
602 if (mask & wxSockWriteMask)
603 FD_SET(handle, &m_writefds);
604 if (handle >= m_maxSocketNr)
605 m_maxSocketNr = handle + 1;
606 return find;
607}
608
609void wxApp::RemoveSocketHandler(int handle)
610{
611 struct GsocketCallbackInfo
612 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
613 if (handle < m_maxSocketHandles)
614 {
615 if (CallbackInfo[handle].type & wxSockReadMask)
616 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
617 if (CallbackInfo[handle].type & wxSockWriteMask)
618 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
619 CallbackInfo[handle].handle = -1;
620 }
621}
622
623//-----------------------------------------------------------------------------
624// wxWakeUpIdle
625//-----------------------------------------------------------------------------
626
627void wxApp::WakeUpIdle()
628{
629 //
630 // Send the top window a dummy message so idle handler processing will
631 // start up again. Doing it this way ensures that the idle handler
632 // wakes up in the right thread (see also wxWakeUpMainThread() which does
633 // the same for the main app thread only)
634 //
635 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
636
637 if (pTopWindow)
638 {
639 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
640 {
641 //
642 // Should never happen
643 //
644 wxLogLastError(wxT("PostMessage(WM_NULL)"));
645 }
646 }
647} // end of wxWakeUpIdle
648
649HAB wxGetInstance()
650{
651 return vHabmain;
652}
653
654void wxSetInstance( HAB vHab )
655{
656 vHabmain = vHab;
657}