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