1 /* TUI display registers in window.
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
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
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "arch-utils.h"
25 #include "tui/tui-data.h"
33 #include "tui/tui-layout.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-wingeneral.h"
36 #include "tui/tui-file.h"
37 #include "tui/tui-regs.h"
38 #include "tui/tui-io.h"
39 #include "reggroups.h"
41 #include "completer.h"
43 #include "gdb_curses.h"
45 static void tui_display_register (struct tui_data_item_window *data);
47 static void tui_show_register_group (tui_data_window *win_info,
48 struct reggroup *group,
49 struct frame_info *frame,
50 int refresh_values_only);
52 static void tui_get_register (struct frame_info *frame,
53 struct tui_data_item_window *data,
54 int regnum, bool *changedp);
59 tui_data_item_window::~tui_data_item_window ()
68 tui_data_window::last_regs_line_no () const
72 if (!regs_content.empty ())
74 num_lines = regs_content.size () / regs_column_count;
75 if (regs_content.size () % regs_column_count)
84 tui_data_window::line_from_reg_element_no (int element_no) const
86 if (element_no < regs_content.size ())
93 if (element_no < regs_column_count * i)
105 /* See tui-regs.h. */
108 tui_data_window::first_reg_element_no_inline (int line_no) const
110 if (line_no * regs_column_count <= regs_content.size ())
111 return ((line_no + 1) * regs_column_count) - regs_column_count;
116 /* A helper function to display the register window in the appropriate
122 enum tui_layout_type cur_layout = tui_current_layout ();
123 enum tui_layout_type new_layout;
124 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
125 new_layout = SRC_DATA_COMMAND;
127 new_layout = DISASSEM_DATA_COMMAND;
128 tui_set_layout (new_layout);
131 /* Show the registers of the given group in the data window
132 and refresh the window. */
134 tui_show_registers (struct reggroup *group)
136 /* Make sure the curses mode is enabled. */
139 /* Make sure the register window is visible. If not, select an
140 appropriate layout. */
141 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
145 group = general_reggroup;
147 /* Say that registers should be displayed, even if there is a
149 TUI_DATA_WIN->display_regs = true;
151 if (target_has_registers && target_has_stack && target_has_memory)
153 tui_show_register_group (TUI_DATA_WIN, group, get_selected_frame (NULL),
154 group == TUI_DATA_WIN->current_group);
156 /* Clear all notation of changed values. */
157 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
159 if (data_item_win != nullptr)
160 data_item_win->highlight = false;
162 TUI_DATA_WIN->current_group = group;
163 TUI_DATA_WIN->display_all_data ();
167 TUI_DATA_WIN->current_group = 0;
168 TUI_DATA_WIN->erase_data_content (NO_REGS_STRING);
173 /* Set the data window to display the registers of the register group
174 using the given frame. Values are refreshed only when
175 refresh_values_only is TRUE. */
178 tui_show_register_group (tui_data_window *win_info,
179 struct reggroup *group,
180 struct frame_info *frame,
181 int refresh_values_only)
183 struct gdbarch *gdbarch = get_frame_arch (frame);
188 /* Make a new title showing which group we display. */
189 snprintf (title, sizeof (title) - 1, "Register group: %s",
190 reggroup_name (group));
191 xfree (win_info->title);
192 win_info->title = xstrdup (title);
194 /* See how many registers must be displayed. */
196 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
200 /* Must be in the group. */
201 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
204 /* If the register name is empty, it is undefined for this
205 processor, so don't display anything. */
206 name = gdbarch_register_name (gdbarch, regnum);
207 if (name == 0 || *name == '\0')
213 if (!refresh_values_only)
214 win_info->regs_content.clear ();
216 if (nr_regs < win_info->regs_content.size ())
217 win_info->regs_content.resize (nr_regs);
220 for (int i = win_info->regs_content.size (); i < nr_regs; ++i)
221 win_info->regs_content.emplace_back (new tui_data_item_window ());
224 /* Now set the register names and values. */
226 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
228 struct tui_data_item_window *data_item_win;
231 /* Must be in the group. */
232 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
235 /* If the register name is empty, it is undefined for this
236 processor, so don't display anything. */
237 name = gdbarch_register_name (gdbarch, regnum);
238 if (name == 0 || *name == '\0')
241 data_item_win = win_info->regs_content[pos].get ();
244 if (!refresh_values_only)
246 data_item_win->item_no = regnum;
247 data_item_win->name = name;
248 data_item_win->highlight = false;
250 tui_get_register (frame, data_item_win, regnum, 0);
256 /* See tui-regs.h. */
259 tui_data_window::display_registers_from (int start_element_no)
261 if (!regs_content.empty ())
263 int j, item_win_width, cur_y;
266 for (auto &&data_item_win : regs_content)
272 p = data_item_win->content;
277 len = 8 * ((len / 8) + 1);
285 item_win_width = max_len + 1;
286 int i = start_element_no;
288 regs_column_count = (width - 2) / item_win_width;
289 if (regs_column_count == 0)
290 regs_column_count = 1;
291 item_win_width = (width - 2) / regs_column_count;
293 /* Now create each data "sub" window, and write the display into
296 while (i < regs_content.size ()
297 && cur_y <= viewport_height)
300 j < regs_column_count && i < regs_content.size ();
303 struct tui_data_item_window *data_item_win;
305 /* Create the window if necessary. */
306 data_item_win = regs_content[i].get ();
307 if (data_item_win->handle != NULL
308 && (data_item_win->height != 1
309 || data_item_win->width != item_win_width
310 || data_item_win->origin.x != (item_win_width * j) + 1
311 || data_item_win->origin.y != cur_y))
313 tui_delete_win (data_item_win->handle);
314 data_item_win->handle = 0;
317 if (data_item_win->handle == NULL)
319 data_item_win->height = 1;
320 data_item_win->width = item_win_width;
321 data_item_win->origin.x = (item_win_width * j) + 1;
322 data_item_win->origin.y = cur_y;
323 tui_make_window (data_item_win);
324 scrollok (data_item_win->handle, FALSE);
326 touchwin (data_item_win->handle);
328 /* Get the printable representation of the register
330 tui_display_register (data_item_win);
331 i++; /* Next register. */
333 cur_y++; /* Next row. */
338 /* See tui-regs.h. */
341 tui_data_window::display_reg_element_at_line (int start_element_no,
344 if (!regs_content.empty ())
346 int element_no = start_element_no;
348 if (start_element_no != 0 && start_line_no != 0)
350 int last_line_no, first_line_on_last_page;
352 last_line_no = last_regs_line_no ();
353 first_line_on_last_page = last_line_no - (height - 2);
354 if (first_line_on_last_page < 0)
355 first_line_on_last_page = 0;
357 /* If the element_no causes us to scroll past the end of the
358 registers, adjust what element to really start the
360 if (start_line_no > first_line_on_last_page)
361 element_no = first_reg_element_no_inline (first_line_on_last_page);
363 display_registers_from (element_no);
367 /* See tui-regs.h. */
370 tui_data_window::display_registers_from_line (int line_no)
372 check_and_display_highlight_if_needed ();
373 if (!regs_content.empty ())
381 /* Make sure that we don't display off the end of the
383 if (line_no >= last_regs_line_no ())
385 line_no = line_from_reg_element_no (regs_content.size () - 1);
391 element_no = first_reg_element_no_inline (line_no);
392 if (element_no < regs_content.size ())
393 display_reg_element_at_line (element_no, line_no);
400 return (-1); /* Nothing was displayed. */
404 /* Answer the index first element displayed. If none are displayed,
407 tui_data_window::first_data_item_displayed ()
409 for (int i = 0; i < regs_content.size (); i++)
411 struct tui_gen_win_info *data_item_win;
413 data_item_win = regs_content[i].get ();
414 if (data_item_win->handle != NULL && data_item_win->is_visible)
421 /* See tui-regs.h. */
424 tui_data_window::delete_data_content_windows ()
426 for (auto &&win : regs_content)
428 tui_delete_win (win->handle);
430 win->is_visible = false;
436 tui_data_window::erase_data_content (const char *prompt)
439 check_and_display_highlight_if_needed ();
442 int half_width = (width - 2) / 2;
445 if (strlen (prompt) >= half_width)
448 x_pos = half_width - strlen (prompt);
449 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
454 /* See tui-regs.h. */
457 tui_data_window::display_all_data ()
459 if (regs_content.empty ())
460 erase_data_content (NO_DATA_STRING);
463 erase_data_content (NULL);
464 delete_data_content_windows ();
465 check_and_display_highlight_if_needed ();
466 display_registers_from (0);
471 /* Function to redisplay the contents of the data window. */
473 tui_data_window::refresh_all ()
475 erase_data_content (NULL);
476 if (!regs_content.empty ())
478 int first_element = first_data_item_displayed ();
480 if (first_element >= 0) /* Re-use existing windows. */
482 int first_line = (-1);
484 if (first_element < regs_content.size ())
485 first_line = line_from_reg_element_no (first_element);
489 erase_data_content (NULL);
490 display_registers_from_line (first_line);
497 /* Scroll the data window vertically forward or backward. */
499 tui_data_window::do_scroll_vertical (int num_to_scroll)
501 int first_element_no;
502 int first_line = (-1);
504 first_element_no = first_data_item_displayed ();
505 if (first_element_no < regs_content.size ())
506 first_line = line_from_reg_element_no (first_element_no);
508 { /* Calculate the first line from the element number which is in
509 the general data content. */
514 first_line += num_to_scroll;
515 erase_data_content (NULL);
516 delete_data_content_windows ();
517 display_registers_from_line (first_line);
521 /* See tui-regs.h. */
524 tui_data_window::rerender ()
526 /* Delete all data item windows. */
527 for (auto &&win : regs_content)
529 tui_delete_win (win->handle);
535 /* See tui-regs.h. */
538 tui_data_window::refresh_window ()
540 tui_gen_win_info::refresh_window ();
541 for (auto &&win : regs_content)
544 win->refresh_window ();
548 /* This function check all displayed registers for changes in values,
549 given a particular frame. If the values have changed, they are
550 updated with the new value and highlighted. */
552 tui_check_register_values (struct frame_info *frame)
554 if (TUI_DATA_WIN != NULL
555 && TUI_DATA_WIN->is_visible)
557 if (TUI_DATA_WIN->regs_content.empty ()
558 && TUI_DATA_WIN->display_regs)
559 tui_show_registers (TUI_DATA_WIN->current_group);
562 for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
566 was_hilighted = data_item_win_ptr->highlight;
568 tui_get_register (frame, data_item_win_ptr.get (),
569 data_item_win_ptr->item_no,
570 &data_item_win_ptr->highlight);
572 if (data_item_win_ptr->highlight || was_hilighted)
573 tui_display_register (data_item_win_ptr.get ());
579 /* Display a register in a window. If hilite is TRUE, then the value
580 will be displayed in reverse video. */
582 tui_display_register (struct tui_data_item_window *data)
584 if (data->handle != NULL)
589 /* We ignore the return value, casting it to void in order to avoid
590 a compiler warning. The warning itself was introduced by a patch
591 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
592 to code that causes the compiler to generate an unused-value
594 (void) wstandout (data->handle);
596 wmove (data->handle, 0, 0);
597 for (i = 1; i < data->width; i++)
598 waddch (data->handle, ' ');
599 wmove (data->handle, 0, 0);
601 waddstr (data->handle, data->content);
604 /* We ignore the return value, casting it to void in order to avoid
605 a compiler warning. The warning itself was introduced by a patch
606 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
607 to code that causes the compiler to generate an unused-value
609 (void) wstandend (data->handle);
610 data->refresh_window ();
614 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
615 around behaviour. Returns the next register group, or NULL if the
616 register window is not currently being displayed. */
618 static struct reggroup *
619 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
621 struct reggroup *group = NULL;
623 if (current_group != NULL)
625 group = reggroup_next (gdbarch, current_group);
627 group = reggroup_next (gdbarch, NULL);
632 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
633 around behaviour. Returns the previous register group, or NULL if the
634 register window is not currently being displayed. */
636 static struct reggroup *
637 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
639 struct reggroup *group = NULL;
641 if (current_group != NULL)
643 group = reggroup_prev (gdbarch, current_group);
645 group = reggroup_prev (gdbarch, NULL);
650 /* Implement the 'tui reg' command. Changes the register group displayed
651 in the tui register window. Displays the tui register window if it is
652 not already on display. */
655 tui_reg_command (const char *args, int from_tty)
657 struct gdbarch *gdbarch = get_current_arch ();
661 struct reggroup *group, *match = NULL;
662 size_t len = strlen (args);
664 /* Make sure the curses mode is enabled. */
667 /* Make sure the register window is visible. If not, select an
668 appropriate layout. We need to do this before trying to run the
669 'next' or 'prev' commands. */
670 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
673 struct reggroup *current_group = NULL;
674 if (TUI_DATA_WIN != NULL)
675 current_group = TUI_DATA_WIN->current_group;
676 if (strncmp (args, "next", len) == 0)
677 match = tui_reg_next (current_group, gdbarch);
678 else if (strncmp (args, "prev", len) == 0)
679 match = tui_reg_prev (current_group, gdbarch);
681 /* This loop matches on the initial part of a register group
682 name. If this initial part in ARGS matches only one register
683 group then the switch is made. */
684 for (group = reggroup_next (gdbarch, NULL);
686 group = reggroup_next (gdbarch, group))
688 if (strncmp (reggroup_name (group), args, len) == 0)
691 error (_("ambiguous register group name '%s'"), args);
697 error (_("unknown register group '%s'"), args);
699 tui_show_registers (match);
703 struct reggroup *group;
706 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
707 "either a register group,\nor one of 'next' "
708 "or 'prev'. Known register groups are:\n"));
710 for (first = 1, group = reggroup_next (gdbarch, NULL);
712 first = 0, group = reggroup_next (gdbarch, group))
715 printf_unfiltered (", ");
716 printf_unfiltered ("%s", reggroup_name (group));
719 printf_unfiltered ("\n");
723 /* Complete names of register groups, and add the special "prev" and "next"
727 tui_reggroup_completer (struct cmd_list_element *ignore,
728 completion_tracker &tracker,
729 const char *text, const char *word)
731 static const char *extra[] = { "next", "prev", NULL };
732 size_t len = strlen (word);
735 reggroup_completer (ignore, tracker, text, word);
737 /* XXXX use complete_on_enum instead? */
738 for (tmp = extra; *tmp != NULL; ++tmp)
740 if (strncmp (word, *tmp, len) == 0)
741 tracker.add_completion (make_unique_xstrdup (*tmp));
745 /* Get the register from the frame and return a printable
746 representation of it. */
749 tui_register_format (struct frame_info *frame, int regnum)
751 struct gdbarch *gdbarch = get_frame_arch (frame);
755 scoped_restore save_pagination
756 = make_scoped_restore (&pagination_enabled, 0);
757 scoped_restore save_stdout
758 = make_scoped_restore (&gdb_stdout, &stream);
760 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
762 /* Remove the possible \n. */
763 std::string &str = stream.string ();
764 if (!str.empty () && str.back () == '\n')
765 str.resize (str.size () - 1);
767 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
768 return tui_expand_tabs (str.c_str (), 0);
771 /* Get the register value from the given frame and format it for the
772 display. When changep is set, check if the new register value has
773 changed with respect to the previous call. */
775 tui_get_register (struct frame_info *frame,
776 struct tui_data_item_window *data,
777 int regnum, bool *changedp)
781 if (target_has_registers)
783 char *prev_content = data->content;
785 data->content = tui_register_format (frame, regnum);
788 && strcmp (prev_content, data->content) != 0)
791 xfree (prev_content);
796 _initialize_tui_regs (void)
798 struct cmd_list_element **tuicmd, *cmd;
800 tuicmd = tui_get_cmd_list ();
802 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
803 TUI command to control the register window."), tuicmd);
804 set_cmd_completer (cmd, tui_reggroup_completer);