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, struct reggroup *group,
55 struct frame_info *frame, int refresh_values_only);
57 static enum tui_status
58 tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame,
59 struct tui_data_element *data, int regnum, int *changedp);
60 static void tui_register_format
61 (struct gdbarch *, struct frame_info *, struct tui_data_element*, int);
62 static void tui_scroll_regs_forward_command (char *, int);
63 static void tui_scroll_regs_backward_command (char *, int);
67 /*****************************************
68 ** PUBLIC FUNCTIONS **
69 ******************************************/
71 /* Answer the number of the last line in the regs display. If there
72 are no registers (-1) is returned. */
74 tui_last_regs_line_no (void)
78 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
80 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
81 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
82 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
83 TUI_DATA_WIN->detail.data_display_info.regs_column_count)
90 /* Answer the line number that the register element at element_no is
91 on. If element_no is greater than the number of register elements
92 there are, -1 is returned. */
94 tui_line_from_reg_element_no (int element_no)
96 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
104 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
117 /* Answer the index of the first element in line_no. If line_no is
118 past the register area (-1) is returned. */
120 tui_first_reg_element_no_inline (int line_no)
122 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
123 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
124 return ((line_no + 1) *
125 TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
126 TUI_DATA_WIN->detail.data_display_info.regs_column_count;
132 /* Answer the index of the last element in line_no. If line_no is
133 past the register area (-1) is returned. */
135 tui_last_reg_element_no_in_line (int line_no)
137 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
138 TUI_DATA_WIN->detail.data_display_info.regs_content_count)
139 return ((line_no + 1) *
140 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
145 /* Show the registers of the given group in the data window
146 and refresh the window. */
148 tui_show_registers (struct reggroup *group)
150 enum tui_status ret = TUI_FAILURE;
151 struct tui_data_info *display_info;
153 /* Make sure the curses mode is enabled. */
156 /* Make sure the register window is visible. If not, select an
157 appropriate layout. */
158 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
159 tui_set_layout_for_display_command (DATA_NAME);
161 display_info = &TUI_DATA_WIN->detail.data_display_info;
163 group = general_reggroup;
165 /* Say that registers should be displayed, even if there is a
167 display_info->display_regs = TRUE;
169 if (target_has_registers && target_has_stack && target_has_memory)
171 ret = tui_show_register_group (current_gdbarch, group,
172 get_current_frame (),
173 group == display_info->current_group);
175 if (ret == TUI_FAILURE)
177 display_info->current_group = 0;
178 tui_erase_data_content (NO_REGS_STRING);
184 /* Clear all notation of changed values. */
185 for (i = 0; i < display_info->regs_content_count; i++)
187 struct tui_gen_win_info *data_item_win;
188 struct tui_win_element *win;
190 data_item_win = &display_info->regs_content[i]
191 ->which_element.data_window;
192 win = (struct tui_win_element *) data_item_win->content[0];
193 win->which_element.data.highlight = FALSE;
195 display_info->current_group = group;
196 tui_display_all_data ();
201 /* Set the data window to display the registers of the register group
202 using the given frame. Values are refreshed only when
203 refresh_values_only is TRUE. */
205 static enum tui_status
206 tui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group,
207 struct frame_info *frame, int refresh_values_only)
209 enum tui_status ret = TUI_FAILURE;
211 int allocated_here = FALSE;
214 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
216 /* Make a new title showing which group we display. */
217 snprintf (title, sizeof (title) - 1, "Register group: %s",
218 reggroup_name (group));
219 xfree (TUI_DATA_WIN->generic.title);
220 TUI_DATA_WIN->generic.title = xstrdup (title);
222 /* See how many registers must be displayed. */
225 regnum < gdbarch_num_regs (current_gdbarch)
226 + gdbarch_num_pseudo_regs (current_gdbarch);
229 /* Must be in the group and have a name. */
230 if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
231 && gdbarch_register_name (gdbarch, regnum) != 0)
235 if (display_info->regs_content_count > 0 && !refresh_values_only)
237 tui_free_data_content (display_info->regs_content,
238 display_info->regs_content_count);
239 display_info->regs_content_count = 0;
242 if (display_info->regs_content_count <= 0)
244 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
245 allocated_here = TRUE;
246 refresh_values_only = FALSE;
249 if (display_info->regs_content != (tui_win_content) NULL)
251 if (!refresh_values_only || allocated_here)
253 TUI_DATA_WIN->generic.content = (void*) NULL;
254 TUI_DATA_WIN->generic.content_size = 0;
255 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
256 display_info->regs_content
257 = (tui_win_content) TUI_DATA_WIN->generic.content;
258 display_info->regs_content_count = nr_regs;
261 /* Now set the register names and values. */
264 regnum < gdbarch_num_regs (current_gdbarch)
265 + gdbarch_num_pseudo_regs (current_gdbarch);
268 struct tui_gen_win_info *data_item_win;
269 struct tui_data_element *data;
272 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
275 name = gdbarch_register_name (gdbarch, regnum);
280 &display_info->regs_content[pos]->which_element.data_window;
282 &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
285 if (!refresh_values_only)
287 data->item_no = regnum;
289 data->highlight = FALSE;
291 if (data->value == (void*) NULL)
292 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
294 tui_get_register (gdbarch, frame, data, regnum, 0);
299 TUI_DATA_WIN->generic.content_size =
300 display_info->regs_content_count + display_info->data_content_count;
307 /* Function to display the registers in the content from
308 'start_element_no' until the end of the register content or the end
309 of the display height. No checking for displaying past the end of
310 the registers is done here. */
312 tui_display_registers_from (int start_element_no)
314 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
316 if (display_info->regs_content != (tui_win_content) NULL &&
317 display_info->regs_content_count > 0)
319 int i = start_element_no;
320 int j, value_chars_wide, item_win_width, cur_y;
323 for (i = 0; i < display_info->regs_content_count; i++)
325 struct tui_data_element *data;
326 struct tui_gen_win_info *data_item_win;
330 data_item_win = &display_info->regs_content[i]->which_element.data_window;
331 data = &((struct tui_win_element *)
332 data_item_win->content[0])->which_element.data;
339 len = 8 * ((len / 8) + 1);
347 item_win_width = max_len + 1;
348 i = start_element_no;
350 display_info->regs_column_count =
351 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
352 if (display_info->regs_column_count == 0)
353 display_info->regs_column_count = 1;
355 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
358 ** Now create each data "sub" window, and write the display
362 while (i < display_info->regs_content_count &&
363 cur_y <= TUI_DATA_WIN->generic.viewport_height)
366 (j < display_info->regs_column_count &&
367 i < display_info->regs_content_count); j++)
369 struct tui_gen_win_info *data_item_win;
370 struct tui_data_element *data_element_ptr;
372 /* Create the window if necessary. */
373 data_item_win = &display_info->regs_content[i]
374 ->which_element.data_window;
375 data_element_ptr = &((struct tui_win_element *)
376 data_item_win->content[0])->which_element.data;
377 if (data_item_win->handle != (WINDOW*) NULL
378 && (data_item_win->height != 1
379 || data_item_win->width != item_win_width
380 || data_item_win->origin.x != (item_win_width * j) + 1
381 || data_item_win->origin.y != cur_y))
383 tui_delete_win (data_item_win->handle);
384 data_item_win->handle = 0;
387 if (data_item_win->handle == (WINDOW *) NULL)
389 data_item_win->height = 1;
390 data_item_win->width = item_win_width;
391 data_item_win->origin.x = (item_win_width * j) + 1;
392 data_item_win->origin.y = cur_y;
393 tui_make_window (data_item_win, DONT_BOX_WINDOW);
394 scrollok (data_item_win->handle, FALSE);
396 touchwin (data_item_win->handle);
398 /* Get the printable representation of the register
400 tui_display_register (data_element_ptr, data_item_win);
401 i++; /* Next register. */
403 cur_y++; /* Next row. */
409 /* Function to display the registers in the content from
410 'start_element_no' on 'start_line_no' until the end of the register
411 content or the end of the display height. This function checks
412 that we won't display off the end of the register display. */
414 tui_display_reg_element_at_line (int start_element_no, int start_line_no)
416 if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
417 TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
419 int element_no = start_element_no;
421 if (start_element_no != 0 && start_line_no != 0)
423 int last_line_no, first_line_on_last_page;
425 last_line_no = tui_last_regs_line_no ();
426 first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
427 if (first_line_on_last_page < 0)
428 first_line_on_last_page = 0;
430 ** If there is no other data displayed except registers,
431 ** and the element_no causes us to scroll past the end of
432 ** the registers, adjust what element to really start the
435 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 &&
436 start_line_no > first_line_on_last_page)
437 element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
439 tui_display_registers_from (element_no);
445 /* Function to display the registers starting at line line_no in the
446 data window. Answers the line number that the display actually
447 started from. If nothing is displayed (-1) is returned. */
449 tui_display_registers_from_line (int line_no, int force_display)
451 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
453 int line, element_no;
457 else if (force_display)
459 ** If we must display regs (force_display is true), then make
460 ** sure that we don't display off the end of the registers.
462 if (line_no >= tui_last_regs_line_no ())
464 if ((line = tui_line_from_reg_element_no (
465 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
474 element_no = tui_first_reg_element_no_inline (line);
475 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
476 tui_display_reg_element_at_line (element_no, line);
483 return (-1); /* Nothing was displayed. */
487 /* This function check all displayed registers for changes in values,
488 given a particular frame. If the values have changed, they are
489 updated with the new value and highlighted. */
491 tui_check_register_values (struct frame_info *frame)
493 if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
495 struct tui_data_info *display_info
496 = &TUI_DATA_WIN->detail.data_display_info;
498 if (display_info->regs_content_count <= 0 && display_info->display_regs)
499 tui_show_registers (display_info->current_group);
504 for (i = 0; (i < display_info->regs_content_count); i++)
506 struct tui_data_element *data;
507 struct tui_gen_win_info *data_item_win_ptr;
510 data_item_win_ptr = &display_info->regs_content[i]->
511 which_element.data_window;
512 data = &((struct tui_win_element *)
513 data_item_win_ptr->content[0])->which_element.data;
514 was_hilighted = data->highlight;
516 tui_get_register (current_gdbarch, frame, data,
517 data->item_no, &data->highlight);
519 if (data->highlight || was_hilighted)
521 tui_display_register (data, data_item_win_ptr);
528 /* Display a register in a window. If hilite is TRUE, then the value
529 will be displayed in reverse video. */
531 tui_display_register (struct tui_data_element *data,
532 struct tui_gen_win_info *win_info)
534 if (win_info->handle != (WINDOW *) NULL)
539 wstandout (win_info->handle);
541 wmove (win_info->handle, 0, 0);
542 for (i = 1; i < win_info->width; i++)
543 waddch (win_info->handle, ' ');
544 wmove (win_info->handle, 0, 0);
546 waddstr (win_info->handle, data->content);
549 wstandend (win_info->handle);
550 tui_refresh_win (win_info);
555 tui_reg_next_command (char *arg, int from_tty)
557 if (TUI_DATA_WIN != 0)
559 struct reggroup *group
560 = TUI_DATA_WIN->detail.data_display_info.current_group;
562 group = reggroup_next (current_gdbarch, group);
564 group = reggroup_next (current_gdbarch, 0);
567 tui_show_registers (group);
572 tui_reg_float_command (char *arg, int from_tty)
574 tui_show_registers (float_reggroup);
578 tui_reg_general_command (char *arg, int from_tty)
580 tui_show_registers (general_reggroup);
584 tui_reg_system_command (char *arg, int from_tty)
586 tui_show_registers (system_reggroup);
589 static struct cmd_list_element *tuireglist;
592 tui_reg_command (char *args, int from_tty)
594 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
595 "tui reg command.\n"));
596 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
600 _initialize_tui_regs (void)
602 struct cmd_list_element **tuicmd;
604 tuicmd = tui_get_cmd_list ();
606 add_prefix_cmd ("reg", class_tui, tui_reg_command,
607 _("TUI commands to control the register window."),
608 &tuireglist, "tui reg ", 0,
611 add_cmd ("float", class_tui, tui_reg_float_command,
612 _("Display only floating point registers."),
614 add_cmd ("general", class_tui, tui_reg_general_command,
615 _("Display only general registers."),
617 add_cmd ("system", class_tui, tui_reg_system_command,
618 _("Display only system registers."),
620 add_cmd ("next", class_tui, tui_reg_next_command,
621 _("Display next register group."),
626 add_com ("fr", class_tui, tui_reg_float_command,
627 _("Display only floating point registers\n"));
628 add_com ("gr", class_tui, tui_reg_general_command,
629 _("Display only general registers\n"));
630 add_com ("sr", class_tui, tui_reg_system_command,
631 _("Display only special registers\n"));
632 add_com ("+r", class_tui, tui_scroll_regs_forward_command,
633 _("Scroll the registers window forward\n"));
634 add_com ("-r", class_tui, tui_scroll_regs_backward_command,
635 _("Scroll the register window backward\n"));
640 /*****************************************
641 ** STATIC LOCAL FUNCTIONS **
642 ******************************************/
644 extern int pagination_enabled;
647 tui_restore_gdbout (void *ui)
649 ui_file_delete (gdb_stdout);
650 gdb_stdout = (struct ui_file*) ui;
651 pagination_enabled = 1;
654 /* Get the register from the frame and make a printable representation
655 of it in the data element. */
657 tui_register_format (struct gdbarch *gdbarch, struct frame_info *frame,
658 struct tui_data_element *data_element, int regnum)
660 struct ui_file *stream;
661 struct ui_file *old_stdout;
663 struct cleanup *cleanups;
666 struct type *type = register_type (gdbarch, regnum);
668 name = gdbarch_register_name (gdbarch, regnum);
674 pagination_enabled = 0;
675 old_stdout = gdb_stdout;
676 stream = tui_sfileopen (256);
678 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
679 if (TYPE_VECTOR (type) != 0 && 0)
681 gdb_byte buf[MAX_REGISTER_SIZE];
684 len = register_size (current_gdbarch, regnum);
685 fprintf_filtered (stream, "%-14s ", name);
686 get_frame_register (frame, regnum, buf);
687 print_scalar_formatted (buf, type, 'f', len, stream);
691 gdbarch_print_registers_info (current_gdbarch, stream,
695 /* Save formatted output in the buffer. */
696 p = tui_file_get_strbuf (stream);
698 /* Remove the possible \n. */
699 s = strrchr (p, '\n');
703 xfree (data_element->content);
704 data_element->content = xstrdup (p);
705 do_cleanups (cleanups);
708 /* Get the register value from the given frame and format it for the
709 display. When changep is set, check if the new register value has
710 changed with respect to the previous call. */
711 static enum tui_status
712 tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame,
713 struct tui_data_element *data, int regnum, int *changedp)
715 enum tui_status ret = TUI_FAILURE;
719 if (target_has_registers)
721 gdb_byte buf[MAX_REGISTER_SIZE];
722 get_frame_register (frame, regnum, buf);
726 int size = register_size (gdbarch, regnum);
727 char *old = (char*) data->value;
730 for (i = 0; i < size; i++)
731 if (buf[i] != old[i])
738 /* Reformat the data content if the value changed. */
739 if (changedp == 0 || *changedp == TRUE)
740 tui_register_format (gdbarch, frame, data, regnum);
748 tui_scroll_regs_forward_command (char *arg, int from_tty)
750 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
755 tui_scroll_regs_backward_command (char *arg, int from_tty)
757 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);