1 /* TUI display registers in window.
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
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., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, 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 past
118 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
= &TUI_DATA_WIN
->detail
.data_display_info
;
154 group
= general_reggroup
;
156 /* Say that registers should be displayed, even if there is a problem. */
157 display_info
->display_regs
= TRUE
;
159 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
161 ret
= tui_show_register_group (current_gdbarch
, group
,
162 get_current_frame (),
163 group
== display_info
->current_group
);
165 if (ret
== TUI_FAILURE
)
167 display_info
->current_group
= 0;
168 tui_erase_data_content (NO_REGS_STRING
);
174 /* Clear all notation of changed values */
175 for (i
= 0; i
< display_info
->regs_content_count
; i
++)
177 struct tui_gen_win_info
*data_item_win
;
178 struct tui_win_element
*win
;
180 data_item_win
= &display_info
->regs_content
[i
]
181 ->which_element
.data_window
;
182 win
= (struct tui_win_element
*) data_item_win
->content
[0];
183 win
->which_element
.data
.highlight
= FALSE
;
185 display_info
->current_group
= group
;
186 tui_display_all_data ();
191 /* Set the data window to display the registers of the register group
192 using the given frame. Values are refreshed only when refresh_values_only
195 static enum tui_status
196 tui_show_register_group (struct gdbarch
*gdbarch
, struct reggroup
*group
,
197 struct frame_info
*frame
, int refresh_values_only
)
199 enum tui_status ret
= TUI_FAILURE
;
201 int allocated_here
= FALSE
;
204 struct tui_data_info
*display_info
= &TUI_DATA_WIN
->detail
.data_display_info
;
206 /* Make a new title showing which group we display. */
207 snprintf (title
, sizeof (title
) - 1, "Register group: %s",
208 reggroup_name (group
));
209 xfree (TUI_DATA_WIN
->generic
.title
);
210 TUI_DATA_WIN
->generic
.title
= xstrdup (title
);
212 /* See how many registers must be displayed. */
214 for (regnum
= 0; regnum
< NUM_REGS
+ NUM_PSEUDO_REGS
; regnum
++)
216 /* Must be in the group and have a name. */
217 if (gdbarch_register_reggroup_p (gdbarch
, regnum
, group
)
218 && gdbarch_register_name (gdbarch
, regnum
) != 0)
222 if (display_info
->regs_content_count
> 0 && !refresh_values_only
)
224 tui_free_data_content (display_info
->regs_content
,
225 display_info
->regs_content_count
);
226 display_info
->regs_content_count
= 0;
229 if (display_info
->regs_content_count
<= 0)
231 display_info
->regs_content
= tui_alloc_content (nr_regs
, DATA_WIN
);
232 allocated_here
= TRUE
;
233 refresh_values_only
= FALSE
;
236 if (display_info
->regs_content
!= (tui_win_content
) NULL
)
238 if (!refresh_values_only
|| allocated_here
)
240 TUI_DATA_WIN
->generic
.content
= (void*) NULL
;
241 TUI_DATA_WIN
->generic
.content_size
= 0;
242 tui_add_content_elements (&TUI_DATA_WIN
->generic
, nr_regs
);
243 display_info
->regs_content
244 = (tui_win_content
) TUI_DATA_WIN
->generic
.content
;
245 display_info
->regs_content_count
= nr_regs
;
248 /* Now set the register names and values */
250 for (regnum
= 0; regnum
< NUM_REGS
+ NUM_PSEUDO_REGS
; regnum
++)
252 struct tui_gen_win_info
*data_item_win
;
253 struct tui_data_element
*data
;
256 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
259 name
= gdbarch_register_name (gdbarch
, regnum
);
264 &display_info
->regs_content
[pos
]->which_element
.data_window
;
266 &((struct tui_win_element
*) data_item_win
->content
[0])->which_element
.data
;
269 if (!refresh_values_only
)
271 data
->item_no
= regnum
;
273 data
->highlight
= FALSE
;
275 if (data
->value
== (void*) NULL
)
276 data
->value
= (void*) xmalloc (MAX_REGISTER_SIZE
);
278 tui_get_register (gdbarch
, frame
, data
, regnum
, 0);
283 TUI_DATA_WIN
->generic
.content_size
=
284 display_info
->regs_content_count
+ display_info
->data_content_count
;
291 /* Function to display the registers in the content from
292 'start_element_no' until the end of the register content or the end
293 of the display height. No checking for displaying past the end of
294 the registers is done here. */
296 tui_display_registers_from (int start_element_no
)
298 struct tui_data_info
*display_info
= &TUI_DATA_WIN
->detail
.data_display_info
;
300 if (display_info
->regs_content
!= (tui_win_content
) NULL
&&
301 display_info
->regs_content_count
> 0)
303 int i
= start_element_no
;
304 int j
, value_chars_wide
, item_win_width
, cur_y
;
307 for (i
= 0; i
< display_info
->regs_content_count
; i
++)
309 struct tui_data_element
*data
;
310 struct tui_gen_win_info
*data_item_win
;
314 data_item_win
= &display_info
->regs_content
[i
]->which_element
.data_window
;
315 data
= &((struct tui_win_element
*)
316 data_item_win
->content
[0])->which_element
.data
;
323 len
= 8 * ((len
/ 8) + 1);
331 item_win_width
= max_len
+ 1;
332 i
= start_element_no
;
334 display_info
->regs_column_count
=
335 (TUI_DATA_WIN
->generic
.width
- 2) / item_win_width
;
336 if (display_info
->regs_column_count
== 0)
337 display_info
->regs_column_count
= 1;
339 (TUI_DATA_WIN
->generic
.width
- 2) / display_info
->regs_column_count
;
342 ** Now create each data "sub" window, and write the display into it.
345 while (i
< display_info
->regs_content_count
&&
346 cur_y
<= TUI_DATA_WIN
->generic
.viewport_height
)
349 (j
< display_info
->regs_column_count
&&
350 i
< display_info
->regs_content_count
); j
++)
352 struct tui_gen_win_info
* data_item_win
;
353 struct tui_data_element
* data_element_ptr
;
355 /* create the window if necessary */
356 data_item_win
= &display_info
->regs_content
[i
]
357 ->which_element
.data_window
;
358 data_element_ptr
= &((struct tui_win_element
*)
359 data_item_win
->content
[0])->which_element
.data
;
360 if (data_item_win
->handle
!= (WINDOW
*) NULL
361 && (data_item_win
->height
!= 1
362 || data_item_win
->width
!= item_win_width
363 || data_item_win
->origin
.x
!= (item_win_width
* j
) + 1
364 || data_item_win
->origin
.y
!= cur_y
))
366 tui_delete_win (data_item_win
->handle
);
367 data_item_win
->handle
= 0;
370 if (data_item_win
->handle
== (WINDOW
*) NULL
)
372 data_item_win
->height
= 1;
373 data_item_win
->width
= item_win_width
;
374 data_item_win
->origin
.x
= (item_win_width
* j
) + 1;
375 data_item_win
->origin
.y
= cur_y
;
376 tui_make_window (data_item_win
, DONT_BOX_WINDOW
);
377 scrollok (data_item_win
->handle
, FALSE
);
379 touchwin (data_item_win
->handle
);
381 /* Get the printable representation of the register
383 tui_display_register (data_element_ptr
, data_item_win
);
384 i
++; /* next register */
386 cur_y
++; /* next row; */
392 /* Function to display the registers in the content from
393 'start_element_no' on 'start_line_no' until the end of the register
394 content or the end of the display height. This function checks
395 that we won't display off the end of the register display. */
397 tui_display_reg_element_at_line (int start_element_no
, int start_line_no
)
399 if (TUI_DATA_WIN
->detail
.data_display_info
.regs_content
!= (tui_win_content
) NULL
&&
400 TUI_DATA_WIN
->detail
.data_display_info
.regs_content_count
> 0)
402 int element_no
= start_element_no
;
404 if (start_element_no
!= 0 && start_line_no
!= 0)
406 int last_line_no
, first_line_on_last_page
;
408 last_line_no
= tui_last_regs_line_no ();
409 first_line_on_last_page
= last_line_no
- (TUI_DATA_WIN
->generic
.height
- 2);
410 if (first_line_on_last_page
< 0)
411 first_line_on_last_page
= 0;
413 ** If there is no other data displayed except registers,
414 ** and the element_no causes us to scroll past the end of the
415 ** registers, adjust what element to really start the display at.
417 if (TUI_DATA_WIN
->detail
.data_display_info
.data_content_count
<= 0 &&
418 start_line_no
> first_line_on_last_page
)
419 element_no
= tui_first_reg_element_no_inline (first_line_on_last_page
);
421 tui_display_registers_from (element_no
);
427 /* Function to display the registers starting at line line_no in the
428 data window. Answers the line number that the display actually
429 started from. If nothing is displayed (-1) is returned. */
431 tui_display_registers_from_line (int line_no
, int force_display
)
433 if (TUI_DATA_WIN
->detail
.data_display_info
.regs_content_count
> 0)
435 int line
, element_no
;
439 else if (force_display
)
441 ** If we must display regs (force_display is true), then make
442 ** sure that we don't display off the end of the registers.
444 if (line_no
>= tui_last_regs_line_no ())
446 if ((line
= tui_line_from_reg_element_no (
447 TUI_DATA_WIN
->detail
.data_display_info
.regs_content_count
- 1)) < 0)
456 element_no
= tui_first_reg_element_no_inline (line
);
457 if (element_no
< TUI_DATA_WIN
->detail
.data_display_info
.regs_content_count
)
458 tui_display_reg_element_at_line (element_no
, line
);
465 return (-1); /* nothing was displayed */
469 /* This function check all displayed registers for changes in values,
470 given a particular frame. If the values have changed, they are
471 updated with the new value and highlighted. */
473 tui_check_register_values (struct frame_info
*frame
)
475 if (TUI_DATA_WIN
!= NULL
&& TUI_DATA_WIN
->generic
.is_visible
)
477 struct tui_data_info
*display_info
478 = &TUI_DATA_WIN
->detail
.data_display_info
;
480 if (display_info
->regs_content_count
<= 0 && display_info
->display_regs
)
481 tui_show_registers (display_info
->current_group
);
486 for (i
= 0; (i
< display_info
->regs_content_count
); i
++)
488 struct tui_data_element
*data
;
489 struct tui_gen_win_info
*data_item_win_ptr
;
492 data_item_win_ptr
= &display_info
->regs_content
[i
]->
493 which_element
.data_window
;
494 data
= &((struct tui_win_element
*)
495 data_item_win_ptr
->content
[0])->which_element
.data
;
496 was_hilighted
= data
->highlight
;
498 tui_get_register (current_gdbarch
, frame
, data
,
499 data
->item_no
, &data
->highlight
);
501 if (data
->highlight
|| was_hilighted
)
503 tui_display_register (data
, data_item_win_ptr
);
510 /* Display a register in a window. If hilite is TRUE,
511 then the value will be displayed in reverse video */
513 tui_display_register (struct tui_data_element
*data
,
514 struct tui_gen_win_info
*win_info
)
516 if (win_info
->handle
!= (WINDOW
*) NULL
)
521 wstandout (win_info
->handle
);
523 wmove (win_info
->handle
, 0, 0);
524 for (i
= 1; i
< win_info
->width
; i
++)
525 waddch (win_info
->handle
, ' ');
526 wmove (win_info
->handle
, 0, 0);
528 waddstr (win_info
->handle
, data
->content
);
531 wstandend (win_info
->handle
);
532 tui_refresh_win (win_info
);
537 tui_reg_next_command (char *arg
, int from_tty
)
539 if (TUI_DATA_WIN
!= 0)
541 struct reggroup
*group
542 = TUI_DATA_WIN
->detail
.data_display_info
.current_group
;
544 group
= reggroup_next (current_gdbarch
, group
);
546 group
= reggroup_next (current_gdbarch
, 0);
549 tui_show_registers (group
);
554 tui_reg_float_command (char *arg
, int from_tty
)
556 tui_show_registers (float_reggroup
);
560 tui_reg_general_command (char *arg
, int from_tty
)
562 tui_show_registers (general_reggroup
);
566 tui_reg_system_command (char *arg
, int from_tty
)
568 tui_show_registers (system_reggroup
);
571 static struct cmd_list_element
*tuireglist
;
574 tui_reg_command (char *args
, int from_tty
)
576 printf_unfiltered ("\"tui reg\" must be followed by the name of a "
577 "tui reg command.\n");
578 help_list (tuireglist
, "tui reg ", -1, gdb_stdout
);
582 _initialize_tui_regs (void)
584 struct cmd_list_element
**tuicmd
;
586 tuicmd
= tui_get_cmd_list ();
588 add_prefix_cmd ("reg", class_tui
, tui_reg_command
,
589 "TUI commands to control the register window.",
590 &tuireglist
, "tui reg ", 0,
593 add_cmd ("float", class_tui
, tui_reg_float_command
,
594 "Display only floating point registers\n",
596 add_cmd ("general", class_tui
, tui_reg_general_command
,
597 "Display only general registers\n",
599 add_cmd ("system", class_tui
, tui_reg_system_command
,
600 "Display only system registers\n",
602 add_cmd ("next", class_tui
, tui_reg_next_command
,
603 "Display next register group\n",
608 add_com ("fr", class_tui
, tui_reg_float_command
,
609 "Display only floating point registers\n");
610 add_com ("gr", class_tui
, tui_reg_general_command
,
611 "Display only general registers\n");
612 add_com ("sr", class_tui
, tui_reg_system_command
,
613 "Display only special registers\n");
614 add_com ("+r", class_tui
, tui_scroll_regs_forward_command
,
615 "Scroll the registers window forward\n");
616 add_com ("-r", class_tui
, tui_scroll_regs_backward_command
,
617 "Scroll the register window backward\n");
622 /*****************************************
623 ** STATIC LOCAL FUNCTIONS **
624 ******************************************/
626 extern int pagination_enabled
;
629 tui_restore_gdbout (void *ui
)
631 ui_file_delete (gdb_stdout
);
632 gdb_stdout
= (struct ui_file
*) ui
;
633 pagination_enabled
= 1;
636 /* Get the register from the frame and make a printable representation
637 of it in the data element. */
639 tui_register_format (struct gdbarch
*gdbarch
, struct frame_info
*frame
,
640 struct tui_data_element
*data_element
, int regnum
)
642 struct ui_file
*stream
;
643 struct ui_file
*old_stdout
;
645 struct cleanup
*cleanups
;
648 struct type
*type
= gdbarch_register_type (gdbarch
, regnum
);
650 name
= gdbarch_register_name (gdbarch
, regnum
);
656 pagination_enabled
= 0;
657 old_stdout
= gdb_stdout
;
658 stream
= tui_sfileopen (256);
660 cleanups
= make_cleanup (tui_restore_gdbout
, (void*) old_stdout
);
661 if (TYPE_VECTOR (type
) != 0 && 0)
663 char buf
[MAX_REGISTER_SIZE
];
666 len
= register_size (current_gdbarch
, regnum
);
667 fprintf_filtered (stream
, "%-14s ", name
);
668 get_frame_register (frame
, regnum
, buf
);
669 print_scalar_formatted (buf
, type
, 'f', len
, stream
);
673 gdbarch_print_registers_info (current_gdbarch
, stream
,
677 /* Save formatted output in the buffer. */
678 p
= tui_file_get_strbuf (stream
);
680 /* Remove the possible \n. */
681 s
= strrchr (p
, '\n');
685 xfree (data_element
->content
);
686 data_element
->content
= xstrdup (p
);
687 do_cleanups (cleanups
);
690 /* Get the register value from the given frame and format it for
691 the display. When changep is set, check if the new register value
692 has changed with respect to the previous call. */
693 static enum tui_status
694 tui_get_register (struct gdbarch
*gdbarch
, struct frame_info
*frame
,
695 struct tui_data_element
*data
, int regnum
, int *changedp
)
697 enum tui_status ret
= TUI_FAILURE
;
701 if (target_has_registers
)
703 char buf
[MAX_REGISTER_SIZE
];
705 get_frame_register (frame
, regnum
, buf
);
706 /* NOTE: cagney/2003-03-13: This is bogus. It is refering to
707 the register cache and not the frame which could have pulled
708 the register value off the stack. */
709 if (register_cached (regnum
) >= 0)
713 int size
= register_size (gdbarch
, regnum
);
714 char *old
= (char*) data
->value
;
717 for (i
= 0; i
< size
; i
++)
718 if (buf
[i
] != old
[i
])
725 /* Reformat the data content if the value changed. */
726 if (changedp
== 0 || *changedp
== TRUE
)
727 tui_register_format (gdbarch
, frame
, data
, regnum
);
735 tui_scroll_regs_forward_command (char *arg
, int from_tty
)
737 tui_scroll (FORWARD_SCROLL
, TUI_DATA_WIN
, 1);
742 tui_scroll_regs_backward_command (char *arg
, int from_tty
)
744 tui_scroll (BACKWARD_SCROLL
, TUI_DATA_WIN
, 1);