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" 
  24 #if wxUSE_WX_RESOURCES 
  25     #include "wx/resource.h" 
  28 #include "wx/module.h" 
  31 #include "wx/thread.h" 
  39 #include "wx/gtk/win_gtk.h" 
  41 //----------------------------------------------------------------------------- 
  43 //----------------------------------------------------------------------------- 
  45 wxApp 
*wxTheApp 
= (wxApp 
*)  NULL
; 
  46 wxAppInitializerFunction 
wxApp::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
  48 extern wxList wxPendingDelete
; 
  49 extern wxResourceCache 
*wxTheResourceCache
; 
  51 unsigned char g_palette
[64*3] = 
 119 //----------------------------------------------------------------------------- 
 121 //----------------------------------------------------------------------------- 
 123 extern void wxFlushResources(void); 
 125 //----------------------------------------------------------------------------- 
 127 //----------------------------------------------------------------------------- 
 136     while (gtk_events_pending() > 0) gtk_main_iteration(); 
 140 //----------------------------------------------------------------------------- 
 142 //----------------------------------------------------------------------------- 
 144 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
) 
 146 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
 147     EVT_IDLE(wxApp::OnIdle
) 
 150 gint 
wxapp_idle_callback( gpointer 
WXUNUSED(data
) ) 
 154         while (wxTheApp
->ProcessIdle()) 
 170     m_topWindow 
= (wxWindow 
*) NULL
; 
 171     m_exitOnFrameDelete 
= TRUE
; 
 173     m_idleTag 
= gtk_idle_add( wxapp_idle_callback
, (gpointer
) NULL 
); 
 175     m_colorCube 
= (unsigned char*) NULL
; 
 180     gtk_idle_remove( m_idleTag 
); 
 182     if (m_colorCube
) free(m_colorCube
); 
 185 bool wxApp::OnInitGui() 
 187     /* Nothing to do for 15, 16, 24, 32 bit displays */ 
 189     GdkVisual 
*visual 
= gdk_visual_get_system(); 
 190     if (visual
->depth 
> 8) return TRUE
; 
 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 
 197            NOTE: this doesn't really seem to work this way... */ 
 200         GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); 
 202         for (int i = 0; i < 64; i++) 
 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; 
 210             gdk_color_alloc( cmap, &col ); 
 213         gtk_widget_set_default_colormap( cmap ); 
 216     /* initialize color cube for 8-bit color reduction dithering */ 
 218     GdkColormap 
*cmap 
= gtk_widget_get_default_colormap(); 
 220     m_colorCube 
= (unsigned char*)malloc(32 * 32 * 32); 
 222      for (int r 
= 0; r 
< 32; r
++) 
 224         for (int g 
= 0; g 
< 32; g
++) 
 226             for (int b 
= 0; b 
< 32; b
++) 
 228                 int rr 
= (r 
<< 3) | (r 
>> 2); 
 229                 int gg 
= (g 
<< 3) | (g 
>> 2); 
 230                 int bb 
= (b 
<< 3) | (b 
>> 2); 
 232                 GdkColor 
*colors 
= cmap
->colors
; 
 233                 int max 
= 3 * (65536); 
 236                 for (int i 
= 0; i 
< cmap
->size
; i
++) 
 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
; } 
 245                 m_colorCube
[ (r
*1024) + (g
*32) + b 
] = index
; 
 254 bool wxApp::ProcessIdle() 
 257     event
.SetEventObject( this ); 
 258     ProcessEvent( event 
); 
 260     return event
.MoreRequested(); 
 263 void wxApp::OnIdle( wxIdleEvent 
&event 
) 
 265     static bool inOnIdle 
= FALSE
; 
 267     /* Avoid recursion (via ProcessEvent default case) */ 
 273     /* 'Garbage' collection of windows deleted with Close(). */ 
 274     DeletePendingObjects(); 
 276     /* flush the logged messages if any */ 
 277     wxLog 
*log 
= wxLog::GetActiveTarget(); 
 278     if (log 
!= NULL 
&& log
->HasPendingMessages()) 
 281     /* Send OnIdle events to all windows */ 
 282     bool needMore 
= SendIdleEvents(); 
 285         event
.RequestMore(TRUE
); 
 290 bool wxApp::SendIdleEvents() 
 292     bool needMore 
= FALSE
; 
 294     wxNode
* node 
= wxTopLevelWindows
.First(); 
 297         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 298         if (SendIdleEvents(win
)) 
 305 bool wxApp::SendIdleEvents( wxWindow
* win 
) 
 307     bool needMore 
= FALSE
; 
 310     event
.SetEventObject(win
); 
 312     win
->OnInternalIdle(); 
 314     win
->ProcessEvent(event
); 
 316     if (event
.MoreRequested()) 
 319     wxNode
* node 
= win
->GetChildren().First(); 
 322         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 323         if (SendIdleEvents(win
)) 
 331 int wxApp::MainLoop() 
 337 void wxApp::ExitMainLoop() 
 342 bool wxApp::Initialized() 
 344     return m_initialized
; 
 347 bool wxApp::Pending() 
 352 void wxApp::Dispatch() 
 356 void wxApp::DeletePendingObjects() 
 358     wxNode 
*node 
= wxPendingDelete
.First(); 
 361         wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
 365         if (wxPendingDelete
.Member(obj
)) 
 368         node 
= wxPendingDelete
.First(); 
 372 wxWindow 
*wxApp::GetTopWindow() 
 374     if (m_topWindow
) return m_topWindow
; 
 375     wxNode 
*node 
= wxTopLevelWindows
.First(); 
 376     if (!node
) return (wxWindow 
*) NULL
; 
 377     return (wxWindow
*)node
->Data(); 
 380 void wxApp::SetTopWindow( wxWindow 
*win 
) 
 385 bool wxApp::Initialize() 
 387     wxBuffer 
= new char[BUFSIZ 
+ 512]; 
 389     wxClassInfo::InitializeClasses(); 
 391     wxSystemSettings::Init(); 
 394     wxTheFontNameDirectory =  new wxFontNameDirectory; 
 395     wxTheFontNameDirectory->Initialize(); 
 398     wxTheColourDatabase 
= new wxColourDatabase( wxKEY_STRING 
); 
 399     wxTheColourDatabase
->Initialize(); 
 401     wxInitializeStockLists(); 
 402     wxInitializeStockObjects(); 
 404 #if wxUSE_WX_RESOURCES 
 405     wxTheResourceCache 
= new wxResourceCache( wxKEY_STRING 
); 
 407     wxInitializeResourceSystem(); 
 410     wxImage::InitStandardHandlers(); 
 412     /* no global cursor under X 
 413        g_globalCursor = new wxCursor; */ 
 415     wxModule::RegisterModules(); 
 416     if (!wxModule::InitializeModules()) return FALSE
; 
 421 void wxApp::CleanUp() 
 423     wxModule::CleanUpModules(); 
 425 #if wxUSE_WX_RESOURCES 
 428     if (wxTheResourceCache
) 
 429         delete wxTheResourceCache
; 
 430     wxTheResourceCache 
= (wxResourceCache
*) NULL
; 
 432     wxCleanUpResourceSystem(); 
 435     if (wxTheColourDatabase
) 
 436         delete wxTheColourDatabase
; 
 437     wxTheColourDatabase 
= (wxColourDatabase
*) NULL
; 
 440     if (wxTheFontNameDirectory) delete wxTheFontNameDirectory; 
 441     wxTheFontNameDirectory = (wxFontNameDirectory*) NULL; 
 444     wxDeleteStockObjects(); 
 446     wxDeleteStockLists(); 
 448     wxImage::CleanUpHandlers(); 
 451     wxTheApp 
= (wxApp
*) NULL
; 
 453     wxSystemSettings::Done(); 
 457     wxClassInfo::CleanUpClasses(); 
 459     // check for memory leaks 
 460 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 461     if (wxDebugContext::CountObjectsLeft() > 0) 
 463         wxLogDebug("There were memory leaks.\n"); 
 464         wxDebugContext::Dump(); 
 465         wxDebugContext::PrintStatistics(); 
 469     // do this as the very last thing because everything else can log messages 
 470     wxLog::DontCreateOnDemand(); 
 472     wxLog 
*oldLog 
= wxLog::SetActiveTarget( (wxLog
*) NULL 
); 
 477 wxLog 
*wxApp::CreateLogTarget() 
 482 //----------------------------------------------------------------------------- 
 484 //----------------------------------------------------------------------------- 
 486 int wxEntry( int argc
, char *argv
[] ) 
 490     gtk_init( &argc
, &argv 
); 
 492     if (!wxApp::Initialize()) 
 497         wxCHECK_MSG( wxApp::GetInitializerFunction(), -1, 
 498                      "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" ); 
 500         wxAppInitializerFunction app_ini 
= wxApp::GetInitializerFunction(); 
 502         wxObject 
*test_app 
= app_ini(); 
 504         wxTheApp 
= (wxApp
*) test_app
; 
 507     wxCHECK_MSG( wxTheApp
, -1, "wxWindows error: no application object" ); 
 509     wxTheApp
->argc 
= argc
; 
 510     wxTheApp
->argv 
= argv
; 
 513     strcpy( name
, argv
[0] ); 
 514     strcpy( name
, wxFileNameFromPath(name
) ); 
 515     wxStripExtension( name 
); 
 516     wxTheApp
->SetAppName( name 
); 
 518     if (!wxTheApp
->OnInitGui()) 
 521     /* Here frames insert themselves automatically 
 522      * into wxTopLevelWindows by getting created 
 525     if (!wxTheApp
->OnInit()) 
 528     wxTheApp
->m_initialized 
= (wxTopLevelWindows
.Number() > 0); 
 532     if (wxTheApp
->Initialized()) 
 533         retValue 
= wxTheApp
->OnRun(); 
 535     wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 538         // Forcibly delete the window. 
 539         if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 540             topWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 542             topWindow
->Close( TRUE 
); 
 543             wxTheApp
->DeletePendingObjects(); 
 548             wxTheApp
->SetTopWindow( (wxWindow
*) NULL 
); 
 554     // flush the logged messages if any 
 555     wxLog 
*log 
= wxLog::GetActiveTarget(); 
 556     if (log 
!= NULL 
&& log
->HasPendingMessages()) 
 559     // continuing to use user defined log target is unsafe from now on because 
 560     // some resources may be already unavailable, so replace it by something 
 562     wxLog 
*oldlog 
= wxLog::SetActiveTarget(new wxLogStderr
);