changeset 15407:0b4626dc4d38

Merge in Ed's changes
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Tue, 18 Sep 2012 08:41:27 -0400
parents 6d4cd994ea71 (current diff) f52a62a6db3a (diff)
children 057beb799f13
files libgui/src/octave-adapter/octave-event-observer.h libgui/src/octave-adapter/octave-event.cc libgui/src/octave-adapter/octave-event.h
diffstat 32 files changed, 1020 insertions(+), 1181 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/history-dockwidget.cc
+++ b/libgui/src/history-dockwidget.cc
@@ -26,75 +26,21 @@
 
 #include <QVBoxLayout>
 
-#include "cmd-hist.h"
-
 #include "error.h"
 
+#include "cmd-hist.h"
+
 #include "history-dockwidget.h"
+#include "octave-link.h"
 
 history_dock_widget::history_dock_widget (QWidget * p)
-  : QDockWidget (p), octave_event_observer ()
+  : QDockWidget (p)
 {
   setObjectName ("HistoryDockWidget");
   construct ();
 }
 
 void
-history_dock_widget::handle_event (octave_event *e, bool accept)
-{
-  static bool scroll_window = false;
-
-  if (accept)
-    {
-      if (dynamic_cast <octave_update_history_event*> (e))
-        {
-          // Determine the client's (our) history length and the one of the server.
-          int clientHistoryLength = _history_model->rowCount ();
-          int serverHistoryLength = command_history::length ();
-
-          // If were behind the server, iterate through all new entries and add
-          // them to our history.
-          if (clientHistoryLength < serverHistoryLength)
-            {
-              int elts_to_add = serverHistoryLength - clientHistoryLength;
-
-              _history_model->insertRows (clientHistoryLength, elts_to_add);
-
-              for (int i = clientHistoryLength; i < serverHistoryLength; i++)
-                {
-                  std::string entry = command_history::get_entry (i);
-
-                  _history_model->setData (_history_model->index (i),
-                                           QString::fromStdString (entry));
-                }
-
-              // FIXME -- does this behavior make sense?  Calling
-              // _history_list_view->scrollToBottom () here doesn't seem to
-              // have any effect.  Instead, we need to request that action
-              // and wait until the next event occurs in which no items
-              // are added to the history list.
-
-              scroll_window = true;
-            }
-          else if (scroll_window)
-            {
-              scroll_window = false;
-
-              _history_list_view->scrollToBottom ();
-            }
-        }
-
-      // Post a new update event in a given time. This prevents flooding the
-      // event queue.
-      _update_history_model_timer.start ();
-    }
-  else
-    {
-      // octave_event::perform failed to handle event.
-    }
-}
-
-void
 history_dock_widget::construct ()
 {
   _history_model = new QStringListModel ();
@@ -161,7 +107,7 @@
 void
 history_dock_widget::request_history_model_update ()
 {
-  octave_link::post_event (new octave_update_history_event (*this));
+  octave_link::post_event (this, &history_dock_widget::update_history_callback);
 }
 
 void
@@ -176,3 +122,48 @@
   emit active_changed (false);
   QDockWidget::closeEvent (e);
 }
+
+void
+history_dock_widget::update_history_callback (void)
+{
+  static bool scroll_window = false;
+
+  // Determine the client's (our) history length and the one of the server.
+  int clientHistoryLength = _history_model->rowCount ();
+  int serverHistoryLength = command_history::length ();
+
+  // If were behind the server, iterate through all new entries and add
+  // them to our history.
+  if (clientHistoryLength < serverHistoryLength)
+    {
+      int elts_to_add = serverHistoryLength - clientHistoryLength;
+
+      _history_model->insertRows (clientHistoryLength, elts_to_add);
+
+      for (int i = clientHistoryLength; i < serverHistoryLength; i++)
+        {
+          std::string entry = command_history::get_entry (i);
+
+          _history_model->setData (_history_model->index (i),
+                                   QString::fromStdString (entry));
+        }
+
+      // FIXME -- does this behavior make sense?  Calling
+      // _history_list_view->scrollToBottom () here doesn't seem to
+      // have any effect.  Instead, we need to request that action
+      // and wait until the next event occurs in which no items
+      // are added to the history list.
+
+      scroll_window = true;
+    }
+  else if (scroll_window)
+    {
+      scroll_window = false;
+
+      _history_list_view->scrollToBottom ();
+    }
+
+  // Post a new update event in a given time. This prevents flooding the
+  // event queue.
+  _update_history_model_timer.start ();
+}
--- a/libgui/src/history-dockwidget.h
+++ b/libgui/src/history-dockwidget.h
@@ -30,17 +30,12 @@
 #include <QStringListModel>
 #include <QTimer>
 
-#include "octave-link.h"
-#include "octave-event-observer.h"
-
-class history_dock_widget : public QDockWidget, public octave_event_observer
+class history_dock_widget : public QDockWidget
 {
   Q_OBJECT
   public:
   history_dock_widget (QWidget *parent = 0);
 
-  void handle_event (octave_event *e, bool accept);
-
 public slots:
   void handle_visibility_changed (bool visible);
   void request_history_model_update ();
@@ -69,6 +64,8 @@
   QStringListModel *_history_model;
 
   QTimer _update_history_model_timer;
+
+  void update_history_callback (void);
 };
 
 #endif // HISTORYDOCKWIDGET_H
--- a/libgui/src/m-editor/file-editor-tab.cc
+++ b/libgui/src/m-editor/file-editor-tab.cc
@@ -24,12 +24,6 @@
 #include <config.h>
 #endif
 
-#include "file-editor-tab.h"
-#include "file-editor.h"
-#include "find-dialog.h"
-#include "octave-link.h"
-
-
 #include <Qsci/qsciapis.h>
 // Not available in the Debian repos yet!
 // #include <Qsci/qscilexeroctave.h>
@@ -46,8 +40,16 @@
 #include <QTextStream>
 #include <QVBoxLayout>
 
+#include "file-editor-tab.h"
+#include "file-editor.h"
+#include "find-dialog.h"
+#include "octave-link.h"
+
+#include "debug.h"
+#include "oct-env.h"
+
 file_editor_tab::file_editor_tab(file_editor *fileEditor)
-  : QWidget ((QWidget*)fileEditor), octave_event_observer ()
+  : QWidget ((QWidget*)fileEditor)
 {
   _file_editor = fileEditor;
   _file_name = "";
@@ -116,44 +118,6 @@
 }
 
 void
-file_editor_tab::handle_event (octave_event *e, bool accept)
-{
-  if (accept)
-    {
-      if (dynamic_cast<octave_run_file_event*> (e))
-        {
-          // File was run successfully.
-        }
-
-      if (octave_add_breakpoint_event *abe
-          = dynamic_cast<octave_add_breakpoint_event*> (e))
-        {
-          // TODO: Check file.
-          _edit_area->markerAdd (abe->get_line (), breakpoint);
-        }
-
-      if (octave_remove_breakpoint_event *rbe
-          = dynamic_cast<octave_remove_breakpoint_event*> (e))
-        {
-          // TODO: Check file.
-          _edit_area->markerDelete (rbe->get_line (), breakpoint);
-        }
-
-      if (dynamic_cast<octave_remove_all_breakpoints_event*> (e))
-        {
-          _edit_area->markerDeleteAll (breakpoint);
-        }
-    }
-  else
-    {
-      if (dynamic_cast<octave_run_file_event*> (e))
-        {
-          // Running file failed.
-        }
-    }
-}
-
-void
 file_editor_tab::closeEvent (QCloseEvent *e)
 {
   if (_file_editor->get_main_window ()->is_closing ())
@@ -307,9 +271,10 @@
   // We have to cut off the suffix, because octave appends it.
   function_name.chop (file_info.suffix ().length () + 1);
 
-  octave_link::post_event (new octave_add_breakpoint_event
-                           (*this, path.toStdString (),
-                            function_name.toStdString (), line));
+  bp_info info (path, function_name, line);
+
+  octave_link::post_event
+    (this, &file_editor_tab::add_breakpoint_callback, info);
 }
 
 void
@@ -322,9 +287,10 @@
   // We have to cut off the suffix, because octave appends it.
   function_name.chop (file_info.suffix ().length () + 1);
 
-  octave_link::post_event (new octave_remove_breakpoint_event
-                           (*this, path.toStdString (),
-                            function_name.toStdString (), line));
+  bp_info info (path, function_name, line);
+
+  octave_link::post_event
+    (this, &file_editor_tab::remove_breakpoint_callback, info);
 }
 
 void
@@ -492,9 +458,10 @@
   // We have to cut off the suffix, because octave appends it.
   function_name.chop (file_info.suffix ().length () + 1);
 
-  octave_link::post_event (new octave_remove_all_breakpoints_event
-                           (*this, path.toStdString (),
-                            function_name.toStdString ()));
+  bp_info info (path, function_name, 0);
+
+  octave_link::post_event
+    (this, &file_editor_tab::remove_all_breakpoints_callback, info);
 }
 
 void
@@ -749,8 +716,8 @@
   _file_editor->terminal ()->sendText (QString ("cd \'%1\'\n%2\n")
                                        .arg(path).arg (function_name));
   // TODO: Sending a run event crashes for long scripts. Find out why.
-  //  octave_link::post_event (new octave_run_file_event
-  //                           (*this, _file_name.toStdString ()));
+  // octave_link::post_event
+  //   (this, &file_editor_tab::run_file_callback, _file_name.toStdString ()));
 }
 
 void
@@ -839,3 +806,61 @@
 
   update_window_title (false);
 }
+
+void
+file_editor_tab::run_file_callback (void)
+{
+  // Maybe someday we will do something here?
+}
+
+void
+file_editor_tab::add_breakpoint_callback (const bp_info& info)
+{
+  bp_table::intmap intmap;
+  intmap[0] = info.line + 1;
+
+  std::string previous_directory = octave_env::get_current_directory ();
+  octave_env::chdir (info.path);
+  intmap = bp_table::add_breakpoint (info.function_name, intmap);
+  octave_env::chdir (previous_directory);
+
+  if (intmap.size () > 0)
+    {
+    // FIXME -- Check file.
+      _edit_area->markerAdd (info.line, breakpoint);
+    }
+}
+
+void
+file_editor_tab::remove_breakpoint_callback (const bp_info& info)
+{
+  bp_table::intmap intmap;
+  intmap[0] = info.line;
+
+  std::string previous_directory = octave_env::get_current_directory ();
+  octave_env::chdir (info.path);
+  bp_table::remove_breakpoint (info.function_name, intmap);
+  octave_env::chdir (previous_directory);
+
+  // FIXME -- check result
+  bool success = true;
+
+  if (success)
+    {
+      // FIXME -- check file.
+      _edit_area->markerDelete (info.line, breakpoint);
+    }
+}
+
+void
+file_editor_tab::remove_all_breakpoints_callback (const bp_info& info)
+{
+  bp_table::intmap intmap;
+  std::string previous_directory = octave_env::get_current_directory ();
+  octave_env::chdir (info.path);
+  intmap = bp_table::remove_all_breakpoints_in_file (info.function_name, true);
+  octave_env::chdir (previous_directory);
+
+  if (intmap.size() > 0)
+    _edit_area->markerDeleteAll (breakpoint);
+}
--- a/libgui/src/m-editor/file-editor-tab.h
+++ b/libgui/src/m-editor/file-editor-tab.h
@@ -27,18 +27,15 @@
 #include <QWidget>
 #include <QCloseEvent>
 #include <QFileSystemWatcher>
-#include "octave-event-observer.h"
 
 class file_editor;
-class file_editor_tab : public QWidget, public octave_event_observer
+class file_editor_tab : public QWidget
 {
   Q_OBJECT
   public:
   file_editor_tab (file_editor *fileEditor);
   bool copy_available ();
 
-  void handle_event (octave_event *e, bool accept);
-
 public slots:
   void update_window_title(bool modified);
   void handle_copy_available(bool enableCopy);
@@ -87,6 +84,18 @@
   void set_file_name (const QString& fileName);
 
 private:
+
+  struct bp_info
+  {
+    bp_info (const QString& p, const QString& fn, int l)
+      : path (p.toStdString ()), function_name (fn.toStdString ()), line (l)
+    { }
+
+    std::string path;
+    std::string function_name;
+    int line;
+  };
+
   void update_lexer ();
   void request_add_breakpoint (int line);
   void request_remove_breakpoint (int line);
@@ -95,6 +104,11 @@
   int check_file_modified (const QString& msg, int cancelButton);
   void do_comment_selected_text (bool comment);
 
+  void run_file_callback (void);
+  void add_breakpoint_callback (const bp_info& info);
+  void remove_breakpoint_callback (const bp_info& info);
+  void remove_all_breakpoints_callback (const bp_info& info);
+
   file_editor *         _file_editor;
   QsciScintilla *       _edit_area;
 
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -37,12 +37,23 @@
 #include <QMessageBox>
 #include <QIcon>
 
+#include "file-editor.h"
 #include "main-window.h"
-#include "file-editor.h"
+#include "octave-link.h"
 #include "settings-dialog.h"
 
+#include "debug.h"
+#include "defaults.h"
+#include "load-save.h"
+#include "toplev.h"
+#include "variables.h"
+#include "version.h"
+
+#include "cmd-hist.h"
+#include "oct-env.h"
+
 main_window::main_window (QWidget *p)
-  : QMainWindow (p), octave_event_observer ()
+  : QMainWindow (p)
 {
   // We have to set up all our windows, before we finally launch octave.
   construct ();
@@ -54,23 +65,6 @@
 }
 
 void
-main_window::handle_event (octave_event *e, bool accept)
-{
-  if (accept)
-    {
-      if (dynamic_cast<octave_clear_history_event*> (e))
-        {
-          // After clearing the history, we need to reset the model.
-          _history_dock_widget->reset_model ();
-        }
-    }
-  else
-    {
-      // octave_event::perform failed to process event.
-    }
-}
-
-void
 main_window::new_file ()
 {
   _file_editor->request_new_file ();
@@ -104,10 +98,8 @@
     QFileDialog::getSaveFileName (this, tr ("Save Workspace"),
                                   resource_manager::get_home_path ());
   if (!selectedFile.isEmpty ())
-    {
-      octave_link::post_event (new octave_save_workspace_event
-                               (*this, selectedFile.toStdString ()));
-    }
+    octave_link::post_event (this, &main_window::save_workspace_callback,
+                             selectedFile.toStdString ());
 }
 
 void
@@ -117,22 +109,20 @@
     QFileDialog::getOpenFileName (this, tr ("Load Workspace"),
                                   resource_manager::get_home_path ());
   if (!selectedFile.isEmpty ())
-    {
-      octave_link::post_event (new octave_load_workspace_event
-                               (*this, selectedFile.toStdString ()));
-    }
+    octave_link::post_event (this, &main_window::load_workspace_callback,
+                             selectedFile.toStdString ());
 }
 
 void
 main_window::handle_clear_workspace_request ()
 {
-  octave_link::post_event (new octave_clear_workspace_event (*this));
+  octave_link::post_event (this, &main_window::clear_workspace_callback);
 }
 
 void
 main_window::handle_clear_history_request()
 {
-  octave_link::post_event (new octave_clear_history_event (*this));
+  octave_link::post_event (this, &main_window::clear_history_callback);
 }
 
 void
@@ -232,17 +222,15 @@
     QFileDialog::getExistingDirectory(this, tr ("Set working direcotry"));
 
   if (!selectedDirectory.isEmpty ())
-    {
-      octave_link::post_event (new octave_change_directory_event
-                               (*this, selectedDirectory.toStdString ()));
-    }
+    octave_link::post_event (this, &main_window::change_directory_callback,
+                             selectedDirectory.toStdString ());
 }
 
 void
 main_window::set_current_working_directory (const QString& directory)
 {
-  octave_link::post_event (new octave_change_directory_event
-                           (*this, directory.toStdString ()));
+  octave_link::post_event (this, &main_window::change_directory_callback,
+                           directory.toStdString ());
 }
 
 void
@@ -360,52 +348,37 @@
 void
 main_window::debug_continue ()
 {
-  octave_link::post_event (new octave_debug_continue_event (*this));
+  octave_link::post_event (this, &main_window::debug_continue_callback);
 }
 
 void
 main_window::debug_step_into ()
 {
-  octave_link::post_event (new octave_debug_step_into_event (*this));
+  octave_link::post_event (this, &main_window::debug_step_into_callback);
 }
 
 void
 main_window::debug_step_over ()
 {
-  octave_link::post_event (new octave_debug_step_over_event (*this));
+  octave_link::post_event (this, &main_window::debug_step_over_callback);
 }
 
 void
 main_window::debug_step_out ()
 {
-  octave_link::post_event (new octave_debug_step_out_event (*this));
+  octave_link::post_event (this, &main_window::debug_step_out_callback);
 }
 
 void
 main_window::debug_quit ()
 {
-  octave_link::post_event (new octave_debug_quit_event (*this));
+  octave_link::post_event (this, &main_window::debug_quit_callback);
 }
 
 void
 main_window::show_about_octave ()
 {
-  QString message =
-    "GNU Octave\n"
-    "Copyright (C) 2009 John W. Eaton and others.\n"
-    "This is free software; see the source code for copying conditions."
-    "There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or"
-    "FITNESS FOR A PARTICULAR PURPOSE.  For details, type `warranty'.\n"
-    "\n"
-    "Additional information about Octave is available at http://www.octave.org.\n"
-    "\n"
-    "Please contribute if you find this software useful."
-    "For more information, visit http://www.octave.org/help-wanted.html\n"
-    "\n"
-    "Report bugs to <bug@octave.org> (but first, please read"
-    "http://www.octave.org/bugs.html to learn how to write a helpful report).\n"
-    "\n"
-    "For information about changes from previous versions, type `news'.\n";
+  QString message = OCTAVE_STARTUP_MESSAGE;
 
   QMessageBox::about (this, tr ("About Octave"), message);
 }
@@ -414,7 +387,7 @@
 main_window::closeEvent (QCloseEvent *e)
 {
   e->ignore ();
-  octave_link::post_event (new octave_exit_event (*this));
+  octave_link::post_event (this, &main_window::exit_callback);
 }
 
 void
@@ -895,3 +868,70 @@
            SLOT (handle_quit_debug_mode ()));
 }
 
+void
+main_window::save_workspace_callback (const std::string& file)
+{
+  save_workspace (file);
+}
+
+void
+main_window::load_workspace_callback (const std::string& file)
+{
+  load_workspace (file);
+}
+
+void
+main_window::clear_workspace_callback (void)
+{
+  clear_current_scope ();
+}
+
+void
+main_window::clear_history_callback (void)
+{
+  command_history::clear ();
+
+  _history_dock_widget->reset_model ();
+}
+
+void
+main_window::change_directory_callback (const std::string& directory)
+{
+  octave_env::chdir (directory); 
+}
+
+void
+main_window::debug_continue_callback (void)
+{
+  debug_continue ();
+}
+
+void
+main_window::debug_step_into_callback (void)
+{
+  debug_step ("in");
+}
+
+void
+main_window::debug_step_over_callback (void)
+{
+  debug_step ();
+}
+
+void
+main_window::debug_step_out_callback (void)
+{
+  debug_step ("out");
+}
+
+void
+main_window::debug_quit_callback (void)
+{
+  debug_quit ();
+}
+
+void
+main_window::exit_callback (void)
+{
+  clean_up_and_exit (0);
+}
--- a/libgui/src/main-window.h
+++ b/libgui/src/main-window.h
@@ -44,29 +44,24 @@
 
 // Own includes
 #include "resource-manager.h"
-#include "octave-link.h"
 #include "workspace-view.h"
 #include "history-dockwidget.h"
 #include "files-dockwidget.h"
 #include "terminal-dockwidget.h"
 #include "documentation-dockwidget.h"
 #include "octave-qt-event-listener.h"
-#include "octave-event-observer.h"
 
 /**
  * \class MainWindow
  *
  * Represents the main window.
  */
-class main_window
-  : public QMainWindow, public octave_event_observer
+class main_window : public QMainWindow
 {
   Q_OBJECT public:
   main_window (QWidget * parent = 0);
   ~main_window ();
 
-  void handle_event (octave_event *e, bool accept);
-
   QTerminal *get_terminal_view () { return _terminal; }
   history_dock_widget *get_history_dock_widget ()
   {
@@ -128,6 +123,28 @@
   void construct ();
   void establish_octave_link ();
 
+  void save_workspace_callback (const std::string& file);
+
+  void load_workspace_callback (const std::string& file);
+
+  void clear_workspace_callback (void);
+
+  void clear_history_callback (void);
+
+  void change_directory_callback (const std::string& directory);
+
+  void debug_continue_callback (void);
+
+  void debug_step_into_callback (void);
+
+  void debug_step_over_callback (void);
+
+  void debug_step_out_callback (void);
+
+  void debug_quit_callback (void);
+
+  void exit_callback (void);
+
   QTerminal *               _terminal;
   file_editor_interface *   _file_editor;
   QMenu *                   _debug_menu;
--- a/libgui/src/module.mk
+++ b/libgui/src/module.mk
@@ -84,8 +84,6 @@
   src/m-editor/lexer-octave-gui.h \
   src/main-window.h \
   src/octave-adapter/octave-event-listener.h \
-  src/octave-adapter/octave-event-observer.h \
-  src/octave-adapter/octave-event.h \
   src/octave-adapter/octave-link.h \
   src/octave-adapter/octave-main-thread.h \
   src/octave-gui.h \
@@ -109,7 +107,6 @@
   src/m-editor/find-dialog.cc \
   src/m-editor/lexer-octave-gui.cc \
   src/main-window.cc \
-  src/octave-adapter/octave-event.cc \
   src/octave-adapter/octave-link.cc \
   src/octave-adapter/octave-main-thread.cc \
   src/octave-gui.cc \
@@ -144,7 +141,7 @@
   -I$(top_builddir)/liboctave/operators -I$(top_srcdir)/liboctave/operators \
   -I$(top_srcdir)/liboctave/system \
   -I$(top_srcdir)/liboctave/util \
-  -I$(top_srcdir)/libinterp \
+  -I$(top_builddir)/libinterp -I$(top_srcdir)/libinterp \
   -I$(top_builddir)/libinterp/parse-tree -I$(top_srcdir)/libinterp/parse-tree \
   -I$(top_builddir)/libinterp/interp-core -I$(top_srcdir)/libinterp/interp-core \
   -I$(top_builddir)/libinterp/interpfcn -I$(top_srcdir)/libinterp/interpfcn \
deleted file mode 100644
--- a/libgui/src/octave-adapter/octave-event-observer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-
-Copyright (C) 2011-2012 Jacob Dawid
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef OCTAVEEVENTOBSERVER_H
-#define OCTAVEEVENTOBSERVER_H
-
-class octave_event;
-
-/**
-  * \class octave_event_observer
-  * \brief Implements the observer part for the observer pattern.
-  */
-class octave_event_observer
-{
-  public:
-    octave_event_observer () { }
-    virtual ~octave_event_observer () { }
-
-    /**
-      * This will be called after the octave_event::perform function
-      * has processed an event.  ACCEPT will be true if the event was
-      * successfully handled and false otherwise.
-      */
-    virtual void handle_event (octave_event *e, bool accept) = 0;
-};
-
-#include "octave-event.h"
-
-#endif // OCTAVEEVENTOBSERVER_H
deleted file mode 100644
--- a/libgui/src/octave-adapter/octave-event.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
-
-Copyright (C) 2011-2012 Jacob Dawid
-Copyright (C) 2011-2012 John P. Swensen
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string>
-
-#include "cmd-hist.h"
-#include "oct-env.h"
-
-#include "debug.h"
-#include "oct-obj.h"
-#include "parse.h"
-#include "symtab.h"
-#include "toplev.h"
-
-#include "octave-event.h"
-
-#include <readline/readline.h>
-
-void
-octave_event::call_octave_function (const std::string& name)
-{
-  call_octave_function (name, octave_value_list ());
-}
-
-void
-octave_event::call_octave_function (const std::string& name,
-                                    const octave_value_list& args,
-                                    int nargout)
-{
-  try
-    {
-      feval (name, args, nargout);
-    } catch (...) { } // Ignore exceptions. Crashes without that.
-}
-
-void
-octave_event::finish_readline_event () const
-{
-  rl_line_buffer[0] = '\0';
-  rl_point = rl_end = 0;
-  rl_done = 1;
-  //rl_forced_update_display ();
-}
-
-bool
-octave_clear_history_event::perform ()
-{
-  int i;
-  while ((i = command_history::length ()) > 0) {
-    command_history::remove (i - 1);
-  }
-  return true;
-}
-
-bool
-octave_debug_step_into_event::perform ()
-{
-  octave_value_list args;
-  args.append (octave_value ("in"));
-  call_octave_function ("dbstep", args);
-  finish_readline_event ();
-  return true;
-}
-
-bool
-octave_debug_step_out_event::perform ()
-{
-  octave_value_list args;
-  args.append (octave_value ("out"));
-  call_octave_function ("dbstep", args);
-  finish_readline_event ();
-  return true;
-}
-
-
-bool
-octave_exit_event::perform ()
-{
-  clean_up_and_exit (0);
-  return true;
-}
-
-bool
-octave_run_file_event::perform ()
-{
-  octave_value_list args;
-  args.append (octave_value (_file));
-  call_octave_function ("run", args);
-  finish_readline_event ();
-  return true;
-}
-
-bool
-octave_change_directory_event::perform ()
-{
-  return octave_env::chdir (_directory);
-}
-
-bool
-octave_load_workspace_event::perform ()
-{
-  octave_value_list args;
-  args.append (octave_value (_file));
-  call_octave_function ("load", args);
-  return true;
-}
-
-bool
-octave_save_workspace_event::perform ()
-{
-  octave_value_list args;
-  args.append (octave_value (_file));
-  call_octave_function ("save", args);
-  return true;
-}
-
-bool
-octave_add_breakpoint_event::perform ()
-{
-  bp_table::intmap intmap;
-  intmap[0] = _line + 1;
-
-  std::string previous_directory = octave_env::get_current_directory ();
-  octave_env::chdir (_path);
-  intmap = bp_table::add_breakpoint (_function_name, intmap);
-  octave_env::chdir (previous_directory);
-  return intmap.size () > 0;
-}
-
-bool
-octave_remove_breakpoint_event::perform ()
-{
-  bp_table::intmap intmap;
-  intmap[0] = _line;
-
-  std::string previous_directory = octave_env::get_current_directory ();
-  octave_env::chdir (_path);
-  bp_table::remove_breakpoint (_function_name, intmap);
-  octave_env::chdir (previous_directory);
-  return true; // TODO: Check result.
-}
-
-bool
-octave_remove_all_breakpoints_event::perform ()
-{
-  bp_table::intmap intmap;
-  std::string previous_directory = octave_env::get_current_directory ();
-  octave_env::chdir (_path);
-  intmap = bp_table::remove_all_breakpoints_in_file (_function_name, true);
-  octave_env::chdir (previous_directory);
-  return intmap.size() > 0;
-}
deleted file mode 100644
--- a/libgui/src/octave-adapter/octave-event.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
-
-Copyright (C) 2011-2012 Jacob Dawid
-Copyright (C) 2011-2012 John P. Swensen
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef OCTAVEEVENT_H
-#define OCTAVEEVENT_H
-
-#include <string>
-
-class octave_value_list;
-
-#include "octave-event-observer.h"
-
-/**
-  * \class octave_event
-  * \brief Base class for an octave event.
-  * In order to make communication with octave threadsafe, comunication is
-  * implemented via events. An application may create events and post them,
-  * however there is no guarantee events will be processed in a given time.
-  *
-  * In order to create an event, there must be an event observer. The event
-  * observer will be given the opportunity to react on the event as soon as
-  * it has been processed in the octave thread. Accepting and ignoring takes
-  * places in the octave thread.
-  */
-class octave_event
-{
-  public:
-    octave_event (octave_event_observer& o)
-      : _octave_event_observer (o)
-    { }
-
-    virtual ~octave_event ()
-    { }
-
-    /** Performs what is necessary to make this event happen. This
-      * code is thread-safe since it will be executed in the octave
-      * thread. However, you should take care to keep this code as
-      * short as possible. */
-    virtual bool perform () = 0;
-
-    /**
-      * Pass the event on to the class that posted the event.  ACCEPT
-      * will be true if the perform function was successful, and false
-      * otherwise.
-      */
-    void handle_event (bool accept)
-    {
-      _octave_event_observer.handle_event (this, accept);
-    }
-
-  protected:
-    void call_octave_function (const std::string& name);
-
-    void call_octave_function (const std::string& name,
-                               const octave_value_list& args,
-                               int nargout = 0);
-
-    void finish_readline_event () const;
-
-  private:
-    octave_event_observer& _octave_event_observer;
-};
-
-class octave_update_history_event : public octave_event
-{
-  public:
-    /** Creates a new octave_exit_event. */
-    octave_update_history_event (octave_event_observer& o)
-      : octave_event (o)
-    { }
-
-    bool perform ()
-    { return true; /* Always grant. */ }
-};
-
-class octave_update_workspace_event : public octave_event
-{
-  public:
-    /** Creates a new octave_exit_event. */
-    octave_update_workspace_event (octave_event_observer& o)
-      : octave_event (o)
-    { }
-
-    bool perform ()
-    { return true; /* Always grant. */ }
-};
-
-/** Implements an octave exit event. */
-class octave_exit_event : public octave_event
-{
-  public:
-    /** Creates a new octave_exit_event. */
-    octave_exit_event (octave_event_observer& o)
-      : octave_event (o)
-    { }
-
-    bool perform ();
-};
-
-/** Implements an octave run file event. */
-class octave_run_file_event : public octave_event
-{
-  public:
-    /** Creates a new octave_run_file_event. */
-    octave_run_file_event (octave_event_observer& o,
-                           const std::string& file)
-      : octave_event (o)
-    { _file = file; }
-
-    bool perform ();
-
-  private:
-    std::string _file;
-};
-
-/** Implements a change directory event. */
-class octave_change_directory_event : public octave_event
-{
-  public:
-    /** Creates a new octave_change_directory_event. */
-    octave_change_directory_event (octave_event_observer& o,
-                                   const std::string& directory)
-      : octave_event (o)
-    { _directory = directory; }
-
-    bool perform ();
-
-  private:
-    std::string _directory;
-};
-
-/** Implements a clear workspace event. */
-class octave_clear_workspace_event : public octave_event
-{
-  public:
-    /** Creates a new octave_run_file_event. */
-    octave_clear_workspace_event (octave_event_observer& o)
-      : octave_event (o)
-    { }
-
-    bool perform ()
-    {
-      call_octave_function ("clear");
-      return true;
-    }
-};
-
-/** Implements a load workspace event. */
-class octave_load_workspace_event : public octave_event
-{
-  public:
-    /** Creates a new octave_change_directory_event. */
-    octave_load_workspace_event (octave_event_observer& o,
-                                 const std::string& file)
-      : octave_event (o)
-    { _file = file; }
-
-    bool perform ();
-
-  private:
-    std::string _file;
-};
-
-/** Implements a save workspace event. */
-class octave_save_workspace_event : public octave_event
-{
-  public:
-    /** Creates a new octave_change_directory_event. */
-    octave_save_workspace_event (octave_event_observer& o,
-                                 const std::string& file)
-      : octave_event (o)
-    { _file = file; }
-
-    bool perform ();
-
-  private:
-    std::string _file;
-};
-
-class octave_clear_history_event : public octave_event
-{
-  public:
-    /** Creates a new octave_clear_history_event. */
-    octave_clear_history_event (octave_event_observer& o)
-      : octave_event (o)
-    { }
-
-  bool perform ();
-};
-
-class octave_add_breakpoint_event : public octave_event
-{
-  public:
-    octave_add_breakpoint_event (octave_event_observer& o,
-                                 const std::string& path,
-                                 const std::string& function_name,
-                                 int line)
-      : octave_event (o)
-    {
-      _path = path;
-      _function_name = function_name;
-      _line = line;
-    }
-
-    bool perform ();
-
-    std::string get_path ()
-    {
-      return _path;
-    }
-
-    std::string get_function_name ()
-    {
-      return _function_name;
-    }
-
-    int get_line ()
-    {
-      return _line;
-    }
-
-  private:
-    std::string _path;
-    std::string _function_name;
-    int _line;
-};
-
-class octave_remove_breakpoint_event : public octave_event
-{
-  public:
-    octave_remove_breakpoint_event (octave_event_observer& o,
-                                    const std::string& path,
-                                    const std::string& function_name,
-                                    int line)
-      : octave_event (o)
-    {
-      _path = path;
-      _function_name = function_name;
-      _line = line;
-    }
-
-    bool perform ();
-
-    std::string get_path ()
-    {
-      return _path;
-    }
-
-    std::string get_function_name ()
-    {
-      return _function_name;
-    }
-
-    int get_line ()
-    {
-      return _line;
-    }
-
-  private:
-    std::string _path;
-    std::string _function_name;
-    int _line;
-};
-
-class octave_remove_all_breakpoints_event : public octave_event
-{
-  public:
-    octave_remove_all_breakpoints_event (octave_event_observer& o,
-                                         const std::string& path,
-                                         const std::string& function_name)
-      : octave_event (o)
-    {
-      _path = path;
-      _function_name = function_name;
-    }
-
-    bool perform ();
-
-    std::string get_path ()
-    {
-      return _path;
-    }
-
-    std::string get_function_name ()
-    {
-      return _function_name;
-    }
-
-  private:
-    std::string _path;
-    std::string _function_name;
-};
-
-class octave_debug_step_into_event : public octave_event
-{
-  public:
-    /** Creates a new octave_debug_step_into_event. */
-    octave_debug_step_into_event (octave_event_observer& o)
-      : octave_event (o) { }
-
-    bool perform ();
-};
-
-class octave_debug_step_over_event : public octave_event
-{
-  public:
-    /** Creates a new octave_debug_step_over_event. */
-    octave_debug_step_over_event (octave_event_observer& o)
-      : octave_event (o) { }
-
-    bool perform ()
-    {
-      call_octave_function ("dbnext");
-      finish_readline_event ();
-      return true;
-    }
-};
-
-class octave_debug_step_out_event : public octave_event
-{
-  public:
-    /** Creates a new octave_debug_step_out_event. */
-    octave_debug_step_out_event (octave_event_observer& o)
-      : octave_event (o) { }
-
-    bool perform ();
-};
-
-class octave_debug_continue_event : public octave_event
-{
-  public:
-    /** Creates a new octave_debug_step_out_event. */
-    octave_debug_continue_event (octave_event_observer& o)
-      : octave_event (o) { }
-
-    bool perform ()
-    {
-      call_octave_function ("dbcont");
-      finish_readline_event ();
-      return true;
-    }
-};
-
-class octave_debug_quit_event : public octave_event
-{
-  public:
-    /** Creates a new octave_debug_step_out_event. */
-    octave_debug_quit_event (octave_event_observer& o)
-      : octave_event (o) { }
-
-    bool perform ()
-    {
-      call_octave_function ("dbquit");
-      finish_readline_event ();
-      return true;
-    }
-};
-
-#endif // OCTAVEEVENT_H
--- a/libgui/src/octave-adapter/octave-link.cc
+++ b/libgui/src/octave-adapter/octave-link.cc
@@ -55,7 +55,7 @@
 
 octave_link::octave_link (void)
   : event_listener (0), event_queue_mutex (new octave_mutex ()),
-    event_queue (), last_cwd (), debugging (false)
+    gui_event_queue (), last_cwd (), debugging (false)
 { }
 
 void
@@ -110,40 +110,17 @@
 {
   event_queue_mutex->lock ();
 
-  while (event_queue.size () > 0)
-    {
-      octave_event *e = event_queue.front ();
-
-      event_queue.pop ();
-
-      bool status = e->perform ();
-
-      e->handle_event (status);
-
-      delete e;
-    }
+  gui_event_queue.run ();
 
   event_queue_mutex->unlock ();
 }
 
 void
-octave_link::do_post_event (octave_event *e)
-{
-  if (e)
-    {
-      event_queue_mutex->lock ();
-      event_queue.push (e);
-      event_queue_mutex->unlock ();
-    }
-}
-
-void
 octave_link::do_about_to_exit (void)
 {
   event_queue_mutex->lock ();
 
-  while (! event_queue.empty ())
-    event_queue.pop ();
+  gui_event_queue.discard ();
 
   event_queue_mutex->unlock ();
 
@@ -157,11 +134,6 @@
   return last_cwd;
 }
 
-void
-octave_link::handle_event (octave_event *, bool)
-{
-}
-
 bool
 octave_link::instance_ok (void)
 {
--- a/libgui/src/octave-adapter/octave-link.h
+++ b/libgui/src/octave-adapter/octave-link.h
@@ -24,14 +24,13 @@
 #ifndef OCTAVELINK_H
 #define OCTAVELINK_H
 
-#include <queue>
 #include <string>
 
 class octave_mutex;
 
+#include "event-queue.h"
+
 #include "octave-main-thread.h"
-#include "octave-event.h"
-#include "octave-event-observer.h"
 #include "octave-event-listener.h"
 
 // \class OctaveLink
@@ -42,7 +41,7 @@
 // buffering access operations to octave and executing them in the
 // readline event hook, which lives in the octave thread.
 
-class octave_link : public octave_event_observer
+class octave_link
 {
 protected:
 
@@ -76,10 +75,25 @@
       instance->do_process_events ();
   }
 
-  static void post_event (octave_event *e)
+  template <class T>
+  static void post_event (T *obj, void (T::*method) (void))
   {
     if (instance_ok ())
-      instance->do_post_event (e);
+      instance->do_post_event (obj, method);
+  }
+
+  template <class T, class A>
+  static void post_event (T *obj, void (T::*method) (A), A arg)
+  {
+    if (instance_ok ())
+      instance->do_post_event (obj, method, arg);
+  }
+
+  template <class T, class A>
+  static void post_event (T *obj, void (T::*method) (const A&), const A& arg)
+  {
+    if (instance_ok ())
+      instance->do_post_event (obj, method, arg);
   }
 
   static void about_to_exit (void)
@@ -128,8 +142,8 @@
   // Semaphore to lock access to the event queue.
   octave_mutex *event_queue_mutex;
 
-  // Buffer for queueing events until they will be processed.
-  std::queue <octave_event *> event_queue;
+  // Event Queue.
+  event_queue gui_event_queue;
 
   // Stores the last known current working directory of octave.
   std::string last_cwd;
@@ -141,7 +155,24 @@
 
   void do_generate_events (void);
   void do_process_events (void);
-  void do_post_event (octave_event *e);
+
+  template <class T>
+  void do_post_event (T *obj, void (T::*method) (void))
+  {
+    gui_event_queue.add_method (obj, method);
+  }
+
+  template <class T, class A>
+  void do_post_event (T *obj, void (T::*method) (A), A arg)
+  {
+    gui_event_queue.add_method (obj, method, arg);
+  }
+
+  template <class T, class A>
+  void do_post_event (T *obj, void (T::*method) (const A&), const A& arg)
+  {
+    gui_event_queue.add_method (obj, method, arg);
+  }
 
   void do_about_to_exit (void);
 
@@ -149,8 +180,6 @@
   void do_finished_readline_hook (void) { }
 
   std::string do_last_working_directory (void);
-
-  void handle_event (octave_event *e, bool accept);
 };
 
 #endif // OCTAVELINK_H
--- a/libgui/src/workspace-model.cc
+++ b/libgui/src/workspace-model.cc
@@ -29,13 +29,14 @@
 
 #include <list>
 
-#include <symtab.h>
+#include "symtab.h"
+#include "variables.h"
 
 #include "workspace-model.h"
 #include "octave-link.h"
 
 workspace_model::workspace_model(QObject *p)
-  : QAbstractItemModel (p), octave_event_observer ()
+  : QAbstractItemModel (p)
 {
   QList<QVariant> rootData;
   rootData << tr ("Name") << tr ("Class") << tr("Dimension") << tr ("Value");
@@ -63,68 +64,7 @@
 void
 workspace_model::request_update_workspace ()
 {
-  octave_link::post_event (new octave_update_workspace_event (*this));
-}
-
-void
-workspace_model::handle_event (octave_event *e, bool accept)
-{
-  if (accept)
-    {
-      if (dynamic_cast <octave_update_workspace_event*> (e))
-        {
-          std::list < symbol_table::symbol_record > symbolTable = symbol_table::all_variables ();
-
-          _symbol_information.clear ();
-          for (std::list < symbol_table::symbol_record > ::iterator iterator = symbolTable.begin ();
-               iterator != symbolTable.end (); iterator++)
-            _symbol_information.push_back (symbol_information (*iterator));
-
-          beginResetModel();
-          top_level_item (0)->delete_child_items ();
-          top_level_item (1)->delete_child_items ();
-          top_level_item (2)->delete_child_items ();
-
-          foreach (const symbol_information& s, _symbol_information)
-            {
-              tree_item *child = new tree_item ();
-
-              child->set_data (0, s.symbol ());
-              child->set_data (1, s.class_name ());
-              child->set_data (2, s.dimension ());
-              child->set_data (3, s.value ());
-
-              switch (s.scope ())
-                {
-                case symbol_information::local:
-                  top_level_item (0)->add_child (child);
-                  break;
-
-                case symbol_information::global:
-                  top_level_item (1)->add_child (child);
-                  break;
-
-                case symbol_information::persistent:
-                  top_level_item (2)->add_child (child);
-                  break;
-
-                default:
-                  break;
-                }
-            }
-
-          endResetModel();
-          emit model_changed();
-        }
-
-      // Post a new event in a given time.
-      // This prevents flooding the event queue when no events are being processed.
-      _update_workspace_model_timer.start ();
-    }
-  else
-    {
-      // octave_event::perform failed to process event.
-    }
+  octave_link::post_event (this, &workspace_model::update_workspace_callback);
 }
 
 QModelIndex
@@ -236,3 +176,54 @@
   return item->data(idx.column());
 }
 
+void
+workspace_model::update_workspace_callback (void)
+{
+  std::list < symbol_table::symbol_record > symbolTable = symbol_table::all_variables ();
+
+  _symbol_information.clear ();
+  for (std::list < symbol_table::symbol_record > ::iterator iterator = symbolTable.begin ();
+       iterator != symbolTable.end (); iterator++)
+    _symbol_information.push_back (symbol_information (*iterator));
+
+  beginResetModel();
+  top_level_item (0)->delete_child_items ();
+  top_level_item (1)->delete_child_items ();
+  top_level_item (2)->delete_child_items ();
+
+  foreach (const symbol_information& s, _symbol_information)
+    {
+      tree_item *child = new tree_item ();
+
+      child->set_data (0, s.symbol ());
+      child->set_data (1, s.class_name ());
+      child->set_data (2, s.dimension ());
+      child->set_data (3, s.value ());
+
+      switch (s.scope ())
+        {
+        case symbol_information::local:
+          top_level_item (0)->add_child (child);
+          break;
+
+        case symbol_information::global:
+          top_level_item (1)->add_child (child);
+          break;
+
+        case symbol_information::persistent:
+          top_level_item (2)->add_child (child);
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  endResetModel();
+  emit model_changed();
+
+  // Post a new event in a given time.
+  // This prevents flooding the event queue when no events are being processed.
+  _update_workspace_model_timer.start ();
+}
+
--- a/libgui/src/workspace-model.h
+++ b/libgui/src/workspace-model.h
@@ -30,7 +30,6 @@
 #include <QTimer>
 
 #include "symbol-information.h"
-#include "octave-event-observer.h"
 
 class tree_item
 {
@@ -112,7 +111,7 @@
 };
 
 class workspace_model
-  : public QAbstractItemModel, public octave_event_observer
+  : public QAbstractItemModel
 {
   Q_OBJECT
 
@@ -120,8 +119,6 @@
   workspace_model (QObject *parent = 0);
   ~workspace_model ();
 
-  void handle_event (octave_event *e, bool accept);
-
   QVariant data (const QModelIndex &index, int role) const;
   Qt::ItemFlags flags (const QModelIndex &index) const;
   QVariant headerData (int section, Qt::Orientation orientation,
@@ -142,6 +139,9 @@
   void model_changed ();
 
 private:
+
+  void update_workspace_callback (void);
+
   /** Timer for periodically updating the workspace model from the current
    * symbol information. */
   QTimer _update_workspace_model_timer;
--- a/libgui/src/workspace-view.h
+++ b/libgui/src/workspace-view.h
@@ -26,7 +26,7 @@
 #include <QDockWidget>
 #include <QTreeView>
 #include <QSemaphore>
-#include "octave-link.h"
+
 #include "workspace-model.h"
 
 class workspace_view : public QDockWidget
new file mode 100644
--- /dev/null
+++ b/libinterp/interp-core/action-container.h
@@ -0,0 +1,342 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_action_container_h)
+#define octave_action_container_h 1
+
+// This class allows registering actions in a list for later
+// execution, either explicitly or when the container goes out of
+// scope.
+
+// FIXME -- is there a better name for this class?
+
+class
+OCTINTERP_API
+action_container
+{
+public:
+
+  // A generic unwind_protect element. Knows how to run itself and
+  // discard itself.  Also, contains a pointer to the next element.
+  class elem
+  {
+  public:
+    elem (void) { }
+
+    virtual void run (void) { }
+
+    virtual ~elem (void) { }
+
+    friend class action_container;
+
+  private:
+
+    // No copying!
+
+    elem (const elem&);
+
+    elem& operator = (const elem&);
+  };
+
+  // An element that merely runs a void (*)(void) function.
+
+  class fcn_elem : public elem
+  {
+  public:
+    fcn_elem (void (*fptr) (void))
+      : e_fptr (fptr) { }
+
+    void run (void) { e_fptr (); }
+
+  private:
+    void (*e_fptr) (void);
+  };
+
+  // An element that stores a variable of type T along with a void (*) (T)
+  // function pointer, and calls the function with the parameter.
+
+  template <class T>
+  class fcn_arg_elem : public elem
+  {
+  public:
+    fcn_arg_elem (void (*fcn) (T), T arg)
+      : e_fcn (fcn), e_arg (arg) { }
+
+    void run (void) { e_fcn (e_arg); }
+
+  private:
+
+    // No copying!
+
+    fcn_arg_elem (const fcn_arg_elem&);
+
+    fcn_arg_elem& operator = (const fcn_arg_elem&);
+
+    void (*e_fcn) (T);
+    T e_arg;
+  };
+
+  // An element that stores a variable of type T along with a
+  // void (*) (const T&) function pointer, and calls the function with
+  // the parameter.
+
+  template <class T>
+  class fcn_crefarg_elem : public elem
+  {
+  public:
+    fcn_crefarg_elem (void (*fcn) (const T&), const T& arg)
+      : e_fcn (fcn), e_arg (arg) { }
+
+    void run (void) { e_fcn (e_arg); }
+
+  private:
+    void (*e_fcn) (const T&);
+    T e_arg;
+  };
+
+  // An element for calling a member function.
+
+  template <class T>
+  class method_elem : public elem
+  {
+  public:
+    method_elem (T *obj, void (T::*method) (void))
+      : e_obj (obj), e_method (method) { }
+
+    void run (void) { (e_obj->*e_method) (); }
+
+  private:
+
+    T *e_obj;
+    void (T::*e_method) (void);
+
+    // No copying!
+
+    method_elem (const method_elem&);
+
+    method_elem operator = (const method_elem&);
+  };
+
+  // An element for calling a member function with a single argument
+
+  template <class T, class A>
+  class method_arg_elem : public elem
+  {
+  public:
+    method_arg_elem (T *obj, void (T::*method) (A), A arg)
+      : e_obj (obj), e_method (method), e_arg (arg) { }
+
+    void run (void) { (e_obj->*e_method) (e_arg); }
+
+  private:
+
+    T *e_obj;
+    void (T::*e_method) (A);
+    A e_arg;
+
+    // No copying!
+
+    method_arg_elem (const method_arg_elem&);
+
+    method_arg_elem operator = (const method_arg_elem&);
+  };
+
+  // An element for calling a member function with a single argument
+
+  template <class T, class A>
+  class method_crefarg_elem : public elem
+  {
+  public:
+    method_crefarg_elem (T *obj, void (T::*method) (const A&), const A& arg)
+      : e_obj (obj), e_method (method), e_arg (arg) { }
+
+    void run (void) { (e_obj->*e_method) (e_arg); }
+
+  private:
+
+    T *e_obj;
+    void (T::*e_method) (const A&);
+    A e_arg;
+
+    // No copying!
+
+    method_crefarg_elem (const method_crefarg_elem&);
+
+    method_crefarg_elem operator = (const method_crefarg_elem&);
+  };
+
+  // An element that stores arbitrary variable, and restores it.
+
+  template <class T>
+  class restore_var_elem : public elem
+  {
+  public:
+    restore_var_elem (T& ref, const T& val)
+      : e_ptr (&ref), e_val (val) { }
+
+    void run (void) { *e_ptr = e_val; }
+
+  private:
+
+    // No copying!
+
+    restore_var_elem (const restore_var_elem&);
+
+    restore_var_elem& operator = (const restore_var_elem&);
+
+    T *e_ptr, e_val;
+  };
+
+  // Deletes a class allocated using new.
+
+  template <class T>
+  class delete_ptr_elem : public elem
+  {
+  public:
+    delete_ptr_elem (T *ptr)
+      : e_ptr (ptr) { }
+
+    void run (void) { delete e_ptr; }
+
+  private:
+
+    T *e_ptr;
+
+    // No copying!
+
+    delete_ptr_elem (const delete_ptr_elem&);
+
+    delete_ptr_elem operator = (const delete_ptr_elem&);
+  };
+
+  action_container (void) { }
+
+  virtual ~action_container (void) { }
+
+  virtual void add (elem *new_elem) = 0;
+
+  // Call to void func (void).
+  void add_fcn (void (*fcn) (void))
+  {
+    add (new fcn_elem (fcn));
+  }
+
+  // Call to void func (T).
+  template <class T>
+  void add_fcn (void (*action) (T), T val)
+  {
+    add (new fcn_arg_elem<T> (action, val));
+  }
+
+  // Call to void func (const T&).
+  template <class T>
+  void add_fcn (void (*action) (const T&), const T& val)
+  {
+    add (new fcn_crefarg_elem<T> (action, val));
+  }
+
+  // Call to T::method (void).
+  template <class T>
+  void add_method (T *obj, void (T::*method) (void))
+  {
+    add (new method_elem<T> (obj, method));
+  }
+
+  // Call to T::method (A).
+  template <class T, class A>
+  void add_method (T *obj, void (T::*method) (A), A arg)
+  {
+    add (new method_arg_elem<T, A> (obj, method, arg));
+  }
+
+  // Call to T::method (const A&).
+  template <class T, class A>
+  void add_method (T *obj, void (T::*method) (const A&), const A& arg)
+  {
+    add (new method_crefarg_elem<T, A> (obj, method, arg));
+  }
+
+  // Call to delete (T*).
+
+  template <class T>
+  void add_delete (T *obj)
+  {
+    add (new delete_ptr_elem<T> (obj));
+  }
+
+  // Protect any variable.
+  template <class T>
+  void protect_var (T& var)
+  {
+    add (new restore_var_elem<T> (var, var));
+  }
+
+  // Protect any variable, value given.
+  template <class T>
+  void protect_var (T& var, const T& val)
+  {
+    add (new restore_var_elem<T> (var, val));
+  }
+
+  operator bool (void) const { return ! empty (); }
+
+  virtual void run_first (void) = 0;
+
+  void run (size_t num)
+  {
+    if (num > size ())
+      num = size ();
+
+    for (size_t i = 0; i < num; i++)
+      run_first ();
+  }
+
+  void run (void) { run (size ()); }
+
+  virtual void discard_first (void) = 0;
+
+  void discard (size_t num)
+  {
+    if (num > size ())
+      num = size ();
+
+    for (size_t i = 0; i < num; i++)
+      discard_first ();
+  }
+
+  void discard (void) { discard (size ()); }
+
+  virtual size_t size (void) const = 0;
+
+  bool empty (void) const { return size () == 0; }
+
+private:
+
+  // No copying!
+
+  action_container (const action_container&);
+
+  action_container& operator = (const action_container&);
+};
+
+#endif
--- a/libinterp/interp-core/defun-dld.h
+++ b/libinterp/interp-core/defun-dld.h
@@ -57,14 +57,14 @@
 #else
 
 #define DEFUN_DLD(name, args_name, nargout_name, doc) \
-  DECLARE_FUN (name, args_name, nargout_name); \
+  DECLARE_FUN_NO_DEFAULTS (name, args_name, nargout_name); \
   DEFINE_FUN_INSTALLER_FUN (name, doc) \
-  DECLARE_FUN (name, args_name, nargout_name)
+  DECLARE_FUN_NO_DEFAULTS (name, args_name, nargout_name)
 
 #define DEFUNX_DLD(name, fname, gname, args_name, nargout_name, doc) \
-  DECLARE_FUNX (fname, args_name, nargout_name); \
+  DECLARE_FUNX_NO_DEFAULTS (fname, args_name, nargout_name); \
   DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc) \
-  DECLARE_FUNX (fname, args_name, nargout_name)
+  DECLARE_FUNX_NO_DEFAULTS (fname, args_name, nargout_name)
 
 #endif
 
--- a/libinterp/interp-core/defun-int.h
+++ b/libinterp/interp-core/defun-int.h
@@ -77,13 +77,23 @@
 extern OCTINTERP_API void
 defun_isargout (int, int, bool *);
 
+#define DECLARE_FUNXX(name, args_decl, nargout_decl) \
+  OCTAVE_EXPORT octave_value_list name (args_decl, nargout_decl)
+
 #define DECLARE_FUNX(name, args_name, nargout_name) \
-  OCTAVE_EXPORT octave_value_list \
-  name (const octave_value_list& args_name, int nargout_name)
+  DECLARE_FUNXX (name, \
+                 const octave_value_list& args_name = octave_value_list (), \
+                 int nargout_name = 0)
+
+#define DECLARE_FUNX_NO_DEFAULTS(name, args_name, nargout_name) \
+  DECLARE_FUNXX (name, const octave_value_list& args_name, int nargout_name)
 
 #define DECLARE_FUN(name, args_name, nargout_name) \
   DECLARE_FUNX (F ## name, args_name, nargout_name)
 
+#define DECLARE_FUN_NO_DEFAULTS(name, args_name, nargout_name) \
+  DECLARE_FUNX_NO_DEFAULTS (F ## name, args_name, nargout_name)
+
 // Define the code that will be used to insert the new function into
 // the symbol table.  We look for this name instead of the actual
 // function so that we can easily install the doc std::string too.
new file mode 100644
--- /dev/null
+++ b/libinterp/interp-core/event-queue.h
@@ -0,0 +1,126 @@
+/*
+
+Copyright (C) 2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_event_queue_h)
+#define octave_event_queue_h 1
+
+#include <queue>
+#include <memory>
+
+#include "action-container.h"
+
+class
+OCTINTERP_API
+event_queue : public action_container
+{
+public:
+
+  event_queue (void) : fifo () { }
+
+  // Destructor should not raise an exception, so all actions
+  // registered should be exception-safe (but setting error_state is
+  // allowed). If you're not sure, see event_queue_safe.
+
+  ~event_queue (void) { run (); }
+
+  void add (elem *new_elem)
+  {
+    fifo.push (new_elem);
+  }
+
+  void run_first (void)
+  {
+    if (! empty ())
+      {
+        // No leak on exception!
+        std::auto_ptr<elem> ptr (fifo.front ());
+        fifo.pop ();
+        ptr->run ();
+      }
+  }
+
+  void discard_first (void)
+  {
+    if (! empty ())
+      {
+        elem *ptr = fifo.front ();
+        fifo.pop ();
+        delete ptr;
+      }
+  }
+
+  size_t size (void) const { return fifo.size (); }
+
+protected:
+
+  std::queue<elem *> fifo;
+
+private:
+
+  // No copying!
+
+  event_queue (const event_queue&);
+
+  event_queue& operator = (const event_queue&);
+};
+
+// Like event_queue, but this one will guard against the
+// possibility of seeing an exception (or interrupt) in the cleanup
+// actions. Not that we can do much about it, but at least we won't
+// crash.
+
+class
+event_queue_safe : public event_queue
+{
+private:
+
+  static void gripe_exception (void);
+
+public:
+
+  event_queue_safe (void) : event_queue () { }
+
+  ~event_queue_safe (void)
+    {
+      while (! empty ())
+        {
+          try
+            {
+              run_first ();
+            }
+          catch (...) // Yes, the black hole. Remember we're in a dtor.
+            {
+              gripe_exception ();
+            }
+        }
+    }
+
+private:
+
+  // No copying!
+
+  event_queue_safe (const event_queue_safe&);
+
+  event_queue_safe& operator = (const event_queue_safe&);
+};
+
+#endif
--- a/libinterp/interp-core/module.mk
+++ b/libinterp/interp-core/module.mk
@@ -12,6 +12,7 @@
 
 INTERP_CORE_INC = \
   interp-core/Cell.h \
+  interp-core/action-container.h \
   interp-core/c-file-ptr-stream.h \
   interp-core/comment-list.h \
   interp-core/cutils.h \
@@ -19,6 +20,7 @@
   interp-core/defun-int.h \
   interp-core/display.h \
   interp-core/dynamic-ld.h \
+  interp-core/event-queue.h \
   interp-core/gl-render.h \
   interp-core/gl2ps-renderer.h \
   interp-core/gl2ps.h \
--- a/libinterp/interp-core/unwind-prot.cc
+++ b/libinterp/interp-core/unwind-prot.cc
@@ -25,12 +25,8 @@
 #include <config.h>
 #endif
 
-#include <cstddef>
-#include <cstring>
-
 #include "error.h"
 #include "unwind-prot.h"
-#include "utils.h"
 
 void unwind_protect_safe::gripe_exception (void)
 {
--- a/libinterp/interp-core/unwind-prot.h
+++ b/libinterp/interp-core/unwind-prot.h
@@ -24,289 +24,74 @@
 #if !defined (octave_unwind_prot_h)
 #define octave_unwind_prot_h 1
 
-#include <cstddef>
-
-#include <string>
+#include <stack>
 #include <memory>
 
-// This class allows registering cleanup actions.
+#include "action-container.h"
+
 class
 OCTINTERP_API
-unwind_protect
+unwind_protect : public action_container
 {
 public:
 
-  // A generic unwind_protect element. Knows how to run itself and discard itself.
-  // Also, contains a pointer to the next element.
-  class elem
-  {
-    elem *next;
-
-  public:
-    elem (void) : next (0) { }
-
-    virtual void run (void) { }
-
-    virtual ~elem (void) { }
-
-    friend class unwind_protect;
-
-  private:
-
-    // No copying!
-
-    elem (const elem&);
-
-    elem& operator = (const elem&);
-  };
-
-  // An element that merely runs a void (*)(void) function.
-
-  class fcn_elem : public elem
-  {
-  public:
-    fcn_elem (void (*fptr) (void))
-      : e_fptr (fptr) { }
+  unwind_protect (void) : lifo () { }
 
-    void run (void) { e_fptr (); }
-
-  private:
-    void (*e_fptr) (void);
-  };
-
-  // An element that stores a variable of type T along with a void (*) (T)
-  // function pointer, and calls the function with the parameter.
-
-  template <class T>
-  class fcn_arg_elem : public elem
-  {
-  public:
-    fcn_arg_elem (void (*fcn) (T), T arg)
-      : e_fcn (fcn), e_arg (arg) { }
+  // Destructor should not raise an exception, so all actions
+  // registered should be exception-safe (but setting error_state is
+  // allowed). If you're not sure, see unwind_protect_safe.
 
-    void run (void) { e_fcn (e_arg); }
-
-  private:
-
-    // No copying!
-
-    fcn_arg_elem (const fcn_arg_elem&);
-
-    fcn_arg_elem& operator = (const fcn_arg_elem&);
-
-    void (*e_fcn) (T);
-    T e_arg;
-  };
-
-  // An element that stores a variable of type T along with a void (*) (const T&)
-  // function pointer, and calls the function with the parameter.
+  ~unwind_protect (void) { run (); }
 
-  template <class T>
-  class fcn_crefarg_elem : public elem
+  virtual void add (elem *new_elem)
   {
-  public:
-    fcn_crefarg_elem (void (*fcn) (const T&), T arg)
-      : e_fcn (fcn), e_arg (arg) { }
-
-    void run (void) { e_fcn (e_arg); }
-
-  private:
-    void (*e_fcn) (const T&);
-    T e_arg;
-  };
-
-  // An element for calling a member function.
-
-  template <class T>
-  class method_elem : public elem
-  {
-  public:
-    method_elem (T *obj, void (T::*method) (void))
-      : e_obj (obj), e_method (method) { }
-
-    void run (void) { (e_obj->*e_method) (); }
-
-  private:
-
-    T *e_obj;
-    void (T::*e_method) (void);
-
-    // No copying!
-
-    method_elem (const method_elem&);
+    lifo.push (new_elem);
+  }
 
-    method_elem operator = (const method_elem&);
-  };
-
-  // An element that stores arbitrary variable, and restores it.
-
-  template <class T>
-  class restore_var_elem : public elem
+  void add (void (*fcn) (void *), void *ptr = 0) GCC_ATTR_DEPRECATED
   {
-  public:
-    restore_var_elem (T& ref, const T& val)
-      : e_ptr (&ref), e_val (val) { }
-
-    void run (void) { *e_ptr = e_val; }
-
-  private:
+    add (new fcn_arg_elem<void *> (fcn, ptr));
+  }
 
-    // No copying!
-
-    restore_var_elem (const restore_var_elem&);
-
-    restore_var_elem& operator = (const restore_var_elem&);
-
-    T *e_ptr, e_val;
-  };
+  operator bool (void) const { return ! empty (); }
 
-  // Deletes a class allocated using new.
-
-  template <class T>
-  class delete_ptr_elem : public elem
-  {
-  public:
-    delete_ptr_elem (T *ptr)
-      : e_ptr (ptr) { }
+  void run_top (void) GCC_ATTR_DEPRECATED { run_first (); }
 
-    void run (void) { delete e_ptr; }
-
-  private:
-
-    T *e_ptr;
-
-    // No copying!
-
-    delete_ptr_elem (const delete_ptr_elem&);
-
-    delete_ptr_elem operator = (const delete_ptr_elem&);
-  };
-
-  unwind_protect (void) : head () { }
-
-  void add (elem *new_elem)
-    {
-      new_elem->next = head;
-      head = new_elem;
-    }
-
-  // For backward compatibility.
-  void add (void (*fcn) (void *), void *ptr = 0)
-    {
-      add (new fcn_arg_elem<void *> (fcn, ptr));
-    }
+  void run_first (void)
+  {
+    if (! empty ())
+      {
+        // No leak on exception!
+        std::auto_ptr<elem> ptr (lifo.top ());
+        lifo.pop ();
+        ptr->run ();
+      }
+  }
 
-  // Call to void func (void).
-  void add_fcn (void (*fcn) (void))
-    {
-      add (new fcn_elem (fcn));
-    }
-
-  // Call to void func (T).
-  template <class T>
-  void add_fcn (void (*action) (T), T val)
-    {
-      add (new fcn_arg_elem<T> (action, val));
-    }
+  void run_top (int num) GCC_ATTR_DEPRECATED { run (num); }
 
-  // Call to void func (const T&).
-  template <class T>
-  void add_fcn (void (*action) (const T&), T val)
-    {
-      add (new fcn_crefarg_elem<T> (action, val));
-    }
-
-  // Call to T::method (void).
-  template <class T>
-  void add_method (T *obj, void (T::*method) (void))
-    {
-      add (new method_elem<T> (obj, method));
-    }
-
-  // Call to delete (T*).
-
-  template <class T>
-  void add_delete (T *obj)
-    {
-      add (new delete_ptr_elem<T> (obj));
-    }
+  void discard_top (void) GCC_ATTR_DEPRECATED { discard_first (); }
 
-  // Protect any variable.
-  template <class T>
-  void protect_var (T& var)
-    {
-      add (new restore_var_elem<T> (var, var));
-    }
-
-  // Protect any variable, value given.
-  template <class T>
-  void protect_var (T& var, const T& val)
-    {
-      add (new restore_var_elem<T> (var, val));
-    }
-
-  operator bool (void) const
-    {
-      return head != 0;
-    }
-
-  void run_top (void)
-    {
-      if (head)
-        {
-          // No leak on exception!
-          std::auto_ptr<elem> ptr (head);
-          head = ptr->next;
-          ptr->run ();
-        }
-    }
-
-  void run_top (int num)
-    {
-      while (num-- > 0)
-        run_top ();
-    }
+  void discard_first (void)
+  {
+    if (! empty ())
+      {
+        elem *ptr = lifo.top ();
+        lifo.pop ();
+        delete ptr;
+      }
+  }
 
-  void discard_top (void)
-    {
-      if (head)
-        {
-          elem *ptr = head;
-          head = ptr->next;
-          delete ptr;
-        }
-    }
+  void discard_top (int num) GCC_ATTR_DEPRECATED { discard (num); }
 
-  void discard_top (int num)
-    {
-      while (num-- > 0)
-        discard_top ();
-    }
+  size_t size (void) const { return lifo.size (); }
 
-  void run (void)
-    {
-      while (head)
-        run_top ();
-    }
+protected:
 
-  void discard (void)
-    {
-      while (head)
-        discard_top ();
-    }
-
-  // Destructor should not raise an exception, so all actions registered should
-  // be exception-safe (but setting error_state is allowed). If you're not sure,
-  // see unwind_protect_safe.
-  ~unwind_protect (void)
-    {
-      run ();
-    }
+  std::stack<elem *> lifo;
 
 private:
 
-  elem *head;
-
   // No copying!
 
   unwind_protect (const unwind_protect&);
@@ -314,24 +99,30 @@
   unwind_protect& operator = (const unwind_protect&);
 };
 
-// Like unwind_protect, but this one will guard against the possibility of seeing
-// an exception (or interrupt) in the cleanup actions. Not that we can do much about
-// it, but at least we won't crash.
+// Like unwind_protect, but this one will guard against the
+// possibility of seeing an exception (or interrupt) in the cleanup
+// actions. Not that we can do much about it, but at least we won't
+// crash.
 
 class
 OCTINTERP_API
 unwind_protect_safe : public unwind_protect
 {
+private:
+
   static void gripe_exception (void);
 
 public:
+
+  unwind_protect_safe (void) : unwind_protect () { }
+
   ~unwind_protect_safe (void)
     {
-      while (*this)
+      while (! empty ())
         {
           try
             {
-              run_top ();
+              run_first ();
             }
           catch (...) // Yes, the black hole. Remember we're in a dtor.
             {
@@ -339,6 +130,14 @@
             }
         }
     }
+
+private:
+
+  // No copying!
+
+  unwind_protect_safe (const unwind_protect_safe&);
+
+  unwind_protect_safe& operator = (const unwind_protect_safe&);
 };
 
 #endif
--- a/libinterp/interpfcn/debug.cc
+++ b/libinterp/interpfcn/debug.cc
@@ -1201,6 +1201,17 @@
 
 DEFALIAS (dbnext, dbstep);
 
+void
+debug_step (const std::string& what)
+{
+  octave_value_list args;
+
+  if (! what.empty ())
+    args(0) = what;
+
+  Fdbstep (args);
+}
+
 DEFUN (dbcont, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Command} {} dbcont\n\
@@ -1225,6 +1236,12 @@
   return octave_value_list ();
 }
 
+void
+debug_continue (void)
+{
+  Fdbcont ();
+}
+
 DEFUN (dbquit, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Command} {} dbquit\n\
@@ -1252,6 +1269,12 @@
   return octave_value_list ();
 }
 
+void
+debug_quit (void)
+{
+  Fdbquit ();
+}
+
 DEFUN (isdebugmode, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isdebugmode ()\n\
--- a/libinterp/interpfcn/debug.h
+++ b/libinterp/interpfcn/debug.h
@@ -129,6 +129,12 @@
   bool do_have_breakpoints (void) { return (! bp_set.empty ()); }
 };
 
-std::string get_file_line (const std::string& fname, size_t line);
+extern std::string get_file_line (const std::string& fname, size_t line);
+
+extern void OCTINTERP_API debug_continue (void);
+
+extern void OCTINTERP_API debug_step (const std::string& what = std::string ());
+
+extern void OCTINTERP_API debug_quit (void);
 
 #endif
--- a/libinterp/interpfcn/load-save.cc
+++ b/libinterp/interpfcn/load-save.cc
@@ -1443,6 +1443,16 @@
     }
 }
 
+void
+load_workspace (const std::string& file)
+{
+  octave_value_list args;
+
+  if (! file.empty ())
+    args(0) = file;
+
+  Fload (args);
+}
 
 DEFUN (save, args, ,
   "-*- texinfo -*-\n\
@@ -1745,6 +1755,17 @@
   return retval;
 }
 
+void
+save_workspace (const std::string& file)
+{
+  octave_value_list args;
+
+  if (! file.empty ())
+    args(0) = file;
+
+  Fsave (args);
+}
+
 DEFUN (crash_dumps_octave_core, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} crash_dumps_octave_core ()\n\
--- a/libinterp/interpfcn/load-save.h
+++ b/libinterp/interpfcn/load-save.h
@@ -87,4 +87,7 @@
 extern void
 write_header (std::ostream& os, load_save_format format);
 
+extern OCTINTERP_API void load_workspace (const std::string& file);
+extern OCTINTERP_API void save_workspace (const std::string& file);
+
 #endif
--- a/libinterp/interpfcn/variables.cc
+++ b/libinterp/interpfcn/variables.cc
@@ -2340,8 +2340,8 @@
     {
       if (argc == 1)
         {
-          do_clear_globals (argv, argc, 1);
-          do_clear_variables (argv, argc, 1);
+          do_clear_globals (argv, argc, true);
+          do_clear_variables (argv, argc, true);
         }
       else
         {
@@ -2460,6 +2460,12 @@
   return retval;
 }
 
+void
+clear_current_scope (void)
+{
+  Fclear ();
+}
+
 DEFUN (whos_line_format, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} whos_line_format ()\n\
--- a/libinterp/interpfcn/variables.h
+++ b/libinterp/interpfcn/variables.h
@@ -148,4 +148,7 @@
 
 extern OCTINTERP_API void maybe_missing_function_hook (const std::string& name);
 
+// Equivalent to Fclear without any arguments.
+extern OCTINTERP_API void clear_current_scope (void);
+
 #endif
--- a/liboctave/util/cmd-hist.cc
+++ b/liboctave/util/cmd-hist.cc
@@ -69,6 +69,8 @@
 
   void do_remove (int);
 
+  void do_clear (void);
+
   int do_where (void) const;
 
   int do_length (void) const;
@@ -201,6 +203,12 @@
   ::octave_remove_history (n);
 }
 
+void
+gnu_history::do_clear (void)
+{
+  ::octave_clear_history ();
+}
+
 int
 gnu_history::do_where (void) const
 {
@@ -587,6 +595,13 @@
     instance->do_remove (n);
 }
 
+void
+command_history::clear (void)
+{
+  if (instance_ok ())
+    instance->do_clear ();
+}
+
 int
 command_history::where (void)
 {
@@ -807,6 +822,11 @@
 {
 }
 
+void
+command_history::do_clear (void)
+{
+}
+
 int
 command_history::do_where (void) const
 {
--- a/liboctave/util/cmd-hist.h
+++ b/liboctave/util/cmd-hist.h
@@ -65,6 +65,8 @@
 
   static void remove (int);
 
+  static void clear (void);
+
   static int where (void);
 
   static int length (void);
@@ -158,6 +160,8 @@
 
   virtual void do_remove (int);
 
+  virtual void do_clear (void);
+
   virtual int do_where (void) const;
 
   virtual int do_length (void) const;
--- a/liboctave/util/oct-rl-hist.c
+++ b/liboctave/util/oct-rl-hist.c
@@ -210,6 +210,12 @@
     }
 }
 
+void
+octave_clear_history (void)
+{
+  clear_history ();
+}
+
 char *
 octave_history_goto_mark (int n)
 {
--- a/liboctave/util/oct-rl-hist.h
+++ b/liboctave/util/oct-rl-hist.h
@@ -66,6 +66,8 @@
 
 extern void octave_remove_history (int);
 
+extern void octave_clear_history (void);
+
 extern char *octave_history_goto_mark (int n);
 
 extern char *octave_history_get (int n);