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