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