]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
tree ctrl sorting shouldn't crash when items don't have data
[wxWidgets.git] / src / gtk / app.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose:
4// Author: Robert Roebling
32e9da8b 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart
8bbe427f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
afb74891 11 #pragma implementation "app.h"
c801d85f
KB
12#endif
13
14#include "wx/app.h"
15#include "wx/gdicmn.h"
16#include "wx/utils.h"
c801d85f
KB
17#include "wx/intl.h"
18#include "wx/log.h"
46dc76ba 19#include "wx/memory.h"
a3622daa
VZ
20#include "wx/font.h"
21#include "wx/settings.h"
0d2a2b60 22#include "wx/dialog.h"
afb74891 23
06cfab17 24#if wxUSE_WX_RESOURCES
afb74891 25 #include "wx/resource.h"
f5abe911 26#endif
afb74891 27
031b2a7b 28#include "wx/module.h"
4bc67cc5 29#include "wx/image.h"
afb74891 30
f3855ef0 31#include "wx/thread.h"
afb74891 32
c801d85f
KB
33#include "unistd.h"
34
afb74891
VZ
35#include <glib.h>
36#include <gdk/gdk.h>
37#include <gtk/gtk.h>
24178e4a 38
83624f79
RR
39#include "wx/gtk/win_gtk.h"
40
c801d85f
KB
41//-----------------------------------------------------------------------------
42// global data
43//-----------------------------------------------------------------------------
44
c67daf87 45wxApp *wxTheApp = (wxApp *) NULL;
c801d85f
KB
46wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
47
48extern wxList wxPendingDelete;
7214297d 49#if wxUSE_THREADS
4d3a259a
GL
50extern wxList *wxPendingEvents;
51extern wxCriticalSection *wxPendingEventsLocker;
7214297d 52#endif
a3622daa 53extern wxResourceCache *wxTheResourceCache;
acfd422a 54extern bool g_isIdle;
c801d85f 55
01111366
RR
56unsigned char g_palette[64*3] =
57{
58 0x0, 0x0, 0x0,
59 0xff, 0xff, 0xff,
60 0xff, 0x0, 0x0,
61 0xff, 0xff, 0x0,
62 0x0, 0xff, 0x0,
63 0x0, 0x0, 0xff,
64 0x0, 0xff, 0xff,
65 0x99, 0x99, 0x99,
66 0xff, 0x88, 0x0,
67 0x88, 0x0, 0x0,
68 0x0, 0x88, 0x88,
69 0x88, 0x88, 0x0,
70 0xff, 0xcc, 0x97,
71 0xbb, 0xbb, 0xbb,
72 0x9f, 0x6b, 0x42,
73 0x55, 0x55, 0x55,
74 0xdd, 0xdd, 0xdd,
75 0x77, 0x77, 0x77,
76 0x33, 0x33, 0x33,
77 0xcc, 0x0, 0x0,
78 0xff, 0x44, 0x0,
79 0xff, 0xcc, 0x0,
80 0xcc, 0xcc, 0x0,
81 0x60, 0x60, 0x0,
82 0x0, 0x43, 0x0,
83 0x0, 0x7f, 0x0,
84 0x0, 0xcc, 0x0,
85 0x0, 0x44, 0x44,
86 0x0, 0x0, 0x44,
87 0x0, 0x0, 0x88,
88 0xef, 0xb1, 0x7b,
89 0xdf, 0x98, 0x5f,
90 0xbf, 0x87, 0x56,
91 0x7f, 0x57, 0x26,
92 0x5f, 0x39, 0xc,
93 0x3f, 0x1c, 0x0,
94 0x21, 0x0, 0x0,
95 0x0, 0x43, 0x87,
96 0x2d, 0x70, 0xaf,
97 0x5a, 0x9e, 0xd7,
98 0x87, 0xcc, 0xff,
99 0xff, 0xe0, 0xba,
100 0x21, 0x43, 0xf,
101 0x3d, 0x5d, 0x25,
102 0x59, 0x78, 0x3a,
103 0x75, 0x93, 0x4f,
104 0x91, 0xae, 0x64,
105 0xad, 0xc8, 0x7a,
e0253070 106 0xf0, 0xa8, 0xef,
01111366
RR
107 0xd0, 0x88, 0xd0,
108 0xaf, 0x66, 0xaf,
109 0x8e, 0x44, 0x8e,
110 0x6d, 0x22, 0x6d,
e0253070 111 0x4b, 0x0, 0x4b,
01111366
RR
112 0xff, 0xc0, 0xbc,
113 0xff, 0x93, 0x91,
114 0xff, 0x66, 0x67,
115 0xd8, 0xf2, 0xbf,
116 0xff, 0xc9, 0x68,
117 0xff, 0x96, 0x67,
118 0xa5, 0x60, 0xff,
119 0x51, 0xff, 0x99,
120 0x3f, 0xa5, 0x63,
121 0x98, 0x90, 0x67
122};
123
c801d85f
KB
124//-----------------------------------------------------------------------------
125// local functions
126//-----------------------------------------------------------------------------
127
128extern void wxFlushResources(void);
129
130//-----------------------------------------------------------------------------
131// global functions
132//-----------------------------------------------------------------------------
133
60acb947 134void wxExit()
c801d85f 135{
ec758a20 136 gtk_main_quit();
ff7b1510 137}
c801d85f 138
acfd422a 139/* forward declaration */
53a8af59
KB
140gint wxapp_idle_callback( gpointer WXUNUSED(data) );
141
60acb947 142bool wxYield()
c801d85f 143{
5f12ae5c
VZ
144 // it's necessary to call ProcessIdle() to update the frames sizes which
145 // might have been changed (it also will update other things set from
146 // OnUpdateUI() which is a nice (and desired) side effect)
e146b8c8 147 for ( wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
5f12ae5c
VZ
148 node;
149 node = node->GetNext() )
150 {
e146b8c8 151 wxWindow *win = node->GetData();
5f12ae5c
VZ
152 win->OnInternalIdle();
153 }
154
acfd422a
RR
155 if (wxTheApp->m_idleTag)
156 {
157 /* We need to temporarily remove idle callbacks or the loop will
158 never finish. */
159 gtk_idle_remove( wxTheApp->m_idleTag );
160 wxTheApp->m_idleTag = 0;
161
162 while (gtk_events_pending())
163 gtk_main_iteration();
164
165 /* re-add idle handler */
166 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
167 }
168 else
169 {
170 while (gtk_events_pending())
171 gtk_main_iteration();
172 }
173
174 return TRUE;
175}
176
177gint wxapp_idle_callback( gpointer WXUNUSED(data) )
178{
179 if (!wxTheApp) return TRUE;
180
181 /* sent idle event to all who request them */
182 while (wxTheApp->ProcessIdle()) { }
183
184 /* we don't want any more idle events until the next event is
185 sent to wxGTK */
53a8af59 186 gtk_idle_remove( wxTheApp->m_idleTag );
acfd422a
RR
187 wxTheApp->m_idleTag = 0;
188
189 /* indicate that we are now in idle mode - even so deeply
190 in idle mode that we don't get any idle events anymore.
191 this is like wxMSW where an idle event is sent only
192 once each time after the event queue has been completely
193 emptied */
194 g_isIdle = TRUE;
195
b9a535f5
RR
196 /* wake up other threads */
197 wxMutexGuiLeave();
198 wxUsleep(0);
199 wxMutexGuiEnter();
acfd422a
RR
200
201 return TRUE;
202}
8801832d 203
acfd422a
RR
204void wxapp_install_idle_handler()
205{
206 /* this routine gets called by all event handlers
207 indicating that the idle is over. */
5f12ae5c 208
53a8af59 209 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
acfd422a
RR
210
211 g_isIdle = FALSE;
ff7b1510 212}
c801d85f
KB
213
214//-----------------------------------------------------------------------------
215// wxApp
216//-----------------------------------------------------------------------------
217
218IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
219
53010e52
RR
220BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
221 EVT_IDLE(wxApp::OnIdle)
222END_EVENT_TABLE()
223
c801d85f
KB
224wxApp::wxApp()
225{
0d2a2b60 226 wxTheApp = this;
60acb947 227
ec758a20
RR
228 m_topWindow = (wxWindow *) NULL;
229 m_exitOnFrameDelete = TRUE;
60acb947 230
0d2a2b60 231 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
60acb947 232
f6fcbb63 233 m_colorCube = (unsigned char*) NULL;
ff7b1510 234}
c801d85f 235
60acb947 236wxApp::~wxApp()
c801d85f 237{
acfd422a 238 if (m_idleTag) gtk_idle_remove( m_idleTag );
60acb947 239
f6fcbb63 240 if (m_colorCube) free(m_colorCube);
ff7b1510 241}
c801d85f 242
0d2a2b60 243bool wxApp::OnInitGui()
c801d85f 244{
f6fcbb63
RR
245 /* Nothing to do for 15, 16, 24, 32 bit displays */
246
247 GdkVisual *visual = gdk_visual_get_system();
248 if (visual->depth > 8) return TRUE;
60acb947 249
0d2a2b60
RR
250 /* this initiates the standard palette as defined by GdkImlib
251 in the GNOME libraries. it ensures that all GNOME applications
252 use the same 64 colormap entries on 8-bit displays so you
253 can use several rather graphics-heavy applications at the
254 same time.
8801832d 255 NOTE: this doesn't really seem to work this way... */
bbe0af5b 256
0d2a2b60
RR
257 /*
258 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 259
0d2a2b60
RR
260 for (int i = 0; i < 64; i++)
261 {
262 GdkColor col;
263 col.red = g_palette[i*3 + 0] << 8;
264 col.green = g_palette[i*3 + 1] << 8;
265 col.blue = g_palette[i*3 + 2] << 8;
266 col.pixel = 0;
267
268 gdk_color_alloc( cmap, &col );
269 }
60acb947 270
0d2a2b60
RR
271 gtk_widget_set_default_colormap( cmap );
272 */
60acb947 273
f6fcbb63 274 /* initialize color cube for 8-bit color reduction dithering */
60acb947 275
f6fcbb63 276 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 277
f6fcbb63
RR
278 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
279
280 for (int r = 0; r < 32; r++)
281 {
8801832d
VZ
282 for (int g = 0; g < 32; g++)
283 {
284 for (int b = 0; b < 32; b++)
285 {
286 int rr = (r << 3) | (r >> 2);
287 int gg = (g << 3) | (g >> 2);
288 int bb = (b << 3) | (b >> 2);
60acb947 289
f6fcbb63 290 GdkColor *colors = cmap->colors;
3418cb8b
KB
291 if(colors)
292 {
293 int max = 3 * 65536;
294 int index = -1;
f6fcbb63 295
3418cb8b
KB
296 for (int i = 0; i < cmap->size; i++)
297 {
f6fcbb63 298 int rdiff = ((rr << 8) - colors[i].red);
acfd422a
RR
299 int gdiff = ((gg << 8) - colors[i].green);
300 int bdiff = ((bb << 8) - colors[i].blue);
f6fcbb63
RR
301 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
302 if (sum < max) { index = i; max = sum; }
303 }
3418cb8b 304 }
8801832d
VZ
305 m_colorCube[ (r*1024) + (g*32) + b ] = index;
306 }
307 }
f6fcbb63 308 }
c801d85f 309
bbe0af5b
RR
310 return TRUE;
311}
312
60acb947 313bool wxApp::ProcessIdle()
53010e52 314{
ec758a20
RR
315 wxIdleEvent event;
316 event.SetEventObject( this );
317 ProcessEvent( event );
0cf2cb36 318
ec758a20 319 return event.MoreRequested();
ff7b1510 320}
53010e52
RR
321
322void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 323{
ec758a20 324 static bool inOnIdle = FALSE;
53010e52 325
d524867f 326 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
327 if (inOnIdle)
328 return;
53010e52 329
ec758a20 330 inOnIdle = TRUE;
53010e52 331
d345e841 332#if wxUSE_THREADS
7214297d
GL
333 /* Resend in the main thread events which have been prepared in other
334 threads */
335 ProcessPendingEvents();
d345e841 336#endif
7214297d 337
d524867f 338 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 339 DeletePendingObjects();
53010e52 340
d524867f
RR
341 /* flush the logged messages if any */
342 wxLog *log = wxLog::GetActiveTarget();
343 if (log != NULL && log->HasPendingMessages())
344 log->Flush();
53010e52 345
d524867f 346 /* Send OnIdle events to all windows */
ec758a20 347 bool needMore = SendIdleEvents();
53010e52 348
ec758a20
RR
349 if (needMore)
350 event.RequestMore(TRUE);
53010e52 351
ec758a20 352 inOnIdle = FALSE;
ff7b1510 353}
53010e52 354
60acb947 355bool wxApp::SendIdleEvents()
53010e52
RR
356{
357 bool needMore = FALSE;
e0253070 358
e146b8c8 359 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
360 while (node)
361 {
e146b8c8 362 wxWindow* win = node->GetData();
f3855ef0 363 if (SendIdleEvents(win))
53010e52 364 needMore = TRUE;
e146b8c8 365 node = node->GetNext();
ec758a20 366 }
e146b8c8 367
53010e52 368 return needMore;
ff7b1510 369}
53010e52
RR
370
371bool wxApp::SendIdleEvents( wxWindow* win )
372{
373 bool needMore = FALSE;
374
8bbe427f
VZ
375 wxIdleEvent event;
376 event.SetEventObject(win);
60acb947 377
9390a202 378 win->OnInternalIdle();
60acb947 379
8bbe427f 380 win->ProcessEvent(event);
53010e52
RR
381
382 if (event.MoreRequested())
383 needMore = TRUE;
384
8bbe427f
VZ
385 wxNode* node = win->GetChildren().First();
386 while (node)
387 {
388 wxWindow* win = (wxWindow*) node->Data();
389 if (SendIdleEvents(win))
53010e52
RR
390 needMore = TRUE;
391
8bbe427f
VZ
392 node = node->Next();
393 }
53010e52 394 return needMore ;
ff7b1510 395}
c801d85f 396
60acb947 397int wxApp::MainLoop()
c801d85f 398{
ec758a20
RR
399 gtk_main();
400 return 0;
ff7b1510 401}
c801d85f 402
60acb947 403void wxApp::ExitMainLoop()
c801d85f 404{
ec758a20 405 gtk_main_quit();
ff7b1510 406}
c801d85f 407
60acb947 408bool wxApp::Initialized()
c801d85f 409{
ec758a20 410 return m_initialized;
ff7b1510 411}
c801d85f 412
60acb947 413bool wxApp::Pending()
c801d85f 414{
acfd422a 415 return (gtk_events_pending() > 0);
ff7b1510 416}
c801d85f 417
60acb947 418void wxApp::Dispatch()
c801d85f 419{
8801832d 420 gtk_main_iteration();
ff7b1510 421}
c801d85f 422
7214297d
GL
423#if wxUSE_THREADS
424void wxApp::ProcessPendingEvents()
425{
4d3a259a
GL
426 wxNode *node = wxPendingEvents->First();
427 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
7214297d
GL
428
429 while (node)
430 {
431 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
432
433 handler->ProcessPendingEvents();
e146b8c8 434
7214297d
GL
435 delete node;
436
4d3a259a 437 node = wxPendingEvents->First();
7214297d
GL
438 }
439}
8801832d 440#endif // wxUSE_THREADS
7214297d 441
60acb947 442void wxApp::DeletePendingObjects()
c801d85f 443{
ec758a20
RR
444 wxNode *node = wxPendingDelete.First();
445 while (node)
446 {
447 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 448
ec758a20 449 delete obj;
c801d85f 450
ec758a20
RR
451 if (wxPendingDelete.Member(obj))
452 delete node;
c801d85f 453
ec758a20
RR
454 node = wxPendingDelete.First();
455 }
ff7b1510 456}
c801d85f 457
60acb947 458wxWindow *wxApp::GetTopWindow()
c801d85f 459{
e146b8c8
VZ
460 if (m_topWindow)
461 return m_topWindow;
462 else if (wxTopLevelWindows.GetCount() > 0)
463 return wxTopLevelWindows.GetFirst()->GetData();
464 else
465 return NULL;
ff7b1510 466}
c801d85f
KB
467
468void wxApp::SetTopWindow( wxWindow *win )
469{
ec758a20 470 m_topWindow = win;
ff7b1510 471}
c801d85f 472
60acb947 473bool wxApp::Initialize()
c801d85f 474{
9cc7a35d 475 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
476
477 wxClassInfo::InitializeClasses();
60acb947 478
0d2a2b60 479 wxSystemSettings::Init();
60acb947 480
4d3a259a
GL
481 // GL: I'm annoyed ... I don't know where to put this and I don't want to
482 // create a module for that as it's part of the core.
483#if wxUSE_THREADS
484 wxPendingEvents = new wxList();
485 wxPendingEventsLocker = new wxCriticalSection();
486#endif
487
36b3b54a 488/*
0d2a2b60
RR
489 wxTheFontNameDirectory = new wxFontNameDirectory;
490 wxTheFontNameDirectory->Initialize();
36b3b54a 491*/
c801d85f 492
0d2a2b60
RR
493 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
494 wxTheColourDatabase->Initialize();
a3622daa 495
0d2a2b60
RR
496 wxInitializeStockLists();
497 wxInitializeStockObjects();
c801d85f 498
06cfab17 499#if wxUSE_WX_RESOURCES
0d2a2b60 500 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 501
0d2a2b60 502 wxInitializeResourceSystem();
f5abe911 503#endif
0cf2cb36 504
0d2a2b60 505 wxImage::InitStandardHandlers();
e0253070 506
0d2a2b60
RR
507 /* no global cursor under X
508 g_globalCursor = new wxCursor; */
60acb947 509
0d2a2b60
RR
510 wxModule::RegisterModules();
511 if (!wxModule::InitializeModules()) return FALSE;
60acb947 512
0d2a2b60 513 return TRUE;
ff7b1510 514}
c801d85f 515
60acb947 516void wxApp::CleanUp()
c801d85f 517{
0d2a2b60 518 wxModule::CleanUpModules();
0cf2cb36 519
06cfab17 520#if wxUSE_WX_RESOURCES
ec758a20 521 wxFlushResources();
a3622daa 522
60acb947
VZ
523 if (wxTheResourceCache)
524 delete wxTheResourceCache;
bbe0af5b 525 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 526
f5abe911
RR
527 wxCleanUpResourceSystem();
528#endif
a3622daa 529
60acb947
VZ
530 if (wxTheColourDatabase)
531 delete wxTheColourDatabase;
0d2a2b60 532 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 533
36b3b54a 534/*
0d2a2b60
RR
535 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
536 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 537*/
60acb947 538
0d2a2b60
RR
539 wxDeleteStockObjects();
540
ec758a20 541 wxDeleteStockLists();
a3622daa 542
ec758a20 543 wxImage::CleanUpHandlers();
0cf2cb36 544
0d2a2b60
RR
545 delete wxTheApp;
546 wxTheApp = (wxApp*) NULL;
547
4d3a259a
GL
548 // GL: I'm annoyed ... I don't know where to put this and I don't want to
549 // create a module for that as it's part of the core.
550#if wxUSE_THREADS
551 delete wxPendingEvents;
552 delete wxPendingEventsLocker;
553#endif
554
3e61c765 555 wxSystemSettings::Done();
60acb947 556
3e61c765
RR
557 delete[] wxBuffer;
558
559 wxClassInfo::CleanUpClasses();
60acb947
VZ
560
561 // check for memory leaks
0d2a2b60
RR
562#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
563 if (wxDebugContext::CountObjectsLeft() > 0)
564 {
9cc7a35d 565 wxLogDebug(_T("There were memory leaks.\n"));
0d2a2b60
RR
566 wxDebugContext::Dump();
567 wxDebugContext::PrintStatistics();
568 }
8801832d 569#endif // Debug
0d2a2b60 570
60acb947 571 // do this as the very last thing because everything else can log messages
0d2a2b60 572 wxLog::DontCreateOnDemand();
60acb947 573
0d2a2b60 574 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
575 if (oldLog)
576 delete oldLog;
ff7b1510 577}
0cf2cb36 578
c801d85f
KB
579wxLog *wxApp::CreateLogTarget()
580{
0d2a2b60 581 return new wxLogGui;
c801d85f
KB
582}
583
584//-----------------------------------------------------------------------------
585// wxEntry
586//-----------------------------------------------------------------------------
587
588int wxEntry( int argc, char *argv[] )
589{
0d2a2b60 590 gtk_set_locale();
c801d85f 591
0d2a2b60 592 gtk_init( &argc, &argv );
0cf2cb36 593
60acb947
VZ
594 if (!wxApp::Initialize())
595 return -1;
0cf2cb36 596
ec758a20 597 if (!wxTheApp)
c801d85f 598 {
60acb947 599 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
9cc7a35d 600 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 601
ec758a20 602 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 603
ec758a20 604 wxObject *test_app = app_ini();
0cf2cb36 605
ec758a20
RR
606 wxTheApp = (wxApp*) test_app;
607 }
0cf2cb36 608
9cc7a35d 609 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
c801d85f 610
ec758a20
RR
611 wxTheApp->argc = argc;
612 wxTheApp->argv = argv;
0cf2cb36 613
8801832d 614 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
615 wxStripExtension( name );
616 wxTheApp->SetAppName( name );
e0253070 617
0151c3eb
VZ
618 int retValue = 0;
619
620 if ( !wxTheApp->OnInitGui() )
621 retValue = -1;
c801d85f 622
8801832d
VZ
623 // Here frames insert themselves automatically into wxTopLevelWindows by
624 // getting created in OnInit().
0151c3eb
VZ
625 if ( retValue == 0 )
626 {
627 if ( !wxTheApp->OnInit() )
628 retValue = -1;
629 }
0cf2cb36 630
0151c3eb
VZ
631 if ( retValue == 0 )
632 {
633 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 634
0151c3eb
VZ
635 if (wxTheApp->Initialized())
636 retValue = wxTheApp->OnRun();
0cf2cb36 637
0151c3eb
VZ
638 wxWindow *topWindow = wxTheApp->GetTopWindow();
639 if (topWindow)
0d2a2b60 640 {
0151c3eb
VZ
641 // Forcibly delete the window.
642 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
643 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
644 {
645 topWindow->Close( TRUE );
646 wxTheApp->DeletePendingObjects();
647 }
648 else
649 {
650 delete topWindow;
651 wxTheApp->SetTopWindow( (wxWindow*) NULL );
652 }
0d2a2b60 653 }
e0253070 654
0151c3eb
VZ
655 wxTheApp->OnExit();
656 }
0cf2cb36 657
60acb947 658 // flush the logged messages if any
0d2a2b60
RR
659 wxLog *log = wxLog::GetActiveTarget();
660 if (log != NULL && log->HasPendingMessages())
661 log->Flush();
662
60acb947
VZ
663 // continuing to use user defined log target is unsafe from now on because
664 // some resources may be already unavailable, so replace it by something
665 // more safe
666 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
667 if ( oldlog )
668 delete oldlog;
669
0d2a2b60 670 wxApp::CleanUp();
184b5d99 671
ec758a20 672 return retValue;
ff7b1510 673}
1a56f55c 674