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