1 /* TUI display registers in window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009
4 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/>. */
25 #include "tui/tui-data.h"
33 #include "gdb_string.h"
34 #include "tui/tui-layout.h"
35 #include "tui/tui-win.h"
36 #include "tui/tui-windata.h"
37 #include "tui/tui-wingeneral.h"
38 #include "tui/tui-file.h"
39 #include "tui/tui-regs.h"
40 #include "reggroups.h"
43 #include "gdb_curses.h"
46 /*****************************************
47 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
48 ******************************************/
50 tui_display_register (struct tui_data_element *data,
51 struct tui_gen_win_info *win_info);
53 static enum tui_status tui_show_register_group (struct reggroup *group,
54 struct frame_info *frame,
55 int refresh_values_only);
57 static enum tui_status tui_get_register (struct frame_info *frame,
58 struct tui_data_element *data,
59 int regnum, int *changedp);
61 static void tui_register_format (struct frame_info *,
62 struct tui_data_element*, int);
64 static void tui_scroll_regs_forward_command (char *, int);
65 static void tui_scroll_regs_backward_command (char *, int);
69 /*****************************************
70 ** PUBLIC FUNCTIONS **
71 ******************************************/
73 /* Answer the number of the last line in the regs display. If there
74 are no registers (-1) is returned. */
76 tui_last_regs_line_no (void)
80 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
82 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
83 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
84 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
85 TUI_DATA_WIN->detail.data_display_info.regs_column_count)
92 /* Answer the line number that the register element at element_no is
93 on. If element_no is greater than the number of register elements
94 there are, -1 is returned. */
96 tui_line_from_reg_element_no (int element_no)
98 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
106 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
119 /* Answer the index of the first element in line_no. If line_no is
120 past the register area (-1) is returned. */
122 tui_first_reg_element_no_inline (int line_no)
124 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
125 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
126 return ((line_no + 1) *
127 TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
128 TUI_DATA_WIN->detail.data_display_info.regs_column_count;
134 /* Answer the index of the last element in line_no. If line_no is
135 past the register area (-1) is returned. */
137 tui_last_reg_element_no_in_line (int line_no)
139 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
140 TUI_DATA_WIN->detail.data_display_info.regs_content_count)
141 return ((line_no + 1) *
142 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
147 /* Show the registers of the given group in the data window
148 and refresh the window. */
150 tui_show_registers (struct reggroup *group)
152 enum tui_status ret = TUI_FAILURE;
153 struct tui_data_info *display_info;
155 /* Make sure the curses mode is enabled. */
158 /* Make sure the register window is visible. If not, select an
159 appropriate layout. */
160 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
161 tui_set_layout_for_display_command (DATA_NAME);
163 display_info = &TUI_DATA_WIN->detail.data_display_info;
165 group = general_reggroup;
167 /* Say that registers should be displayed, even if there is a
169 display_info->display_regs = TRUE;
171 if (target_has_registers && target_has_stack && target_has_memory)
173 ret = tui_show_register_group (group, get_current_frame (),
174 group == display_info->current_group);
176 if (ret == TUI_FAILURE)
178 display_info->current_group = 0;
179 tui_erase_data_content (NO_REGS_STRING);
185 /* Clear all notation of changed values. */
186 for (i = 0; i < display_info->regs_content_count; i++)
188 struct tui_gen_win_info *data_item_win;
189 struct tui_win_element *win;
191 data_item_win = &display_info->regs_content[i]
192 ->which_element.data_window;
193 win = (struct tui_win_element *) data_item_win->content[0];
194 win->which_element.data.highlight = FALSE;
196 display_info->current_group = group;
197 tui_display_all_data ();
202 /* Set the data window to display the registers of the register group
203 using the given frame. Values are refreshed only when
204 refresh_values_only is TRUE. */
206 static enum tui_status
207 tui_show_register_group (struct reggroup *group,
208 struct frame_info *frame,
209 int refresh_values_only)
211 struct gdbarch *gdbarch = get_frame_arch (frame);
212 enum tui_status ret = TUI_FAILURE;
214 int allocated_here = FALSE;
217 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
219 /* Make a new title showing which group we display. */
220 snprintf (title, sizeof (title) - 1, "Register group: %s",
221 reggroup_name (group));
222 xfree (TUI_DATA_WIN->generic.title);
223 TUI_DATA_WIN->generic.title = xstrdup (title);
225 /* See how many registers must be displayed. */
228 regnum < gdbarch_num_regs (gdbarch)
229 + gdbarch_num_pseudo_regs (gdbarch);
232 /* Must be in the group and have a name. */
233 if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
234 && gdbarch_register_name (gdbarch, regnum) != 0)
238 if (display_info->regs_content_count > 0 && !refresh_values_only)
240 tui_free_data_content (display_info->regs_content,
241 display_info->regs_content_count);
242 display_info->regs_content_count = 0;
245 if (display_info->regs_content_count <= 0)
247 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
248 allocated_here = TRUE;
249 refresh_values_only = FALSE;
252 if (display_info->regs_content != (tui_win_content) NULL)
254 if (!refresh_values_only || allocated_here)
256 TUI_DATA_WIN->generic.content = (void*) NULL;
257 TUI_DATA_WIN->generic.content_size = 0;
258 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
259 display_info->regs_content
260 = (tui_win_content) TUI_DATA_WIN->generic.content;
261 display_info->regs_content_count = nr_regs;
264 /* Now set the register names and values. */
267 regnum < gdbarch_num_regs (gdbarch)
268 + gdbarch_num_pseudo_regs (gdbarch);
271 struct tui_gen_win_info *data_item_win;
272 struct tui_data_element *data;
275 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
278 name = gdbarch_register_name (gdbarch, regnum);
283 &display_info->regs_content[pos]->which_element.data_window;
285 &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
288 if (!refresh_values_only)
290 data->item_no = regnum;
292 data->highlight = FALSE;
294 if (data->value == (void*) NULL)
295 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
297 tui_get_register (frame, data, regnum, 0);
302 TUI_DATA_WIN->generic.content_size =
303 display_info->regs_content_count + display_info->data_content_count;
310 /* Function to display the registers in the content from
311 'start_element_no' until the end of the register content or the end
312 of the display height. No checking for displaying past the end of
313 the registers is done here. */
315 tui_display_registers_from (int start_element_no)
317 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
319 if (display_info->regs_content != (tui_win_content) NULL
320 && display_info->regs_content_count > 0)
322 int i = start_element_no;
323 int j, value_chars_wide, item_win_width, cur_y;
326 for (i = 0; i < display_info->regs_content_count; i++)
328 struct tui_data_element *data;
329 struct tui_gen_win_info *data_item_win;
333 data_item_win = &display_info->regs_content[i]->which_element.data_window;
334 data = &((struct tui_win_element *)
335 data_item_win->content[0])->which_element.data;
342 len = 8 * ((len / 8) + 1);
350 item_win_width = max_len + 1;
351 i = start_element_no;
353 display_info->regs_column_count =
354 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
355 if (display_info->regs_column_count == 0)
356 display_info->regs_column_count = 1;
358 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
360 /* Now create each data "sub" window, and write the display into
363 while (i < display_info->regs_content_count
364 && cur_y <= TUI_DATA_WIN->generic.viewport_height)
367 j < display_info->regs_column_count
368 && i < display_info->regs_content_count;
371 struct tui_gen_win_info *data_item_win;
372 struct tui_data_element *data_element_ptr;
374 /* Create the window if necessary. */
375 data_item_win = &display_info->regs_content[i]
376 ->which_element.data_window;
377 data_element_ptr = &((struct tui_win_element *)
378 data_item_win->content[0])->which_element.data;
379 if (data_item_win->handle != (WINDOW*) NULL
380 && (data_item_win->height != 1
381 || data_item_win->width != item_win_width
382 || data_item_win->origin.x != (item_win_width * j) + 1
383 || data_item_win->origin.y != cur_y))
385 tui_delete_win (data_item_win->handle);
386 data_item_win->handle = 0;
389 if (data_item_win->handle == (WINDOW *) NULL)
391 data_item_win->height = 1;
392 data_item_win->width = item_win_width;
393 data_item_win->origin.x = (item_win_width * j) + 1;
394 data_item_win->origin.y = cur_y;
395 tui_make_window (data_item_win, DONT_BOX_WINDOW);
396 scrollok (data_item_win->handle, FALSE);
398 touchwin (data_item_win->handle);
400 /* Get the printable representation of the register
402 tui_display_register (data_element_ptr, data_item_win);
403 i++; /* Next register. */
405 cur_y++; /* Next row. */
411 /* Function to display the registers in the content from
412 'start_element_no' on 'start_line_no' until the end of the register
413 content or the end of the display height. This function checks
414 that we won't display off the end of the register display. */
416 tui_display_reg_element_at_line (int start_element_no,
419 if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL
420 && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
422 int element_no = start_element_no;
424 if (start_element_no != 0 && start_line_no != 0)
426 int last_line_no, first_line_on_last_page;
428 last_line_no = tui_last_regs_line_no ();
429 first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
430 if (first_line_on_last_page < 0)
431 first_line_on_last_page = 0;
433 /* If there is no other data displayed except registers, and
434 the element_no causes us to scroll past the end of the
435 registers, adjust what element to really start the
437 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
438 && start_line_no > first_line_on_last_page)
439 element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
441 tui_display_registers_from (element_no);
447 /* Function to display the registers starting at line line_no in the
448 data window. Answers the line number that the display actually
449 started from. If nothing is displayed (-1) is returned. */
451 tui_display_registers_from_line (int line_no,
454 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
456 int line, element_no;
460 else if (force_display)
461 { /* If we must display regs (force_display is true), then
462 make sure that we don't display off the end of the
464 if (line_no >= tui_last_regs_line_no ())
466 if ((line = tui_line_from_reg_element_no (
467 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
476 element_no = tui_first_reg_element_no_inline (line);
477 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
478 tui_display_reg_element_at_line (element_no, line);
485 return (-1); /* Nothing was displayed. */
489 /* This function check all displayed registers for changes in values,
490 given a particular frame. If the values have changed, they are
491 updated with the new value and highlighted. */
493 tui_check_register_values (struct frame_info *frame)
495 if (TUI_DATA_WIN != NULL
496 && TUI_DATA_WIN->generic.is_visible)
498 struct tui_data_info *display_info
499 = &TUI_DATA_WIN->detail.data_display_info;
501 if (display_info->regs_content_count <= 0
502 && display_info->display_regs)
503 tui_show_registers (display_info->current_group);
508 for (i = 0; (i < display_info->regs_content_count); i++)
510 struct tui_data_element *data;
511 struct tui_gen_win_info *data_item_win_ptr;
514 data_item_win_ptr = &display_info->regs_content[i]->
515 which_element.data_window;
516 data = &((struct tui_win_element *)
517 data_item_win_ptr->content[0])->which_element.data;
518 was_hilighted = data->highlight;
520 tui_get_register (frame, data,
521 data->item_no, &data->highlight);
523 if (data->highlight || was_hilighted)
525 tui_display_register (data, data_item_win_ptr);
532 /* Display a register in a window. If hilite is TRUE, then the value
533 will be displayed in reverse video. */
535 tui_display_register (struct tui_data_element *data,
536 struct tui_gen_win_info *win_info)
538 if (win_info->handle != (WINDOW *) NULL)
543 wstandout (win_info->handle);
545 wmove (win_info->handle, 0, 0);
546 for (i = 1; i < win_info->width; i++)
547 waddch (win_info->handle, ' ');
548 wmove (win_info->handle, 0, 0);
550 waddstr (win_info->handle, data->content);
553 wstandend (win_info->handle);
554 tui_refresh_win (win_info);
559 tui_reg_next_command (char *arg, int from_tty)
561 if (TUI_DATA_WIN != 0)
563 struct reggroup *group
564 = TUI_DATA_WIN->detail.data_display_info.current_group;
566 group = reggroup_next (current_gdbarch, group);
568 group = reggroup_next (current_gdbarch, 0);
571 tui_show_registers (group);
576 tui_reg_float_command (char *arg, int from_tty)
578 tui_show_registers (float_reggroup);
582 tui_reg_general_command (char *arg, int from_tty)
584 tui_show_registers (general_reggroup);
588 tui_reg_system_command (char *arg, int from_tty)
590 tui_show_registers (system_reggroup);
593 static struct cmd_list_element *tuireglist;
596 tui_reg_command (char *args, int from_tty)
598 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
599 "tui reg command.\n"));
600 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
603 /* Provide a prototype to silence -Wmissing-prototypes. */
604 extern initialize_file_ftype _initialize_tui_regs;
607 _initialize_tui_regs (void)
609 struct cmd_list_element **tuicmd;
611 tuicmd = tui_get_cmd_list ();
613 add_prefix_cmd ("reg", class_tui, tui_reg_command,
614 _("TUI commands to control the register window."),
615 &tuireglist, "tui reg ", 0,
618 add_cmd ("float", class_tui, tui_reg_float_command,
619 _("Display only floating point registers."),
621 add_cmd ("general", class_tui, tui_reg_general_command,
622 _("Display only general registers."),
624 add_cmd ("system", class_tui, tui_reg_system_command,
625 _("Display only system registers."),
627 add_cmd ("next", class_tui, tui_reg_next_command,
628 _("Display next register group."),
633 add_com ("fr", class_tui, tui_reg_float_command,
634 _("Display only floating point registers\n"));
635 add_com ("gr", class_tui, tui_reg_general_command,
636 _("Display only general registers\n"));
637 add_com ("sr", class_tui, tui_reg_system_command,
638 _("Display only special registers\n"));
639 add_com ("+r", class_tui, tui_scroll_regs_forward_command,
640 _("Scroll the registers window forward\n"));
641 add_com ("-r", class_tui, tui_scroll_regs_backward_command,
642 _("Scroll the register window backward\n"));
647 /*****************************************
648 ** STATIC LOCAL FUNCTIONS **
649 ******************************************/
651 extern int pagination_enabled;
654 tui_restore_gdbout (void *ui)
656 ui_file_delete (gdb_stdout);
657 gdb_stdout = (struct ui_file*) ui;
658 pagination_enabled = 1;
661 /* Get the register from the frame and make a printable representation
662 of it in the data element. */
664 tui_register_format (struct frame_info *frame,
665 struct tui_data_element *data_element,
668 struct gdbarch *gdbarch = get_frame_arch (frame);
669 struct ui_file *stream;
670 struct ui_file *old_stdout;
672 struct cleanup *cleanups;
675 struct type *type = register_type (gdbarch, regnum);
677 name = gdbarch_register_name (gdbarch, regnum);
683 pagination_enabled = 0;
684 old_stdout = gdb_stdout;
685 stream = tui_sfileopen (256);
687 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
688 if (TYPE_VECTOR (type) != 0 && 0)
690 gdb_byte buf[MAX_REGISTER_SIZE];
692 struct value_print_options opts;
694 len = register_size (gdbarch, regnum);
695 fprintf_filtered (stream, "%-14s ", name);
696 get_frame_register (frame, regnum, buf);
697 get_formatted_print_options (&opts, 'f');
698 print_scalar_formatted (buf, type, &opts, len, stream);
702 gdbarch_print_registers_info (gdbarch, stream,
706 /* Save formatted output in the buffer. */
707 p = tui_file_get_strbuf (stream);
709 /* Remove the possible \n. */
710 s = strrchr (p, '\n');
714 xfree (data_element->content);
715 data_element->content = xstrdup (p);
716 do_cleanups (cleanups);
719 /* Get the register value from the given frame and format it for the
720 display. When changep is set, check if the new register value has
721 changed with respect to the previous call. */
722 static enum tui_status
723 tui_get_register (struct frame_info *frame,
724 struct tui_data_element *data,
725 int regnum, int *changedp)
727 enum tui_status ret = TUI_FAILURE;
731 if (target_has_registers)
733 gdb_byte buf[MAX_REGISTER_SIZE];
734 get_frame_register (frame, regnum, buf);
738 struct gdbarch *gdbarch = get_frame_arch (frame);
739 int size = register_size (gdbarch, regnum);
740 char *old = (char*) data->value;
743 for (i = 0; i < size; i++)
744 if (buf[i] != old[i])
751 /* Reformat the data content if the value changed. */
752 if (changedp == 0 || *changedp == TRUE)
753 tui_register_format (frame, data, regnum);
761 tui_scroll_regs_forward_command (char *arg, int from_tty)
763 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
768 tui_scroll_regs_backward_command (char *arg, int from_tty)
770 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);