1 /* TUI display registers in window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009,
4 2010, 2011 Free Software Foundation, Inc.
6 Contributed by Hewlett-Packard Company.
8 This file is part of GDB.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #include "arch-utils.h"
26 #include "tui/tui-data.h"
34 #include "gdb_string.h"
35 #include "tui/tui-layout.h"
36 #include "tui/tui-win.h"
37 #include "tui/tui-windata.h"
38 #include "tui/tui-wingeneral.h"
39 #include "tui/tui-file.h"
40 #include "tui/tui-regs.h"
41 #include "reggroups.h"
44 #include "gdb_curses.h"
47 /*****************************************
48 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
49 ******************************************/
51 tui_display_register (struct tui_data_element *data,
52 struct tui_gen_win_info *win_info);
54 static enum tui_status tui_show_register_group (struct reggroup *group,
55 struct frame_info *frame,
56 int refresh_values_only);
58 static enum tui_status tui_get_register (struct frame_info *frame,
59 struct tui_data_element *data,
60 int regnum, int *changedp);
62 static void tui_register_format (struct frame_info *,
63 struct tui_data_element*, int);
65 static void tui_scroll_regs_forward_command (char *, int);
66 static void tui_scroll_regs_backward_command (char *, int);
70 /*****************************************
71 ** PUBLIC FUNCTIONS **
72 ******************************************/
74 /* Answer the number of the last line in the regs display. If there
75 are no registers (-1) is returned. */
77 tui_last_regs_line_no (void)
81 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
83 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
84 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
85 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
86 TUI_DATA_WIN->detail.data_display_info.regs_column_count)
93 /* Answer the line number that the register element at element_no is
94 on. If element_no is greater than the number of register elements
95 there are, -1 is returned. */
97 tui_line_from_reg_element_no (int element_no)
99 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
107 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
120 /* Answer the index of the first element in line_no. If line_no is
121 past the register area (-1) is returned. */
123 tui_first_reg_element_no_inline (int line_no)
125 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
126 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
127 return ((line_no + 1) *
128 TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
129 TUI_DATA_WIN->detail.data_display_info.regs_column_count;
135 /* Answer the index of the last element in line_no. If line_no is
136 past the register area (-1) is returned. */
138 tui_last_reg_element_no_in_line (int line_no)
140 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
141 TUI_DATA_WIN->detail.data_display_info.regs_content_count)
142 return ((line_no + 1) *
143 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
148 /* Show the registers of the given group in the data window
149 and refresh the window. */
151 tui_show_registers (struct reggroup *group)
153 enum tui_status ret = TUI_FAILURE;
154 struct tui_data_info *display_info;
156 /* Make sure the curses mode is enabled. */
159 /* Make sure the register window is visible. If not, select an
160 appropriate layout. */
161 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
162 tui_set_layout_for_display_command (DATA_NAME);
164 display_info = &TUI_DATA_WIN->detail.data_display_info;
166 group = general_reggroup;
168 /* Say that registers should be displayed, even if there is a
170 display_info->display_regs = TRUE;
172 if (target_has_registers && target_has_stack && target_has_memory)
174 ret = tui_show_register_group (group, get_current_frame (),
175 group == display_info->current_group);
177 if (ret == TUI_FAILURE)
179 display_info->current_group = 0;
180 tui_erase_data_content (NO_REGS_STRING);
186 /* Clear all notation of changed values. */
187 for (i = 0; i < display_info->regs_content_count; i++)
189 struct tui_gen_win_info *data_item_win;
190 struct tui_win_element *win;
192 data_item_win = &display_info->regs_content[i]
193 ->which_element.data_window;
194 win = (struct tui_win_element *) data_item_win->content[0];
195 win->which_element.data.highlight = FALSE;
197 display_info->current_group = group;
198 tui_display_all_data ();
203 /* Set the data window to display the registers of the register group
204 using the given frame. Values are refreshed only when
205 refresh_values_only is TRUE. */
207 static enum tui_status
208 tui_show_register_group (struct reggroup *group,
209 struct frame_info *frame,
210 int refresh_values_only)
212 struct gdbarch *gdbarch = get_frame_arch (frame);
213 enum tui_status ret = TUI_FAILURE;
215 int allocated_here = FALSE;
218 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
220 /* Make a new title showing which group we display. */
221 snprintf (title, sizeof (title) - 1, "Register group: %s",
222 reggroup_name (group));
223 xfree (TUI_DATA_WIN->generic.title);
224 TUI_DATA_WIN->generic.title = xstrdup (title);
226 /* See how many registers must be displayed. */
229 regnum < gdbarch_num_regs (gdbarch)
230 + gdbarch_num_pseudo_regs (gdbarch);
233 /* Must be in the group and have a name. */
234 if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
235 && gdbarch_register_name (gdbarch, regnum) != 0)
239 if (display_info->regs_content_count > 0 && !refresh_values_only)
241 tui_free_data_content (display_info->regs_content,
242 display_info->regs_content_count);
243 display_info->regs_content_count = 0;
246 if (display_info->regs_content_count <= 0)
248 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
249 allocated_here = TRUE;
250 refresh_values_only = FALSE;
253 if (display_info->regs_content != (tui_win_content) NULL)
255 if (!refresh_values_only || allocated_here)
257 TUI_DATA_WIN->generic.content = (void*) NULL;
258 TUI_DATA_WIN->generic.content_size = 0;
259 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
260 display_info->regs_content
261 = (tui_win_content) TUI_DATA_WIN->generic.content;
262 display_info->regs_content_count = nr_regs;
265 /* Now set the register names and values. */
268 regnum < gdbarch_num_regs (gdbarch)
269 + gdbarch_num_pseudo_regs (gdbarch);
272 struct tui_gen_win_info *data_item_win;
273 struct tui_data_element *data;
276 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
279 name = gdbarch_register_name (gdbarch, regnum);
284 &display_info->regs_content[pos]->which_element.data_window;
286 &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
289 if (!refresh_values_only)
291 data->item_no = regnum;
293 data->highlight = FALSE;
295 if (data->value == (void*) NULL)
296 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
298 tui_get_register (frame, data, regnum, 0);
303 TUI_DATA_WIN->generic.content_size =
304 display_info->regs_content_count + display_info->data_content_count;
311 /* Function to display the registers in the content from
312 'start_element_no' until the end of the register content or the end
313 of the display height. No checking for displaying past the end of
314 the registers is done here. */
316 tui_display_registers_from (int start_element_no)
318 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
320 if (display_info->regs_content != (tui_win_content) NULL
321 && display_info->regs_content_count > 0)
323 int i = start_element_no;
324 int j, item_win_width, cur_y;
327 for (i = 0; i < display_info->regs_content_count; i++)
329 struct tui_data_element *data;
330 struct tui_gen_win_info *data_item_win;
334 data_item_win = &display_info->regs_content[i]->which_element.data_window;
335 data = &((struct tui_win_element *)
336 data_item_win->content[0])->which_element.data;
343 len = 8 * ((len / 8) + 1);
351 item_win_width = max_len + 1;
352 i = start_element_no;
354 display_info->regs_column_count =
355 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
356 if (display_info->regs_column_count == 0)
357 display_info->regs_column_count = 1;
359 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
361 /* Now create each data "sub" window, and write the display into
364 while (i < display_info->regs_content_count
365 && cur_y <= TUI_DATA_WIN->generic.viewport_height)
368 j < display_info->regs_column_count
369 && i < display_info->regs_content_count;
372 struct tui_gen_win_info *data_item_win;
373 struct tui_data_element *data_element_ptr;
375 /* Create the window if necessary. */
376 data_item_win = &display_info->regs_content[i]
377 ->which_element.data_window;
378 data_element_ptr = &((struct tui_win_element *)
379 data_item_win->content[0])->which_element.data;
380 if (data_item_win->handle != (WINDOW*) NULL
381 && (data_item_win->height != 1
382 || data_item_win->width != item_win_width
383 || data_item_win->origin.x != (item_win_width * j) + 1
384 || data_item_win->origin.y != cur_y))
386 tui_delete_win (data_item_win->handle);
387 data_item_win->handle = 0;
390 if (data_item_win->handle == (WINDOW *) NULL)
392 data_item_win->height = 1;
393 data_item_win->width = item_win_width;
394 data_item_win->origin.x = (item_win_width * j) + 1;
395 data_item_win->origin.y = cur_y;
396 tui_make_window (data_item_win, DONT_BOX_WINDOW);
397 scrollok (data_item_win->handle, FALSE);
399 touchwin (data_item_win->handle);
401 /* Get the printable representation of the register
403 tui_display_register (data_element_ptr, data_item_win);
404 i++; /* Next register. */
406 cur_y++; /* Next row. */
412 /* Function to display the registers in the content from
413 'start_element_no' on 'start_line_no' until the end of the register
414 content or the end of the display height. This function checks
415 that we won't display off the end of the register display. */
417 tui_display_reg_element_at_line (int start_element_no,
420 if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL
421 && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
423 int element_no = start_element_no;
425 if (start_element_no != 0 && start_line_no != 0)
427 int last_line_no, first_line_on_last_page;
429 last_line_no = tui_last_regs_line_no ();
430 first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
431 if (first_line_on_last_page < 0)
432 first_line_on_last_page = 0;
434 /* If there is no other data displayed except registers, and
435 the element_no causes us to scroll past the end of the
436 registers, adjust what element to really start the
438 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
439 && start_line_no > first_line_on_last_page)
440 element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
442 tui_display_registers_from (element_no);
448 /* Function to display the registers starting at line line_no in the
449 data window. Answers the line number that the display actually
450 started from. If nothing is displayed (-1) is returned. */
452 tui_display_registers_from_line (int line_no,
455 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
457 int line, element_no;
461 else if (force_display)
462 { /* If we must display regs (force_display is true), then
463 make sure that we don't display off the end of the
465 if (line_no >= tui_last_regs_line_no ())
467 if ((line = tui_line_from_reg_element_no (
468 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
477 element_no = tui_first_reg_element_no_inline (line);
478 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
479 tui_display_reg_element_at_line (element_no, line);
486 return (-1); /* Nothing was displayed. */
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_check_register_values (struct frame_info *frame)
496 if (TUI_DATA_WIN != NULL
497 && TUI_DATA_WIN->generic.is_visible)
499 struct tui_data_info *display_info
500 = &TUI_DATA_WIN->detail.data_display_info;
502 if (display_info->regs_content_count <= 0
503 && display_info->display_regs)
504 tui_show_registers (display_info->current_group);
509 for (i = 0; (i < display_info->regs_content_count); i++)
511 struct tui_data_element *data;
512 struct tui_gen_win_info *data_item_win_ptr;
515 data_item_win_ptr = &display_info->regs_content[i]->
516 which_element.data_window;
517 data = &((struct tui_win_element *)
518 data_item_win_ptr->content[0])->which_element.data;
519 was_hilighted = data->highlight;
521 tui_get_register (frame, data,
522 data->item_no, &data->highlight);
524 if (data->highlight || was_hilighted)
526 tui_display_register (data, data_item_win_ptr);
533 /* Display a register in a window. If hilite is TRUE, then the value
534 will be displayed in reverse video. */
536 tui_display_register (struct tui_data_element *data,
537 struct tui_gen_win_info *win_info)
539 if (win_info->handle != (WINDOW *) NULL)
544 /* We ignore the return value, casting it to void in order to avoid
545 a compiler warning. The warning itself was introduced by a patch
546 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
547 to code that causes the compiler to generate an unused-value
549 (void) wstandout (win_info->handle);
551 wmove (win_info->handle, 0, 0);
552 for (i = 1; i < win_info->width; i++)
553 waddch (win_info->handle, ' ');
554 wmove (win_info->handle, 0, 0);
556 waddstr (win_info->handle, data->content);
559 /* We ignore the return value, casting it to void in order to avoid
560 a compiler warning. The warning itself was introduced by a patch
561 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
562 to code that causes the compiler to generate an unused-value
564 (void) wstandend (win_info->handle);
565 tui_refresh_win (win_info);
570 tui_reg_next_command (char *arg, int from_tty)
572 struct gdbarch *gdbarch = get_current_arch ();
574 if (TUI_DATA_WIN != 0)
576 struct reggroup *group
577 = TUI_DATA_WIN->detail.data_display_info.current_group;
579 group = reggroup_next (gdbarch, group);
581 group = reggroup_next (gdbarch, 0);
584 tui_show_registers (group);
589 tui_reg_float_command (char *arg, int from_tty)
591 tui_show_registers (float_reggroup);
595 tui_reg_general_command (char *arg, int from_tty)
597 tui_show_registers (general_reggroup);
601 tui_reg_system_command (char *arg, int from_tty)
603 tui_show_registers (system_reggroup);
606 static struct cmd_list_element *tuireglist;
609 tui_reg_command (char *args, int from_tty)
611 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
612 "tui reg command.\n"));
613 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
616 /* Provide a prototype to silence -Wmissing-prototypes. */
617 extern initialize_file_ftype _initialize_tui_regs;
620 _initialize_tui_regs (void)
622 struct cmd_list_element **tuicmd;
624 tuicmd = tui_get_cmd_list ();
626 add_prefix_cmd ("reg", class_tui, tui_reg_command,
627 _("TUI commands to control the register window."),
628 &tuireglist, "tui reg ", 0,
631 add_cmd ("float", class_tui, tui_reg_float_command,
632 _("Display only floating point registers."),
634 add_cmd ("general", class_tui, tui_reg_general_command,
635 _("Display only general registers."),
637 add_cmd ("system", class_tui, tui_reg_system_command,
638 _("Display only system registers."),
640 add_cmd ("next", class_tui, tui_reg_next_command,
641 _("Display next register group."),
646 add_com ("fr", class_tui, tui_reg_float_command,
647 _("Display only floating point registers\n"));
648 add_com ("gr", class_tui, tui_reg_general_command,
649 _("Display only general registers\n"));
650 add_com ("sr", class_tui, tui_reg_system_command,
651 _("Display only special registers\n"));
652 add_com ("+r", class_tui, tui_scroll_regs_forward_command,
653 _("Scroll the registers window forward\n"));
654 add_com ("-r", class_tui, tui_scroll_regs_backward_command,
655 _("Scroll the register window backward\n"));
660 /*****************************************
661 ** STATIC LOCAL FUNCTIONS **
662 ******************************************/
664 extern int pagination_enabled;
667 tui_restore_gdbout (void *ui)
669 ui_file_delete (gdb_stdout);
670 gdb_stdout = (struct ui_file*) ui;
671 pagination_enabled = 1;
674 /* Get the register from the frame and make a printable representation
675 of it in the data element. */
677 tui_register_format (struct frame_info *frame,
678 struct tui_data_element *data_element,
681 struct gdbarch *gdbarch = get_frame_arch (frame);
682 struct ui_file *stream;
683 struct ui_file *old_stdout;
685 struct cleanup *cleanups;
687 struct type *type = register_type (gdbarch, regnum);
689 name = gdbarch_register_name (gdbarch, regnum);
695 pagination_enabled = 0;
696 old_stdout = gdb_stdout;
697 stream = tui_sfileopen (256);
699 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
700 if (TYPE_VECTOR (type) != 0 && 0)
702 gdb_byte buf[MAX_REGISTER_SIZE];
704 struct value_print_options opts;
706 len = register_size (gdbarch, regnum);
707 fprintf_filtered (stream, "%-14s ", name);
708 get_frame_register (frame, regnum, buf);
709 get_formatted_print_options (&opts, 'f');
710 print_scalar_formatted (buf, type, &opts, len, stream);
714 gdbarch_print_registers_info (gdbarch, stream,
718 /* Save formatted output in the buffer. */
719 p = tui_file_get_strbuf (stream);
721 /* Remove the possible \n. */
722 s = strrchr (p, '\n');
726 xfree (data_element->content);
727 data_element->content = xstrdup (p);
728 do_cleanups (cleanups);
731 /* Get the register value from the given frame and format it for the
732 display. When changep is set, check if the new register value has
733 changed with respect to the previous call. */
734 static enum tui_status
735 tui_get_register (struct frame_info *frame,
736 struct tui_data_element *data,
737 int regnum, int *changedp)
739 enum tui_status ret = TUI_FAILURE;
743 if (target_has_registers)
745 gdb_byte buf[MAX_REGISTER_SIZE];
747 get_frame_register (frame, regnum, buf);
750 struct gdbarch *gdbarch = get_frame_arch (frame);
751 int size = register_size (gdbarch, regnum);
752 char *old = (char*) data->value;
755 for (i = 0; i < size; i++)
756 if (buf[i] != old[i])
763 /* Reformat the data content if the value changed. */
764 if (changedp == 0 || *changedp == TRUE)
765 tui_register_format (frame, data, regnum);
773 tui_scroll_regs_forward_command (char *arg, int from_tty)
775 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
780 tui_scroll_regs_backward_command (char *arg, int from_tty)
782 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);