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"
42 #include "gdb_curses.h"
45 /*****************************************
46 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
47 ******************************************/
49 tui_display_register (struct tui_data_element *data,
50 struct tui_gen_win_info *win_info);
52 static enum tui_status
53 tui_show_register_group (struct gdbarch *gdbarch,
54 struct reggroup *group,
55 struct frame_info *frame,
56 int refresh_values_only);
58 static enum tui_status
59 tui_get_register (struct gdbarch *gdbarch,
60 struct frame_info *frame,
61 struct tui_data_element *data,
62 int regnum, int *changedp);
63 static void tui_register_format (struct gdbarch *,
65 struct tui_data_element*,
67 static void tui_scroll_regs_forward_command (char *, int);
68 static void tui_scroll_regs_backward_command (char *, int);
72 /*****************************************
73 ** PUBLIC FUNCTIONS **
74 ******************************************/
76 /* Answer the number of the last line in the regs display. If there
77 are no registers (-1) is returned. */
79 tui_last_regs_line_no (void)
83 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
85 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
86 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
87 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
88 TUI_DATA_WIN->detail.data_display_info.regs_column_count)
95 /* Answer the line number that the register element at element_no is
96 on. If element_no is greater than the number of register elements
97 there are, -1 is returned. */
99 tui_line_from_reg_element_no (int element_no)
101 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
109 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
122 /* Answer the index of the first element in line_no. If line_no is
123 past the register area (-1) is returned. */
125 tui_first_reg_element_no_inline (int line_no)
127 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
128 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
129 return ((line_no + 1) *
130 TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
131 TUI_DATA_WIN->detail.data_display_info.regs_column_count;
137 /* Answer the index of the last element in line_no. If line_no is
138 past the register area (-1) is returned. */
140 tui_last_reg_element_no_in_line (int line_no)
142 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
143 TUI_DATA_WIN->detail.data_display_info.regs_content_count)
144 return ((line_no + 1) *
145 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
150 /* Show the registers of the given group in the data window
151 and refresh the window. */
153 tui_show_registers (struct reggroup *group)
155 enum tui_status ret = TUI_FAILURE;
156 struct tui_data_info *display_info;
158 /* Make sure the curses mode is enabled. */
161 /* Make sure the register window is visible. If not, select an
162 appropriate layout. */
163 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
164 tui_set_layout_for_display_command (DATA_NAME);
166 display_info = &TUI_DATA_WIN->detail.data_display_info;
168 group = general_reggroup;
170 /* Say that registers should be displayed, even if there is a
172 display_info->display_regs = TRUE;
174 if (target_has_registers && target_has_stack && target_has_memory)
176 ret = tui_show_register_group (current_gdbarch, group,
177 get_current_frame (),
178 group == display_info->current_group);
180 if (ret == TUI_FAILURE)
182 display_info->current_group = 0;
183 tui_erase_data_content (NO_REGS_STRING);
189 /* Clear all notation of changed values. */
190 for (i = 0; i < display_info->regs_content_count; i++)
192 struct tui_gen_win_info *data_item_win;
193 struct tui_win_element *win;
195 data_item_win = &display_info->regs_content[i]
196 ->which_element.data_window;
197 win = (struct tui_win_element *) data_item_win->content[0];
198 win->which_element.data.highlight = FALSE;
200 display_info->current_group = group;
201 tui_display_all_data ();
206 /* Set the data window to display the registers of the register group
207 using the given frame. Values are refreshed only when
208 refresh_values_only is TRUE. */
210 static enum tui_status
211 tui_show_register_group (struct gdbarch *gdbarch,
212 struct reggroup *group,
213 struct frame_info *frame,
214 int refresh_values_only)
216 enum tui_status ret = TUI_FAILURE;
218 int allocated_here = FALSE;
221 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
223 /* Make a new title showing which group we display. */
224 snprintf (title, sizeof (title) - 1, "Register group: %s",
225 reggroup_name (group));
226 xfree (TUI_DATA_WIN->generic.title);
227 TUI_DATA_WIN->generic.title = xstrdup (title);
229 /* See how many registers must be displayed. */
232 regnum < gdbarch_num_regs (current_gdbarch)
233 + gdbarch_num_pseudo_regs (current_gdbarch);
236 /* Must be in the group and have a name. */
237 if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
238 && gdbarch_register_name (gdbarch, regnum) != 0)
242 if (display_info->regs_content_count > 0 && !refresh_values_only)
244 tui_free_data_content (display_info->regs_content,
245 display_info->regs_content_count);
246 display_info->regs_content_count = 0;
249 if (display_info->regs_content_count <= 0)
251 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
252 allocated_here = TRUE;
253 refresh_values_only = FALSE;
256 if (display_info->regs_content != (tui_win_content) NULL)
258 if (!refresh_values_only || allocated_here)
260 TUI_DATA_WIN->generic.content = (void*) NULL;
261 TUI_DATA_WIN->generic.content_size = 0;
262 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
263 display_info->regs_content
264 = (tui_win_content) TUI_DATA_WIN->generic.content;
265 display_info->regs_content_count = nr_regs;
268 /* Now set the register names and values. */
271 regnum < gdbarch_num_regs (current_gdbarch)
272 + gdbarch_num_pseudo_regs (current_gdbarch);
275 struct tui_gen_win_info *data_item_win;
276 struct tui_data_element *data;
279 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
282 name = gdbarch_register_name (gdbarch, regnum);
287 &display_info->regs_content[pos]->which_element.data_window;
289 &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
292 if (!refresh_values_only)
294 data->item_no = regnum;
296 data->highlight = FALSE;
298 if (data->value == (void*) NULL)
299 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
301 tui_get_register (gdbarch, frame, data, regnum, 0);
306 TUI_DATA_WIN->generic.content_size =
307 display_info->regs_content_count + display_info->data_content_count;
314 /* Function to display the registers in the content from
315 'start_element_no' until the end of the register content or the end
316 of the display height. No checking for displaying past the end of
317 the registers is done here. */
319 tui_display_registers_from (int start_element_no)
321 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
323 if (display_info->regs_content != (tui_win_content) NULL
324 && display_info->regs_content_count > 0)
326 int i = start_element_no;
327 int j, value_chars_wide, item_win_width, cur_y;
330 for (i = 0; i < display_info->regs_content_count; i++)
332 struct tui_data_element *data;
333 struct tui_gen_win_info *data_item_win;
337 data_item_win = &display_info->regs_content[i]->which_element.data_window;
338 data = &((struct tui_win_element *)
339 data_item_win->content[0])->which_element.data;
346 len = 8 * ((len / 8) + 1);
354 item_win_width = max_len + 1;
355 i = start_element_no;
357 display_info->regs_column_count =
358 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
359 if (display_info->regs_column_count == 0)
360 display_info->regs_column_count = 1;
362 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
364 /* Now create each data "sub" window, and write the display into
367 while (i < display_info->regs_content_count
368 && cur_y <= TUI_DATA_WIN->generic.viewport_height)
371 j < display_info->regs_column_count
372 && i < display_info->regs_content_count;
375 struct tui_gen_win_info *data_item_win;
376 struct tui_data_element *data_element_ptr;
378 /* Create the window if necessary. */
379 data_item_win = &display_info->regs_content[i]
380 ->which_element.data_window;
381 data_element_ptr = &((struct tui_win_element *)
382 data_item_win->content[0])->which_element.data;
383 if (data_item_win->handle != (WINDOW*) NULL
384 && (data_item_win->height != 1
385 || data_item_win->width != item_win_width
386 || data_item_win->origin.x != (item_win_width * j) + 1
387 || data_item_win->origin.y != cur_y))
389 tui_delete_win (data_item_win->handle);
390 data_item_win->handle = 0;
393 if (data_item_win->handle == (WINDOW *) NULL)
395 data_item_win->height = 1;
396 data_item_win->width = item_win_width;
397 data_item_win->origin.x = (item_win_width * j) + 1;
398 data_item_win->origin.y = cur_y;
399 tui_make_window (data_item_win, DONT_BOX_WINDOW);
400 scrollok (data_item_win->handle, FALSE);
402 touchwin (data_item_win->handle);
404 /* Get the printable representation of the register
406 tui_display_register (data_element_ptr, data_item_win);
407 i++; /* Next register. */
409 cur_y++; /* Next row. */
415 /* Function to display the registers in the content from
416 'start_element_no' on 'start_line_no' until the end of the register
417 content or the end of the display height. This function checks
418 that we won't display off the end of the register display. */
420 tui_display_reg_element_at_line (int start_element_no,
423 if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL
424 && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
426 int element_no = start_element_no;
428 if (start_element_no != 0 && start_line_no != 0)
430 int last_line_no, first_line_on_last_page;
432 last_line_no = tui_last_regs_line_no ();
433 first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
434 if (first_line_on_last_page < 0)
435 first_line_on_last_page = 0;
437 /* If there is no other data displayed except registers, and
438 the element_no causes us to scroll past the end of the
439 registers, adjust what element to really start the
441 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
442 && start_line_no > first_line_on_last_page)
443 element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
445 tui_display_registers_from (element_no);
451 /* Function to display the registers starting at line line_no in the
452 data window. Answers the line number that the display actually
453 started from. If nothing is displayed (-1) is returned. */
455 tui_display_registers_from_line (int line_no,
458 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
460 int line, element_no;
464 else if (force_display)
465 { /* If we must display regs (force_display is true), then
466 make sure that we don't display off the end of the
468 if (line_no >= tui_last_regs_line_no ())
470 if ((line = tui_line_from_reg_element_no (
471 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
480 element_no = tui_first_reg_element_no_inline (line);
481 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
482 tui_display_reg_element_at_line (element_no, line);
489 return (-1); /* Nothing was displayed. */
493 /* This function check all displayed registers for changes in values,
494 given a particular frame. If the values have changed, they are
495 updated with the new value and highlighted. */
497 tui_check_register_values (struct frame_info *frame)
499 if (TUI_DATA_WIN != NULL
500 && TUI_DATA_WIN->generic.is_visible)
502 struct tui_data_info *display_info
503 = &TUI_DATA_WIN->detail.data_display_info;
505 if (display_info->regs_content_count <= 0
506 && display_info->display_regs)
507 tui_show_registers (display_info->current_group);
512 for (i = 0; (i < display_info->regs_content_count); i++)
514 struct tui_data_element *data;
515 struct tui_gen_win_info *data_item_win_ptr;
518 data_item_win_ptr = &display_info->regs_content[i]->
519 which_element.data_window;
520 data = &((struct tui_win_element *)
521 data_item_win_ptr->content[0])->which_element.data;
522 was_hilighted = data->highlight;
524 tui_get_register (current_gdbarch, frame, data,
525 data->item_no, &data->highlight);
527 if (data->highlight || was_hilighted)
529 tui_display_register (data, data_item_win_ptr);
536 /* Display a register in a window. If hilite is TRUE, then the value
537 will be displayed in reverse video. */
539 tui_display_register (struct tui_data_element *data,
540 struct tui_gen_win_info *win_info)
542 if (win_info->handle != (WINDOW *) NULL)
547 wstandout (win_info->handle);
549 wmove (win_info->handle, 0, 0);
550 for (i = 1; i < win_info->width; i++)
551 waddch (win_info->handle, ' ');
552 wmove (win_info->handle, 0, 0);
554 waddstr (win_info->handle, data->content);
557 wstandend (win_info->handle);
558 tui_refresh_win (win_info);
563 tui_reg_next_command (char *arg, int from_tty)
565 if (TUI_DATA_WIN != 0)
567 struct reggroup *group
568 = TUI_DATA_WIN->detail.data_display_info.current_group;
570 group = reggroup_next (current_gdbarch, group);
572 group = reggroup_next (current_gdbarch, 0);
575 tui_show_registers (group);
580 tui_reg_float_command (char *arg, int from_tty)
582 tui_show_registers (float_reggroup);
586 tui_reg_general_command (char *arg, int from_tty)
588 tui_show_registers (general_reggroup);
592 tui_reg_system_command (char *arg, int from_tty)
594 tui_show_registers (system_reggroup);
597 static struct cmd_list_element *tuireglist;
600 tui_reg_command (char *args, int from_tty)
602 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
603 "tui reg command.\n"));
604 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
608 _initialize_tui_regs (void)
610 struct cmd_list_element **tuicmd;
612 tuicmd = tui_get_cmd_list ();
614 add_prefix_cmd ("reg", class_tui, tui_reg_command,
615 _("TUI commands to control the register window."),
616 &tuireglist, "tui reg ", 0,
619 add_cmd ("float", class_tui, tui_reg_float_command,
620 _("Display only floating point registers."),
622 add_cmd ("general", class_tui, tui_reg_general_command,
623 _("Display only general registers."),
625 add_cmd ("system", class_tui, tui_reg_system_command,
626 _("Display only system registers."),
628 add_cmd ("next", class_tui, tui_reg_next_command,
629 _("Display next register group."),
634 add_com ("fr", class_tui, tui_reg_float_command,
635 _("Display only floating point registers\n"));
636 add_com ("gr", class_tui, tui_reg_general_command,
637 _("Display only general registers\n"));
638 add_com ("sr", class_tui, tui_reg_system_command,
639 _("Display only special registers\n"));
640 add_com ("+r", class_tui, tui_scroll_regs_forward_command,
641 _("Scroll the registers window forward\n"));
642 add_com ("-r", class_tui, tui_scroll_regs_backward_command,
643 _("Scroll the register window backward\n"));
648 /*****************************************
649 ** STATIC LOCAL FUNCTIONS **
650 ******************************************/
652 extern int pagination_enabled;
655 tui_restore_gdbout (void *ui)
657 ui_file_delete (gdb_stdout);
658 gdb_stdout = (struct ui_file*) ui;
659 pagination_enabled = 1;
662 /* Get the register from the frame and make a printable representation
663 of it in the data element. */
665 tui_register_format (struct gdbarch *gdbarch,
666 struct frame_info *frame,
667 struct tui_data_element *data_element,
670 struct ui_file *stream;
671 struct ui_file *old_stdout;
673 struct cleanup *cleanups;
676 struct type *type = register_type (gdbarch, regnum);
678 name = gdbarch_register_name (gdbarch, regnum);
684 pagination_enabled = 0;
685 old_stdout = gdb_stdout;
686 stream = tui_sfileopen (256);
688 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
689 if (TYPE_VECTOR (type) != 0 && 0)
691 gdb_byte buf[MAX_REGISTER_SIZE];
693 struct value_print_options opts;
695 len = register_size (current_gdbarch, regnum);
696 fprintf_filtered (stream, "%-14s ", name);
697 get_frame_register (frame, regnum, buf);
698 get_formatted_print_options (&opts, 'f');
699 print_scalar_formatted (buf, type, &opts, len, stream);
703 gdbarch_print_registers_info (current_gdbarch, stream,
707 /* Save formatted output in the buffer. */
708 p = tui_file_get_strbuf (stream);
710 /* Remove the possible \n. */
711 s = strrchr (p, '\n');
715 xfree (data_element->content);
716 data_element->content = xstrdup (p);
717 do_cleanups (cleanups);
720 /* Get the register value from the given frame and format it for the
721 display. When changep is set, check if the new register value has
722 changed with respect to the previous call. */
723 static enum tui_status
724 tui_get_register (struct gdbarch *gdbarch,
725 struct frame_info *frame,
726 struct tui_data_element *data,
727 int regnum, int *changedp)
729 enum tui_status ret = TUI_FAILURE;
733 if (target_has_registers)
735 gdb_byte buf[MAX_REGISTER_SIZE];
736 get_frame_register (frame, regnum, buf);
740 int size = register_size (gdbarch, regnum);
741 char *old = (char*) data->value;
744 for (i = 0; i < size; i++)
745 if (buf[i] != old[i])
752 /* Reformat the data content if the value changed. */
753 if (changedp == 0 || *changedp == TRUE)
754 tui_register_format (gdbarch, frame, data, regnum);
762 tui_scroll_regs_forward_command (char *arg, int from_tty)
764 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
769 tui_scroll_regs_backward_command (char *arg, int from_tty)
771 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);