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