Add two methods to tui_data_window
[deliverable/binutils-gdb.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
4
5 Contributed by Hewlett-Packard Company.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "tui/tui.h"
25 #include "tui/tui-data.h"
26 #include "symtab.h"
27 #include "gdbtypes.h"
28 #include "gdbcmd.h"
29 #include "frame.h"
30 #include "regcache.h"
31 #include "inferior.h"
32 #include "target.h"
33 #include "tui/tui-layout.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-wingeneral.h"
36 #include "tui/tui-file.h"
37 #include "tui/tui-regs.h"
38 #include "tui/tui-io.h"
39 #include "reggroups.h"
40 #include "valprint.h"
41 #include "completer.h"
42
43 #include "gdb_curses.h"
44
45 static void tui_display_register (struct tui_data_item_window *data);
46
47 /* Get the register from the frame and return a printable
48 representation of it. */
49
50 static gdb::unique_xmalloc_ptr<char>
51 tui_register_format (struct frame_info *frame, int regnum)
52 {
53 struct gdbarch *gdbarch = get_frame_arch (frame);
54
55 string_file stream;
56
57 scoped_restore save_pagination
58 = make_scoped_restore (&pagination_enabled, 0);
59 scoped_restore save_stdout
60 = make_scoped_restore (&gdb_stdout, &stream);
61
62 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
63
64 /* Remove the possible \n. */
65 std::string &str = stream.string ();
66 if (!str.empty () && str.back () == '\n')
67 str.resize (str.size () - 1);
68
69 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
70 return tui_expand_tabs (str.c_str ());
71 }
72
73 /* Get the register value from the given frame and format it for the
74 display. When changep is set, check if the new register value has
75 changed with respect to the previous call. */
76 static void
77 tui_get_register (struct frame_info *frame,
78 struct tui_data_item_window *data,
79 int regnum, bool *changedp)
80 {
81 if (changedp)
82 *changedp = false;
83 if (target_has_registers)
84 {
85 gdb::unique_xmalloc_ptr<char> new_content
86 = tui_register_format (frame, regnum);
87
88 if (changedp != NULL
89 && strcmp (data->content.get (), new_content.get ()) != 0)
90 *changedp = true;
91
92 data->content = std::move (new_content);
93 }
94 }
95
96 /* See tui-regs.h. */
97
98 int
99 tui_data_window::last_regs_line_no () const
100 {
101 int num_lines = (-1);
102
103 if (!regs_content.empty ())
104 {
105 num_lines = regs_content.size () / regs_column_count;
106 if (regs_content.size () % regs_column_count)
107 num_lines++;
108 }
109 return num_lines;
110 }
111
112 /* See tui-regs.h. */
113
114 int
115 tui_data_window::line_from_reg_element_no (int element_no) const
116 {
117 if (element_no < regs_content.size ())
118 {
119 int i, line = (-1);
120
121 i = 1;
122 while (line == (-1))
123 {
124 if (element_no < regs_column_count * i)
125 line = i - 1;
126 else
127 i++;
128 }
129
130 return line;
131 }
132 else
133 return (-1);
134 }
135
136 /* See tui-regs.h. */
137
138 int
139 tui_data_window::first_reg_element_no_inline (int line_no) const
140 {
141 if (line_no * regs_column_count <= regs_content.size ())
142 return ((line_no + 1) * regs_column_count) - regs_column_count;
143 else
144 return (-1);
145 }
146
147 /* Show the registers of the given group in the data window
148 and refresh the window. */
149 void
150 tui_data_window::show_registers (struct reggroup *group)
151 {
152 if (group == 0)
153 group = general_reggroup;
154
155 /* Say that registers should be displayed, even if there is a
156 problem. */
157 display_regs = true;
158
159 if (target_has_registers && target_has_stack && target_has_memory)
160 {
161 show_register_group (group, get_selected_frame (NULL),
162 group == current_group);
163
164 /* Clear all notation of changed values. */
165 for (auto &&data_item_win : regs_content)
166 {
167 if (data_item_win != nullptr)
168 data_item_win->highlight = false;
169 }
170 current_group = group;
171 display_all_data ();
172 }
173 else
174 {
175 current_group = 0;
176 erase_data_content (_("[ Register Values Unavailable ]"));
177 }
178 }
179
180
181 /* Set the data window to display the registers of the register group
182 using the given frame. Values are refreshed only when
183 refresh_values_only is TRUE. */
184
185 void
186 tui_data_window::show_register_group (struct reggroup *group,
187 struct frame_info *frame,
188 int refresh_values_only)
189 {
190 struct gdbarch *gdbarch = get_frame_arch (frame);
191 int nr_regs;
192 int regnum, pos;
193
194 /* Make a new title showing which group we display. */
195 xfree (title);
196 title = xstrprintf ("Register group: %s", reggroup_name (group));
197
198 /* See how many registers must be displayed. */
199 nr_regs = 0;
200 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
201 {
202 const char *name;
203
204 /* Must be in the group. */
205 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
206 continue;
207
208 /* If the register name is empty, it is undefined for this
209 processor, so don't display anything. */
210 name = gdbarch_register_name (gdbarch, regnum);
211 if (name == 0 || *name == '\0')
212 continue;
213
214 nr_regs++;
215 }
216
217 if (!refresh_values_only)
218 regs_content.clear ();
219
220 if (nr_regs < regs_content.size ())
221 regs_content.resize (nr_regs);
222 else
223 {
224 for (int i = regs_content.size (); i < nr_regs; ++i)
225 regs_content.emplace_back (new tui_data_item_window ());
226 }
227
228 /* Now set the register names and values. */
229 pos = 0;
230 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
231 {
232 struct tui_data_item_window *data_item_win;
233 const char *name;
234
235 /* Must be in the group. */
236 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
237 continue;
238
239 /* If the register name is empty, it is undefined for this
240 processor, so don't display anything. */
241 name = gdbarch_register_name (gdbarch, regnum);
242 if (name == 0 || *name == '\0')
243 continue;
244
245 data_item_win = regs_content[pos].get ();
246 if (data_item_win)
247 {
248 if (!refresh_values_only)
249 {
250 data_item_win->item_no = regnum;
251 data_item_win->name = name;
252 data_item_win->highlight = false;
253 }
254 tui_get_register (frame, data_item_win, regnum, 0);
255 }
256 pos++;
257 }
258 }
259
260 /* See tui-regs.h. */
261
262 void
263 tui_data_window::display_registers_from (int start_element_no)
264 {
265 if (!regs_content.empty ())
266 {
267 int j, item_win_width, cur_y;
268
269 int max_len = 0;
270 for (auto &&data_item_win : regs_content)
271 {
272 const char *p;
273 int len;
274
275 len = 0;
276 p = data_item_win->content.get ();
277 if (p != 0)
278 len = strlen (p);
279
280 if (len > max_len)
281 max_len = len;
282 }
283 item_win_width = max_len + 1;
284 int i = start_element_no;
285
286 regs_column_count = (width - 2) / item_win_width;
287 if (regs_column_count == 0)
288 regs_column_count = 1;
289 item_win_width = (width - 2) / regs_column_count;
290
291 /* Now create each data "sub" window, and write the display into
292 it. */
293 cur_y = 1;
294 while (i < regs_content.size ()
295 && cur_y <= viewport_height)
296 {
297 for (j = 0;
298 j < regs_column_count && i < regs_content.size ();
299 j++)
300 {
301 struct tui_data_item_window *data_item_win;
302
303 /* Create the window if necessary. */
304 data_item_win = regs_content[i].get ();
305 if (data_item_win->handle != NULL
306 && (data_item_win->height != 1
307 || data_item_win->width != item_win_width
308 || data_item_win->origin.x != (item_win_width * j) + 1
309 || data_item_win->origin.y != cur_y))
310 {
311 tui_delete_win (data_item_win->handle);
312 data_item_win->handle = 0;
313 }
314
315 if (data_item_win->handle == NULL)
316 {
317 data_item_win->height = 1;
318 data_item_win->width = item_win_width;
319 data_item_win->origin.x = (item_win_width * j) + 1;
320 data_item_win->origin.y = cur_y;
321 tui_make_window (data_item_win);
322 scrollok (data_item_win->handle, FALSE);
323 }
324 touchwin (data_item_win->handle);
325
326 /* Get the printable representation of the register
327 and display it. */
328 tui_display_register (data_item_win);
329 i++; /* Next register. */
330 }
331 cur_y++; /* Next row. */
332 }
333 }
334 }
335
336 /* See tui-regs.h. */
337
338 void
339 tui_data_window::display_reg_element_at_line (int start_element_no,
340 int start_line_no)
341 {
342 if (!regs_content.empty ())
343 {
344 int element_no = start_element_no;
345
346 if (start_element_no != 0 && start_line_no != 0)
347 {
348 int last_line_no, first_line_on_last_page;
349
350 last_line_no = last_regs_line_no ();
351 first_line_on_last_page = last_line_no - (height - 2);
352 if (first_line_on_last_page < 0)
353 first_line_on_last_page = 0;
354
355 /* If the element_no causes us to scroll past the end of the
356 registers, adjust what element to really start the
357 display at. */
358 if (start_line_no > first_line_on_last_page)
359 element_no = first_reg_element_no_inline (first_line_on_last_page);
360 }
361 display_registers_from (element_no);
362 }
363 }
364
365 /* See tui-regs.h. */
366
367 int
368 tui_data_window::display_registers_from_line (int line_no)
369 {
370 check_and_display_highlight_if_needed ();
371 if (!regs_content.empty ())
372 {
373 int element_no;
374
375 if (line_no < 0)
376 line_no = 0;
377 else
378 {
379 /* Make sure that we don't display off the end of the
380 registers. */
381 if (line_no >= last_regs_line_no ())
382 {
383 line_no = line_from_reg_element_no (regs_content.size () - 1);
384 if (line_no < 0)
385 line_no = 0;
386 }
387 }
388
389 element_no = first_reg_element_no_inline (line_no);
390 if (element_no < regs_content.size ())
391 display_reg_element_at_line (element_no, line_no);
392 else
393 line_no = (-1);
394
395 return line_no;
396 }
397
398 return (-1); /* Nothing was displayed. */
399 }
400
401
402 /* Answer the index first element displayed. If none are displayed,
403 then return (-1). */
404 int
405 tui_data_window::first_data_item_displayed ()
406 {
407 for (int i = 0; i < regs_content.size (); i++)
408 {
409 struct tui_gen_win_info *data_item_win;
410
411 data_item_win = regs_content[i].get ();
412 if (data_item_win->is_visible ())
413 return i;
414 }
415
416 return -1;
417 }
418
419 /* See tui-regs.h. */
420
421 void
422 tui_data_window::delete_data_content_windows ()
423 {
424 for (auto &&win : regs_content)
425 {
426 tui_delete_win (win->handle);
427 win->handle = NULL;
428 }
429 }
430
431
432 void
433 tui_data_window::erase_data_content (const char *prompt)
434 {
435 werase (handle);
436 check_and_display_highlight_if_needed ();
437 if (prompt != NULL)
438 {
439 int half_width = (width - 2) / 2;
440 int x_pos;
441
442 if (strlen (prompt) >= half_width)
443 x_pos = 1;
444 else
445 x_pos = half_width - strlen (prompt);
446 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
447 }
448 wrefresh (handle);
449 }
450
451 /* See tui-regs.h. */
452
453 void
454 tui_data_window::display_all_data ()
455 {
456 if (regs_content.empty ())
457 erase_data_content (NO_DATA_STRING);
458 else
459 {
460 erase_data_content (NULL);
461 delete_data_content_windows ();
462 check_and_display_highlight_if_needed ();
463 display_registers_from (0);
464 }
465 }
466
467
468 /* Function to redisplay the contents of the data window. */
469 void
470 tui_data_window::refresh_all ()
471 {
472 erase_data_content (NULL);
473 if (!regs_content.empty ())
474 {
475 int first_element = first_data_item_displayed ();
476
477 if (first_element >= 0) /* Re-use existing windows. */
478 {
479 int first_line = (-1);
480
481 if (first_element < regs_content.size ())
482 first_line = line_from_reg_element_no (first_element);
483
484 if (first_line >= 0)
485 {
486 erase_data_content (NULL);
487 display_registers_from_line (first_line);
488 }
489 }
490 }
491 }
492
493
494 /* Scroll the data window vertically forward or backward. */
495 void
496 tui_data_window::do_scroll_vertical (int num_to_scroll)
497 {
498 int first_element_no;
499 int first_line = (-1);
500
501 first_element_no = first_data_item_displayed ();
502 if (first_element_no < regs_content.size ())
503 first_line = line_from_reg_element_no (first_element_no);
504 else
505 { /* Calculate the first line from the element number which is in
506 the general data content. */
507 }
508
509 if (first_line >= 0)
510 {
511 first_line += num_to_scroll;
512 erase_data_content (NULL);
513 delete_data_content_windows ();
514 display_registers_from_line (first_line);
515 }
516 }
517
518 /* See tui-regs.h. */
519
520 void
521 tui_data_window::rerender ()
522 {
523 /* Delete all data item windows. */
524 for (auto &&win : regs_content)
525 {
526 tui_delete_win (win->handle);
527 win->handle = NULL;
528 }
529 display_all_data ();
530 }
531
532 /* See tui-regs.h. */
533
534 void
535 tui_data_window::refresh_window ()
536 {
537 tui_gen_win_info::refresh_window ();
538 for (auto &&win : regs_content)
539 {
540 if (win != NULL)
541 win->refresh_window ();
542 }
543 }
544
545 /* This function check all displayed registers for changes in values,
546 given a particular frame. If the values have changed, they are
547 updated with the new value and highlighted. */
548 void
549 tui_data_window::check_register_values (struct frame_info *frame)
550 {
551 if (regs_content.empty () && display_regs)
552 show_registers (current_group);
553 else
554 {
555 for (auto &&data_item_win_ptr : regs_content)
556 {
557 int was_hilighted;
558
559 was_hilighted = data_item_win_ptr->highlight;
560
561 tui_get_register (frame, data_item_win_ptr.get (),
562 data_item_win_ptr->item_no,
563 &data_item_win_ptr->highlight);
564
565 if (data_item_win_ptr->highlight || was_hilighted)
566 tui_display_register (data_item_win_ptr.get ());
567 }
568 }
569 }
570
571 /* Display a register in a window. If hilite is TRUE, then the value
572 will be displayed in reverse video. */
573 static void
574 tui_display_register (struct tui_data_item_window *data)
575 {
576 if (data->handle != NULL)
577 {
578 int i;
579
580 if (data->highlight)
581 /* We ignore the return value, casting it to void in order to avoid
582 a compiler warning. The warning itself was introduced by a patch
583 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
584 to code that causes the compiler to generate an unused-value
585 warning. */
586 (void) wstandout (data->handle);
587
588 wmove (data->handle, 0, 0);
589 for (i = 1; i < data->width; i++)
590 waddch (data->handle, ' ');
591 wmove (data->handle, 0, 0);
592 if (data->content)
593 waddstr (data->handle, data->content.get ());
594
595 if (data->highlight)
596 /* We ignore the return value, casting it to void in order to avoid
597 a compiler warning. The warning itself was introduced by a patch
598 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
599 to code that causes the compiler to generate an unused-value
600 warning. */
601 (void) wstandend (data->handle);
602 data->refresh_window ();
603 }
604 }
605
606 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
607 around behaviour. Returns the next register group, or NULL if the
608 register window is not currently being displayed. */
609
610 static struct reggroup *
611 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
612 {
613 struct reggroup *group = NULL;
614
615 if (current_group != NULL)
616 {
617 group = reggroup_next (gdbarch, current_group);
618 if (group == NULL)
619 group = reggroup_next (gdbarch, NULL);
620 }
621 return group;
622 }
623
624 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
625 around behaviour. Returns the previous register group, or NULL if the
626 register window is not currently being displayed. */
627
628 static struct reggroup *
629 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
630 {
631 struct reggroup *group = NULL;
632
633 if (current_group != NULL)
634 {
635 group = reggroup_prev (gdbarch, current_group);
636 if (group == NULL)
637 group = reggroup_prev (gdbarch, NULL);
638 }
639 return group;
640 }
641
642 /* A helper function to display the register window in the appropriate
643 way. */
644
645 static void
646 tui_reg_layout ()
647 {
648 enum tui_layout_type cur_layout = tui_current_layout ();
649 enum tui_layout_type new_layout;
650 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
651 new_layout = SRC_DATA_COMMAND;
652 else
653 new_layout = DISASSEM_DATA_COMMAND;
654 tui_set_layout (new_layout);
655 }
656
657 /* Implement the 'tui reg' command. Changes the register group displayed
658 in the tui register window. Displays the tui register window if it is
659 not already on display. */
660
661 static void
662 tui_reg_command (const char *args, int from_tty)
663 {
664 struct gdbarch *gdbarch = get_current_arch ();
665
666 if (args != NULL)
667 {
668 struct reggroup *group, *match = NULL;
669 size_t len = strlen (args);
670
671 /* Make sure the curses mode is enabled. */
672 tui_enable ();
673
674 /* Make sure the register window is visible. If not, select an
675 appropriate layout. We need to do this before trying to run the
676 'next' or 'prev' commands. */
677 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
678 tui_reg_layout ();
679
680 struct reggroup *current_group = TUI_DATA_WIN->current_group;
681 if (strncmp (args, "next", len) == 0)
682 match = tui_reg_next (current_group, gdbarch);
683 else if (strncmp (args, "prev", len) == 0)
684 match = tui_reg_prev (current_group, gdbarch);
685
686 /* This loop matches on the initial part of a register group
687 name. If this initial part in ARGS matches only one register
688 group then the switch is made. */
689 for (group = reggroup_next (gdbarch, NULL);
690 group != NULL;
691 group = reggroup_next (gdbarch, group))
692 {
693 if (strncmp (reggroup_name (group), args, len) == 0)
694 {
695 if (match != NULL)
696 error (_("ambiguous register group name '%s'"), args);
697 match = group;
698 }
699 }
700
701 if (match == NULL)
702 error (_("unknown register group '%s'"), args);
703
704 TUI_DATA_WIN->show_registers (match);
705 }
706 else
707 {
708 struct reggroup *group;
709 int first;
710
711 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
712 "either a register group,\nor one of 'next' "
713 "or 'prev'. Known register groups are:\n"));
714
715 for (first = 1, group = reggroup_next (gdbarch, NULL);
716 group != NULL;
717 first = 0, group = reggroup_next (gdbarch, group))
718 {
719 if (!first)
720 printf_unfiltered (", ");
721 printf_unfiltered ("%s", reggroup_name (group));
722 }
723
724 printf_unfiltered ("\n");
725 }
726 }
727
728 /* Complete names of register groups, and add the special "prev" and "next"
729 names. */
730
731 static void
732 tui_reggroup_completer (struct cmd_list_element *ignore,
733 completion_tracker &tracker,
734 const char *text, const char *word)
735 {
736 static const char *extra[] = { "next", "prev", NULL };
737 size_t len = strlen (word);
738 const char **tmp;
739
740 reggroup_completer (ignore, tracker, text, word);
741
742 /* XXXX use complete_on_enum instead? */
743 for (tmp = extra; *tmp != NULL; ++tmp)
744 {
745 if (strncmp (word, *tmp, len) == 0)
746 tracker.add_completion (make_unique_xstrdup (*tmp));
747 }
748 }
749
750 void
751 _initialize_tui_regs (void)
752 {
753 struct cmd_list_element **tuicmd, *cmd;
754
755 tuicmd = tui_get_cmd_list ();
756
757 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
758 TUI command to control the register window."), tuicmd);
759 set_cmd_completer (cmd, tui_reggroup_completer);
760 }
This page took 0.058848 seconds and 4 git commands to generate.