Fix the processing of Meta-key commands in TUI
[deliverable/binutils-gdb.git] / gdb / tui / tui-io.c
index 2fb7bb436c338e4832f2756b72702ca2e7850cf6..aa1d1c70863e0ddcf99207c3fbf479c6a720bebe 100644 (file)
@@ -1,6 +1,6 @@
 /* TUI support I/O functions.
 
-   Copyright (C) 1998-2004, 2007-2012 Free Software Foundation, Inc.
+   Copyright (C) 1998-2014 Free Software Foundation, Inc.
 
    Contributed by Hewlett-Packard Company.
 
@@ -36,7 +36,7 @@
 #include "cli-out.h"
 #include <fcntl.h>
 #include <signal.h>
-#include <stdio.h>
+#include "filestuff.h"
 
 #include "gdb_curses.h"
 
@@ -128,10 +128,10 @@ static struct ui_file *tui_old_stderr;
 struct ui_out *tui_old_uiout;
 
 /* Readline previous hooks.  */
-static Function *tui_old_rl_getc_function;
-static VFunction *tui_old_rl_redisplay_function;
-static VFunction *tui_old_rl_prep_terminal;
-static VFunction *tui_old_rl_deprep_terminal;
+static rl_getc_func_t *tui_old_rl_getc_function;
+static rl_voidfunc_t *tui_old_rl_redisplay_function;
+static rl_vintfunc_t *tui_old_rl_prep_terminal;
+static rl_voidfunc_t *tui_old_rl_deprep_terminal;
 static int tui_old_rl_echoing_p;
 
 /* Readline output stream.
@@ -211,8 +211,11 @@ tui_redisplay_readline (void)
 
   /* Detect when we temporarily left SingleKey and now the readline
      edit buffer is empty, automatically restore the SingleKey
-     mode.  */
-  if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0)
+     mode.  The restore must only be done if the command has finished.
+     The command could call prompt_for_continue and we must not
+     restore SingleKey so that the prompt and normal keymap are used.  */
+  if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0
+      && immediate_quit == 0)
     tui_set_key_mode (TUI_SINGLE_KEY_MODE);
 
   if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
@@ -289,7 +292,7 @@ tui_prep_terminal (int notused1)
      (we can't use gdb_prompt() due to secondary prompts and can't use
      rl_prompt because it points to an alloca buffer).  */
   xfree (tui_rl_saved_prompt);
-  tui_rl_saved_prompt = xstrdup (rl_prompt);
+  tui_rl_saved_prompt = rl_prompt != NULL ? xstrdup (rl_prompt) : NULL;
 }
 
 /* Readline callback to restore the terminal.  It is called once each
@@ -416,7 +419,8 @@ tui_rl_display_match_list (char **matches, int len, int max)
     {
       char msg[256];
 
-      sprintf (msg, "\nDisplay all %d possibilities? (y or n)", len);
+      xsnprintf (msg, sizeof (msg),
+                "\nDisplay all %d possibilities? (y or n)", len);
       tui_puts (msg);
       if (get_y_or_n () == 0)
        {
@@ -604,25 +608,20 @@ tui_initialize_io (void)
   tui_stderr = tui_fileopen (stderr);
   tui_out = tui_out_new (tui_stdout);
 
-  /* Create the default UI.  It is not created because we installed a
-     deprecated_init_ui_hook.  */
+  /* Create the default UI.  */
   tui_old_uiout = cli_out_new (gdb_stdout);
 
 #ifdef TUI_USE_PIPE_FOR_READLINE
   /* Temporary solution for readline writing to stdout: redirect
      readline output in a pipe, read that pipe and output the content
      in the curses command window.  */
-  if (pipe (tui_readline_pipe) != 0)
-    {
-      fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
-      exit (1);
-    }
+  if (gdb_pipe_cloexec (tui_readline_pipe) != 0)
+    error (_("Cannot create pipe for readline"));
+
   tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
   if (tui_rl_outstream == 0)
-    {
-      fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
-      exit (1);
-    }
+    error (_("Cannot redirect readline output"));
+
   setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0);
 
 #ifdef O_NONBLOCK
@@ -692,7 +691,33 @@ tui_getc (FILE *fp)
     TUI_CMD_WIN->detail.command_info.curch = 0;
   if (ch == KEY_BACKSPACE)
     return '\b';
-  
+
+  if (async_command_editing_p && key_is_start_sequence (ch))
+    {
+      int ch_pending;
+
+      nodelay (w, TRUE);
+      ch_pending = wgetch (w);
+      nodelay (w, FALSE);
+
+      /* If we have pending input following a start sequence, call the stdin
+        event handler again because ncurses may have already read and stored
+        the input into its internal buffer, meaning that we won't get an stdin
+        event for it.  If we don't compensate for this missed stdin event, key
+        sequences as Alt_F (^[f) will not behave promptly.
+
+        (We only compensates for the missed 2nd byte of a key sequence because
+        2-byte sequences are by far the most commonly used. ncurses may have
+        buffered a larger, 3+-byte key sequence though it remains to be seen
+        whether it is useful to compensate for all the bytes of such
+        sequences.)  */
+      if (ch_pending != ERR)
+       {
+         ungetch (ch_pending);
+         call_stdin_event_handler_again_p = 1;
+       }
+    }
+
   return ch;
 }
 
This page took 0.031954 seconds and 4 git commands to generate.