1 /* TUI display registers in window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007
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 2 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, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA. */
27 #include "tui/tui-data.h"
35 #include "gdb_string.h"
36 #include "tui/tui-layout.h"
37 #include "tui/tui-win.h"
38 #include "tui/tui-windata.h"
39 #include "tui/tui-wingeneral.h"
40 #include "tui/tui-file.h"
41 #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
54 tui_show_register_group (struct gdbarch *gdbarch,
55 struct reggroup *group,
56 struct frame_info *frame,
57 int refresh_values_only);
59 static enum tui_status
60 tui_get_register (struct gdbarch *gdbarch,
61 struct frame_info *frame,
62 struct tui_data_element *data,
63 int regnum, int *changedp);
64 static void tui_register_format (struct gdbarch *,
66 struct tui_data_element*,
68 static void tui_scroll_regs_forward_command (char *, int);
69 static void tui_scroll_regs_backward_command (char *, int);
73 /*****************************************
74 ** PUBLIC FUNCTIONS **
75 ******************************************/
77 /* Answer the number of the last line in the regs display. If there
78 are no registers (-1) is returned. */
80 tui_last_regs_line_no (void)
84 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
86 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
87 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
88 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
89 TUI_DATA_WIN->detail.data_display_info.regs_column_count)
96 /* Answer the line number that the register element at element_no is
97 on. If element_no is greater than the number of register elements
98 there are, -1 is returned. */
100 tui_line_from_reg_element_no (int element_no)
102 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
110 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
123 /* Answer the index of the first element in line_no. If line_no is
124 past the register area (-1) is returned. */
126 tui_first_reg_element_no_inline (int line_no)
128 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
129 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
130 return ((line_no + 1) *
131 TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
132 TUI_DATA_WIN->detail.data_display_info.regs_column_count;
138 /* Answer the index of the last element in line_no. If line_no is
139 past the register area (-1) is returned. */
141 tui_last_reg_element_no_in_line (int line_no)
143 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
144 TUI_DATA_WIN->detail.data_display_info.regs_content_count)
145 return ((line_no + 1) *
146 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
151 /* Show the registers of the given group in the data window
152 and refresh the window. */
154 tui_show_registers (struct reggroup *group)
156 enum tui_status ret = TUI_FAILURE;
157 struct tui_data_info *display_info;
159 /* Make sure the curses mode is enabled. */
162 /* Make sure the register window is visible. If not, select an
163 appropriate layout. */
164 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
165 tui_set_layout_for_display_command (DATA_NAME);
167 display_info = &TUI_DATA_WIN->detail.data_display_info;
169 group = general_reggroup;
171 /* Say that registers should be displayed, even if there is a
173 display_info->display_regs = TRUE;
175 if (target_has_registers && target_has_stack && target_has_memory)
177 ret = tui_show_register_group (current_gdbarch, group,
178 get_current_frame (),
179 group == display_info->current_group);
181 if (ret == TUI_FAILURE)
183 display_info->current_group = 0;
184 tui_erase_data_content (NO_REGS_STRING);
190 /* Clear all notation of changed values. */
191 for (i = 0; i < display_info->regs_content_count; i++)
193 struct tui_gen_win_info *data_item_win;
194 struct tui_win_element *win;
196 data_item_win = &display_info->regs_content[i]
197 ->which_element.data_window;
198 win = (struct tui_win_element *) data_item_win->content[0];
199 win->which_element.data.highlight = FALSE;
201 display_info->current_group = group;
202 tui_display_all_data ();
207 /* Set the data window to display the registers of the register group
208 using the given frame. Values are refreshed only when
209 refresh_values_only is TRUE. */
211 static enum tui_status
212 tui_show_register_group (struct gdbarch *gdbarch,
213 struct reggroup *group,
214 struct frame_info *frame,
215 int refresh_values_only)
217 enum tui_status ret = TUI_FAILURE;
219 int allocated_here = FALSE;
222 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
224 /* Make a new title showing which group we display. */
225 snprintf (title, sizeof (title) - 1, "Register group: %s",
226 reggroup_name (group));
227 xfree (TUI_DATA_WIN->generic.title);
228 TUI_DATA_WIN->generic.title = xstrdup (title);
230 /* See how many registers must be displayed. */
233 regnum < gdbarch_num_regs (current_gdbarch)
234 + gdbarch_num_pseudo_regs (current_gdbarch);
237 /* Must be in the group and have a name. */
238 if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
239 && gdbarch_register_name (gdbarch, regnum) != 0)
243 if (display_info->regs_content_count > 0 && !refresh_values_only)
245 tui_free_data_content (display_info->regs_content,
246 display_info->regs_content_count);
247 display_info->regs_content_count = 0;
250 if (display_info->regs_content_count <= 0)
252 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
253 allocated_here = TRUE;
254 refresh_values_only = FALSE;
257 if (display_info->regs_content != (tui_win_content) NULL)
259 if (!refresh_values_only || allocated_here)
261 TUI_DATA_WIN->generic.content = (void*) NULL;
262 TUI_DATA_WIN->generic.content_size = 0;
263 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
264 display_info->regs_content
265 = (tui_win_content) TUI_DATA_WIN->generic.content;
266 display_info->regs_content_count = nr_regs;
269 /* Now set the register names and values. */
272 regnum < gdbarch_num_regs (current_gdbarch)
273 + gdbarch_num_pseudo_regs (current_gdbarch);
276 struct tui_gen_win_info *data_item_win;
277 struct tui_data_element *data;
280 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
283 name = gdbarch_register_name (gdbarch, regnum);
288 &display_info->regs_content[pos]->which_element.data_window;
290 &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
293 if (!refresh_values_only)
295 data->item_no = regnum;
297 data->highlight = FALSE;
299 if (data->value == (void*) NULL)
300 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
302 tui_get_register (gdbarch, frame, data, regnum, 0);
307 TUI_DATA_WIN->generic.content_size =
308 display_info->regs_content_count + display_info->data_content_count;
315 /* Function to display the registers in the content from
316 'start_element_no' until the end of the register content or the end
317 of the display height. No checking for displaying past the end of
318 the registers is done here. */
320 tui_display_registers_from (int start_element_no)
322 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
324 if (display_info->regs_content != (tui_win_content) NULL &&
325 display_info->regs_content_count > 0)
327 int i = start_element_no;
328 int j, value_chars_wide, item_win_width, cur_y;
331 for (i = 0; i < display_info->regs_content_count; i++)
333 struct tui_data_element *data;
334 struct tui_gen_win_info *data_item_win;
338 data_item_win = &display_info->regs_content[i]->which_element.data_window;
339 data = &((struct tui_win_element *)
340 data_item_win->content[0])->which_element.data;
347 len = 8 * ((len / 8) + 1);
355 item_win_width = max_len + 1;
356 i = start_element_no;
358 display_info->regs_column_count =
359 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
360 if (display_info->regs_column_count == 0)
361 display_info->regs_column_count = 1;
363 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
365 /* Now create each data "sub" window, and write the display into
368 while (i < display_info->regs_content_count &&
369 cur_y <= TUI_DATA_WIN->generic.viewport_height)
372 (j < display_info->regs_column_count &&
373 i < display_info->regs_content_count); j++)
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 && 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 && display_info->display_regs)
505 tui_show_registers (display_info->current_group);
510 for (i = 0; (i < display_info->regs_content_count); i++)
512 struct tui_data_element *data;
513 struct tui_gen_win_info *data_item_win_ptr;
516 data_item_win_ptr = &display_info->regs_content[i]->
517 which_element.data_window;
518 data = &((struct tui_win_element *)
519 data_item_win_ptr->content[0])->which_element.data;
520 was_hilighted = data->highlight;
522 tui_get_register (current_gdbarch, frame, data,
523 data->item_no, &data->highlight);
525 if (data->highlight || was_hilighted)
527 tui_display_register (data, data_item_win_ptr);
534 /* Display a register in a window. If hilite is TRUE, then the value
535 will be displayed in reverse video. */
537 tui_display_register (struct tui_data_element *data,
538 struct tui_gen_win_info *win_info)
540 if (win_info->handle != (WINDOW *) NULL)
545 wstandout (win_info->handle);
547 wmove (win_info->handle, 0, 0);
548 for (i = 1; i < win_info->width; i++)
549 waddch (win_info->handle, ' ');
550 wmove (win_info->handle, 0, 0);
552 waddstr (win_info->handle, data->content);
555 wstandend (win_info->handle);
556 tui_refresh_win (win_info);
561 tui_reg_next_command (char *arg, int from_tty)
563 if (TUI_DATA_WIN != 0)
565 struct reggroup *group
566 = TUI_DATA_WIN->detail.data_display_info.current_group;
568 group = reggroup_next (current_gdbarch, group);
570 group = reggroup_next (current_gdbarch, 0);
573 tui_show_registers (group);
578 tui_reg_float_command (char *arg, int from_tty)
580 tui_show_registers (float_reggroup);
584 tui_reg_general_command (char *arg, int from_tty)
586 tui_show_registers (general_reggroup);
590 tui_reg_system_command (char *arg, int from_tty)
592 tui_show_registers (system_reggroup);
595 static struct cmd_list_element *tuireglist;
598 tui_reg_command (char *args, int from_tty)
600 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
601 "tui reg command.\n"));
602 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
606 _initialize_tui_regs (void)
608 struct cmd_list_element **tuicmd;
610 tuicmd = tui_get_cmd_list ();
612 add_prefix_cmd ("reg", class_tui, tui_reg_command,
613 _("TUI commands to control the register window."),
614 &tuireglist, "tui reg ", 0,
617 add_cmd ("float", class_tui, tui_reg_float_command,
618 _("Display only floating point registers."),
620 add_cmd ("general", class_tui, tui_reg_general_command,
621 _("Display only general registers."),
623 add_cmd ("system", class_tui, tui_reg_system_command,
624 _("Display only system registers."),
626 add_cmd ("next", class_tui, tui_reg_next_command,
627 _("Display next register group."),
632 add_com ("fr", class_tui, tui_reg_float_command,
633 _("Display only floating point registers\n"));
634 add_com ("gr", class_tui, tui_reg_general_command,
635 _("Display only general registers\n"));
636 add_com ("sr", class_tui, tui_reg_system_command,
637 _("Display only special registers\n"));
638 add_com ("+r", class_tui, tui_scroll_regs_forward_command,
639 _("Scroll the registers window forward\n"));
640 add_com ("-r", class_tui, tui_scroll_regs_backward_command,
641 _("Scroll the register window backward\n"));
646 /*****************************************
647 ** STATIC LOCAL FUNCTIONS **
648 ******************************************/
650 extern int pagination_enabled;
653 tui_restore_gdbout (void *ui)
655 ui_file_delete (gdb_stdout);
656 gdb_stdout = (struct ui_file*) ui;
657 pagination_enabled = 1;
660 /* Get the register from the frame and make a printable representation
661 of it in the data element. */
663 tui_register_format (struct gdbarch *gdbarch,
664 struct frame_info *frame,
665 struct tui_data_element *data_element,
668 struct ui_file *stream;
669 struct ui_file *old_stdout;
671 struct cleanup *cleanups;
674 struct type *type = register_type (gdbarch, regnum);
676 name = gdbarch_register_name (gdbarch, regnum);
682 pagination_enabled = 0;
683 old_stdout = gdb_stdout;
684 stream = tui_sfileopen (256);
686 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
687 if (TYPE_VECTOR (type) != 0 && 0)
689 gdb_byte buf[MAX_REGISTER_SIZE];
692 len = register_size (current_gdbarch, regnum);
693 fprintf_filtered (stream, "%-14s ", name);
694 get_frame_register (frame, regnum, buf);
695 print_scalar_formatted (buf, type, 'f', len, stream);
699 gdbarch_print_registers_info (current_gdbarch, stream,
703 /* Save formatted output in the buffer. */
704 p = tui_file_get_strbuf (stream);
706 /* Remove the possible \n. */
707 s = strrchr (p, '\n');
711 xfree (data_element->content);
712 data_element->content = xstrdup (p);
713 do_cleanups (cleanups);
716 /* Get the register value from the given frame and format it for the
717 display. When changep is set, check if the new register value has
718 changed with respect to the previous call. */
719 static enum tui_status
720 tui_get_register (struct gdbarch *gdbarch,
721 struct frame_info *frame,
722 struct tui_data_element *data,
723 int regnum, int *changedp)
725 enum tui_status ret = TUI_FAILURE;
729 if (target_has_registers)
731 gdb_byte buf[MAX_REGISTER_SIZE];
732 get_frame_register (frame, regnum, buf);
736 int size = register_size (gdbarch, regnum);
737 char *old = (char*) data->value;
740 for (i = 0; i < size; i++)
741 if (buf[i] != old[i])
748 /* Reformat the data content if the value changed. */
749 if (changedp == 0 || *changedp == TRUE)
750 tui_register_format (gdbarch, frame, data, regnum);
758 tui_scroll_regs_forward_command (char *arg, int from_tty)
760 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
765 tui_scroll_regs_backward_command (char *arg, int from_tty)
767 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);