Home | History | Annotate | Line # | Download | only in tui
tui-regs.c revision 1.9
      1  1.1  christos /* TUI display registers in window.
      2  1.1  christos 
      3  1.9  christos    Copyright (C) 1998-2020 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    Contributed by Hewlett-Packard Company.
      6  1.1  christos 
      7  1.1  christos    This file is part of GDB.
      8  1.1  christos 
      9  1.1  christos    This program is free software; you can redistribute it and/or modify
     10  1.1  christos    it under the terms of the GNU General Public License as published by
     11  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12  1.1  christos    (at your option) any later version.
     13  1.1  christos 
     14  1.1  christos    This program is distributed in the hope that it will be useful,
     15  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  1.1  christos    GNU General Public License for more details.
     18  1.1  christos 
     19  1.1  christos    You should have received a copy of the GNU General Public License
     20  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21  1.1  christos 
     22  1.1  christos #include "defs.h"
     23  1.1  christos #include "arch-utils.h"
     24  1.1  christos #include "tui/tui.h"
     25  1.1  christos #include "tui/tui-data.h"
     26  1.1  christos #include "symtab.h"
     27  1.1  christos #include "gdbtypes.h"
     28  1.1  christos #include "gdbcmd.h"
     29  1.1  christos #include "frame.h"
     30  1.1  christos #include "regcache.h"
     31  1.1  christos #include "inferior.h"
     32  1.1  christos #include "target.h"
     33  1.1  christos #include "tui/tui-layout.h"
     34  1.1  christos #include "tui/tui-win.h"
     35  1.1  christos #include "tui/tui-wingeneral.h"
     36  1.1  christos #include "tui/tui-file.h"
     37  1.1  christos #include "tui/tui-regs.h"
     38  1.3  christos #include "tui/tui-io.h"
     39  1.1  christos #include "reggroups.h"
     40  1.1  christos #include "valprint.h"
     41  1.5  christos #include "completer.h"
     42  1.1  christos 
     43  1.1  christos #include "gdb_curses.h"
     44  1.1  christos 
     45  1.9  christos /* A subclass of string_file that expands tab characters.  */
     46  1.9  christos class tab_expansion_file : public string_file
     47  1.9  christos {
     48  1.9  christos public:
     49  1.1  christos 
     50  1.9  christos   tab_expansion_file () = default;
     51  1.1  christos 
     52  1.9  christos   void write (const char *buf, long length_buf) override;
     53  1.1  christos 
     54  1.9  christos private:
     55  1.1  christos 
     56  1.9  christos   int m_column = 0;
     57  1.9  christos };
     58  1.1  christos 
     59  1.9  christos void
     60  1.9  christos tab_expansion_file::write (const char *buf, long length_buf)
     61  1.9  christos {
     62  1.9  christos   for (long i = 0; i < length_buf; ++i)
     63  1.9  christos     {
     64  1.9  christos       if (buf[i] == '\t')
     65  1.9  christos 	{
     66  1.9  christos 	  do
     67  1.9  christos 	    {
     68  1.9  christos 	      string_file::write (" ", 1);
     69  1.9  christos 	      ++m_column;
     70  1.9  christos 	    }
     71  1.9  christos 	  while ((m_column % 8) != 0);
     72  1.9  christos 	}
     73  1.9  christos       else
     74  1.9  christos 	{
     75  1.9  christos 	  string_file::write (&buf[i], 1);
     76  1.9  christos 	  if (buf[i] == '\n')
     77  1.9  christos 	    m_column = 0;
     78  1.9  christos 	  else
     79  1.9  christos 	    ++m_column;
     80  1.9  christos 	}
     81  1.9  christos     }
     82  1.9  christos }
     83  1.1  christos 
     84  1.9  christos /* Get the register from the frame and return a printable
     85  1.9  christos    representation of it.  */
     86  1.1  christos 
     87  1.9  christos static std::string
     88  1.9  christos tui_register_format (struct frame_info *frame, int regnum)
     89  1.1  christos {
     90  1.9  christos   struct gdbarch *gdbarch = get_frame_arch (frame);
     91  1.9  christos 
     92  1.9  christos   /* Expand tabs into spaces, since ncurses on MS-Windows doesn't.  */
     93  1.9  christos   tab_expansion_file stream;
     94  1.9  christos 
     95  1.9  christos   scoped_restore save_pagination
     96  1.9  christos     = make_scoped_restore (&pagination_enabled, 0);
     97  1.9  christos   scoped_restore save_stdout
     98  1.9  christos     = make_scoped_restore (&gdb_stdout, &stream);
     99  1.9  christos 
    100  1.9  christos   gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
    101  1.1  christos 
    102  1.9  christos   /* Remove the possible \n.  */
    103  1.9  christos   std::string &str = stream.string ();
    104  1.9  christos   if (!str.empty () && str.back () == '\n')
    105  1.9  christos     str.resize (str.size () - 1);
    106  1.9  christos 
    107  1.9  christos   return str;
    108  1.9  christos }
    109  1.9  christos 
    110  1.9  christos /* Get the register value from the given frame and format it for the
    111  1.9  christos    display.  When changep is set, check if the new register value has
    112  1.9  christos    changed with respect to the previous call.  */
    113  1.9  christos static void
    114  1.9  christos tui_get_register (struct frame_info *frame,
    115  1.9  christos                   struct tui_data_item_window *data,
    116  1.9  christos 		  int regnum, bool *changedp)
    117  1.9  christos {
    118  1.9  christos   if (changedp)
    119  1.9  christos     *changedp = false;
    120  1.9  christos   if (target_has_registers)
    121  1.1  christos     {
    122  1.9  christos       std::string new_content = tui_register_format (frame, regnum);
    123  1.9  christos 
    124  1.9  christos       if (changedp != NULL && data->content != new_content)
    125  1.9  christos 	*changedp = true;
    126  1.9  christos 
    127  1.9  christos       data->content = std::move (new_content);
    128  1.1  christos     }
    129  1.9  christos }
    130  1.9  christos 
    131  1.9  christos /* See tui-regs.h.  */
    132  1.9  christos 
    133  1.9  christos int
    134  1.9  christos tui_data_window::last_regs_line_no () const
    135  1.9  christos {
    136  1.9  christos   int num_lines = m_regs_content.size () / m_regs_column_count;
    137  1.9  christos   if (m_regs_content.size () % m_regs_column_count)
    138  1.9  christos     num_lines++;
    139  1.1  christos   return num_lines;
    140  1.1  christos }
    141  1.1  christos 
    142  1.9  christos /* See tui-regs.h.  */
    143  1.1  christos 
    144  1.1  christos int
    145  1.9  christos tui_data_window::line_from_reg_element_no (int element_no) const
    146  1.1  christos {
    147  1.9  christos   if (element_no < m_regs_content.size ())
    148  1.1  christos     {
    149  1.1  christos       int i, line = (-1);
    150  1.1  christos 
    151  1.1  christos       i = 1;
    152  1.1  christos       while (line == (-1))
    153  1.1  christos 	{
    154  1.9  christos 	  if (element_no < m_regs_column_count * i)
    155  1.1  christos 	    line = i - 1;
    156  1.1  christos 	  else
    157  1.1  christos 	    i++;
    158  1.1  christos 	}
    159  1.1  christos 
    160  1.1  christos       return line;
    161  1.1  christos     }
    162  1.1  christos   else
    163  1.1  christos     return (-1);
    164  1.1  christos }
    165  1.1  christos 
    166  1.9  christos /* See tui-regs.h.  */
    167  1.1  christos 
    168  1.1  christos int
    169  1.9  christos tui_data_window::first_reg_element_no_inline (int line_no) const
    170  1.1  christos {
    171  1.9  christos   if (line_no * m_regs_column_count <= m_regs_content.size ())
    172  1.9  christos     return ((line_no + 1) * m_regs_column_count) - m_regs_column_count;
    173  1.1  christos   else
    174  1.1  christos     return (-1);
    175  1.1  christos }
    176  1.1  christos 
    177  1.1  christos /* Show the registers of the given group in the data window
    178  1.1  christos    and refresh the window.  */
    179  1.1  christos void
    180  1.9  christos tui_data_window::show_registers (struct reggroup *group)
    181  1.1  christos {
    182  1.1  christos   if (group == 0)
    183  1.1  christos     group = general_reggroup;
    184  1.1  christos 
    185  1.1  christos   if (target_has_registers && target_has_stack && target_has_memory)
    186  1.1  christos     {
    187  1.9  christos       show_register_group (group, get_selected_frame (NULL),
    188  1.9  christos 			   group == m_current_group);
    189  1.9  christos 
    190  1.9  christos       /* Clear all notation of changed values.  */
    191  1.9  christos       for (auto &&data_item_win : m_regs_content)
    192  1.9  christos 	data_item_win.highlight = false;
    193  1.9  christos       m_current_group = group;
    194  1.1  christos     }
    195  1.9  christos   else
    196  1.1  christos     {
    197  1.9  christos       m_current_group = 0;
    198  1.9  christos       m_regs_content.clear ();
    199  1.1  christos     }
    200  1.1  christos 
    201  1.9  christos   rerender ();
    202  1.1  christos }
    203  1.1  christos 
    204  1.1  christos 
    205  1.1  christos /* Set the data window to display the registers of the register group
    206  1.1  christos    using the given frame.  Values are refreshed only when
    207  1.9  christos    refresh_values_only is true.  */
    208  1.1  christos 
    209  1.9  christos void
    210  1.9  christos tui_data_window::show_register_group (struct reggroup *group,
    211  1.9  christos 				      struct frame_info *frame,
    212  1.9  christos 				      bool refresh_values_only)
    213  1.1  christos {
    214  1.1  christos   struct gdbarch *gdbarch = get_frame_arch (frame);
    215  1.1  christos   int nr_regs;
    216  1.1  christos   int regnum, pos;
    217  1.1  christos 
    218  1.1  christos   /* Make a new title showing which group we display.  */
    219  1.9  christos   title = string_printf ("Register group: %s", reggroup_name (group));
    220  1.1  christos 
    221  1.1  christos   /* See how many registers must be displayed.  */
    222  1.1  christos   nr_regs = 0;
    223  1.8  christos   for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
    224  1.1  christos     {
    225  1.1  christos       const char *name;
    226  1.1  christos 
    227  1.1  christos       /* Must be in the group.  */
    228  1.1  christos       if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
    229  1.1  christos 	continue;
    230  1.1  christos 
    231  1.1  christos       /* If the register name is empty, it is undefined for this
    232  1.1  christos 	 processor, so don't display anything.  */
    233  1.1  christos       name = gdbarch_register_name (gdbarch, regnum);
    234  1.1  christos       if (name == 0 || *name == '\0')
    235  1.1  christos 	continue;
    236  1.1  christos 
    237  1.1  christos       nr_regs++;
    238  1.1  christos     }
    239  1.1  christos 
    240  1.9  christos   m_regs_content.resize (nr_regs);
    241  1.9  christos 
    242  1.9  christos   /* Now set the register names and values.  */
    243  1.9  christos   pos = 0;
    244  1.9  christos   for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
    245  1.1  christos     {
    246  1.9  christos       struct tui_data_item_window *data_item_win;
    247  1.9  christos       const char *name;
    248  1.9  christos 
    249  1.9  christos       /* Must be in the group.  */
    250  1.9  christos       if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
    251  1.9  christos 	continue;
    252  1.9  christos 
    253  1.9  christos       /* If the register name is empty, it is undefined for this
    254  1.9  christos 	 processor, so don't display anything.  */
    255  1.9  christos       name = gdbarch_register_name (gdbarch, regnum);
    256  1.9  christos       if (name == 0 || *name == '\0')
    257  1.9  christos 	continue;
    258  1.9  christos 
    259  1.9  christos       data_item_win = &m_regs_content[pos];
    260  1.9  christos       if (!refresh_values_only)
    261  1.9  christos 	{
    262  1.9  christos 	  data_item_win->regno = regnum;
    263  1.9  christos 	  data_item_win->highlight = false;
    264  1.9  christos 	}
    265  1.9  christos       tui_get_register (frame, data_item_win, regnum, 0);
    266  1.9  christos       pos++;
    267  1.1  christos     }
    268  1.9  christos }
    269  1.9  christos 
    270  1.9  christos /* See tui-regs.h.  */
    271  1.1  christos 
    272  1.9  christos void
    273  1.9  christos tui_data_window::display_registers_from (int start_element_no)
    274  1.9  christos {
    275  1.9  christos   int max_len = 0;
    276  1.9  christos   for (auto &&data_item_win : m_regs_content)
    277  1.1  christos     {
    278  1.9  christos       int len = data_item_win.content.size ();
    279  1.9  christos 
    280  1.9  christos       if (len > max_len)
    281  1.9  christos 	max_len = len;
    282  1.1  christos     }
    283  1.9  christos   m_item_width = max_len + 1;
    284  1.9  christos   int i = start_element_no;
    285  1.1  christos 
    286  1.9  christos   m_regs_column_count = (width - 2) / m_item_width;
    287  1.9  christos   if (m_regs_column_count == 0)
    288  1.9  christos     m_regs_column_count = 1;
    289  1.9  christos   m_item_width = (width - 2) / m_regs_column_count;
    290  1.9  christos 
    291  1.9  christos   /* Now create each data "sub" window, and write the display into
    292  1.9  christos      it.  */
    293  1.9  christos   int cur_y = 1;
    294  1.9  christos   while (i < m_regs_content.size () && cur_y <= height - 2)
    295  1.1  christos     {
    296  1.9  christos       for (int j = 0;
    297  1.9  christos 	   j < m_regs_column_count && i < m_regs_content.size ();
    298  1.9  christos 	   j++)
    299  1.1  christos 	{
    300  1.9  christos 	  /* Create the window if necessary.  */
    301  1.9  christos 	  m_regs_content[i].x = (m_item_width * j) + 1;
    302  1.9  christos 	  m_regs_content[i].y = cur_y;
    303  1.9  christos 	  m_regs_content[i].visible = true;
    304  1.9  christos 	  m_regs_content[i].rerender (handle.get (), m_item_width);
    305  1.9  christos 	  i++;		/* Next register.  */
    306  1.1  christos 	}
    307  1.9  christos       cur_y++;		/* Next row.  */
    308  1.9  christos     }
    309  1.9  christos }
    310  1.1  christos 
    311  1.9  christos /* See tui-regs.h.  */
    312  1.9  christos 
    313  1.9  christos void
    314  1.9  christos tui_data_window::display_reg_element_at_line (int start_element_no,
    315  1.9  christos 					      int start_line_no)
    316  1.9  christos {
    317  1.9  christos   int element_no = start_element_no;
    318  1.9  christos 
    319  1.9  christos   if (start_element_no != 0 && start_line_no != 0)
    320  1.9  christos     {
    321  1.9  christos       int last_line_no, first_line_on_last_page;
    322  1.1  christos 
    323  1.9  christos       last_line_no = last_regs_line_no ();
    324  1.9  christos       first_line_on_last_page = last_line_no - (height - 2);
    325  1.9  christos       if (first_line_on_last_page < 0)
    326  1.9  christos 	first_line_on_last_page = 0;
    327  1.1  christos 
    328  1.9  christos       /* If the element_no causes us to scroll past the end of the
    329  1.9  christos 	 registers, adjust what element to really start the
    330  1.9  christos 	 display at.  */
    331  1.9  christos       if (start_line_no > first_line_on_last_page)
    332  1.9  christos 	element_no = first_reg_element_no_inline (first_line_on_last_page);
    333  1.1  christos     }
    334  1.9  christos   display_registers_from (element_no);
    335  1.1  christos }
    336  1.1  christos 
    337  1.9  christos /* See tui-regs.h.  */
    338  1.1  christos 
    339  1.9  christos int
    340  1.9  christos tui_data_window::display_registers_from_line (int line_no)
    341  1.1  christos {
    342  1.9  christos   int element_no;
    343  1.9  christos 
    344  1.9  christos   if (line_no < 0)
    345  1.9  christos     line_no = 0;
    346  1.9  christos   else
    347  1.1  christos     {
    348  1.9  christos       /* Make sure that we don't display off the end of the
    349  1.9  christos 	 registers.  */
    350  1.9  christos       if (line_no >= last_regs_line_no ())
    351  1.9  christos 	{
    352  1.9  christos 	  line_no = line_from_reg_element_no (m_regs_content.size () - 1);
    353  1.9  christos 	  if (line_no < 0)
    354  1.9  christos 	    line_no = 0;
    355  1.9  christos 	}
    356  1.9  christos     }
    357  1.9  christos 
    358  1.9  christos   element_no = first_reg_element_no_inline (line_no);
    359  1.9  christos   if (element_no < m_regs_content.size ())
    360  1.9  christos     display_reg_element_at_line (element_no, line_no);
    361  1.9  christos   else
    362  1.9  christos     line_no = (-1);
    363  1.9  christos 
    364  1.9  christos   return line_no;
    365  1.9  christos }
    366  1.1  christos 
    367  1.1  christos 
    368  1.9  christos /* Answer the index first element displayed.  If none are displayed,
    369  1.9  christos    then return (-1).  */
    370  1.9  christos int
    371  1.9  christos tui_data_window::first_data_item_displayed ()
    372  1.9  christos {
    373  1.9  christos   for (int i = 0; i < m_regs_content.size (); i++)
    374  1.9  christos     {
    375  1.9  christos       if (m_regs_content[i].visible)
    376  1.9  christos 	return i;
    377  1.1  christos     }
    378  1.9  christos 
    379  1.9  christos   return -1;
    380  1.1  christos }
    381  1.1  christos 
    382  1.9  christos /* See tui-regs.h.  */
    383  1.9  christos 
    384  1.9  christos void
    385  1.9  christos tui_data_window::delete_data_content_windows ()
    386  1.9  christos {
    387  1.9  christos   for (auto &win : m_regs_content)
    388  1.9  christos     win.visible = false;
    389  1.9  christos }
    390  1.1  christos 
    391  1.1  christos 
    392  1.9  christos void
    393  1.9  christos tui_data_window::erase_data_content (const char *prompt)
    394  1.1  christos {
    395  1.9  christos   werase (handle.get ());
    396  1.9  christos   check_and_display_highlight_if_needed ();
    397  1.9  christos   if (prompt != NULL)
    398  1.1  christos     {
    399  1.9  christos       int half_width = (width - 2) / 2;
    400  1.9  christos       int x_pos;
    401  1.1  christos 
    402  1.9  christos       if (strlen (prompt) >= half_width)
    403  1.9  christos 	x_pos = 1;
    404  1.1  christos       else
    405  1.9  christos 	x_pos = half_width - strlen (prompt);
    406  1.9  christos       mvwaddstr (handle.get (), (height / 2), x_pos, (char *) prompt);
    407  1.9  christos     }
    408  1.9  christos   tui_wrefresh (handle.get ());
    409  1.9  christos }
    410  1.9  christos 
    411  1.9  christos /* See tui-regs.h.  */
    412  1.1  christos 
    413  1.9  christos void
    414  1.9  christos tui_data_window::rerender ()
    415  1.9  christos {
    416  1.9  christos   if (m_regs_content.empty ())
    417  1.9  christos     erase_data_content (_("[ Register Values Unavailable ]"));
    418  1.9  christos   else
    419  1.9  christos     {
    420  1.9  christos       erase_data_content (NULL);
    421  1.9  christos       delete_data_content_windows ();
    422  1.9  christos       display_registers_from (0);
    423  1.9  christos     }
    424  1.9  christos }
    425  1.9  christos 
    426  1.9  christos 
    427  1.9  christos /* Scroll the data window vertically forward or backward.  */
    428  1.9  christos void
    429  1.9  christos tui_data_window::do_scroll_vertical (int num_to_scroll)
    430  1.9  christos {
    431  1.9  christos   int first_element_no;
    432  1.9  christos   int first_line = (-1);
    433  1.1  christos 
    434  1.9  christos   first_element_no = first_data_item_displayed ();
    435  1.9  christos   if (first_element_no < m_regs_content.size ())
    436  1.9  christos     first_line = line_from_reg_element_no (first_element_no);
    437  1.9  christos   else
    438  1.9  christos     { /* Calculate the first line from the element number which is in
    439  1.9  christos         the general data content.  */
    440  1.1  christos     }
    441  1.1  christos 
    442  1.9  christos   if (first_line >= 0)
    443  1.9  christos     {
    444  1.9  christos       first_line += num_to_scroll;
    445  1.9  christos       erase_data_content (NULL);
    446  1.9  christos       delete_data_content_windows ();
    447  1.9  christos       display_registers_from_line (first_line);
    448  1.9  christos     }
    449  1.1  christos }
    450  1.1  christos 
    451  1.1  christos /* This function check all displayed registers for changes in values,
    452  1.1  christos    given a particular frame.  If the values have changed, they are
    453  1.1  christos    updated with the new value and highlighted.  */
    454  1.1  christos void
    455  1.9  christos tui_data_window::check_register_values (struct frame_info *frame)
    456  1.1  christos {
    457  1.9  christos   if (m_regs_content.empty ())
    458  1.9  christos     show_registers (m_current_group);
    459  1.9  christos   else
    460  1.1  christos     {
    461  1.9  christos       for (auto &&data_item_win : m_regs_content)
    462  1.9  christos 	{
    463  1.9  christos 	  int was_hilighted;
    464  1.9  christos 
    465  1.9  christos 	  was_hilighted = data_item_win.highlight;
    466  1.1  christos 
    467  1.9  christos 	  tui_get_register (frame, &data_item_win,
    468  1.9  christos 			    data_item_win.regno,
    469  1.9  christos 			    &data_item_win.highlight);
    470  1.1  christos 
    471  1.9  christos 	  if (data_item_win.highlight || was_hilighted)
    472  1.9  christos 	    data_item_win.rerender (handle.get (), m_item_width);
    473  1.1  christos 	}
    474  1.1  christos     }
    475  1.9  christos 
    476  1.9  christos   tui_wrefresh (handle.get ());
    477  1.1  christos }
    478  1.1  christos 
    479  1.1  christos /* Display a register in a window.  If hilite is TRUE, then the value
    480  1.1  christos    will be displayed in reverse video.  */
    481  1.9  christos void
    482  1.9  christos tui_data_item_window::rerender (WINDOW *handle, int field_width)
    483  1.1  christos {
    484  1.9  christos   if (highlight)
    485  1.9  christos     /* We ignore the return value, casting it to void in order to avoid
    486  1.9  christos        a compiler warning.  The warning itself was introduced by a patch
    487  1.9  christos        to ncurses 5.7 dated 2009-08-29, changing this macro to expand
    488  1.9  christos        to code that causes the compiler to generate an unused-value
    489  1.9  christos        warning.  */
    490  1.9  christos     (void) wstandout (handle);
    491  1.9  christos 
    492  1.9  christos   mvwaddnstr (handle, y, x, content.c_str (), field_width - 1);
    493  1.9  christos   waddstr (handle, n_spaces (field_width - content.size ()));
    494  1.1  christos 
    495  1.9  christos   if (highlight)
    496  1.9  christos     /* We ignore the return value, casting it to void in order to avoid
    497  1.9  christos        a compiler warning.  The warning itself was introduced by a patch
    498  1.9  christos        to ncurses 5.7 dated 2009-08-29, changing this macro to expand
    499  1.9  christos        to code that causes the compiler to generate an unused-value
    500  1.9  christos        warning.  */
    501  1.9  christos     (void) wstandend (handle);
    502  1.1  christos }
    503  1.1  christos 
    504  1.5  christos /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
    505  1.5  christos    around behaviour.  Returns the next register group, or NULL if the
    506  1.5  christos    register window is not currently being displayed.  */
    507  1.5  christos 
    508  1.5  christos static struct reggroup *
    509  1.9  christos tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
    510  1.1  christos {
    511  1.5  christos   struct reggroup *group = NULL;
    512  1.1  christos 
    513  1.9  christos   if (current_group != NULL)
    514  1.1  christos     {
    515  1.9  christos       group = reggroup_next (gdbarch, current_group);
    516  1.5  christos       if (group == NULL)
    517  1.5  christos         group = reggroup_next (gdbarch, NULL);
    518  1.1  christos     }
    519  1.5  christos   return group;
    520  1.1  christos }
    521  1.1  christos 
    522  1.5  christos /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
    523  1.5  christos    around behaviour.  Returns the previous register group, or NULL if the
    524  1.5  christos    register window is not currently being displayed.  */
    525  1.5  christos 
    526  1.5  christos static struct reggroup *
    527  1.9  christos tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
    528  1.1  christos {
    529  1.5  christos   struct reggroup *group = NULL;
    530  1.5  christos 
    531  1.9  christos   if (current_group != NULL)
    532  1.5  christos     {
    533  1.9  christos       group = reggroup_prev (gdbarch, current_group);
    534  1.5  christos       if (group == NULL)
    535  1.5  christos 	group = reggroup_prev (gdbarch, NULL);
    536  1.5  christos     }
    537  1.5  christos   return group;
    538  1.1  christos }
    539  1.1  christos 
    540  1.5  christos /* Implement the 'tui reg' command.  Changes the register group displayed
    541  1.5  christos    in the tui register window.  Displays the tui register window if it is
    542  1.5  christos    not already on display.  */
    543  1.5  christos 
    544  1.1  christos static void
    545  1.8  christos tui_reg_command (const char *args, int from_tty)
    546  1.1  christos {
    547  1.5  christos   struct gdbarch *gdbarch = get_current_arch ();
    548  1.5  christos 
    549  1.5  christos   if (args != NULL)
    550  1.5  christos     {
    551  1.5  christos       struct reggroup *group, *match = NULL;
    552  1.5  christos       size_t len = strlen (args);
    553  1.5  christos 
    554  1.5  christos       /* Make sure the curses mode is enabled.  */
    555  1.5  christos       tui_enable ();
    556  1.5  christos 
    557  1.9  christos       tui_suppress_output suppress;
    558  1.9  christos 
    559  1.5  christos       /* Make sure the register window is visible.  If not, select an
    560  1.5  christos 	 appropriate layout.  We need to do this before trying to run the
    561  1.5  christos 	 'next' or 'prev' commands.  */
    562  1.9  christos       if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
    563  1.9  christos 	tui_regs_layout ();
    564  1.5  christos 
    565  1.9  christos       struct reggroup *current_group = TUI_DATA_WIN->get_current_group ();
    566  1.5  christos       if (strncmp (args, "next", len) == 0)
    567  1.9  christos 	match = tui_reg_next (current_group, gdbarch);
    568  1.5  christos       else if (strncmp (args, "prev", len) == 0)
    569  1.9  christos 	match = tui_reg_prev (current_group, gdbarch);
    570  1.5  christos 
    571  1.5  christos       /* This loop matches on the initial part of a register group
    572  1.5  christos 	 name.  If this initial part in ARGS matches only one register
    573  1.5  christos 	 group then the switch is made.  */
    574  1.5  christos       for (group = reggroup_next (gdbarch, NULL);
    575  1.5  christos 	   group != NULL;
    576  1.5  christos 	   group = reggroup_next (gdbarch, group))
    577  1.5  christos 	{
    578  1.5  christos 	  if (strncmp (reggroup_name (group), args, len) == 0)
    579  1.5  christos 	    {
    580  1.5  christos 	      if (match != NULL)
    581  1.5  christos 		error (_("ambiguous register group name '%s'"), args);
    582  1.5  christos 	      match = group;
    583  1.5  christos 	    }
    584  1.5  christos 	}
    585  1.5  christos 
    586  1.5  christos       if (match == NULL)
    587  1.5  christos 	error (_("unknown register group '%s'"), args);
    588  1.5  christos 
    589  1.9  christos       TUI_DATA_WIN->show_registers (match);
    590  1.5  christos     }
    591  1.5  christos   else
    592  1.5  christos     {
    593  1.5  christos       struct reggroup *group;
    594  1.5  christos       int first;
    595  1.5  christos 
    596  1.5  christos       printf_unfiltered (_("\"tui reg\" must be followed by the name of "
    597  1.5  christos 			   "either a register group,\nor one of 'next' "
    598  1.5  christos 			   "or 'prev'.  Known register groups are:\n"));
    599  1.5  christos 
    600  1.5  christos       for (first = 1, group = reggroup_next (gdbarch, NULL);
    601  1.5  christos 	   group != NULL;
    602  1.5  christos 	   first = 0, group = reggroup_next (gdbarch, group))
    603  1.5  christos 	{
    604  1.5  christos 	  if (!first)
    605  1.5  christos 	    printf_unfiltered (", ");
    606  1.5  christos 	  printf_unfiltered ("%s", reggroup_name (group));
    607  1.5  christos 	}
    608  1.5  christos 
    609  1.5  christos       printf_unfiltered ("\n");
    610  1.5  christos     }
    611  1.1  christos }
    612  1.1  christos 
    613  1.5  christos /* Complete names of register groups, and add the special "prev" and "next"
    614  1.5  christos    names.  */
    615  1.5  christos 
    616  1.8  christos static void
    617  1.5  christos tui_reggroup_completer (struct cmd_list_element *ignore,
    618  1.8  christos 			completion_tracker &tracker,
    619  1.5  christos 			const char *text, const char *word)
    620  1.1  christos {
    621  1.9  christos   static const char * const extra[] = { "next", "prev", NULL };
    622  1.5  christos 
    623  1.8  christos   reggroup_completer (ignore, tracker, text, word);
    624  1.1  christos 
    625  1.9  christos   complete_on_enum (tracker, extra, text, word);
    626  1.1  christos }
    627  1.1  christos 
    628  1.9  christos void _initialize_tui_regs ();
    629  1.1  christos void
    630  1.9  christos _initialize_tui_regs ()
    631  1.1  christos {
    632  1.5  christos   struct cmd_list_element **tuicmd, *cmd;
    633  1.1  christos 
    634  1.1  christos   tuicmd = tui_get_cmd_list ();
    635  1.1  christos 
    636  1.5  christos   cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
    637  1.9  christos TUI command to control the register window.\n\
    638  1.9  christos Usage: tui reg NAME\n\
    639  1.9  christos NAME is the name of the register group to display"), tuicmd);
    640  1.5  christos   set_cmd_completer (cmd, tui_reggroup_completer);
    641  1.1  christos }
    642