changeset 16415:70032fc70bee

move octave-link and octave-event-listener classes to libinterp * libinterp/interp-core/octave-event-listener.h: Rename from libgui/src/octave-adapter/octave-event-listener.h. * libinterp/interp-core/octave-link.cc: Rename from libgui/src/octave-adapter/octave-link.cc. * libinterp/interp-core/octave-link.h: Rename from libgui/src/octave-adapter/octave-link.h. * octave-link.h, octave-link.cc: (octave_link::connect): New function. (octave_link::instance_ok): Don't create octave_link instance. (octave_link::launch_octave, octave_link::do_launch_octave): Delete. (octave_link::pre_input_event): Rename from octave_link::pre_input_event_hook_fcn. Change all callers. (octave_link::post_input_event): Rename from octave_link::post_input_event_hook_fcn. Change all callers. (octave_link::enter_debugger_event): Rename from octave_link::enter_debugger_event_hook_fcn. Change all callers. (octave_link::exit_debugger_event): Rename from octave_link::exit_debugger_event_hook_fcn. Change all callers. (octave_link::update_breakpoint): Rename from octave_link::update_breakpoint_hook_fcn. Change all callers. (octave_link::do_pre_input_event): Rename from octave_link::do_pre_input_event_hook_fcn. Change all callers. (octave_link::do_post_input_event): Rename from octave_link::do_post_input_event_hook_fcn. Change all callers. (octave_link::do_enter_debugger_event): Rename from octave_link::do_enter_debugger_event_hook_fcn. Change all callers. (octave_link::do_exit_debugger_event): Rename from octave_link::do_exit_debugger_event_hook_fcn. Change all callers. (octave_link::do_update_breakpoint): Rename from octave_link::do_update_breakpoint_hook_fcn. Change all callers. (octave_link::do_update_workspace, octave_link::do_update_history, octave_link::do_insert_debugger_pointer, octave_link::do_delete_debugger_pointer, octave_link::do_pre_input_event, octave_link::do_post_input_event, octave_link::do_enter_debugger_event, octave_link::do_exit_debugger_event, octave_link::do_update_breakpoint, octave_link::do_edit_file): Now pure virtual functions. (octave_link::main_thread): Delete. * libinterp/interp-core/module.mk (INTERP_CORE_INC): Include interp-core/octave-event-listener.h and interp-core/octave-link.h in the list. (INTERP_CORE_SRC): Include interp-core/octave-link.cc in the list. * octave-qt-link.h, octave-qt-link.cc: New files. * main-window.cc (main_window::construct): Call octave_link::connect and octave_link::register_event_listener after everything else is initialized. (main_window::main_window): Don't call octave_link::launch_octave. * libgui/src/octave-main-thread.h: Rename from libgui/src/octave-adapter/octave-main-thread.h. * libgui/src/module.mk (octave_gui_MOC): Update for new location of octave-main-thread.cc. (noinst_HEADERS): Update for new locations of octave-event-listener.h, octave-link.h, and octave-main-thread.h. Include src/octave-qt-link.h in the list. (src_libgui_src_la_SOURCES): Update for new locations of octave-link.cc and octave-main-thread.cc. Include src/octave-qt-link.cc in the list. (src_libgui_src_la_CPPFLAGS): Delete -I$(srcdir)/src/octave-adapter from the list.
author John W. Eaton <jwe@octave.org>
date Wed, 03 Apr 2013 18:11:55 -0400
parents 610e02bf9579
children 169f71c9d9c8
files libgui/src/main-window.cc libgui/src/module.mk libgui/src/octave-adapter/octave-event-listener.h libgui/src/octave-adapter/octave-link.cc libgui/src/octave-adapter/octave-link.h libgui/src/octave-adapter/octave-main-thread.cc libgui/src/octave-adapter/octave-main-thread.h libgui/src/octave-main-thread.cc libgui/src/octave-main-thread.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libinterp/interp-core/module.mk libinterp/interp-core/octave-event-listener.h libinterp/interp-core/octave-link.cc libinterp/interp-core/octave-link.h
diffstat 15 files changed, 975 insertions(+), 855 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/main-window.cc	Wed Aug 08 20:51:24 2012 -0700
+++ b/libgui/src/main-window.cc	Wed Apr 03 18:11:55 2013 -0400
@@ -42,7 +42,7 @@
 #include "file-editor.h"
 #endif
 #include "main-window.h"
-#include "octave-link.h"
+#include "octave-qt-link.h"
 #include "settings-dialog.h"
 
 #include "builtins.h"
@@ -60,7 +60,6 @@
 {
   // We have to set up all our windows, before we finally launch octave.
   construct ();
-  octave_link::launch_octave ();
 }
 
 main_window::~main_window ()
@@ -1165,7 +1164,6 @@
   setStatusBar (_status_bar);
 
   _octave_qt_event_listener = new octave_qt_event_listener ();
-  octave_link::register_event_listener (_octave_qt_event_listener);
 
   connect (_octave_qt_event_listener,
            SIGNAL (current_directory_has_changed_signal (QString)),
@@ -1209,6 +1207,12 @@
            SIGNAL (edit_file_signal (const QString&)),
            this,
            SLOT (handle_edit_file_request(const QString&)));
+
+  // FIXME -- is it possible to eliminate the event_listenter?
+
+  octave_link::connect (new octave_qt_link ());
+
+  octave_link::register_event_listener (_octave_qt_event_listener);
 }
 
 void
--- a/libgui/src/module.mk	Wed Aug 08 20:51:24 2012 -0700
+++ b/libgui/src/module.mk	Wed Apr 03 18:11:55 2013 -0400
@@ -71,6 +71,7 @@
   src/moc-files-dockwidget.cc \
   src/moc-history-dockwidget.cc \
   src/moc-main-window.cc \
+  src/moc-octave-main-thread.cc \
   src/moc-octave-qt-event-listener.cc \
   src/moc-settings-dialog.cc \
   src/moc-terminal-dockwidget.cc \
@@ -78,7 +79,6 @@
   src/moc-welcome-wizard.cc \
   src/moc-workspace-model.cc \
   src/moc-workspace-view.cc \
-  src/octave-adapter/moc-octave-main-thread.cc \
   src/qtinfo/moc-parser.cc \
   src/qtinfo/moc-webinfo.cc \
   src/moc-octave-dock-widget.cc
@@ -104,11 +104,10 @@
   src/m-editor/find-dialog.h \
   src/m-editor/lexer-octave-gui.h \
   src/main-window.h \
-  src/octave-adapter/octave-event-listener.h \
-  src/octave-adapter/octave-link.h \
-  src/octave-adapter/octave-main-thread.h \
   src/octave-gui.h \
+  src/octave-main-thread.h \
   src/octave-qt-event-listener.h \
+  src/octave-qt-link.h \
   src/qtinfo/parser.h \
   src/qtinfo/webinfo.h \
   src/resource-manager.h \
@@ -129,10 +128,10 @@
   src/m-editor/find-dialog.cc \
   src/m-editor/lexer-octave-gui.cc \
   src/main-window.cc \
-  src/octave-adapter/octave-link.cc \
-  src/octave-adapter/octave-main-thread.cc \
   src/octave-gui.cc \
+  src/octave-main-thread.cc \
   src/octave-qt-event-listener.cc \
+  src/octave-qt-link.cc \
   src/qtinfo/parser.cc \
   src/qtinfo/webinfo.cc \
   src/resource-manager.cc \
@@ -153,7 +152,6 @@
   -I$(srcdir)/qterminal/libqterminal \
   -Isrc -I$(srcdir)/src \
   -I$(srcdir)/src/m-editor \
-  -I$(srcdir)/src/octave-adapter \
   -I$(srcdir)/src/qtinfo \
   -I$(top_srcdir)/liboctave/cruft/misc \
   -I$(top_srcdir)/liboctave/array \
--- a/libgui/src/octave-adapter/octave-event-listener.h	Wed Aug 08 20:51:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +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 OCTAVEEVENTLISTENER_H
-#define OCTAVEEVENTLISTENER_H
-
-#include <string>
-
-class octave_event_listener
-{
-  public:
-    octave_event_listener () { }
-    virtual ~octave_event_listener () { }
-
-    virtual void
-    current_directory_has_changed (const std::string& directory) = 0;
-
-    virtual void
-    update_workspace (void) = 0;
-
-    virtual void
-    update_history (void) = 0;
-
-    virtual void
-    insert_debugger_pointer (const std::string& file, int line) = 0;
-
-    virtual void
-    delete_debugger_pointer (const std::string& file, int line) = 0;
-
-    virtual void
-    update_dbstop_marker (bool insert, const std::string& file, int line) = 0;
-
-    virtual void edit_file (const std::string& file) = 0;
-
-    virtual void about_to_exit () = 0;
-
-    virtual void entered_debug_mode () = 0;
-    virtual void quit_debug_mode () = 0;
-};
-
-#endif // OCTAVEEVENTLISTENER_H
--- a/libgui/src/octave-adapter/octave-link.cc	Wed Aug 08 20:51:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,330 +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 "cmd-edit.h"
-#include "oct-env.h"
-#include "oct-mutex.h"
-#include "singleton-cleanup.h"
-#include "symtab.h"
-#include "toplev.h"
-
-#include "octave-link.h"
-
-static int
-octave_readline_hook (void)
-{
-  octave_link::entered_readline_hook ();
-  octave_link::generate_events ();
-  octave_link::process_events ();
-  octave_link::finished_readline_hook ();
-
-  return 0;
-}
-
-static void
-octave_exit_hook (int)
-{
-  octave_link::about_to_exit ();
-}
-
-octave_link *octave_link::instance = 0;
-
-octave_link::octave_link (void)
-  : event_listener (0), event_queue_mutex (new octave_mutex ()),
-    gui_event_queue (), last_cwd (), debugging (false)
-{ }
-
-void
-octave_link::do_launch_octave (void)
-{
-  // Create both threads.
-  main_thread = new octave_main_thread ();
-
-  command_editor::add_event_hook (octave_readline_hook);
-
-  octave_exit = octave_exit_hook;
-
-  // Start the first one.
-  main_thread->start ();
-}
-
-void
-octave_link::do_register_event_listener (octave_event_listener *el)
-{
-  event_listener = el;
-}
-
-void
-octave_link::do_generate_events (void)
-{
-  std::string current_working_directory = octave_env::get_current_directory ();
-
-  if (current_working_directory != last_cwd)
-    {
-      last_cwd = current_working_directory;
-
-      if (event_listener)
-        event_listener->current_directory_has_changed (last_cwd);
-    }
-
-  if (debugging != Vdebugging)
-    {
-      debugging = Vdebugging;
-
-      if (event_listener)
-        {
-          if (debugging)
-            event_listener->entered_debug_mode ();
-          else
-            event_listener->quit_debug_mode ();
-        }
-    }
-}
-
-void
-octave_link::do_process_events (void)
-{
-  event_queue_mutex->lock ();
-
-  gui_event_queue.run ();
-
-  event_queue_mutex->unlock ();
-}
-
-void
-octave_link::do_about_to_exit (void)
-{
-  event_queue_mutex->lock ();
-
-  gui_event_queue.discard ();
-
-  event_queue_mutex->unlock ();
-
-  if (event_listener)
-    event_listener->about_to_exit ();
-}
-
-std::string
-octave_link::do_last_working_directory (void)
-{
-  return last_cwd;
-}
-
-void
-octave_link::do_update_workspace (void)
-{
-  if (event_listener)
-    {
-      event_listener->update_workspace ();
-
-      do_process_events ();
-    }
-}
-
-void
-octave_link::do_update_history (void)
-{
-  if (event_listener)
-    {
-      event_listener->update_history ();
-
-      do_process_events ();
-    }
-}
-
-void
-octave_link::do_insert_debugger_pointer (const octave_value_list& args)
-{
-  if (event_listener)
-    {
-      if (args.length () == 1)
-        {
-          octave_scalar_map m = args(0).scalar_map_value ();
-
-          if (! error_state)
-            {
-              octave_value ov_file = m.getfield ("file");
-              octave_value ov_line = m.getfield ("line");
-
-              std::string file = ov_file.string_value ();
-              int line = ov_line.int_value ();
-
-              if (! error_state)
-                {
-                  event_listener->insert_debugger_pointer (file, line);
-
-                  do_process_events ();
-                }
-              else
-                ::error ("invalid struct in debug pointer callback");
-            }
-          else
-            ::error ("expecting struct in debug pointer callback");
-        }
-      else
-        ::error ("invalid call to debug pointer callback");
-    }
-}
-
-void
-octave_link::do_delete_debugger_pointer (const octave_value_list& args)
-{
-  if (event_listener)
-    {
-      if (args.length () == 1)
-        {
-          octave_scalar_map m = args(0).scalar_map_value ();
-
-          if (! error_state)
-            {
-              octave_value ov_file = m.getfield ("file");
-              octave_value ov_line = m.getfield ("line");
-
-              std::string file = ov_file.string_value ();
-              int line = ov_line.int_value ();
-
-              if (! error_state)
-                {
-                  event_listener->delete_debugger_pointer (file, line);
-
-                  do_process_events ();
-                }
-              else
-                ::error ("invalid struct in debug pointer callback");
-            }
-          else
-            ::error ("expecting struct in debug pointer callback");
-        }
-      else
-        ::error ("invalid call to debug pointer callback");
-    }
-}
-
-void
-octave_link::do_pre_input_event_hook_fcn (void)
-{
-  do_update_workspace ();
-}
-
-void
-octave_link::do_post_input_event_hook_fcn (void)
-{
-  do_update_history ();
-}
-
-void
-octave_link::do_enter_debugger_event_hook_fcn (const octave_value_list& args)
-{
-  do_insert_debugger_pointer (args);
-}
-
-void
-octave_link::do_exit_debugger_event_hook_fcn (const octave_value_list& args)
-{
-  do_delete_debugger_pointer (args);
-}
-
-void
-octave_link::do_update_breakpoint_hook_fcn
-  (bool insert, const octave_value_list& args)
-{
-  if (event_listener)
-    {
-      if (args.length () == 1)
-        {
-          octave_scalar_map m = args(0).scalar_map_value ();
-
-          if (! error_state)
-            {
-              octave_value ov_file = m.getfield ("file");
-              octave_value ov_line = m.getfield ("line");
-
-              std::string file = ov_file.string_value ();
-              int line = ov_line.int_value ();
-
-              if (! error_state)
-                {
-                  event_listener->update_dbstop_marker (insert, file, line);
-
-                  do_process_events ();
-                }
-              else
-                ::error ("invalid struct in dbstop marker callback");
-            }
-          else
-            ::error ("expecting struct in dbstop marker callback");
-        }
-      else
-        ::error ("invalid call to dbstop marker callback");
-    }
-}
-
-void
-octave_link::do_edit_file (const octave_value_list& args)
-{
-  if (event_listener)
-    {
-      if (args.length () == 1)
-        {
-          std::string file = args(0).string_value ();
-
-          if (! error_state)
-            {
-              event_listener->edit_file (file);
-              do_process_events ();
-
-            }
-          else
-            ::error ("expecting file name in edit file callback");
-        }
-      else
-        ::error ("invalid call to edit file callback");
-    }
-}
-
-bool
-octave_link::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_link ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create octave_link object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
--- a/libgui/src/octave-adapter/octave-link.h	Wed Aug 08 20:51:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +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 OCTAVELINK_H
-#define OCTAVELINK_H
-
-#include <string>
-
-class octave_mutex;
-
-#include "oct-obj.h"
-
-#include "event-queue.h"
-
-#include "octave-main-thread.h"
-#include "octave-event-listener.h"
-
-// \class OctaveLink
-// \brief Provides threadsafe access to octave.
-// \author Jacob Dawid
-//
-// This class is a wrapper around octave and provides thread safety by
-// buffering access operations to octave and executing them in the
-// readline event hook, which lives in the octave thread.
-
-class octave_link
-{
-protected:
-
-  octave_link (void);
-
-public:
-
-  ~octave_link (void) { }
-
-  static void launch_octave (void)
-  {
-    if (instance_ok ())
-      instance->do_launch_octave ();
-  }
-
-  static void register_event_listener (octave_event_listener *el)
-  {
-    if (instance_ok ())
-      instance->do_register_event_listener (el);
-  }
-
-  static void generate_events (void)
-  {
-    if (instance_ok ())
-      instance->do_generate_events ();
-  }
-
-  static void process_events (void)
-  {
-    if (instance_ok ())
-      instance->do_process_events ();
-  }
-
-  template <class T>
-  static void post_event (T *obj, void (T::*method) (void))
-  {
-    if (instance_ok ())
-      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)
-  {
-    if (instance_ok ())
-      instance->do_about_to_exit ();
-  }
-
-  static void entered_readline_hook (void)
-  {
-    if (instance_ok ())
-      instance->do_entered_readline_hook ();
-  }
-
-  static void finished_readline_hook (void)
-  {
-    if (instance_ok ())
-      instance->do_finished_readline_hook ();
-  }
-
-  static std::string last_working_directory (void)
-  {
-    return instance_ok ()
-      ? instance->do_last_working_directory () : std::string ();
-  }
-
-  static void update_workspace (void)
-  {
-    if (instance_ok ())
-      instance->do_update_workspace ();
-  }
-
-  static void update_history (void)
-  {
-    if (instance_ok ())
-      instance->do_update_history ();
-  }
-
-  static void pre_input_event_hook_fcn (void)
-  {
-    if (instance_ok ())
-      instance->do_pre_input_event_hook_fcn ();
-  }
-
-  static void post_input_event_hook_fcn (void)
-  {
-    if (instance_ok ())
-      instance->do_post_input_event_hook_fcn ();
-  }
-
-  static void enter_debugger_event_hook_fcn (const octave_value_list& args)
-  {
-    if (instance_ok ())
-      instance->do_enter_debugger_event_hook_fcn (args);
-  }
-
-  static void exit_debugger_event_hook_fcn (const octave_value_list& args)
-  {
-    if (instance_ok ())
-      instance->do_exit_debugger_event_hook_fcn (args);
-  }
-
-  static void
-  update_breakpoint_hook_fcn (bool insert, const octave_value_list& args)
-  {
-    if (instance_ok ())
-      instance->do_update_breakpoint_hook_fcn (insert, args);
-  }
-
-  static void
-  edit_file (const octave_value_list& args)
-  {
-    if (instance_ok ())
-      instance->do_edit_file (args);
-  }
-
-private:
-
-  static octave_link *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  // No copying!
-
-  octave_link (const octave_link&);
-
-  octave_link& operator = (const octave_link&);
-
-  static bool instance_ok (void);
-
-  octave_event_listener *event_listener;
-
-  // Thread running octave_main.
-  octave_main_thread *main_thread;
-
-  // Semaphore to lock access to the event queue.
-  octave_mutex *event_queue_mutex;
-
-  // Event Queue.
-  event_queue gui_event_queue;
-
-  // Stores the last known current working directory of octave.
-  std::string last_cwd;
-
-  bool debugging;
-
-  void do_launch_octave (void);
-  void do_register_event_listener (octave_event_listener *oel);
-
-  void do_generate_events (void);
-  void do_process_events (void);
-
-  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);
-
-  void do_entered_readline_hook (void) { }
-  void do_finished_readline_hook (void) { }
-
-  std::string do_last_working_directory (void);
-  void do_update_workspace (void);
-  void do_update_history (void);
-  void do_insert_debugger_pointer (const octave_value_list& args);
-  void do_delete_debugger_pointer (const octave_value_list& args);
-
-  void do_pre_input_event_hook_fcn (void);
-  void do_post_input_event_hook_fcn (void);
-  void do_enter_debugger_event_hook_fcn (const octave_value_list& args);
-  void do_exit_debugger_event_hook_fcn (const octave_value_list& args);
-  void do_update_breakpoint_hook_fcn (bool insert,
-                                      const octave_value_list& args);
-
-  void do_edit_file (const octave_value_list& args);
-};
-
-#endif // OCTAVELINK_H
--- a/libgui/src/octave-adapter/octave-main-thread.cc	Wed Aug 08 20:51:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <clocale>
-#include <string>
-
-#include "builtin-defun-decls.h"
-#include "octave.h"
-#include "ov-builtin.h"
-#include "ov-fcn-handle.h"
-
-#include "octave-main-thread.h"
-#include "octave-link.h"
-
-static octave_value_list
-pre_input_event_hook_fcn (const octave_value_list&, int)
-{
-  octave_value_list retval;
-
-  octave_link::pre_input_event_hook_fcn ();
-
-  return retval;
-}
-
-static octave_value_list
-post_input_event_hook_fcn (const octave_value_list&, int)
-{
-  octave_value_list retval;
-
-  octave_link::post_input_event_hook_fcn ();
-
-  return retval;
-}
-
-static octave_value_list
-enter_debugger_event_hook_fcn (const octave_value_list& args, int)
-{
-  octave_value_list retval;
-
-  octave_link::enter_debugger_event_hook_fcn (args);
-
-  return retval;
-}
-
-static octave_value_list
-exit_debugger_event_hook_fcn (const octave_value_list& args, int)
-{
-  octave_value_list retval;
-
-  octave_link::exit_debugger_event_hook_fcn (args);
-
-  return retval;
-}
-
-static octave_value_list
-dbstop_hook_fcn (const octave_value_list& args, int)
-{
-  octave_value_list retval;
-
-  octave_link::update_breakpoint_hook_fcn (true, args);
-
-  return retval;
-}
-
-static octave_value_list
-dbclear_hook_fcn (const octave_value_list& args, int)
-{
-  octave_value_list retval;
-
-  octave_link::update_breakpoint_hook_fcn (false, args);
-
-  return retval;
-}
-
-static octave_value_list
-edit_hook_fcn (const octave_value_list& args, int)
-{
-  octave_value_list retval;
-
-  octave_link::edit_file (args);
-
-  return retval;
-}
-
-octave_main_thread::octave_main_thread () : QThread ()
-{
-}
-
-void
-octave_main_thread::run ()
-{
-  // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
-  setlocale (LC_NUMERIC, "C");
-
-  emit ready ();
-
-  octave_initialize_interpreter (octave_cmdline_argc, octave_cmdline_argv,
-                                 octave_embedded);
-
-  octave_value pre_fcn (new octave_builtin (pre_input_event_hook_fcn));
-  octave_value pre_fcn_handle (new octave_fcn_handle (pre_fcn));
-  Fadd_pre_input_event_hook (pre_fcn_handle);
-
-  octave_value post_fcn (new octave_builtin (post_input_event_hook_fcn));
-  octave_value post_fcn_handle (new octave_fcn_handle (post_fcn));
-  Fadd_post_input_event_hook (post_fcn_handle);
-
-  octave_value enter_debugger_fcn (new octave_builtin (enter_debugger_event_hook_fcn));
-  octave_value enter_debugger_fcn_handle (new octave_fcn_handle (enter_debugger_fcn));
-  Fadd_enter_debugger_event_hook (enter_debugger_fcn_handle);
-
-  octave_value exit_debugger_fcn (new octave_builtin (exit_debugger_event_hook_fcn));
-  octave_value exit_debugger_fcn_handle (new octave_fcn_handle (exit_debugger_fcn));
-  Fadd_exit_debugger_event_hook (exit_debugger_fcn_handle);
-
-  octave_value dbstop_fcn (new octave_builtin (dbstop_hook_fcn));
-  octave_value dbstop_fcn_handle (new octave_fcn_handle (dbstop_fcn));
-  Fadd_dbstop_hook (dbstop_fcn_handle);
-
-  octave_value dbclear_fcn (new octave_builtin (dbclear_hook_fcn));
-  octave_value dbclear_fcn_handle (new octave_fcn_handle (dbclear_fcn));
-  Fadd_dbclear_hook (dbclear_fcn_handle);
-
-  octave_value edit_fcn (new octave_builtin (edit_hook_fcn));
-  octave_value edit_fcn_handle (new octave_fcn_handle (edit_fcn));
-  Fadd_edit_hook (edit_fcn_handle);
-
-  // Prime the history list.
-  octave_link::update_history ();
-
-  octave_execute_interpreter ();
-}
--- a/libgui/src/octave-adapter/octave-main-thread.h	Wed Aug 08 20:51:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +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 OCTAVEMAINTHREAD_H
-#define OCTAVEMAINTHREAD_H
-
-#include <QThread>
-
-/**
-  * \class octave_main
-  * \brief This class represents a thread just running octave_main.
-  * \author Jacob Dawid
-  */
-class octave_main_thread : public QThread
-{
-  Q_OBJECT
-public:
-  /** Creates a new thread running octave_main. */
-  octave_main_thread ();
-
-signals:
-  /** This signal will be emitted when the thread is about to actually
-    * run octave_main. */
-  void ready();
-
-protected:
-  /** Runs octave_main. */
-  void run ();
-};
-
-#endif // OCTAVEMAINTHREAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-main-thread.cc	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,155 @@
+/*
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <clocale>
+#include <string>
+
+#include "builtin-defun-decls.h"
+#include "octave.h"
+#include "ov-builtin.h"
+#include "ov-fcn-handle.h"
+
+#include "octave-main-thread.h"
+#include "octave-link.h"
+
+static octave_value_list
+pre_input_event_hook_fcn (const octave_value_list&, int)
+{
+  octave_value_list retval;
+
+  octave_link::pre_input_event ();
+
+  return retval;
+}
+
+static octave_value_list
+post_input_event_hook_fcn (const octave_value_list&, int)
+{
+  octave_value_list retval;
+
+  octave_link::post_input_event ();
+
+  return retval;
+}
+
+static octave_value_list
+enter_debugger_event_hook_fcn (const octave_value_list& args, int)
+{
+  octave_value_list retval;
+
+  octave_link::enter_debugger_event (args);
+
+  return retval;
+}
+
+static octave_value_list
+exit_debugger_event_hook_fcn (const octave_value_list& args, int)
+{
+  octave_value_list retval;
+
+  octave_link::exit_debugger_event (args);
+
+  return retval;
+}
+
+static octave_value_list
+dbstop_hook_fcn (const octave_value_list& args, int)
+{
+  octave_value_list retval;
+
+  octave_link::update_breakpoint (true, args);
+
+  return retval;
+}
+
+static octave_value_list
+dbclear_hook_fcn (const octave_value_list& args, int)
+{
+  octave_value_list retval;
+
+  octave_link::update_breakpoint (false, args);
+
+  return retval;
+}
+
+static octave_value_list
+edit_hook_fcn (const octave_value_list& args, int)
+{
+  octave_value_list retval;
+
+  octave_link::edit_file (args);
+
+  return retval;
+}
+
+octave_main_thread::octave_main_thread () : QThread ()
+{
+}
+
+void
+octave_main_thread::run ()
+{
+  // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
+  setlocale (LC_NUMERIC, "C");
+
+  emit ready ();
+
+  octave_initialize_interpreter (octave_cmdline_argc, octave_cmdline_argv,
+                                 octave_embedded);
+
+  octave_value pre_fcn (new octave_builtin (pre_input_event_hook_fcn));
+  octave_value pre_fcn_handle (new octave_fcn_handle (pre_fcn));
+  Fadd_pre_input_event_hook (pre_fcn_handle);
+
+  octave_value post_fcn (new octave_builtin (post_input_event_hook_fcn));
+  octave_value post_fcn_handle (new octave_fcn_handle (post_fcn));
+  Fadd_post_input_event_hook (post_fcn_handle);
+
+  octave_value enter_debugger_fcn (new octave_builtin (enter_debugger_event_hook_fcn));
+  octave_value enter_debugger_fcn_handle (new octave_fcn_handle (enter_debugger_fcn));
+  Fadd_enter_debugger_event_hook (enter_debugger_fcn_handle);
+
+  octave_value exit_debugger_fcn (new octave_builtin (exit_debugger_event_hook_fcn));
+  octave_value exit_debugger_fcn_handle (new octave_fcn_handle (exit_debugger_fcn));
+  Fadd_exit_debugger_event_hook (exit_debugger_fcn_handle);
+
+  octave_value dbstop_fcn (new octave_builtin (dbstop_hook_fcn));
+  octave_value dbstop_fcn_handle (new octave_fcn_handle (dbstop_fcn));
+  Fadd_dbstop_hook (dbstop_fcn_handle);
+
+  octave_value dbclear_fcn (new octave_builtin (dbclear_hook_fcn));
+  octave_value dbclear_fcn_handle (new octave_fcn_handle (dbclear_fcn));
+  Fadd_dbclear_hook (dbclear_fcn_handle);
+
+  octave_value edit_fcn (new octave_builtin (edit_hook_fcn));
+  octave_value edit_fcn_handle (new octave_fcn_handle (edit_fcn));
+  Fadd_edit_hook (edit_fcn_handle);
+
+  // Prime the history list.
+  octave_link::update_history ();
+
+  octave_execute_interpreter ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-main-thread.h	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,50 @@
+/*
+
+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 OCTAVEMAINTHREAD_H
+#define OCTAVEMAINTHREAD_H
+
+#include <QThread>
+
+/**
+  * \class octave_main
+  * \brief This class represents a thread just running octave_main.
+  * \author Jacob Dawid
+  */
+class octave_main_thread : public QThread
+{
+  Q_OBJECT
+public:
+  /** Creates a new thread running octave_main. */
+  octave_main_thread ();
+
+signals:
+  /** This signal will be emitted when the thread is about to actually
+    * run octave_main. */
+  void ready();
+
+protected:
+  /** Runs octave_main. */
+  void run ();
+};
+
+#endif // OCTAVEMAINTHREAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-qt-link.cc	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,215 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+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 "cmd-edit.h"
+#include "oct-env.h"
+#include "oct-mutex.h"
+#include "singleton-cleanup.h"
+#include "symtab.h"
+#include "toplev.h"
+
+#include "octave-qt-link.h"
+
+octave_qt_link::octave_qt_link (void)
+  : octave_link (), main_thread (new octave_main_thread)
+{
+  // Start the first one.
+  main_thread->start ();
+}
+
+void
+octave_qt_link::do_update_workspace (void)
+{
+  if (event_listener)
+    {
+      event_listener->update_workspace ();
+
+      do_process_events ();
+    }
+}
+
+void
+octave_qt_link::do_update_history (void)
+{
+  if (event_listener)
+    {
+      event_listener->update_history ();
+
+      do_process_events ();
+    }
+}
+
+void
+octave_qt_link::do_insert_debugger_pointer (const octave_value_list& args)
+{
+  if (event_listener)
+    {
+      if (args.length () == 1)
+        {
+          octave_scalar_map m = args(0).scalar_map_value ();
+
+          if (! error_state)
+            {
+              octave_value ov_file = m.getfield ("file");
+              octave_value ov_line = m.getfield ("line");
+
+              std::string file = ov_file.string_value ();
+              int line = ov_line.int_value ();
+
+              if (! error_state)
+                {
+                  event_listener->insert_debugger_pointer (file, line);
+
+                  do_process_events ();
+                }
+              else
+                ::error ("invalid struct in debug pointer callback");
+            }
+          else
+            ::error ("expecting struct in debug pointer callback");
+        }
+      else
+        ::error ("invalid call to debug pointer callback");
+    }
+}
+
+void
+octave_qt_link::do_delete_debugger_pointer (const octave_value_list& args)
+{
+  if (event_listener)
+    {
+      if (args.length () == 1)
+        {
+          octave_scalar_map m = args(0).scalar_map_value ();
+
+          if (! error_state)
+            {
+              octave_value ov_file = m.getfield ("file");
+              octave_value ov_line = m.getfield ("line");
+
+              std::string file = ov_file.string_value ();
+              int line = ov_line.int_value ();
+
+              if (! error_state)
+                {
+                  event_listener->delete_debugger_pointer (file, line);
+
+                  do_process_events ();
+                }
+              else
+                ::error ("invalid struct in debug pointer callback");
+            }
+          else
+            ::error ("expecting struct in debug pointer callback");
+        }
+      else
+        ::error ("invalid call to debug pointer callback");
+    }
+}
+
+void
+octave_qt_link::do_pre_input_event (void)
+{
+  do_update_workspace ();
+}
+
+void
+octave_qt_link::do_post_input_event (void)
+{
+  do_update_history ();
+}
+
+void
+octave_qt_link::do_enter_debugger_event (const octave_value_list& args)
+{
+  do_insert_debugger_pointer (args);
+}
+
+void
+octave_qt_link::do_exit_debugger_event (const octave_value_list& args)
+{
+  do_delete_debugger_pointer (args);
+}
+
+void
+octave_qt_link::do_update_breakpoint (bool insert,
+                                      const octave_value_list& args)
+{
+  if (event_listener)
+    {
+      if (args.length () == 1)
+        {
+          octave_scalar_map m = args(0).scalar_map_value ();
+
+          if (! error_state)
+            {
+              octave_value ov_file = m.getfield ("file");
+              octave_value ov_line = m.getfield ("line");
+
+              std::string file = ov_file.string_value ();
+              int line = ov_line.int_value ();
+
+              if (! error_state)
+                {
+                  event_listener->update_dbstop_marker (insert, file, line);
+
+                  do_process_events ();
+                }
+              else
+                ::error ("invalid struct in dbstop marker callback");
+            }
+          else
+            ::error ("expecting struct in dbstop marker callback");
+        }
+      else
+        ::error ("invalid call to dbstop marker callback");
+    }
+}
+
+void
+octave_qt_link::do_edit_file (const octave_value_list& args)
+{
+  if (event_listener)
+    {
+      if (args.length () == 1)
+        {
+          std::string file = args(0).string_value ();
+
+          if (! error_state)
+            {
+              event_listener->edit_file (file);
+              do_process_events ();
+
+            }
+          else
+            ::error ("expecting file name in edit file callback");
+        }
+      else
+        ::error ("invalid call to edit file callback");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-qt-link.h	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,85 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+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 OCTAVE_QT_LINK_H
+#define OCTAVE_QT_LINK_H
+
+#include <string>
+
+class octave_mutex;
+
+#include "oct-obj.h"
+
+#include "event-queue.h"
+
+#include "octave-link.h"
+#include "octave-main-thread.h"
+#include "octave-event-listener.h"
+
+// \class OctaveLink
+// \brief Provides threadsafe access to octave.
+// \author Jacob Dawid
+//
+// This class is a wrapper around octave and provides thread safety by
+// buffering access operations to octave and executing them in the
+// readline event hook, which lives in the octave thread.
+
+class octave_qt_link : public octave_link
+{
+public:
+
+  octave_qt_link (void);
+
+  ~octave_qt_link (void) { }
+
+  void do_update_workspace (void);
+
+  void do_update_history (void);
+
+  void do_insert_debugger_pointer (const octave_value_list& args);
+  void do_delete_debugger_pointer (const octave_value_list& args);
+
+  void do_pre_input_event (void);
+  void do_post_input_event (void);
+
+  void do_enter_debugger_event (const octave_value_list& args);
+  void do_exit_debugger_event (const octave_value_list& args);
+
+  void do_update_breakpoint (bool insert, const octave_value_list& args);
+
+  void do_edit_file (const octave_value_list& args);
+
+private:
+
+  // No copying!
+
+  octave_qt_link (const octave_qt_link&);
+
+  octave_qt_link& operator = (const octave_qt_link&);
+
+  // Thread running octave_main.
+  octave_main_thread *main_thread;
+};
+
+#endif // OCTAVELINK_H
--- a/libinterp/interp-core/module.mk	Wed Aug 08 20:51:24 2012 -0700
+++ b/libinterp/interp-core/module.mk	Wed Apr 03 18:11:55 2013 -0400
@@ -35,6 +35,8 @@
   interp-core/mex.h \
   interp-core/mexproto.h \
   interp-core/mxarray.in.h \
+  interp-core/octave-event-listener.h \
+  interp-core/octave-link.h \
   interp-core/oct-errno.h \
   interp-core/oct-fstrm.h \
   interp-core/oct-hdf5.h \
@@ -90,6 +92,7 @@
   interp-core/ls-oct-binary.cc \
   interp-core/ls-utils.cc \
   interp-core/mex.cc \
+  interp-core/octave-link.cc \
   interp-core/oct-fstrm.cc \
   interp-core/oct-iostrm.cc \
   interp-core/oct-lvalue.cc \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/interp-core/octave-event-listener.h	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,60 @@
+/*
+
+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 OCTAVEEVENTLISTENER_H
+#define OCTAVEEVENTLISTENER_H
+
+#include <string>
+
+class octave_event_listener
+{
+  public:
+    octave_event_listener () { }
+    virtual ~octave_event_listener () { }
+
+    virtual void
+    current_directory_has_changed (const std::string& directory) = 0;
+
+    virtual void
+    update_workspace (void) = 0;
+
+    virtual void
+    update_history (void) = 0;
+
+    virtual void
+    insert_debugger_pointer (const std::string& file, int line) = 0;
+
+    virtual void
+    delete_debugger_pointer (const std::string& file, int line) = 0;
+
+    virtual void
+    update_dbstop_marker (bool insert, const std::string& file, int line) = 0;
+
+    virtual void edit_file (const std::string& file) = 0;
+
+    virtual void about_to_exit () = 0;
+
+    virtual void entered_debug_mode () = 0;
+    virtual void quit_debug_mode () = 0;
+};
+
+#endif // OCTAVEEVENTLISTENER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/interp-core/octave-link.cc	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,146 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+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 "cmd-edit.h"
+#include "oct-env.h"
+#include "oct-mutex.h"
+#include "singleton-cleanup.h"
+#include "symtab.h"
+#include "toplev.h"
+
+#include "octave-link.h"
+
+static int
+octave_readline_hook (void)
+{
+  octave_link::entered_readline_hook ();
+  octave_link::generate_events ();
+  octave_link::process_events ();
+  octave_link::finished_readline_hook ();
+
+  return 0;
+}
+
+static void
+octave_exit_hook (int)
+{
+  octave_link::about_to_exit ();
+}
+
+octave_link *octave_link::instance = 0;
+
+octave_link::octave_link (void)
+  : event_listener (0), event_queue_mutex (new octave_mutex ()),
+    gui_event_queue (), last_cwd (), debugging (false)
+{
+  command_editor::add_event_hook (octave_readline_hook);
+
+  octave_exit = octave_exit_hook;
+}
+
+// OBJ should be a new object of a class that is derived from
+// the base class octave_link.  It will be cleaned up by octave_link.
+
+void
+octave_link::connect (octave_link* obj)
+{
+  if (instance)
+    ::error ("octave_link is already linked!");
+  else
+    instance = obj;
+
+  singleton_cleanup_list::add (cleanup_instance);
+}
+
+void
+octave_link::do_register_event_listener (octave_event_listener *el)
+{
+  event_listener = el;
+}
+
+void
+octave_link::do_generate_events (void)
+{
+  std::string current_working_directory = octave_env::get_current_directory ();
+
+  if (current_working_directory != last_cwd)
+    {
+      last_cwd = current_working_directory;
+
+      if (event_listener)
+        event_listener->current_directory_has_changed (last_cwd);
+    }
+
+  if (debugging != Vdebugging)
+    {
+      debugging = Vdebugging;
+
+      if (event_listener)
+        {
+          if (debugging)
+            event_listener->entered_debug_mode ();
+          else
+            event_listener->quit_debug_mode ();
+        }
+    }
+}
+
+void
+octave_link::do_process_events (void)
+{
+  event_queue_mutex->lock ();
+
+  gui_event_queue.run ();
+
+  event_queue_mutex->unlock ();
+}
+
+void
+octave_link::do_about_to_exit (void)
+{
+  event_queue_mutex->lock ();
+
+  gui_event_queue.discard ();
+
+  event_queue_mutex->unlock ();
+
+  if (event_listener)
+    event_listener->about_to_exit ();
+}
+
+std::string
+octave_link::do_last_working_directory (void)
+{
+  return last_cwd;
+}
+
+bool
+octave_link::instance_ok (void)
+{
+  return instance != 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/interp-core/octave-link.h	Wed Apr 03 18:11:55 2013 -0400
@@ -0,0 +1,249 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+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/>.
+
+*/
+
+#if !defined (octave_link_h)
+#define octave_link_h 1
+
+#include <string>
+
+class octave_mutex;
+
+#include "oct-obj.h"
+
+#include "event-queue.h"
+
+#include "octave-event-listener.h"
+
+// \class OctaveLink
+// \brief Provides threadsafe access to octave.
+// \author Jacob Dawid
+//
+// This class is a wrapper around octave and provides thread safety by
+// buffering access operations to octave and executing them in the
+// readline event hook, which lives in the octave thread.
+
+class octave_link
+{
+protected:
+
+  octave_link (void);
+
+public:
+
+  virtual ~octave_link (void) { }
+
+  static void register_event_listener (octave_event_listener *el)
+  {
+    if (instance_ok ())
+      instance->do_register_event_listener (el);
+  }
+
+  static void generate_events (void)
+  {
+    if (instance_ok ())
+      instance->do_generate_events ();
+  }
+
+  static void process_events (void)
+  {
+    if (instance_ok ())
+      instance->do_process_events ();
+  }
+
+  template <class T>
+  static void post_event (T *obj, void (T::*method) (void))
+  {
+    if (instance_ok ())
+      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)
+  {
+    if (instance_ok ())
+      instance->do_about_to_exit ();
+  }
+
+  static void entered_readline_hook (void)
+  {
+    if (instance_ok ())
+      instance->do_entered_readline_hook ();
+  }
+
+  static void finished_readline_hook (void)
+  {
+    if (instance_ok ())
+      instance->do_finished_readline_hook ();
+  }
+
+  static std::string last_working_directory (void)
+  {
+    return instance_ok ()
+      ? instance->do_last_working_directory () : std::string ();
+  }
+
+  static void update_workspace (void)
+  {
+    if (instance_ok ())
+      instance->do_update_workspace ();
+  }
+
+  static void update_history (void)
+  {
+    if (instance_ok ())
+      instance->do_update_history ();
+  }
+
+  static void pre_input_event (void)
+  {
+    if (instance_ok ())
+      instance->do_pre_input_event ();
+  }
+
+  static void post_input_event (void)
+  {
+    if (instance_ok ())
+      instance->do_post_input_event ();
+  }
+
+  static void enter_debugger_event (const octave_value_list& args)
+  {
+    if (instance_ok ())
+      instance->do_enter_debugger_event (args);
+  }
+
+  static void exit_debugger_event (const octave_value_list& args)
+  {
+    if (instance_ok ())
+      instance->do_exit_debugger_event (args);
+  }
+
+  static void
+  update_breakpoint (bool insert, const octave_value_list& args)
+  {
+    if (instance_ok ())
+      instance->do_update_breakpoint (insert, args);
+  }
+
+  static void
+  edit_file (const octave_value_list& args)
+  {
+    if (instance_ok ())
+      instance->do_edit_file (args);
+  }
+
+  static void connect (octave_link *);
+
+private:
+
+  static octave_link *instance;
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
+  // No copying!
+
+  octave_link (const octave_link&);
+
+  octave_link& operator = (const octave_link&);
+
+  static bool instance_ok (void);
+
+protected:
+
+  octave_event_listener *event_listener;
+
+  // Semaphore to lock access to the event queue.
+  octave_mutex *event_queue_mutex;
+
+  // Event Queue.
+  event_queue gui_event_queue;
+
+  // Stores the last known current working directory of octave.
+  std::string last_cwd;
+
+  bool debugging;
+
+  void do_register_event_listener (octave_event_listener *oel);
+
+  void do_generate_events (void);
+  void do_process_events (void);
+
+  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);
+
+  void do_entered_readline_hook (void) { }
+  void do_finished_readline_hook (void) { }
+
+  std::string do_last_working_directory (void);
+
+  virtual void do_update_workspace (void) = 0;
+
+  virtual void do_update_history (void) = 0;
+
+  virtual void do_insert_debugger_pointer (const octave_value_list& args) = 0;
+  virtual void do_delete_debugger_pointer (const octave_value_list& args) = 0;
+
+  virtual void do_pre_input_event (void) = 0;
+  virtual void do_post_input_event (void) = 0;
+
+  virtual void do_enter_debugger_event (const octave_value_list& args) = 0;
+  virtual void do_exit_debugger_event (const octave_value_list& args) = 0;
+
+  virtual void do_update_breakpoint (bool insert,
+                                     const octave_value_list& args) = 0;
+
+  virtual void do_edit_file (const octave_value_list& args) = 0;
+};
+
+#endif // OCTAVELINK_H