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