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