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