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