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