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