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