]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
Added (untested) support for sub-locales.
[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__
11#pragma implementation "app.h"
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"
06cfab17 23#if wxUSE_WX_RESOURCES
8d71b555 24#include "wx/resource.h"
f5abe911 25#endif
031b2a7b 26#include "wx/module.h"
4bc67cc5 27#include "wx/image.h"
06cfab17 28#if wxUSE_THREADS
f3855ef0 29#include "wx/thread.h"
ac57418f 30#endif
c801d85f
KB
31#include "unistd.h"
32
24178e4a 33#ifdef __SUN__
38044011
KB
34extern "C"
35{
36void usleep(unsigned long usec);
37};
24178e4a
KB
38#endif
39
83624f79
RR
40#include "glib.h"
41#include "gdk/gdk.h"
42#include "gtk/gtk.h"
43#include "wx/gtk/win_gtk.h"
44
69919241
KB
45#include <unistd.h> // usleep() on solaris
46
c801d85f
KB
47//-----------------------------------------------------------------------------
48// global data
49//-----------------------------------------------------------------------------
50
c67daf87 51wxApp *wxTheApp = (wxApp *) NULL;
c801d85f
KB
52wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
53
54extern wxList wxPendingDelete;
a3622daa 55extern wxResourceCache *wxTheResourceCache;
c801d85f 56
01111366
RR
57unsigned char g_palette[64*3] =
58{
59 0x0, 0x0, 0x0,
60 0xff, 0xff, 0xff,
61 0xff, 0x0, 0x0,
62 0xff, 0xff, 0x0,
63 0x0, 0xff, 0x0,
64 0x0, 0x0, 0xff,
65 0x0, 0xff, 0xff,
66 0x99, 0x99, 0x99,
67 0xff, 0x88, 0x0,
68 0x88, 0x0, 0x0,
69 0x0, 0x88, 0x88,
70 0x88, 0x88, 0x0,
71 0xff, 0xcc, 0x97,
72 0xbb, 0xbb, 0xbb,
73 0x9f, 0x6b, 0x42,
74 0x55, 0x55, 0x55,
75 0xdd, 0xdd, 0xdd,
76 0x77, 0x77, 0x77,
77 0x33, 0x33, 0x33,
78 0xcc, 0x0, 0x0,
79 0xff, 0x44, 0x0,
80 0xff, 0xcc, 0x0,
81 0xcc, 0xcc, 0x0,
82 0x60, 0x60, 0x0,
83 0x0, 0x43, 0x0,
84 0x0, 0x7f, 0x0,
85 0x0, 0xcc, 0x0,
86 0x0, 0x44, 0x44,
87 0x0, 0x0, 0x44,
88 0x0, 0x0, 0x88,
89 0xef, 0xb1, 0x7b,
90 0xdf, 0x98, 0x5f,
91 0xbf, 0x87, 0x56,
92 0x7f, 0x57, 0x26,
93 0x5f, 0x39, 0xc,
94 0x3f, 0x1c, 0x0,
95 0x21, 0x0, 0x0,
96 0x0, 0x43, 0x87,
97 0x2d, 0x70, 0xaf,
98 0x5a, 0x9e, 0xd7,
99 0x87, 0xcc, 0xff,
100 0xff, 0xe0, 0xba,
101 0x21, 0x43, 0xf,
102 0x3d, 0x5d, 0x25,
103 0x59, 0x78, 0x3a,
104 0x75, 0x93, 0x4f,
105 0x91, 0xae, 0x64,
106 0xad, 0xc8, 0x7a,
e0253070 107 0xf0, 0xa8, 0xef,
01111366
RR
108 0xd0, 0x88, 0xd0,
109 0xaf, 0x66, 0xaf,
110 0x8e, 0x44, 0x8e,
111 0x6d, 0x22, 0x6d,
e0253070 112 0x4b, 0x0, 0x4b,
01111366
RR
113 0xff, 0xc0, 0xbc,
114 0xff, 0x93, 0x91,
115 0xff, 0x66, 0x67,
116 0xd8, 0xf2, 0xbf,
117 0xff, 0xc9, 0x68,
118 0xff, 0x96, 0x67,
119 0xa5, 0x60, 0xff,
120 0x51, 0xff, 0x99,
121 0x3f, 0xa5, 0x63,
122 0x98, 0x90, 0x67
123};
124
c801d85f
KB
125//-----------------------------------------------------------------------------
126// local functions
127//-----------------------------------------------------------------------------
128
129extern void wxFlushResources(void);
130
131//-----------------------------------------------------------------------------
132// global functions
133//-----------------------------------------------------------------------------
134
135void wxExit(void)
136{
ec758a20 137 gtk_main_quit();
ff7b1510 138}
c801d85f
KB
139
140bool wxYield(void)
141{
ec758a20
RR
142 while (gtk_events_pending() > 0) gtk_main_iteration();
143 return TRUE;
ff7b1510 144}
c801d85f
KB
145
146//-----------------------------------------------------------------------------
147// wxApp
148//-----------------------------------------------------------------------------
149
150IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
151
53010e52
RR
152BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
153 EVT_IDLE(wxApp::OnIdle)
154END_EVENT_TABLE()
155
c801d85f
KB
156gint wxapp_idle_callback( gpointer WXUNUSED(data) )
157{
ec758a20 158 if (wxTheApp) while (wxTheApp->ProcessIdle()) {}
06cfab17 159#if wxUSE_THREADS
f3855ef0 160 wxMutexGuiLeave();
ac57418f 161#endif
f3855ef0 162 usleep(10000);
06cfab17 163#if wxUSE_THREADS
f3855ef0 164 wxMutexGuiEnter();
ac57418f 165#endif
ec758a20 166 return TRUE;
ff7b1510 167}
c801d85f
KB
168
169wxApp::wxApp()
170{
0d2a2b60
RR
171 wxTheApp = this;
172
ec758a20
RR
173 m_topWindow = (wxWindow *) NULL;
174 m_exitOnFrameDelete = TRUE;
0d2a2b60
RR
175
176 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
177
f6fcbb63 178 m_colorCube = (unsigned char*) NULL;
ff7b1510 179}
c801d85f
KB
180
181wxApp::~wxApp(void)
182{
ec758a20 183 gtk_idle_remove( m_idleTag );
f6fcbb63
RR
184
185 if (m_colorCube) free(m_colorCube);
ff7b1510 186}
c801d85f 187
0d2a2b60 188bool wxApp::OnInitGui()
c801d85f 189{
f6fcbb63
RR
190 /* Nothing to do for 15, 16, 24, 32 bit displays */
191
192 GdkVisual *visual = gdk_visual_get_system();
193 if (visual->depth > 8) return TRUE;
bbe0af5b 194
0d2a2b60
RR
195 /* this initiates the standard palette as defined by GdkImlib
196 in the GNOME libraries. it ensures that all GNOME applications
197 use the same 64 colormap entries on 8-bit displays so you
198 can use several rather graphics-heavy applications at the
199 same time.
200 NOTE: this doesn't really seem to work this way... */
bbe0af5b 201
0d2a2b60
RR
202 /*
203 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 204
0d2a2b60
RR
205 for (int i = 0; i < 64; i++)
206 {
207 GdkColor col;
208 col.red = g_palette[i*3 + 0] << 8;
209 col.green = g_palette[i*3 + 1] << 8;
210 col.blue = g_palette[i*3 + 2] << 8;
211 col.pixel = 0;
212
213 gdk_color_alloc( cmap, &col );
214 }
aae24d21 215
0d2a2b60
RR
216 gtk_widget_set_default_colormap( cmap );
217 */
f6fcbb63
RR
218
219 /* initialize color cube for 8-bit color reduction dithering */
220
221 GdkColormap *cmap = gtk_widget_get_default_colormap();
222
223 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
224
225 for (int r = 0; r < 32; r++)
226 {
227 for (int g = 0; g < 32; g++)
228 {
229 for (int b = 0; b < 32; b++)
230 {
231 int rr = (r << 3) | (r >> 2);
232 int gg = (g << 3) | (g >> 2);
233 int bb = (b << 3) | (b >> 2);
234
235 GdkColor *colors = cmap->colors;
236 int max = 3 * (65536);
237 int index = -1;
238
239 for (int i = 0; i < cmap->size; i++)
240 {
241 int rdiff = ((rr << 8) - colors[i].red);
242 int gdiff = ((gg << 8)- colors[i].green);
243 int bdiff = ((bb << 8)- colors[i].blue);
244 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
245 if (sum < max) { index = i; max = sum; }
246 }
247
248 m_colorCube[ (r*1024) + (g*32) + b ] = index;
249 }
250 }
251 }
c801d85f 252
bbe0af5b
RR
253
254 return TRUE;
255}
256
53010e52
RR
257bool wxApp::ProcessIdle(void)
258{
ec758a20
RR
259 wxIdleEvent event;
260 event.SetEventObject( this );
261 ProcessEvent( event );
0cf2cb36 262
ec758a20 263 return event.MoreRequested();
ff7b1510 264}
53010e52
RR
265
266void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 267{
ec758a20 268 static bool inOnIdle = FALSE;
53010e52 269
d524867f 270 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
271 if (inOnIdle)
272 return;
53010e52 273
ec758a20 274 inOnIdle = TRUE;
53010e52 275
d524867f 276 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 277 DeletePendingObjects();
53010e52 278
d524867f
RR
279 /* flush the logged messages if any */
280 wxLog *log = wxLog::GetActiveTarget();
281 if (log != NULL && log->HasPendingMessages())
282 log->Flush();
53010e52 283
d524867f 284 /* Send OnIdle events to all windows */
ec758a20 285 bool needMore = SendIdleEvents();
53010e52 286
ec758a20
RR
287 if (needMore)
288 event.RequestMore(TRUE);
53010e52 289
ec758a20 290 inOnIdle = FALSE;
ff7b1510 291}
53010e52
RR
292
293bool wxApp::SendIdleEvents(void)
294{
295 bool needMore = FALSE;
e0253070 296
ec758a20
RR
297 wxNode* node = wxTopLevelWindows.First();
298 while (node)
299 {
f3855ef0
RR
300 wxWindow* win = (wxWindow*) node->Data();
301 if (SendIdleEvents(win))
53010e52 302 needMore = TRUE;
ec758a20
RR
303 node = node->Next();
304 }
53010e52 305 return needMore;
ff7b1510 306}
53010e52
RR
307
308bool wxApp::SendIdleEvents( wxWindow* win )
309{
310 bool needMore = FALSE;
311
8bbe427f
VZ
312 wxIdleEvent event;
313 event.SetEventObject(win);
9390a202
RR
314
315 win->OnInternalIdle();
316
8bbe427f 317 win->ProcessEvent(event);
53010e52
RR
318
319 if (event.MoreRequested())
320 needMore = TRUE;
321
8bbe427f
VZ
322 wxNode* node = win->GetChildren().First();
323 while (node)
324 {
325 wxWindow* win = (wxWindow*) node->Data();
326 if (SendIdleEvents(win))
53010e52
RR
327 needMore = TRUE;
328
8bbe427f
VZ
329 node = node->Next();
330 }
53010e52 331 return needMore ;
ff7b1510 332}
c801d85f 333
c801d85f
KB
334int wxApp::MainLoop(void)
335{
ec758a20
RR
336 gtk_main();
337 return 0;
ff7b1510 338}
c801d85f
KB
339
340void wxApp::ExitMainLoop(void)
341{
ec758a20 342 gtk_main_quit();
ff7b1510 343}
c801d85f
KB
344
345bool wxApp::Initialized(void)
346{
ec758a20 347 return m_initialized;
ff7b1510 348}
c801d85f 349
0cf2cb36 350bool wxApp::Pending(void)
c801d85f 351{
ec758a20 352 return FALSE;
ff7b1510 353}
c801d85f 354
0cf2cb36 355void wxApp::Dispatch(void)
c801d85f 356{
ff7b1510 357}
c801d85f
KB
358
359void wxApp::DeletePendingObjects(void)
360{
ec758a20
RR
361 wxNode *node = wxPendingDelete.First();
362 while (node)
363 {
364 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 365
ec758a20 366 delete obj;
c801d85f 367
ec758a20
RR
368 if (wxPendingDelete.Member(obj))
369 delete node;
c801d85f 370
ec758a20
RR
371 node = wxPendingDelete.First();
372 }
ff7b1510 373}
c801d85f
KB
374
375wxWindow *wxApp::GetTopWindow(void)
376{
ec758a20
RR
377 if (m_topWindow) return m_topWindow;
378 wxNode *node = wxTopLevelWindows.First();
379 if (!node) return (wxWindow *) NULL;
380 return (wxWindow*)node->Data();
ff7b1510 381}
c801d85f
KB
382
383void wxApp::SetTopWindow( wxWindow *win )
384{
ec758a20 385 m_topWindow = win;
ff7b1510 386}
c801d85f 387
0d2a2b60 388bool wxApp::Initialize(void)
c801d85f 389{
0d2a2b60
RR
390 wxBuffer = new char[BUFSIZ + 512];
391
392 wxClassInfo::InitializeClasses();
393
394 wxSystemSettings::Init();
f5abe911 395
36b3b54a 396/*
0d2a2b60
RR
397 wxTheFontNameDirectory = new wxFontNameDirectory;
398 wxTheFontNameDirectory->Initialize();
36b3b54a 399*/
c801d85f 400
0d2a2b60
RR
401 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
402 wxTheColourDatabase->Initialize();
a3622daa 403
0d2a2b60
RR
404 wxInitializeStockLists();
405 wxInitializeStockObjects();
c801d85f 406
06cfab17 407#if wxUSE_WX_RESOURCES
0d2a2b60 408 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
f5abe911 409
0d2a2b60 410 wxInitializeResourceSystem();
f5abe911 411#endif
0cf2cb36 412
0d2a2b60 413 wxImage::InitStandardHandlers();
e0253070 414
0d2a2b60
RR
415 /* no global cursor under X
416 g_globalCursor = new wxCursor; */
417
418 wxModule::RegisterModules();
419 if (!wxModule::InitializeModules()) return FALSE;
420
421 return TRUE;
ff7b1510 422}
c801d85f 423
0d2a2b60 424void wxApp::CleanUp(void)
c801d85f 425{
0d2a2b60 426 wxModule::CleanUpModules();
0cf2cb36 427
06cfab17 428#if wxUSE_WX_RESOURCES
ec758a20 429 wxFlushResources();
a3622daa 430
bbe0af5b
RR
431 if (wxTheResourceCache) delete wxTheResourceCache;
432 wxTheResourceCache = (wxResourceCache*) NULL;
f5abe911
RR
433
434 wxCleanUpResourceSystem();
435#endif
a3622daa 436
0d2a2b60
RR
437 if (wxTheColourDatabase) delete wxTheColourDatabase;
438 wxTheColourDatabase = (wxColourDatabase*) NULL;
439
36b3b54a 440/*
0d2a2b60
RR
441 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
442 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 443*/
0d2a2b60
RR
444
445 wxDeleteStockObjects();
446
ec758a20 447 wxDeleteStockLists();
a3622daa 448
ec758a20 449 wxImage::CleanUpHandlers();
0cf2cb36 450
0d2a2b60
RR
451 delete wxTheApp;
452 wxTheApp = (wxApp*) NULL;
453
3e61c765
RR
454 wxSystemSettings::Done();
455
456 delete[] wxBuffer;
457
458 wxClassInfo::CleanUpClasses();
459
0d2a2b60
RR
460 /* check for memory leaks */
461#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
462 if (wxDebugContext::CountObjectsLeft() > 0)
463 {
464 wxLogDebug("There were memory leaks.\n");
465 wxDebugContext::Dump();
466 wxDebugContext::PrintStatistics();
467 }
468#endif
469
470 /* do this as the very last thing because everything else can log messages */
471 wxLog::DontCreateOnDemand();
472
473 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
474 if (oldLog) delete oldLog;
ff7b1510 475}
0cf2cb36 476
c801d85f
KB
477wxLog *wxApp::CreateLogTarget()
478{
0d2a2b60 479 return new wxLogGui;
c801d85f
KB
480}
481
482//-----------------------------------------------------------------------------
483// wxEntry
484//-----------------------------------------------------------------------------
485
486int wxEntry( int argc, char *argv[] )
487{
0d2a2b60 488 gtk_set_locale();
c801d85f 489
0d2a2b60 490 gtk_init( &argc, &argv );
0cf2cb36 491
0d2a2b60 492 if (!wxApp::Initialize()) return 0;
0cf2cb36 493
ec758a20 494 if (!wxTheApp)
c801d85f 495 {
ec758a20
RR
496 if (!wxApp::GetInitializerFunction())
497 {
498 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
499 return 0;
500 }
0cf2cb36 501
ec758a20 502 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 503
ec758a20 504 wxObject *test_app = app_ini();
0cf2cb36 505
ec758a20
RR
506 wxTheApp = (wxApp*) test_app;
507 }
0cf2cb36 508
ec758a20
RR
509 if (!wxTheApp)
510 {
511 printf( "wxWindows error: wxTheApp == NULL\n" );
512 return 0;
513 }
c801d85f 514
ec758a20
RR
515 wxTheApp->argc = argc;
516 wxTheApp->argv = argv;
0cf2cb36 517
ec758a20
RR
518 char name[200];
519 strcpy( name, argv[0] );
520 strcpy( name, wxFileNameFromPath(name) );
521 wxStripExtension( name );
522 wxTheApp->SetAppName( name );
e0253070 523
bbe0af5b 524 if (!wxTheApp->OnInitGui()) return 0;
c801d85f 525
0d2a2b60
RR
526 /* Here frames insert themselves automatically
527 * into wxTopLevelWindows by getting created
528 * in OnInit(). */
0cf2cb36 529
ec758a20 530 if (!wxTheApp->OnInit()) return 0;
c801d85f 531
ec758a20 532 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
0cf2cb36 533
ec758a20 534 int retValue = 0;
0cf2cb36 535
ec758a20 536 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
0cf2cb36 537
0d2a2b60
RR
538 wxWindow *topWindow = wxTheApp->GetTopWindow();
539 if (topWindow)
ec758a20 540 {
0d2a2b60
RR
541 /* Forcibly delete the window. */
542 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
543 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
544 {
545 topWindow->Close( TRUE );
546 wxTheApp->DeletePendingObjects();
547 }
548 else
549 {
550 delete topWindow;
551 wxTheApp->SetTopWindow( (wxWindow*) NULL );
552 }
ec758a20 553 }
e0253070 554
0d2a2b60 555 wxTheApp->OnExit();
0cf2cb36 556
0d2a2b60
RR
557 /* flush the logged messages if any */
558 wxLog *log = wxLog::GetActiveTarget();
559 if (log != NULL && log->HasPendingMessages())
560 log->Flush();
561
562 wxApp::CleanUp();
184b5d99 563
ec758a20 564 return retValue;
ff7b1510 565}
1a56f55c 566