# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1365104758 14400 # Node ID 22c0e0df1dbcd0f7065d1e1b0c9d90ef7fcfb3d8 # Parent aa81cfa5c3599afa6891ea2d0d2334159a141a7f# Parent 2c8860d563e54477148c6db03aef81c671935aa5 Merge in Adam's changes diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/qterminal/libqterminal/unix/SelfListener.cpp --- a/libgui/qterminal/libqterminal/unix/SelfListener.cpp Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/qterminal/libqterminal/unix/SelfListener.cpp Thu Apr 04 15:45:58 2013 -0400 @@ -23,7 +23,7 @@ } void SelfListener::run() { - char buf[4096]; + char buf[4096 + 1]; int len; bool running = true; while(running) { diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/history-dockwidget.cc --- a/libgui/src/history-dockwidget.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/history-dockwidget.cc Thu Apr 04 15:45:58 2013 -0400 @@ -120,40 +120,24 @@ } void -history_dock_widget::request_history_model_update () +history_dock_widget::set_history (const QStringList& hist) { - octave_link::post_event (this, &history_dock_widget::update_history_callback); + _history_model->setStringList (hist); + _history_list_view->scrollToBottom (); } void -history_dock_widget::reset_model () +history_dock_widget::append_history (const QString& hist_entry) +{ + QStringList lst = _history_model->stringList (); + lst.append (hist_entry); + _history_model->setStringList (lst); + _history_list_view->scrollToBottom (); +} + +void +history_dock_widget::clear_history (void) { _history_model->setStringList (QStringList ()); } -void -history_dock_widget::update_history_callback (void) -{ - // 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::fromUtf8 (entry.data (), entry.size ())); - } - - _history_list_view->scrollToBottom (); - } -} diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/history-dockwidget.h --- a/libgui/src/history-dockwidget.h Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/history-dockwidget.h Thu Apr 04 15:45:58 2013 -0400 @@ -35,11 +35,10 @@ public: history_dock_widget (QWidget *parent = 0); - void update_history_callback (void); - public slots: - void request_history_model_update (); - void reset_model (); + void set_history (const QStringList& hist); + void append_history (const QString& hist_entry); + void clear_history (void); signals: void information (const QString& message); diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/main-window.cc --- a/libgui/src/main-window.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/main-window.cc Thu Apr 04 15:45:58 2013 -0400 @@ -42,7 +42,6 @@ #include "file-editor.h" #endif #include "main-window.h" -#include "octave-link.h" #include "settings-dialog.h" #include "builtins.h" @@ -60,7 +59,6 @@ { // We have to set up all our windows, before we finally launch octave. construct (); - octave_link::launch_octave (); } main_window::~main_window () @@ -72,6 +70,9 @@ if (_octave_qt_event_listener) delete _octave_qt_event_listener; + octave_link::connect_link (0); + delete _octave_qt_link; + #ifdef HAVE_QSCINTILLA if (_file_editor) delete _file_editor; @@ -155,7 +156,7 @@ } void -main_window::handle_clear_history_request() +main_window::handle_clear_history_request (void) { octave_link::post_event (this, &main_window::clear_history_callback); } @@ -288,12 +289,6 @@ } void -main_window::update_history (void) -{ - _history_dock_widget->update_history_callback (); -} - -void main_window::change_current_working_directory () { QString directory = @@ -494,39 +489,6 @@ } void -main_window::handle_insert_debugger_pointer_request (const QString& file, int line) -{ -#ifdef HAVE_QSCINTILLA - _file_editor->handle_insert_debugger_pointer_request (file, line); -#endif -} - -void -main_window::handle_delete_debugger_pointer_request (const QString& file, int line) -{ -#ifdef HAVE_QSCINTILLA - _file_editor->handle_delete_debugger_pointer_request (file, line); -#endif -} - -void -main_window::handle_update_dbstop_marker_request (bool insert, - const QString& file, int line) -{ -#ifdef HAVE_QSCINTILLA - _file_editor->handle_update_dbstop_marker_request (insert, file, line); -#endif -} - -void -main_window::handle_edit_file_request (const QString& file) -{ -#ifdef HAVE_QSCINTILLA - _file_editor->handle_edit_file_request (file); -#endif -} - -void main_window::debug_continue () { octave_link::post_event (this, &main_window::debug_continue_callback); @@ -1165,7 +1127,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)), @@ -1178,11 +1139,6 @@ SLOT (update_workspace ())); connect (_octave_qt_event_listener, - SIGNAL (update_history_signal ()), - this, - SLOT (update_history ())); - - connect (_octave_qt_event_listener, SIGNAL (entered_debug_mode_signal ()), this, SLOT(handle_entered_debug_mode ())); @@ -1192,23 +1148,47 @@ this, SLOT (handle_quit_debug_mode ())); - connect (_octave_qt_event_listener, - SIGNAL (insert_debugger_pointer_signal (const QString&, int)), this, + // FIXME -- is it possible to eliminate the event_listenter? + + _octave_qt_link = new octave_qt_link (); + + connect (_octave_qt_link, + SIGNAL (set_history_signal (const QStringList&)), + _history_dock_widget, SLOT (set_history (const QStringList&))); + + connect (_octave_qt_link, + SIGNAL (append_history_signal (const QString&)), + _history_dock_widget, SLOT (append_history (const QString&))); + + connect (_octave_qt_link, + SIGNAL (clear_history_signal (void)), + _history_dock_widget, SLOT (clear_history (void))); + + connect (_octave_qt_link, + SIGNAL (update_dbstop_marker_signal (bool, const QString&, int)), + _file_editor, + SLOT (handle_update_dbstop_marker_request (bool, const QString&, int))); + + connect (_octave_qt_link, + SIGNAL (edit_file_signal (const QString&)), + _file_editor, + SLOT (handle_edit_file_request (const QString&))); + + connect (_octave_qt_link, + SIGNAL (insert_debugger_pointer_signal (const QString&, int)), + _file_editor, SLOT (handle_insert_debugger_pointer_request (const QString&, int))); - connect (_octave_qt_event_listener, - SIGNAL (delete_debugger_pointer_signal (const QString&, int)), this, + connect (_octave_qt_link, + SIGNAL (delete_debugger_pointer_signal (const QString&, int)), + _file_editor, SLOT (handle_delete_debugger_pointer_request (const QString&, int))); - connect (_octave_qt_event_listener, - SIGNAL (update_dbstop_marker_signal (bool, const QString&, int)), - this, - SLOT (handle_update_dbstop_marker_request (bool, const QString&, int))); + _octave_qt_link->execute_interpreter (); - connect (_octave_qt_event_listener, - SIGNAL (edit_file_signal (const QString&)), - this, - SLOT (handle_edit_file_request(const QString&))); + octave_link::connect_link (_octave_qt_link); + + octave_link::register_event_listener (_octave_qt_event_listener); } void @@ -1232,9 +1212,7 @@ void main_window::clear_history_callback (void) { - command_history::clear (); - - _history_dock_widget->reset_model (); + Fhistory (ovl ("-c")); } void diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/main-window.h --- a/libgui/src/main-window.h Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/main-window.h Thu Apr 04 15:45:58 2013 -0400 @@ -50,6 +50,7 @@ #include "terminal-dockwidget.h" #include "documentation-dockwidget.h" #include "octave-qt-event-listener.h" +#include "octave-qt-link.h" /** * \class MainWindow @@ -70,7 +71,7 @@ void handle_save_workspace_request (); void handle_load_workspace_request (); void handle_clear_workspace_request (); - void handle_clear_history_request (); + void handle_clear_history_request (void); void handle_command_double_clicked (const QString& command); void new_file (); void open_file (); @@ -86,7 +87,6 @@ void reset_windows (); void current_working_directory_has_changed (const QString& directory); void update_workspace (void); - void update_history (void); void change_current_working_directory (); void set_current_working_directory (const QString& directory); void current_working_directory_up (); @@ -107,10 +107,6 @@ void handle_entered_debug_mode (); void handle_quit_debug_mode (); - void handle_insert_debugger_pointer_request (const QString& file, int line); - void handle_delete_debugger_pointer_request (const QString& file, int line); - void handle_update_dbstop_marker_request (bool insert, const QString& file, int line); - void handle_edit_file_request (const QString& file); void debug_continue (); void debug_step_into (); void debug_step_over (); @@ -178,6 +174,8 @@ octave_qt_event_listener *_octave_qt_event_listener; + octave_qt_link *_octave_qt_link; + // Flag for closing whole application bool _closing; }; diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/module.mk --- a/libgui/src/module.mk Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/module.mk Thu Apr 04 15:45:58 2013 -0400 @@ -72,13 +72,13 @@ src/moc-history-dockwidget.cc \ src/moc-main-window.cc \ src/moc-octave-qt-event-listener.cc \ + src/moc-octave-qt-link.cc \ src/moc-settings-dialog.cc \ src/moc-terminal-dockwidget.cc \ src/moc-color-picker.cc \ 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 \ diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-adapter/octave-event-listener.h --- a/libgui/src/octave-adapter/octave-event-listener.h Thu Apr 04 20:18:54 2013 +0100 +++ /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 -. - -*/ - -#ifndef OCTAVEEVENTLISTENER_H -#define OCTAVEEVENTLISTENER_H - -#include - -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 diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-adapter/octave-link.cc --- a/libgui/src/octave-adapter/octave-link.cc Thu Apr 04 20:18:54 2013 +0100 +++ /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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#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; -} diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-adapter/octave-link.h --- a/libgui/src/octave-adapter/octave-link.h Thu Apr 04 20:18:54 2013 +0100 +++ /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 -. - -*/ - -#ifndef OCTAVELINK_H -#define OCTAVELINK_H - -#include - -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 - static void post_event (T *obj, void (T::*method) (void)) - { - if (instance_ok ()) - instance->do_post_event (obj, method); - } - - template - static void post_event (T *obj, void (T::*method) (A), A arg) - { - if (instance_ok ()) - instance->do_post_event (obj, method, arg); - } - - template - 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 - void do_post_event (T *obj, void (T::*method) (void)) - { - gui_event_queue.add_method (obj, method); - } - - template - void do_post_event (T *obj, void (T::*method) (A), A arg) - { - gui_event_queue.add_method (obj, method, arg); - } - - template - 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 diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-adapter/octave-main-thread.cc --- a/libgui/src/octave-adapter/octave-main-thread.cc Thu Apr 04 20:18:54 2013 +0100 +++ /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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#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 (); -} diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-adapter/octave-main-thread.h --- a/libgui/src/octave-adapter/octave-main-thread.h Thu Apr 04 20:18:54 2013 +0100 +++ /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 -. - -*/ - -#ifndef OCTAVEMAINTHREAD_H -#define OCTAVEMAINTHREAD_H - -#include - -/** - * \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 diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-gui.cc --- a/libgui/src/octave-gui.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/octave-gui.cc Thu Apr 04 15:45:58 2013 -0400 @@ -80,7 +80,7 @@ int octave_start_gui (int argc, char *argv[]) { - dissociate_terminal (); + // dissociate_terminal (); QApplication application (argc, argv); diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-main-thread.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/octave-main-thread.cc Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,55 @@ +/* + +Copyright (C) 2013 John W. Eaton +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#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" + +void +octave_main_thread::run (void) +{ + // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting + setlocale (LC_NUMERIC, "C"); + + octave_initialize_interpreter (octave_cmdline_argc, octave_cmdline_argv, + octave_embedded); + + octave_execute_interpreter (); +} + +void +octave_main_thread::execute_interpreter (void) +{ + start (); +} diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-main-thread.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/octave-main-thread.h Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,49 @@ +/* + +Copyright (C) 2013 John W. Eaton +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 +. + +*/ + +#ifndef OCTAVEMAINTHREAD_H +#define OCTAVEMAINTHREAD_H + +#include + +/** + * \class octave_main + * \brief This class represents a thread just running octave_main. + * \author Jacob Dawid + */ +class octave_main_thread : public QThread +{ +public: + // Create a new thread for running the octave interpreter. + octave_main_thread (void) : QThread () { } + + // Start the thread and initialize and execute the octave + // interpreter. + void execute_interpreter (void); + +protected: + // Avoid exec. Run the octave interpreter in the new thread. + void run (void); +}; + +#endif // OCTAVEMAINTHREAD_H diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-qt-event-listener.cc --- a/libgui/src/octave-qt-event-listener.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/octave-qt-event-listener.cc Thu Apr 04 15:45:58 2013 -0400 @@ -48,41 +48,6 @@ } void -octave_qt_event_listener::update_history (void) -{ - emit update_history_signal (); -} - -void -octave_qt_event_listener::insert_debugger_pointer (const std::string& file, - int line) -{ - emit insert_debugger_pointer_signal (QString::fromStdString (file), line); -} - -void -octave_qt_event_listener::delete_debugger_pointer (const std::string& file, - int line) -{ - emit delete_debugger_pointer_signal (QString::fromStdString (file), line); -} - -void -octave_qt_event_listener::update_dbstop_marker (bool insert, - const std::string& file, - int line) -{ - emit update_dbstop_marker_signal (insert, QString::fromStdString (file), - line); -} - -void -octave_qt_event_listener::edit_file (const std::string& file) -{ - emit edit_file_signal (QString::fromStdString (file)); -} - -void octave_qt_event_listener::about_to_exit () { qApp->quit (); diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-qt-event-listener.h --- a/libgui/src/octave-qt-event-listener.h Thu Apr 04 20:18:54 2013 +0100 +++ b/libgui/src/octave-qt-event-listener.h Thu Apr 04 15:45:58 2013 -0400 @@ -36,11 +36,6 @@ void current_directory_has_changed (const std::string& directory); void update_workspace (void); - void update_history (void); - void insert_debugger_pointer (const std::string& file, int line); - void delete_debugger_pointer (const std::string& file, int line); - void update_dbstop_marker (bool insert, const std::string& file, int line); - void edit_file (const std::string& file); void about_to_exit (); void entered_debug_mode (); @@ -49,11 +44,6 @@ signals: void current_directory_has_changed_signal (const QString& directory); void update_workspace_signal (void); - void update_history_signal (void); - void insert_debugger_pointer_signal (const QString& file, int line); - void delete_debugger_pointer_signal (const QString& file, int line); - void update_dbstop_marker_signal (bool insert, const QString& file, int line); - void edit_file_signal (const QString& file); void entered_debug_mode_signal (); void quit_debug_mode_signal (); }; diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-qt-link.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/octave-qt-link.cc Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,128 @@ +/* + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "str-vec.h" + +#include "octave-qt-link.h" + +octave_qt_link::octave_qt_link (void) + : octave_link (), main_thread (new octave_main_thread) +{ +} + +void +octave_qt_link::execute_interpreter (void) +{ + main_thread->execute_interpreter (); +} + +void +octave_qt_link::do_update_workspace (void) +{ + if (event_listener) + { + event_listener->update_workspace (); + + do_process_events (); + } +} + +void +octave_qt_link::do_set_history (const string_vector& hist) +{ + QStringList qt_hist; + + for (octave_idx_type i = 0; i < hist.length (); i++) + qt_hist.append (QString::fromStdString (hist[i])); + + emit set_history_signal (qt_hist); +} + +void +octave_qt_link::do_append_history (const std::string& hist_entry) +{ + emit append_history_signal (QString::fromStdString (hist_entry)); +} + +void +octave_qt_link::do_clear_history (void) +{ + emit clear_history_signal (); +} + +void +octave_qt_link::do_pre_input_event (void) +{ + do_update_workspace (); +} + +void +octave_qt_link::do_post_input_event (void) +{ +} + +void +octave_qt_link::do_enter_debugger_event (const std::string& file, int line) +{ + do_insert_debugger_pointer (file, line); +} + +void +octave_qt_link::do_exit_debugger_event (const std::string& file, int line) +{ + do_delete_debugger_pointer (file, line); +} + +void +octave_qt_link::do_update_breakpoint (bool insert, + const std::string& file, int line) +{ + emit update_dbstop_marker_signal (insert, QString::fromStdString (file), line); +} + +bool +octave_qt_link::do_edit_file (const std::string& file) +{ + emit edit_file_signal (QString::fromStdString (file)); + + return true; +} + +void +octave_qt_link::do_insert_debugger_pointer (const std::string& file, int line) +{ + emit insert_debugger_pointer_signal (QString::fromStdString (file), line); +} + +void +octave_qt_link::do_delete_debugger_pointer (const std::string& file, int line) +{ + emit delete_debugger_pointer_signal (QString::fromStdString (file), line); +} diff -r aa81cfa5c359 -r 22c0e0df1dbc libgui/src/octave-qt-link.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/octave-qt-link.h Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,102 @@ +/* + +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 +. + +*/ + +#ifndef OCTAVE_QT_LINK_H +#define OCTAVE_QT_LINK_H + +#include + +#include +#include + +#include "octave-link.h" +#include "octave-main-thread.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 QObject, public octave_link +{ + Q_OBJECT + +public: + + octave_qt_link (void); + + ~octave_qt_link (void) { } + + void execute_interpreter (void); + + void do_update_workspace (void); + + void do_set_history (const string_vector& hist); + void do_append_history (const std::string& hist_entry); + void do_clear_history (void); + + void do_pre_input_event (void); + void do_post_input_event (void); + + void do_enter_debugger_event (const std::string& file, int line); + void do_exit_debugger_event (const std::string& file, int line); + + void do_update_breakpoint (bool insert, const std::string& file, int line); + + bool do_edit_file (const std::string& file); + +private: + + // No copying! + + octave_qt_link (const octave_qt_link&); + + octave_qt_link& operator = (const octave_qt_link&); + + void do_insert_debugger_pointer (const std::string& file, int line); + + void do_delete_debugger_pointer (const std::string& file, int line); + + // Thread running octave_main. + octave_main_thread *main_thread; + +signals: + + void set_history_signal (const QStringList& hist); + void append_history_signal (const QString& hist_entry); + void clear_history_signal (void); + + void update_dbstop_marker_signal (bool insert, const QString& file, int line); + + void edit_file_signal (const QString& file); + + void insert_debugger_pointer_signal (const QString&, int); + + void delete_debugger_pointer_signal (const QString&, int); +}; + +#endif diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/corefcn/__execute_edit_hook__.cc --- a/libinterp/corefcn/__execute_edit_hook__.cc Thu Apr 04 20:18:54 2013 +0100 +++ /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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#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) -*/ diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/corefcn/module.mk Thu Apr 04 15:45:58 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 \ diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interp-core/ls-mat5.cc --- a/libinterp/interp-core/ls-mat5.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interp-core/ls-mat5.cc Thu Apr 04 15:45:58 2013 -0400 @@ -82,6 +82,7 @@ #endif #define PAD(l) (((l) > 0 && (l) <= 4) ? 4 : (((l)+7)/8)*8) +#define INT8(l) ((l) == miINT8 || (l) == miUINT8 || (l) == miUTF8) // The subsystem data block @@ -674,7 +675,7 @@ dims(1) = 1; } - if (read_mat5_tag (is, swap, type, len) || type != miINT8) + if (read_mat5_tag (is, swap, type, len) || !INT8(type)) { error ("load: invalid array name subelement"); goto early_read_error; @@ -1059,7 +1060,7 @@ { int32_t fn_type; int32_t fn_len; - if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8) + if (read_mat5_tag (is, swap, fn_type, fn_len) || !INT8(fn_type)) { error ("load: invalid field name subelement"); goto data_read_error; @@ -1120,7 +1121,7 @@ { isclass = true; - if (read_mat5_tag (is, swap, type, len) || type != miINT8) + if (read_mat5_tag (is, swap, type, len) || !INT8(type)) { error ("load: invalid class name"); goto skip_ahead; @@ -1170,7 +1171,7 @@ // field name subelement. The length of this subelement tells // us how many fields there are. - if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8) + if (read_mat5_tag (is, swap, fn_type, fn_len) || !INT8(fn_type)) { error ("load: invalid field name subelement"); goto data_read_error; diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interp-core/module.mk --- a/libinterp/interp-core/module.mk Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interp-core/module.mk Thu Apr 04 15:45:58 2013 -0400 @@ -35,6 +35,7 @@ interp-core/mex.h \ interp-core/mexproto.h \ interp-core/mxarray.in.h \ + interp-core/octave-event-listener.h \ interp-core/oct-errno.h \ interp-core/oct-fstrm.h \ interp-core/oct-hdf5.h \ diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interp-core/octave-event-listener.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/interp-core/octave-event-listener.h Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,46 @@ +/* + +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 +. + +*/ + +#ifndef OCTAVEEVENTLISTENER_H +#define OCTAVEEVENTLISTENER_H + +#include + +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 about_to_exit () = 0; + + virtual void entered_debug_mode () = 0; + virtual void quit_debug_mode () = 0; +}; + +#endif // OCTAVEEVENTLISTENER_H diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/debug.cc --- a/libinterp/interpfcn/debug.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interpfcn/debug.cc Thu Apr 04 15:45:58 2013 -0400 @@ -37,9 +37,9 @@ #include "defun.h" #include "error.h" #include "help.h" -#include "hook-fcn.h" #include "input.h" #include "pager.h" +#include "octave-link.h" #include "oct-obj.h" #include "utils.h" #include "parse.h" @@ -186,17 +186,6 @@ return dbg_fcn; } -octave_value -location_info (const std::string& fname, int line) -{ - octave_scalar_map location_info_map; - - location_info_map.setfield ("file", fname); - location_info_map.setfield ("line", line); - - return octave_value (location_info_map); -} - static void parse_dbfunction_params (const char *who, const octave_value_list& args, std::string& symbol_name, bp_table::intmap& lines) @@ -285,201 +274,6 @@ return retval; } -static hook_function_list dbstop_hook_functions; -static hook_function_list dbclear_hook_functions; - -DEFUN (add_dbstop_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{id} =} add_dbstop_hook (@var{fcn})\n\ -@deftypefnx {Built-in Function} {@var{id} =} add_dbstop_hook (@var{fcn}, @var{data})\n\ -Add the named function or function handle @var{fcn} to the list of\n\ -functions to call when a debugger breakpoint is set. The function\n\ -should have the form\n\ -\n\ -@example\n\ -@var{fcn} (@var{location}, @var{data})\n\ -@end example\n\ -\n\ -in which @var{location} is a structure containing the following elements:\n\ -\n\ -@table @code\n\ -@item file\n\ -The name of the file where the breakpoint is located.\n\ -@item line\n\ -The line number corresponding to the breakpoint.\n\ -@end table\n\ -\n\ -If @var{data} is omitted when the hook function is added, the hook\n\ -function is called with a single 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_dbstop_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) - { - dbstop_hook_functions.insert (hook_fcn.id (), hook_fcn); - - retval = hook_fcn.id (); - } - else - error ("add_dbstop_hook: expecting string as first arg"); - } - else - print_usage (); - - return retval; -} - -DEFUN (remove_dbstop_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} remove_dbstop_hook (@var{name})\n\ -@deftypefnx {Built-in Function} {} remove_dbstop_hook (@var{fcn_id})\n\ -Remove the named function or function handle with the given identifier\n\ -from the list of functions to call when a debugger breakpoint is set.\n\ -@seealso{add_dbstop_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 - = dbstop_hook_functions.find (hook_fcn_id); - - if (p != dbstop_hook_functions.end ()) - dbstop_hook_functions.erase (p); - else if (warn) - warning ("remove_dbstop_hook: %s not found in list", - hook_fcn_id.c_str ()); - } - else - error ("remove_dbstop_hook: argument not valid as a hook function name or id"); - } - else - print_usage (); - - return retval; -} - -DEFUN (add_dbclear_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{id} =} add_dbclear_hook (@var{fcn})\n\ -@deftypefnx {Built-in Function} {@var{id} =} add_dbclear_hook (@var{fcn}, @var{data})\n\ -Add the named function or function handle @var{fcn} to the list of\n\ -functions to call when a debugger breakpoint is cleared. The function\n\ -should have the form\n\ -\n\ -@example\n\ -@var{fcn} (@var{location}, @var{data})\n\ -@end example\n\ -\n\ -in which @var{location} is a structure containing the following elements:\n\ -\n\ -@table @code\n\ -@item file\n\ -The name of the file where the breakpoint is located.\n\ -@item line\n\ -The line number corresponding to the breakpoint.\n\ -@end table\n\ -\n\ -If @var{data} is omitted when the hook function is added, the hook\n\ -function is called with a single 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_dbclear_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) - { - dbclear_hook_functions.insert (hook_fcn.id (), hook_fcn); - - retval = hook_fcn.id (); - } - else - error ("add_dbclear_hook: expecting string as first arg"); - } - else - print_usage (); - - return retval; -} - -DEFUN (remove_dbclear_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} remove_dbclear_hook (@var{name})\n\ -@deftypefnx {Built-in Function} {} remove_dbclear_hook (@var{fcn_id})\n\ -Remove the named function or function handle with the given identifier\n\ -from the list of functions to call when a debugger breakpoint is cleared.\n\ -@seealso{add_dbclear_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 - = dbclear_hook_functions.find (hook_fcn_id); - - if (p != dbclear_hook_functions.end ()) - dbclear_hook_functions.erase (p); - else if (warn) - warning ("remove_dbclear_hook: %s not found in list", - hook_fcn_id.c_str ()); - } - else - error ("remove_dbclear_hook: argument not valid as a hook function name or id"); - } - else - print_usage (); - - return retval; -} - bp_table::intmap bp_table::do_add_breakpoint (const std::string& fname, const bp_table::intmap& line) @@ -513,8 +307,7 @@ std::string file = dbg_fcn->fcn_file_name (); if (! file.empty ()) - dbstop_hook_functions.run - (location_info (file, retval[i])); + octave_link::update_breakpoint (true, file, retval[i]); } } } @@ -569,8 +362,7 @@ cmds->delete_breakpoint (lineno); if (! file.empty ()) - dbclear_hook_functions.run - (location_info (file, lineno)); + octave_link::update_breakpoint (false, file, lineno); } } @@ -619,7 +411,7 @@ retval[i] = lineno; if (! file.empty ()) - dbclear_hook_functions.run (location_info (file, lineno)); + octave_link::update_breakpoint (false, file, lineno); } bp_set_iterator it = bp_set.find (fname); diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/debug.h --- a/libinterp/interpfcn/debug.h Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interpfcn/debug.h Thu Apr 04 15:45:58 2013 -0400 @@ -131,6 +131,4 @@ extern std::string get_file_line (const std::string& fname, size_t line); -extern octave_value location_info (const std::string& fname, int line); - #endif diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/input.cc --- a/libinterp/interpfcn/input.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interpfcn/input.cc Thu Apr 04 15:45:58 2013 -0400 @@ -53,6 +53,7 @@ #include "input.h" #include "lex.h" #include "load-path.h" +#include "octave-link.h" #include "oct-map.h" #include "oct-hist.h" #include "toplev.h" @@ -122,11 +123,7 @@ // The filemarker used to separate filenames from subfunction names char Vfilemarker = '>'; -static hook_function_list pre_input_event_hook_functions; static hook_function_list input_event_hook_functions; -static hook_function_list post_input_event_hook_functions; -static hook_function_list enter_debugger_event_hook_functions; -static hook_function_list exit_debugger_event_hook_functions; // For octave_quit. void @@ -215,7 +212,7 @@ // printing the prompt. if (interactive || forced_interactive) - pre_input_event_hook_functions.run (); + octave_link::pre_input_event (); bool history_skip_auto_repeated_debugging_command = false; @@ -255,7 +252,12 @@ if (retval != "\n") { if (! history_skip_auto_repeated_debugging_command) - command_history::add (retval); + { + command_history::add (retval); + + if (! command_history::ignoring_entries ()) + octave_link::append_history (retval); + } octave_diary << retval; @@ -271,7 +273,7 @@ // list has been updated. if (interactive || forced_interactive) - post_input_event_hook_functions.run (); + octave_link::post_input_event (); return retval; } @@ -458,9 +460,9 @@ } static void -exit_debugger_cleanup (const octave_value& loc_info) +exit_debugger_handler (const std::pair& arg) { - exit_debugger_event_hook_functions.run (loc_info); + octave_link::exit_debugger_event (arg.first, arg.second); } static void @@ -510,11 +512,10 @@ if (have_file) { - octave_value loc_info = location_info (nm, curr_debug_line); + octave_link::enter_debugger_event (nm, curr_debug_line); - enter_debugger_event_hook_functions.run (loc_info); - - frame.add_fcn (exit_debugger_cleanup, loc_info); + frame.add_fcn (exit_debugger_handler, + std::pair (nm, curr_debug_line)); std::string line_buf = get_file_line (nm, curr_debug_line); @@ -1091,94 +1092,6 @@ return retval; } -DEFUN (add_pre_input_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{id} =} add_pre_input_event_hook (@var{fcn})\n\ -@deftypefnx {Built-in Function} {@var{id} =} add_pre_input_event_hook (@var{fcn}, @var{data})\n\ -Add the named function or function handle @var{fcn} to the list of functions to call\n\ -immediately prior to prompting for interactive user input. The\n\ -function should have the form\n\ -\n\ -@example\n\ -@var{fcn} (@var{data})\n\ -@end example\n\ -\n\ -If @var{data} is omitted, Octave calls the function without any\n\ -arguments.\n\ -\n\ -The returned identifier may be used to remove the function handle from\n\ -the list of input hook functions.\n\ -@seealso{remove_pre_input_event_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) - { - pre_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn); - - retval = hook_fcn.id (); - } - else - error ("add_pre_input_event_hook: expecting string as first arg"); - } - else - print_usage (); - - return retval; -} - -DEFUN (remove_pre_input_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} remove_pre_input_event_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 immediately prior to prompting for\n\ -interactive user input.\n\ -@seealso{add_pre_input_event_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 - = pre_input_event_hook_functions.find (hook_fcn_id); - - if (p != pre_input_event_hook_functions.end ()) - pre_input_event_hook_functions.erase (p); - else if (warn) - warning ("remove_pre_input_event_hook: %s not found in list", - hook_fcn_id.c_str ()); - } - else - error ("remove_pre_input_event_hook: argument not valid as a hook function name or id"); - } - else - print_usage (); - - return retval; -} - static int internal_input_event_hook_fcn (void) { @@ -1284,288 +1197,6 @@ return retval; } -DEFUN (add_post_input_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{id} =} add_post_input_event_hook (@var{fcn})\n\ -@deftypefnx {Built-in Function} {@var{id} =} add_post_input_event_hook (@var{fcn}, @var{data})\n\ -Add the named function or function handle @var{fcn} to the list of functions to call\n\ -immediately after accepting interactive user input. The function\n\ -should have the form\n\ -\n\ -@example\n\ -@var{fcn} (@var{data})\n\ -@end example\n\ -\n\ -If @var{data} is omitted, Octave calls the function without any\n\ -arguments.\n\ -\n\ -The returned identifier may be used to remove the function handle from\n\ -the list of input hook functions.\n\ -@seealso{remove_post_input_event_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) - { - post_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn); - - retval = hook_fcn.id (); - } - else - error ("add_post_input_event_hook: expecting string as first arg"); - } - else - print_usage (); - - return retval; -} - -DEFUN (remove_post_input_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} remove_post_input_event_hook (@var{name})\n\ -@deftypefnx {Built-in Function} {} remove_post_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 immediately after accepting\n\ -interactive user input.\n\ -@seealso{add_post_input_event_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 - = post_input_event_hook_functions.find (hook_fcn_id); - - if (p != post_input_event_hook_functions.end ()) - post_input_event_hook_functions.erase (p); - else if (warn) - warning ("remove_post_input_event_hook: %s not found in list", - hook_fcn_id.c_str ()); - } - else - error ("remove_post_input_event_hook: argument not valid as a hook function name or id"); - } - else - print_usage (); - - return retval; -} - -DEFUN (add_enter_debugger_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{id} =} add_enter_debugger_event_hook (@var{fcn})\n\ -@deftypefnx {Built-in Function} {@var{id} =} add_enter_debugger_event_hook (@var{fcn}, @var{data})\n\ -Add the named function or function handle @var{fcn} to the list of\n\ -functions to call when a debugger breakpoint is reached. The function\n\ -should have the form\n\ -\n\ -@example\n\ -@var{fcn} (@var{location}, @var{data})\n\ -@end example\n\ -\n\ -in which @var{location} is a structure containing the following elements:\n\ -\n\ -@table @code\n\ -@item file\n\ -The name of the file where the breakpoint is located.\n\ -@item line\n\ -The line number corresponding to the breakpoint.\n\ -@end table\n\ -\n\ -If @var{data} is omitted when the hook function is added, the hook\n\ -function is called with a single 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_enter_debugger_event_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) - { - enter_debugger_event_hook_functions.insert (hook_fcn.id (), hook_fcn); - - retval = hook_fcn.id (); - } - else - error ("add_enter_debugger_event_hook: expecting string as first arg"); - } - else - print_usage (); - - return retval; -} - -DEFUN (remove_enter_debugger_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} remove_enter_debugger_event_hook (@var{name})\n\ -@deftypefnx {Built-in Function} {} remove_enter_debugger_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 immediately after accepting\n\ -interactive user input.\n\ -@seealso{add_enter_debugger_event_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 - = enter_debugger_event_hook_functions.find (hook_fcn_id); - - if (p != enter_debugger_event_hook_functions.end ()) - enter_debugger_event_hook_functions.erase (p); - else if (warn) - warning ("remove_enter_debugger_event_hook: %s not found in list", - hook_fcn_id.c_str ()); - } - else - error ("remove_enter_debugger_event_hook: argument not valid as a hook function name or id"); - } - else - print_usage (); - - return retval; -} - -DEFUN (add_exit_debugger_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{id} =} add_exit_debugger_event_hook (@var{fcn})\n\ -@deftypefnx {Built-in Function} {@var{id} =} add_exit_debugger_event_hook (@var{fcn}, @var{data})\n\ -Add the named function or function handle @var{fcn} to the list of\n\ -functions to call when continuing execution after a debugger breakpoint.\n\ -The function should have the form\n\ -\n\ -@example\n\ -@var{fcn} (@var{location}, @var{data})\n\ -@end example\n\ -\n\ -in which @var{location} is a structure containing the following elements:\n\ -\n\ -@table @code\n\ -@item file\n\ -The name of the file where the breakpoint is located.\n\ -@item line\n\ -The line number corresponding to the breakpoint.\n\ -@end table\n\ -\n\ -If @var{data} is omitted when the hook function is added, the hook\n\ -function is called with a single 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_exit_debugger_event_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) - { - exit_debugger_event_hook_functions.insert (hook_fcn.id (), hook_fcn); - - retval = hook_fcn.id (); - } - else - error ("add_exit_debugger_event_hook: expecting string as first arg"); - } - else - print_usage (); - - return retval; -} - -DEFUN (remove_exit_debugger_event_hook, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} remove_exit_debugger_event_hook (@var{name})\n\ -@deftypefnx {Built-in Function} {} remove_exit_debugger_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 immediately after accepting\n\ -interactive user input.\n\ -@seealso{add_exit_debugger_event_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 - = exit_debugger_event_hook_functions.find (hook_fcn_id); - - if (p != exit_debugger_event_hook_functions.end ()) - exit_debugger_event_hook_functions.erase (p); - else if (warn) - warning ("remove_exit_debugger_event_hook: %s not found in list", - hook_fcn_id.c_str ()); - } - else - error ("remove_exit_debugger_event_hook: argument not valid as a hook function name or id"); - } - else - print_usage (); - - return retval; -} - DEFUN (PS1, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} PS1 ()\n\ diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/module.mk --- a/libinterp/interpfcn/module.mk Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interpfcn/module.mk Thu Apr 04 15:45:58 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 \ diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/oct-hist.cc --- a/libinterp/interpfcn/oct-hist.cc Thu Apr 04 20:18:54 2013 +0100 +++ b/libinterp/interpfcn/oct-hist.cc Thu Apr 04 15:45:58 2013 -0400 @@ -48,6 +48,7 @@ #include "cmd-hist.h" #include "file-ops.h" #include "lo-mappers.h" +#include "octave-link.h" #include "oct-env.h" #include "oct-time.h" #include "str-vec.h" @@ -186,18 +187,29 @@ command_history::write (); else if (option == "-r") - // Read entire file. - command_history::read (); + { + // Read entire file. + command_history::read (); + octave_link::set_history (command_history::list ()); + } else if (option == "-n") - // Read 'new' history from file. - command_history::read_range (); + { + // Read 'new' history from file. + command_history::read_range (); + octave_link::set_history (command_history::list ()); + } else panic_impossible (); return hlist; } + else if (option == "-c") + { + command_history::clear (); + octave_link::clear_history (); + } else if (option == "-q") numbered_output = false; else if (option == "--") @@ -354,7 +366,10 @@ tmp.resize (len - 1); if (! tmp.empty ()) - command_history::add (tmp); + { + command_history::add (tmp); + octave_link::append_history (tmp); + } } } @@ -601,6 +616,8 @@ default_history_file (), default_history_size (), octave_env::getenv ("OCTAVE_HISTCONTROL")); + + octave_link::set_history (command_history::list ()); } void @@ -611,7 +628,10 @@ std::string timestamp = now.strftime (Vhistory_timestamp_format_string); if (! timestamp.empty ()) - command_history::add (timestamp); + { + command_history::add (timestamp); + octave_link::append_history (timestamp); + } } DEFUN (edit_history, args, , @@ -671,6 +691,9 @@ @itemx -@var{n}\n\ Display only the most recent @var{n} lines of history.\n\ \n\ +@item -c\n\ +Clear the history list.\n\ +\n\ @item -q\n\ Don't number the displayed lines of history. This is useful for cutting\n\ and pasting commands using the X Window System.\n\ diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/octave-link.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/interpfcn/octave-link.cc Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,167 @@ +/* + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#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 an object of a class that is derived from the base +// class octave_link, or 0 to disconnect the link. It is the +// responsibility of the caller to delete obj. + +void +octave_link::connect_link (octave_link* obj) +{ + if (obj && instance) + ::error ("octave_link is already linked!"); + else + instance = obj; +} + +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; +} diff -r aa81cfa5c359 -r 22c0e0df1dbc libinterp/interpfcn/octave-link.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/interpfcn/octave-link.h Thu Apr 04 15:45:58 2013 -0400 @@ -0,0 +1,257 @@ +/* + +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 +. + +*/ + +#if !defined (octave_link_h) +#define octave_link_h 1 + +#include + +#include "event-queue.h" +#include "octave-event-listener.h" + +class octave_mutex; +class string_vector; + +// \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 + static void post_event (T *obj, void (T::*method) (void)) + { + if (instance_ok ()) + instance->do_post_event (obj, method); + } + + template + static void post_event (T *obj, void (T::*method) (A), A arg) + { + if (instance_ok ()) + instance->do_post_event (obj, method, arg); + } + + template + 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 set_history (const string_vector& hist) + { + if (instance_ok ()) + instance->do_set_history (hist); + } + + static void append_history (const std::string& hist_entry) + { + if (instance_ok ()) + instance->do_append_history (hist_entry); + } + + static void clear_history (void) + { + if (instance_ok ()) + instance->do_clear_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_link (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 + void do_post_event (T *obj, void (T::*method) (void)) + { + gui_event_queue.add_method (obj, method); + } + + template + void do_post_event (T *obj, void (T::*method) (A), A arg) + { + gui_event_queue.add_method (obj, method, arg); + } + + template + 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_set_history (const string_vector& hist) = 0; + virtual void do_append_history (const std::string& hist_entry) = 0; + virtual void do_clear_history (void) = 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 diff -r aa81cfa5c359 -r 22c0e0df1dbc scripts/miscellaneous/edit.m --- a/scripts/miscellaneous/edit.m Thu Apr 04 20:18:54 2013 +0100 +++ b/scripts/miscellaneous/edit.m Thu Apr 04 15:45:58 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), diff -r aa81cfa5c359 -r 22c0e0df1dbc scripts/signal/fftfilt.m --- a/scripts/signal/fftfilt.m Thu Apr 04 20:18:54 2013 +0100 +++ b/scripts/signal/fftfilt.m Thu Apr 04 15:45:58 2013 -0400 @@ -94,53 +94,99 @@ endif y = y(1:r_x, :); - if (transpose) - y = y.'; + + ## Final cleanups: + + ## - If both b and x are real, y should be real. + ## - If b is real and x is imaginary, y should be imaginary. + ## - If b is imaginary and x is real, y should be imaginary. + ## - If both b and x are imaginary, y should be real. + xisreal = zeros (1,size(x,2)); + xisimag = xisreal; + for cx = 1:size(x,2) + if (all (imag (x(:,cx)) == 0)) + xisreal (cx) = 1; + elseif (all (real (x (:,cx)) == 0)) + xisimag (cx) = 1; + endif + endfor + xisreal = find(xisreal); + xisimag = find(xisimag); + if (all (imag (b) == 0)) + y (:,xisreal) = real (y (:,xisreal)); + y (:,xisimag) = complex (real (y (:,xisimag)) * 0, imag (y (:,xisimag))); + elseif (all (real (b) == 0)) + y (:,xisreal) = complex (real (y (:,xisreal)) * 0, imag (y (:,xisreal))); + y (:,xisimag) = real (y (:,xisimag)); endif - ## Final cleanups: If both x and b are real, y should be real. - ## If both x and b are integer, y should be integer. + ## - If both x and b are integer in both real and imaginary + ## components, y should be integer. + if (! any (b - fix (b))) + idx = find (! any (x - fix (x))); + y (:, idx) = round (y (:, idx)); + endif - if (isreal (b) && isreal (x)) - y = real (y); - endif - if (! any (b - fix (b))) - idx = !any (x - fix (x)); - y(:, idx) = round (y(:, idx)); + ## Transpose after cleanup, otherwise rounding fails. + if (transpose) + y = y.'; endif endfunction %!shared b, x, r + %!test %! b = [1 1]; %! x = [1, zeros(1,9)]; -%! assert (fftfilt (b, x ), [1 1 0 0 0 0 0 0 0 0] , eps); -%! assert (fftfilt (b, x.'), [1 1 0 0 0 0 0 0 0 0].', eps); -%! assert (fftfilt (b.',x ), [1 1 0 0 0 0 0 0 0 0] , eps); -%! assert (fftfilt (b.',x.'), [1 1 0 0 0 0 0 0 0 0].', eps); +%! assert (fftfilt (b, x ), [1 1 0 0 0 0 0 0 0 0] ); +%! assert (fftfilt (b, x.'), [1 1 0 0 0 0 0 0 0 0].'); +%! assert (fftfilt (b.',x ), [1 1 0 0 0 0 0 0 0 0] ); +%! assert (fftfilt (b.',x.'), [1 1 0 0 0 0 0 0 0 0].'); +%! assert (fftfilt (b, [x.' x.']), [1 1 0 0 0 0 0 0 0 0].'*[1 1]); +%! assert (fftfilt (b, [x.'+eps x.']) == [1 1 0 0 0 0 0 0 0 0].'*[1 1], [false(10, 1) true(10, 1)]); %!test %! r = sqrt (1/2) * (1+i); %! b = b*r; -%! assert (fftfilt (b, x ), r*[1 1 0 0 0 0 0 0 0 0] , eps); -%! assert (fftfilt (b, r*x), r*r*[1 1 0 0 0 0 0 0 0 0], eps); -%! assert (fftfilt (b, x.'), r*[1 1 0 0 0 0 0 0 0 0].', eps); +%! assert (fftfilt (b, x ), r*[1 1 0 0 0 0 0 0 0 0] , eps ); +%! assert (fftfilt (b, r*x), r*r*[1 1 0 0 0 0 0 0 0 0], 2*eps); +%! assert (fftfilt (b, x.'), r*[1 1 0 0 0 0 0 0 0 0].', eps ); %!test -%! b = [1 1]; -%! x = zeros (10,3); x(1,1)=-1; x(1,2)=1; +%! b = [1 1]; +%! x = zeros (10,3); x(1,1)=-1; x(1,2)=1; %! y0 = zeros (10,3); y0(1:2,1)=-1; y0(1:2,2)=1; -%! y = fftfilt (b, x); -%! assert (y,y0); +%! y = fftfilt (b, x); +%! assert (y0, y); +%! y = fftfilt (b*i, x); +%! assert (y0*i, y); +%! y = fftfilt (b, x*i); +%! assert (y0*i, y); +%! y = fftfilt (b*i, x*i); +%! assert (-y0, y); +%! x = rand (10, 1); +%! y = fftfilt (b, [x x*i]); +%! assert (true, isreal (y(:,1))); +%! assert (false, any (real (y(:,2)))); %!test %! b = rand (10, 1); %! x = rand (10, 1); %! y0 = filter (b, 1, x); -%! y = filter (b, 1, x); -%! assert (y, y0); +%! y = fftfilt (b, x); +%! assert (y0, y, 16*eps); +%! y0 = filter (b*i, 1, x*i); +%! y = fftfilt (b*i, x*i); +%! assert (y0, y, 16*eps); + +%!test +%! b = rand (10, 1) + i*rand (10, 1); +%! x = rand (10, 1) + i*rand (10, 1); +%! y0 = filter (b, 1, x); +%! y = fftfilt (b, x); +%! assert (y0, y, 55*eps); %% Test input validation %!error fftfilt (1) diff -r aa81cfa5c359 -r 22c0e0df1dbc scripts/sparse/svds.m --- a/scripts/sparse/svds.m Thu Apr 04 20:18:54 2013 +0100 +++ b/scripts/sparse/svds.m Thu Apr 04 15:45:58 2013 -0400 @@ -103,7 +103,7 @@ endif if (nargin < 4) - opts.tol = 1e-10 / root2; + opts.tol = 0; ## use ARPACK default opts.disp = 0; opts.maxit = 300; else @@ -111,7 +111,7 @@ error ("svds: OPTS must be a structure"); endif if (!isfield (opts, "tol")) - opts.tol = 1e-10 / root2; + opts.tol = 0; ## use ARPACK default else opts.tol = opts.tol / root2; endif @@ -152,7 +152,6 @@ b_opts = opts; ## Call to eigs is always a symmetric matrix by construction b_opts.issym = true; - b_opts.tol = opts.tol / max_a; b_sigma = sigma; if (!ischar (b_sigma)) b_sigma = b_sigma / max_a; @@ -235,14 +234,14 @@ endif if (nargout > 3) - flag = norm (A*v - u*s, 1) > root2 * opts.tol * norm (A, 1); + flag = (flag != 0); endif endif endfunction -%!shared n, k, A, u, s, v, opts, rand_state, randn_state +%!shared n, k, A, u, s, v, opts, rand_state, randn_state, tol %! n = 100; %! k = 7; %! A = sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[ones(1,n-2),0.4*n*ones(1,n),ones(1,n-2)]); @@ -263,13 +262,15 @@ %! [u2,s2,v2,flag] = svds (A,k); %! s2 = diag (s2); %! assert (flag, !1); -%! assert (s2, s(end:-1:end-k+1), 1e-10); +%! tol = 10 * eps() * norm(s2, 1); +%! assert (s2, s(end:-1:end-k+1), tol); %! %!testif HAVE_ARPACK, HAVE_UMFPACK %! [u2,s2,v2,flag] = svds (A,k,0,opts); %! s2 = diag (s2); %! assert (flag, !1); -%! assert (s2, s(k:-1:1), 1e-10); +%! tol = 10 * eps() * norm(s2, 1); +%! assert (s2, s(k:-1:1), tol); %! %!testif HAVE_ARPACK, HAVE_UMFPACK %! idx = floor (n/2); @@ -278,7 +279,8 @@ %! [u2,s2,v2,flag] = svds (A,k,sigma,opts); %! s2 = diag (s2); %! assert (flag, !1); -%! assert (s2, s((idx+floor(k/2)):-1:(idx-floor(k/2))), 1e-10); +%! tol = 10 * eps() * norm(s2, 1); +%! assert (s2, s((idx+floor(k/2)):-1:(idx-floor(k/2))), tol); %! %!testif HAVE_ARPACK %! [u2,s2,v2,flag] = svds (zeros (10), k);