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