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