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