1 /* TUI display registers in window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008
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 "reggroups.h"
41 #include "gdb_curses.h"
44 /*****************************************
45 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
46 ******************************************/
48 tui_display_register (struct tui_data_element *data,
49 struct tui_gen_win_info *win_info);
51 static enum tui_status
52 tui_show_register_group (struct gdbarch *gdbarch,
53 struct reggroup *group,
54 struct frame_info *frame,
55 int refresh_values_only);
57 static enum tui_status
58 tui_get_register (struct gdbarch *gdbarch,
59 struct frame_info *frame,
60 struct tui_data_element *data,
61 int regnum, int *changedp);
62 static void tui_register_format (struct gdbarch *,
64 struct tui_data_element*,
66 static void tui_scroll_regs_forward_command (char *, int);
67 static void tui_scroll_regs_backward_command (char *, int);
71 /*****************************************
72 ** PUBLIC FUNCTIONS **
73 ******************************************/
75 /* Answer the number of the last line in the regs display. If there
76 are no registers (-1) is returned. */
78 tui_last_regs_line_no (void)
82 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
84 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
85 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
86 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
87 TUI_DATA_WIN->detail.data_display_info.regs_column_count)
94 /* Answer the line number that the register element at element_no is
95 on. If element_no is greater than the number of register elements
96 there are, -1 is returned. */
98 tui_line_from_reg_element_no (int element_no)
100 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
108 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
121 /* Answer the index of the first element in line_no. If line_no is
122 past the register area (-1) is returned. */
124 tui_first_reg_element_no_inline (int line_no)
126 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
127 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
128 return ((line_no + 1) *
129 TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
130 TUI_DATA_WIN->detail.data_display_info.regs_column_count;
136 /* Answer the index of the last element in line_no. If line_no is
137 past the register area (-1) is returned. */
139 tui_last_reg_element_no_in_line (int line_no)
141 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
142 TUI_DATA_WIN->detail.data_display_info.regs_content_count)
143 return ((line_no + 1) *
144 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
149 /* Show the registers of the given group in the data window
150 and refresh the window. */
152 tui_show_registers (struct reggroup *group)
154 enum tui_status ret = TUI_FAILURE;
155 struct tui_data_info *display_info;
157 /* Make sure the curses mode is enabled. */
160 /* Make sure the register window is visible. If not, select an
161 appropriate layout. */
162 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
163 tui_set_layout_for_display_command (DATA_NAME);
165 display_info = &TUI_DATA_WIN->detail.data_display_info;
167 group = general_reggroup;
169 /* Say that registers should be displayed, even if there is a
171 display_info->display_regs = TRUE;
173 if (target_has_registers && target_has_stack && target_has_memory)
175 ret = tui_show_register_group (current_gdbarch, group,
176 get_current_frame (),
177 group == display_info->current_group);
179 if (ret == TUI_FAILURE)
181 display_info->current_group = 0;
182 tui_erase_data_content (NO_REGS_STRING);
188 /* Clear all notation of changed values. */
189 for (i = 0; i < display_info->regs_content_count; i++)
191 struct tui_gen_win_info *data_item_win;
192 struct tui_win_element *win;
194 data_item_win = &display_info->regs_content[i]
195 ->which_element.data_window;
196 win = (struct tui_win_element *) data_item_win->content[0];
197 win->which_element.data.highlight = FALSE;
199 display_info->current_group = group;
200 tui_display_all_data ();
205 /* Set the data window to display the registers of the register group
206 using the given frame. Values are refreshed only when
207 refresh_values_only is TRUE. */
209 static enum tui_status
210 tui_show_register_group (struct gdbarch *gdbarch,
211 struct reggroup *group,
212 struct frame_info *frame,
213 int refresh_values_only)
215 enum tui_status ret = TUI_FAILURE;
217 int allocated_here = FALSE;
220 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
222 /* Make a new title showing which group we display. */
223 snprintf (title, sizeof (title) - 1, "Register group: %s",
224 reggroup_name (group));
225 xfree (TUI_DATA_WIN->generic.title);
226 TUI_DATA_WIN->generic.title = xstrdup (title);
228 /* See how many registers must be displayed. */
231 regnum < gdbarch_num_regs (current_gdbarch)
232 + gdbarch_num_pseudo_regs (current_gdbarch);
235 /* Must be in the group and have a name. */
236 if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
237 && gdbarch_register_name (gdbarch, regnum) != 0)
241 if (display_info->regs_content_count > 0 && !refresh_values_only)
243 tui_free_data_content (display_info->regs_content,
244 display_info->regs_content_count);
245 display_info->regs_content_count = 0;
248 if (display_info->regs_content_count <= 0)
250 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
251 allocated_here = TRUE;
252 refresh_values_only = FALSE;
255 if (display_info->regs_content != (tui_win_content) NULL)
257 if (!refresh_values_only || allocated_here)
259 TUI_DATA_WIN->generic.content = (void*) NULL;
260 TUI_DATA_WIN->generic.content_size = 0;
261 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
262 display_info->regs_content
263 = (tui_win_content) TUI_DATA_WIN->generic.content;
264 display_info->regs_content_count = nr_regs;
267 /* Now set the register names and values. */
270 regnum < gdbarch_num_regs (current_gdbarch)
271 + gdbarch_num_pseudo_regs (current_gdbarch);
274 struct tui_gen_win_info *data_item_win;
275 struct tui_data_element *data;
278 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
281 name = gdbarch_register_name (gdbarch, regnum);
286 &display_info->regs_content[pos]->which_element.data_window;
288 &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
291 if (!refresh_values_only)
293 data->item_no = regnum;
295 data->highlight = FALSE;
297 if (data->value == (void*) NULL)
298 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
300 tui_get_register (gdbarch, frame, data, regnum, 0);
305 TUI_DATA_WIN->generic.content_size =
306 display_info->regs_content_count + display_info->data_content_count;
313 /* Function to display the registers in the content from
314 'start_element_no' until the end of the register content or the end
315 of the display height. No checking for displaying past the end of
316 the registers is done here. */
318 tui_display_registers_from (int start_element_no)
320 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
322 if (display_info->regs_content != (tui_win_content) NULL
323 && display_info->regs_content_count > 0)
325 int i = start_element_no;
326 int j, value_chars_wide, item_win_width, cur_y;
329 for (i = 0; i < display_info->regs_content_count; i++)
331 struct tui_data_element *data;
332 struct tui_gen_win_info *data_item_win;
336 data_item_win = &display_info->regs_content[i]->which_element.data_window;
337 data = &((struct tui_win_element *)
338 data_item_win->content[0])->which_element.data;
345 len = 8 * ((len / 8) + 1);
353 item_win_width = max_len + 1;
354 i = start_element_no;
356 display_info->regs_column_count =
357 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
358 if (display_info->regs_column_count == 0)
359 display_info->regs_column_count = 1;
361 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
363 /* Now create each data "sub" window, and write the display into
366 while (i < display_info->regs_content_count
367 && cur_y <= TUI_DATA_WIN->generic.viewport_height)
370 j < display_info->regs_column_count
371 && i < display_info->regs_content_count;
374 struct tui_gen_win_info *data_item_win;
375 struct tui_data_element *data_element_ptr;
377 /* Create the window if necessary. */
378 data_item_win = &display_info->regs_content[i]
379 ->which_element.data_window;
380 data_element_ptr = &((struct tui_win_element *)
381 data_item_win->content[0])->which_element.data;
382 if (data_item_win->handle != (WINDOW*) NULL
383 && (data_item_win->height != 1
384 || data_item_win->width != item_win_width
385 || data_item_win->origin.x != (item_win_width * j) + 1
386 || data_item_win->origin.y != cur_y))
388 tui_delete_win (data_item_win->handle);
389 data_item_win->handle = 0;
392 if (data_item_win->handle == (WINDOW *) NULL)
394 data_item_win->height = 1;
395 data_item_win->width = item_win_width;
396 data_item_win->origin.x = (item_win_width * j) + 1;
397 data_item_win->origin.y = cur_y;
398 tui_make_window (data_item_win, DONT_BOX_WINDOW);
399 scrollok (data_item_win->handle, FALSE);
401 touchwin (data_item_win->handle);
403 /* Get the printable representation of the register
405 tui_display_register (data_element_ptr, data_item_win);
406 i++; /* Next register. */
408 cur_y++; /* Next row. */
414 /* Function to display the registers in the content from
415 'start_element_no' on 'start_line_no' until the end of the register
416 content or the end of the display height. This function checks
417 that we won't display off the end of the register display. */
419 tui_display_reg_element_at_line (int start_element_no,
422 if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL
423 && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
425 int element_no = start_element_no;
427 if (start_element_no != 0 && start_line_no != 0)
429 int last_line_no, first_line_on_last_page;
431 last_line_no = tui_last_regs_line_no ();
432 first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
433 if (first_line_on_last_page < 0)
434 first_line_on_last_page = 0;
436 /* If there is no other data displayed except registers, and
437 the element_no causes us to scroll past the end of the
438 registers, adjust what element to really start the
440 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
441 && start_line_no > first_line_on_last_page)
442 element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
444 tui_display_registers_from (element_no);
450 /* Function to display the registers starting at line line_no in the
451 data window. Answers the line number that the display actually
452 started from. If nothing is displayed (-1) is returned. */
454 tui_display_registers_from_line (int line_no,
457 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
459 int line, element_no;
463 else if (force_display)
464 { /* If we must display regs (force_display is true), then
465 make sure that we don't display off the end of the
467 if (line_no >= tui_last_regs_line_no ())
469 if ((line = tui_line_from_reg_element_no (
470 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
479 element_no = tui_first_reg_element_no_inline (line);
480 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
481 tui_display_reg_element_at_line (element_no, line);
488 return (-1); /* Nothing was displayed. */
492 /* This function check all displayed registers for changes in values,
493 given a particular frame. If the values have changed, they are
494 updated with the new value and highlighted. */
496 tui_check_register_values (struct frame_info *frame)
498 if (TUI_DATA_WIN != NULL
499 && TUI_DATA_WIN->generic.is_visible)
501 struct tui_data_info *display_info
502 = &TUI_DATA_WIN->detail.data_display_info;
504 if (display_info->regs_content_count <= 0
505 && display_info->display_regs)
506 tui_show_registers (display_info->current_group);
511 for (i = 0; (i < display_info->regs_content_count); i++)
513 struct tui_data_element *data;
514 struct tui_gen_win_info *data_item_win_ptr;
517 data_item_win_ptr = &display_info->regs_content[i]->
518 which_element.data_window;
519 data = &((struct tui_win_element *)
520 data_item_win_ptr->content[0])->which_element.data;
521 was_hilighted = data->highlight;
523 tui_get_register (current_gdbarch, frame, data,
524 data->item_no, &data->highlight);
526 if (data->highlight || was_hilighted)
528 tui_display_register (data, data_item_win_ptr);
535 /* Display a register in a window. If hilite is TRUE, then the value
536 will be displayed in reverse video. */
538 tui_display_register (struct tui_data_element *data,
539 struct tui_gen_win_info *win_info)
541 if (win_info->handle != (WINDOW *) NULL)
546 wstandout (win_info->handle);
548 wmove (win_info->handle, 0, 0);
549 for (i = 1; i < win_info->width; i++)
550 waddch (win_info->handle, ' ');
551 wmove (win_info->handle, 0, 0);
553 waddstr (win_info->handle, data->content);
556 wstandend (win_info->handle);
557 tui_refresh_win (win_info);
562 tui_reg_next_command (char *arg, int from_tty)
564 if (TUI_DATA_WIN != 0)
566 struct reggroup *group
567 = TUI_DATA_WIN->detail.data_display_info.current_group;
569 group = reggroup_next (current_gdbarch, group);
571 group = reggroup_next (current_gdbarch, 0);
574 tui_show_registers (group);
579 tui_reg_float_command (char *arg, int from_tty)
581 tui_show_registers (float_reggroup);
585 tui_reg_general_command (char *arg, int from_tty)
587 tui_show_registers (general_reggroup);
591 tui_reg_system_command (char *arg, int from_tty)
593 tui_show_registers (system_reggroup);
596 static struct cmd_list_element *tuireglist;
599 tui_reg_command (char *args, int from_tty)
601 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
602 "tui reg command.\n"));
603 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
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 gdbarch *gdbarch,
665 struct frame_info *frame,
666 struct tui_data_element *data_element,
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];
693 len = register_size (current_gdbarch, regnum);
694 fprintf_filtered (stream, "%-14s ", name);
695 get_frame_register (frame, regnum, buf);
696 print_scalar_formatted (buf, type, 'f', len, stream);
700 gdbarch_print_registers_info (current_gdbarch, stream,
704 /* Save formatted output in the buffer. */
705 p = tui_file_get_strbuf (stream);
707 /* Remove the possible \n. */
708 s = strrchr (p, '\n');
712 xfree (data_element->content);
713 data_element->content = xstrdup (p);
714 do_cleanups (cleanups);
717 /* Get the register value from the given frame and format it for the
718 display. When changep is set, check if the new register value has
719 changed with respect to the previous call. */
720 static enum tui_status
721 tui_get_register (struct gdbarch *gdbarch,
722 struct frame_info *frame,
723 struct tui_data_element *data,
724 int regnum, int *changedp)
726 enum tui_status ret = TUI_FAILURE;
730 if (target_has_registers)
732 gdb_byte buf[MAX_REGISTER_SIZE];
733 get_frame_register (frame, regnum, buf);
737 int size = register_size (gdbarch, regnum);
738 char *old = (char*) data->value;
741 for (i = 0; i < size; i++)
742 if (buf[i] != old[i])
749 /* Reformat the data content if the value changed. */
750 if (changedp == 0 || *changedp == TRUE)
751 tui_register_format (gdbarch, frame, data, regnum);
759 tui_scroll_regs_forward_command (char *arg, int from_tty)
761 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
766 tui_scroll_regs_backward_command (char *arg, int from_tty)
768 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);