]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/app.cpp
some appearance fixes from Michael Bedward
[wxWidgets.git] / src / gtk1 / 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
8dbf4589 228/*
6b3eb77a 229#if wxUSE_THREADS
7b90a8f2
RR
230static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
231{
232 gtk_timeout_remove( wxTheApp->m_wakeUpTimerTag );
233 wxTheApp->m_wakeUpTimerTag = 0;
234
86fdd27b 235#if (GTK_MINOR_VERSION > 0)
8dbf4589
RR
236 // when getting called from GDK's time-out handler
237 // we are no longer within GDK's grab on the GUI
238 // thread so we must lock it here ourselves
7b90a8f2 239 GDK_THREADS_ENTER ();
86fdd27b 240#endif
7b90a8f2 241
8dbf4589 242 // unblock other threads wishing to do some GUI things
7b90a8f2
RR
243 wxMutexGuiLeave();
244
8dbf4589 245 // wake up other threads
7b90a8f2
RR
246 wxUsleep( 1 );
247
8dbf4589 248 // block other thread again
7b90a8f2
RR
249 wxMutexGuiEnter();
250
86fdd27b 251#if (GTK_MINOR_VERSION > 0)
8dbf4589 252 // release lock again
7b90a8f2 253 GDK_THREADS_LEAVE ();
86fdd27b 254#endif
7b90a8f2 255
db2d879a 256 wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 20, wxapp_wakeup_timerout_callback, (gpointer) NULL );
7b90a8f2
RR
257
258 return TRUE;
259}
6b3eb77a 260#endif
8dbf4589 261*/
7b90a8f2 262
c801d85f
KB
263//-----------------------------------------------------------------------------
264// wxApp
265//-----------------------------------------------------------------------------
266
267IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
268
53010e52
RR
269BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
270 EVT_IDLE(wxApp::OnIdle)
271END_EVENT_TABLE()
272
c801d85f
KB
273wxApp::wxApp()
274{
0d2a2b60 275 wxTheApp = this;
60acb947 276
ec758a20
RR
277 m_topWindow = (wxWindow *) NULL;
278 m_exitOnFrameDelete = TRUE;
60acb947 279
0d2a2b60 280 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
7b90a8f2 281
8dbf4589 282/*
6b3eb77a 283#if wxUSE_THREADS
db2d879a 284 m_wakeUpTimerTag = gtk_timeout_add( 20, wxapp_wakeup_timerout_callback, (gpointer) NULL );
6b3eb77a 285#endif
8dbf4589 286*/
60acb947 287
f6fcbb63 288 m_colorCube = (unsigned char*) NULL;
ff7b1510 289}
c801d85f 290
60acb947 291wxApp::~wxApp()
c801d85f 292{
acfd422a 293 if (m_idleTag) gtk_idle_remove( m_idleTag );
60acb947 294
8dbf4589 295/*
6b3eb77a 296#if wxUSE_THREADS
7b90a8f2 297 if (m_wakeUpTimerTag) gtk_timeout_remove( m_wakeUpTimerTag );
6b3eb77a 298#endif
8dbf4589 299*/
7b90a8f2 300
f6fcbb63 301 if (m_colorCube) free(m_colorCube);
ff7b1510 302}
c801d85f 303
0d2a2b60 304bool wxApp::OnInitGui()
c801d85f 305{
b134516c
RR
306 GdkVisual *visual = gdk_visual_get_system();
307
308 /* on some machines, the default visual is just 256 colours, so
309 we make sure we get the best. this can sometimes be wasteful,
7b280524 310 of course, but what do these guys pay $30.000 for? */
b134516c
RR
311/*
312 if (gdk_visual_get_best() != gdk_visual_get_system())
313 {
314 GdkVisual* vis = gdk_visual_get_best();
315 gtk_widget_set_default_visual( vis );
f6fcbb63 316
b134516c
RR
317 GdkColormap *colormap = gdk_colormap_new( vis, FALSE );
318 gtk_widget_set_default_colormap( colormap );
319
320 visual = vis;
321 }
322*/
323
7b280524 324 /* Nothing to do for 15, 16, 24, 32 bit displays */
f6fcbb63 325 if (visual->depth > 8) return TRUE;
60acb947 326
0d2a2b60
RR
327 /* this initiates the standard palette as defined by GdkImlib
328 in the GNOME libraries. it ensures that all GNOME applications
329 use the same 64 colormap entries on 8-bit displays so you
330 can use several rather graphics-heavy applications at the
331 same time.
8801832d 332 NOTE: this doesn't really seem to work this way... */
bbe0af5b 333
0d2a2b60
RR
334 /*
335 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 336
0d2a2b60
RR
337 for (int i = 0; i < 64; i++)
338 {
339 GdkColor col;
340 col.red = g_palette[i*3 + 0] << 8;
341 col.green = g_palette[i*3 + 1] << 8;
342 col.blue = g_palette[i*3 + 2] << 8;
343 col.pixel = 0;
344
345 gdk_color_alloc( cmap, &col );
346 }
60acb947 347
0d2a2b60
RR
348 gtk_widget_set_default_colormap( cmap );
349 */
60acb947 350
f6fcbb63 351 /* initialize color cube for 8-bit color reduction dithering */
60acb947 352
f6fcbb63 353 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 354
f6fcbb63
RR
355 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
356
f03fc89f
VZ
357 for (int r = 0; r < 32; r++)
358 {
8801832d
VZ
359 for (int g = 0; g < 32; g++)
360 {
361 for (int b = 0; b < 32; b++)
362 {
363 int rr = (r << 3) | (r >> 2);
364 int gg = (g << 3) | (g >> 2);
365 int bb = (b << 3) | (b >> 2);
60acb947 366
f03fc89f
VZ
367 int index = -1;
368
f6fcbb63 369 GdkColor *colors = cmap->colors;
ca26177c 370 if (colors)
f03fc89f
VZ
371 {
372 int max = 3 * 65536;
373
374 for (int i = 0; i < cmap->size; i++)
375 {
376 int rdiff = ((rr << 8) - colors[i].red);
377 int gdiff = ((gg << 8) - colors[i].green);
378 int bdiff = ((bb << 8) - colors[i].blue);
379 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
380 if (sum < max)
381 {
382 index = i; max = sum;
383 }
384 }
f6fcbb63 385 }
ca26177c
RR
386 else
387 {
58c7cd12 388#if (GTK_MINOR_VERSION > 0)
ca26177c
RR
389 /* assume 8-bit true or static colors. this really
390 exists. */
391 GdkVisual* vis = gdk_colormap_get_visual( cmap );
392 index = (r >> (5 - vis->red_prec)) << vis->red_shift;
393 index |= (g >> (5 - vis->green_prec)) << vis->green_shift;
394 index |= (b >> (5 - vis->blue_prec)) << vis->blue_shift;
58c7cd12
RR
395#else
396 wxFAIL_MSG( _T("Unsupported graphics hardware") );
397#endif
ca26177c 398 }
8801832d
VZ
399 m_colorCube[ (r*1024) + (g*32) + b ] = index;
400 }
401 }
f6fcbb63 402 }
c801d85f 403
bbe0af5b
RR
404 return TRUE;
405}
406
60acb947 407bool wxApp::ProcessIdle()
53010e52 408{
ec758a20
RR
409 wxIdleEvent event;
410 event.SetEventObject( this );
411 ProcessEvent( event );
0cf2cb36 412
ec758a20 413 return event.MoreRequested();
ff7b1510 414}
53010e52
RR
415
416void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 417{
ec758a20 418 static bool inOnIdle = FALSE;
53010e52 419
d524867f 420 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
421 if (inOnIdle)
422 return;
53010e52 423
ec758a20 424 inOnIdle = TRUE;
53010e52 425
d345e841 426#if wxUSE_THREADS
7214297d
GL
427 /* Resend in the main thread events which have been prepared in other
428 threads */
429 ProcessPendingEvents();
d345e841 430#endif
7214297d 431
d524867f 432 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 433 DeletePendingObjects();
53010e52 434
d524867f 435 /* flush the logged messages if any */
88ac883a 436#if wxUSE_LOG
d524867f
RR
437 wxLog *log = wxLog::GetActiveTarget();
438 if (log != NULL && log->HasPendingMessages())
439 log->Flush();
88ac883a 440#endif // wxUSE_LOG
53010e52 441
d524867f 442 /* Send OnIdle events to all windows */
ec758a20 443 bool needMore = SendIdleEvents();
53010e52 444
ec758a20
RR
445 if (needMore)
446 event.RequestMore(TRUE);
53010e52 447
ec758a20 448 inOnIdle = FALSE;
ff7b1510 449}
53010e52 450
60acb947 451bool wxApp::SendIdleEvents()
53010e52
RR
452{
453 bool needMore = FALSE;
e0253070 454
e146b8c8 455 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
456 while (node)
457 {
e146b8c8 458 wxWindow* win = node->GetData();
f3855ef0 459 if (SendIdleEvents(win))
53010e52 460 needMore = TRUE;
e146b8c8 461 node = node->GetNext();
ec758a20 462 }
e146b8c8 463
53010e52 464 return needMore;
ff7b1510 465}
53010e52
RR
466
467bool wxApp::SendIdleEvents( wxWindow* win )
468{
469 bool needMore = FALSE;
470
8bbe427f
VZ
471 wxIdleEvent event;
472 event.SetEventObject(win);
60acb947 473
9390a202 474 win->OnInternalIdle();
60acb947 475
8bbe427f 476 win->ProcessEvent(event);
53010e52
RR
477
478 if (event.MoreRequested())
479 needMore = TRUE;
480
8bbe427f
VZ
481 wxNode* node = win->GetChildren().First();
482 while (node)
483 {
484 wxWindow* win = (wxWindow*) node->Data();
485 if (SendIdleEvents(win))
53010e52
RR
486 needMore = TRUE;
487
8bbe427f
VZ
488 node = node->Next();
489 }
53010e52 490 return needMore ;
ff7b1510 491}
c801d85f 492
60acb947 493int wxApp::MainLoop()
c801d85f 494{
ec758a20
RR
495 gtk_main();
496 return 0;
ff7b1510 497}
c801d85f 498
60acb947 499void wxApp::ExitMainLoop()
c801d85f 500{
ec758a20 501 gtk_main_quit();
ff7b1510 502}
c801d85f 503
60acb947 504bool wxApp::Initialized()
c801d85f 505{
ec758a20 506 return m_initialized;
ff7b1510 507}
c801d85f 508
60acb947 509bool wxApp::Pending()
c801d85f 510{
acfd422a 511 return (gtk_events_pending() > 0);
ff7b1510 512}
c801d85f 513
60acb947 514void wxApp::Dispatch()
c801d85f 515{
8801832d 516 gtk_main_iteration();
ff7b1510 517}
c801d85f 518
7214297d
GL
519#if wxUSE_THREADS
520void wxApp::ProcessPendingEvents()
521{
4d3a259a
GL
522 wxNode *node = wxPendingEvents->First();
523 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
7214297d
GL
524
525 while (node)
526 {
527 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
528
529 handler->ProcessPendingEvents();
e146b8c8 530
7214297d
GL
531 delete node;
532
4d3a259a 533 node = wxPendingEvents->First();
7214297d
GL
534 }
535}
8801832d 536#endif // wxUSE_THREADS
7214297d 537
60acb947 538void wxApp::DeletePendingObjects()
c801d85f 539{
ec758a20
RR
540 wxNode *node = wxPendingDelete.First();
541 while (node)
542 {
543 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 544
ec758a20 545 delete obj;
c801d85f 546
f03fc89f
VZ
547 if (wxPendingDelete.Find(obj))
548 delete node;
c801d85f 549
ec758a20
RR
550 node = wxPendingDelete.First();
551 }
ff7b1510 552}
c801d85f 553
60acb947 554wxWindow *wxApp::GetTopWindow()
c801d85f 555{
e146b8c8
VZ
556 if (m_topWindow)
557 return m_topWindow;
558 else if (wxTopLevelWindows.GetCount() > 0)
559 return wxTopLevelWindows.GetFirst()->GetData();
560 else
561 return NULL;
ff7b1510 562}
c801d85f
KB
563
564void wxApp::SetTopWindow( wxWindow *win )
565{
ec758a20 566 m_topWindow = win;
ff7b1510 567}
c801d85f 568
60acb947 569bool wxApp::Initialize()
c801d85f 570{
9cc7a35d 571 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
572
573 wxClassInfo::InitializeClasses();
60acb947 574
0d2a2b60 575 wxSystemSettings::Init();
60acb947 576
4d3a259a
GL
577 // GL: I'm annoyed ... I don't know where to put this and I don't want to
578 // create a module for that as it's part of the core.
579#if wxUSE_THREADS
580 wxPendingEvents = new wxList();
581 wxPendingEventsLocker = new wxCriticalSection();
582#endif
583
36b3b54a 584/*
0d2a2b60
RR
585 wxTheFontNameDirectory = new wxFontNameDirectory;
586 wxTheFontNameDirectory->Initialize();
36b3b54a 587*/
c801d85f 588
0d2a2b60
RR
589 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
590 wxTheColourDatabase->Initialize();
a3622daa 591
0d2a2b60
RR
592 wxInitializeStockLists();
593 wxInitializeStockObjects();
c801d85f 594
06cfab17 595#if wxUSE_WX_RESOURCES
0d2a2b60 596 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 597
0d2a2b60 598 wxInitializeResourceSystem();
f5abe911 599#endif
0cf2cb36 600
0d2a2b60 601 wxImage::InitStandardHandlers();
e0253070 602
0d2a2b60
RR
603 wxModule::RegisterModules();
604 if (!wxModule::InitializeModules()) return FALSE;
60acb947 605
0d2a2b60 606 return TRUE;
ff7b1510 607}
c801d85f 608
60acb947 609void wxApp::CleanUp()
c801d85f 610{
0d2a2b60 611 wxModule::CleanUpModules();
0cf2cb36 612
06cfab17 613#if wxUSE_WX_RESOURCES
ec758a20 614 wxFlushResources();
a3622daa 615
60acb947
VZ
616 if (wxTheResourceCache)
617 delete wxTheResourceCache;
bbe0af5b 618 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 619
f5abe911
RR
620 wxCleanUpResourceSystem();
621#endif
a3622daa 622
60acb947
VZ
623 if (wxTheColourDatabase)
624 delete wxTheColourDatabase;
0d2a2b60 625 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 626
36b3b54a 627/*
0d2a2b60
RR
628 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
629 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 630*/
60acb947 631
0d2a2b60
RR
632 wxDeleteStockObjects();
633
ec758a20 634 wxDeleteStockLists();
a3622daa 635
ec758a20 636 wxImage::CleanUpHandlers();
0cf2cb36 637
0d2a2b60
RR
638 delete wxTheApp;
639 wxTheApp = (wxApp*) NULL;
640
4d3a259a
GL
641 // GL: I'm annoyed ... I don't know where to put this and I don't want to
642 // create a module for that as it's part of the core.
643#if wxUSE_THREADS
644 delete wxPendingEvents;
645 delete wxPendingEventsLocker;
646#endif
647
3e61c765 648 wxSystemSettings::Done();
60acb947 649
3e61c765
RR
650 delete[] wxBuffer;
651
652 wxClassInfo::CleanUpClasses();
60acb947
VZ
653
654 // check for memory leaks
0d2a2b60
RR
655#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
656 if (wxDebugContext::CountObjectsLeft() > 0)
657 {
9cc7a35d 658 wxLogDebug(_T("There were memory leaks.\n"));
0d2a2b60
RR
659 wxDebugContext::Dump();
660 wxDebugContext::PrintStatistics();
661 }
8801832d 662#endif // Debug
0d2a2b60 663
88ac883a 664#if wxUSE_LOG
60acb947 665 // do this as the very last thing because everything else can log messages
0d2a2b60 666 wxLog::DontCreateOnDemand();
60acb947 667
0d2a2b60 668 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
669 if (oldLog)
670 delete oldLog;
ff7b1510 671}
0cf2cb36 672
c801d85f
KB
673wxLog *wxApp::CreateLogTarget()
674{
0d2a2b60 675 return new wxLogGui;
c801d85f 676}
88ac883a 677#endif // wxUSE_LOG
c801d85f
KB
678
679//-----------------------------------------------------------------------------
680// wxEntry
681//-----------------------------------------------------------------------------
682
683int wxEntry( int argc, char *argv[] )
684{
0d2a2b60 685 gtk_set_locale();
c801d85f 686
dcf924a3 687 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
002f4218 688
0d2a2b60 689 gtk_init( &argc, &argv );
0cf2cb36 690
f0492f7d
RR
691 wxSetDetectableAutoRepeat( TRUE );
692
60acb947
VZ
693 if (!wxApp::Initialize())
694 return -1;
0cf2cb36 695
ec758a20 696 if (!wxTheApp)
c801d85f 697 {
60acb947 698 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
9cc7a35d 699 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 700
ec758a20 701 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 702
ec758a20 703 wxObject *test_app = app_ini();
0cf2cb36 704
ec758a20
RR
705 wxTheApp = (wxApp*) test_app;
706 }
0cf2cb36 707
9cc7a35d 708 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
c801d85f 709
ec758a20
RR
710 wxTheApp->argc = argc;
711 wxTheApp->argv = argv;
0cf2cb36 712
8801832d 713 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
714 wxStripExtension( name );
715 wxTheApp->SetAppName( name );
e0253070 716
0151c3eb
VZ
717 int retValue = 0;
718
719 if ( !wxTheApp->OnInitGui() )
720 retValue = -1;
c801d85f 721
8801832d
VZ
722 // Here frames insert themselves automatically into wxTopLevelWindows by
723 // getting created in OnInit().
0151c3eb
VZ
724 if ( retValue == 0 )
725 {
726 if ( !wxTheApp->OnInit() )
727 retValue = -1;
728 }
0cf2cb36 729
0151c3eb
VZ
730 if ( retValue == 0 )
731 {
cfb50f14
RR
732 /* delete pending toplevel windows (typically a single
733 dialog) so that, if there isn't any left, we don't
734 call OnRun() */
735 wxTheApp->DeletePendingObjects();
736
0151c3eb 737 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 738
0151c3eb 739 if (wxTheApp->Initialized())
cfb50f14 740 {
0151c3eb 741 retValue = wxTheApp->OnRun();
0cf2cb36 742
cfb50f14
RR
743 wxWindow *topWindow = wxTheApp->GetTopWindow();
744 if (topWindow)
0151c3eb 745 {
cfb50f14
RR
746 /* Forcibly delete the window. */
747 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
748 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
749 {
750 topWindow->Close( TRUE );
751 wxTheApp->DeletePendingObjects();
752 }
753 else
754 {
755 delete topWindow;
756 wxTheApp->SetTopWindow( (wxWindow*) NULL );
757 }
758 }
759 wxTheApp->OnExit();
0d2a2b60 760 }
0151c3eb 761 }
0cf2cb36 762
88ac883a 763#if wxUSE_LOG
60acb947 764 // flush the logged messages if any
0d2a2b60
RR
765 wxLog *log = wxLog::GetActiveTarget();
766 if (log != NULL && log->HasPendingMessages())
767 log->Flush();
768
60acb947
VZ
769 // continuing to use user defined log target is unsafe from now on because
770 // some resources may be already unavailable, so replace it by something
771 // more safe
772 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
773 if ( oldlog )
774 delete oldlog;
88ac883a 775#endif // wxUSE_LOG
60acb947 776
0d2a2b60 777 wxApp::CleanUp();
184b5d99 778
ec758a20 779 return retValue;
ff7b1510 780}
1a56f55c 781