]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tui/tui-regs.c
Change tui_data_item_window::content to be a unique_xmalloc_ptr
[thirdparty/binutils-gdb.git] / gdb / tui / tui-regs.c
CommitLineData
f377b406 1/* TUI display registers in window.
f33c6cbf 2
42a4f53d 3 Copyright (C) 1998-2019 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
41bcff7f 45static void tui_display_register (struct tui_data_item_window *data);
c906108c 46
e80cd204
TT
47static void tui_show_register_group (tui_data_window *win_info,
48 struct reggroup *group,
21e1c91e
TT
49 struct frame_info *frame,
50 int refresh_values_only);
5eccfcc2 51
1a4f81dd
TT
52/* Get the register from the frame and return a printable
53 representation of it. */
54
b9ad3686 55static gdb::unique_xmalloc_ptr<char>
1a4f81dd
TT
56tui_register_format (struct frame_info *frame, int regnum)
57{
58 struct gdbarch *gdbarch = get_frame_arch (frame);
5eccfcc2 59
1a4f81dd
TT
60 string_file stream;
61
62 scoped_restore save_pagination
63 = make_scoped_restore (&pagination_enabled, 0);
64 scoped_restore save_stdout
65 = make_scoped_restore (&gdb_stdout, &stream);
66
67 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
68
69 /* Remove the possible \n. */
70 std::string &str = stream.string ();
71 if (!str.empty () && str.back () == '\n')
72 str.resize (str.size () - 1);
73
74 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
b9ad3686 75 return tui_expand_tabs (str.c_str ());
1a4f81dd
TT
76}
77
78/* Get the register value from the given frame and format it for the
79 display. When changep is set, check if the new register value has
80 changed with respect to the previous call. */
81static void
82tui_get_register (struct frame_info *frame,
83 struct tui_data_item_window *data,
84 int regnum, bool *changedp)
85{
86 if (changedp)
87 *changedp = false;
88 if (target_has_registers)
89 {
b9ad3686
TT
90 gdb::unique_xmalloc_ptr<char> new_content
91 = tui_register_format (frame, regnum);
1a4f81dd
TT
92
93 if (changedp != NULL
b9ad3686 94 && strcmp (data->content.get (), new_content.get ()) != 0)
1a4f81dd
TT
95 *changedp = true;
96
b9ad3686 97 data->content = std::move (new_content);
1a4f81dd
TT
98 }
99}
96bd6233
TT
100
101/* See tui-regs.h. */
102
c906108c 103int
0b5ec218 104tui_data_window::last_regs_line_no () const
c906108c 105{
d02c80cd 106 int num_lines = (-1);
c906108c 107
0b5ec218 108 if (!regs_content.empty ())
c906108c 109 {
0b5ec218
TT
110 num_lines = regs_content.size () / regs_column_count;
111 if (regs_content.size () % regs_column_count)
6ba8e26f 112 num_lines++;
c906108c 113 }
6ba8e26f 114 return num_lines;
55fb0713 115}
c906108c 116
18ab23af 117/* See tui-regs.h. */
c906108c 118
c906108c 119int
3b23c5f2 120tui_data_window::line_from_reg_element_no (int element_no) const
c906108c 121{
3b23c5f2 122 if (element_no < regs_content.size ())
c906108c
SS
123 {
124 int i, line = (-1);
125
126 i = 1;
127 while (line == (-1))
128 {
3b23c5f2 129 if (element_no < regs_column_count * i)
c906108c
SS
130 line = i - 1;
131 else
132 i++;
133 }
134
135 return line;
136 }
137 else
138 return (-1);
55fb0713 139}
c906108c 140
18ab23af 141/* See tui-regs.h. */
c906108c 142
c906108c 143int
baff0c28 144tui_data_window::first_reg_element_no_inline (int line_no) const
c906108c 145{
baff0c28
TT
146 if (line_no * regs_column_count <= regs_content.size ())
147 return ((line_no + 1) * regs_column_count) - regs_column_count;
c906108c
SS
148 else
149 return (-1);
55fb0713 150}
c906108c 151
0379b883
TT
152/* A helper function to display the register window in the appropriate
153 way. */
154
155static void
156tui_reg_layout ()
157{
158 enum tui_layout_type cur_layout = tui_current_layout ();
159 enum tui_layout_type new_layout;
160 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
161 new_layout = SRC_DATA_COMMAND;
162 else
163 new_layout = DISASSEM_DATA_COMMAND;
164 tui_set_layout (new_layout);
165}
c906108c 166
10f59415
SC
167/* Show the registers of the given group in the data window
168 and refresh the window. */
c906108c 169void
10f59415 170tui_show_registers (struct reggroup *group)
c906108c 171{
0bfbda3b
SC
172 /* Make sure the curses mode is enabled. */
173 tui_enable ();
174
175 /* Make sure the register window is visible. If not, select an
176 appropriate layout. */
2d83e710 177 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
0379b883 178 tui_reg_layout ();
0bfbda3b 179
10f59415
SC
180 if (group == 0)
181 group = general_reggroup;
c906108c 182
1cc6d956
MS
183 /* Say that registers should be displayed, even if there is a
184 problem. */
ceb13a13 185 TUI_DATA_WIN->display_regs = true;
10f59415
SC
186
187 if (target_has_registers && target_has_stack && target_has_memory)
c906108c 188 {
e80cd204 189 tui_show_register_group (TUI_DATA_WIN, group, get_selected_frame (NULL),
21e1c91e 190 group == TUI_DATA_WIN->current_group);
368c1354 191
1cc6d956 192 /* Clear all notation of changed values. */
21e1c91e 193 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
c906108c 194 {
21e1c91e
TT
195 if (data_item_win != nullptr)
196 data_item_win->highlight = false;
c906108c 197 }
238eb706 198 TUI_DATA_WIN->current_group = group;
50daf268 199 TUI_DATA_WIN->display_all_data ();
c906108c 200 }
368c1354
TT
201 else
202 {
203 TUI_DATA_WIN->current_group = 0;
605dc2c2 204 TUI_DATA_WIN->erase_data_content (_("[ Register Values Unavailable ]"));
368c1354 205 }
55fb0713 206}
c906108c
SS
207
208
10f59415 209/* Set the data window to display the registers of the register group
1cc6d956
MS
210 using the given frame. Values are refreshed only when
211 refresh_values_only is TRUE. */
10f59415 212
21e1c91e 213static void
e80cd204
TT
214tui_show_register_group (tui_data_window *win_info,
215 struct reggroup *group,
08ef48c5
MS
216 struct frame_info *frame,
217 int refresh_values_only)
10f59415 218{
5eccfcc2 219 struct gdbarch *gdbarch = get_frame_arch (frame);
10f59415 220 int nr_regs;
10f59415
SC
221 int regnum, pos;
222 char title[80];
10f59415
SC
223
224 /* Make a new title showing which group we display. */
225 snprintf (title, sizeof (title) - 1, "Register group: %s",
226 reggroup_name (group));
e80cd204
TT
227 xfree (win_info->title);
228 win_info->title = xstrdup (title);
10f59415
SC
229
230 /* See how many registers must be displayed. */
231 nr_regs = 0;
f6efe3f8 232 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
10f59415 233 {
d20c1c3f
PA
234 const char *name;
235
236 /* Must be in the group. */
237 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
238 continue;
239
240 /* If the register name is empty, it is undefined for this
241 processor, so don't display anything. */
242 name = gdbarch_register_name (gdbarch, regnum);
243 if (name == 0 || *name == '\0')
244 continue;
245
246 nr_regs++;
10f59415
SC
247 }
248
21e1c91e 249 if (!refresh_values_only)
e80cd204 250 win_info->regs_content.clear ();
10f59415 251
e80cd204
TT
252 if (nr_regs < win_info->regs_content.size ())
253 win_info->regs_content.resize (nr_regs);
21e1c91e 254 else
10f59415 255 {
e80cd204
TT
256 for (int i = win_info->regs_content.size (); i < nr_regs; ++i)
257 win_info->regs_content.emplace_back (new tui_data_item_window ());
10f59415
SC
258 }
259
21e1c91e
TT
260 /* Now set the register names and values. */
261 pos = 0;
262 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
10f59415 263 {
21e1c91e
TT
264 struct tui_data_item_window *data_item_win;
265 const char *name;
10f59415 266
21e1c91e
TT
267 /* Must be in the group. */
268 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
269 continue;
10f59415 270
21e1c91e
TT
271 /* If the register name is empty, it is undefined for this
272 processor, so don't display anything. */
273 name = gdbarch_register_name (gdbarch, regnum);
274 if (name == 0 || *name == '\0')
275 continue;
10f59415 276
e80cd204 277 data_item_win = win_info->regs_content[pos].get ();
21e1c91e
TT
278 if (data_item_win)
279 {
280 if (!refresh_values_only)
281 {
282 data_item_win->item_no = regnum;
283 data_item_win->name = name;
284 data_item_win->highlight = false;
285 }
286 tui_get_register (frame, data_item_win, regnum, 0);
287 }
288 pos++;
289 }
10f59415
SC
290}
291
18ab23af 292/* See tui-regs.h. */
517e9505 293
c906108c 294void
517e9505 295tui_data_window::display_registers_from (int start_element_no)
c906108c 296{
517e9505 297 if (!regs_content.empty ())
c906108c 298 {
0043e6a5 299 int j, item_win_width, cur_y;
10f59415
SC
300
301 int max_len = 0;
517e9505 302 for (auto &&data_item_win : regs_content)
10f59415 303 {
b9ad3686 304 const char *p;
10f59415
SC
305 int len;
306
10f59415 307 len = 0;
b9ad3686 308 p = data_item_win->content.get ();
10f59415 309 if (p != 0)
b9ad3686 310 len = strlen (p);
10f59415
SC
311
312 if (len > max_len)
313 max_len = len;
314 }
315 item_win_width = max_len + 1;
21e1c91e 316 int i = start_element_no;
10f59415 317
517e9505
TT
318 regs_column_count = (width - 2) / item_win_width;
319 if (regs_column_count == 0)
320 regs_column_count = 1;
321 item_win_width = (width - 2) / regs_column_count;
10f59415 322
ef5eab5a
MS
323 /* Now create each data "sub" window, and write the display into
324 it. */
6ba8e26f 325 cur_y = 1;
517e9505
TT
326 while (i < regs_content.size ()
327 && cur_y <= viewport_height)
c906108c
SS
328 {
329 for (j = 0;
517e9505 330 j < regs_column_count && i < regs_content.size ();
e5908723 331 j++)
c906108c 332 {
41bcff7f 333 struct tui_data_item_window *data_item_win;
c906108c 334
1cc6d956 335 /* Create the window if necessary. */
517e9505 336 data_item_win = regs_content[i].get ();
cafb3438 337 if (data_item_win->handle != NULL
10f59415
SC
338 && (data_item_win->height != 1
339 || data_item_win->width != item_win_width
340 || data_item_win->origin.x != (item_win_width * j) + 1
341 || data_item_win->origin.y != cur_y))
342 {
343 tui_delete_win (data_item_win->handle);
344 data_item_win->handle = 0;
345 }
346
cafb3438 347 if (data_item_win->handle == NULL)
c906108c 348 {
6ba8e26f 349 data_item_win->height = 1;
10f59415 350 data_item_win->width = item_win_width;
6ba8e26f
AC
351 data_item_win->origin.x = (item_win_width * j) + 1;
352 data_item_win->origin.y = cur_y;
65962b20 353 tui_make_window (data_item_win);
6ba8e26f 354 scrollok (data_item_win->handle, FALSE);
c906108c 355 }
6ba8e26f 356 touchwin (data_item_win->handle);
fea14702 357
10f59415
SC
358 /* Get the printable representation of the register
359 and display it. */
41bcff7f 360 tui_display_register (data_item_win);
1cc6d956 361 i++; /* Next register. */
c906108c 362 }
1cc6d956 363 cur_y++; /* Next row. */
c906108c
SS
364 }
365 }
55fb0713 366}
c906108c 367
18ab23af 368/* See tui-regs.h. */
c906108c 369
aca2dd16
TT
370void
371tui_data_window::display_reg_element_at_line (int start_element_no,
372 int start_line_no)
c906108c 373{
aca2dd16 374 if (!regs_content.empty ())
c906108c 375 {
d02c80cd 376 int element_no = start_element_no;
c906108c 377
6ba8e26f 378 if (start_element_no != 0 && start_line_no != 0)
c906108c 379 {
d02c80cd 380 int last_line_no, first_line_on_last_page;
c906108c 381
aca2dd16
TT
382 last_line_no = last_regs_line_no ();
383 first_line_on_last_page = last_line_no - (height - 2);
6ba8e26f
AC
384 if (first_line_on_last_page < 0)
385 first_line_on_last_page = 0;
ef5eab5a 386
115ac53b 387 /* If the element_no causes us to scroll past the end of the
ef5eab5a
MS
388 registers, adjust what element to really start the
389 display at. */
115ac53b 390 if (start_line_no > first_line_on_last_page)
aca2dd16 391 element_no = first_reg_element_no_inline (first_line_on_last_page);
c906108c 392 }
aca2dd16 393 display_registers_from (element_no);
c906108c 394 }
6ba8e26f 395}
c906108c 396
18ab23af 397/* See tui-regs.h. */
c906108c 398
c906108c 399int
517e9505 400tui_data_window::display_registers_from_line (int line_no)
c906108c 401{
b4ef5aeb 402 check_and_display_highlight_if_needed ();
517e9505 403 if (!regs_content.empty ())
c906108c 404 {
80cb6c27 405 int element_no;
c906108c 406
6ba8e26f 407 if (line_no < 0)
80cb6c27
TT
408 line_no = 0;
409 else
410 {
411 /* Make sure that we don't display off the end of the
ef5eab5a 412 registers. */
517e9505 413 if (line_no >= last_regs_line_no ())
c906108c 414 {
517e9505
TT
415 line_no = line_from_reg_element_no (regs_content.size () - 1);
416 if (line_no < 0)
80cb6c27 417 line_no = 0;
c906108c 418 }
c906108c 419 }
c906108c 420
517e9505
TT
421 element_no = first_reg_element_no_inline (line_no);
422 if (element_no < regs_content.size ())
aca2dd16 423 display_reg_element_at_line (element_no, line_no);
c906108c 424 else
80cb6c27 425 line_no = (-1);
c906108c 426
80cb6c27 427 return line_no;
c906108c
SS
428 }
429
1cc6d956 430 return (-1); /* Nothing was displayed. */
55fb0713 431}
c906108c
SS
432
433
18ab23af
TT
434/* Answer the index first element displayed. If none are displayed,
435 then return (-1). */
436int
437tui_data_window::first_data_item_displayed ()
438{
439 for (int i = 0; i < regs_content.size (); i++)
440 {
441 struct tui_gen_win_info *data_item_win;
442
443 data_item_win = regs_content[i].get ();
2d83e710 444 if (data_item_win->is_visible ())
18ab23af
TT
445 return i;
446 }
447
448 return -1;
449}
450
451/* See tui-regs.h. */
452
453void
454tui_data_window::delete_data_content_windows ()
455{
456 for (auto &&win : regs_content)
457 {
458 tui_delete_win (win->handle);
459 win->handle = NULL;
18ab23af
TT
460 }
461}
462
463
464void
465tui_data_window::erase_data_content (const char *prompt)
466{
467 werase (handle);
b4ef5aeb 468 check_and_display_highlight_if_needed ();
18ab23af
TT
469 if (prompt != NULL)
470 {
471 int half_width = (width - 2) / 2;
472 int x_pos;
473
474 if (strlen (prompt) >= half_width)
475 x_pos = 1;
476 else
477 x_pos = half_width - strlen (prompt);
478 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
479 }
480 wrefresh (handle);
481}
482
483/* See tui-regs.h. */
484
485void
486tui_data_window::display_all_data ()
487{
488 if (regs_content.empty ())
489 erase_data_content (NO_DATA_STRING);
490 else
491 {
492 erase_data_content (NULL);
493 delete_data_content_windows ();
b4ef5aeb 494 check_and_display_highlight_if_needed ();
18ab23af
TT
495 display_registers_from (0);
496 }
497}
498
499
500/* Function to redisplay the contents of the data window. */
501void
502tui_data_window::refresh_all ()
503{
504 erase_data_content (NULL);
505 if (!regs_content.empty ())
506 {
507 int first_element = first_data_item_displayed ();
508
509 if (first_element >= 0) /* Re-use existing windows. */
510 {
511 int first_line = (-1);
512
513 if (first_element < regs_content.size ())
514 first_line = line_from_reg_element_no (first_element);
515
516 if (first_line >= 0)
517 {
518 erase_data_content (NULL);
519 display_registers_from_line (first_line);
520 }
521 }
522 }
523}
524
525
526/* Scroll the data window vertically forward or backward. */
527void
528tui_data_window::do_scroll_vertical (int num_to_scroll)
529{
530 int first_element_no;
531 int first_line = (-1);
532
533 first_element_no = first_data_item_displayed ();
534 if (first_element_no < regs_content.size ())
535 first_line = line_from_reg_element_no (first_element_no);
536 else
537 { /* Calculate the first line from the element number which is in
538 the general data content. */
539 }
540
541 if (first_line >= 0)
542 {
543 first_line += num_to_scroll;
544 erase_data_content (NULL);
545 delete_data_content_windows ();
546 display_registers_from_line (first_line);
547 }
548}
549
550/* See tui-regs.h. */
551
18ab23af 552void
3df505f6 553tui_data_window::rerender ()
18ab23af
TT
554{
555 /* Delete all data item windows. */
556 for (auto &&win : regs_content)
557 {
558 tui_delete_win (win->handle);
559 win->handle = NULL;
560 }
18ab23af
TT
561 display_all_data ();
562}
563
564/* See tui-regs.h. */
565
566void
567tui_data_window::refresh_window ()
568{
569 tui_gen_win_info::refresh_window ();
570 for (auto &&win : regs_content)
571 {
572 if (win != NULL)
573 win->refresh_window ();
574 }
575}
576
55fb0713
AC
577/* This function check all displayed registers for changes in values,
578 given a particular frame. If the values have changed, they are
579 updated with the new value and highlighted. */
c906108c 580void
55fb0713 581tui_check_register_values (struct frame_info *frame)
c906108c 582{
e5908723 583 if (TUI_DATA_WIN != NULL
2d83e710 584 && TUI_DATA_WIN->is_visible ())
c906108c 585 {
21e1c91e 586 if (TUI_DATA_WIN->regs_content.empty ()
238eb706
TT
587 && TUI_DATA_WIN->display_regs)
588 tui_show_registers (TUI_DATA_WIN->current_group);
c906108c
SS
589 else
590 {
21e1c91e 591 for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
c906108c 592 {
6ba8e26f 593 int was_hilighted;
c906108c 594
41bcff7f 595 was_hilighted = data_item_win_ptr->highlight;
10f59415 596
21e1c91e 597 tui_get_register (frame, data_item_win_ptr.get (),
41bcff7f
TT
598 data_item_win_ptr->item_no,
599 &data_item_win_ptr->highlight);
10f59415 600
41bcff7f 601 if (data_item_win_ptr->highlight || was_hilighted)
21e1c91e 602 tui_display_register (data_item_win_ptr.get ());
c906108c
SS
603 }
604 }
605 }
55fb0713 606}
c906108c 607
1cc6d956
MS
608/* Display a register in a window. If hilite is TRUE, then the value
609 will be displayed in reverse video. */
10f59415 610static void
41bcff7f 611tui_display_register (struct tui_data_item_window *data)
10f59415 612{
41bcff7f 613 if (data->handle != NULL)
10f59415
SC
614 {
615 int i;
c906108c 616
10f59415 617 if (data->highlight)
cae3f17b
JB
618 /* We ignore the return value, casting it to void in order to avoid
619 a compiler warning. The warning itself was introduced by a patch
620 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
621 to code that causes the compiler to generate an unused-value
622 warning. */
41bcff7f 623 (void) wstandout (data->handle);
10f59415 624
41bcff7f
TT
625 wmove (data->handle, 0, 0);
626 for (i = 1; i < data->width; i++)
627 waddch (data->handle, ' ');
628 wmove (data->handle, 0, 0);
10f59415 629 if (data->content)
b9ad3686 630 waddstr (data->handle, data->content.get ());
10f59415
SC
631
632 if (data->highlight)
cae3f17b
JB
633 /* We ignore the return value, casting it to void in order to avoid
634 a compiler warning. The warning itself was introduced by a patch
635 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
636 to code that causes the compiler to generate an unused-value
637 warning. */
41bcff7f
TT
638 (void) wstandend (data->handle);
639 data->refresh_window ();
10f59415
SC
640 }
641}
642
51f0e40d
AB
643/* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
644 around behaviour. Returns the next register group, or NULL if the
645 register window is not currently being displayed. */
646
647static struct reggroup *
fe3eaf1c 648tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
c906108c 649{
51f0e40d 650 struct reggroup *group = NULL;
e17c207e 651
fe3eaf1c 652 if (current_group != NULL)
10f59415 653 {
fe3eaf1c 654 group = reggroup_next (gdbarch, current_group);
b75c69bb
AB
655 if (group == NULL)
656 group = reggroup_next (gdbarch, NULL);
10f59415 657 }
51f0e40d 658 return group;
10f59415
SC
659}
660
51f0e40d
AB
661/* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
662 around behaviour. Returns the previous register group, or NULL if the
663 register window is not currently being displayed. */
55b40027 664
51f0e40d 665static struct reggroup *
fe3eaf1c 666tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
55b40027 667{
51f0e40d 668 struct reggroup *group = NULL;
55b40027 669
fe3eaf1c 670 if (current_group != NULL)
55b40027 671 {
fe3eaf1c 672 group = reggroup_prev (gdbarch, current_group);
55b40027
AB
673 if (group == NULL)
674 group = reggroup_prev (gdbarch, NULL);
55b40027 675 }
51f0e40d 676 return group;
55b40027
AB
677}
678
51f0e40d
AB
679/* Implement the 'tui reg' command. Changes the register group displayed
680 in the tui register window. Displays the tui register window if it is
681 not already on display. */
c906108c 682
10f59415 683static void
e2d8ae16 684tui_reg_command (const char *args, int from_tty)
10f59415 685{
51f0e40d 686 struct gdbarch *gdbarch = get_current_arch ();
c906108c 687
51f0e40d
AB
688 if (args != NULL)
689 {
690 struct reggroup *group, *match = NULL;
691 size_t len = strlen (args);
692
693 /* Make sure the curses mode is enabled. */
694 tui_enable ();
695
696 /* Make sure the register window is visible. If not, select an
697 appropriate layout. We need to do this before trying to run the
698 'next' or 'prev' commands. */
2d83e710 699 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
0379b883 700 tui_reg_layout ();
51f0e40d 701
0f8d8876 702 struct reggroup *current_group = TUI_DATA_WIN->current_group;
51f0e40d 703 if (strncmp (args, "next", len) == 0)
fe3eaf1c 704 match = tui_reg_next (current_group, gdbarch);
51f0e40d 705 else if (strncmp (args, "prev", len) == 0)
fe3eaf1c 706 match = tui_reg_prev (current_group, gdbarch);
51f0e40d
AB
707
708 /* This loop matches on the initial part of a register group
709 name. If this initial part in ARGS matches only one register
710 group then the switch is made. */
711 for (group = reggroup_next (gdbarch, NULL);
712 group != NULL;
713 group = reggroup_next (gdbarch, group))
714 {
715 if (strncmp (reggroup_name (group), args, len) == 0)
716 {
717 if (match != NULL)
718 error (_("ambiguous register group name '%s'"), args);
719 match = group;
720 }
721 }
722
723 if (match == NULL)
724 error (_("unknown register group '%s'"), args);
725
726 tui_show_registers (match);
727 }
728 else
729 {
730 struct reggroup *group;
731 int first;
732
733 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
734 "either a register group,\nor one of 'next' "
735 "or 'prev'. Known register groups are:\n"));
736
737 for (first = 1, group = reggroup_next (gdbarch, NULL);
738 group != NULL;
739 first = 0, group = reggroup_next (gdbarch, group))
740 {
741 if (!first)
742 printf_unfiltered (", ");
743 printf_unfiltered ("%s", reggroup_name (group));
744 }
745
746 printf_unfiltered ("\n");
747 }
10f59415
SC
748}
749
51f0e40d
AB
750/* Complete names of register groups, and add the special "prev" and "next"
751 names. */
c906108c 752
eb3ff9a5 753static void
51f0e40d 754tui_reggroup_completer (struct cmd_list_element *ignore,
eb3ff9a5 755 completion_tracker &tracker,
51f0e40d 756 const char *text, const char *word)
10f59415 757{
51f0e40d
AB
758 static const char *extra[] = { "next", "prev", NULL };
759 size_t len = strlen (word);
760 const char **tmp;
761
eb3ff9a5 762 reggroup_completer (ignore, tracker, text, word);
51f0e40d 763
eb3ff9a5 764 /* XXXX use complete_on_enum instead? */
51f0e40d
AB
765 for (tmp = extra; *tmp != NULL; ++tmp)
766 {
767 if (strncmp (word, *tmp, len) == 0)
b02f78f9 768 tracker.add_completion (make_unique_xstrdup (*tmp));
51f0e40d 769 }
10f59415 770}
c906108c 771
18ab23af
TT
772void
773_initialize_tui_regs (void)
774{
775 struct cmd_list_element **tuicmd, *cmd;
776
777 tuicmd = tui_get_cmd_list ();
778
779 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
780TUI command to control the register window."), tuicmd);
781 set_cmd_completer (cmd, tui_reggroup_completer);
782}