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