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