]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/app.cpp
fixed compile error
[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
RR
146 bool has_idle = (wxTheApp->m_idleTag != 0);
147
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()) { }
163
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 }
956dbab1 169
acfd422a
RR
170 return TRUE;
171}
172
173gint wxapp_idle_callback( gpointer WXUNUSED(data) )
174{
175 if (!wxTheApp) return TRUE;
956dbab1 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{
861ccde4 209 wxASSERT_MSG( wxTheApp->m_idleTag == 0, _T("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
RR
226 if (wxTheApp->m_wakeUpTimerTag) return;
227
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;
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}
6b3eb77a 268#endif
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
RR
399#else
400 wxFAIL_MSG( _T("Unsupported graphics hardware") );
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
956dbab1
RR
417 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
418 while (node)
419 {
420 wxWindow* win = node->GetData();
421 win->OnInternalIdle();
422 node = node->GetNext();
423 }
424
ec758a20 425 return event.MoreRequested();
ff7b1510 426}
53010e52
RR
427
428void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 429{
956dbab1 430 static bool s_inOnIdle = FALSE;
53010e52 431
d524867f 432 /* Avoid recursion (via ProcessEvent default case) */
956dbab1 433 if (s_inOnIdle)
ec758a20 434 return;
53010e52 435
956dbab1 436 s_inOnIdle = TRUE;
53010e52 437
d345e841 438#if wxUSE_THREADS
7214297d
GL
439 /* Resend in the main thread events which have been prepared in other
440 threads */
441 ProcessPendingEvents();
d345e841 442#endif
7214297d 443
d524867f 444 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 445 DeletePendingObjects();
53010e52 446
d524867f 447 /* flush the logged messages if any */
88ac883a 448#if wxUSE_LOG
d524867f
RR
449 wxLog *log = wxLog::GetActiveTarget();
450 if (log != NULL && log->HasPendingMessages())
451 log->Flush();
88ac883a 452#endif // wxUSE_LOG
53010e52 453
d524867f 454 /* Send OnIdle events to all windows */
ec758a20 455 bool needMore = SendIdleEvents();
53010e52 456
ec758a20
RR
457 if (needMore)
458 event.RequestMore(TRUE);
53010e52 459
956dbab1 460 s_inOnIdle = FALSE;
ff7b1510 461}
53010e52 462
60acb947 463bool wxApp::SendIdleEvents()
53010e52
RR
464{
465 bool needMore = FALSE;
e0253070 466
e146b8c8 467 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
468 while (node)
469 {
e146b8c8 470 wxWindow* win = node->GetData();
f3855ef0 471 if (SendIdleEvents(win))
53010e52 472 needMore = TRUE;
e146b8c8 473 node = node->GetNext();
ec758a20 474 }
e146b8c8 475
53010e52 476 return needMore;
ff7b1510 477}
53010e52
RR
478
479bool wxApp::SendIdleEvents( wxWindow* win )
480{
481 bool needMore = FALSE;
482
8bbe427f
VZ
483 wxIdleEvent event;
484 event.SetEventObject(win);
60acb947 485
8bbe427f 486 win->ProcessEvent(event);
53010e52
RR
487
488 if (event.MoreRequested())
489 needMore = TRUE;
490
8bbe427f
VZ
491 wxNode* node = win->GetChildren().First();
492 while (node)
493 {
494 wxWindow* win = (wxWindow*) node->Data();
495 if (SendIdleEvents(win))
53010e52
RR
496 needMore = TRUE;
497
8bbe427f
VZ
498 node = node->Next();
499 }
53010e52 500 return needMore ;
ff7b1510 501}
c801d85f 502
60acb947 503int wxApp::MainLoop()
c801d85f 504{
ec758a20
RR
505 gtk_main();
506 return 0;
ff7b1510 507}
c801d85f 508
60acb947 509void wxApp::ExitMainLoop()
c801d85f 510{
ec758a20 511 gtk_main_quit();
ff7b1510 512}
c801d85f 513
60acb947 514bool wxApp::Initialized()
c801d85f 515{
ec758a20 516 return m_initialized;
ff7b1510 517}
c801d85f 518
60acb947 519bool wxApp::Pending()
c801d85f 520{
acfd422a 521 return (gtk_events_pending() > 0);
ff7b1510 522}
c801d85f 523
60acb947 524void wxApp::Dispatch()
c801d85f 525{
8801832d 526 gtk_main_iteration();
ff7b1510 527}
c801d85f 528
7214297d
GL
529#if wxUSE_THREADS
530void wxApp::ProcessPendingEvents()
531{
4d3a259a
GL
532 wxNode *node = wxPendingEvents->First();
533 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
7214297d
GL
534
535 while (node)
536 {
537 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
538
539 handler->ProcessPendingEvents();
e146b8c8 540
7214297d
GL
541 delete node;
542
4d3a259a 543 node = wxPendingEvents->First();
7214297d
GL
544 }
545}
8801832d 546#endif // wxUSE_THREADS
7214297d 547
60acb947 548void wxApp::DeletePendingObjects()
c801d85f 549{
ec758a20
RR
550 wxNode *node = wxPendingDelete.First();
551 while (node)
552 {
553 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 554
ec758a20 555 delete obj;
c801d85f 556
f03fc89f
VZ
557 if (wxPendingDelete.Find(obj))
558 delete node;
c801d85f 559
ec758a20
RR
560 node = wxPendingDelete.First();
561 }
ff7b1510 562}
c801d85f 563
60acb947 564bool wxApp::Initialize()
c801d85f 565{
9cc7a35d 566 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
567
568 wxClassInfo::InitializeClasses();
60acb947 569
0d2a2b60 570 wxSystemSettings::Init();
60acb947 571
4d3a259a
GL
572 // GL: I'm annoyed ... I don't know where to put this and I don't want to
573 // create a module for that as it's part of the core.
574#if wxUSE_THREADS
575 wxPendingEvents = new wxList();
576 wxPendingEventsLocker = new wxCriticalSection();
577#endif
578
36b3b54a 579/*
0d2a2b60
RR
580 wxTheFontNameDirectory = new wxFontNameDirectory;
581 wxTheFontNameDirectory->Initialize();
36b3b54a 582*/
c801d85f 583
0d2a2b60
RR
584 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
585 wxTheColourDatabase->Initialize();
a3622daa 586
0d2a2b60
RR
587 wxInitializeStockLists();
588 wxInitializeStockObjects();
c801d85f 589
06cfab17 590#if wxUSE_WX_RESOURCES
0d2a2b60 591 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 592
0d2a2b60 593 wxInitializeResourceSystem();
f5abe911 594#endif
0cf2cb36 595
0d2a2b60 596 wxImage::InitStandardHandlers();
e0253070 597
0d2a2b60
RR
598 wxModule::RegisterModules();
599 if (!wxModule::InitializeModules()) return FALSE;
60acb947 600
0d2a2b60 601 return TRUE;
ff7b1510 602}
c801d85f 603
60acb947 604void wxApp::CleanUp()
c801d85f 605{
0d2a2b60 606 wxModule::CleanUpModules();
0cf2cb36 607
06cfab17 608#if wxUSE_WX_RESOURCES
ec758a20 609 wxFlushResources();
a3622daa 610
60acb947
VZ
611 if (wxTheResourceCache)
612 delete wxTheResourceCache;
bbe0af5b 613 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 614
f5abe911
RR
615 wxCleanUpResourceSystem();
616#endif
a3622daa 617
60acb947
VZ
618 if (wxTheColourDatabase)
619 delete wxTheColourDatabase;
0d2a2b60 620 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 621
36b3b54a 622/*
0d2a2b60
RR
623 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
624 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 625*/
60acb947 626
0d2a2b60
RR
627 wxDeleteStockObjects();
628
ec758a20 629 wxDeleteStockLists();
a3622daa 630
ec758a20 631 wxImage::CleanUpHandlers();
0cf2cb36 632
0d2a2b60
RR
633 delete wxTheApp;
634 wxTheApp = (wxApp*) NULL;
635
4d3a259a
GL
636 // GL: I'm annoyed ... I don't know where to put this and I don't want to
637 // create a module for that as it's part of the core.
638#if wxUSE_THREADS
639 delete wxPendingEvents;
640 delete wxPendingEventsLocker;
641#endif
642
3e61c765 643 wxSystemSettings::Done();
60acb947 644
3e61c765
RR
645 delete[] wxBuffer;
646
647 wxClassInfo::CleanUpClasses();
60acb947
VZ
648
649 // check for memory leaks
0d2a2b60
RR
650#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
651 if (wxDebugContext::CountObjectsLeft() > 0)
652 {
9cc7a35d 653 wxLogDebug(_T("There were memory leaks.\n"));
0d2a2b60
RR
654 wxDebugContext::Dump();
655 wxDebugContext::PrintStatistics();
656 }
8801832d 657#endif // Debug
0d2a2b60 658
88ac883a 659#if wxUSE_LOG
60acb947 660 // do this as the very last thing because everything else can log messages
0d2a2b60 661 wxLog::DontCreateOnDemand();
60acb947 662
0d2a2b60 663 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
664 if (oldLog)
665 delete oldLog;
ff7b1510 666}
0cf2cb36 667
88ac883a 668#endif // wxUSE_LOG
c801d85f
KB
669
670//-----------------------------------------------------------------------------
671// wxEntry
672//-----------------------------------------------------------------------------
673
674int wxEntry( int argc, char *argv[] )
675{
0d2a2b60 676 gtk_set_locale();
c801d85f 677
dcf924a3 678 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
002f4218 679
0d2a2b60 680 gtk_init( &argc, &argv );
0cf2cb36 681
f0492f7d 682 wxSetDetectableAutoRepeat( TRUE );
094637f6 683
60acb947
VZ
684 if (!wxApp::Initialize())
685 return -1;
0cf2cb36 686
ec758a20 687 if (!wxTheApp)
c801d85f 688 {
60acb947 689 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
9cc7a35d 690 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 691
ec758a20 692 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 693
ec758a20 694 wxObject *test_app = app_ini();
0cf2cb36 695
ec758a20
RR
696 wxTheApp = (wxApp*) test_app;
697 }
0cf2cb36 698
9cc7a35d 699 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
c801d85f 700
ec758a20 701 wxTheApp->argc = argc;
6de92826
OK
702#if wxUSE_UNICODE
703 wxTheApp->argv = new wxChar*[argc+1];
704 int mb_argc = 0;
705 while (mb_argc < argc) {
706 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
707 mb_argc++;
708 }
709 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
710#else
ec758a20 711 wxTheApp->argv = argv;
6de92826 712#endif
0cf2cb36 713
8801832d 714 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
715 wxStripExtension( name );
716 wxTheApp->SetAppName( name );
e0253070 717
0151c3eb
VZ
718 int retValue = 0;
719
720 if ( !wxTheApp->OnInitGui() )
721 retValue = -1;
c801d85f 722
8801832d
VZ
723 // Here frames insert themselves automatically into wxTopLevelWindows by
724 // getting created in OnInit().
0151c3eb
VZ
725 if ( retValue == 0 )
726 {
727 if ( !wxTheApp->OnInit() )
728 retValue = -1;
729 }
0cf2cb36 730
0151c3eb
VZ
731 if ( retValue == 0 )
732 {
cfb50f14 733 /* delete pending toplevel windows (typically a single
094637f6
VZ
734 dialog) so that, if there isn't any left, we don't
735 call OnRun() */
cfb50f14 736 wxTheApp->DeletePendingObjects();
094637f6 737
0151c3eb 738 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 739
0151c3eb 740 if (wxTheApp->Initialized())
094637f6 741 {
0151c3eb 742 retValue = wxTheApp->OnRun();
0cf2cb36 743
cfb50f14
RR
744 wxWindow *topWindow = wxTheApp->GetTopWindow();
745 if (topWindow)
0151c3eb 746 {
cfb50f14
RR
747 /* Forcibly delete the window. */
748 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
749 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
750 {
751 topWindow->Close( TRUE );
752 wxTheApp->DeletePendingObjects();
753 }
754 else
755 {
756 delete topWindow;
757 wxTheApp->SetTopWindow( (wxWindow*) NULL );
758 }
094637f6 759 }
cfb50f14 760 wxTheApp->OnExit();
0d2a2b60 761 }
0151c3eb 762 }
0cf2cb36 763
88ac883a 764#if wxUSE_LOG
60acb947 765 // flush the logged messages if any
0d2a2b60
RR
766 wxLog *log = wxLog::GetActiveTarget();
767 if (log != NULL && log->HasPendingMessages())
768 log->Flush();
769
60acb947
VZ
770 // continuing to use user defined log target is unsafe from now on because
771 // some resources may be already unavailable, so replace it by something
772 // more safe
773 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
774 if ( oldlog )
775 delete oldlog;
88ac883a 776#endif // wxUSE_LOG
60acb947 777
0d2a2b60 778 wxApp::CleanUp();
184b5d99 779
ec758a20 780 return retValue;
ff7b1510 781}
1a56f55c 782
094637f6
VZ
783#include "wx/gtk/info.xpm"
784#include "wx/gtk/error.xpm"
785#include "wx/gtk/question.xpm"
786#include "wx/gtk/warning.xpm"
787
ebea0891
KB
788wxIcon
789wxApp::GetStdIcon(int which) const
790{
094637f6
VZ
791 switch(which)
792 {
793 case wxICON_INFORMATION:
794 return wxIcon(info_xpm);
795
796 case wxICON_QUESTION:
797 return wxIcon(question_xpm);
798
799 case wxICON_EXCLAMATION:
800 return wxIcon(warning_xpm);
801
802 default:
6de92826 803 wxFAIL_MSG(_T("requested non existent standard icon"));
094637f6
VZ
804 // still fall through
805
806 case wxICON_HAND:
807 return wxIcon(error_xpm);
808 }
ebea0891 809}