? logging.patch
? cygnal/cygnal.patch
? cygnal/testsuite/cygnal.all/site.exp
? cygnal/testsuite/cygnal.all/test_buffer
? cygnal/testsuite/cygnal.all/test_cque
? doc/C/asspec/Makefile
? doc/C/asspec/Makefile.in
? gui/Info.plist
? libbase/rc.loT
? libltdl/COPYING.LIB
? libltdl/Makefile.am
? libltdl/Makefile.in
? libltdl/README
? libltdl/acinclude.m4
? libltdl/aclocal.m4
? libltdl/config-h.in
? libltdl/config.guess
? libltdl/config.sub
? libltdl/configure
? libltdl/configure.ac
? libltdl/install-sh
? libltdl/ltdl.c
? libltdl/ltdl.h
? libltdl/ltmain.sh
? libltdl/missing
? libmedia/.deps
? libmedia/libgnashmedia_la-MediaDecoder.loT
? libnet/.deps
? libnet/.libs
? libnet/Makefile
? libnet/Makefile.in
? libnet/cque.lo
? libnet/gnash.log
? libnet/gnash.sum
? libnet/handler.lo
? libnet/http.lo
? libnet/libgnashnet.la
? libnet/lirc.lo
? libnet/netstats.lo
? libnet/network.lo
? libnet/rtmp.lo
? libnet/rtmp_server.lo
? libnet/site.exp
? libnet/statistics.lo
? po/de.po.autosave
? pythonmodule/.deps
? pythonmodule/gnash.la
? pythonmodule/libgnashpython.la
? pythonmodule/test.py
? server/date.cpp
? testsuite/actionscript.all/gnash.xml
? testsuite/actionscript.all/systemtest.as
? testsuite/libamf.all/test_buffer
? testsuite/libamf.all/test_el
? testsuite/libamf.all/test_lc
? testsuite/libamf.all/test_object.loT
? testsuite/libamf.all/test_sol
? testsuite/libbase/memtest
? testsuite/libnet.all/site.exp
? testsuite/libnet.all/testrun.log
? testsuite/libnet.all/testrun.sum
? testsuite/misc-ming.all/easyvideo.c
? testsuite/misc-ming.all/fd.as
? testsuite/misc-ming.all/fd.swfswf
? testsuite/misc-ming.all/p.xml
? testsuite/misc-ming.all/random_test.c
? testsuite/misc-ming.all/test.cpp
? testsuite/misc-swfc.all/action_execution_order_test10.swf.output.29795
? testsuite/misc-swfc.all/gnash.log
? testsuite/misc-swfc.all/gnash.sum
? testsuite/server/AsValueTest
? testsuite/swfdec/run_swfdec_testsuite
Index: gui/gtk.cpp
===================================================================
RCS file: /sources/gnash/gnash/gui/gtk.cpp,v
retrieving revision 1.163
diff -u -r1.163 gtk.cpp
--- gui/gtk.cpp	9 Apr 2008 11:57:34 -0000	1.163
+++ gui/gtk.cpp	10 Apr 2008 15:09:51 -0000
@@ -73,6 +73,10 @@
 # include <hildon/hildon.h>
 #endif
 
+namespace {
+gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
+}
+
 namespace gnash 
 {
 
@@ -81,6 +85,9 @@
 bool createHelpMenu(GtkWidget *obj);
 bool createControlMenu(GtkWidget *obj);
 
+GtkTextBuffer* GtkGui::_logBuffer = NULL;
+GtkWidget* GtkGui::_logWindow = NULL;
+
 // This is global so it can be accessed by the evnt handler, which
 // isn't part of this class. 
 Lirc *lirc;
@@ -101,6 +108,8 @@
 {
     //GNASH_REPORT_FUNCTION;
 
+    gdk_threads_init();
+
     gtk_init (&argc, argv);
 
 #ifdef GUI_HILDON
@@ -225,6 +234,7 @@
                         this, NULL);
 
     gtk_main();
+    
     return true;
 }
 
@@ -234,6 +244,83 @@
     g_timeout_add(timeout, (GSourceFunc)gtk_main_quit, NULL);
 }
 
+void
+GtkGui::createLogWindow()
+{
+    // We only want one log window.
+    if (!_logWindow)
+    {
+        GtkWidget *view;
+        GtkWidget *sw;
+    
+        _logWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+        gtk_window_set_default_size(GTK_WINDOW(_logWindow), 450, 450);
+        gtk_window_set_destroy_with_parent(GTK_WINDOW(_logWindow), TRUE);
+
+        g_signal_connect (_logWindow, "destroy",
+			G_CALLBACK (&gtk_widget_destroyed), &_logWindow);        
+        g_signal_connect (_logWindow, "delete-event",
+			G_CALLBACK (&closeLogDialog), NULL);
+
+        gtk_window_set_title (GTK_WINDOW (_logWindow), "Log messages");
+        gtk_container_set_border_width (GTK_CONTAINER (_logWindow), 0);
+
+        view = gtk_text_view_new ();
+        gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
+
+        _logBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+      
+        sw = gtk_scrolled_window_new (NULL, NULL);
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+				      GTK_POLICY_AUTOMATIC,
+				      GTK_POLICY_AUTOMATIC);
+        gtk_container_add (GTK_CONTAINER (_logWindow), sw);
+        gtk_container_add (GTK_CONTAINER (sw), view);
+
+        gtk_widget_show_all (_logWindow);
+    }
+}
+
+void 
+GtkGui::writeLogToDialog(const std::string& msg)
+{
+
+    if (!_logBuffer) return;
+    
+    std::string output = msg + "\n";
+    GtkTextIter iter;
+
+    // If this isn't mutex-protected, writes from separate threads (in
+    // particular the parsing thread) invalidate the buffer.
+    gdk_threads_leave();
+    gdk_threads_enter();
+
+    gtk_text_buffer_get_end_iter(_logBuffer, &iter);
+    gtk_text_buffer_insert(_logBuffer, &iter, output.c_str(), output.size());
+
+    gdk_threads_leave();
+
+}
+
+void
+GtkGui::closeLogDialog()
+{
+    std::cout << "DEBUG: closeLogDialog" << std::endl;
+
+    // Make sure to join threads to avoid deadlock.
+    gdk_threads_leave();
+    removeLogListener();
+
+    if (!_logWindow) return;
+    gtk_widget_destroy(_logWindow);
+}
+
+void
+GtkGui::removeLogListener()
+{
+    dbglogfile.registerLogCallback(NULL);
+}
+
 bool
 GtkGui::addFDListener(int fd, callback_t callback, void* data)
 {
@@ -292,7 +379,7 @@
         // It could be a good hack if it were done earlier.
         // There really doesn't seem to be a proper way of setting the starting size
         // of a widget but allowing it to be shrunk.
-        gtk_widget_set_size_request(_drawingArea, -1, -1);
+            gtk_widget_set_size_request(_drawingArea, -1, -1);
     	gtk_window_fullscreen(GTK_WINDOW(_window));
 
         showMenu(false);
@@ -421,23 +508,21 @@
 int
 GtkGui::getScreenResX()
 {
-    GdkScreen *screen = gdk_screen_get_default();
-    if (!screen) return 0;
-    return gdk_screen_get_width(screen);
+    return gdk_screen_width();
 }
 
 int
 GtkGui::getScreenResY()
 {
-    GdkScreen *screen = gdk_screen_get_default();
-    if (!screen) return 0;
-    return gdk_screen_get_height(screen); 
+    return gdk_screen_height(); 
 }
 
 // private
 void
 GtkGui::setupWindowEvents()
 {
+//    g_signal_connect(G_OBJECT(gtk_widget_get_toplevel(_drawingArea)), "destroy_event",
+//                   G_CALLBACK(delete_event), this);
     g_signal_connect(G_OBJECT(gtk_widget_get_toplevel(_drawingArea)), "delete_event",
                    G_CALLBACK(delete_event), this);
     g_signal_connect(G_OBJECT(gtk_widget_get_toplevel(_drawingArea)), "key_press_event",
@@ -1452,6 +1537,13 @@
 }
 
 void
+GtkGui::showLogDialog()
+{
+    createLogWindow();
+    dbglogfile.registerLogCallback(&writeLogToDialog);
+}
+
+void
 GtkGui::menuitem_openfile_callback(GtkMenuItem* /*menuitem*/, gpointer data)
 {
     GtkWidget* dialog;
@@ -1521,6 +1613,14 @@
     gui->showPropertiesDialog();
 }
 
+// Properties Callback
+void
+GtkGui::menuitemLogCallback(GtkMenuItem* /*menuitem*/, gpointer data)
+{
+    GtkGui* gui = static_cast<GtkGui*>(data);
+    gui->showLogDialog();
+}
+
 // This pops up the menu when the right mouse button is clicked
 gint
 GtkGui::popup_handler(GtkWidget *widget, GdkEvent *event)
@@ -1564,6 +1664,10 @@
 {
     //GNASH_REPORT_FUNCTION;
     Gui* gui = static_cast<Gui*>(data);
+
+    // Avoid deadlock while logging    
+    if (_logWindow) gdk_threads_leave();
+    
     gui->menu_restart();
 }
 
@@ -1709,7 +1813,12 @@
 GtkGui::delete_event(GtkWidget* /*widget*/, GdkEvent* /*event*/,
 			gpointer /*data*/)
 {
-    GNASH_REPORT_FUNCTION;
+    //GNASH_REPORT_FUNCTION;
+    std::cout << "DEBUG: delete_event" << std::endl;
+
+    gdk_threads_leave();
+
+    closeLogDialog();
 
     gtk_main_quit();
     return TRUE;
@@ -1953,6 +2062,17 @@
     gtk_widget_show(GTK_WIDGET(menuitem_fullscreen));
     g_signal_connect(GTK_OBJECT(menuitem_fullscreen), "activate",
                          G_CALLBACK(&menuitem_fullscreen_callback), this);
+
+    GtkWidget *separator = gtk_separator_menu_item_new ();
+    gtk_widget_show (separator);
+    gtk_menu_append (menu, GTK_WIDGET(separator));
+
+    GtkMenuItem *menuitem_log =
+ 	GTK_MENU_ITEM(gtk_menu_item_new_with_label(_("View message log")));
+    gtk_menu_append(menu, GTK_WIDGET(menuitem_log));
+    gtk_widget_show(GTK_WIDGET(menuitem_log));
+    g_signal_connect(GTK_OBJECT(menuitem_log), "activate",
+                         G_CALLBACK(&menuitemLogCallback), this);
 }
 
 // Create a Control menu that can be used from the menu bar or the popup.
Index: gui/gtksup.h
===================================================================
RCS file: /sources/gnash/gnash/gui/gtksup.h,v
retrieving revision 1.71
diff -u -r1.71 gtksup.h
--- gui/gtksup.h	9 Apr 2008 11:57:34 -0000	1.71
+++ gui/gtksup.h	10 Apr 2008 15:09:54 -0000
@@ -118,6 +118,9 @@
     
     // Display an About dialogue
     void showAboutDialog();
+    
+    // Display a window for Gnash log messages.
+    void showLogDialog();
 
     // Menu Item callbacks
     static void menuitem_sound_callback(GtkMenuItem *menuitem,
@@ -150,6 +153,8 @@
                                               gpointer instance);
     static void menuitem_movieinfo_callback(GtkMenuItem *menuitem,
                                               gpointer instance);
+    static void menuitemLogCallback(GtkMenuItem *menuitem,
+                                              gpointer instance);
 
     /// Force redraw (Ctrl-L)
     static void menuitem_refresh_view_callback(GtkMenuItem *menuitem,
@@ -192,6 +197,12 @@
 
     virtual void showMenu(bool show);
 
+    static void writeLogToDialog(const std::string& msg);
+    static void createLogWindow();
+    
+    static void advance(Gui* gui);
+    
+
  private:
 #ifdef GUI_HILDON
     HildonProgram *_hildon_program;
@@ -230,6 +241,13 @@
     static gnash::key::code gdk_to_gnash_key(guint key);
     static int gdk_to_gnash_modifier(int state);
 
+    /// The text buffer to which a logging listener can write. Writes
+    /// must be mutex-protected.
+    static GtkTextBuffer* _logBuffer;
+    
+    /// A singleton logging window for displaying logging calls.
+    static GtkWidget* _logWindow;
+
     // A struct containing pointers to widgets for passing preference 
     // data from the dialogue   
     struct prefData {
@@ -261,6 +279,12 @@
     
     static void handlePrefs(GtkWidget* widget, gint response, gpointer data);
     static void openFile(GtkWidget* dialog, gpointer data);
+    
+    /// Handles joining threads and destroying the log window.
+    static void closeLogDialog();
+    
+    /// Reset the logging listener to NULL
+    static void removeLogListener();
 
 };
 
Index: libbase/log.cpp
===================================================================
RCS file: /sources/gnash/gnash/libbase/log.cpp,v
retrieving revision 1.75
diff -u -r1.75 log.cpp
--- libbase/log.cpp	10 Apr 2008 07:24:01 -0000	1.75
+++ libbase/log.cpp	10 Apr 2008 15:09:54 -0000
@@ -173,26 +173,28 @@
 void
 LogFile::log(const std::string& msg)
 {
-
-	boost::mutex::scoped_lock lock(_ioMutex);
-
-	if (_stamp == true )
-	{
-        	std::string ts = timestamp();
-        	if (_verbose) cout << ts << " " << msg << endl;
-		if (openLogIfNeeded()) {
-			_outstream << ts << ": " << msg << endl;
-		}
-	}
-	else
-	{
-		if (_verbose) cout << msg << endl;
-		if (openLogIfNeeded()) {
-			_outstream << msg << endl;
-		}
-	}
 	
-	if (_listener)
+    {
+        boost::mutex::scoped_lock lock(_ioMutex);
+
+        if (_stamp == true )
+        {
+            	std::string ts = timestamp();
+            	if (_verbose) cout << ts << " " << msg << endl;
+            if (openLogIfNeeded()) {
+	            _outstream << ts << ": " << msg << endl;
+            }
+        }
+        else
+        {
+            if (_verbose) cout << msg << endl;
+            if (openLogIfNeeded()) {
+	            _outstream << msg << endl;
+            }
+        }
+    }
+    
+    if (_listener)
 	{
 	    (*_listener)(msg);
 	}
Index: server/asobj/Date.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Date.cpp,v
retrieving revision 1.63
diff -u -r1.63 Date.cpp
--- server/asobj/Date.cpp	7 Apr 2008 10:59:27 -0000	1.63
+++ server/asobj/Date.cpp	10 Apr 2008 15:09:55 -0000
@@ -361,7 +361,7 @@
     }
 
     // TODO: move this to date_as_object constructor
-    if (fn.nargs < 1 || fn.arg(0).is_undefined()) {
+    if (fn.nargs < 1 || fn.arg(0).is_undefined() || !fn.isInstantiation()) {
         // Set from system clock
         date->value = clocktime::getTicks();
     }
