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