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