Commit | Line | Data |
---|---|---|
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" | |
35 | #include "tui/tui-windata.h" | |
36 | #include "tui/tui-wingeneral.h" | |
37 | #include "tui/tui-file.h" | |
2c0b251b | 38 | #include "tui/tui-regs.h" |
312809f8 | 39 | #include "tui/tui-io.h" |
10f59415 | 40 | #include "reggroups.h" |
79a45b7d | 41 | #include "valprint.h" |
51f0e40d | 42 | #include "completer.h" |
c906108c | 43 | |
6a83354a | 44 | #include "gdb_curses.h" |
96ec9981 | 45 | |
c906108c SS |
46 | |
47 | /***************************************** | |
10f59415 | 48 | ** STATIC LOCAL FUNCTIONS FORWARD DECLS ** |
c906108c | 49 | ******************************************/ |
10f59415 SC |
50 | static void |
51 | tui_display_register (struct tui_data_element *data, | |
52 | struct tui_gen_win_info *win_info); | |
c906108c | 53 | |
5eccfcc2 UW |
54 | static enum tui_status tui_show_register_group (struct reggroup *group, |
55 | struct frame_info *frame, | |
56 | int refresh_values_only); | |
57 | ||
58 | static enum tui_status tui_get_register (struct frame_info *frame, | |
59 | struct tui_data_element *data, | |
60 | int regnum, int *changedp); | |
61 | ||
c906108c SS |
62 | |
63 | ||
64 | /***************************************** | |
65 | ** PUBLIC FUNCTIONS ** | |
66 | ******************************************/ | |
67 | ||
55fb0713 AC |
68 | /* Answer the number of the last line in the regs display. If there |
69 | are no registers (-1) is returned. */ | |
c906108c | 70 | int |
55fb0713 | 71 | tui_last_regs_line_no (void) |
c906108c | 72 | { |
d02c80cd | 73 | int num_lines = (-1); |
c906108c | 74 | |
238eb706 | 75 | if (TUI_DATA_WIN->regs_content_count > 0) |
c906108c | 76 | { |
238eb706 TT |
77 | num_lines = (TUI_DATA_WIN->regs_content_count |
78 | / TUI_DATA_WIN->regs_column_count); | |
79 | if (TUI_DATA_WIN->regs_content_count % TUI_DATA_WIN->regs_column_count) | |
6ba8e26f | 80 | num_lines++; |
c906108c | 81 | } |
6ba8e26f | 82 | return num_lines; |
55fb0713 | 83 | } |
c906108c SS |
84 | |
85 | ||
6ba8e26f AC |
86 | /* Answer the line number that the register element at element_no is |
87 | on. If element_no is greater than the number of register elements | |
55fb0713 | 88 | there are, -1 is returned. */ |
c906108c | 89 | int |
6ba8e26f | 90 | tui_line_from_reg_element_no (int element_no) |
c906108c | 91 | { |
238eb706 | 92 | if (element_no < TUI_DATA_WIN->regs_content_count) |
c906108c SS |
93 | { |
94 | int i, line = (-1); | |
95 | ||
96 | i = 1; | |
97 | while (line == (-1)) | |
98 | { | |
238eb706 | 99 | if (element_no < TUI_DATA_WIN->regs_column_count * i) |
c906108c SS |
100 | line = i - 1; |
101 | else | |
102 | i++; | |
103 | } | |
104 | ||
105 | return line; | |
106 | } | |
107 | else | |
108 | return (-1); | |
55fb0713 | 109 | } |
c906108c SS |
110 | |
111 | ||
1cc6d956 MS |
112 | /* Answer the index of the first element in line_no. If line_no is |
113 | past the register area (-1) is returned. */ | |
c906108c | 114 | int |
6ba8e26f | 115 | tui_first_reg_element_no_inline (int line_no) |
c906108c | 116 | { |
238eb706 TT |
117 | if ((line_no * TUI_DATA_WIN->regs_column_count) |
118 | <= TUI_DATA_WIN->regs_content_count) | |
119 | return (((line_no + 1) * TUI_DATA_WIN->regs_column_count) | |
120 | - TUI_DATA_WIN->regs_column_count); | |
c906108c SS |
121 | else |
122 | return (-1); | |
55fb0713 | 123 | } |
c906108c SS |
124 | |
125 | ||
10f59415 SC |
126 | /* Show the registers of the given group in the data window |
127 | and refresh the window. */ | |
c906108c | 128 | void |
10f59415 | 129 | tui_show_registers (struct reggroup *group) |
c906108c | 130 | { |
22940a24 | 131 | enum tui_status ret = TUI_FAILURE; |
c906108c | 132 | |
0bfbda3b SC |
133 | /* Make sure the curses mode is enabled. */ |
134 | tui_enable (); | |
135 | ||
136 | /* Make sure the register window is visible. If not, select an | |
137 | appropriate layout. */ | |
138 | if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible) | |
7bd0be3a | 139 | tui_set_layout_by_name (DATA_NAME); |
0bfbda3b | 140 | |
10f59415 SC |
141 | if (group == 0) |
142 | group = general_reggroup; | |
c906108c | 143 | |
1cc6d956 MS |
144 | /* Say that registers should be displayed, even if there is a |
145 | problem. */ | |
ceb13a13 | 146 | TUI_DATA_WIN->display_regs = true; |
10f59415 SC |
147 | |
148 | if (target_has_registers && target_has_stack && target_has_memory) | |
c906108c | 149 | { |
8eb6bda2 | 150 | ret = tui_show_register_group (group, get_selected_frame (NULL), |
238eb706 | 151 | group == TUI_DATA_WIN->current_group); |
c906108c SS |
152 | } |
153 | if (ret == TUI_FAILURE) | |
154 | { | |
238eb706 | 155 | TUI_DATA_WIN->current_group = 0; |
edae1ccf | 156 | tui_erase_data_content (NO_REGS_STRING); |
c906108c SS |
157 | } |
158 | else | |
159 | { | |
160 | int i; | |
161 | ||
1cc6d956 | 162 | /* Clear all notation of changed values. */ |
238eb706 | 163 | for (i = 0; i < TUI_DATA_WIN->regs_content_count; i++) |
c906108c | 164 | { |
10f59415 SC |
165 | struct tui_gen_win_info *data_item_win; |
166 | struct tui_win_element *win; | |
c906108c | 167 | |
dc2c33e4 | 168 | data_item_win = TUI_DATA_WIN->regs_content[i] |
10f59415 | 169 | ->which_element.data_window; |
63ed8182 | 170 | win = data_item_win->content[0]; |
10f59415 | 171 | win->which_element.data.highlight = FALSE; |
c906108c | 172 | } |
238eb706 | 173 | TUI_DATA_WIN->current_group = group; |
edae1ccf | 174 | tui_display_all_data (); |
c906108c | 175 | } |
55fb0713 | 176 | } |
c906108c SS |
177 | |
178 | ||
10f59415 | 179 | /* Set the data window to display the registers of the register group |
1cc6d956 MS |
180 | using the given frame. Values are refreshed only when |
181 | refresh_values_only is TRUE. */ | |
10f59415 SC |
182 | |
183 | static enum tui_status | |
5eccfcc2 | 184 | tui_show_register_group (struct reggroup *group, |
08ef48c5 MS |
185 | struct frame_info *frame, |
186 | int refresh_values_only) | |
10f59415 | 187 | { |
5eccfcc2 | 188 | struct gdbarch *gdbarch = get_frame_arch (frame); |
10f59415 SC |
189 | enum tui_status ret = TUI_FAILURE; |
190 | int nr_regs; | |
191 | int allocated_here = FALSE; | |
192 | int regnum, pos; | |
193 | char title[80]; | |
10f59415 SC |
194 | |
195 | /* Make a new title showing which group we display. */ | |
196 | snprintf (title, sizeof (title) - 1, "Register group: %s", | |
197 | reggroup_name (group)); | |
198 | xfree (TUI_DATA_WIN->generic.title); | |
199 | TUI_DATA_WIN->generic.title = xstrdup (title); | |
200 | ||
201 | /* See how many registers must be displayed. */ | |
202 | nr_regs = 0; | |
f6efe3f8 | 203 | for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) |
10f59415 | 204 | { |
d20c1c3f PA |
205 | const char *name; |
206 | ||
207 | /* Must be in the group. */ | |
208 | if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) | |
209 | continue; | |
210 | ||
211 | /* If the register name is empty, it is undefined for this | |
212 | processor, so don't display anything. */ | |
213 | name = gdbarch_register_name (gdbarch, regnum); | |
214 | if (name == 0 || *name == '\0') | |
215 | continue; | |
216 | ||
217 | nr_regs++; | |
10f59415 SC |
218 | } |
219 | ||
238eb706 | 220 | if (TUI_DATA_WIN->regs_content_count > 0 && !refresh_values_only) |
10f59415 | 221 | { |
238eb706 TT |
222 | tui_free_data_content (TUI_DATA_WIN->regs_content, |
223 | TUI_DATA_WIN->regs_content_count); | |
224 | TUI_DATA_WIN->regs_content_count = 0; | |
10f59415 SC |
225 | } |
226 | ||
238eb706 | 227 | if (TUI_DATA_WIN->regs_content_count <= 0) |
10f59415 | 228 | { |
238eb706 | 229 | TUI_DATA_WIN->regs_content = tui_alloc_content (nr_regs, DATA_WIN); |
10f59415 SC |
230 | allocated_here = TRUE; |
231 | refresh_values_only = FALSE; | |
232 | } | |
233 | ||
238eb706 | 234 | if (TUI_DATA_WIN->regs_content != NULL) |
10f59415 SC |
235 | { |
236 | if (!refresh_values_only || allocated_here) | |
237 | { | |
e65b5245 | 238 | TUI_DATA_WIN->generic.content = NULL; |
10f59415 SC |
239 | TUI_DATA_WIN->generic.content_size = 0; |
240 | tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs); | |
238eb706 TT |
241 | TUI_DATA_WIN->regs_content = TUI_DATA_WIN->generic.content; |
242 | TUI_DATA_WIN->regs_content_count = nr_regs; | |
10f59415 SC |
243 | } |
244 | ||
1cc6d956 | 245 | /* Now set the register names and values. */ |
10f59415 | 246 | pos = 0; |
f6efe3f8 | 247 | for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) |
10f59415 SC |
248 | { |
249 | struct tui_gen_win_info *data_item_win; | |
250 | struct tui_data_element *data; | |
251 | const char *name; | |
252 | ||
d20c1c3f | 253 | /* Must be in the group. */ |
10f59415 SC |
254 | if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) |
255 | continue; | |
256 | ||
d20c1c3f PA |
257 | /* If the register name is empty, it is undefined for this |
258 | processor, so don't display anything. */ | |
259 | name = gdbarch_register_name (gdbarch, regnum); | |
260 | if (name == 0 || *name == '\0') | |
261 | continue; | |
10f59415 SC |
262 | |
263 | data_item_win = | |
dc2c33e4 | 264 | TUI_DATA_WIN->regs_content[pos]->which_element.data_window; |
63ed8182 | 265 | data = &data_item_win->content[0]->which_element.data; |
10f59415 SC |
266 | if (data) |
267 | { | |
268 | if (!refresh_values_only) | |
269 | { | |
270 | data->item_no = regnum; | |
271 | data->name = name; | |
272 | data->highlight = FALSE; | |
273 | } | |
5eccfcc2 | 274 | tui_get_register (frame, data, regnum, 0); |
10f59415 SC |
275 | } |
276 | pos++; | |
277 | } | |
278 | ||
279 | TUI_DATA_WIN->generic.content_size = | |
238eb706 | 280 | TUI_DATA_WIN->regs_content_count + TUI_DATA_WIN->data_content_count; |
10f59415 SC |
281 | ret = TUI_SUCCESS; |
282 | } | |
283 | ||
284 | return ret; | |
285 | } | |
286 | ||
55fb0713 | 287 | /* Function to display the registers in the content from |
6ba8e26f | 288 | 'start_element_no' until the end of the register content or the end |
55fb0713 AC |
289 | of the display height. No checking for displaying past the end of |
290 | the registers is done here. */ | |
c906108c | 291 | void |
6ba8e26f | 292 | tui_display_registers_from (int start_element_no) |
c906108c | 293 | { |
238eb706 TT |
294 | if (TUI_DATA_WIN->regs_content != NULL |
295 | && TUI_DATA_WIN->regs_content_count > 0) | |
c906108c | 296 | { |
d02c80cd | 297 | int i = start_element_no; |
0043e6a5 | 298 | int j, item_win_width, cur_y; |
10f59415 SC |
299 | |
300 | int max_len = 0; | |
238eb706 | 301 | for (i = 0; i < TUI_DATA_WIN->regs_content_count; i++) |
10f59415 SC |
302 | { |
303 | struct tui_data_element *data; | |
304 | struct tui_gen_win_info *data_item_win; | |
305 | char *p; | |
306 | int len; | |
307 | ||
9a2b4c1b | 308 | data_item_win |
dc2c33e4 | 309 | = TUI_DATA_WIN->regs_content[i]->which_element.data_window; |
63ed8182 | 310 | data = &data_item_win->content[0]->which_element.data; |
10f59415 SC |
311 | len = 0; |
312 | p = data->content; | |
313 | if (p != 0) | |
314 | while (*p) | |
315 | { | |
316 | if (*p++ == '\t') | |
317 | len = 8 * ((len / 8) + 1); | |
318 | else | |
319 | len++; | |
320 | } | |
321 | ||
322 | if (len > max_len) | |
323 | max_len = len; | |
324 | } | |
325 | item_win_width = max_len + 1; | |
326 | i = start_element_no; | |
327 | ||
238eb706 | 328 | TUI_DATA_WIN->regs_column_count = |
10f59415 | 329 | (TUI_DATA_WIN->generic.width - 2) / item_win_width; |
238eb706 TT |
330 | if (TUI_DATA_WIN->regs_column_count == 0) |
331 | TUI_DATA_WIN->regs_column_count = 1; | |
10f59415 | 332 | item_win_width = |
238eb706 | 333 | (TUI_DATA_WIN->generic.width - 2) / TUI_DATA_WIN->regs_column_count; |
10f59415 | 334 | |
ef5eab5a MS |
335 | /* Now create each data "sub" window, and write the display into |
336 | it. */ | |
6ba8e26f | 337 | cur_y = 1; |
238eb706 | 338 | while (i < TUI_DATA_WIN->regs_content_count |
e5908723 | 339 | && cur_y <= TUI_DATA_WIN->generic.viewport_height) |
c906108c SS |
340 | { |
341 | for (j = 0; | |
238eb706 TT |
342 | j < TUI_DATA_WIN->regs_column_count |
343 | && i < TUI_DATA_WIN->regs_content_count; | |
e5908723 | 344 | j++) |
c906108c | 345 | { |
5b6fe301 MS |
346 | struct tui_gen_win_info *data_item_win; |
347 | struct tui_data_element *data_element_ptr; | |
c906108c | 348 | |
1cc6d956 | 349 | /* Create the window if necessary. */ |
dc2c33e4 | 350 | data_item_win = TUI_DATA_WIN->regs_content[i] |
10f59415 | 351 | ->which_element.data_window; |
63ed8182 | 352 | data_element_ptr = &data_item_win->content[0]->which_element.data; |
cafb3438 | 353 | if (data_item_win->handle != NULL |
10f59415 SC |
354 | && (data_item_win->height != 1 |
355 | || data_item_win->width != item_win_width | |
356 | || data_item_win->origin.x != (item_win_width * j) + 1 | |
357 | || data_item_win->origin.y != cur_y)) | |
358 | { | |
359 | tui_delete_win (data_item_win->handle); | |
360 | data_item_win->handle = 0; | |
361 | } | |
362 | ||
cafb3438 | 363 | if (data_item_win->handle == NULL) |
c906108c | 364 | { |
6ba8e26f | 365 | data_item_win->height = 1; |
10f59415 | 366 | data_item_win->width = item_win_width; |
6ba8e26f AC |
367 | data_item_win->origin.x = (item_win_width * j) + 1; |
368 | data_item_win->origin.y = cur_y; | |
369 | tui_make_window (data_item_win, DONT_BOX_WINDOW); | |
370 | scrollok (data_item_win->handle, FALSE); | |
c906108c | 371 | } |
6ba8e26f | 372 | touchwin (data_item_win->handle); |
fea14702 | 373 | |
10f59415 SC |
374 | /* Get the printable representation of the register |
375 | and display it. */ | |
376 | tui_display_register (data_element_ptr, data_item_win); | |
1cc6d956 | 377 | i++; /* Next register. */ |
c906108c | 378 | } |
1cc6d956 | 379 | cur_y++; /* Next row. */ |
c906108c SS |
380 | } |
381 | } | |
55fb0713 | 382 | } |
c906108c SS |
383 | |
384 | ||
6ba8e26f AC |
385 | /* Function to display the registers in the content from |
386 | 'start_element_no' on 'start_line_no' until the end of the register | |
387 | content or the end of the display height. This function checks | |
388 | that we won't display off the end of the register display. */ | |
2c0b251b | 389 | static void |
08ef48c5 MS |
390 | tui_display_reg_element_at_line (int start_element_no, |
391 | int start_line_no) | |
c906108c | 392 | { |
238eb706 TT |
393 | if (TUI_DATA_WIN->regs_content != NULL |
394 | && TUI_DATA_WIN->regs_content_count > 0) | |
c906108c | 395 | { |
d02c80cd | 396 | int element_no = start_element_no; |
c906108c | 397 | |
6ba8e26f | 398 | if (start_element_no != 0 && start_line_no != 0) |
c906108c | 399 | { |
d02c80cd | 400 | int last_line_no, first_line_on_last_page; |
c906108c | 401 | |
6ba8e26f | 402 | last_line_no = tui_last_regs_line_no (); |
9a2b4c1b MS |
403 | first_line_on_last_page |
404 | = last_line_no - (TUI_DATA_WIN->generic.height - 2); | |
6ba8e26f AC |
405 | if (first_line_on_last_page < 0) |
406 | first_line_on_last_page = 0; | |
ef5eab5a MS |
407 | |
408 | /* If there is no other data displayed except registers, and | |
409 | the element_no causes us to scroll past the end of the | |
410 | registers, adjust what element to really start the | |
411 | display at. */ | |
238eb706 | 412 | if (TUI_DATA_WIN->data_content_count <= 0 |
e5908723 | 413 | && start_line_no > first_line_on_last_page) |
9a2b4c1b MS |
414 | element_no |
415 | = tui_first_reg_element_no_inline (first_line_on_last_page); | |
c906108c | 416 | } |
6ba8e26f | 417 | tui_display_registers_from (element_no); |
c906108c | 418 | } |
6ba8e26f | 419 | } |
c906108c SS |
420 | |
421 | ||
422 | ||
6ba8e26f | 423 | /* Function to display the registers starting at line line_no in the |
55fb0713 AC |
424 | data window. Answers the line number that the display actually |
425 | started from. If nothing is displayed (-1) is returned. */ | |
c906108c | 426 | int |
08ef48c5 MS |
427 | tui_display_registers_from_line (int line_no, |
428 | int force_display) | |
c906108c | 429 | { |
238eb706 | 430 | if (TUI_DATA_WIN->regs_content_count > 0) |
c906108c | 431 | { |
6ba8e26f | 432 | int line, element_no; |
c906108c | 433 | |
6ba8e26f | 434 | if (line_no < 0) |
c906108c | 435 | line = 0; |
6ba8e26f | 436 | else if (force_display) |
ef5eab5a MS |
437 | { /* If we must display regs (force_display is true), then |
438 | make sure that we don't display off the end of the | |
439 | registers. */ | |
6ba8e26f | 440 | if (line_no >= tui_last_regs_line_no ()) |
c906108c | 441 | { |
55fb0713 | 442 | if ((line = tui_line_from_reg_element_no ( |
238eb706 | 443 | TUI_DATA_WIN->regs_content_count - 1)) < 0) |
c906108c SS |
444 | line = 0; |
445 | } | |
446 | else | |
6ba8e26f | 447 | line = line_no; |
c906108c SS |
448 | } |
449 | else | |
6ba8e26f | 450 | line = line_no; |
c906108c | 451 | |
6ba8e26f | 452 | element_no = tui_first_reg_element_no_inline (line); |
9a2b4c1b | 453 | if (element_no |
238eb706 | 454 | < TUI_DATA_WIN->regs_content_count) |
6ba8e26f | 455 | tui_display_reg_element_at_line (element_no, line); |
c906108c SS |
456 | else |
457 | line = (-1); | |
458 | ||
459 | return line; | |
460 | } | |
461 | ||
1cc6d956 | 462 | return (-1); /* Nothing was displayed. */ |
55fb0713 | 463 | } |
c906108c SS |
464 | |
465 | ||
55fb0713 AC |
466 | /* This function check all displayed registers for changes in values, |
467 | given a particular frame. If the values have changed, they are | |
468 | updated with the new value and highlighted. */ | |
c906108c | 469 | void |
55fb0713 | 470 | tui_check_register_values (struct frame_info *frame) |
c906108c | 471 | { |
e5908723 MS |
472 | if (TUI_DATA_WIN != NULL |
473 | && TUI_DATA_WIN->generic.is_visible) | |
c906108c | 474 | { |
238eb706 TT |
475 | if (TUI_DATA_WIN->regs_content_count <= 0 |
476 | && TUI_DATA_WIN->display_regs) | |
477 | tui_show_registers (TUI_DATA_WIN->current_group); | |
c906108c SS |
478 | else |
479 | { | |
0043e6a5 | 480 | int i; |
c906108c | 481 | |
238eb706 | 482 | for (i = 0; (i < TUI_DATA_WIN->regs_content_count); i++) |
c906108c | 483 | { |
10f59415 SC |
484 | struct tui_data_element *data; |
485 | struct tui_gen_win_info *data_item_win_ptr; | |
6ba8e26f | 486 | int was_hilighted; |
c906108c | 487 | |
dc2c33e4 | 488 | data_item_win_ptr = TUI_DATA_WIN->regs_content[i]-> |
10f59415 | 489 | which_element.data_window; |
63ed8182 | 490 | data = &data_item_win_ptr->content[0]->which_element.data; |
10f59415 SC |
491 | was_hilighted = data->highlight; |
492 | ||
5eccfcc2 | 493 | tui_get_register (frame, data, |
10f59415 SC |
494 | data->item_no, &data->highlight); |
495 | ||
496 | if (data->highlight || was_hilighted) | |
c906108c | 497 | { |
10f59415 | 498 | tui_display_register (data, data_item_win_ptr); |
c906108c SS |
499 | } |
500 | } | |
501 | } | |
502 | } | |
55fb0713 | 503 | } |
c906108c | 504 | |
1cc6d956 MS |
505 | /* Display a register in a window. If hilite is TRUE, then the value |
506 | will be displayed in reverse video. */ | |
10f59415 SC |
507 | static void |
508 | tui_display_register (struct tui_data_element *data, | |
509 | struct tui_gen_win_info *win_info) | |
510 | { | |
cafb3438 | 511 | if (win_info->handle != NULL) |
10f59415 SC |
512 | { |
513 | int i; | |
c906108c | 514 | |
10f59415 | 515 | if (data->highlight) |
cae3f17b JB |
516 | /* We ignore the return value, casting it to void in order to avoid |
517 | a compiler warning. The warning itself was introduced by a patch | |
518 | to ncurses 5.7 dated 2009-08-29, changing this macro to expand | |
519 | to code that causes the compiler to generate an unused-value | |
520 | warning. */ | |
ae3bccd4 | 521 | (void) wstandout (win_info->handle); |
10f59415 SC |
522 | |
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); | |
527 | if (data->content) | |
528 | waddstr (win_info->handle, data->content); | |
529 | ||
530 | if (data->highlight) | |
cae3f17b JB |
531 | /* We ignore the return value, casting it to void in order to avoid |
532 | a compiler warning. The warning itself was introduced by a patch | |
533 | to ncurses 5.7 dated 2009-08-29, changing this macro to expand | |
534 | to code that causes the compiler to generate an unused-value | |
535 | warning. */ | |
ae3bccd4 | 536 | (void) wstandend (win_info->handle); |
10f59415 SC |
537 | tui_refresh_win (win_info); |
538 | } | |
539 | } | |
540 | ||
51f0e40d AB |
541 | /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap |
542 | around behaviour. Returns the next register group, or NULL if the | |
543 | register window is not currently being displayed. */ | |
544 | ||
545 | static struct reggroup * | |
546 | tui_reg_next (struct gdbarch *gdbarch) | |
c906108c | 547 | { |
51f0e40d | 548 | struct reggroup *group = NULL; |
e17c207e | 549 | |
b75c69bb | 550 | if (TUI_DATA_WIN != NULL) |
10f59415 | 551 | { |
238eb706 | 552 | group = TUI_DATA_WIN->current_group; |
e17c207e | 553 | group = reggroup_next (gdbarch, group); |
b75c69bb AB |
554 | if (group == NULL) |
555 | group = reggroup_next (gdbarch, NULL); | |
10f59415 | 556 | } |
51f0e40d | 557 | return group; |
10f59415 SC |
558 | } |
559 | ||
51f0e40d AB |
560 | /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap |
561 | around behaviour. Returns the previous register group, or NULL if the | |
562 | register window is not currently being displayed. */ | |
55b40027 | 563 | |
51f0e40d AB |
564 | static struct reggroup * |
565 | tui_reg_prev (struct gdbarch *gdbarch) | |
55b40027 | 566 | { |
51f0e40d | 567 | struct reggroup *group = NULL; |
55b40027 AB |
568 | |
569 | if (TUI_DATA_WIN != NULL) | |
570 | { | |
238eb706 | 571 | group = TUI_DATA_WIN->current_group; |
55b40027 AB |
572 | group = reggroup_prev (gdbarch, group); |
573 | if (group == NULL) | |
574 | group = reggroup_prev (gdbarch, NULL); | |
55b40027 | 575 | } |
51f0e40d | 576 | return group; |
55b40027 AB |
577 | } |
578 | ||
51f0e40d AB |
579 | /* Implement the 'tui reg' command. Changes the register group displayed |
580 | in the tui register window. Displays the tui register window if it is | |
581 | not already on display. */ | |
c906108c | 582 | |
10f59415 | 583 | static void |
e2d8ae16 | 584 | tui_reg_command (const char *args, int from_tty) |
10f59415 | 585 | { |
51f0e40d | 586 | struct gdbarch *gdbarch = get_current_arch (); |
c906108c | 587 | |
51f0e40d AB |
588 | if (args != NULL) |
589 | { | |
590 | struct reggroup *group, *match = NULL; | |
591 | size_t len = strlen (args); | |
592 | ||
593 | /* Make sure the curses mode is enabled. */ | |
594 | tui_enable (); | |
595 | ||
596 | /* Make sure the register window is visible. If not, select an | |
597 | appropriate layout. We need to do this before trying to run the | |
598 | 'next' or 'prev' commands. */ | |
599 | if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible) | |
600 | tui_set_layout_by_name (DATA_NAME); | |
601 | ||
602 | if (strncmp (args, "next", len) == 0) | |
603 | match = tui_reg_next (gdbarch); | |
604 | else if (strncmp (args, "prev", len) == 0) | |
605 | match = tui_reg_prev (gdbarch); | |
606 | ||
607 | /* This loop matches on the initial part of a register group | |
608 | name. If this initial part in ARGS matches only one register | |
609 | group then the switch is made. */ | |
610 | for (group = reggroup_next (gdbarch, NULL); | |
611 | group != NULL; | |
612 | group = reggroup_next (gdbarch, group)) | |
613 | { | |
614 | if (strncmp (reggroup_name (group), args, len) == 0) | |
615 | { | |
616 | if (match != NULL) | |
617 | error (_("ambiguous register group name '%s'"), args); | |
618 | match = group; | |
619 | } | |
620 | } | |
621 | ||
622 | if (match == NULL) | |
623 | error (_("unknown register group '%s'"), args); | |
624 | ||
625 | tui_show_registers (match); | |
626 | } | |
627 | else | |
628 | { | |
629 | struct reggroup *group; | |
630 | int first; | |
631 | ||
632 | printf_unfiltered (_("\"tui reg\" must be followed by the name of " | |
633 | "either a register group,\nor one of 'next' " | |
634 | "or 'prev'. Known register groups are:\n")); | |
635 | ||
636 | for (first = 1, group = reggroup_next (gdbarch, NULL); | |
637 | group != NULL; | |
638 | first = 0, group = reggroup_next (gdbarch, group)) | |
639 | { | |
640 | if (!first) | |
641 | printf_unfiltered (", "); | |
642 | printf_unfiltered ("%s", reggroup_name (group)); | |
643 | } | |
644 | ||
645 | printf_unfiltered ("\n"); | |
646 | } | |
10f59415 SC |
647 | } |
648 | ||
51f0e40d AB |
649 | /* Complete names of register groups, and add the special "prev" and "next" |
650 | names. */ | |
c906108c | 651 | |
eb3ff9a5 | 652 | static void |
51f0e40d | 653 | tui_reggroup_completer (struct cmd_list_element *ignore, |
eb3ff9a5 | 654 | completion_tracker &tracker, |
51f0e40d | 655 | const char *text, const char *word) |
10f59415 | 656 | { |
51f0e40d AB |
657 | static const char *extra[] = { "next", "prev", NULL }; |
658 | size_t len = strlen (word); | |
659 | const char **tmp; | |
660 | ||
eb3ff9a5 | 661 | reggroup_completer (ignore, tracker, text, word); |
51f0e40d | 662 | |
eb3ff9a5 | 663 | /* XXXX use complete_on_enum instead? */ |
51f0e40d AB |
664 | for (tmp = extra; *tmp != NULL; ++tmp) |
665 | { | |
666 | if (strncmp (word, *tmp, len) == 0) | |
b02f78f9 | 667 | tracker.add_completion (make_unique_xstrdup (*tmp)); |
51f0e40d | 668 | } |
10f59415 | 669 | } |
c906108c SS |
670 | |
671 | void | |
6ba8e26f | 672 | _initialize_tui_regs (void) |
c906108c | 673 | { |
51f0e40d | 674 | struct cmd_list_element **tuicmd, *cmd; |
10f59415 SC |
675 | |
676 | tuicmd = tui_get_cmd_list (); | |
677 | ||
51f0e40d AB |
678 | cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\ |
679 | TUI command to control the register window."), tuicmd); | |
680 | set_cmd_completer (cmd, tui_reggroup_completer); | |
41783295 | 681 | } |
c906108c SS |
682 | |
683 | ||
684 | /***************************************** | |
685 | ** STATIC LOCAL FUNCTIONS ** | |
686 | ******************************************/ | |
687 | ||
6eed1678 PA |
688 | /* Get the register from the frame and return a printable |
689 | representation of it. */ | |
690 | ||
691 | static char * | |
692 | tui_register_format (struct frame_info *frame, int regnum) | |
c906108c | 693 | { |
5eccfcc2 | 694 | struct gdbarch *gdbarch = get_frame_arch (frame); |
d20c1c3f | 695 | |
d7e74731 PA |
696 | string_file stream; |
697 | ||
31b68d4a TT |
698 | scoped_restore save_pagination |
699 | = make_scoped_restore (&pagination_enabled, 0); | |
700 | scoped_restore save_stdout | |
701 | = make_scoped_restore (&gdb_stdout, &stream); | |
702 | ||
d7e74731 | 703 | gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1); |
c46cc7df SC |
704 | |
705 | /* Remove the possible \n. */ | |
d7e74731 PA |
706 | std::string &str = stream.string (); |
707 | if (!str.empty () && str.back () == '\n') | |
708 | str.resize (str.size () - 1); | |
c46cc7df | 709 | |
312809f8 | 710 | /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */ |
31b68d4a | 711 | return tui_expand_tabs (str.c_str (), 0); |
c46cc7df | 712 | } |
c906108c | 713 | |
1cc6d956 MS |
714 | /* Get the register value from the given frame and format it for the |
715 | display. When changep is set, check if the new register value has | |
716 | changed with respect to the previous call. */ | |
22940a24 | 717 | static enum tui_status |
5eccfcc2 | 718 | tui_get_register (struct frame_info *frame, |
08ef48c5 MS |
719 | struct tui_data_element *data, |
720 | int regnum, int *changedp) | |
c906108c | 721 | { |
22940a24 | 722 | enum tui_status ret = TUI_FAILURE; |
c906108c | 723 | |
10f59415 SC |
724 | if (changedp) |
725 | *changedp = FALSE; | |
c906108c SS |
726 | if (target_has_registers) |
727 | { | |
6eed1678 | 728 | char *prev_content = data->content; |
10f59415 | 729 | |
6eed1678 | 730 | data->content = tui_register_format (frame, regnum); |
9c5ea4d9 | 731 | |
6eed1678 PA |
732 | if (changedp != NULL |
733 | && strcmp (prev_content, data->content) != 0) | |
734 | *changedp = 1; | |
d20c1c3f | 735 | |
6eed1678 | 736 | xfree (prev_content); |
9c5ea4d9 UW |
737 | |
738 | ret = TUI_SUCCESS; | |
c906108c | 739 | } |
c906108c | 740 | return ret; |
6ba8e26f | 741 | } |