]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
Default wxDateTime objects are now 'invalid',
[wxWidgets.git] / src / os2 / app.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
d88de032 4// Author: David Webster
0e320a79 5// Modified by:
d88de032 6// Created: 10/13/99
0e320a79 7// RCS-ID: $Id$
d88de032
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
d88de032
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/pen.h"
21 #include "wx/brush.h"
22 #include "wx/cursor.h"
23 #include "wx/icon.h"
24 #include "wx/palette.h"
25 #include "wx/dc.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/intl.h"
29 #include "wx/dynarray.h"
cb21bd1b
SN
30 #include "wx/wxchar.h"
31 #include "wx/icon.h"
32 #include "wx/timer.h"
0e320a79
DW
33#endif
34
0e320a79
DW
35#include "wx/log.h"
36#include "wx/module.h"
d88de032
DW
37
38#include "wx/os2/private.h"
39
3958ae62
SN
40#if defined(__VISAGECPP__) && __IBMCPP__ < 400
41#include <machine\endian.h>
42#include <ioctl.h>
43#include <select.h>
44#include <unistd.h>
45#else
46#include <sys\ioctl.h>
47#include <sys\select.h>
48#ifndef __EMX__
49#define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
50int _System bsdselect(int,
51 struct fd_set *,
52 struct fd_set *,
53 struct fd_set *,
54 struct timeval *);
55#endif
56#endif
57
d88de032
DW
58#if wxUSE_THREADS
59 #include "wx/thread.h"
60
9ed0fac8
DW
61 // define the array of QMSG strutures
62 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
d88de032
DW
63
64 #include "wx/arrimpl.cpp"
65
9ed0fac8 66 WX_DEFINE_OBJARRAY(wxMsgArray);
d88de032 67#endif // wxUSE_THREADS
0e320a79
DW
68
69#if wxUSE_WX_RESOURCES
d88de032 70 #include "wx/resource.h"
0e320a79
DW
71#endif
72
8df85a61
DW
73#if wxUSE_TOOLTIPS
74 #include "wx/tooltip.h"
75#endif // wxUSE_TOOLTIPS
76
0e320a79 77#include <string.h>
d88de032
DW
78#include <ctype.h>
79
80// ---------------------------------------------------------------------------
81// global variables
82// ---------------------------------------------------------------------------
83
9ed0fac8 84extern wxChar* wxBuffer;
9ed0fac8
DW
85extern wxList* wxWinHandleList;
86extern wxList WXDLLEXPORT wxPendingDelete;
9ed0fac8 87extern wxCursor* g_globalCursor;
0e320a79 88
8df85a61 89HAB vHabmain = NULLHANDLE;
9ed0fac8
DW
90QMSG svCurrentMsg;
91wxApp* wxTheApp = NULL;
d88de032
DW
92
93// NB: all "NoRedraw" classes must have the same names as the "normal" classes
13a4ea8d 94// with NR suffix - wxWindow::OS2Create() supposes this
9ed0fac8
DW
95wxChar wxFrameClassName[] = wxT("wxFrameClass");
96wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
97wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
98wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
99wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
d88de032 100wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
9ed0fac8
DW
101wxChar wxPanelClassName[] = wxT("wxPanelClass");
102wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
d88de032 103
9ed0fac8
DW
104HICON wxSTD_FRAME_ICON = (HICON) NULL;
105HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
d88de032
DW
106HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
107
9ed0fac8
DW
108HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
109HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
110HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
d88de032
DW
111
112HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
113
51c1d535
DW
114MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
115MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
116
d88de032
DW
117// ===========================================================================
118// implementation
119// ===========================================================================
120
3958ae62
SN
121// ---------------------------------------------------------------------------
122// helper struct and functions for socket handling
123// ---------------------------------------------------------------------------
124
125struct GsocketCallbackInfo{
126 void (*proc)(void *);
127 int type;
128 int handle;
129 void* gsock;
130};
131
132// These defines and wrapper functions are used here and in gsockpm.c
133#define wxSockReadMask 0x01
134#define wxSockWriteMask 0x02
135
136extern "C"
137int wxAppAddSocketHandler(int handle, int mask,
138 void (*callback)(void*), void * gsock)
139{
140 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
141}
142
143extern "C"
144void wxAppRemoveSocketHandler(int handle)
145{
146 wxTheApp->RemoveSocketHandler(handle);
147}
148
149void wxApp::HandleSockets()
150{
151 bool pendingEvent = false;
152
153 // Check whether it's time for Gsocket operation
154 if (m_maxSocketHandles > 0 && m_maxSocketNr > 0)
155 {
156 fd_set readfds = m_readfds;
157 fd_set writefds = m_writefds;
158 struct timeval timeout;
159 int i;
160 struct GsocketCallbackInfo
161 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
162 int r = 0;
163 timeout.tv_sec = 0;
164 timeout.tv_usec = 0;
165 if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0)
166 {
167 for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle; i++)
168 {
169 if (i == m_maxSocketNr)
170 i = 0;
171 if (FD_ISSET(i, &readfds))
172 {
173 int r;
174 for (r = 0; r < m_maxSocketHandles; r++){
175 if(CallbackInfo[r].handle == i &&
176 CallbackInfo[r].type == wxSockReadMask)
177 break;
178 }
179 if (r < m_maxSocketHandles)
180 {
181 CallbackInfo[r].proc(CallbackInfo[r].gsock);
182 pendingEvent = true;
183 wxYield();
184 }
185 }
186 if (FD_ISSET(i, &writefds))
187 {
188 int r;
189 for (r = 0; r < m_maxSocketHandles; r++)
190 if(CallbackInfo[r].handle == i &&
191 CallbackInfo[r].type == wxSockWriteMask)
192 break;
193 if (r < m_maxSocketHandles)
194 {
195 CallbackInfo[r].proc(CallbackInfo[r].gsock);
196 pendingEvent = true;
197 wxYield();
198 }
199 }
200 }
201 m_lastUsedHandle = i;
202 }
203 if (pendingEvent)
204 wxYield();
205 }
206}
d88de032
DW
207// ---------------------------------------------------------------------------
208// wxApp
209// ---------------------------------------------------------------------------
210
d88de032 211 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
0e320a79 212
d88de032
DW
213 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
214 EVT_IDLE(wxApp::OnIdle)
215 EVT_END_SESSION(wxApp::OnEndSession)
216 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
217 END_EVENT_TABLE()
0e320a79 218
8df85a61
DW
219//
220// Initialize
221//
9ed0fac8
DW
222bool wxApp::Initialize(
223 HAB vHab
224)
0e320a79 225{
7e99520b
DW
226#if defined(wxUSE_CONSOLEDEBUG)
227 #if wxUSE_CONSOLEDEBUG
228/***********************************************/
229/* Code for using stdout debug */
230/* To use it you mast link app as "Window" - EK*/
231/***********************************************/
232 {
233 PPIB pib;
234 PTIB tib;
235
236 printf("In console\n");
237
238 DosGetInfoBlocks(&tib, &pib);
239/* Try morphing into a PM application. */
240// if(pib->pib_ultype == 2) /* VIO */
241 pib->pib_ultype = 3;
242 }
243/**********************************************/
244/**********************************************/
245 #endif //wxUSE_CONSOLEDEBUG
246#endif
247
914589c2
DW
248 //
249 // OS2 has to have an anchorblock
250 //
251 vHab = WinInitialize(0);
252
253 if (!vHab)
254 return FALSE;
255 else
256 vHabmain = vHab;
257
d88de032
DW
258 // Some people may wish to use this, but
259 // probably it shouldn't be here by default.
260#ifdef __WXDEBUG__
261 // wxRedirectIOToConsole();
0e320a79
DW
262#endif
263
13a4ea8d 264 wxBuffer = new wxChar[1500]; // FIXME; why?
0e320a79 265
d88de032 266 wxClassInfo::InitializeClasses();
0e320a79 267
8df85a61
DW
268#if wxUSE_THREADS
269 wxPendingEventsLocker = new wxCriticalSection;
270#endif
271
d88de032
DW
272 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
273 wxTheColourDatabase->Initialize();
274
275 wxInitializeStockLists();
276 wxInitializeStockObjects();
0e320a79
DW
277
278#if wxUSE_WX_RESOURCES
d88de032 279 wxInitializeResourceSystem();
0e320a79
DW
280#endif
281
d88de032
DW
282 wxBitmap::InitStandardHandlers();
283
9ed0fac8 284 RegisterWindowClasses(vHab);
d88de032
DW
285 wxWinHandleList = new wxList(wxKEY_INTEGER);
286
287 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
288 // PLEASE DO NOT ALTER THIS.
1b3d5e55 289#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
d88de032
DW
290 extern char wxDummyChar;
291 if (wxDummyChar) wxDummyChar++;
292#endif
293
61243a51 294 // wxSetKeyboardHook(TRUE);
d88de032
DW
295
296 wxModule::RegisterModules();
297 if (!wxModule::InitializeModules())
298 return FALSE;
299 return TRUE;
8df85a61 300} // end of wxApp::Initialize
d88de032 301
7e99520b 302const char* CANTREGISTERCLASS = " Can't register Class ";
d88de032
DW
303// ---------------------------------------------------------------------------
304// RegisterWindowClasses
305// ---------------------------------------------------------------------------
306
9ed0fac8
DW
307bool wxApp::RegisterWindowClasses(
308 HAB vHab
309)
d88de032 310{
3b9e3455 311 APIRET rc;
914589c2
DW
312 ERRORID vError = 0L;
313 wxString sError;
3b9e3455 314
f23208ca
DW
315 if (!::WinRegisterClass( vHab
316 ,wxFrameClassName
51c1d535
DW
317 ,wxFrameWndProc
318 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT | CS_CLIPCHILDREN
a0606634 319 ,sizeof(ULONG)
f23208ca 320 ))
d88de032 321 {
914589c2
DW
322 vError = ::WinGetLastError(vHab);
323 sError = wxPMErrorToStr(vError);
324 wxLogLastError(sError);
d88de032
DW
325 return FALSE;
326 }
327
f23208ca
DW
328 if (!::WinRegisterClass( vHab
329 ,wxFrameClassNameNoRedraw
51c1d535 330 ,wxWndProc
f23208ca 331 ,0
51c1d535 332 ,sizeof(ULONG)
f23208ca 333 ))
d88de032 334 {
914589c2
DW
335 vError = ::WinGetLastError(vHab);
336 sError = wxPMErrorToStr(vError);
337 wxLogLastError(sError);
d88de032
DW
338 return FALSE;
339 }
340
f23208ca
DW
341 if (!::WinRegisterClass( vHab
342 ,wxMDIFrameClassName
51c1d535 343 ,wxWndProc
f6bcfd97 344 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
51c1d535 345 ,sizeof(ULONG)
f23208ca 346 ))
d88de032 347 {
914589c2
DW
348 vError = ::WinGetLastError(vHab);
349 sError = wxPMErrorToStr(vError);
350 wxLogLastError(sError);
d88de032
DW
351 return FALSE;
352 }
0e320a79 353
f23208ca
DW
354 if (!::WinRegisterClass( vHab
355 ,wxMDIFrameClassNameNoRedraw
51c1d535 356 ,wxWndProc
f23208ca 357 ,0
51c1d535 358 ,sizeof(ULONG)
f23208ca 359 ))
d88de032 360 {
914589c2
DW
361 vError = ::WinGetLastError(vHab);
362 sError = wxPMErrorToStr(vError);
363 wxLogLastError(sError);
d88de032
DW
364 return FALSE;
365 }
366
f23208ca
DW
367 if (!::WinRegisterClass( vHab
368 ,wxMDIChildFrameClassName
51c1d535 369 ,wxWndProc
f23208ca 370 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
51c1d535 371 ,sizeof(ULONG)
f23208ca 372 ))
d88de032 373 {
914589c2
DW
374 vError = ::WinGetLastError(vHab);
375 sError = wxPMErrorToStr(vError);
376 wxLogLastError(sError);
d88de032
DW
377 return FALSE;
378 }
379
f23208ca
DW
380 if (!::WinRegisterClass( vHab
381 ,wxMDIChildFrameClassNameNoRedraw
51c1d535 382 ,wxWndProc
f23208ca 383 ,CS_HITTEST
51c1d535 384 ,sizeof(ULONG)
f23208ca 385 ))
d88de032 386 {
914589c2
DW
387 vError = ::WinGetLastError(vHab);
388 sError = wxPMErrorToStr(vError);
389 wxLogLastError(sError);
d88de032
DW
390 return FALSE;
391 }
392
f23208ca
DW
393 if (!::WinRegisterClass( vHab
394 ,wxPanelClassName
51c1d535 395 ,wxWndProc
f23208ca 396 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
51c1d535 397 ,sizeof(ULONG)
f23208ca 398 ))
d88de032 399 {
914589c2
DW
400 vError = ::WinGetLastError(vHab);
401 sError = wxPMErrorToStr(vError);
402 wxLogLastError(sError);
d88de032
DW
403 return FALSE;
404 }
405
f23208ca
DW
406 if (!::WinRegisterClass( vHab
407 ,wxCanvasClassName
51c1d535 408 ,wxWndProc
e99762c0 409 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT | CS_CLIPCHILDREN
51c1d535 410 ,sizeof(ULONG)
f23208ca 411 ))
d88de032 412 {
914589c2
DW
413 vError = ::WinGetLastError(vHab);
414 sError = wxPMErrorToStr(vError);
415 wxLogLastError(sError);
d88de032
DW
416 return FALSE;
417 }
d88de032 418 return TRUE;
8df85a61 419} // end of wxApp::RegisterWindowClasses
d88de032 420
8df85a61
DW
421//
422// Cleans up any wxWindows internal structures left lying around
423//
0e320a79
DW
424void wxApp::CleanUp()
425{
8df85a61
DW
426 //
427 // COMMON CLEANUP
428 //
d88de032
DW
429
430#if wxUSE_LOG
8df85a61
DW
431
432 //
433 // Flush the logged messages if any and install a 'safer' log target: the
d88de032
DW
434 // default one (wxLogGui) can't be used after the resources are freed just
435 // below and the user suppliedo ne might be even more unsafe (using any
436 // wxWindows GUI function is unsafe starting from now)
8df85a61 437 //
d88de032
DW
438 wxLog::DontCreateOnDemand();
439
8df85a61
DW
440 //
441 // This will flush the old messages if any
442 //
d88de032
DW
443 delete wxLog::SetActiveTarget(new wxLogStderr);
444#endif // wxUSE_LOG
445
8df85a61 446 //
d88de032 447 // One last chance for pending objects to be cleaned up
8df85a61 448 //
d88de032
DW
449 wxTheApp->DeletePendingObjects();
450
451 wxModule::CleanUpModules();
0e320a79
DW
452
453#if wxUSE_WX_RESOURCES
d88de032 454 wxCleanUpResourceSystem();
d88de032 455#endif
0e320a79 456
d88de032 457 wxDeleteStockObjects();
0e320a79 458
8df85a61 459 //
d88de032 460 // Destroy all GDI lists, etc.
8df85a61 461 //
d88de032 462 wxDeleteStockLists();
0e320a79 463
d88de032
DW
464 delete wxTheColourDatabase;
465 wxTheColourDatabase = NULL;
0e320a79 466
d88de032 467 wxBitmap::CleanUpHandlers();
0e320a79 468
d88de032
DW
469 delete[] wxBuffer;
470 wxBuffer = NULL;
0e320a79 471
8df85a61
DW
472 //
473 // PM-SPECIFIC CLEANUP
474 //
0e320a79 475
61243a51 476 // wxSetKeyboardHook(FALSE);
9ed0fac8 477
d88de032 478 if (wxSTD_FRAME_ICON)
9ed0fac8 479 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
d88de032 480 if (wxSTD_MDICHILDFRAME_ICON)
9ed0fac8 481 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
d88de032 482 if (wxSTD_MDIPARENTFRAME_ICON)
9ed0fac8 483 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
d88de032
DW
484
485 if (wxDEFAULT_FRAME_ICON)
9ed0fac8 486 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
d88de032 487 if (wxDEFAULT_MDICHILDFRAME_ICON)
9ed0fac8 488 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
d88de032 489 if (wxDEFAULT_MDIPARENTFRAME_ICON)
9ed0fac8
DW
490 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
491
d88de032
DW
492 if ( wxDisableButtonBrush )
493 {
494// TODO: ::DeleteObject( wxDisableButtonBrush );
495 }
496
497 if (wxWinHandleList)
498 delete wxWinHandleList;
499
d88de032 500 delete wxPendingEvents;
8df85a61 501#if wxUSE_THREADS
d88de032
DW
502 delete wxPendingEventsLocker;
503 // If we don't do the following, we get an apparent memory leak.
504 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
505#endif
0e320a79 506
d88de032 507 wxClassInfo::CleanUpClasses();
0e320a79 508
468e327a
SN
509 // Delete Message queue
510 if (wxTheApp->m_hMq)
511 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
512
d88de032
DW
513 delete wxTheApp;
514 wxTheApp = NULL;
77cd51c3 515
0e320a79 516#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
d88de032
DW
517 // At this point we want to check if there are any memory
518 // blocks that aren't part of the wxDebugContext itself,
519 // as a special case. Then when dumping we need to ignore
520 // wxDebugContext, too.
521 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
522 {
523 wxLogDebug(wxT("There were memory leaks."));
524 wxDebugContext::Dump();
525 wxDebugContext::PrintStatistics();
526 }
527 // wxDebugContext::SetStream(NULL, NULL);
0e320a79 528#endif
77cd51c3 529
d88de032
DW
530#if wxUSE_LOG
531 // do it as the very last thing because everything else can log messages
532 delete wxLog::SetActiveTarget(NULL);
533#endif // wxUSE_LOG
8df85a61 534} // end of wxApp::CleanUp
0e320a79 535
7e99520b
DW
536//----------------------------------------------------------------------
537// Main wxWindows entry point
538//----------------------------------------------------------------------
9ed0fac8
DW
539int wxEntry(
540 int argc
541, char* argv[]
542)
d88de032 543{
9dea36ef 544 HAB vHab = 0;
d88de032 545
9ed0fac8
DW
546 if (!wxApp::Initialize(vHab))
547 return 0;
d88de032 548
9ed0fac8
DW
549 //
550 // create the application object or ensure that one already exists
551 //
552 if (!wxTheApp)
553 {
426d5745
DW
554 // The app may have declared a global application object, but we recommend
555 // the IMPLEMENT_APP macro is used instead, which sets an initializer
556 // function for delayed, dynamic app object construction.
557 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
558 wxT("No initializer - use IMPLEMENT_APP macro.") );
559 wxTheApp = (*wxApp::GetInitializerFunction()) ();
9ed0fac8 560 }
426d5745 561 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
9ed0fac8 562 wxTheApp->argc = argc;
d88de032 563
9ed0fac8
DW
564#if wxUSE_UNICODE
565 wxTheApp->argv = new wxChar*[argc+1];
566
567 int nArgc = 0;
568
569 while (nArgc < argc)
570 {
571 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
572 nArgc++;
573 }
574 wxTheApp->argv[nArgc] = (wxChar *)NULL;
575#else
576 wxTheApp->argv = argv;
577#endif
d88de032 578
9ed0fac8 579 wxString sName(wxFileNameFromPath(argv[0]));
d88de032 580
9ed0fac8
DW
581 wxStripExtension(sName);
582 wxTheApp->SetAppName(sName);
d88de032 583
9ed0fac8 584 int nRetValue = 0;
d88de032 585
9ed0fac8
DW
586 if (!wxTheApp->OnInitGui())
587 nRetValue = -1;
d88de032 588
9ed0fac8
DW
589 if (nRetValue == 0)
590 {
591 if (wxTheApp->OnInit())
d88de032 592 {
7bed7a50 593 nRetValue = wxTheApp->OnRun();
7bed7a50 594 }
51c1d535
DW
595 // Normal exit
596 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
597 if (pTopWindow)
d88de032 598 {
51c1d535
DW
599 // Forcibly delete the window.
600 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
601 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
602 {
603 pTopWindow->Close(TRUE);
604 wxTheApp->DeletePendingObjects();
605 }
606 else
607 {
608 delete pTopWindow;
609 wxTheApp->SetTopWindow(NULL);
610 }
d88de032 611 }
9ed0fac8 612 }
7e99520b
DW
613 else // app initialization failed
614 {
615 wxLogLastError(" Gui initialization failed, exitting");
616 }
617#if wxUSE_CONSOLEDEBUG
618 printf("wxTheApp->OnExit ");
619 fflush(stdout);
620#endif
9ed0fac8 621 wxTheApp->OnExit();
7e99520b
DW
622#if wxUSE_CONSOLEDEBUG
623 printf("wxApp::CleanUp ");
624 fflush(stdout);
625#endif
9ed0fac8 626 wxApp::CleanUp();
7e99520b
DW
627#if wxUSE_CONSOLEDEBUG
628 printf("return %i ", nRetValue);
629 fflush(stdout);
630#endif
9ed0fac8 631 return(nRetValue);
8df85a61 632} // end of wxEntry
77cd51c3 633
9ed0fac8 634bool wxApp::OnInitGui()
d88de032 635{
914589c2
DW
636 ERRORID vError;
637 wxString sError;
77cd51c3 638
f23208ca 639 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
914589c2
DW
640 if (!m_hMq)
641 {
642 vError = ::WinGetLastError(vHabmain);
643 sError = wxPMErrorToStr(vError);
644 wxLogDebug(sError);
645 return FALSE;
646 }
9ed0fac8 647 return TRUE;
8df85a61 648} // end of wxApp::OnInitGui
0e320a79 649
9ed0fac8
DW
650//
651// Static member initialization
652//
d88de032 653wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
0e320a79
DW
654
655wxApp::wxApp()
656{
d88de032
DW
657 m_topWindow = NULL;
658 wxTheApp = this;
659 m_wantDebugOutput = TRUE;
660
661 argc = 0;
662 argv = NULL;
9ed0fac8 663 m_nPrintMode = wxPRINT_WINDOWS;
d88de032 664 m_exitOnFrameDelete = TRUE;
9ed0fac8 665 m_bAuto3D = TRUE;
468e327a 666 m_hMq = 0;
3958ae62
SN
667 m_maxSocketHandles = 0;
668 m_maxSocketNr = 0;
669 m_sockCallbackInfo = 0;
8df85a61 670} // end of wxApp::wxApp
d88de032
DW
671
672wxApp::~wxApp()
673{
8df85a61 674 //
d88de032 675 // Delete command-line args
8df85a61 676 //
039bec17 677#if wxUSE_UNICODE
8df85a61
DW
678 int i;
679
d88de032
DW
680 for (i = 0; i < argc; i++)
681 {
682 delete[] argv[i];
683 }
684 delete[] argv;
039bec17 685#endif
8df85a61 686} // end of wxApp::~wxApp
0e320a79
DW
687
688bool wxApp::Initialized()
689{
d88de032
DW
690 if (GetTopWindow())
691 return TRUE;
692 else
693 return FALSE;
8df85a61 694} // end of wxApp::Initialized
0e320a79 695
9ed0fac8
DW
696//
697// Get and process a message, returning FALSE if WM_QUIT
698// received (and also set the flag telling the app to exit the main loop)
699//
3958ae62 700
d88de032
DW
701bool wxApp::DoMessage()
702{
468e327a 703 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
9ed0fac8
DW
704
705 if (bRc == 0)
d88de032
DW
706 {
707 // got WM_QUIT
9ed0fac8 708 m_bKeepGoing = FALSE;
d88de032
DW
709 return FALSE;
710 }
9ed0fac8 711 else if (bRc == -1)
d88de032
DW
712 {
713 // should never happen, but let's test for it nevertheless
714 wxLogLastError("GetMessage");
715 }
716 else
717 {
718#if wxUSE_THREADS
9ed0fac8
DW
719 wxASSERT_MSG( wxThread::IsMain()
720 ,wxT("only the main thread can process Windows messages")
721 );
d88de032 722
9ed0fac8
DW
723 static bool sbHadGuiLock = TRUE;
724 static wxMsgArray svSavedMessages;
d88de032 725
9ed0fac8 726 //
8df85a61 727 // If a secondary thread owns is doing GUI calls, save all messages for
d88de032
DW
728 // later processing - we can't process them right now because it will
729 // lead to recursive library calls (and we're not reentrant)
9ed0fac8
DW
730 //
731 if (!wxGuiOwnedByMainThread())
d88de032 732 {
9ed0fac8 733 sbHadGuiLock = FALSE;
d88de032 734
8df85a61
DW
735 //
736 // Leave out WM_COMMAND messages: too dangerous, sometimes
d88de032 737 // the message will be processed twice
8df85a61 738 //
d88de032 739 if ( !wxIsWaitingForThread() ||
9ed0fac8 740 svCurrentMsg.msg != WM_COMMAND )
d88de032 741 {
9ed0fac8 742 svSavedMessages.Add(svCurrentMsg);
d88de032 743 }
d88de032
DW
744 return TRUE;
745 }
746 else
747 {
9ed0fac8 748 //
8df85a61 749 // Have we just regained the GUI lock? if so, post all of the saved
d88de032
DW
750 // messages
751 //
9ed0fac8 752 if (!sbHadGuiLock )
d88de032 753 {
9ed0fac8 754 sbHadGuiLock = TRUE;
d88de032 755
9ed0fac8
DW
756 size_t nCount = svSavedMessages.Count();
757
758 for (size_t n = 0; n < nCount; n++)
d88de032 759 {
9ed0fac8 760 QMSG vMsg = svSavedMessages[n];
d88de032 761
9ed0fac8 762 if ( !ProcessMessage((WXMSG *)&vMsg) )
d88de032 763 {
43543d98 764 ::WinDispatchMsg(vHabmain, &vMsg);
d88de032
DW
765 }
766 }
9ed0fac8 767 svSavedMessages.Empty();
d88de032
DW
768 }
769 }
d88de032
DW
770#endif // wxUSE_THREADS
771
772 // Process the message
468e327a 773 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
d88de032 774 {
43543d98 775 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
d88de032 776 }
d88de032 777 }
d88de032 778 return TRUE;
8df85a61 779} // end of wxApp::DoMessage
d88de032 780
9ed0fac8
DW
781//////////////////////////////////////////////////////////////////////////////
782//
783// Keep trying to process messages until WM_QUIT
784// received.
785//
786// If there are messages to be processed, they will all be
787// processed and OnIdle will not be called.
788// When there are no more messages, OnIdle is called.
789// If OnIdle requests more time,
790// it will be repeatedly called so long as there are no pending messages.
791// A 'feature' of this is that once OnIdle has decided that no more processing
792// is required, then it won't get processing time until further messages
793// are processed (it'll sit in DoMessage).
794//
795//////////////////////////////////////////////////////////////////////////////
0e320a79
DW
796int wxApp::MainLoop()
797{
9ed0fac8 798 m_bKeepGoing = TRUE;
d88de032 799
9ed0fac8 800 while (m_bKeepGoing)
d88de032
DW
801 {
802#if wxUSE_THREADS
803 wxMutexGuiLeaveOrEnter();
804#endif // wxUSE_THREADS
3958ae62 805 while (!Pending() && ProcessIdle())
5b3ed311 806 {
3958ae62
SN
807 HandleSockets();
808 wxUsleep(10000);
5b3ed311 809 }
3958ae62
SN
810 HandleSockets();
811 if (Pending())
812 DoMessage();
813 else
814 wxUsleep(10000);
815
d88de032 816 }
9ed0fac8 817 return (int)svCurrentMsg.mp1;
8df85a61 818} // end of wxApp::MainLoop
0e320a79 819
9ed0fac8 820//
0e320a79 821// Returns TRUE if more time is needed.
9ed0fac8 822//
0e320a79
DW
823bool wxApp::ProcessIdle()
824{
9ed0fac8 825 wxIdleEvent vEvent;
0e320a79 826
9ed0fac8
DW
827 vEvent.SetEventObject(this);
828 ProcessEvent(vEvent);
829 return vEvent.MoreRequested();
8df85a61 830} // end of wxApp::ProcessIdle
d88de032 831
0e320a79
DW
832void wxApp::ExitMainLoop()
833{
9ed0fac8 834 m_bKeepGoing = FALSE;
0e320a79
DW
835}
836
0e320a79
DW
837bool wxApp::Pending()
838{
43543d98 839 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
0e320a79
DW
840}
841
0e320a79
DW
842void wxApp::Dispatch()
843{
d88de032 844 DoMessage();
0e320a79
DW
845}
846
9ed0fac8
DW
847//////////////////////////////////////////////////////////////////////////////
848//
849// Give all windows a chance to preprocess
850// the message. Some may have accelerator tables, or have
851// MDI complications.
852//
853//////////////////////////////////////////////////////////////////////////////
854bool wxApp::ProcessMessage(
855 WXMSG* pWxmsg
856)
0e320a79 857{
f6bcfd97
BP
858 QMSG* pMsg = (PQMSG)pWxmsg;
859 HWND hWnd = pMsg->hwnd;
9ed0fac8
DW
860 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
861 wxWindow* pWnd;
d88de032 862
8df85a61
DW
863#if wxUSE_TOOLTIPS
864 //
865 // We must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
866 // popup the tooltip bubbles
867 //
f6bcfd97 868 if (pWndThis && (pMsg->msg == WM_MOUSEMOVE))
8df85a61
DW
869 {
870 wxToolTip* pToolTip = pWndThis->GetToolTip();
871 if (pToolTip)
872 {
873 pToolTip->RelayEvent(pWxmsg);
874 }
875 }
876#endif // wxUSE_TOOLTIPS
877
05a8bfed
DW
878 //
879 // We must relay Timer events to wxTimer's processing function
880 //
881 if (pMsg->msg == WM_TIMER)
496fd9fb 882 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
05a8bfed 883
9ed0fac8 884 //
8df85a61 885 // For some composite controls (like a combobox), wndThis might be NULL
d88de032
DW
886 // because the subcontrol is not a wxWindow, but only the control itself
887 // is - try to catch this case
9ed0fac8
DW
888 //
889 while (hWnd && !pWndThis)
d88de032 890 {
9ed0fac8
DW
891 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
892 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
d88de032 893 }
0e320a79 894
f6bcfd97
BP
895 //
896 // Try translations first; find the youngest window with
f09d8a3b
DW
897 // a translation table. OS/2 has case sensative accels, so
898 // this block, coded by BK, removes that and helps make them
899 // case insensative.
f6bcfd97 900 //
f09d8a3b 901 if(pMsg->msg == WM_CHAR)
f6bcfd97 902 {
f09d8a3b
DW
903 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
904 USHORT uSch = CHARMSG(pChmsg)->chr;
905 bool bRc;
906
907 //
908 // Do not process keyup events
909 //
910 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
911 {
912 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
f1f22049 913 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
f09d8a3b 914
7e99520b 915
5b3ed311
DW
916 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
917 {
918 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
919 break;
920 }
7e99520b 921
f09d8a3b
DW
922 if(!bRc) // untranslated, should restore original value
923 CHARMSG(pChmsg)->chr = uSch;
924 }
f6bcfd97 925 }
8df85a61 926 //
d88de032 927 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 928 //
e604d44b
DW
929// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
930// {
931// if (pWnd->OS2ProcessMessage(pWxmsg))
932// return TRUE;
933// }
d88de032 934 return FALSE;
8df85a61 935} // end of wxApp::ProcessMessage
0e320a79 936
9ed0fac8
DW
937void wxApp::OnIdle(
938 wxIdleEvent& rEvent
939)
d88de032 940{
9ed0fac8 941 static bool sbInOnIdle = FALSE;
d88de032 942
9ed0fac8 943 //
d88de032 944 // Avoid recursion (via ProcessEvent default case)
9ed0fac8 945 //
5b3ed311 946 if (sbInOnIdle)
d88de032 947 return;
0e320a79 948
9ed0fac8 949 sbInOnIdle = TRUE;
0e320a79 950
8df85a61
DW
951 //
952 // If there are pending events, we must process them: pending events
953 // are either events to the threads other than main or events posted
954 // with wxPostEvent() functions
955 //
956 ProcessPendingEvents();
957
9ed0fac8 958 //
d88de032 959 // 'Garbage' collection of windows deleted with Close().
9ed0fac8 960 //
d88de032 961 DeletePendingObjects();
0e320a79 962
d88de032 963#if wxUSE_LOG
8df85a61
DW
964 //
965 // Flush the logged messages if any
966 //
967 wxLog::FlushActive();
d88de032 968#endif // wxUSE_LOG
0e320a79 969
8df85a61 970 //
d88de032 971 // Send OnIdle events to all windows
8df85a61 972 //
9ed0fac8 973 if (SendIdleEvents())
d88de032 974 {
9ed0fac8 975 //
d88de032
DW
976 // SendIdleEvents() returns TRUE if at least one window requested more
977 // idle events
9ed0fac8
DW
978 //
979 rEvent.RequestMore(TRUE);
d88de032 980 }
9ed0fac8 981 sbInOnIdle = FALSE;
8df85a61 982} // end of wxApp::OnIdle
9779893b 983
0e320a79
DW
984// Send idle event to all top-level windows
985bool wxApp::SendIdleEvents()
986{
9ed0fac8
DW
987 bool bNeedMore = FALSE;
988 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
d88de032 989
9ed0fac8 990 while (pNode)
d88de032 991 {
9ed0fac8 992 wxWindow* pWin = pNode->GetData();
0e320a79 993
9ed0fac8
DW
994 if (SendIdleEvents(pWin))
995 bNeedMore = TRUE;
996 pNode = pNode->GetNext();
997 }
998 return bNeedMore;
8df85a61 999} // end of wxApp::SendIdleEvents
0e320a79 1000
9ed0fac8 1001//
0e320a79 1002// Send idle event to window and all subwindows
9ed0fac8
DW
1003//
1004bool wxApp::SendIdleEvents(
1005 wxWindow* pWin
1006)
0e320a79 1007{
9ed0fac8
DW
1008 bool bNeedMore = FALSE;
1009 wxIdleEvent vEvent;
1010
1011 vEvent.SetEventObject(pWin);
1012 pWin->GetEventHandler()->ProcessEvent(vEvent);
0e320a79 1013
9ed0fac8
DW
1014 if (vEvent.MoreRequested())
1015 bNeedMore = TRUE;
0e320a79 1016
9ed0fac8 1017 wxNode* pNode = pWin->GetChildren().First();
0e320a79 1018
9ed0fac8 1019 while (pNode)
d88de032 1020 {
9ed0fac8 1021 wxWindow* pWin = (wxWindow*) pNode->Data();
0e320a79 1022
9ed0fac8
DW
1023 if (SendIdleEvents(pWin))
1024 bNeedMore = TRUE;
1025 pNode = pNode->Next();
d88de032 1026 }
9ed0fac8 1027 return bNeedMore;
8df85a61 1028} // end of wxApp::SendIdleEvents
0e320a79
DW
1029
1030void wxApp::DeletePendingObjects()
1031{
9ed0fac8
DW
1032 wxNode* pNode = wxPendingDelete.First();
1033
1034 while (pNode)
d88de032 1035 {
9ed0fac8 1036 wxObject* pObj = (wxObject *)pNode->Data();
77cd51c3 1037
9ed0fac8 1038 delete pObj;
0e320a79 1039
9ed0fac8
DW
1040 if (wxPendingDelete.Member(pObj))
1041 delete pNode;
0e320a79 1042
9ed0fac8 1043 //
d88de032
DW
1044 // Deleting one object may have deleted other pending
1045 // objects, so start from beginning of list again.
9ed0fac8
DW
1046 //
1047 pNode = wxPendingDelete.First();
d88de032 1048 }
8df85a61 1049} // end of wxApp::DeletePendingObjects
0e320a79 1050
9ed0fac8
DW
1051void wxApp::OnEndSession(
1052 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 1053{
d88de032
DW
1054 if (GetTopWindow())
1055 GetTopWindow()->Close(TRUE);
8df85a61 1056} // end of wxApp::OnEndSession
0e320a79 1057
9ed0fac8 1058//
d88de032
DW
1059// Default behaviour: close the application with prompts. The
1060// user can veto the close, and therefore the end session.
9ed0fac8
DW
1061//
1062void wxApp::OnQueryEndSession(
1063 wxCloseEvent& rEvent
1064)
0e320a79 1065{
d88de032
DW
1066 if (GetTopWindow())
1067 {
9ed0fac8
DW
1068 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
1069 rEvent.Veto(TRUE);
d88de032 1070 }
8df85a61 1071} // end of wxApp::OnQueryEndSession
0e320a79
DW
1072
1073void wxExit()
1074{
d88de032
DW
1075 wxLogError(_("Fatal error: exiting"));
1076
1077 wxApp::CleanUp();
ee453a16 1078} // end of wxExit
0e320a79 1079
8b63ae37
DW
1080static bool gs_inYield = FALSE;
1081
8df85a61 1082//
d88de032 1083// Yield to incoming messages
8df85a61 1084//
0e320a79
DW
1085bool wxYield()
1086{
9dea36ef 1087 HAB vHab = 0;
dde11e60 1088 QMSG vMsg;
ee453a16 1089
8df85a61
DW
1090 //
1091 // Disable log flushing from here because a call to wxYield() shouldn't
1092 // normally result in message boxes popping up &c
1093 //
1094 wxLog::Suspend();
1095
8b63ae37
DW
1096 gs_inYield = TRUE;
1097
8df85a61 1098 //
d88de032
DW
1099 // We want to go back to the main message loop
1100 // if we see a WM_QUIT. (?)
8df85a61 1101 //
dde11e60 1102 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 1103 {
8df85a61
DW
1104#if wxUSE_THREADS
1105 wxMutexGuiLeaveOrEnter();
1106#endif // wxUSE_THREADS
dde11e60 1107 if (!wxTheApp->DoMessage())
d88de032
DW
1108 break;
1109 }
8df85a61 1110 //
d88de032 1111 // If they are pending events, we must process them.
8df85a61
DW
1112 //
1113 if (wxTheApp)
1114 wxTheApp->ProcessPendingEvents();
1115
1116 //
1117 // Let the logs be flashed again
1118 //
1119 wxLog::Resume();
8b63ae37 1120 gs_inYield = FALSE;
d88de032 1121 return TRUE;
8df85a61 1122} // end of wxYield
d88de032 1123
8b63ae37
DW
1124// Yield to incoming messages; but fail silently if recursion is detected.
1125bool wxYieldIfNeeded()
1126{
1127 if (gs_inYield)
1128 return FALSE;
1129
1130 return wxYield();
1131}
1132
9ed0fac8
DW
1133wxIcon wxApp::GetStdIcon(
1134 int nWhich
1135) const
d88de032 1136{
9ed0fac8 1137 switch(nWhich)
d88de032
DW
1138 {
1139 case wxICON_INFORMATION:
1140 return wxIcon("wxICON_INFO");
1141
1142 case wxICON_QUESTION:
1143 return wxIcon("wxICON_QUESTION");
1144
1145 case wxICON_EXCLAMATION:
1146 return wxIcon("wxICON_WARNING");
1147
1148 default:
1149 wxFAIL_MSG(wxT("requested non existent standard icon"));
1150 // still fall through
1151
1152 case wxICON_HAND:
1153 return wxIcon("wxICON_ERROR");
1154 }
d88de032 1155 return wxIcon("wxICON_ERROR");
8df85a61
DW
1156} // end of wxApp::GetStdIcon
1157
3958ae62
SN
1158int wxApp::AddSocketHandler(int handle, int mask,
1159 void (*callback)(void*), void * gsock)
1160{
1161 int find;
1162 struct GsocketCallbackInfo
1163 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1164
1165 for (find = 0; find < m_maxSocketHandles; find++)
1166 if (CallbackInfo[find].handle == -1)
1167 break;
1168 if (find == m_maxSocketHandles)
1169 {
1170 // Allocate new memory
1171 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
1172 (m_maxSocketHandles+=10)*
1173 sizeof(struct GsocketCallbackInfo));
1174 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1175 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
1176 CallbackInfo[find].handle = -1;
1177 find = m_maxSocketHandles - 10;
1178 }
1179 CallbackInfo[find].proc = callback;
1180 CallbackInfo[find].type = mask;
1181 CallbackInfo[find].handle = handle;
1182 CallbackInfo[find].gsock = gsock;
1183 if (mask & wxSockReadMask)
1184 FD_SET(handle, &m_readfds);
1185 if (mask & wxSockWriteMask)
1186 FD_SET(handle, &m_writefds);
1187 if (handle >= m_maxSocketNr)
1188 m_maxSocketNr = handle + 1;
1189 return find;
1190}
1191
1192void wxApp::RemoveSocketHandler(int handle)
1193{
1194 struct GsocketCallbackInfo
1195 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1196 if (handle < m_maxSocketHandles)
1197 {
1198 if (CallbackInfo[handle].type & wxSockReadMask)
1199 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
1200 if (CallbackInfo[handle].type & wxSockWriteMask)
1201 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
1202 CallbackInfo[handle].handle = -1;
1203 }
1204}
1205
8df85a61
DW
1206//-----------------------------------------------------------------------------
1207// wxWakeUpIdle
1208//-----------------------------------------------------------------------------
1209
1210void wxWakeUpIdle()
1211{
1212 //
1213 // Send the top window a dummy message so idle handler processing will
1214 // start up again. Doing it this way ensures that the idle handler
1215 // wakes up in the right thread (see also wxWakeUpMainThread() which does
1216 // the same for the main app thread only)
1217 //
1218 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
1219
1220 if (pTopWindow)
1221 {
1222 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
1223 {
1224 //
1225 // Should never happen
1226 //
1227 wxLogLastError("PostMessage(WM_NULL)");
1228 }
1229 }
1230} // end of wxWakeUpIdle
d88de032 1231
76990f63 1232HAB wxGetInstance()
d88de032 1233{
76990f63 1234 return vHabmain;
d88de032
DW
1235}
1236
76990f63
DW
1237void wxSetInstance(
1238 HAB vHab
1239)
d88de032 1240{
76990f63 1241 vHabmain = vHab;
0e320a79
DW
1242}
1243