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