]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
wxFontEnumerator mostly works for wxMSW
[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
42 // define the array of MSG strutures
43// TODO: WX_DECLARE_OBJARRAY(MSG, wxMsgArray);
44
45 #include "wx/arrimpl.cpp"
46
47// TODO: WX_DEFINE_OBJARRAY(wxMsgArray);
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
61extern wxChar *wxBuffer;
62extern wxChar *wxOsVersion;
63extern wxList *wxWinHandleList;
64extern wxList WXDLLEXPORT wxPendingDelete;
65#if wxUSE_THREADS
66extern wxList *wxPendingEvents;
67extern wxCriticalSection *wxPendingEventsLocker;
68#endif
69extern void wxSetKeyboardHook(bool doIt);
70extern wxCursor *g_globalCursor;
0e320a79 71
d88de032
DW
72HINSTANCE wxhInstance = 0;
73// TODO: MSG s_currentMsg;
0e320a79
DW
74wxApp *wxTheApp = NULL;
75
d88de032
DW
76// FIXME why not const? and not static?
77
78// NB: all "NoRedraw" classes must have the same names as the "normal" classes
79// with NR suffix - wxWindow::MSWCreate() supposes this
80wxChar wxFrameClassName[] = wxT("wxFrameClass");
81wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
82wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
83wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
84wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
85wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
86wxChar wxPanelClassName[] = wxT("wxPanelClass");
87wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
88
89HICON wxSTD_FRAME_ICON = (HICON) NULL;
90HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
91HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
92
93HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
94HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
95HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
96
97HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
98
99MRESULT wxWndProc(HWND, UINT, MPARAM, MPARAM);
100
101// ===========================================================================
102// implementation
103// ===========================================================================
104
105// ---------------------------------------------------------------------------
106// wxApp
107// ---------------------------------------------------------------------------
108
0e320a79 109#if !USE_SHARED_LIBRARY
d88de032 110 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
0e320a79 111
d88de032
DW
112 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
113 EVT_IDLE(wxApp::OnIdle)
114 EVT_END_SESSION(wxApp::OnEndSession)
115 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
116 END_EVENT_TABLE()
117#endif
0e320a79 118
d88de032 119//// Initialize
0e320a79
DW
120bool wxApp::Initialize()
121{
d88de032
DW
122 // Some people may wish to use this, but
123 // probably it shouldn't be here by default.
124#ifdef __WXDEBUG__
125 // wxRedirectIOToConsole();
0e320a79
DW
126#endif
127
d88de032 128 wxBuffer = new wxChar[1500]; // FIXME
0e320a79 129
d88de032 130 wxClassInfo::InitializeClasses();
0e320a79 131
d88de032
DW
132#if wxUSE_RESOURCES
133 wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
134#endif
135
136 // I'm annoyed ... I don't know where to put this and I don't want to
137 // create a module for that as it's part of the core.
138#if wxUSE_THREADS
139 wxPendingEvents = new wxList();
140 wxPendingEventsLocker = new wxCriticalSection();
141#endif
142
143 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
144 wxTheColourDatabase->Initialize();
145
146 wxInitializeStockLists();
147 wxInitializeStockObjects();
0e320a79
DW
148
149#if wxUSE_WX_RESOURCES
d88de032 150 wxInitializeResourceSystem();
0e320a79
DW
151#endif
152
d88de032
DW
153 wxBitmap::InitStandardHandlers();
154
155 g_globalCursor = new wxCursor;
156
157// TODO:
158/*
159 wxSTD_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_FRAME"));
160 wxSTD_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_MDIPARENTFRAME"));
161 wxSTD_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_MDICHILDFRAME"));
162
163 wxDEFAULT_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_FRAME"));
164 wxDEFAULT_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_MDIPARENTFRAME"));
165 wxDEFAULT_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_MDICHILDFRAME"));
166*/
167 RegisterWindowClasses();
168
169 // Create the brush for disabling bitmap buttons
170// TODO:
171/*
172 LOGBRUSH lb;
173 lb.lbStyle = BS_PATTERN;
174 lb.lbHatch = (int)LoadBitmap( wxhInstance, wxT("wxDISABLE_BUTTON_BITMAP") );
175 if ( lb.lbHatch )
176 {
177 wxDisableButtonBrush = ::CreateBrushIndirect( & lb );
178 ::DeleteObject( (HGDIOBJ)lb.lbHatch );
179 }
180 */
181 //else: wxWindows resources are probably not linked in
182
183 wxWinHandleList = new wxList(wxKEY_INTEGER);
184
185 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
186 // PLEASE DO NOT ALTER THIS.
187#if !defined(WXMAKINGDLL)
188 extern char wxDummyChar;
189 if (wxDummyChar) wxDummyChar++;
190#endif
191
192 wxSetKeyboardHook(TRUE);
193
194 wxModule::RegisterModules();
195 if (!wxModule::InitializeModules())
196 return FALSE;
197 return TRUE;
198}
199
200// ---------------------------------------------------------------------------
201// RegisterWindowClasses
202// ---------------------------------------------------------------------------
203
204// TODO we should only register classes really used by the app. For this it
205// would be enough to just delay the class registration until an attempt
206// to create a window of this class is made.
207bool wxApp::RegisterWindowClasses()
208{
209// TODO:
210/*
211 WNDCLASS wndclass;
212
213 // for each class we register one with CS_(V|H)REDRAW style and one
214 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
215 static const long styleNormal = 0; // TODO: CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
216 static const long styleNoRedraw = 0; // TODO: CS_DBLCLKS;
217
218 // the fields which are common to all classes
219 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
220 wndclass.cbClsExtra = 0;
221 wndclass.cbWndExtra = sizeof( DWORD ); // VZ: what is this DWORD used for?
222 wndclass.hInstance = wxhInstance;
223 wndclass.hIcon = (HICON) NULL;
224 wndclass.hCursor = 0; // TODO: ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
225 wndclass.lpszMenuName = NULL;
226
227 // Register the frame window class.
228 wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
229 wndclass.lpszClassName = wxFrameClassName;
230 wndclass.style = styleNormal;
231
232 if ( !RegisterClass(&wndclass) )
233 {
234 wxLogLastError("RegisterClass(frame)");
235
236 return FALSE;
237 }
238
239 // "no redraw" frame
240 wndclass.lpszClassName = wxFrameClassNameNoRedraw;
241 wndclass.style = styleNoRedraw;
242
243 if ( !RegisterClass(&wndclass) )
244 {
245 wxLogLastError("RegisterClass(no redraw frame)");
246
247 return FALSE;
248 }
249
250 // Register the MDI frame window class.
251 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
252 wndclass.lpszClassName = wxMDIFrameClassName;
253 wndclass.style = styleNormal;
254
255 if ( !RegisterClass(&wndclass) )
256 {
257 wxLogLastError("RegisterClass(MDI parent)");
258
259 return FALSE;
260 }
0e320a79 261
d88de032
DW
262 // "no redraw" MDI frame
263 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
264 wndclass.style = styleNoRedraw;
0e320a79 265
d88de032
DW
266 if ( !RegisterClass(&wndclass) )
267 {
268 wxLogLastError("RegisterClass(no redraw MDI parent frame)");
269
270 return FALSE;
271 }
272
273 // Register the MDI child frame window class.
274 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
275 wndclass.lpszClassName = wxMDIChildFrameClassName;
276 wndclass.style = styleNormal;
277
278 if ( !RegisterClass(&wndclass) )
279 {
280 wxLogLastError("RegisterClass(MDI child)");
281
282 return FALSE;
283 }
284
285 // "no redraw" MDI child frame
286 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
287 wndclass.style = styleNoRedraw;
288
289 if ( !RegisterClass(&wndclass) )
290 {
291 wxLogLastError("RegisterClass(no redraw MDI child)");
292
293 return FALSE;
294 }
295
296 // Register the panel window class.
297 wndclass.hbrBackground = (HBRUSH) GetStockObject( LTGRAY_BRUSH );
298 wndclass.lpszClassName = wxPanelClassName;
299 wndclass.style = styleNormal;
300
301 if ( !RegisterClass(&wndclass) )
302 {
303 wxLogLastError("RegisterClass(panel)");
304
305 return FALSE;
306 }
307
308 // Register the canvas and textsubwindow class name
309 wndclass.hbrBackground = (HBRUSH)NULL;
310 wndclass.lpszClassName = wxCanvasClassName;
311
312 if ( !RegisterClass(&wndclass) )
313 {
314 wxLogLastError("RegisterClass(canvas)");
315
316 return FALSE;
317 }
318*/
319 return TRUE;
0e320a79
DW
320}
321
d88de032
DW
322// ---------------------------------------------------------------------------
323// Convert Windows to argc, argv style
324// ---------------------------------------------------------------------------
325
326void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine)
327{
328 wxStringList args;
329
330 wxString cmdLine(lpCmdLine);
331 int count = 0;
332
333 // Get application name
334 wxChar name[260]; // 260 is MAX_PATH value from windef.h
335// TODO: ::GetModuleFileName(wxhInstance, name, WXSIZEOF(name));
336
337 args.Add(name);
338 count++;
339
340 wxStrcpy(name, wxFileNameFromPath(name));
341 wxStripExtension(name);
342 wxTheApp->SetAppName(name);
343
344 // Break up string
345 // Treat strings enclosed in double-quotes as single arguments
346 int i = 0;
347 int len = cmdLine.Length();
348 while (i < len)
349 {
350 // Skip whitespace
351 while ((i < len) && wxIsspace(cmdLine.GetChar(i)))
352 i ++;
353
354 if (i < len)
355 {
356 if (cmdLine.GetChar(i) == wxT('"')) // We found the start of a string
357 {
358 i ++;
359 int first = i;
360 while ((i < len) && (cmdLine.GetChar(i) != wxT('"')))
361 i ++;
362
363 wxString arg(cmdLine.Mid(first, (i - first)));
364
365 args.Add(arg);
366 count ++;
367
368 if (i < len)
369 i ++; // Skip past 2nd quote
370 }
371 else // Unquoted argument
372 {
373 int first = i;
374 while ((i < len) && !wxIsspace(cmdLine.GetChar(i)))
375 i ++;
376
377 wxString arg(cmdLine.Mid(first, (i - first)));
378
379 args.Add(arg);
380 count ++;
381 }
382 }
383 }
384
385 wxTheApp->argv = new wxChar*[count + 1];
386 for (i = 0; i < count; i++)
387 {
388 wxString arg(args[i]);
389 wxTheApp->argv[i] = copystring((const wxChar*)arg);
390 }
391 wxTheApp->argv[count] = NULL; // argv[] is a NULL-terminated list
392 wxTheApp->argc = count;
393}
394
395//// Cleans up any wxWindows internal structures left lying around
396
0e320a79
DW
397void wxApp::CleanUp()
398{
d88de032
DW
399 //// COMMON CLEANUP
400
401#if wxUSE_LOG
402 // flush the logged messages if any and install a 'safer' log target: the
403 // default one (wxLogGui) can't be used after the resources are freed just
404 // below and the user suppliedo ne might be even more unsafe (using any
405 // wxWindows GUI function is unsafe starting from now)
406 wxLog::DontCreateOnDemand();
407
408 // this will flush the old messages if any
409 delete wxLog::SetActiveTarget(new wxLogStderr);
410#endif // wxUSE_LOG
411
412 // One last chance for pending objects to be cleaned up
413 wxTheApp->DeletePendingObjects();
414
415 wxModule::CleanUpModules();
0e320a79
DW
416
417#if wxUSE_WX_RESOURCES
d88de032 418 wxCleanUpResourceSystem();
0e320a79 419
d88de032
DW
420 // wxDefaultResourceTable->ClearTable();
421#endif
0e320a79 422
d88de032
DW
423 // Indicate that the cursor can be freed, so that cursor won't be deleted
424 // by deleting the bitmap list before g_globalCursor goes out of scope
425 // (double deletion of the cursor).
426 wxSetCursor(wxNullCursor);
427 delete g_globalCursor;
428 g_globalCursor = NULL;
0e320a79 429
d88de032 430 wxDeleteStockObjects();
0e320a79 431
d88de032
DW
432 // Destroy all GDI lists, etc.
433 wxDeleteStockLists();
0e320a79 434
d88de032
DW
435 delete wxTheColourDatabase;
436 wxTheColourDatabase = NULL;
0e320a79 437
d88de032 438 wxBitmap::CleanUpHandlers();
0e320a79 439
d88de032
DW
440 delete[] wxBuffer;
441 wxBuffer = NULL;
0e320a79 442
d88de032 443 //// WINDOWS-SPECIFIC CLEANUP
0e320a79 444
d88de032
DW
445 wxSetKeyboardHook(FALSE);
446// TODO:
447/*
448 if (wxSTD_FRAME_ICON)
449 DestroyIcon(wxSTD_FRAME_ICON);
450 if (wxSTD_MDICHILDFRAME_ICON)
451 DestroyIcon(wxSTD_MDICHILDFRAME_ICON);
452 if (wxSTD_MDIPARENTFRAME_ICON)
453 DestroyIcon(wxSTD_MDIPARENTFRAME_ICON);
454
455 if (wxDEFAULT_FRAME_ICON)
456 DestroyIcon(wxDEFAULT_FRAME_ICON);
457 if (wxDEFAULT_MDICHILDFRAME_ICON)
458 DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON);
459 if (wxDEFAULT_MDIPARENTFRAME_ICON)
460 DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
461*/
462 if ( wxDisableButtonBrush )
463 {
464// TODO: ::DeleteObject( wxDisableButtonBrush );
465 }
466
467 if (wxWinHandleList)
468 delete wxWinHandleList;
469
470 // GL: I'm annoyed ... I don't know where to put this and I don't want to
471 // create a module for that as it's part of the core.
472#if wxUSE_THREADS
473 delete wxPendingEvents;
474 delete wxPendingEventsLocker;
475 // If we don't do the following, we get an apparent memory leak.
476 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
477#endif
0e320a79 478
d88de032 479 wxClassInfo::CleanUpClasses();
0e320a79 480
d88de032
DW
481 delete wxTheApp;
482 wxTheApp = NULL;
77cd51c3 483
0e320a79 484#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
d88de032
DW
485 // At this point we want to check if there are any memory
486 // blocks that aren't part of the wxDebugContext itself,
487 // as a special case. Then when dumping we need to ignore
488 // wxDebugContext, too.
489 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
490 {
491 wxLogDebug(wxT("There were memory leaks."));
492 wxDebugContext::Dump();
493 wxDebugContext::PrintStatistics();
494 }
495 // wxDebugContext::SetStream(NULL, NULL);
0e320a79 496#endif
77cd51c3 497
d88de032
DW
498#if wxUSE_LOG
499 // do it as the very last thing because everything else can log messages
500 delete wxLog::SetActiveTarget(NULL);
501#endif // wxUSE_LOG
0e320a79
DW
502}
503
d88de032 504#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
77cd51c3 505
d88de032
DW
506//// Main wxWindows entry point
507int wxEntry(WXHINSTANCE hInstance,
508 WXHINSTANCE WXUNUSED(hPrevInstance),
509 char *lpCmdLine,
510 int nCmdShow,
511 bool enterLoop)
512{
513 // do check for memory leaks on program exit
514 // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
515 // deallocated memory which may be used to simulate low-memory condition)
516// TODO: wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
517
518 // take everything into a try-except block in release build
519 // FIXME other compilers must support Win32 SEH (structured exception
520 // handling) too, just find the appropriate keyword in their docs!
521 // Please note that it's _not_ the same as C++ exceptions!
522
523 wxhInstance = (HINSTANCE) hInstance;
524
525 if (!wxApp::Initialize())
526 return 0;
527
528 // create the application object or ensure that one already exists
529 if (!wxTheApp)
530 {
531 // The app may have declared a global application object, but we recommend
532 // the IMPLEMENT_APP macro is used instead, which sets an initializer
533 // function for delayed, dynamic app object construction.
534 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
535 wxT("No initializer - use IMPLEMENT_APP macro.") );
536
537 wxTheApp = (wxApp*)(*wxApp::GetInitializerFunction()) ();
538 }
539
540 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
541
542 // save the WinMain() parameters
543 wxTheApp->ConvertToStandardCommandArgs(lpCmdLine);
544 wxTheApp->m_nCmdShow = nCmdShow;
545
546 // GUI-specific initialisation. In fact on Windows we don't have any,
547 // but this call is provided for compatibility across platforms.
548 wxTheApp->OnInitGui();
549
550 int retValue = 0;
551
552 if ( wxTheApp->OnInit() )
553 {
554 if ( enterLoop )
555 {
556 retValue = wxTheApp->OnRun();
557 }
558 else
559 // We want to initialize, but not run or exit immediately.
560 return 1;
561 }
562 //else: app initialization failed, so we skipped OnRun()
563
564 wxWindow *topWindow = wxTheApp->GetTopWindow();
565 if ( topWindow )
566 {
567 // Forcibly delete the window.
568 if ( topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
569 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
570 {
571 topWindow->Close(TRUE);
572 wxTheApp->DeletePendingObjects();
573 }
574 else
575 {
576 delete topWindow;
577 wxTheApp->SetTopWindow(NULL);
578 }
579 }
580
581 wxTheApp->OnExit();
582
583 wxApp::CleanUp();
584
585 return retValue;
586}
77cd51c3 587
d88de032 588#else /* _WINDLL */
0e320a79 589
d88de032 590//// Entry point for DLLs
0e320a79 591
d88de032
DW
592int wxEntry(WXHINSTANCE hInstance)
593{
594 wxhInstance = (HINSTANCE) hInstance;
595 wxApp::Initialize();
0e320a79 596
d88de032
DW
597 // The app may have declared a global application object, but we recommend
598 // the IMPLEMENT_APP macro is used instead, which sets an initializer function
599 // for delayed, dynamic app object construction.
600 if (!wxTheApp)
601 {
602 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
603 "No initializer - use IMPLEMENT_APP macro." );
77cd51c3 604
d88de032
DW
605 wxTheApp = (* wxApp::GetInitializerFunction()) ();
606 }
0e320a79 607
d88de032 608 wxCHECK_MSG( wxTheApp, 0, "You have to define an instance of wxApp!" );
77cd51c3 609
d88de032
DW
610 wxTheApp->argc = 0;
611 wxTheApp->argv = NULL;
0e320a79 612
d88de032 613 wxTheApp->OnInitGui();
77cd51c3 614
d88de032 615 wxTheApp->OnInit();
77cd51c3 616
d88de032
DW
617 wxWindow *topWindow = wxTheApp->GetTopWindow();
618 if ( topWindow && topWindow->GetHWND())
619 {
620 topWindow->Show(TRUE);
621 }
77cd51c3 622
d88de032
DW
623 return 1;
624}
625#endif // _WINDLL
0e320a79 626
d88de032 627//// Static member initialization
0e320a79 628
d88de032 629wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
0e320a79
DW
630
631wxApp::wxApp()
632{
d88de032
DW
633 m_topWindow = NULL;
634 wxTheApp = this;
635 m_wantDebugOutput = TRUE;
636
637 argc = 0;
638 argv = NULL;
639 m_printMode = wxPRINT_WINDOWS;
640 m_exitOnFrameDelete = TRUE;
641 m_auto3D = TRUE;
642}
643
644wxApp::~wxApp()
645{
646 // Delete command-line args
647 int i;
648 for (i = 0; i < argc; i++)
649 {
650 delete[] argv[i];
651 }
652 delete[] argv;
0e320a79
DW
653}
654
655bool wxApp::Initialized()
656{
d88de032
DW
657#ifndef _WINDLL
658 if (GetTopWindow())
659 return TRUE;
660 else
661 return FALSE;
662#endif
663#ifdef _WINDLL // Assume initialized if DLL (no way of telling)
0e320a79 664 return TRUE;
d88de032 665#endif
0e320a79
DW
666}
667
d88de032
DW
668/*
669 * Get and process a message, returning FALSE if WM_QUIT
670 * received (and also set the flag telling the app to exit the main loop)
671 *
672 */
673bool wxApp::DoMessage()
674{
675 BOOL rc = FALSE; // TODO: ::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0);
676 if ( rc == 0 )
677 {
678 // got WM_QUIT
679 m_keepGoing = FALSE;
680
681 return FALSE;
682 }
683 else if ( rc == -1 )
684 {
685 // should never happen, but let's test for it nevertheless
686 wxLogLastError("GetMessage");
687 }
688 else
689 {
690#if wxUSE_THREADS
691 wxASSERT_MSG( wxThread::IsMain(),
692 wxT("only the main thread can process Windows messages") );
693
694 static bool s_hadGuiLock = TRUE;
695// TODO:
696/*
697 static wxMsgArray s_aSavedMessages;
698
699 // if a secondary thread owns is doing GUI calls, save all messages for
700 // later processing - we can't process them right now because it will
701 // lead to recursive library calls (and we're not reentrant)
702 if ( !wxGuiOwnedByMainThread() )
703 {
704 s_hadGuiLock = FALSE;
705
706 // leave out WM_COMMAND messages: too dangerous, sometimes
707 // the message will be processed twice
708 if ( !wxIsWaitingForThread() ||
709 s_currentMsg.message != WM_COMMAND )
710 {
711 s_aSavedMessages.Add(s_currentMsg);
712 }
713
714 return TRUE;
715 }
716 else
717 {
718 // have we just regained the GUI lock? if so, post all of the saved
719 // messages
720 //
721 // FIXME of course, it's not _exactly_ the same as processing the
722 // messages normally - expect some things to break...
723 if ( !s_hadGuiLock )
724 {
725 s_hadGuiLock = TRUE;
726
727 size_t count = s_aSavedMessages.Count();
728 for ( size_t n = 0; n < count; n++ )
729 {
730 MSG& msg = s_aSavedMessages[n];
731
732 if ( !ProcessMessage((WXMSG *)&msg) )
733 {
734 ::TranslateMessage(&msg);
735 ::DispatchMessage(&msg);
736 }
737 }
738 s_aSavedMessages.Empty();
739 }
740 }
741*/
742#endif // wxUSE_THREADS
743
744 // Process the message
745// TODO:
746/*
747 if ( !ProcessMessage((WXMSG *)&s_currentMsg) )
748 {
749 ::TranslateMessage(&s_currentMsg);
750 ::DispatchMessage(&s_currentMsg);
751 }
752*/
753 }
754
755 return TRUE;
756}
757
758/*
759 * Keep trying to process messages until WM_QUIT
760 * received.
761 *
762 * If there are messages to be processed, they will all be
763 * processed and OnIdle will not be called.
764 * When there are no more messages, OnIdle is called.
765 * If OnIdle requests more time,
766 * it will be repeatedly called so long as there are no pending messages.
767 * A 'feature' of this is that once OnIdle has decided that no more processing
768 * is required, then it won't get processing time until further messages
769 * are processed (it'll sit in DoMessage).
770 */
771
0e320a79
DW
772int wxApp::MainLoop()
773{
d88de032
DW
774 m_keepGoing = TRUE;
775
776 while ( m_keepGoing )
777 {
778#if wxUSE_THREADS
779 wxMutexGuiLeaveOrEnter();
780#endif // wxUSE_THREADS
781// TODO:
782/*
783 while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
784 ProcessIdle() )
785 {
786 }
0e320a79
DW
787*/
788
d88de032
DW
789 DoMessage();
790 }
791
792// TODO: return s_currentMsg.wParam;
793 return FALSE;
0e320a79
DW
794}
795
796// Returns TRUE if more time is needed.
797bool wxApp::ProcessIdle()
798{
799 wxIdleEvent event;
800 event.SetEventObject(this);
801 ProcessEvent(event);
802
803 return event.MoreRequested();
804}
805
d88de032
DW
806#if wxUSE_THREADS
807void wxApp::ProcessPendingEvents()
808{
809 wxNode *node = wxPendingEvents->First();
810 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
811
812 while (node)
813 {
814 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
815
816 handler->ProcessPendingEvents();
817
818 delete node;
819 node = wxPendingEvents->First();
820 }
821}
822#endif
823
824
0e320a79
DW
825void wxApp::ExitMainLoop()
826{
d88de032 827 m_keepGoing = FALSE;
0e320a79
DW
828}
829
0e320a79
DW
830bool wxApp::Pending()
831{
d88de032
DW
832// TODO: return (::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0);
833 return FALSE;
0e320a79
DW
834}
835
0e320a79
DW
836void wxApp::Dispatch()
837{
d88de032 838 DoMessage();
0e320a79
DW
839}
840
d88de032
DW
841/*
842 * Give all windows a chance to preprocess
843 * the message. Some may have accelerator tables, or have
844 * MDI complications.
845 */
846
847bool wxApp::ProcessMessage(WXMSG *wxmsg)
0e320a79 848{
d88de032
DW
849// TODO:
850/*
851 MSG *msg = (MSG *)wxmsg;
852 HWND hWnd = msg->hwnd;
853 wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd), *wnd;
854
855 // for some composite controls (like a combobox), wndThis might be NULL
856 // because the subcontrol is not a wxWindow, but only the control itself
857 // is - try to catch this case
858 while ( hWnd && !wndThis )
859 {
860 hWnd = 0; // TODO: ::GetParent(hWnd);
861 wndThis = wxFindWinFromHandle((WXHWND)hWnd);
862 }
0e320a79 863
d88de032
DW
864 // Try translations first; find the youngest window with
865 // a translation table.
866 for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
867 {
868 if ( wnd->OS2TranslateMessage(wxmsg) )
869 return TRUE;
870 }
0e320a79 871
d88de032
DW
872 // Anyone for a non-translation message? Try youngest descendants first.
873 for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
874 {
875 if ( wnd->OS2ProcessMessage(wxmsg) )
876 return TRUE;
877 }
878*/
879 return FALSE;
880}
0e320a79 881
d88de032
DW
882void wxApp::OnIdle(wxIdleEvent& event)
883{
884 static bool s_inOnIdle = FALSE;
885
886 // Avoid recursion (via ProcessEvent default case)
887 if ( s_inOnIdle )
888 return;
0e320a79 889
d88de032 890 s_inOnIdle = TRUE;
0e320a79 891
d88de032
DW
892 // 'Garbage' collection of windows deleted with Close().
893 DeletePendingObjects();
0e320a79 894
d88de032
DW
895#if wxUSE_LOG
896 // flush the logged messages if any
897 wxLog *pLog = wxLog::GetActiveTarget();
898 if ( pLog != NULL && pLog->HasPendingMessages() )
899 pLog->Flush();
900#endif // wxUSE_LOG
0e320a79 901
d88de032
DW
902 // Send OnIdle events to all windows
903 if ( SendIdleEvents() )
904 {
905 // SendIdleEvents() returns TRUE if at least one window requested more
906 // idle events
907 event.RequestMore(TRUE);
908 }
909
910 // If they are pending events, we must process them.
911#if wxUSE_THREADS
912 ProcessPendingEvents();
913#endif
914 s_inOnIdle = FALSE;
0e320a79
DW
915}
916
917// Send idle event to all top-level windows
918bool wxApp::SendIdleEvents()
919{
920 bool needMore = FALSE;
d88de032
DW
921
922 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
923 while (node)
924 {
925 wxWindow* win = node->GetData();
926 if (SendIdleEvents(win))
0e320a79 927 needMore = TRUE;
d88de032
DW
928 node = node->GetNext();
929 }
0e320a79 930
0e320a79
DW
931 return needMore;
932}
933
934// Send idle event to window and all subwindows
935bool wxApp::SendIdleEvents(wxWindow* win)
936{
937 bool needMore = FALSE;
938
d88de032
DW
939 wxIdleEvent event;
940 event.SetEventObject(win);
941 win->GetEventHandler()->ProcessEvent(event);
0e320a79
DW
942
943 if (event.MoreRequested())
944 needMore = TRUE;
945
d88de032
DW
946 wxNode* node = win->GetChildren().First();
947 while (node)
948 {
949 wxWindow* win = (wxWindow*) node->Data();
950 if (SendIdleEvents(win))
0e320a79
DW
951 needMore = TRUE;
952
d88de032
DW
953 node = node->Next();
954 }
955 return needMore;
0e320a79
DW
956}
957
958void wxApp::DeletePendingObjects()
959{
d88de032
DW
960 wxNode *node = wxPendingDelete.First();
961 while (node)
962 {
963 wxObject *obj = (wxObject *)node->Data();
77cd51c3 964
d88de032 965 delete obj;
0e320a79 966
d88de032
DW
967 if (wxPendingDelete.Member(obj))
968 delete node;
0e320a79 969
d88de032
DW
970 // Deleting one object may have deleted other pending
971 // objects, so start from beginning of list again.
972 node = wxPendingDelete.First();
973 }
0e320a79
DW
974}
975
d88de032 976void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
0e320a79 977{
d88de032
DW
978 if (GetTopWindow())
979 GetTopWindow()->Close(TRUE);
0e320a79
DW
980}
981
d88de032
DW
982// Default behaviour: close the application with prompts. The
983// user can veto the close, and therefore the end session.
984void wxApp::OnQueryEndSession(wxCloseEvent& event)
0e320a79 985{
d88de032
DW
986 if (GetTopWindow())
987 {
988 if (!GetTopWindow()->Close(!event.CanVeto()))
989 event.Veto(TRUE);
990 }
991}
992
993int wxApp::GetComCtl32Version() const
994{
995 // TODO: Does OS/2 even need this method?
996 /*
997 // have we loaded COMCTL32 yet?
998 HMODULE theModule = ::GetModuleHandle(wxT("COMCTL32"));
999 int version = 0;
1000
1001 // if so, then we can check for the version
1002 if (theModule)
1003 {
1004 // InitCommonControlsEx is unique to 4.7 and later
1005 FARPROC theProc = ::GetProcAddress(theModule, "InitCommonControlsEx");
1006
1007 if (! theProc)
1008 { // not found, must be 4.00
1009 version = 400;
1010 }
1011 else
1012 {
1013 // The following symbol are unique to 4.71
1014 // DllInstall
1015 // FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos
1016 // FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo
1017 // FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange
1018 // FlatSB_ShowScrollBar
1019 // _DrawIndirectImageList _DuplicateImageList
1020 // InitializeFlatSB
1021 // UninitializeFlatSB
1022 // we could check for any of these - I chose DllInstall
1023 FARPROC theProc = ::GetProcAddress(theModule, "DllInstall");
1024 if (! theProc)
1025 {
1026 // not found, must be 4.70
1027 version = 470;
1028 }
1029 else
1030 { // found, must be 4.71
1031 version = 471;
1032 }
1033 }
1034 }
1035 return version;
1036*/
1037 return 0;
0e320a79
DW
1038}
1039
1040void wxExit()
1041{
d88de032
DW
1042 wxLogError(_("Fatal error: exiting"));
1043
1044 wxApp::CleanUp();
0e320a79
DW
1045}
1046
d88de032 1047// Yield to incoming messages
0e320a79
DW
1048bool wxYield()
1049{
dde11e60
DW
1050 HAB vHab;
1051 QMSG vMsg;
d88de032
DW
1052 // We want to go back to the main message loop
1053 // if we see a WM_QUIT. (?)
dde11e60 1054 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 1055 {
dde11e60 1056 if (!wxTheApp->DoMessage())
d88de032
DW
1057 break;
1058 }
1059 // If they are pending events, we must process them.
1060#if wxUSE_THREADS
1061 wxTheApp->ProcessPendingEvents();
1062#endif
d88de032
DW
1063 return TRUE;
1064}
1065
1066wxIcon wxApp::GetStdIcon(int which) const
1067{
1068 // TODO:
1069 /*
1070 switch(which)
1071 {
1072 case wxICON_INFORMATION:
1073 return wxIcon("wxICON_INFO");
1074
1075 case wxICON_QUESTION:
1076 return wxIcon("wxICON_QUESTION");
1077
1078 case wxICON_EXCLAMATION:
1079 return wxIcon("wxICON_WARNING");
1080
1081 default:
1082 wxFAIL_MSG(wxT("requested non existent standard icon"));
1083 // still fall through
1084
1085 case wxICON_HAND:
1086 return wxIcon("wxICON_ERROR");
1087 }
1088*/
1089 return wxIcon("wxICON_ERROR");
1090}
1091
1092
1093HINSTANCE wxGetInstance()
1094{
1095 return wxhInstance;
1096}
1097
1098void wxSetInstance(HINSTANCE hInst)
1099{
1100 wxhInstance = hInst;
0e320a79
DW
1101}
1102
d88de032 1103