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