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