]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
attempt to fix crash in tree ctrl
[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
e604d44b 187 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT | CS_FRAME
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
e604d44b
DW
654 while (!Pending() && ProcessIdle())
655 {
656// wxUsleep(10000);
657 }
658 DoMessage();
d88de032 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
f09d8a3b
DW
734 // a translation table. OS/2 has case sensative accels, so
735 // this block, coded by BK, removes that and helps make them
736 // case insensative.
f6bcfd97 737 //
f09d8a3b 738 if(pMsg->msg == WM_CHAR)
f6bcfd97 739 {
f09d8a3b
DW
740 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
741 USHORT uSch = CHARMSG(pChmsg)->chr;
742 bool bRc;
743
744 //
745 // Do not process keyup events
746 //
747 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
748 {
749 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
f1f22049 750 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
f09d8a3b
DW
751
752 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
753 {
3210d001 754 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
f09d8a3b
DW
755 break;
756 }
757 if(!bRc) // untranslated, should restore original value
758 CHARMSG(pChmsg)->chr = uSch;
759 }
f6bcfd97 760 }
8df85a61 761 //
d88de032 762 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 763 //
e604d44b
DW
764// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
765// {
766// if (pWnd->OS2ProcessMessage(pWxmsg))
767// return TRUE;
768// }
d88de032 769 return FALSE;
8df85a61 770} // end of wxApp::ProcessMessage
0e320a79 771
9ed0fac8
DW
772void wxApp::OnIdle(
773 wxIdleEvent& rEvent
774)
d88de032 775{
9ed0fac8 776 static bool sbInOnIdle = FALSE;
d88de032 777
9ed0fac8 778 //
d88de032 779 // Avoid recursion (via ProcessEvent default case)
9ed0fac8
DW
780 //
781 if (sbInOnIdle )
d88de032 782 return;
0e320a79 783
9ed0fac8 784 sbInOnIdle = TRUE;
0e320a79 785
8df85a61
DW
786 //
787 // If there are pending events, we must process them: pending events
788 // are either events to the threads other than main or events posted
789 // with wxPostEvent() functions
790 //
791 ProcessPendingEvents();
792
9ed0fac8 793 //
d88de032 794 // 'Garbage' collection of windows deleted with Close().
9ed0fac8 795 //
d88de032 796 DeletePendingObjects();
0e320a79 797
d88de032 798#if wxUSE_LOG
8df85a61
DW
799 //
800 // Flush the logged messages if any
801 //
802 wxLog::FlushActive();
d88de032 803#endif // wxUSE_LOG
0e320a79 804
8df85a61 805 //
d88de032 806 // Send OnIdle events to all windows
8df85a61 807 //
9ed0fac8 808 if (SendIdleEvents())
d88de032 809 {
9ed0fac8 810 //
d88de032
DW
811 // SendIdleEvents() returns TRUE if at least one window requested more
812 // idle events
9ed0fac8
DW
813 //
814 rEvent.RequestMore(TRUE);
d88de032 815 }
9ed0fac8 816 sbInOnIdle = FALSE;
8df85a61 817} // end of wxApp::OnIdle
9779893b 818
0e320a79
DW
819// Send idle event to all top-level windows
820bool wxApp::SendIdleEvents()
821{
9ed0fac8
DW
822 bool bNeedMore = FALSE;
823 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
d88de032 824
9ed0fac8 825 while (pNode)
d88de032 826 {
9ed0fac8 827 wxWindow* pWin = pNode->GetData();
0e320a79 828
9ed0fac8
DW
829 if (SendIdleEvents(pWin))
830 bNeedMore = TRUE;
831 pNode = pNode->GetNext();
832 }
833 return bNeedMore;
8df85a61 834} // end of wxApp::SendIdleEvents
0e320a79 835
9ed0fac8 836//
0e320a79 837// Send idle event to window and all subwindows
9ed0fac8
DW
838//
839bool wxApp::SendIdleEvents(
840 wxWindow* pWin
841)
0e320a79 842{
9ed0fac8
DW
843 bool bNeedMore = FALSE;
844 wxIdleEvent vEvent;
845
846 vEvent.SetEventObject(pWin);
847 pWin->GetEventHandler()->ProcessEvent(vEvent);
0e320a79 848
9ed0fac8
DW
849 if (vEvent.MoreRequested())
850 bNeedMore = TRUE;
0e320a79 851
9ed0fac8 852 wxNode* pNode = pWin->GetChildren().First();
0e320a79 853
9ed0fac8 854 while (pNode)
d88de032 855 {
9ed0fac8 856 wxWindow* pWin = (wxWindow*) pNode->Data();
0e320a79 857
9ed0fac8
DW
858 if (SendIdleEvents(pWin))
859 bNeedMore = TRUE;
860 pNode = pNode->Next();
d88de032 861 }
9ed0fac8 862 return bNeedMore;
8df85a61 863} // end of wxApp::SendIdleEvents
0e320a79
DW
864
865void wxApp::DeletePendingObjects()
866{
9ed0fac8
DW
867 wxNode* pNode = wxPendingDelete.First();
868
869 while (pNode)
d88de032 870 {
9ed0fac8 871 wxObject* pObj = (wxObject *)pNode->Data();
77cd51c3 872
9ed0fac8 873 delete pObj;
0e320a79 874
9ed0fac8
DW
875 if (wxPendingDelete.Member(pObj))
876 delete pNode;
0e320a79 877
9ed0fac8 878 //
d88de032
DW
879 // Deleting one object may have deleted other pending
880 // objects, so start from beginning of list again.
9ed0fac8
DW
881 //
882 pNode = wxPendingDelete.First();
d88de032 883 }
8df85a61 884} // end of wxApp::DeletePendingObjects
0e320a79 885
9ed0fac8
DW
886void wxApp::OnEndSession(
887 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 888{
d88de032
DW
889 if (GetTopWindow())
890 GetTopWindow()->Close(TRUE);
8df85a61 891} // end of wxApp::OnEndSession
0e320a79 892
9ed0fac8 893//
d88de032
DW
894// Default behaviour: close the application with prompts. The
895// user can veto the close, and therefore the end session.
9ed0fac8
DW
896//
897void wxApp::OnQueryEndSession(
898 wxCloseEvent& rEvent
899)
0e320a79 900{
d88de032
DW
901 if (GetTopWindow())
902 {
9ed0fac8
DW
903 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
904 rEvent.Veto(TRUE);
d88de032 905 }
8df85a61 906} // end of wxApp::OnQueryEndSession
0e320a79
DW
907
908void wxExit()
909{
d88de032
DW
910 wxLogError(_("Fatal error: exiting"));
911
912 wxApp::CleanUp();
ee453a16 913} // end of wxExit
0e320a79 914
8df85a61 915//
d88de032 916// Yield to incoming messages
8df85a61 917//
0e320a79
DW
918bool wxYield()
919{
9dea36ef 920 HAB vHab = 0;
dde11e60 921 QMSG vMsg;
ee453a16 922
8df85a61
DW
923 //
924 // Disable log flushing from here because a call to wxYield() shouldn't
925 // normally result in message boxes popping up &c
926 //
927 wxLog::Suspend();
928
929 //
d88de032
DW
930 // We want to go back to the main message loop
931 // if we see a WM_QUIT. (?)
8df85a61 932 //
dde11e60 933 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 934 {
8df85a61
DW
935#if wxUSE_THREADS
936 wxMutexGuiLeaveOrEnter();
937#endif // wxUSE_THREADS
dde11e60 938 if (!wxTheApp->DoMessage())
d88de032
DW
939 break;
940 }
8df85a61 941 //
d88de032 942 // If they are pending events, we must process them.
8df85a61
DW
943 //
944 if (wxTheApp)
945 wxTheApp->ProcessPendingEvents();
946
947 //
948 // Let the logs be flashed again
949 //
950 wxLog::Resume();
d88de032 951 return TRUE;
8df85a61 952} // end of wxYield
d88de032 953
9ed0fac8
DW
954wxIcon wxApp::GetStdIcon(
955 int nWhich
956) const
d88de032 957{
9ed0fac8 958 switch(nWhich)
d88de032
DW
959 {
960 case wxICON_INFORMATION:
961 return wxIcon("wxICON_INFO");
962
963 case wxICON_QUESTION:
964 return wxIcon("wxICON_QUESTION");
965
966 case wxICON_EXCLAMATION:
967 return wxIcon("wxICON_WARNING");
968
969 default:
970 wxFAIL_MSG(wxT("requested non existent standard icon"));
971 // still fall through
972
973 case wxICON_HAND:
974 return wxIcon("wxICON_ERROR");
975 }
d88de032 976 return wxIcon("wxICON_ERROR");
8df85a61
DW
977} // end of wxApp::GetStdIcon
978
979//-----------------------------------------------------------------------------
980// wxWakeUpIdle
981//-----------------------------------------------------------------------------
982
983void wxWakeUpIdle()
984{
985 //
986 // Send the top window a dummy message so idle handler processing will
987 // start up again. Doing it this way ensures that the idle handler
988 // wakes up in the right thread (see also wxWakeUpMainThread() which does
989 // the same for the main app thread only)
990 //
991 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
992
993 if (pTopWindow)
994 {
995 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
996 {
997 //
998 // Should never happen
999 //
1000 wxLogLastError("PostMessage(WM_NULL)");
1001 }
1002 }
1003} // end of wxWakeUpIdle
d88de032 1004
76990f63 1005HAB wxGetInstance()
d88de032 1006{
76990f63 1007 return vHabmain;
d88de032
DW
1008}
1009
76990f63
DW
1010void wxSetInstance(
1011 HAB vHab
1012)
d88de032 1013{
76990f63 1014 vHabmain = vHab;
0e320a79
DW
1015}
1016