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