Change tui_make_window to be a method
[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 if (target_has_registers && target_has_stack && target_has_memory)
156 {
157 show_register_group (group, get_selected_frame (NULL),
158 group == current_group);
159
160 /* Clear all notation of changed values. */
161 for (auto &&data_item_win : regs_content)
162 data_item_win.highlight = false;
163 current_group = group;
164 display_all_data ();
165 }
166 else
167 {
168 current_group = 0;
169 erase_data_content (_("[ Register Values Unavailable ]"));
170 }
171 }
172
173
174 /* Set the data window to display the registers of the register group
175 using the given frame. Values are refreshed only when
176 refresh_values_only is TRUE. */
177
178 void
179 tui_data_window::show_register_group (struct reggroup *group,
180 struct frame_info *frame,
181 int refresh_values_only)
182 {
183 struct gdbarch *gdbarch = get_frame_arch (frame);
184 int nr_regs;
185 int regnum, pos;
186
187 /* Make a new title showing which group we display. */
188 title = string_printf ("Register group: %s", reggroup_name (group));
189
190 /* See how many registers must be displayed. */
191 nr_regs = 0;
192 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
193 {
194 const char *name;
195
196 /* Must be in the group. */
197 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
198 continue;
199
200 /* If the register name is empty, it is undefined for this
201 processor, so don't display anything. */
202 name = gdbarch_register_name (gdbarch, regnum);
203 if (name == 0 || *name == '\0')
204 continue;
205
206 nr_regs++;
207 }
208
209 regs_content.resize (nr_regs);
210
211 /* Now set the register names and values. */
212 pos = 0;
213 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
214 {
215 struct tui_data_item_window *data_item_win;
216 const char *name;
217
218 /* Must be in the group. */
219 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
220 continue;
221
222 /* If the register name is empty, it is undefined for this
223 processor, so don't display anything. */
224 name = gdbarch_register_name (gdbarch, regnum);
225 if (name == 0 || *name == '\0')
226 continue;
227
228 data_item_win = &regs_content[pos];
229 if (data_item_win)
230 {
231 if (!refresh_values_only)
232 {
233 data_item_win->item_no = regnum;
234 data_item_win->name = name;
235 data_item_win->highlight = false;
236 }
237 tui_get_register (frame, data_item_win, regnum, 0);
238 }
239 pos++;
240 }
241 }
242
243 /* See tui-regs.h. */
244
245 void
246 tui_data_window::display_registers_from (int start_element_no)
247 {
248 if (!regs_content.empty ())
249 {
250 int j, item_win_width, cur_y;
251
252 int max_len = 0;
253 for (auto &&data_item_win : regs_content)
254 {
255 const char *p;
256 int len;
257
258 len = 0;
259 p = data_item_win.content.get ();
260 if (p != 0)
261 len = strlen (p);
262
263 if (len > max_len)
264 max_len = len;
265 }
266 item_win_width = max_len + 1;
267 int i = start_element_no;
268
269 regs_column_count = (width - 2) / item_win_width;
270 if (regs_column_count == 0)
271 regs_column_count = 1;
272 item_win_width = (width - 2) / regs_column_count;
273
274 /* Now create each data "sub" window, and write the display into
275 it. */
276 cur_y = 1;
277 while (i < regs_content.size ()
278 && cur_y <= viewport_height)
279 {
280 for (j = 0;
281 j < regs_column_count && i < regs_content.size ();
282 j++)
283 {
284 struct tui_data_item_window *data_item_win;
285
286 /* Create the window if necessary. */
287 data_item_win = &regs_content[i];
288 if (data_item_win->handle != NULL
289 && (data_item_win->height != 1
290 || data_item_win->width != item_win_width
291 || data_item_win->origin.x != (item_win_width * j) + 1
292 || data_item_win->origin.y != cur_y))
293 {
294 tui_delete_win (data_item_win->handle);
295 data_item_win->handle = 0;
296 }
297
298 if (data_item_win->handle == NULL)
299 {
300 data_item_win->height = 1;
301 data_item_win->width = item_win_width;
302 data_item_win->origin.x = (item_win_width * j) + 1;
303 data_item_win->origin.y = cur_y;
304 data_item_win->make_visible (true);
305 scrollok (data_item_win->handle, FALSE);
306 }
307 touchwin (data_item_win->handle);
308
309 /* Get the printable representation of the register
310 and display it. */
311 tui_display_register (data_item_win);
312 i++; /* Next register. */
313 }
314 cur_y++; /* Next row. */
315 }
316 }
317 }
318
319 /* See tui-regs.h. */
320
321 void
322 tui_data_window::display_reg_element_at_line (int start_element_no,
323 int start_line_no)
324 {
325 if (!regs_content.empty ())
326 {
327 int element_no = start_element_no;
328
329 if (start_element_no != 0 && start_line_no != 0)
330 {
331 int last_line_no, first_line_on_last_page;
332
333 last_line_no = last_regs_line_no ();
334 first_line_on_last_page = last_line_no - (height - 2);
335 if (first_line_on_last_page < 0)
336 first_line_on_last_page = 0;
337
338 /* If the element_no causes us to scroll past the end of the
339 registers, adjust what element to really start the
340 display at. */
341 if (start_line_no > first_line_on_last_page)
342 element_no = first_reg_element_no_inline (first_line_on_last_page);
343 }
344 display_registers_from (element_no);
345 }
346 }
347
348 /* See tui-regs.h. */
349
350 int
351 tui_data_window::display_registers_from_line (int line_no)
352 {
353 check_and_display_highlight_if_needed ();
354 if (!regs_content.empty ())
355 {
356 int element_no;
357
358 if (line_no < 0)
359 line_no = 0;
360 else
361 {
362 /* Make sure that we don't display off the end of the
363 registers. */
364 if (line_no >= last_regs_line_no ())
365 {
366 line_no = line_from_reg_element_no (regs_content.size () - 1);
367 if (line_no < 0)
368 line_no = 0;
369 }
370 }
371
372 element_no = first_reg_element_no_inline (line_no);
373 if (element_no < regs_content.size ())
374 display_reg_element_at_line (element_no, line_no);
375 else
376 line_no = (-1);
377
378 return line_no;
379 }
380
381 return (-1); /* Nothing was displayed. */
382 }
383
384
385 /* Answer the index first element displayed. If none are displayed,
386 then return (-1). */
387 int
388 tui_data_window::first_data_item_displayed ()
389 {
390 for (int i = 0; i < regs_content.size (); i++)
391 {
392 struct tui_gen_win_info *data_item_win;
393
394 data_item_win = &regs_content[i];
395 if (data_item_win->is_visible ())
396 return i;
397 }
398
399 return -1;
400 }
401
402 /* See tui-regs.h. */
403
404 void
405 tui_data_window::delete_data_content_windows ()
406 {
407 for (auto &&win : regs_content)
408 {
409 tui_delete_win (win.handle);
410 win.handle = NULL;
411 }
412 }
413
414
415 void
416 tui_data_window::erase_data_content (const char *prompt)
417 {
418 werase (handle);
419 check_and_display_highlight_if_needed ();
420 if (prompt != NULL)
421 {
422 int half_width = (width - 2) / 2;
423 int x_pos;
424
425 if (strlen (prompt) >= half_width)
426 x_pos = 1;
427 else
428 x_pos = half_width - strlen (prompt);
429 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
430 }
431 wrefresh (handle);
432 }
433
434 /* See tui-regs.h. */
435
436 void
437 tui_data_window::display_all_data ()
438 {
439 if (regs_content.empty ())
440 erase_data_content (NO_DATA_STRING);
441 else
442 {
443 erase_data_content (NULL);
444 delete_data_content_windows ();
445 check_and_display_highlight_if_needed ();
446 display_registers_from (0);
447 }
448 }
449
450
451 /* Function to redisplay the contents of the data window. */
452 void
453 tui_data_window::refresh_all ()
454 {
455 erase_data_content (NULL);
456 if (!regs_content.empty ())
457 {
458 int first_element = first_data_item_displayed ();
459
460 if (first_element >= 0) /* Re-use existing windows. */
461 {
462 int first_line = (-1);
463
464 if (first_element < regs_content.size ())
465 first_line = line_from_reg_element_no (first_element);
466
467 if (first_line >= 0)
468 {
469 erase_data_content (NULL);
470 display_registers_from_line (first_line);
471 }
472 }
473 }
474 }
475
476
477 /* Scroll the data window vertically forward or backward. */
478 void
479 tui_data_window::do_scroll_vertical (int num_to_scroll)
480 {
481 int first_element_no;
482 int first_line = (-1);
483
484 first_element_no = first_data_item_displayed ();
485 if (first_element_no < regs_content.size ())
486 first_line = line_from_reg_element_no (first_element_no);
487 else
488 { /* Calculate the first line from the element number which is in
489 the general data content. */
490 }
491
492 if (first_line >= 0)
493 {
494 first_line += num_to_scroll;
495 erase_data_content (NULL);
496 delete_data_content_windows ();
497 display_registers_from_line (first_line);
498 }
499 }
500
501 /* See tui-regs.h. */
502
503 void
504 tui_data_window::rerender ()
505 {
506 /* Delete all data item windows. */
507 for (auto &&win : regs_content)
508 {
509 tui_delete_win (win.handle);
510 win.handle = NULL;
511 }
512 display_all_data ();
513 }
514
515 /* See tui-regs.h. */
516
517 void
518 tui_data_window::refresh_window ()
519 {
520 tui_gen_win_info::refresh_window ();
521 for (auto &&win : regs_content)
522 win.refresh_window ();
523 }
524
525 /* This function check all displayed registers for changes in values,
526 given a particular frame. If the values have changed, they are
527 updated with the new value and highlighted. */
528 void
529 tui_data_window::check_register_values (struct frame_info *frame)
530 {
531 if (regs_content.empty ())
532 show_registers (current_group);
533 else
534 {
535 for (auto &&data_item_win : regs_content)
536 {
537 int was_hilighted;
538
539 was_hilighted = data_item_win.highlight;
540
541 tui_get_register (frame, &data_item_win,
542 data_item_win.item_no,
543 &data_item_win.highlight);
544
545 if (data_item_win.highlight || was_hilighted)
546 tui_display_register (&data_item_win);
547 }
548 }
549 }
550
551 /* Display a register in a window. If hilite is TRUE, then the value
552 will be displayed in reverse video. */
553 static void
554 tui_display_register (struct tui_data_item_window *data)
555 {
556 if (data->handle != NULL)
557 {
558 int i;
559
560 if (data->highlight)
561 /* We ignore the return value, casting it to void in order to avoid
562 a compiler warning. The warning itself was introduced by a patch
563 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
564 to code that causes the compiler to generate an unused-value
565 warning. */
566 (void) wstandout (data->handle);
567
568 wmove (data->handle, 0, 0);
569 for (i = 1; i < data->width; i++)
570 waddch (data->handle, ' ');
571 wmove (data->handle, 0, 0);
572 if (data->content)
573 waddstr (data->handle, data->content.get ());
574
575 if (data->highlight)
576 /* We ignore the return value, casting it to void in order to avoid
577 a compiler warning. The warning itself was introduced by a patch
578 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
579 to code that causes the compiler to generate an unused-value
580 warning. */
581 (void) wstandend (data->handle);
582 data->refresh_window ();
583 }
584 }
585
586 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
587 around behaviour. Returns the next register group, or NULL if the
588 register window is not currently being displayed. */
589
590 static struct reggroup *
591 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
592 {
593 struct reggroup *group = NULL;
594
595 if (current_group != NULL)
596 {
597 group = reggroup_next (gdbarch, current_group);
598 if (group == NULL)
599 group = reggroup_next (gdbarch, NULL);
600 }
601 return group;
602 }
603
604 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
605 around behaviour. Returns the previous register group, or NULL if the
606 register window is not currently being displayed. */
607
608 static struct reggroup *
609 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
610 {
611 struct reggroup *group = NULL;
612
613 if (current_group != NULL)
614 {
615 group = reggroup_prev (gdbarch, current_group);
616 if (group == NULL)
617 group = reggroup_prev (gdbarch, NULL);
618 }
619 return group;
620 }
621
622 /* A helper function to display the register window in the appropriate
623 way. */
624
625 static void
626 tui_reg_layout ()
627 {
628 enum tui_layout_type cur_layout = tui_current_layout ();
629 enum tui_layout_type new_layout;
630 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
631 new_layout = SRC_DATA_COMMAND;
632 else
633 new_layout = DISASSEM_DATA_COMMAND;
634 tui_set_layout (new_layout);
635 }
636
637 /* Implement the 'tui reg' command. Changes the register group displayed
638 in the tui register window. Displays the tui register window if it is
639 not already on display. */
640
641 static void
642 tui_reg_command (const char *args, int from_tty)
643 {
644 struct gdbarch *gdbarch = get_current_arch ();
645
646 if (args != NULL)
647 {
648 struct reggroup *group, *match = NULL;
649 size_t len = strlen (args);
650
651 /* Make sure the curses mode is enabled. */
652 tui_enable ();
653
654 /* Make sure the register window is visible. If not, select an
655 appropriate layout. We need to do this before trying to run the
656 'next' or 'prev' commands. */
657 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
658 tui_reg_layout ();
659
660 struct reggroup *current_group = TUI_DATA_WIN->current_group;
661 if (strncmp (args, "next", len) == 0)
662 match = tui_reg_next (current_group, gdbarch);
663 else if (strncmp (args, "prev", len) == 0)
664 match = tui_reg_prev (current_group, gdbarch);
665
666 /* This loop matches on the initial part of a register group
667 name. If this initial part in ARGS matches only one register
668 group then the switch is made. */
669 for (group = reggroup_next (gdbarch, NULL);
670 group != NULL;
671 group = reggroup_next (gdbarch, group))
672 {
673 if (strncmp (reggroup_name (group), args, len) == 0)
674 {
675 if (match != NULL)
676 error (_("ambiguous register group name '%s'"), args);
677 match = group;
678 }
679 }
680
681 if (match == NULL)
682 error (_("unknown register group '%s'"), args);
683
684 TUI_DATA_WIN->show_registers (match);
685 }
686 else
687 {
688 struct reggroup *group;
689 int first;
690
691 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
692 "either a register group,\nor one of 'next' "
693 "or 'prev'. Known register groups are:\n"));
694
695 for (first = 1, group = reggroup_next (gdbarch, NULL);
696 group != NULL;
697 first = 0, group = reggroup_next (gdbarch, group))
698 {
699 if (!first)
700 printf_unfiltered (", ");
701 printf_unfiltered ("%s", reggroup_name (group));
702 }
703
704 printf_unfiltered ("\n");
705 }
706 }
707
708 /* Complete names of register groups, and add the special "prev" and "next"
709 names. */
710
711 static void
712 tui_reggroup_completer (struct cmd_list_element *ignore,
713 completion_tracker &tracker,
714 const char *text, const char *word)
715 {
716 static const char *extra[] = { "next", "prev", NULL };
717 size_t len = strlen (word);
718 const char **tmp;
719
720 reggroup_completer (ignore, tracker, text, word);
721
722 /* XXXX use complete_on_enum instead? */
723 for (tmp = extra; *tmp != NULL; ++tmp)
724 {
725 if (strncmp (word, *tmp, len) == 0)
726 tracker.add_completion (make_unique_xstrdup (*tmp));
727 }
728 }
729
730 void
731 _initialize_tui_regs (void)
732 {
733 struct cmd_list_element **tuicmd, *cmd;
734
735 tuicmd = tui_get_cmd_list ();
736
737 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
738 TUI command to control the register window."), tuicmd);
739 set_cmd_completer (cmd, tui_reggroup_completer);
740 }
This page took 0.047434 seconds and 5 git commands to generate.