changeset 16420:81ec95768520

use octave-link instead of hook for edit function * octave-main-thread.cc (edit_hook_fcn): Delete. (octave_main_thread::run): Don't install callback function for edit function. * octave-qt-link.h, octave-qt-link.cc (octave_qt_link::do_edit_file): Pass file as string instead of octave_value_list. Return status. * interpfcn/octave-link.h, interpfcn/octave-link.cc: Move here from interp-core directory. * libinterp/interp-core/module.mk, libinterp/interpfcn/module.mk: Update file lists. * octave-link.h: Don't include oct-obj.h. (octave_link::edit_file, octave_link::do_edit_file): Return bool. * octave-link.cc (F__octave_link_edit_file__): New function. * edit.m: Call __octave_link_edit_file__ instead of __execute_edit_hook__. * __execute_edit_hook__.cc: Delete * libinterp/corefcn/module.mk (COREFCN_SRC): Remove it from the list.
author John W. Eaton <jwe@octave.org>
date Wed, 03 Apr 2013 23:16:37 -0400
parents 16bfbf9136d3
children 40d1ddca4db5
files libgui/src/octave-main-thread.cc libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libinterp/corefcn/__execute_edit_hook__.cc libinterp/corefcn/module.mk libinterp/interp-core/module.mk libinterp/interp-core/octave-link.cc libinterp/interp-core/octave-link.h libinterp/interpfcn/module.mk libinterp/interpfcn/octave-link.cc libinterp/interpfcn/octave-link.h scripts/miscellaneous/edit.m
diffstat 12 files changed, 429 insertions(+), 575 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/octave-main-thread.cc	Wed Apr 03 21:15:30 2013 -0400
+++ b/libgui/src/octave-main-thread.cc	Wed Apr 03 23:16:37 2013 -0400
@@ -35,16 +35,6 @@
 #include "octave-main-thread.h"
 #include "octave-link.h"
 
-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 ()
 {
 }
@@ -60,10 +50,6 @@
   octave_initialize_interpreter (octave_cmdline_argc, octave_cmdline_argv,
                                  octave_embedded);
 
-  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 ();
 
--- a/libgui/src/octave-qt-link.cc	Wed Apr 03 21:15:30 2013 -0400
+++ b/libgui/src/octave-qt-link.cc	Wed Apr 03 23:16:37 2013 -0400
@@ -122,25 +122,19 @@
     }
 }
 
-void
-octave_qt_link::do_edit_file (const octave_value_list& args)
+bool
+octave_qt_link::do_edit_file (const std::string& file)
 {
+  bool retval = false;
+
   if (event_listener)
     {
-      if (args.length () == 1)
-        {
-          std::string file = args(0).string_value ();
+      event_listener->edit_file (file);
 
-          if (! error_state)
-            {
-              event_listener->edit_file (file);
-              do_process_events ();
+      do_process_events ();
 
-            }
-          else
-            ::error ("expecting file name in edit file callback");
-        }
-      else
-        ::error ("invalid call to edit file callback");
+      retval = true;
     }
+
+  return retval;
 }
--- a/libgui/src/octave-qt-link.h	Wed Apr 03 21:15:30 2013 -0400
+++ b/libgui/src/octave-qt-link.h	Wed Apr 03 23:16:37 2013 -0400
@@ -68,7 +68,7 @@
 
   void do_update_breakpoint (bool insert, const std::string& file, int line);
 
-  void do_edit_file (const octave_value_list& args);
+  bool do_edit_file (const std::string& file);
 
 private:
 
--- a/libinterp/corefcn/__execute_edit_hook__.cc	Wed Apr 03 21:15:30 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
-
-Copyright (C) 2013 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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "defun.h"
-#include "error.h"
-#include "defun.h"
-#include "hook-fcn.h"
-#include "oct-obj.h"
-
-static hook_function_list edit_hook_functions;
-
-DEFUN (add_edit_hook, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {@var{id} =} add_edit_hook (@var{fcn})\n\
-@deftypefnx {Built-in Function} {@var{id} =} add_edit_hook (@var{fcn}, @var{data})\n\
-Add the named function or function handle @var{fcn} to the list of functions to call\n\
-to handle editing files.  The function should have the form\n\
-\n\
-@example\n\
-@var{fcn} (@var{file}, @var{data})\n\
-@end example\n\
-\n\
-If @var{data} is omitted, Octave calls the function without one argument.\n\
-\n\
-The returned identifier may be used to remove the function handle from\n\
-the list of input hook functions.\n\
-@seealso{remove_edit_hook}\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 1 || nargin == 2)
-    {
-      octave_value user_data;
-
-      if (nargin == 2)
-        user_data = args(1);
-
-      hook_function hook_fcn (args(0), user_data);
-
-      if (! error_state)
-        {
-          edit_hook_functions.insert (hook_fcn.id (), hook_fcn);
-
-          retval = hook_fcn.id ();
-        }
-      else
-        error ("add_edit_hook: expecting string as first arg");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-DEFUN (remove_edit_hook, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} remove_edit_hook (@var{name})\n\
-@deftypefnx {Built-in Function} {} remove_input_event_hook (@var{fcn_id})\n\
-Remove the named function or function handle with the given identifier\n\
-from the list of functions to call to handle editing files.\n\
-@seealso{add_edit_hook}\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 1 || nargin == 2)
-    {
-      std::string hook_fcn_id = args(0).string_value ();
-
-      bool warn = (nargin < 2);
-
-      if (! error_state)
-        {
-          hook_function_list::iterator p
-            = edit_hook_functions.find (hook_fcn_id);
-
-          if (p != edit_hook_functions.end ())
-            edit_hook_functions.erase (p);
-          else if (warn)
-            warning ("remove_edit_hook: %s not found in list",
-                     hook_fcn_id.c_str ());
-        }
-      else
-        error ("remove_edit_hook: argument not valid as a hook function name or id");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-DEFUN (__execute_edit_hook__, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{status} =} __execute_edit_hook__ (@var{file})\n\
-Undocumented internal function.\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  if (edit_hook_functions.empty ())
-    retval = false;
-  else
-    {
-      edit_hook_functions.run (args);
-
-      retval = true;
-    }
-
-  return retval;
-}
-
-/*
-## No test needed for internal helper function.
-%!assert (1)
-*/
--- a/libinterp/corefcn/module.mk	Wed Apr 03 21:15:30 2013 -0400
+++ b/libinterp/corefcn/module.mk	Wed Apr 03 23:16:37 2013 -0400
@@ -27,7 +27,6 @@
 COREFCN_SRC = \
   corefcn/__contourc__.cc \
   corefcn/__dispatch__.cc \
-  corefcn/__execute_edit_hook__.cc \
   corefcn/__lin_interpn__.cc \
   corefcn/__pchip_deriv__.cc \
   corefcn/__qp__.cc \
--- a/libinterp/interp-core/module.mk	Wed Apr 03 21:15:30 2013 -0400
+++ b/libinterp/interp-core/module.mk	Wed Apr 03 23:16:37 2013 -0400
@@ -36,7 +36,6 @@
   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 \
@@ -92,7 +91,6 @@
   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 \
--- a/libinterp/interp-core/octave-link.cc	Wed Apr 03 21:15:30 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
-
-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;
-}
--- a/libinterp/interp-core/octave-link.h	Wed Apr 03 21:15:30 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/*
-
-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 std::string& file, int line)
-  {
-    if (instance_ok ())
-      instance->do_enter_debugger_event (file, line);
-  }
-
-  static void exit_debugger_event (const std::string& file, int line)
-  {
-    if (instance_ok ())
-      instance->do_exit_debugger_event (file, line);
-  }
-
-  static void
-  update_breakpoint (bool insert, const std::string& file, int line)
-  {
-    if (instance_ok ())
-      instance->do_update_breakpoint (insert, file, line);
-  }
-
-  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 std::string& file, int line) = 0;
-
-  virtual void
-  do_delete_debugger_pointer (const std::string& file, int line) = 0;
-
-  virtual void do_pre_input_event (void) = 0;
-  virtual void do_post_input_event (void) = 0;
-
-  virtual void do_enter_debugger_event (const std::string& file, int line) = 0;
-  virtual void do_exit_debugger_event (const std::string& file, int line) = 0;
-
-  virtual void do_update_breakpoint (bool insert,
-                                     const std::string& file, int line) = 0;
-
-  virtual void do_edit_file (const octave_value_list& args) = 0;
-};
-
-#endif // OCTAVELINK_H
--- a/libinterp/interpfcn/module.mk	Wed Apr 03 21:15:30 2013 -0400
+++ b/libinterp/interpfcn/module.mk	Wed Apr 03 23:16:37 2013 -0400
@@ -16,6 +16,7 @@
   interpfcn/load-path.h \
   interpfcn/load-save.h \
   interpfcn/ls-oct-ascii.h \
+  interpfcn/octave-link.h \
   interpfcn/oct-hist.h \
   interpfcn/pager.h \
   interpfcn/pr-output.h \
@@ -42,6 +43,7 @@
   interpfcn/load-path.cc \
   interpfcn/load-save.cc \
   interpfcn/ls-oct-ascii.cc \
+  interpfcn/octave-link.cc \
   interpfcn/oct-hist.cc \
   interpfcn/pager.cc \
   interpfcn/pr-output.cc \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/interpfcn/octave-link.cc	Wed Apr 03 23:16:37 2013 -0400
@@ -0,0 +1,168 @@
+/*
+
+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 "defun.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;
+}
+
+DEFUN (__octave_link_edit_file__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __octave_link_edit_file__ (@var{file})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      std::string file = args(0).string_value ();
+
+      if (! error_state)
+        retval = octave_link::edit_file (file);
+      else
+        error ("expecting file name as argument");
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/interpfcn/octave-link.h	Wed Apr 03 23:16:37 2013 -0400
@@ -0,0 +1,248 @@
+/*
+
+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>
+
+#include "event-queue.h"
+#include "octave-event-listener.h"
+
+class octave_mutex;
+
+// \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 std::string& file, int line)
+  {
+    if (instance_ok ())
+      instance->do_enter_debugger_event (file, line);
+  }
+
+  static void exit_debugger_event (const std::string& file, int line)
+  {
+    if (instance_ok ())
+      instance->do_exit_debugger_event (file, line);
+  }
+
+  static void
+  update_breakpoint (bool insert, const std::string& file, int line)
+  {
+    if (instance_ok ())
+      instance->do_update_breakpoint (insert, file, line);
+  }
+
+  static bool
+  edit_file (const std::string& file)
+  {
+    return instance_ok () ? instance->do_edit_file (file) : false;
+  }
+
+  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 std::string& file, int line) = 0;
+
+  virtual void
+  do_delete_debugger_pointer (const std::string& file, int line) = 0;
+
+  virtual void do_pre_input_event (void) = 0;
+  virtual void do_post_input_event (void) = 0;
+
+  virtual void do_enter_debugger_event (const std::string& file, int line) = 0;
+  virtual void do_exit_debugger_event (const std::string& file, int line) = 0;
+
+  virtual void do_update_breakpoint (bool insert,
+                                     const std::string& file, int line) = 0;
+
+  virtual bool do_edit_file (const std::string& file) = 0;
+};
+
+#endif // OCTAVELINK_H
--- a/scripts/miscellaneous/edit.m	Wed Apr 03 21:15:30 2013 -0400
+++ b/scripts/miscellaneous/edit.m	Wed Apr 03 23:16:37 2013 -0400
@@ -563,7 +563,7 @@
   ## Give the hook function a chance.  If that fails, fall back
   ## on running an editor with the system function.
 
-  status = __execute_edit_hook__ (file);
+  status = __octave_link_edit_file__ (file);
 
   if (! status)
     system (sprintf (undo_string_escapes (editor),