Remove hard-coded TUI layouts
authorTom Tromey <tom@tromey.com>
Sat, 22 Feb 2020 18:48:26 +0000 (11:48 -0700)
committerTom Tromey <tom@tromey.com>
Sat, 22 Feb 2020 18:48:30 +0000 (11:48 -0700)
This changes the TUI so that the available layouts are no longer
completely hard-coded.  "enum tui_layout_type" is removed, and then
all the fallout from this is fixed up.

This patch also reimplements the "layout" command to be a prefix
command.  The concrete layouts are simply sub-commands now.  This
provides completion and correct abbreviation behavior for free.

Finally, this also changes the name of the locator window to "status".
This matches the documentation and will be exposed to the user in a
subsequent patch.

gdb/ChangeLog
2020-02-22  Tom Tromey  <tom@tromey.com>

* tui/tui.c (tui_enable): Call tui_set_initial_layout.
* tui/tui-win.c (window_name_completer): Update comment.
* tui/tui-layout.h (class tui_layout_base) <replace_window>:
Declare method.
(class tui_layout_window) <replace_window>: Likewise.
(class tui_layout_split) <replace_window>: Likewise.
(tui_set_layout): Don't declare.
(tui_set_initial_layout): Declare function.
* tui/tui-layout.c (layouts, applied_skeleton, src_regs_layout)
(asm_regs_layout): New globals.
(tui_current_layout, show_layout): Remove.
(tui_set_layout, tui_add_win_to_layout): Rewrite.
(find_layout, tui_apply_layout): New function.
(layout_completer): Remove.
(tui_next_layout): Reimplement.
(tui_next_layout_command): New function.
(tui_set_initial_layout, tui_prev_layout_command): New functions.
(tui_regs_layout): Reimplement.
(tui_regs_layout_command): New function.
(extract_display_start_addr): Rewrite.
(next_layout, prev_layout): Remove.
(tui_layout_window::replace_window): New method.
(tui_layout_split::replace_window): New method.
(destroy_layout): New function.
(layout_list): New global.
(add_layout_command): New function.
(initialize_layouts): Update.
(tui_layout_command): New function.
(_initialize_tui_layout): Install "layout" commands.
* tui/tui-data.h (enum tui_layout_type): Remove.
(tui_current_layout): Don't declare.

Change-Id: I9b5f7ab3ce838d6b340b8c373ef649a8e0a74b73

gdb/ChangeLog
gdb/tui/tui-data.h
gdb/tui/tui-layout.c
gdb/tui/tui-layout.h
gdb/tui/tui-win.c
gdb/tui/tui.c

index d044a559bc0edff9c84565caeefe78496d58d194..a7e565abcce15c09e0215f95c8be81c7630d4966 100644 (file)
@@ -1,3 +1,37 @@
+2020-02-22  Tom Tromey  <tom@tromey.com>
+
+       * tui/tui.c (tui_enable): Call tui_set_initial_layout.
+       * tui/tui-win.c (window_name_completer): Update comment.
+       * tui/tui-layout.h (class tui_layout_base) <replace_window>:
+       Declare method.
+       (class tui_layout_window) <replace_window>: Likewise.
+       (class tui_layout_split) <replace_window>: Likewise.
+       (tui_set_layout): Don't declare.
+       (tui_set_initial_layout): Declare function.
+       * tui/tui-layout.c (layouts, applied_skeleton, src_regs_layout)
+       (asm_regs_layout): New globals.
+       (tui_current_layout, show_layout): Remove.
+       (tui_set_layout, tui_add_win_to_layout): Rewrite.
+       (find_layout, tui_apply_layout): New function.
+       (layout_completer): Remove.
+       (tui_next_layout): Reimplement.
+       (tui_next_layout_command): New function.
+       (tui_set_initial_layout, tui_prev_layout_command): New functions.
+       (tui_regs_layout): Reimplement.
+       (tui_regs_layout_command): New function.
+       (extract_display_start_addr): Rewrite.
+       (next_layout, prev_layout): Remove.
+       (tui_layout_window::replace_window): New method.
+       (tui_layout_split::replace_window): New method.
+       (destroy_layout): New function.
+       (layout_list): New global.
+       (add_layout_command): New function.
+       (initialize_layouts): Update.
+       (tui_layout_command): New function.
+       (_initialize_tui_layout): Install "layout" commands.
+       * tui/tui-data.h (enum tui_layout_type): Remove.
+       (tui_current_layout): Don't declare.
+
 2020-02-22  Tom Tromey  <tom@tromey.com>
 
        * tui/tui-regs.c (tui_reg_layout): Remove.
index 6f86122f58f1a467270c2c363da0c9912503e6ff..2badcd4f1a65486cc5c1fb0168f18c98ea10d360 100644 (file)
@@ -131,17 +131,6 @@ public:
 /* Strings to display in the TUI status line.  */
 #define SINGLE_KEY              "(SingleKey)"
 
-/* The kinds of layouts available.  */
-enum tui_layout_type
-{
-  SRC_COMMAND,
-  DISASSEM_COMMAND,
-  SRC_DISASSEM_COMMAND,
-  SRC_DATA_COMMAND,
-  DISASSEM_DATA_COMMAND,
-  UNDEFINED_LAYOUT
-};
-
 enum tui_line_or_address_kind
 {
   LOA_LINE,
@@ -310,7 +299,6 @@ struct all_tui_windows
 
 
 /* Data Manipulation Functions.  */
-extern enum tui_layout_type tui_current_layout (void);
 extern int tui_term_height (void);
 extern void tui_set_term_height_to (int);
 extern int tui_term_width (void);
index 74a5745aac9ffd28b59c27acb6333006eb8e8567..e2ddbfb0d2cc3c5735801ae2c5b7d7c85e1c067b 100644 (file)
@@ -25,6 +25,8 @@
 #include "symtab.h"
 #include "frame.h"
 #include "source.h"
+#include "cli/cli-cmds.h"
+#include "cli/cli-decode.h"
 #include <ctype.h>
 
 #include "tui/tui.h"
 #include "tui/tui-source.h"
 #include "gdb_curses.h"
 
-static void show_layout (enum tui_layout_type);
-static enum tui_layout_type next_layout (void);
-static enum tui_layout_type prev_layout (void);
 static void tui_layout_command (const char *, int);
 static void extract_display_start_addr (struct gdbarch **, CORE_ADDR *);
 
-
-/* The pre-defined layouts.  */
-static tui_layout_split *standard_layouts[UNDEFINED_LAYOUT];
+/* The layouts.  */
+static std::vector<std::unique_ptr<tui_layout_split>> layouts;
 
 /* The layout that is currently applied.  */
 static std::unique_ptr<tui_layout_base> applied_layout;
 
-static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
+/* The "skeleton" version of the layout that is currently applied.  */
+static tui_layout_split *applied_skeleton;
 
-/* Accessor for the current layout.  */
-enum tui_layout_type
-tui_current_layout (void)
-{
-  return current_layout;
-}
+/* The two special "regs" layouts.  Note that these aren't registered
+   as commands and so can never be deleted.  */
+static tui_layout_split *src_regs_layout;
+static tui_layout_split *asm_regs_layout;
 
 /* See tui-layout.h.  */
 
@@ -78,113 +75,24 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height)
   applied_layout->adjust_size (win->name (), new_height);
 }
 
-/* Show the screen layout defined.  */
-static void
-show_layout (enum tui_layout_type layout)
-{
-  enum tui_layout_type cur_layout = tui_current_layout ();
-
-  if (layout != cur_layout)
-    {
-      tui_make_all_invisible ();
-      applied_layout = standard_layouts[layout]->clone ();
-      tui_apply_current_layout ();
-      current_layout = layout;
-      tui_delete_invisible_windows ();
-    }
-}
-
+/* Set the current layout to LAYOUT.  */
 
-/* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
-   SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.  */
-void
-tui_set_layout (enum tui_layout_type layout_type)
+static void
+tui_set_layout (tui_layout_split *layout)
 {
-  gdb_assert (layout_type != UNDEFINED_LAYOUT);
-
-  enum tui_layout_type cur_layout = tui_current_layout ();
   struct gdbarch *gdbarch;
   CORE_ADDR addr;
-  struct tui_win_info *win_with_focus = tui_win_with_focus ();
 
   extract_display_start_addr (&gdbarch, &addr);
+  tui_make_all_invisible ();
+  applied_skeleton = layout;
+  applied_layout = layout->clone ();
+  tui_apply_current_layout ();
+  tui_delete_invisible_windows ();
 
-  enum tui_layout_type new_layout = layout_type;
-
-  if (new_layout != cur_layout)
-    {
-      tui_suppress_output suppress;
-
-      show_layout (new_layout);
-
-      /* Now determine where focus should be.  */
-      if (win_with_focus != TUI_CMD_WIN)
-       {
-         switch (new_layout)
-           {
-           case SRC_COMMAND:
-             tui_set_win_focus_to (TUI_SRC_WIN);
-             break;
-           case DISASSEM_COMMAND:
-             /* The previous layout was not showing code.
-                This can happen if there is no source
-                available:
-
-                1. if the source file is in another dir OR
-                2. if target was compiled without -g
-                We still want to show the assembly though!  */
-
-             tui_get_begin_asm_address (&gdbarch, &addr);
-             tui_set_win_focus_to (TUI_DISASM_WIN);
-             break;
-           case SRC_DISASSEM_COMMAND:
-             /* The previous layout was not showing code.
-                This can happen if there is no source
-                available:
-
-                1. if the source file is in another dir OR
-                2. if target was compiled without -g
-                We still want to show the assembly though!  */
-
-             tui_get_begin_asm_address (&gdbarch, &addr);
-             if (win_with_focus == TUI_SRC_WIN)
-               tui_set_win_focus_to (TUI_SRC_WIN);
-             else
-               tui_set_win_focus_to (TUI_DISASM_WIN);
-             break;
-           case SRC_DATA_COMMAND:
-             if (win_with_focus != TUI_DATA_WIN)
-               tui_set_win_focus_to (TUI_SRC_WIN);
-             else
-               tui_set_win_focus_to (TUI_DATA_WIN);
-             break;
-           case DISASSEM_DATA_COMMAND:
-             /* The previous layout was not showing code.
-                This can happen if there is no source
-                available:
-
-                1. if the source file is in another dir OR
-                2. if target was compiled without -g
-                We still want to show the assembly though!  */
-
-             tui_get_begin_asm_address (&gdbarch, &addr);
-             if (win_with_focus != TUI_DATA_WIN)
-               tui_set_win_focus_to (TUI_DISASM_WIN);
-             else
-               tui_set_win_focus_to (TUI_DATA_WIN);
-             break;
-           default:
-             break;
-           }
-       }
-      /*
-       * Now update the window content.
-       */
-      tui_update_source_windows_with_addr (gdbarch, addr);
-      if (new_layout == SRC_DATA_COMMAND
-         || new_layout == DISASSEM_DATA_COMMAND)
-       TUI_DATA_WIN->show_registers (TUI_DATA_WIN->get_current_group ());
-    }
+  if (gdbarch == nullptr && TUI_DISASM_WIN != nullptr)
+    tui_get_begin_asm_address (&gdbarch, &addr);
+  tui_update_source_windows_with_addr (gdbarch, addr);
 }
 
 /* See tui-layout.h.  */
@@ -194,104 +102,113 @@ tui_add_win_to_layout (enum tui_win_type type)
 {
   gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
 
-  enum tui_layout_type cur_layout = tui_current_layout ();
+  /* If the window already exists, no need to add it.  */
+  if (tui_win_list[type] != nullptr)
+    return;
+
+  /* If the window we are trying to replace doesn't exist, we're
+     done.  */
+  enum tui_win_type other = type == SRC_WIN ? DISASSEM_WIN : SRC_WIN;
+  if (tui_win_list[other] == nullptr)
+    return;
+
+  const char *name = type == SRC_WIN ? SRC_NAME : DISASSEM_NAME;
+  applied_layout->replace_window (tui_win_list[other]->name (), name);
+  tui_apply_current_layout ();
+  tui_delete_invisible_windows ();
+}
+
+/* Find LAYOUT in the "layouts" global and return its index.  */
 
-  switch (type)
+static size_t
+find_layout (tui_layout_split *layout)
+{
+  for (size_t i = 0; i < layouts.size (); ++i)
     {
-    case SRC_WIN:
-      if (cur_layout != SRC_COMMAND
-         && cur_layout != SRC_DISASSEM_COMMAND
-         && cur_layout != SRC_DATA_COMMAND)
-       {
-         if (cur_layout == DISASSEM_DATA_COMMAND)
-           tui_set_layout (SRC_DATA_COMMAND);
-         else
-           tui_set_layout (SRC_COMMAND);
-       }
-      break;
-    case DISASSEM_WIN:
-      if (cur_layout != DISASSEM_COMMAND
-         && cur_layout != SRC_DISASSEM_COMMAND
-         && cur_layout != DISASSEM_DATA_COMMAND)
-       {
-         if (cur_layout == SRC_DATA_COMMAND)
-           tui_set_layout (DISASSEM_DATA_COMMAND);
-         else
-           tui_set_layout (DISASSEM_COMMAND);
-       }
-      break;
+      if (layout == layouts[i].get ())
+       return i;
     }
+  gdb_assert_not_reached (_("layout not found!?"));
 }
 
-/* Complete possible layout names.  TEXT is the complete text entered so
-   far, WORD is the word currently being completed.  */
+/* Function to set the layout. */
 
 static void
-layout_completer (struct cmd_list_element *ignore,
-                 completion_tracker &tracker,
-                 const char *text, const char *word)
+tui_apply_layout (struct cmd_list_element *command,
+                 const char *args, int from_tty)
 {
-  static const char *layout_names [] =
-    { "src", "asm", "split", "regs", "next", "prev", NULL };
+  tui_layout_split *layout
+    = (tui_layout_split *) get_cmd_context (command);
 
-  complete_on_enum (tracker, layout_names, text, word);
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  tui_set_layout (layout);
 }
 
-/* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
-   REGS. */
-static void
-tui_layout_command (const char *layout_name, int from_tty)
-{
-  enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
-  enum tui_layout_type cur_layout = tui_current_layout ();
-
-  if (layout_name == NULL || *layout_name == '\0')
-    error (_("Usage: layout prev | next | LAYOUT-NAME"));
+/* See tui-layout.h.  */
 
-  /* First check for ambiguous input.  */
-  if (strcmp (layout_name, "s") == 0)
-    error (_("Ambiguous command input."));
+void
+tui_next_layout ()
+{
+  size_t index = find_layout (applied_skeleton);
+  ++index;
+  if (index == layouts.size ())
+    index = 0;
+  tui_set_layout (layouts[index].get ());
+}
 
-  if (subset_compare (layout_name, "src"))
-    new_layout = SRC_COMMAND;
-  else if (subset_compare (layout_name, "asm"))
-    new_layout = DISASSEM_COMMAND;
-  else if (subset_compare (layout_name, "split"))
-    new_layout = SRC_DISASSEM_COMMAND;
-  else if (subset_compare (layout_name, "regs"))
-    {
-      if (cur_layout == SRC_COMMAND
-         || cur_layout == SRC_DATA_COMMAND)
-       new_layout = SRC_DATA_COMMAND;
-      else
-       new_layout = DISASSEM_DATA_COMMAND;
-    }
-  else if (subset_compare (layout_name, "next"))
-    new_layout = next_layout ();
-  else if (subset_compare (layout_name, "prev"))
-    new_layout = prev_layout ();
-  else
-    error (_("Unrecognized layout: %s"), layout_name);
+/* Implement the "layout next" command.  */
 
-  /* Make sure the curses mode is enabled.  */
+static void
+tui_next_layout_command (const char *arg, int from_tty)
+{
   tui_enable ();
-  tui_set_layout (new_layout);
+  tui_next_layout ();
 }
 
 /* See tui-layout.h.  */
 
 void
-tui_next_layout ()
+tui_set_initial_layout ()
+{
+  tui_set_layout (layouts[0].get ());
+}
+
+/* Implement the "layout prev" command.  */
+
+static void
+tui_prev_layout_command (const char *arg, int from_tty)
 {
-  tui_layout_command ("next", 0);
+  tui_enable ();
+  size_t index = find_layout (applied_skeleton);
+  if (index == 0)
+    index = layouts.size ();
+  --index;
+  tui_set_layout (layouts[index].get ());
 }
 
+
 /* See tui-layout.h.  */
 
 void
 tui_regs_layout ()
 {
-  tui_layout_command ("regs", 0);
+  /* If there's already a register window, we're done.  */
+  if (TUI_DATA_WIN != nullptr)
+    return;
+
+  tui_set_layout (TUI_DISASM_WIN != nullptr
+                 ? asm_regs_layout
+                 : src_regs_layout);
+}
+
+/* Implement the "layout regs" command.  */
+
+static void
+tui_regs_layout_command (const char *arg, int from_tty)
+{
+  tui_enable ();
+  tui_regs_layout ();
 }
 
 /* See tui-layout.h.  */
@@ -319,77 +236,29 @@ tui_remove_some_windows ()
 static void
 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
 {
-  enum tui_layout_type cur_layout = tui_current_layout ();
-  struct gdbarch *gdbarch = get_current_arch ();
-  CORE_ADDR addr;
+  struct gdbarch *gdbarch = nullptr;
+  CORE_ADDR addr = 0;
   CORE_ADDR pc;
   struct symtab_and_line cursal = get_current_source_symtab_and_line ();
 
-  switch (cur_layout)
+  if (TUI_SRC_WIN != nullptr)
     {
-    case SRC_COMMAND:
-    case SRC_DATA_COMMAND:
       gdbarch = TUI_SRC_WIN->gdbarch;
       find_line_pc (cursal.symtab,
                    TUI_SRC_WIN->start_line_or_addr.u.line_no,
                    &pc);
       addr = pc;
-      break;
-    case DISASSEM_COMMAND:
-    case SRC_DISASSEM_COMMAND:
-    case DISASSEM_DATA_COMMAND:
+    }
+  else if (TUI_DISASM_WIN != nullptr)
+    {
       gdbarch = TUI_DISASM_WIN->gdbarch;
       addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
-      break;
-    default:
-      addr = 0;
-      break;
     }
 
   *gdbarch_p = gdbarch;
   *addr_p = addr;
 }
 
-
-/* Answer the previous layout to cycle to.  */
-static enum tui_layout_type
-next_layout (void)
-{
-  int new_layout;
-
-  new_layout = tui_current_layout ();
-  if (new_layout == UNDEFINED_LAYOUT)
-    new_layout = SRC_COMMAND;
-  else
-    {
-      new_layout++;
-      if (new_layout == UNDEFINED_LAYOUT)
-       new_layout = SRC_COMMAND;
-    }
-
-  return (enum tui_layout_type) new_layout;
-}
-
-
-/* Answer the next layout to cycle to.  */
-static enum tui_layout_type
-prev_layout (void)
-{
-  int new_layout;
-
-  new_layout = tui_current_layout ();
-  if (new_layout == SRC_COMMAND)
-    new_layout = DISASSEM_DATA_COMMAND;
-  else
-    {
-      new_layout--;
-      if (new_layout == UNDEFINED_LAYOUT)
-       new_layout = DISASSEM_DATA_COMMAND;
-    }
-
-  return (enum tui_layout_type) new_layout;
-}
-
 void
 tui_gen_win_info::resize (int height_, int width_,
                          int origin_x_, int origin_y_)
@@ -454,7 +323,7 @@ tui_get_window_by_name (const std::string &name)
     }
   else
     {
-      gdb_assert (name == "locator");
+      gdb_assert (name == "status");
       return tui_locator_win_info_ptr ();
     }
 }
@@ -512,6 +381,22 @@ tui_layout_window::bottom_boxed_p () const
 
 /* See tui-layout.h.  */
 
+void
+tui_layout_window::replace_window (const char *name, const char *new_window)
+{
+  if (m_contents == name)
+    {
+      m_contents = new_window;
+      if (m_window != nullptr)
+       {
+         m_window->make_visible (false);
+         m_window = tui_get_window_by_name (m_contents);
+       }
+    }
+}
+
+/* See tui-layout.h.  */
+
 tui_layout_split *
 tui_layout_split::add_split (int weight)
 {
@@ -804,40 +689,102 @@ tui_layout_split::remove_windows (const char *name)
     }
 }
 
+/* See tui-layout.h.  */
+
+void
+tui_layout_split::replace_window (const char *name, const char *new_window)
+{
+  for (auto &item : m_splits)
+    item.layout->replace_window (name, new_window);
+}
+
+/* Destroy the layout associated with SELF.  */
+
 static void
-initialize_layouts ()
+destroy_layout (struct cmd_list_element *self, void *context)
+{
+  tui_layout_split *layout = (tui_layout_split *) context;
+  size_t index = find_layout (layout);
+  layouts.erase (layouts.begin () + index);
+}
+
+/* List holding the sub-commands of "layout".  */
+
+static struct cmd_list_element *layout_list;
+
+/* Add a "layout" command with name NAME that switches to LAYOUT.  */
+
+static void
+add_layout_command (const char *name, tui_layout_split *layout)
 {
-  standard_layouts[SRC_COMMAND] = new tui_layout_split ();
-  standard_layouts[SRC_COMMAND]->add_window ("src", 2);
-  standard_layouts[SRC_COMMAND]->add_window ("locator", 0);
-  standard_layouts[SRC_COMMAND]->add_window ("cmd", 1);
+  struct cmd_list_element *cmd;
 
-  standard_layouts[DISASSEM_COMMAND] = new tui_layout_split ();
-  standard_layouts[DISASSEM_COMMAND]->add_window ("asm", 2);
-  standard_layouts[DISASSEM_COMMAND]->add_window ("locator", 0);
-  standard_layouts[DISASSEM_COMMAND]->add_window ("cmd", 1);
+  gdb::unique_xmalloc_ptr<char> doc (xstrprintf (_("Apply the \"%s\" layout"),
+                                                name));
 
-  standard_layouts[SRC_DATA_COMMAND] = new tui_layout_split ();
-  standard_layouts[SRC_DATA_COMMAND]->add_window ("regs", 1);
-  standard_layouts[SRC_DATA_COMMAND]->add_window ("src", 1);
-  standard_layouts[SRC_DATA_COMMAND]->add_window ("locator", 0);
-  standard_layouts[SRC_DATA_COMMAND]->add_window ("cmd", 1);
+  cmd = add_cmd (name, class_tui, nullptr, doc.get (), &layout_list);
+  set_cmd_context (cmd, layout);
+  /* There is no API to set this.  */
+  cmd->func = tui_apply_layout;
+  cmd->destroyer = destroy_layout;
+  cmd->doc_allocated = 1;
+  doc.release ();
+  layouts.emplace_back (layout);
+}
 
-  standard_layouts[DISASSEM_DATA_COMMAND] = new tui_layout_split ();
-  standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("regs", 1);
-  standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("asm", 1);
-  standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("locator", 0);
-  standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("cmd", 1);
+/* Initialize the standard layouts.  */
 
-  standard_layouts[SRC_DISASSEM_COMMAND] = new tui_layout_split ();
-  standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("src", 1);
-  standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("asm", 1);
-  standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("locator", 0);
-  standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("cmd", 1);
+static void
+initialize_layouts ()
+{
+  tui_layout_split *layout;
+
+  layout = new tui_layout_split ();
+  layout->add_window ("src", 2);
+  layout->add_window ("status", 0);
+  layout->add_window ("cmd", 1);
+  add_layout_command ("src", layout);
+
+  layout = new tui_layout_split ();
+  layout->add_window ("asm", 2);
+  layout->add_window ("status", 0);
+  layout->add_window ("cmd", 1);
+  add_layout_command ("asm", layout);
+
+  layout = new tui_layout_split ();
+  layout->add_window ("src", 1);
+  layout->add_window ("asm", 1);
+  layout->add_window ("status", 0);
+  layout->add_window ("cmd", 1);
+  add_layout_command ("split", layout);
+
+  layout = new tui_layout_split ();
+  layout->add_window ("regs", 1);
+  layout->add_window ("src", 1);
+  layout->add_window ("status", 0);
+  layout->add_window ("cmd", 1);
+  layouts.emplace_back (layout);
+  src_regs_layout = layout;
+
+  layout = new tui_layout_split ();
+  layout->add_window ("regs", 1);
+  layout->add_window ("asm", 1);
+  layout->add_window ("status", 0);
+  layout->add_window ("cmd", 1);
+  layouts.emplace_back (layout);
+  asm_regs_layout = layout;
 }
 
 \f
 
+/* Base command for "layout".  */
+
+static void
+tui_layout_command (const char *layout_name, int from_tty)
+{
+  help_list (layout_list, "layout ", all_commands, gdb_stdout);
+}
+
 /* Function to initialize gdb commands, for tui window layout
    manipulation.  */
 
@@ -845,22 +792,20 @@ void _initialize_tui_layout ();
 void
 _initialize_tui_layout ()
 {
-  struct cmd_list_element *cmd;
-
-  cmd = add_com ("layout", class_tui, tui_layout_command, _("\
+  add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\
 Change the layout of windows.\n\
-Usage: layout prev | next | LAYOUT-NAME\n\
-Layout names are:\n\
-   src   : Displays source and command windows.\n\
-   asm   : Displays disassembly and command windows.\n\
-   split : Displays source, disassembly and command windows.\n\
-   regs  : Displays register window. If existing layout\n\
-           is source/command or assembly/command, the \n\
-           register window is displayed. If the\n\
-           source/assembly/command (split) is displayed, \n\
-           the register window is displayed with \n\
-           the window that has current logical focus."));
-  set_cmd_completer (cmd, layout_completer);
+Usage: layout prev | next | LAYOUT-NAME"),
+                 &layout_list, "layout ", 0, &cmdlist);
+
+  add_cmd ("next", class_tui, tui_next_layout_command,
+          _("Apply the next TUI layout"),
+          &layout_list);
+  add_cmd ("prev", class_tui, tui_prev_layout_command,
+          _("Apply the previous TUI layout"),
+          &layout_list);
+  add_cmd ("regs", class_tui, tui_regs_layout_command,
+          _("Apply the TUI register layout"),
+          &layout_list);
 
   initialize_layouts ();
 }
index 05089ab8fffc7551e11c8c90840d62a817932a84..98bd548aaee9d3db1db57b262eef828bb8d78a96 100644 (file)
@@ -68,6 +68,10 @@ public:
      and the window being passed in here.  */
   virtual void remove_windows (const char *name) = 0;
 
+  /* Replace the window named NAME in the layout with the window named
+     NEW_WINDOW.  */
+  virtual void replace_window (const char *name, const char *new_window) = 0;
+
   /* The most recent space allocation.  */
   int x = 0;
   int y = 0;
@@ -114,6 +118,8 @@ public:
   {
   }
 
+  void replace_window (const char *name, const char *new_window) override;
+
 protected:
 
   void get_sizes (int *min_height, int *max_height) override;
@@ -159,6 +165,8 @@ public:
 
   void remove_windows (const char *name) override;
 
+  void replace_window (const char *name, const char *new_window) override;
+
 protected:
 
   void get_sizes (int *min_height, int *max_height) override;
@@ -189,7 +197,8 @@ private:
    way.  */
 extern void tui_add_win_to_layout (enum tui_win_type);
 
-extern void tui_set_layout (enum tui_layout_type);
+/* Set the initial layout.  */
+extern void tui_set_initial_layout ();
 
 /* Switch to the next layout.  */
 extern void tui_next_layout ();
index 185ae26f698c0318eb09f724bfe74b9e6838e539..8cc002169e883a04dce308c52133a2dbe2330869 100644 (file)
@@ -385,7 +385,7 @@ window_name_completer (completion_tracker &tracker,
   /* If no windows are considered visible then the TUI has not yet been
      initialized.  But still "focus src" and "focus cmd" will work because
      invoking the focus command will entail initializing the TUI which sets the
-     default layout to SRC_COMMAND.  */
+     default layout to "src".  */
   if (completion_name_vec.empty ())
     {
       completion_name_vec.push_back (SRC_NAME);
index 280af8acce9cbc45a84f4fea4e9edcf34d22e5e9..77d7c9068373a6fc7c58b8376e03e80a0e22334f 100644 (file)
@@ -422,7 +422,7 @@ tui_enable (void)
       def_prog_mode ();
 
       tui_show_frame_info (0);
-      tui_set_layout (SRC_COMMAND);
+      tui_set_initial_layout ();
       tui_set_win_focus_to (TUI_SRC_WIN);
       keypad (TUI_CMD_WIN->handle.get (), TRUE);
       wrefresh (TUI_CMD_WIN->handle.get ());