]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
Highly experimental, unstable code (for determining the
[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"
30# include "wx/wxchar.h"
31# include "wx/icon.h"
0e320a79
DW
32#endif
33
0e320a79
DW
34#include "wx/log.h"
35#include "wx/module.h"
d88de032
DW
36
37#include "wx/os2/private.h"
38
39#if wxUSE_THREADS
40 #include "wx/thread.h"
41
9ed0fac8
DW
42 // define the array of QMSG strutures
43 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
d88de032
DW
44
45 #include "wx/arrimpl.cpp"
46
9ed0fac8 47 WX_DEFINE_OBJARRAY(wxMsgArray);
d88de032 48#endif // wxUSE_THREADS
0e320a79
DW
49
50#if wxUSE_WX_RESOURCES
d88de032 51 #include "wx/resource.h"
0e320a79
DW
52#endif
53
8df85a61
DW
54#if wxUSE_TOOLTIPS
55 #include "wx/tooltip.h"
56#endif // wxUSE_TOOLTIPS
57
0e320a79 58#include <string.h>
d88de032
DW
59#include <ctype.h>
60
61// ---------------------------------------------------------------------------
62// global variables
63// ---------------------------------------------------------------------------
64
9ed0fac8
DW
65extern wxChar* wxBuffer;
66extern wxChar* wxOsVersion;
67extern wxList* wxWinHandleList;
68extern wxList WXDLLEXPORT wxPendingDelete;
9ed0fac8 69extern wxCursor* g_globalCursor;
0e320a79 70
8df85a61 71HAB vHabmain = NULLHANDLE;
9ed0fac8
DW
72QMSG svCurrentMsg;
73wxApp* wxTheApp = NULL;
d88de032
DW
74
75// NB: all "NoRedraw" classes must have the same names as the "normal" classes
13a4ea8d 76// with NR suffix - wxWindow::OS2Create() supposes this
9ed0fac8
DW
77wxChar wxFrameClassName[] = wxT("wxFrameClass");
78wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
79wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
80wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
81wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
d88de032 82wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
9ed0fac8
DW
83wxChar wxPanelClassName[] = wxT("wxPanelClass");
84wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
d88de032 85
9ed0fac8
DW
86HICON wxSTD_FRAME_ICON = (HICON) NULL;
87HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
d88de032
DW
88HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
89
9ed0fac8
DW
90HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
91HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
92HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
d88de032
DW
93
94HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
95
f23208ca
DW
96MRESULT EXPENTRY wxWndProc( HWND
97 ,ULONG
98 ,MPARAM
99 ,MPARAM
100 );
d88de032
DW
101
102// ===========================================================================
103// implementation
104// ===========================================================================
105
106// ---------------------------------------------------------------------------
107// wxApp
108// ---------------------------------------------------------------------------
109
d88de032 110 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
0e320a79 111
d88de032
DW
112 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
113 EVT_IDLE(wxApp::OnIdle)
114 EVT_END_SESSION(wxApp::OnEndSession)
115 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
116 END_EVENT_TABLE()
0e320a79 117
8df85a61
DW
118//
119// Initialize
120//
9ed0fac8
DW
121bool wxApp::Initialize(
122 HAB vHab
123)
0e320a79 124{
914589c2
DW
125 //
126 // OS2 has to have an anchorblock
127 //
128 vHab = WinInitialize(0);
129
130 if (!vHab)
131 return FALSE;
132 else
133 vHabmain = vHab;
134
d88de032
DW
135 // Some people may wish to use this, but
136 // probably it shouldn't be here by default.
137#ifdef __WXDEBUG__
138 // wxRedirectIOToConsole();
0e320a79
DW
139#endif
140
13a4ea8d 141 wxBuffer = new wxChar[1500]; // FIXME; why?
0e320a79 142
d88de032 143 wxClassInfo::InitializeClasses();
0e320a79 144
d88de032
DW
145#if wxUSE_RESOURCES
146 wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
147#endif
148
8df85a61
DW
149#if wxUSE_THREADS
150 wxPendingEventsLocker = new wxCriticalSection;
151#endif
152
d88de032
DW
153 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
154 wxTheColourDatabase->Initialize();
155
156 wxInitializeStockLists();
157 wxInitializeStockObjects();
0e320a79
DW
158
159#if wxUSE_WX_RESOURCES
d88de032 160 wxInitializeResourceSystem();
0e320a79
DW
161#endif
162
d88de032
DW
163 wxBitmap::InitStandardHandlers();
164
9ed0fac8 165 RegisterWindowClasses(vHab);
d88de032
DW
166 wxWinHandleList = new wxList(wxKEY_INTEGER);
167
168 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
169 // PLEASE DO NOT ALTER THIS.
1b3d5e55 170#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
d88de032
DW
171 extern char wxDummyChar;
172 if (wxDummyChar) wxDummyChar++;
173#endif
174
61243a51 175 // wxSetKeyboardHook(TRUE);
d88de032
DW
176
177 wxModule::RegisterModules();
178 if (!wxModule::InitializeModules())
179 return FALSE;
180 return TRUE;
8df85a61 181} // end of wxApp::Initialize
d88de032
DW
182
183// ---------------------------------------------------------------------------
184// RegisterWindowClasses
185// ---------------------------------------------------------------------------
186
9ed0fac8
DW
187bool wxApp::RegisterWindowClasses(
188 HAB vHab
189)
d88de032 190{
3b9e3455 191 APIRET rc;
914589c2
DW
192 ERRORID vError = 0L;
193 wxString sError;
3b9e3455 194
f23208ca
DW
195 if (!::WinRegisterClass( vHab
196 ,wxFrameClassName
197 ,(PFNWP)wxWndProc
198 ,CS_SIZEREDRAW | CS_SYNCPAINT
a0606634 199 ,sizeof(ULONG)
f23208ca 200 ))
d88de032 201 {
914589c2
DW
202 vError = ::WinGetLastError(vHab);
203 sError = wxPMErrorToStr(vError);
204 wxLogLastError(sError);
d88de032
DW
205 return FALSE;
206 }
207
f23208ca
DW
208 if (!::WinRegisterClass( vHab
209 ,wxFrameClassNameNoRedraw
210 ,(PFNWP)wxWndProc
211 ,0
212 ,0
213 ))
d88de032 214 {
914589c2
DW
215 vError = ::WinGetLastError(vHab);
216 sError = wxPMErrorToStr(vError);
217 wxLogLastError(sError);
d88de032
DW
218 return FALSE;
219 }
220
f23208ca
DW
221 if (!::WinRegisterClass( vHab
222 ,wxMDIFrameClassName
223 ,(PFNWP)wxWndProc
224 ,CS_SIZEREDRAW | CS_SYNCPAINT
225 ,0
226 ))
d88de032 227 {
914589c2
DW
228 vError = ::WinGetLastError(vHab);
229 sError = wxPMErrorToStr(vError);
230 wxLogLastError(sError);
d88de032
DW
231 return FALSE;
232 }
0e320a79 233
f23208ca
DW
234 if (!::WinRegisterClass( vHab
235 ,wxMDIFrameClassNameNoRedraw
236 ,(PFNWP)wxWndProc
237 ,0
238 ,0
239 ))
d88de032 240 {
914589c2
DW
241 vError = ::WinGetLastError(vHab);
242 sError = wxPMErrorToStr(vError);
243 wxLogLastError(sError);
d88de032
DW
244 return FALSE;
245 }
246
f23208ca
DW
247 if (!::WinRegisterClass( vHab
248 ,wxMDIChildFrameClassName
249 ,(PFNWP)wxWndProc
250 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
251 ,0
252 ))
d88de032 253 {
914589c2
DW
254 vError = ::WinGetLastError(vHab);
255 sError = wxPMErrorToStr(vError);
256 wxLogLastError(sError);
d88de032
DW
257 return FALSE;
258 }
259
f23208ca
DW
260 if (!::WinRegisterClass( vHab
261 ,wxMDIChildFrameClassNameNoRedraw
262 ,(PFNWP)wxWndProc
263 ,CS_HITTEST
264 ,0
265 ))
d88de032 266 {
914589c2
DW
267 vError = ::WinGetLastError(vHab);
268 sError = wxPMErrorToStr(vError);
269 wxLogLastError(sError);
d88de032
DW
270 return FALSE;
271 }
272
f23208ca
DW
273 if (!::WinRegisterClass( vHab
274 ,wxPanelClassName
275 ,(PFNWP)wxWndProc
276 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
277 ,0
278 ))
d88de032 279 {
914589c2
DW
280 vError = ::WinGetLastError(vHab);
281 sError = wxPMErrorToStr(vError);
282 wxLogLastError(sError);
d88de032
DW
283 return FALSE;
284 }
285
f23208ca
DW
286 if (!::WinRegisterClass( vHab
287 ,wxCanvasClassName
288 ,(PFNWP)wxWndProc
289 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
290 ,0
291 ))
d88de032 292 {
914589c2
DW
293 vError = ::WinGetLastError(vHab);
294 sError = wxPMErrorToStr(vError);
295 wxLogLastError(sError);
d88de032
DW
296 return FALSE;
297 }
d88de032 298 return TRUE;
8df85a61 299} // end of wxApp::RegisterWindowClasses
d88de032 300
8df85a61
DW
301//
302// Cleans up any wxWindows internal structures left lying around
303//
0e320a79
DW
304void wxApp::CleanUp()
305{
8df85a61
DW
306 //
307 // COMMON CLEANUP
308 //
d88de032
DW
309
310#if wxUSE_LOG
8df85a61
DW
311
312 //
313 // Flush the logged messages if any and install a 'safer' log target: the
d88de032
DW
314 // default one (wxLogGui) can't be used after the resources are freed just
315 // below and the user suppliedo ne might be even more unsafe (using any
316 // wxWindows GUI function is unsafe starting from now)
8df85a61 317 //
d88de032
DW
318 wxLog::DontCreateOnDemand();
319
8df85a61
DW
320 //
321 // This will flush the old messages if any
322 //
d88de032
DW
323 delete wxLog::SetActiveTarget(new wxLogStderr);
324#endif // wxUSE_LOG
325
8df85a61 326 //
d88de032 327 // One last chance for pending objects to be cleaned up
8df85a61 328 //
d88de032
DW
329 wxTheApp->DeletePendingObjects();
330
331 wxModule::CleanUpModules();
0e320a79
DW
332
333#if wxUSE_WX_RESOURCES
d88de032 334 wxCleanUpResourceSystem();
d88de032 335#endif
0e320a79 336
d88de032 337 wxDeleteStockObjects();
0e320a79 338
8df85a61 339 //
d88de032 340 // Destroy all GDI lists, etc.
8df85a61 341 //
d88de032 342 wxDeleteStockLists();
0e320a79 343
d88de032
DW
344 delete wxTheColourDatabase;
345 wxTheColourDatabase = NULL;
0e320a79 346
d88de032 347 wxBitmap::CleanUpHandlers();
0e320a79 348
d88de032
DW
349 delete[] wxBuffer;
350 wxBuffer = NULL;
0e320a79 351
8df85a61
DW
352 //
353 // PM-SPECIFIC CLEANUP
354 //
0e320a79 355
61243a51 356 // wxSetKeyboardHook(FALSE);
9ed0fac8 357
d88de032 358 if (wxSTD_FRAME_ICON)
9ed0fac8 359 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
d88de032 360 if (wxSTD_MDICHILDFRAME_ICON)
9ed0fac8 361 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
d88de032 362 if (wxSTD_MDIPARENTFRAME_ICON)
9ed0fac8 363 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
d88de032
DW
364
365 if (wxDEFAULT_FRAME_ICON)
9ed0fac8 366 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
d88de032 367 if (wxDEFAULT_MDICHILDFRAME_ICON)
9ed0fac8 368 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
d88de032 369 if (wxDEFAULT_MDIPARENTFRAME_ICON)
9ed0fac8
DW
370 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
371
d88de032
DW
372 if ( wxDisableButtonBrush )
373 {
374// TODO: ::DeleteObject( wxDisableButtonBrush );
375 }
376
377 if (wxWinHandleList)
378 delete wxWinHandleList;
379
d88de032 380 delete wxPendingEvents;
8df85a61 381#if wxUSE_THREADS
d88de032
DW
382 delete wxPendingEventsLocker;
383 // If we don't do the following, we get an apparent memory leak.
384 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
385#endif
0e320a79 386
d88de032 387 wxClassInfo::CleanUpClasses();
0e320a79 388
468e327a
SN
389 // Delete Message queue
390 if (wxTheApp->m_hMq)
391 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
392
d88de032
DW
393 delete wxTheApp;
394 wxTheApp = NULL;
77cd51c3 395
0e320a79 396#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
d88de032
DW
397 // At this point we want to check if there are any memory
398 // blocks that aren't part of the wxDebugContext itself,
399 // as a special case. Then when dumping we need to ignore
400 // wxDebugContext, too.
401 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
402 {
403 wxLogDebug(wxT("There were memory leaks."));
404 wxDebugContext::Dump();
405 wxDebugContext::PrintStatistics();
406 }
407 // wxDebugContext::SetStream(NULL, NULL);
0e320a79 408#endif
77cd51c3 409
d88de032
DW
410#if wxUSE_LOG
411 // do it as the very last thing because everything else can log messages
412 delete wxLog::SetActiveTarget(NULL);
413#endif // wxUSE_LOG
8df85a61 414} // end of wxApp::CleanUp
0e320a79 415
9ed0fac8
DW
416int wxEntry(
417 int argc
418, char* argv[]
419)
d88de032 420{
9dea36ef 421 HAB vHab = 0;
d88de032 422
9ed0fac8
DW
423 if (!wxApp::Initialize(vHab))
424 return 0;
d88de032 425
9ed0fac8
DW
426 //
427 // create the application object or ensure that one already exists
428 //
429 if (!wxTheApp)
430 {
426d5745
DW
431 // The app may have declared a global application object, but we recommend
432 // the IMPLEMENT_APP macro is used instead, which sets an initializer
433 // function for delayed, dynamic app object construction.
434 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
435 wxT("No initializer - use IMPLEMENT_APP macro.") );
436 wxTheApp = (*wxApp::GetInitializerFunction()) ();
9ed0fac8 437 }
426d5745 438 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
9ed0fac8 439 wxTheApp->argc = argc;
d88de032 440
9ed0fac8
DW
441#if wxUSE_UNICODE
442 wxTheApp->argv = new wxChar*[argc+1];
443
444 int nArgc = 0;
445
446 while (nArgc < argc)
447 {
448 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
449 nArgc++;
450 }
451 wxTheApp->argv[nArgc] = (wxChar *)NULL;
452#else
453 wxTheApp->argv = argv;
454#endif
d88de032 455
9ed0fac8 456 wxString sName(wxFileNameFromPath(argv[0]));
d88de032 457
9ed0fac8
DW
458 wxStripExtension(sName);
459 wxTheApp->SetAppName(sName);
d88de032 460
9ed0fac8 461 int nRetValue = 0;
d88de032 462
9ed0fac8
DW
463 if (!wxTheApp->OnInitGui())
464 nRetValue = -1;
d88de032 465
9ed0fac8
DW
466 if (nRetValue == 0)
467 {
468 if (wxTheApp->OnInit())
d88de032 469 {
7bed7a50
DW
470 nRetValue = wxTheApp->OnRun();
471// nRetValue = -1;
d88de032 472 }
9ed0fac8
DW
473 }
474
7bed7a50 475 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
d88de032 476
7bed7a50
DW
477 if (pTopWindow)
478 {
479 // Forcibly delete the window.
480 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
481 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
482 {
483 pTopWindow->Close(TRUE);
484 wxTheApp->DeletePendingObjects();
485 }
486 else
d88de032 487 {
7bed7a50
DW
488 delete pTopWindow;
489 wxTheApp->SetTopWindow(NULL);
d88de032 490 }
9ed0fac8
DW
491 }
492 wxTheApp->OnExit();
493 wxApp::CleanUp();
494 return(nRetValue);
8df85a61 495} // end of wxEntry
77cd51c3 496
9ed0fac8 497bool wxApp::OnInitGui()
d88de032 498{
914589c2
DW
499 ERRORID vError;
500 wxString sError;
77cd51c3 501
f23208ca 502 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
914589c2
DW
503 if (!m_hMq)
504 {
505 vError = ::WinGetLastError(vHabmain);
506 sError = wxPMErrorToStr(vError);
507 wxLogDebug(sError);
508 return FALSE;
509 }
9ed0fac8 510 return TRUE;
8df85a61 511} // end of wxApp::OnInitGui
0e320a79 512
9ed0fac8
DW
513//
514// Static member initialization
515//
d88de032 516wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
0e320a79
DW
517
518wxApp::wxApp()
519{
d88de032
DW
520 m_topWindow = NULL;
521 wxTheApp = this;
522 m_wantDebugOutput = TRUE;
523
524 argc = 0;
525 argv = NULL;
9ed0fac8 526 m_nPrintMode = wxPRINT_WINDOWS;
d88de032 527 m_exitOnFrameDelete = TRUE;
9ed0fac8 528 m_bAuto3D = TRUE;
468e327a 529 m_hMq = 0;
8df85a61 530} // end of wxApp::wxApp
d88de032
DW
531
532wxApp::~wxApp()
533{
8df85a61 534 //
d88de032 535 // Delete command-line args
8df85a61 536 //
039bec17 537#if wxUSE_UNICODE
8df85a61
DW
538 int i;
539
d88de032
DW
540 for (i = 0; i < argc; i++)
541 {
542 delete[] argv[i];
543 }
544 delete[] argv;
039bec17 545#endif
8df85a61 546} // end of wxApp::~wxApp
0e320a79
DW
547
548bool wxApp::Initialized()
549{
d88de032
DW
550 if (GetTopWindow())
551 return TRUE;
552 else
553 return FALSE;
8df85a61 554} // end of wxApp::Initialized
0e320a79 555
9ed0fac8
DW
556//
557// Get and process a message, returning FALSE if WM_QUIT
558// received (and also set the flag telling the app to exit the main loop)
559//
d88de032
DW
560bool wxApp::DoMessage()
561{
468e327a 562 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
9ed0fac8 563
468e327a 564 wxUsleep(10000);
9ed0fac8 565 if (bRc == 0)
d88de032
DW
566 {
567 // got WM_QUIT
9ed0fac8 568 m_bKeepGoing = FALSE;
d88de032
DW
569 return FALSE;
570 }
9ed0fac8 571 else if (bRc == -1)
d88de032
DW
572 {
573 // should never happen, but let's test for it nevertheless
574 wxLogLastError("GetMessage");
575 }
576 else
577 {
578#if wxUSE_THREADS
9ed0fac8
DW
579 wxASSERT_MSG( wxThread::IsMain()
580 ,wxT("only the main thread can process Windows messages")
581 );
d88de032 582
9ed0fac8
DW
583 static bool sbHadGuiLock = TRUE;
584 static wxMsgArray svSavedMessages;
d88de032 585
9ed0fac8 586 //
8df85a61 587 // If a secondary thread owns is doing GUI calls, save all messages for
d88de032
DW
588 // later processing - we can't process them right now because it will
589 // lead to recursive library calls (and we're not reentrant)
9ed0fac8
DW
590 //
591 if (!wxGuiOwnedByMainThread())
d88de032 592 {
9ed0fac8 593 sbHadGuiLock = FALSE;
d88de032 594
8df85a61
DW
595 //
596 // Leave out WM_COMMAND messages: too dangerous, sometimes
d88de032 597 // the message will be processed twice
8df85a61 598 //
d88de032 599 if ( !wxIsWaitingForThread() ||
9ed0fac8 600 svCurrentMsg.msg != WM_COMMAND )
d88de032 601 {
9ed0fac8 602 svSavedMessages.Add(svCurrentMsg);
d88de032 603 }
d88de032
DW
604 return TRUE;
605 }
606 else
607 {
9ed0fac8 608 //
8df85a61 609 // Have we just regained the GUI lock? if so, post all of the saved
d88de032
DW
610 // messages
611 //
9ed0fac8 612 if (!sbHadGuiLock )
d88de032 613 {
9ed0fac8 614 sbHadGuiLock = TRUE;
d88de032 615
9ed0fac8
DW
616 size_t nCount = svSavedMessages.Count();
617
618 for (size_t n = 0; n < nCount; n++)
d88de032 619 {
9ed0fac8 620 QMSG vMsg = svSavedMessages[n];
d88de032 621
9ed0fac8 622 if ( !ProcessMessage((WXMSG *)&vMsg) )
d88de032 623 {
43543d98 624 ::WinDispatchMsg(vHabmain, &vMsg);
d88de032
DW
625 }
626 }
9ed0fac8 627 svSavedMessages.Empty();
d88de032
DW
628 }
629 }
d88de032
DW
630#endif // wxUSE_THREADS
631
632 // Process the message
468e327a 633 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
d88de032 634 {
43543d98 635 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
d88de032 636 }
d88de032 637 }
d88de032 638 return TRUE;
8df85a61 639} // end of wxApp::DoMessage
d88de032 640
9ed0fac8
DW
641//////////////////////////////////////////////////////////////////////////////
642//
643// Keep trying to process messages until WM_QUIT
644// received.
645//
646// If there are messages to be processed, they will all be
647// processed and OnIdle will not be called.
648// When there are no more messages, OnIdle is called.
649// If OnIdle requests more time,
650// it will be repeatedly called so long as there are no pending messages.
651// A 'feature' of this is that once OnIdle has decided that no more processing
652// is required, then it won't get processing time until further messages
653// are processed (it'll sit in DoMessage).
654//
655//////////////////////////////////////////////////////////////////////////////
0e320a79
DW
656int wxApp::MainLoop()
657{
9ed0fac8 658 m_bKeepGoing = TRUE;
d88de032 659
9ed0fac8 660 while (m_bKeepGoing)
d88de032
DW
661 {
662#if wxUSE_THREADS
663 wxMutexGuiLeaveOrEnter();
664#endif // wxUSE_THREADS
8df85a61 665 while (!Pending() && ProcessIdle())
d88de032 666 {
468e327a 667 wxUsleep(10000);
d88de032 668 }
d88de032
DW
669 DoMessage();
670 }
9ed0fac8 671 return (int)svCurrentMsg.mp1;
8df85a61 672} // end of wxApp::MainLoop
0e320a79 673
9ed0fac8 674//
0e320a79 675// Returns TRUE if more time is needed.
9ed0fac8 676//
0e320a79
DW
677bool wxApp::ProcessIdle()
678{
9ed0fac8 679 wxIdleEvent vEvent;
0e320a79 680
9ed0fac8
DW
681 vEvent.SetEventObject(this);
682 ProcessEvent(vEvent);
683 return vEvent.MoreRequested();
8df85a61 684} // end of wxApp::ProcessIdle
d88de032 685
0e320a79
DW
686void wxApp::ExitMainLoop()
687{
9ed0fac8 688 m_bKeepGoing = FALSE;
0e320a79
DW
689}
690
0e320a79
DW
691bool wxApp::Pending()
692{
43543d98 693 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
0e320a79
DW
694}
695
0e320a79
DW
696void wxApp::Dispatch()
697{
d88de032 698 DoMessage();
0e320a79
DW
699}
700
9ed0fac8
DW
701//////////////////////////////////////////////////////////////////////////////
702//
703// Give all windows a chance to preprocess
704// the message. Some may have accelerator tables, or have
705// MDI complications.
706//
707//////////////////////////////////////////////////////////////////////////////
708bool wxApp::ProcessMessage(
709 WXMSG* pWxmsg
710)
0e320a79 711{
9ed0fac8
DW
712 QMSG* vMsg = (PQMSG)pWxmsg;
713 HWND hWnd = vMsg->hwnd;
714 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
715 wxWindow* pWnd;
d88de032 716
8df85a61
DW
717#if wxUSE_TOOLTIPS
718 //
719 // We must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
720 // popup the tooltip bubbles
721 //
722 if (pWndThis && (vMsg->msg == WM_MOUSEMOVE))
723 {
724 wxToolTip* pToolTip = pWndThis->GetToolTip();
725 if (pToolTip)
726 {
727 pToolTip->RelayEvent(pWxmsg);
728 }
729 }
730#endif // wxUSE_TOOLTIPS
731
9ed0fac8 732 //
8df85a61 733 // For some composite controls (like a combobox), wndThis might be NULL
d88de032
DW
734 // because the subcontrol is not a wxWindow, but only the control itself
735 // is - try to catch this case
9ed0fac8
DW
736 //
737 while (hWnd && !pWndThis)
d88de032 738 {
9ed0fac8
DW
739 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
740 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
d88de032 741 }
0e320a79 742
8df85a61 743 //
d88de032 744 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 745 //
9ed0fac8 746 for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
d88de032 747 {
9ed0fac8 748 if (pWnd->OS2ProcessMessage(pWxmsg))
d88de032
DW
749 return TRUE;
750 }
d88de032 751 return FALSE;
8df85a61 752} // end of wxApp::ProcessMessage
0e320a79 753
9ed0fac8
DW
754void wxApp::OnIdle(
755 wxIdleEvent& rEvent
756)
d88de032 757{
9ed0fac8 758 static bool sbInOnIdle = FALSE;
d88de032 759
9ed0fac8 760 //
d88de032 761 // Avoid recursion (via ProcessEvent default case)
9ed0fac8
DW
762 //
763 if (sbInOnIdle )
d88de032 764 return;
0e320a79 765
9ed0fac8 766 sbInOnIdle = TRUE;
0e320a79 767
8df85a61
DW
768 //
769 // If there are pending events, we must process them: pending events
770 // are either events to the threads other than main or events posted
771 // with wxPostEvent() functions
772 //
773 ProcessPendingEvents();
774
9ed0fac8 775 //
d88de032 776 // 'Garbage' collection of windows deleted with Close().
9ed0fac8 777 //
d88de032 778 DeletePendingObjects();
0e320a79 779
d88de032 780#if wxUSE_LOG
8df85a61
DW
781 //
782 // Flush the logged messages if any
783 //
784 wxLog::FlushActive();
d88de032 785#endif // wxUSE_LOG
0e320a79 786
8df85a61 787 //
d88de032 788 // Send OnIdle events to all windows
8df85a61 789 //
9ed0fac8 790 if (SendIdleEvents())
d88de032 791 {
9ed0fac8 792 //
d88de032
DW
793 // SendIdleEvents() returns TRUE if at least one window requested more
794 // idle events
9ed0fac8
DW
795 //
796 rEvent.RequestMore(TRUE);
d88de032 797 }
9ed0fac8 798 sbInOnIdle = FALSE;
8df85a61 799} // end of wxApp::OnIdle
9779893b 800
0e320a79
DW
801// Send idle event to all top-level windows
802bool wxApp::SendIdleEvents()
803{
9ed0fac8
DW
804 bool bNeedMore = FALSE;
805 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
d88de032 806
9ed0fac8 807 while (pNode)
d88de032 808 {
9ed0fac8 809 wxWindow* pWin = pNode->GetData();
0e320a79 810
9ed0fac8
DW
811 if (SendIdleEvents(pWin))
812 bNeedMore = TRUE;
813 pNode = pNode->GetNext();
814 }
815 return bNeedMore;
8df85a61 816} // end of wxApp::SendIdleEvents
0e320a79 817
9ed0fac8 818//
0e320a79 819// Send idle event to window and all subwindows
9ed0fac8
DW
820//
821bool wxApp::SendIdleEvents(
822 wxWindow* pWin
823)
0e320a79 824{
9ed0fac8
DW
825 bool bNeedMore = FALSE;
826 wxIdleEvent vEvent;
827
828 vEvent.SetEventObject(pWin);
829 pWin->GetEventHandler()->ProcessEvent(vEvent);
0e320a79 830
9ed0fac8
DW
831 if (vEvent.MoreRequested())
832 bNeedMore = TRUE;
0e320a79 833
9ed0fac8 834 wxNode* pNode = pWin->GetChildren().First();
0e320a79 835
9ed0fac8 836 while (pNode)
d88de032 837 {
9ed0fac8 838 wxWindow* pWin = (wxWindow*) pNode->Data();
0e320a79 839
9ed0fac8
DW
840 if (SendIdleEvents(pWin))
841 bNeedMore = TRUE;
842 pNode = pNode->Next();
d88de032 843 }
9ed0fac8 844 return bNeedMore;
8df85a61 845} // end of wxApp::SendIdleEvents
0e320a79
DW
846
847void wxApp::DeletePendingObjects()
848{
9ed0fac8
DW
849 wxNode* pNode = wxPendingDelete.First();
850
851 while (pNode)
d88de032 852 {
9ed0fac8 853 wxObject* pObj = (wxObject *)pNode->Data();
77cd51c3 854
9ed0fac8 855 delete pObj;
0e320a79 856
9ed0fac8
DW
857 if (wxPendingDelete.Member(pObj))
858 delete pNode;
0e320a79 859
9ed0fac8 860 //
d88de032
DW
861 // Deleting one object may have deleted other pending
862 // objects, so start from beginning of list again.
9ed0fac8
DW
863 //
864 pNode = wxPendingDelete.First();
d88de032 865 }
8df85a61 866} // end of wxApp::DeletePendingObjects
0e320a79 867
9ed0fac8
DW
868void wxApp::OnEndSession(
869 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 870{
d88de032
DW
871 if (GetTopWindow())
872 GetTopWindow()->Close(TRUE);
8df85a61 873} // end of wxApp::OnEndSession
0e320a79 874
9ed0fac8 875//
d88de032
DW
876// Default behaviour: close the application with prompts. The
877// user can veto the close, and therefore the end session.
9ed0fac8
DW
878//
879void wxApp::OnQueryEndSession(
880 wxCloseEvent& rEvent
881)
0e320a79 882{
d88de032
DW
883 if (GetTopWindow())
884 {
9ed0fac8
DW
885 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
886 rEvent.Veto(TRUE);
d88de032 887 }
8df85a61 888} // end of wxApp::OnQueryEndSession
0e320a79
DW
889
890void wxExit()
891{
d88de032
DW
892 wxLogError(_("Fatal error: exiting"));
893
894 wxApp::CleanUp();
ee453a16 895} // end of wxExit
0e320a79 896
8df85a61 897//
d88de032 898// Yield to incoming messages
8df85a61 899//
0e320a79
DW
900bool wxYield()
901{
9dea36ef 902 HAB vHab = 0;
dde11e60 903 QMSG vMsg;
ee453a16 904
8df85a61
DW
905 //
906 // Disable log flushing from here because a call to wxYield() shouldn't
907 // normally result in message boxes popping up &c
908 //
909 wxLog::Suspend();
910
911 //
d88de032
DW
912 // We want to go back to the main message loop
913 // if we see a WM_QUIT. (?)
8df85a61 914 //
dde11e60 915 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 916 {
8df85a61
DW
917#if wxUSE_THREADS
918 wxMutexGuiLeaveOrEnter();
919#endif // wxUSE_THREADS
dde11e60 920 if (!wxTheApp->DoMessage())
d88de032
DW
921 break;
922 }
8df85a61 923 //
d88de032 924 // If they are pending events, we must process them.
8df85a61
DW
925 //
926 if (wxTheApp)
927 wxTheApp->ProcessPendingEvents();
928
929 //
930 // Let the logs be flashed again
931 //
932 wxLog::Resume();
d88de032 933 return TRUE;
8df85a61 934} // end of wxYield
d88de032 935
9ed0fac8
DW
936wxIcon wxApp::GetStdIcon(
937 int nWhich
938) const
d88de032 939{
9ed0fac8 940 switch(nWhich)
d88de032
DW
941 {
942 case wxICON_INFORMATION:
943 return wxIcon("wxICON_INFO");
944
945 case wxICON_QUESTION:
946 return wxIcon("wxICON_QUESTION");
947
948 case wxICON_EXCLAMATION:
949 return wxIcon("wxICON_WARNING");
950
951 default:
952 wxFAIL_MSG(wxT("requested non existent standard icon"));
953 // still fall through
954
955 case wxICON_HAND:
956 return wxIcon("wxICON_ERROR");
957 }
d88de032 958 return wxIcon("wxICON_ERROR");
8df85a61
DW
959} // end of wxApp::GetStdIcon
960
961//-----------------------------------------------------------------------------
962// wxWakeUpIdle
963//-----------------------------------------------------------------------------
964
965void wxWakeUpIdle()
966{
967 //
968 // Send the top window a dummy message so idle handler processing will
969 // start up again. Doing it this way ensures that the idle handler
970 // wakes up in the right thread (see also wxWakeUpMainThread() which does
971 // the same for the main app thread only)
972 //
973 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
974
975 if (pTopWindow)
976 {
977 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
978 {
979 //
980 // Should never happen
981 //
982 wxLogLastError("PostMessage(WM_NULL)");
983 }
984 }
985} // end of wxWakeUpIdle
d88de032 986
76990f63 987HAB wxGetInstance()
d88de032 988{
76990f63 989 return vHabmain;
d88de032
DW
990}
991
76990f63
DW
992void wxSetInstance(
993 HAB vHab
994)
d88de032 995{
76990f63 996 vHabmain = vHab;
0e320a79
DW
997}
998