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