Merge remote-tracking branch 'origin/stable-2.0'
[bpt/guile.git] / guile-readline / readline.c
index 4d2be73..0e4ad29 100644 (file)
@@ -1,10 +1,10 @@
 /* readline.c --- line editing support for Guile */
 
-/* Copyright (C) 1997,1999,2000,2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1997,1999,2000,2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
  * 
  * This program 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)
+ * the Free Software Foundation; either version 3, or (at your option)
  * any later version.
  * 
  * This program is distributed in the hope that it will be useful,
 
 
 \f
-
-/* Include private, configure generated header (i.e. config.h). */
-#include "guile-readline-config.h"
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 
 #ifdef HAVE_RL_GETC_FUNCTION
 #include "libguile.h"
-#include "libguile/gh.h"
 #include "libguile/iselect.h"
 
 #include <stdio.h>
@@ -129,6 +128,7 @@ rl_free_line_state ()
 
 static int promptp;
 static SCM input_port;
+static SCM output_port;
 static SCM before_read;
 
 static int
@@ -139,14 +139,14 @@ current_input_getc (FILE *in SCM_UNUSED)
       scm_apply (before_read, SCM_EOL, SCM_EOL);
       promptp = 0;
     }
-  return scm_getc (input_port);
+  return scm_get_byte_or_eof (input_port);
 }
 
 static int in_readline = 0;
 static SCM reentry_barrier_mutex;
 
 static SCM internal_readline (SCM text);
-static SCM handle_error (void *data, SCM tag, SCM args);
+static void unwind_readline (void *unused);
 static void reentry_barrier (void);
 
 
@@ -200,10 +200,12 @@ SCM_DEFINE (scm_readline, "%readline", 0, 4, 0,
 
   scm_readline_init_ports (inp, outp);
 
-  ans = scm_internal_catch (SCM_BOOL_T,
-                           (scm_t_catch_body) internal_readline,
-                           (void *) SCM_UNPACK (text),
-                           handle_error, 0);
+  scm_dynwind_begin (0);
+  scm_dynwind_unwind_handler (unwind_readline, NULL, 0);
+  
+  ans = internal_readline (text);
+
+  scm_dynwind_end ();
 
 #ifndef __MINGW32__
   fclose (rl_instream);
@@ -231,8 +233,9 @@ reentry_barrier ()
     scm_misc_error (s_scm_readline, "readline is not reentrant", SCM_EOL);
 }
 
-static SCM
-handle_error (void *data, SCM tag, SCM args)
+/* This function is only called on nonlocal exit from readline(). */
+static void
+unwind_readline (void *unused)
 {
   rl_free_line_state ();
   rl_cleanup_after_signal ();
@@ -242,8 +245,6 @@ handle_error (void *data, SCM tag, SCM args)
   fclose (rl_outstream);
 #endif
   --in_readline;
-  scm_handle_by_throw (data, tag, args);
-  return SCM_UNSPECIFIED; /* never reached */
 }
 
 static SCM
@@ -256,7 +257,12 @@ internal_readline (SCM text)
   promptp = 1;
   s = readline (prompt);
   if (s)
-    ret = scm_from_locale_string (s);
+    {
+      scm_t_port *pt = SCM_PTAB_ENTRY (output_port);
+      
+      ret = scm_from_stringn (s, strlen (s), pt->encoding, 
+                              SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE);
+    }
   else 
     ret = SCM_EOF_VAL;
 
@@ -312,6 +318,7 @@ scm_readline_init_ports (SCM inp, SCM outp)
   }
 
   input_port = inp;
+  output_port = outp;
 #ifndef __MINGW32__
   rl_instream = stream_from_fport (inp, "r", s_scm_readline);
   rl_outstream = stream_from_fport (outp, "w", s_scm_readline);
@@ -329,6 +336,7 @@ SCM_DEFINE (scm_add_history, "add-history", 1, 0, 0,
 
   s = scm_to_locale_string (text);
   add_history (s);
+  free (s);
 
   return SCM_UNSPECIFIED;
 }
@@ -424,6 +432,7 @@ completion_function (char *text, int continuep)
     }
 }
 
+#if HAVE_RL_GET_KEYMAP
 /*Bouncing parenthesis (reimplemented by GH, 11/23/98, since readline is strict gpl)*/
 
 static int match_paren (int x, int k);
@@ -527,26 +536,7 @@ match_paren (int x, int k)
     }
   return 0;
 }
-
-#if defined (HAVE_RL_PRE_INPUT_HOOK) && defined (GUILE_SIGWINCH_SA_RESTART_CLEARED)
-/* Readline disables SA_RESTART on SIGWINCH.
- * This code turns it back on.
- */
-static int
-sigwinch_enable_restart (void)
-{
-#ifdef HAVE_SIGINTERRUPT
-  siginterrupt (SIGWINCH, 0);
-#else
-  struct sigaction action;
-  
-  sigaction (SIGWINCH, NULL, &action);
-  action.sa_flags |= SA_RESTART;
-  sigaction (SIGWINCH, &action, NULL);
-#endif
-  return 0;
-}
-#endif
+#endif /* HAVE_RL_GET_KEYMAP */
 
 #endif /* HAVE_RL_GETC_FUNCTION */
 
@@ -565,16 +555,25 @@ scm_init_readline ()
 #else  
   rl_completion_entry_function = (Function*) completion_function;
 #endif
-  rl_basic_word_break_characters = "\t\n\"'`;()";
+  rl_basic_word_break_characters = " \t\n\"'`;()";
   rl_readline_name = "Guile";
-#if defined (HAVE_RL_PRE_INPUT_HOOK) && defined (GUILE_SIGWINCH_SA_RESTART_CLEARED)
-  rl_pre_input_hook = sigwinch_enable_restart;
-#endif
 
-  reentry_barrier_mutex = scm_permanent_object (scm_make_mutex ());
+  /* Let Guile handle signals. */
+#if defined (HAVE_DECL_RL_CATCH_SIGNALS) && HAVE_DECL_RL_CATCH_SIGNALS
+  rl_catch_signals = 0;
+#endif
+  
+  /* But let readline handle SIGWINCH. */
+#if defined (HAVE_DECL_RL_CATCH_SIGWINCH) && HAVE_DECL_RL_CATCH_SIGWINCH
+  rl_catch_sigwinch = 1;
+#endif
+  
+  reentry_barrier_mutex = scm_make_mutex ();
   scm_init_opts (scm_readline_options,
                 scm_readline_opts);
+#if HAVE_RL_GET_KEYMAP
   init_bouncing_parens();
+#endif
   scm_add_feature ("readline");
 #endif /* HAVE_RL_GETC_FUNCTION */
 }