1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "app.h"
15 #include "wx/gdicmn.h"
19 #include "wx/memory.h"
21 #include "wx/settings.h"
22 #include "wx/dialog.h"
23 #if wxUSE_WX_RESOURCES
24 #include "wx/resource.h"
26 #include "wx/module.h"
29 #include "wx/thread.h"
33 // add more here if you run into problems
34 #if defined(__SUN__) && !defined(__SunOs_5_6) && !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)
37 void usleep(unsigned long usec
);
44 #include "wx/gtk/win_gtk.h"
46 #include <unistd.h> // usleep() on solaris
48 //-----------------------------------------------------------------------------
50 //-----------------------------------------------------------------------------
52 wxApp
*wxTheApp
= (wxApp
*) NULL
;
53 wxAppInitializerFunction
wxApp::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
55 extern wxList wxPendingDelete
;
56 extern wxResourceCache
*wxTheResourceCache
;
58 unsigned char g_palette
[64*3] =
126 //-----------------------------------------------------------------------------
128 //-----------------------------------------------------------------------------
130 extern void wxFlushResources(void);
132 //-----------------------------------------------------------------------------
134 //-----------------------------------------------------------------------------
143 while (gtk_events_pending() > 0) gtk_main_iteration();
147 //-----------------------------------------------------------------------------
149 //-----------------------------------------------------------------------------
151 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
)
153 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
154 EVT_IDLE(wxApp::OnIdle
)
157 gint
wxapp_idle_callback( gpointer
WXUNUSED(data
) )
159 if (wxTheApp
) while (wxTheApp
->ProcessIdle()) {}
174 m_topWindow
= (wxWindow
*) NULL
;
175 m_exitOnFrameDelete
= TRUE
;
177 m_idleTag
= gtk_idle_add( wxapp_idle_callback
, (gpointer
) NULL
);
179 m_colorCube
= (unsigned char*) NULL
;
184 gtk_idle_remove( m_idleTag
);
186 if (m_colorCube
) free(m_colorCube
);
189 bool wxApp::OnInitGui()
191 /* Nothing to do for 15, 16, 24, 32 bit displays */
193 GdkVisual
*visual
= gdk_visual_get_system();
194 if (visual
->depth
> 8) return TRUE
;
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
201 NOTE: this doesn't really seem to work this way... */
204 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
206 for (int i = 0; i < 64; i++)
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;
214 gdk_color_alloc( cmap, &col );
217 gtk_widget_set_default_colormap( cmap );
220 /* initialize color cube for 8-bit color reduction dithering */
222 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
224 m_colorCube
= (unsigned char*)malloc(32 * 32 * 32);
226 for (int r
= 0; r
< 32; r
++)
228 for (int g
= 0; g
< 32; g
++)
230 for (int b
= 0; b
< 32; b
++)
232 int rr
= (r
<< 3) | (r
>> 2);
233 int gg
= (g
<< 3) | (g
>> 2);
234 int bb
= (b
<< 3) | (b
>> 2);
236 GdkColor
*colors
= cmap
->colors
;
237 int max
= 3 * (65536);
240 for (int i
= 0; i
< cmap
->size
; i
++)
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
; }
249 m_colorCube
[ (r
*1024) + (g
*32) + b
] = index
;
258 bool wxApp::ProcessIdle(void)
261 event
.SetEventObject( this );
262 ProcessEvent( event
);
264 return event
.MoreRequested();
267 void wxApp::OnIdle( wxIdleEvent
&event
)
269 static bool inOnIdle
= FALSE
;
271 /* Avoid recursion (via ProcessEvent default case) */
277 /* 'Garbage' collection of windows deleted with Close(). */
278 DeletePendingObjects();
280 /* flush the logged messages if any */
281 wxLog
*log
= wxLog::GetActiveTarget();
282 if (log
!= NULL
&& log
->HasPendingMessages())
285 /* Send OnIdle events to all windows */
286 bool needMore
= SendIdleEvents();
289 event
.RequestMore(TRUE
);
294 bool wxApp::SendIdleEvents(void)
296 bool needMore
= FALSE
;
298 wxNode
* node
= wxTopLevelWindows
.First();
301 wxWindow
* win
= (wxWindow
*) node
->Data();
302 if (SendIdleEvents(win
))
309 bool wxApp::SendIdleEvents( wxWindow
* win
)
311 bool needMore
= FALSE
;
314 event
.SetEventObject(win
);
316 win
->OnInternalIdle();
318 win
->ProcessEvent(event
);
320 if (event
.MoreRequested())
323 wxNode
* node
= win
->GetChildren().First();
326 wxWindow
* win
= (wxWindow
*) node
->Data();
327 if (SendIdleEvents(win
))
335 int wxApp::MainLoop(void)
341 void wxApp::ExitMainLoop(void)
346 bool wxApp::Initialized(void)
348 return m_initialized
;
351 bool wxApp::Pending(void)
356 void wxApp::Dispatch(void)
360 void wxApp::DeletePendingObjects(void)
362 wxNode
*node
= wxPendingDelete
.First();
365 wxObject
*obj
= (wxObject
*)node
->Data();
369 if (wxPendingDelete
.Member(obj
))
372 node
= wxPendingDelete
.First();
376 wxWindow
*wxApp::GetTopWindow(void)
378 if (m_topWindow
) return m_topWindow
;
379 wxNode
*node
= wxTopLevelWindows
.First();
380 if (!node
) return (wxWindow
*) NULL
;
381 return (wxWindow
*)node
->Data();
384 void wxApp::SetTopWindow( wxWindow
*win
)
389 bool wxApp::Initialize(void)
391 wxBuffer
= new char[BUFSIZ
+ 512];
393 wxClassInfo::InitializeClasses();
395 wxSystemSettings::Init();
398 wxTheFontNameDirectory = new wxFontNameDirectory;
399 wxTheFontNameDirectory->Initialize();
402 wxTheColourDatabase
= new wxColourDatabase( wxKEY_STRING
);
403 wxTheColourDatabase
->Initialize();
405 wxInitializeStockLists();
406 wxInitializeStockObjects();
408 #if wxUSE_WX_RESOURCES
409 wxTheResourceCache
= new wxResourceCache( wxKEY_STRING
);
411 wxInitializeResourceSystem();
414 wxImage::InitStandardHandlers();
416 /* no global cursor under X
417 g_globalCursor = new wxCursor; */
419 wxModule::RegisterModules();
420 if (!wxModule::InitializeModules()) return FALSE
;
425 void wxApp::CleanUp(void)
427 wxModule::CleanUpModules();
429 #if wxUSE_WX_RESOURCES
432 if (wxTheResourceCache
) delete wxTheResourceCache
;
433 wxTheResourceCache
= (wxResourceCache
*) NULL
;
435 wxCleanUpResourceSystem();
438 if (wxTheColourDatabase
) delete wxTheColourDatabase
;
439 wxTheColourDatabase
= (wxColourDatabase
*) NULL
;
442 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
443 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
446 wxDeleteStockObjects();
448 wxDeleteStockLists();
450 wxImage::CleanUpHandlers();
453 wxTheApp
= (wxApp
*) NULL
;
455 wxSystemSettings::Done();
459 wxClassInfo::CleanUpClasses();
461 /* check for memory leaks */
462 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
463 if (wxDebugContext::CountObjectsLeft() > 0)
465 wxLogDebug("There were memory leaks.\n");
466 wxDebugContext::Dump();
467 wxDebugContext::PrintStatistics();
471 /* do this as the very last thing because everything else can log messages */
472 wxLog::DontCreateOnDemand();
474 wxLog
*oldLog
= wxLog::SetActiveTarget( (wxLog
*) NULL
);
475 if (oldLog
) delete oldLog
;
478 wxLog
*wxApp::CreateLogTarget()
483 //-----------------------------------------------------------------------------
485 //-----------------------------------------------------------------------------
487 int wxEntry( int argc
, char *argv
[] )
491 gtk_init( &argc
, &argv
);
493 if (!wxApp::Initialize()) return 0;
497 if (!wxApp::GetInitializerFunction())
499 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
503 wxAppInitializerFunction app_ini
= wxApp::GetInitializerFunction();
505 wxObject
*test_app
= app_ini();
507 wxTheApp
= (wxApp
*) test_app
;
512 printf( "wxWindows error: wxTheApp == NULL\n" );
516 wxTheApp
->argc
= argc
;
517 wxTheApp
->argv
= argv
;
520 strcpy( name
, argv
[0] );
521 strcpy( name
, wxFileNameFromPath(name
) );
522 wxStripExtension( name
);
523 wxTheApp
->SetAppName( name
);
525 if (!wxTheApp
->OnInitGui()) return 0;
527 /* Here frames insert themselves automatically
528 * into wxTopLevelWindows by getting created
531 if (!wxTheApp
->OnInit()) return 0;
533 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
537 if (wxTheApp
->Initialized()) retValue
= wxTheApp
->OnRun();
539 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
542 /* Forcibly delete the window. */
543 if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
544 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
546 topWindow
->Close( TRUE
);
547 wxTheApp
->DeletePendingObjects();
552 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
558 /* flush the logged messages if any */
559 wxLog
*log
= wxLog::GetActiveTarget();
560 if (log
!= NULL
&& log
->HasPendingMessages())