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