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