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