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