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