* defs.h (read_command_lines, query_hook): Update prototypes.
authorFred Fish <fnf@specifix.com>
Mon, 20 May 1996 02:05:55 +0000 (02:05 +0000)
committerFred Fish <fnf@specifix.com>
Mon, 20 May 1996 02:05:55 +0000 (02:05 +0000)
(readline_begin_hook, readline_hook, readline_end_hook): Declare.
* breakpoint.c (commands_command): Build message in temporary buffer
and pass that, as well as tty control flag, to read_command_lines.
* top.c (readline_begin_hook, readline_hook, readline_end_hook):
Define here.
(command_loop): Check for non-NULL instream before looping.
(command_line_input): Use readline_hook when appropriate, to get
user input from a GUI window.
(read_next_line): Also build prompt if getting user input from a GUI.
(recurse_read_control_structure): Fix typo in comment.
(read_command_lines): Use passed in prompt and tty flag to decide how
to build message.  Use readline_begin_hook when appropriate, to set
up a GUI interaction window.  Just return head, whether NULL or not,
after using readline_end_hook to complete GUI interaction.
(define_command, document_command): Build message in a temporary
buffer and pass it to read_command_lines, along with tty flag.
* gdbtk.c (gdbtk_readline_begin, gdbtk_readline, gdbtk_readline_end):
New functions.
(tk_command_loop): Set instream to NULL to enable Tk user interaction.
(gdbtk_init): Set readline_begin_hook, readline_hook,
and readline_end_hook.
* gdbtk.tcl (gdbtk_tcl_readline_begin, gdbtk_tcl_readline,
gdbtk_tcl_readline_end): New functions.
(tclsh): Pack scroll bar on right side of window, not left.
PR 9385

gdb/ChangeLog
gdb/breakpoint.c
gdb/gdbtk.c
gdb/gdbtk.tcl
gdb/top.c

index 316f009f19b9a5ba8fbb23473dda69c0743a61ab..7e69edcddb2af79dc37fa799cbbea3edd5584d51 100644 (file)
@@ -1,3 +1,34 @@
+Sun May 19 16:49:37 1996  Fred Fish  <fnf@cygnus.com>
+
+       * defs.h (read_command_lines, query_hook): Update prototypes.
+       (readline_begin_hook, readline_hook, readline_end_hook): Declare.
+       * breakpoint.c (commands_command): Build message in temporary buffer
+       and pass that, as well as tty control flag, to read_command_lines.
+       * top.c (readline_begin_hook, readline_hook, readline_end_hook):
+       Define here.
+       (command_loop): Check for non-NULL instream before looping.
+       (command_line_input): Use readline_hook when appropriate, to get
+       user input from a GUI window.
+       (read_next_line): Also build prompt if getting user input from a GUI.
+       (recurse_read_control_structure): Fix typo in comment.
+       (read_command_lines): Use passed in prompt and tty flag to decide how
+       to build message.  Use readline_begin_hook when appropriate, to set
+       up a GUI interaction window.  Just return head, whether NULL or not,
+       after using readline_end_hook to complete GUI interaction.
+       (define_command, document_command): Build message in a temporary
+       buffer and pass it to read_command_lines, along with tty flag.
+
+start-sanitize-gdbtk
+       * gdbtk.c (gdbtk_readline_begin, gdbtk_readline, gdbtk_readline_end):
+       New functions.
+       (tk_command_loop): Set instream to NULL to enable Tk user interaction.
+       (gdbtk_init): Set readline_begin_hook, readline_hook,
+       and readline_end_hook.
+       * gdbtk.tcl (gdbtk_tcl_readline_begin, gdbtk_tcl_readline,
+       gdbtk_tcl_readline_end): New functions.
+       (tclsh): Pack scroll bar on right side of window, not left.
+end-sanitize-gdbtk
+
 Sat May 18 02:43:58 1996  Peter Schauer  (pes@regent.e-technik.tu-muenchen.de)
 
        * blockframe.c (frameless_look_for_prologue):
index 54c01b6b463e78bebaa220c9ab99be9e6fc374d0..2356288136464d1592b7b9813f3b77e4fa9d94f1 100644 (file)
@@ -330,10 +330,9 @@ commands_command (arg, from_tty)
   ALL_BREAKPOINTS (b)
     if (b->number == bnum)
       {
-       if (from_tty && input_from_terminal_p ())
-         printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\
-End with a line saying just \"end\".\n", bnum);
-       l = read_command_lines ();
+       char tmpbuf[128];
+       sprintf (tmpbuf, "Type commands for when breakpoint %d is hit, one per line.", bnum);
+       l = read_command_lines (tmpbuf, from_tty);
        free_command_lines (&b->commands);
        b->commands = l;
        breakpoints_changed ();
index 6234e4a012f328ef526b85460c8c1565ebc20c1d..2e244480c728f8fd6f64710c0ecf74d25ec5c0bd 100644 (file)
@@ -183,6 +183,64 @@ gdbtk_query (query, args)
   val = atol (interp->result);
   return val;
 }
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+gdbtk_readline_begin (char *format, ...)
+#else
+gdbtk_readline_begin (va_alist)
+     va_dcl
+#endif
+{
+  va_list args;
+  char buf[200], *merge[2];
+  char *command;
+
+#ifdef ANSI_PROTOTYPES
+  va_start (args, format);
+#else
+  char *format;
+  va_start (args);
+  format = va_arg (args, char *);
+#endif
+
+  vsprintf (buf, format, args);
+  merge[0] = "gdbtk_tcl_readline_begin";
+  merge[1] = buf;
+  command = Tcl_Merge (2, merge);
+  Tcl_Eval (interp, command);
+  free (command);
+}
+
+static char *
+gdbtk_readline (prompt)
+     char *prompt;
+{
+  char *merge[2];
+  char *command;
+
+  merge[0] = "gdbtk_tcl_readline";
+  merge[1] = prompt;
+  command = Tcl_Merge (2, merge);
+  if (Tcl_Eval (interp, command) == TCL_OK)
+    {
+      return (strdup (interp -> result));
+    }
+  else
+    {
+      gdbtk_fputs (interp -> result, gdb_stdout);
+      gdbtk_fputs ("\n", gdb_stdout);
+      return (NULL);
+    }
+}
+
+static void
+gdbtk_readline_end ()
+{
+  Tcl_Eval (interp, "gdbtk_tcl_readline_end");
+}
+
 \f
 static void
 #ifdef ANSI_PROTOTYPES
@@ -1117,6 +1175,10 @@ gdbtk_call_command (cmdblk, arg, from_tty)
 static void
 tk_command_loop ()
 {
+  extern GDB_FILE *instream;
+
+  /* We no longer want to use stdin as the command input stream */
+  instream = NULL;
   Tcl_Eval (interp, "gdbtk_tcl_preloop");
   Tk_MainLoop ();
 }
@@ -1180,6 +1242,9 @@ gdbtk_init ()
   interactive_hook = gdbtk_interactive;
   target_wait_hook = gdbtk_wait;
   call_command_hook = gdbtk_call_command;
+  readline_begin_hook = gdbtk_readline_begin;
+  readline_hook = gdbtk_readline;
+  readline_end_hook = gdbtk_readline_end;
 
   /* Get the file descriptor for the X server */
 
index 30af7b3b5df0d0c4c89968a830a23a4a7caba3d7..2bb5b27ffc9d1a38e442be3e43371ca3f0bcd05c 100644 (file)
@@ -265,6 +265,86 @@ proc gdbtk_tcl_breakpoint {action bpnum} {
        ${action}_breakpoint $bpnum $file $line $pc
 }
 
+#
+# GDB Callback:
+#
+#      gdbtk_tcl_readline_begin (message) - Notify Tk to open an interaction
+#      window and start gathering user input
+#
+# Description:
+#
+#      GDB calls this to notify TK that it needs to open an interaction
+#      window, displaying the given message, and be prepared to accept
+#      calls to gdbtk_tcl_readline to gather user input.
+
+proc gdbtk_tcl_readline_begin {message} {
+    global readline_text
+
+    # If another readline window already exists, just bring it to the front.
+    if {[winfo exists .rl]} {raise .rl ; return}
+
+    # Create top level frame with scrollbar and text widget.
+    toplevel .rl
+    wm title .rl "Interaction Window"
+    wm iconname .rl "Input"
+    message .rl.msg -text $message -aspect 7500 -justify left
+    text .rl.text -width 80 -height 20 -setgrid true -cursor hand2 \
+           -yscrollcommand {.rl.scroll set}
+    scrollbar .rl.scroll -command {.rl.text yview}
+    pack .rl.msg -side top -fill x
+    pack .rl.scroll -side right -fill y
+    pack .rl.text -side left -fill both -expand true
+
+    # When the user presses return, get the text from the command start mark to the
+    # current insert point, stash it in the readline text variable, and update the
+    # command start mark to the current insert point
+    bind .rl.text <Return> {
+       set readline_text [.rl.text get cmdstart {end - 1 char}]
+       .rl.text mark set cmdstart insert
+    }
+    bindtags .rl.text {.rl.text Text all}
+}
+
+#
+# GDB Callback:
+#
+#      gdbtk_tcl_readline (prompt) - Get one user input line
+#
+# Description:
+#
+#      GDB calls this to get one line of input from the user interaction
+#      window, using "prompt" as the command line prompt.
+
+proc gdbtk_tcl_readline {prompt} {
+    global readline_text
+
+    .rl.text insert end $prompt
+    .rl.text mark set cmdstart insert
+    .rl.text mark gravity cmdstart left
+    .rl.text see insert
+
+    # Make this window the current one for input.
+    focus .rl.text
+    grab .rl
+    tkwait variable readline_text
+    grab release .rl
+    return $readline_text
+}
+
+#
+# GDB Callback:
+#
+#      gdbtk_tcl_readline_end  - Terminate a user interaction
+#
+# Description:
+#
+#      GDB calls this when it is done getting interactive user input.
+#      Destroy the interaction window.
+
+proc gdbtk_tcl_readline_end {} {
+    if {[winfo exists .rl]} { destroy .rl }
+}
+
 proc create_breakpoints_window {} {
        global bpframe_lasty
 
@@ -3149,8 +3229,8 @@ proc tclsh {} {
     text .eval.text -width 80 -height 20 -setgrid true -cursor hand2 \
            -yscrollcommand {.eval.scroll set}
     scrollbar .eval.scroll -command {.eval.text yview}
-    pack .eval.scroll -side left -fill y
-    pack .eval.text -side right -fill both -expand true
+    pack .eval.scroll -side right -fill y
+    pack .eval.text -side left -fill both -expand true
 
     # Insert the tcl_prompt and initialize the cmdstart mark
     .eval.text insert insert $tcl_prompt
index be7db39afccb870f58a9cddcd1c7f99a55d54b2e..bfab3f7306b0d92cb52e8ac72e2bdad25283b440 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -275,7 +275,7 @@ struct cmd_list_element *showchecklist;
 
 /* stdio stream that command input is being read from.  Set to stdin normally.
    Set by source_command to the file we are sourcing.  Set to NULL if we are
-   executing a user-defined command.  */
+   executing a user-defined command or interacting via a GUI.  */
 
 FILE *instream;
 
@@ -395,6 +395,21 @@ int (*query_hook) PARAMS (());
 
 void (*flush_hook) PARAMS ((FILE *stream));
 
+/* These three functions support getting lines of text from the user.  They
+   are used in sequence.  First readline_begin_hook is called with a text
+   string that might be (for example) a message for the user to type in a
+   sequence of commands to be executed at a breakpoint.  If this function
+   calls back to a GUI, it might take this opportunity to pop up a text
+   interaction window with this message.  Next, readline_hook is called
+   with a prompt that is emitted prior to collecting the user input.
+   It can be called multiple times.  Finally, readline_end_hook is called
+   to notify the GUI that we are done with the interaction window and it
+   can close it. */
+
+void (*readline_begin_hook) PARAMS ((char *, ...));
+char * (*readline_hook) PARAMS ((char *));
+void (*readline_end_hook) PARAMS ((void));
+
 /* Called as appropriate to notify the interface of the specified breakpoint
    conditions.  */
 
@@ -1237,7 +1252,7 @@ command_loop ()
   extern int display_time;
   extern int display_space;
 
-  while (!feof (instream))
+  while (instream && !feof (instream))
     {
       if (window_hook && instream == stdin)
        (*window_hook) (instream, prompt);
@@ -1962,11 +1977,18 @@ command_line_input (prrompt, repeat, annotation_suffix)
        }
 
       /* Don't use fancy stuff if not talking to stdin.  */
-      if (command_editing_p && instream == stdin
-         && ISATTY (instream))
-       rl = readline (local_prompt);
+      if (readline_hook && instream == NULL)
+       {
+         rl = (*readline_hook) (local_prompt);
+       }
+      else if (command_editing_p && instream == stdin && ISATTY (instream))
+       {
+         rl = readline (local_prompt);
+       }
       else
-       rl = gdb_readline (local_prompt);
+       {
+         rl = gdb_readline (local_prompt);
+       }
 
       if (annotation_level > 1 && instream == stdin)
        {
@@ -2138,7 +2160,7 @@ read_next_line (command)
     error ("Control nesting too deep!\n");
 
   /* Set a prompt based on the nesting of the control commands.  */
-  if (instream == stdin)
+  if (instream == stdin || (instream == 0 && readline_hook != NULL))
     {
       for (i = 0; i < control_level; i++)
        control_prompt[i] = ' ';
@@ -2220,7 +2242,7 @@ read_next_line (command)
 }
 
 /* Recursively read in the control structures and create a command_line 
-   tructure from them.
+   structure from them.
 
    The parent_control parameter is the control structure in which the
    following commands are nested.  */
@@ -2331,19 +2353,34 @@ recurse_read_control_structure (current_cmd)
   return ret;
 }
 
+/* Read lines from the input stream and accumulate them in a chain of
+   struct command_line's, which is then returned.  For input from a
+   terminal, the special command "end" is used to mark the end of the
+   input, and is not included in the returned chain of commands. */
 
-/* Read lines from the input stream
-   and accumulate them in a chain of struct command_line's
-   which is then returned.  */
+#define END_MESSAGE "End with a line saying just \"end\"."
 
 struct command_line *
-read_command_lines ()
+read_command_lines (prompt, from_tty)
+char *prompt;
+int from_tty;
 {
   struct command_line *head, *tail, *next;
   struct cleanup *old_chain;
   enum command_control_type ret;
   enum misc_command_type val;
 
+  if (readline_begin_hook)
+    {
+      /* Note - intentional to merge messages with no newline */
+      (*readline_begin_hook) ("%s  %s\n", prompt, END_MESSAGE);
+    }
+  else if (from_tty && input_from_terminal_p ())
+    {
+      printf_unfiltered ("%s\n%s\n", prompt, END_MESSAGE);
+      gdb_flush (gdb_stdout);
+    }
+
   head = tail = NULL;
   old_chain = NULL;
 
@@ -2397,13 +2434,16 @@ read_command_lines ()
       if (ret != invalid_control)
        {
          discard_cleanups (old_chain);
-         return head;
        }
       else
        do_cleanups (old_chain);
     }
 
-  return NULL;
+  if (readline_end_hook)
+    {
+      (*readline_end_hook) ();
+    }
+  return (head);
 }
 
 /* Free a chain of struct command_line's.  */
@@ -2579,6 +2619,7 @@ define_command (comname, from_tty)
   register struct command_line *cmds;
   register struct cmd_list_element *c, *newc, *hookc = 0;
   char *tem = comname;
+  char tmpbuf[128];
 #define        HOOK_STRING     "hook-"
 #define        HOOK_LEN 5
 
@@ -2626,15 +2667,9 @@ define_command (comname, from_tty)
   for (tem = comname; *tem; tem++)
     if (isupper(*tem)) *tem = tolower(*tem);
 
-  if (from_tty)
-    {
-      printf_unfiltered ("Type commands for definition of \"%s\".\n\
-End with a line saying just \"end\".\n", comname);
-      gdb_flush (gdb_stdout);
-    }
-
   control_level = 0;
-  cmds = read_command_lines ();
+  sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname);
+  cmds = read_command_lines (tmpbuf, from_tty);
 
   if (c && c->class == class_user)
     free_command_lines (&c->user_commands);
@@ -2661,6 +2696,7 @@ document_command (comname, from_tty)
   struct command_line *doclines;
   register struct cmd_list_element *c;
   char *tem = comname;
+  char tmpbuf[128];
 
   validate_comname (comname);
 
@@ -2669,11 +2705,8 @@ document_command (comname, from_tty)
   if (c->class != class_user)
     error ("Command \"%s\" is built-in.", comname);
 
-  if (from_tty)
-    printf_unfiltered ("Type documentation for \"%s\".\n\
-End with a line saying just \"end\".\n", comname);
-
-  doclines = read_command_lines ();
+  sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
+  doclines = read_command_lines (tmpbuf, from_tty);
 
   if (c->doc) free (c->doc);