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