octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Updated patch for multiple users of readline event hook


From: John Swensen
Subject: Updated patch for multiple users of readline event hook
Date: Mon, 17 Sep 2007 15:51:55 -0400
User-agent: Thunderbird 2.0.0.6 (Macintosh/20070728)

A while back I posted a patch to allow multiple programs to register for the readline event hook. This was due to the fact that it appears multiple people (JHandles, my UI, others?) use it to determine when the octave interpreter is idle. I never received a lot of feedback, but one criticism was for not using C++ and std::vector. I fixed that and here are the patches.

Because the oct-rl-edit.c and oct-rl-hist.c were being compiled as C file, rather than C++ files, I have attached 2 patches. One is for existing files and the other contains the new C++ versions of those two files. I'm not exactly sure how one normally handles the deletion of a file and the addition of a replacement file using CVS, so let me know if you want it in a different format.

John Swensen
Index: liboctave/Makefile.in
===================================================================
RCS file: /cvs/octave/liboctave/Makefile.in,v
retrieving revision 1.229
diff -u -r1.229 Makefile.in
--- liboctave/Makefile.in       27 Mar 2007 16:05:15 -0000      1.229
+++ liboctave/Makefile.in       17 Sep 2007 19:39:13 -0000
@@ -139,9 +139,9 @@
 
 LIBOCTAVE_SOURCES := $(LIBOCTAVE_CXX_SOURCES) $(LIBOCTAVE_C_SOURCES)
 
-LIBOCT_READLINE_CXX_SOURCES := cmd-edit.cc cmd-hist.cc
+LIBOCT_READLINE_CXX_SOURCES := oct-rl-edit.cc oct-rl-hist.cc cmd-edit.cc 
cmd-hist.cc 
 
-LIBOCT_READLINE_C_SOURCES := oct-rl-edit.c oct-rl-hist.c
+LIBOCT_READLINE_C_SOURCES :=
 
 LIBOCT_READLINE_SOURCES := $(LIBOCT_READLINE_CXX_SOURCES) 
$(LIBOCT_READLINE_C_SOURCES)
 
Index: liboctave/cmd-edit.cc
===================================================================
RCS file: /cvs/octave/liboctave/cmd-edit.cc,v
retrieving revision 1.31
diff -u -r1.31 cmd-edit.cc
--- liboctave/cmd-edit.cc       30 Jun 2006 18:19:42 -0000      1.31
+++ liboctave/cmd-edit.cc       17 Sep 2007 19:39:27 -0000
@@ -409,15 +409,14 @@
 void
 gnu_readline::do_set_event_hook (event_hook_fcn f)
 {
-  previous_event_hook = octave_rl_get_event_hook ();
-
-  ::octave_rl_set_event_hook (f);
+  previous_event_hook = f;
+  ::octave_rl_add_event_hook (f);
 }
 
 void
 gnu_readline::do_restore_event_hook (void)
 {
-  ::octave_rl_set_event_hook (previous_event_hook);
+  ::octave_rl_remove_event_hook( previous_event_hook );
 }
 
 void
Index: liboctave/cmd-hist.h
===================================================================
RCS file: /cvs/octave/liboctave/cmd-hist.h,v
retrieving revision 1.13
diff -u -r1.13 cmd-hist.h
--- liboctave/cmd-hist.h        27 Oct 2006 01:45:55 -0000      1.13
+++ liboctave/cmd-hist.h        17 Sep 2007 19:39:43 -0000
@@ -28,6 +28,8 @@
 
 #include "str-vec.h"
 
+#include "oct-rl-hist.h"
+
 class
 OCTAVE_API
 command_history
Index: liboctave/oct-rl-edit.h
===================================================================
RCS file: /cvs/octave/liboctave/oct-rl-edit.h,v
retrieving revision 1.7
diff -u -r1.7 oct-rl-edit.h
--- liboctave/oct-rl-edit.h     26 Apr 2005 19:24:29 -0000      1.7
+++ liboctave/oct-rl-edit.h     17 Sep 2007 19:39:56 -0000
@@ -24,6 +24,8 @@
 #if !defined (octave_rl_edit_h)
 #define octave_rl_edit_h 1
 
+#include <vector>
+
 typedef int (*rl_startup_hook_fcn_ptr) (void);
 
 typedef int (*rl_event_hook_fcn_ptr) (void);
@@ -96,6 +98,14 @@
 
 extern rl_event_hook_fcn_ptr octave_rl_get_event_hook (void);
 
+extern int octave_rl_event_hook( void );
+
+extern void octave_rl_add_event_hook( rl_event_hook_fcn_ptr f );
+
+extern void octave_rl_remove_event_hook( rl_event_hook_fcn_ptr f );
+
+extern std::vector<rl_event_hook_fcn_ptr> octave_rl_get_event_hook_list(void);
+
 extern char **
 octave_rl_completion_matches (const char *, rl_completer_fcn_ptr);
 
Index: liboctave/oct-rl-hist.h
===================================================================
RCS file: /cvs/octave/liboctave/oct-rl-hist.h,v
retrieving revision 1.2
diff -u -r1.2 oct-rl-hist.h
--- liboctave/oct-rl-hist.h     26 Apr 2005 19:24:29 -0000      1.2
+++ liboctave/oct-rl-hist.h     17 Sep 2007 19:40:10 -0000
@@ -24,11 +24,6 @@
 #if !defined (octave_rl_hist_h)
 #define octave_rl_hist_h 1
 
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
 extern void octave_add_history (const char *);
 
 extern int octave_where_history (void);
@@ -69,10 +64,6 @@
 
 extern void octave_replace_history_entry (int, const char *);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
 
 /*
Index: src/toplev.cc
===================================================================
RCS file: /cvs/octave/src/toplev.cc,v
retrieving revision 1.200
diff -u -r1.200 toplev.cc
--- src/toplev.cc       31 May 2007 20:23:45 -0000      1.200
+++ src/toplev.cc       17 Sep 2007 19:48:53 -0000
@@ -65,6 +65,7 @@
 #include "parse.h"
 #include "pathsearch.h"
 #include "procstream.h"
+#include "oct-rl-edit.h"
 #include "ov.h"
 #include "pt-jump.h"
 #include "pt-stmt.h"
@@ -203,6 +204,7 @@
   octave_initialized = true;
 
   // The big loop.
+  octave_rl_set_event_hook( &octave_rl_event_hook );
 
   int retval = 0;
   do
--- /dev/null   2007-09-17 15:47:52.000000000 -0400
+++ liboctave/oct-rl-hist.cc    2007-08-31 09:02:24.000000000 -0400
@@ -0,0 +1,249 @@
+/*
+
+Copyright (C) 2000 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 2, 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, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (USE_READLINE)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <readline/history.h>
+
+void
+octave_add_history (const char *line)
+{
+  add_history (line);
+}
+
+int
+octave_where_history (void)
+{
+  return where_history ();
+}
+
+int
+octave_history_length (void)
+{
+  return history_length;
+}
+
+int
+octave_max_input_history (void)
+{
+  return max_input_history;
+}
+
+int
+octave_history_base (void)
+{
+  return history_base;
+}
+
+void
+octave_stifle_history (int n)
+{
+  stifle_history (n);
+}
+
+int
+octave_unstifle_history (void)
+{
+  return unstifle_history ();
+}
+
+int
+octave_history_is_stifled (void)
+{
+  return history_is_stifled ();
+}
+
+int
+octave_history_set_pos (int n)
+{
+  return history_set_pos (n);
+}
+
+int
+octave_read_history (const char *f)
+{
+  return read_history (f);
+}
+
+void
+octave_using_history (void)
+{
+  using_history ();
+}
+
+int
+octave_read_history_range (const char *f, int b, int e)
+{
+  return read_history_range (f, b, e);
+}
+
+int
+octave_write_history (const char *f)
+{
+  return write_history (f);
+}
+
+int
+octave_append_history (int n, const char *f)
+{
+  return append_history (n, f);
+}
+
+int
+octave_history_truncate_file (const char *f, int n)
+{
+  return history_truncate_file (f, n);
+}
+
+void
+octave_remove_history (int n)
+{
+  HIST_ENTRY *discard = remove_history (n);
+
+  if (discard)
+    {
+      if (discard->line)
+       free (discard->line);
+
+      free (discard);
+    }
+}
+
+char *
+octave_history_goto_mark (int n)
+{
+  HIST_ENTRY *h;
+
+  char *retval = 0;
+
+  if (history_set_pos (n))
+    {
+      h = current_history ();
+
+      if (h)
+       retval = h->line;
+    }
+
+  return retval;
+}
+
+char *
+octave_history_get (int n)
+{
+  char *retval = 0;
+
+  HIST_ENTRY *h = history_get (n);
+
+  if (h)
+    retval = h->line;
+
+  return retval;
+}
+
+char **
+octave_history_list (int limit, int number_lines)
+{
+  static char **retval = 0;
+
+  HIST_ENTRY **hlist = 0;
+
+  if (retval)
+    {
+      char **p = retval;
+
+      while (*p)
+       free (*p++);
+
+      free (retval);
+
+      retval = 0;
+    }
+
+  hlist = history_list ();
+
+  if (hlist)
+    {
+      int i, k;
+
+      int beg = 0;
+      int end = 0;
+      while (hlist[end])
+       end++;
+
+      beg = (limit < 0 || end < limit) ? 0 : (end - limit);
+
+      retval = static_cast<char**>(malloc ((end - beg + 1) * sizeof (char 
**)));
+
+      k = 0;
+      for (i = beg; i < end; i++)
+       {
+         char *line = hlist[i]->line;
+         int len = line ? strlen (line) : 0;
+         char *tmp = static_cast<char*>(malloc (len + 64));
+
+         if (number_lines)
+           sprintf (tmp, "%5d%c%s", i + history_base,
+                    hlist[i]->data ? '*' : ' ',
+                    line ? line : "");
+         else
+           sprintf (tmp, "%c%s", hlist[i]->data ? '*' : ' ',
+                    line ? line : "");
+
+         retval[k++] = tmp;
+       }
+
+      retval[k] = 0;
+    }
+
+  return retval;
+}
+
+void
+octave_replace_history_entry (int which, const char *line)
+{
+  HIST_ENTRY *discard = replace_history_entry (which, line, 0);
+
+  if (discard)
+    {
+      if (discard->line)
+       free (discard->line);
+
+      free (discard);
+    }
+}
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- /dev/null   2007-09-17 15:47:52.000000000 -0400
+++ liboctave/oct-rl-edit.cc    2007-09-17 15:21:08.000000000 -0400
@@ -0,0 +1,397 @@
+/*
+
+Copyright (C) 2000 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 2, 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, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (USE_READLINE)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <readline/readline.h>
+
+#include "oct-rl-edit.h"
+#include "pthread.h"
+
+#include <vector>
+#include <algorithm>
+
+
+/**
+ * A list of registered readline event hooks.
+ */
+std::vector<rl_event_hook_fcn_ptr> rl_event_hook_list;
+
+/**
+ * Mutex for providing threadsafe access to the list of readline
+ * event hooks.
+ */
+pthread_mutex_t event_hook_list_mutex;
+
+#define OCTAVE_RL_SAVE_STRING(ss, s) \
+  static char *ss = 0; \
+ \
+  if (ss) \
+    { \
+      free (ss); \
+      ss = 0; \
+    } \
+ \
+  ss = (char*)malloc (strlen (s) + 1);         \
+ \
+  strcpy ( ss, s)
+
+int
+octave_rl_screen_height (void)
+{
+  int rows, cols;
+  rl_get_screen_size (&rows, &cols);
+  return rows;
+}
+
+int
+octave_rl_screen_width (void)
+{
+  int rows, cols;
+  rl_get_screen_size (&rows, &cols);
+  return cols;
+}
+
+void
+octave_rl_enable_paren_matching (int val)
+{
+  rl_variable_bind ("blink-matching-paren", val ? "1" : "0");
+}
+
+/* It would be much simpler if we could just call _rl_clear_screen to
+   only clear the screen, but it is not a public function, and on some
+   systems, it is not exported from shared library versions of
+   readline, so we can't use it.
+
+   Instead, temporarily redefine the redisplay function to do nothing.
+
+   FIXME -- It would be safer to do this when protected from
+   interrupts... */
+
+static void
+flush_stdout (void)
+{
+  fflush (stdout);
+}
+
+void
+octave_rl_clear_screen (void)
+{
+  int ignore1 = 0;
+  int ignore2 = 0;
+
+  rl_voidfunc_t *saved_redisplay_function = rl_redisplay_function;
+  rl_redisplay_function = flush_stdout;
+
+  rl_clear_screen (ignore1, ignore2);
+
+  rl_redisplay_function = saved_redisplay_function;
+}
+
+void
+octave_rl_resize_terminal (void)
+{
+  rl_resize_terminal ();
+}
+
+void
+octave_rl_restore_terminal_state ()
+{
+  if (rl_deprep_term_function)
+    rl_deprep_term_function ();
+}
+
+void
+octave_rl_insert_text (const char *s)
+{
+  rl_insert_text (s);
+}
+
+void
+octave_rl_newline (void)
+{
+  rl_newline (1, '\n');
+}
+
+void
+octave_rl_clear_undo_list (void)
+{
+  if (rl_undo_list)
+    {
+      rl_free_undo_list ();
+
+      rl_undo_list = 0;
+    }
+}
+
+void
+octave_rl_set_name (const char *n)
+{
+  OCTAVE_RL_SAVE_STRING (nm, n);
+
+  rl_readline_name = nm;
+
+  /* Since we've already called rl_initialize, we need to re-read the
+     init file to take advantage of the conditional parsing feature
+     based on rl_readline_name; */
+
+  rl_re_read_init_file (0, 0);
+}
+
+char *
+octave_rl_readline (const char *prompt)
+{
+  return readline (prompt);
+}
+
+void
+octave_rl_set_input_stream (FILE *f)
+{
+  rl_instream = f;
+}
+
+FILE *
+octave_rl_get_input_stream (void)
+{
+  return rl_instream;
+}
+
+void
+octave_rl_set_output_stream (FILE *f)
+{
+  rl_outstream = f;
+}
+
+FILE *
+octave_rl_get_output_stream (void)
+{
+  return rl_outstream;
+}
+
+void
+octave_rl_read_init_file (const char *f)
+{
+  if (f && *f)
+    rl_read_init_file (f);
+  else
+    rl_re_read_init_file (0, 0);
+}
+
+int
+octave_rl_filename_completion_desired (int arg)
+{
+  int retval = rl_filename_completion_desired;
+  rl_filename_completion_desired = arg;
+  return retval;
+}
+
+char *
+octave_rl_filename_completion_function (const char *text, int state)
+{
+  return rl_filename_completion_function (text, state);
+}
+
+void
+octave_rl_set_basic_word_break_characters (const char *s)
+{
+  OCTAVE_RL_SAVE_STRING (ss, s);
+
+  rl_basic_word_break_characters = ss;
+}
+
+void
+octave_rl_set_completer_word_break_characters (const char *s)
+{
+  OCTAVE_RL_SAVE_STRING (ss, s);
+
+  rl_completer_word_break_characters = ss;
+}
+
+void
+octave_rl_set_basic_quote_characters (const char *s)
+{
+  OCTAVE_RL_SAVE_STRING (ss, s);
+
+  rl_basic_quote_characters = ss;
+}
+
+void
+octave_rl_set_completion_append_character (char c)
+{
+  rl_completion_append_character = c;
+}
+
+void
+octave_rl_set_completion_function (rl_attempted_completion_fcn_ptr f)
+{
+  rl_attempted_completion_function = f;
+}
+
+void
+octave_rl_set_startup_hook (rl_startup_hook_fcn_ptr f)
+{
+  rl_startup_hook = f;
+}
+
+rl_startup_hook_fcn_ptr
+octave_rl_get_startup_hook (void)
+{
+  return rl_startup_hook;
+}
+
+void
+octave_rl_set_event_hook (rl_event_hook_fcn_ptr f)
+{ 
+  pthread_mutex_destroy(&event_hook_list_mutex);
+  pthread_mutex_init(&event_hook_list_mutex, NULL);
+  rl_event_hook = f;
+}
+
+rl_event_hook_fcn_ptr
+octave_rl_get_event_hook (void)
+{
+  return rl_event_hook;
+}
+
+int
+octave_rl_event_hook( void )
+{
+  pthread_mutex_lock( &event_hook_list_mutex );
+
+  // Iterate through the registered event hook functions in the order they were
+  // registered.
+  std::vector<rl_event_hook_fcn_ptr>::iterator it;
+  for( it = rl_event_hook_list.begin() ; it != rl_event_hook_list.end() ; it++ 
)
+  {
+    (*it)();
+  }
+
+  pthread_mutex_unlock( &event_hook_list_mutex );
+
+  return 0;
+}
+
+void
+octave_rl_add_event_hook (rl_event_hook_fcn_ptr f)
+{
+  pthread_mutex_lock( &event_hook_list_mutex );
+
+  rl_event_hook_list.push_back( f );
+
+  pthread_mutex_unlock( &event_hook_list_mutex );
+}
+
+void
+octave_rl_remove_event_hook( rl_event_hook_fcn_ptr f )
+{
+  pthread_mutex_lock( &event_hook_list_mutex );
+
+  // Find the matching event_hook and remove it
+  std::vector<rl_event_hook_fcn_ptr>::iterator it;
+  it = std::find( rl_event_hook_list.begin(), rl_event_hook_list.end(), f );
+  rl_event_hook_list.erase( it );
+  
+
+  pthread_mutex_unlock( &event_hook_list_mutex );
+}
+
+std::vector<rl_event_hook_fcn_ptr>
+octave_rl_get_event_hook_list (void)
+{
+  return rl_event_hook_list;
+}
+
+char **
+octave_rl_completion_matches (const char *text, rl_completer_fcn_ptr f)
+{
+  return rl_completion_matches (text, f);
+}
+
+char
+octave_rl_prompt_start_ignore (void)
+{
+  return RL_PROMPT_START_IGNORE;
+}
+
+char
+octave_rl_prompt_end_ignore (void)
+{
+  return RL_PROMPT_END_IGNORE;
+}
+
+void
+octave_rl_add_defun (const char *name, rl_fcn_ptr f, char key)
+{
+  rl_add_defun (name, f, key);
+}
+
+void
+octave_rl_set_terminal_name (const char *term)
+{
+  rl_terminal_name = term;
+}
+
+void
+octave_rl_initialize (void)
+{
+  rl_initialize ();
+}
+
+int
+octave_rl_history_search_forward (int count, int ignore)
+{
+  return rl_history_search_forward (count, ignore);
+}
+
+int
+octave_rl_history_search_backward (int count, int ignore)
+{
+  return rl_history_search_backward (count, ignore);
+}
+
+char
+octave_rl_ctrl (char c)
+{
+  return CTRL (c);
+}
+
+char
+octave_rl_meta (char c)
+{
+  return META (c);
+}
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]