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