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 /* Get the register from the frame and return a printable
48 representation of it. */
50 static gdb::unique_xmalloc_ptr<char>
51 tui_register_format (struct frame_info *frame, int regnum)
53 struct gdbarch *gdbarch = get_frame_arch (frame);
57 scoped_restore save_pagination
58 = make_scoped_restore (&pagination_enabled, 0);
59 scoped_restore save_stdout
60 = make_scoped_restore (&gdb_stdout, &stream);
62 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
64 /* Remove the possible \n. */
65 std::string &str = stream.string ();
66 if (!str.empty () && str.back () == '\n')
67 str.resize (str.size () - 1);
69 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
70 return tui_expand_tabs (str.c_str ());
73 /* Get the register value from the given frame and format it for the
74 display. When changep is set, check if the new register value has
75 changed with respect to the previous call. */
77 tui_get_register (struct frame_info *frame,
78 struct tui_data_item_window *data,
79 int regnum, bool *changedp)
83 if (target_has_registers)
85 gdb::unique_xmalloc_ptr<char> new_content
86 = tui_register_format (frame, regnum);
89 && strcmp (data->content.get (), new_content.get ()) != 0)
92 data->content = std::move (new_content);
99 tui_data_window::last_regs_line_no () const
101 int num_lines = regs_content.size () / regs_column_count;
102 if (regs_content.size () % regs_column_count)
107 /* See tui-regs.h. */
110 tui_data_window::line_from_reg_element_no (int element_no) const
112 if (element_no < regs_content.size ())
119 if (element_no < regs_column_count * i)
131 /* See tui-regs.h. */
134 tui_data_window::first_reg_element_no_inline (int line_no) const
136 if (line_no * regs_column_count <= regs_content.size ())
137 return ((line_no + 1) * regs_column_count) - regs_column_count;
142 /* Show the registers of the given group in the data window
143 and refresh the window. */
145 tui_data_window::show_registers (struct reggroup *group)
148 group = general_reggroup;
150 if (target_has_registers && target_has_stack && target_has_memory)
152 show_register_group (group, get_selected_frame (NULL),
153 group == current_group);
155 /* Clear all notation of changed values. */
156 for (auto &&data_item_win : regs_content)
157 data_item_win.highlight = false;
158 current_group = group;
164 erase_data_content (_("[ Register Values Unavailable ]"));
169 /* Set the data window to display the registers of the register group
170 using the given frame. Values are refreshed only when
171 refresh_values_only is TRUE. */
174 tui_data_window::show_register_group (struct reggroup *group,
175 struct frame_info *frame,
176 int refresh_values_only)
178 struct gdbarch *gdbarch = get_frame_arch (frame);
182 /* Make a new title showing which group we display. */
183 title = string_printf ("Register group: %s", reggroup_name (group));
185 /* See how many registers must be displayed. */
187 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
191 /* Must be in the group. */
192 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
195 /* If the register name is empty, it is undefined for this
196 processor, so don't display anything. */
197 name = gdbarch_register_name (gdbarch, regnum);
198 if (name == 0 || *name == '\0')
204 regs_content.resize (nr_regs);
206 /* Now set the register names and values. */
208 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
210 struct tui_data_item_window *data_item_win;
213 /* Must be in the group. */
214 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
217 /* If the register name is empty, it is undefined for this
218 processor, so don't display anything. */
219 name = gdbarch_register_name (gdbarch, regnum);
220 if (name == 0 || *name == '\0')
223 data_item_win = ®s_content[pos];
226 if (!refresh_values_only)
228 data_item_win->item_no = regnum;
229 data_item_win->name = name;
230 data_item_win->highlight = false;
232 tui_get_register (frame, data_item_win, regnum, 0);
238 /* See tui-regs.h. */
241 tui_data_window::display_registers_from (int start_element_no)
243 int j, item_win_width, cur_y;
246 for (auto &&data_item_win : regs_content)
252 p = data_item_win.content.get ();
259 item_win_width = max_len + 1;
260 int i = start_element_no;
262 regs_column_count = (width - 2) / item_win_width;
263 if (regs_column_count == 0)
264 regs_column_count = 1;
265 item_win_width = (width - 2) / regs_column_count;
267 /* Now create each data "sub" window, and write the display into
270 while (i < regs_content.size ()
271 && cur_y <= viewport_height)
274 j < regs_column_count && i < regs_content.size ();
277 struct tui_data_item_window *data_item_win;
279 /* Create the window if necessary. */
280 data_item_win = ®s_content[i];
281 if (data_item_win->handle != NULL
282 && (data_item_win->height != 1
283 || data_item_win->width != item_win_width
284 || data_item_win->origin.x != (item_win_width * j) + 1
285 || data_item_win->origin.y != cur_y))
287 tui_delete_win (data_item_win->handle);
288 data_item_win->handle = 0;
291 if (data_item_win->handle == NULL)
293 data_item_win->height = 1;
294 data_item_win->width = item_win_width;
295 data_item_win->origin.x = (item_win_width * j) + 1;
296 data_item_win->origin.y = cur_y;
297 data_item_win->make_visible (true);
298 scrollok (data_item_win->handle, FALSE);
300 touchwin (data_item_win->handle);
302 /* Get the printable representation of the register
304 tui_display_register (data_item_win);
305 i++; /* Next register. */
307 cur_y++; /* Next row. */
311 /* See tui-regs.h. */
314 tui_data_window::display_reg_element_at_line (int start_element_no,
317 int element_no = start_element_no;
319 if (start_element_no != 0 && start_line_no != 0)
321 int last_line_no, first_line_on_last_page;
323 last_line_no = last_regs_line_no ();
324 first_line_on_last_page = last_line_no - (height - 2);
325 if (first_line_on_last_page < 0)
326 first_line_on_last_page = 0;
328 /* If the element_no causes us to scroll past the end of the
329 registers, adjust what element to really start the
331 if (start_line_no > first_line_on_last_page)
332 element_no = first_reg_element_no_inline (first_line_on_last_page);
334 display_registers_from (element_no);
337 /* See tui-regs.h. */
340 tui_data_window::display_registers_from_line (int line_no)
348 /* Make sure that we don't display off the end of the
350 if (line_no >= last_regs_line_no ())
352 line_no = line_from_reg_element_no (regs_content.size () - 1);
358 element_no = first_reg_element_no_inline (line_no);
359 if (element_no < regs_content.size ())
360 display_reg_element_at_line (element_no, line_no);
368 /* Answer the index first element displayed. If none are displayed,
371 tui_data_window::first_data_item_displayed ()
373 for (int i = 0; i < regs_content.size (); i++)
375 struct tui_gen_win_info *data_item_win;
377 data_item_win = ®s_content[i];
378 if (data_item_win->is_visible ())
385 /* See tui-regs.h. */
388 tui_data_window::delete_data_content_windows ()
390 for (auto &&win : regs_content)
392 tui_delete_win (win.handle);
399 tui_data_window::erase_data_content (const char *prompt)
402 check_and_display_highlight_if_needed ();
405 int half_width = (width - 2) / 2;
408 if (strlen (prompt) >= half_width)
411 x_pos = half_width - strlen (prompt);
412 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
417 /* See tui-regs.h. */
420 tui_data_window::rerender ()
422 if (regs_content.empty ())
423 erase_data_content (_("[ Register Values Unavailable ]"));
426 erase_data_content (NULL);
427 delete_data_content_windows ();
428 display_registers_from (0);
433 /* Function to redisplay the contents of the data window. */
435 tui_data_window::refresh_all ()
437 erase_data_content (NULL);
438 if (!regs_content.empty ())
440 int first_element = first_data_item_displayed ();
442 if (first_element >= 0) /* Re-use existing windows. */
444 int first_line = (-1);
446 if (first_element < regs_content.size ())
447 first_line = line_from_reg_element_no (first_element);
450 display_registers_from_line (first_line);
456 /* Scroll the data window vertically forward or backward. */
458 tui_data_window::do_scroll_vertical (int num_to_scroll)
460 int first_element_no;
461 int first_line = (-1);
463 first_element_no = first_data_item_displayed ();
464 if (first_element_no < regs_content.size ())
465 first_line = line_from_reg_element_no (first_element_no);
467 { /* Calculate the first line from the element number which is in
468 the general data content. */
473 first_line += num_to_scroll;
474 erase_data_content (NULL);
475 delete_data_content_windows ();
476 display_registers_from_line (first_line);
480 /* See tui-regs.h. */
483 tui_data_window::refresh_window ()
485 tui_gen_win_info::refresh_window ();
486 for (auto &&win : regs_content)
487 win.refresh_window ();
490 /* This function check all displayed registers for changes in values,
491 given a particular frame. If the values have changed, they are
492 updated with the new value and highlighted. */
494 tui_data_window::check_register_values (struct frame_info *frame)
496 if (regs_content.empty ())
497 show_registers (current_group);
500 for (auto &&data_item_win : regs_content)
504 was_hilighted = data_item_win.highlight;
506 tui_get_register (frame, &data_item_win,
507 data_item_win.item_no,
508 &data_item_win.highlight);
510 if (data_item_win.highlight || was_hilighted)
511 tui_display_register (&data_item_win);
516 /* Display a register in a window. If hilite is TRUE, then the value
517 will be displayed in reverse video. */
519 tui_display_register (struct tui_data_item_window *data)
521 if (data->handle != NULL)
526 /* We ignore the return value, casting it to void in order to avoid
527 a compiler warning. The warning itself was introduced by a patch
528 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
529 to code that causes the compiler to generate an unused-value
531 (void) wstandout (data->handle);
533 wmove (data->handle, 0, 0);
534 for (i = 1; i < data->width; i++)
535 waddch (data->handle, ' ');
536 wmove (data->handle, 0, 0);
538 waddstr (data->handle, data->content.get ());
541 /* We ignore the return value, casting it to void in order to avoid
542 a compiler warning. The warning itself was introduced by a patch
543 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
544 to code that causes the compiler to generate an unused-value
546 (void) wstandend (data->handle);
547 data->refresh_window ();
551 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
552 around behaviour. Returns the next register group, or NULL if the
553 register window is not currently being displayed. */
555 static struct reggroup *
556 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
558 struct reggroup *group = NULL;
560 if (current_group != NULL)
562 group = reggroup_next (gdbarch, current_group);
564 group = reggroup_next (gdbarch, NULL);
569 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
570 around behaviour. Returns the previous register group, or NULL if the
571 register window is not currently being displayed. */
573 static struct reggroup *
574 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
576 struct reggroup *group = NULL;
578 if (current_group != NULL)
580 group = reggroup_prev (gdbarch, current_group);
582 group = reggroup_prev (gdbarch, NULL);
587 /* A helper function to display the register window in the appropriate
593 enum tui_layout_type cur_layout = tui_current_layout ();
594 enum tui_layout_type new_layout;
595 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
596 new_layout = SRC_DATA_COMMAND;
598 new_layout = DISASSEM_DATA_COMMAND;
599 tui_set_layout (new_layout);
602 /* Implement the 'tui reg' command. Changes the register group displayed
603 in the tui register window. Displays the tui register window if it is
604 not already on display. */
607 tui_reg_command (const char *args, int from_tty)
609 struct gdbarch *gdbarch = get_current_arch ();
613 struct reggroup *group, *match = NULL;
614 size_t len = strlen (args);
616 /* Make sure the curses mode is enabled. */
619 /* Make sure the register window is visible. If not, select an
620 appropriate layout. We need to do this before trying to run the
621 'next' or 'prev' commands. */
622 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
625 struct reggroup *current_group = TUI_DATA_WIN->get_current_group ();
626 if (strncmp (args, "next", len) == 0)
627 match = tui_reg_next (current_group, gdbarch);
628 else if (strncmp (args, "prev", len) == 0)
629 match = tui_reg_prev (current_group, gdbarch);
631 /* This loop matches on the initial part of a register group
632 name. If this initial part in ARGS matches only one register
633 group then the switch is made. */
634 for (group = reggroup_next (gdbarch, NULL);
636 group = reggroup_next (gdbarch, group))
638 if (strncmp (reggroup_name (group), args, len) == 0)
641 error (_("ambiguous register group name '%s'"), args);
647 error (_("unknown register group '%s'"), args);
649 TUI_DATA_WIN->show_registers (match);
653 struct reggroup *group;
656 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
657 "either a register group,\nor one of 'next' "
658 "or 'prev'. Known register groups are:\n"));
660 for (first = 1, group = reggroup_next (gdbarch, NULL);
662 first = 0, group = reggroup_next (gdbarch, group))
665 printf_unfiltered (", ");
666 printf_unfiltered ("%s", reggroup_name (group));
669 printf_unfiltered ("\n");
673 /* Complete names of register groups, and add the special "prev" and "next"
677 tui_reggroup_completer (struct cmd_list_element *ignore,
678 completion_tracker &tracker,
679 const char *text, const char *word)
681 static const char *extra[] = { "next", "prev", NULL };
682 size_t len = strlen (word);
685 reggroup_completer (ignore, tracker, text, word);
687 /* XXXX use complete_on_enum instead? */
688 for (tmp = extra; *tmp != NULL; ++tmp)
690 if (strncmp (word, *tmp, len) == 0)
691 tracker.add_completion (make_unique_xstrdup (*tmp));
696 _initialize_tui_regs (void)
698 struct cmd_list_element **tuicmd, *cmd;
700 tuicmd = tui_get_cmd_list ();
702 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
703 TUI command to control the register window."), tuicmd);
704 set_cmd_completer (cmd, tui_reggroup_completer);