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