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