1130803Smarcel/* TUI display registers in window. 2130803Smarcel 3130803Smarcel Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software 4130803Smarcel Foundation, Inc. 5130803Smarcel 6130803Smarcel Contributed by Hewlett-Packard Company. 7130803Smarcel 8130803Smarcel This file is part of GDB. 9130803Smarcel 10130803Smarcel This program is free software; you can redistribute it and/or modify 11130803Smarcel it under the terms of the GNU General Public License as published by 12130803Smarcel the Free Software Foundation; either version 2 of the License, or 13130803Smarcel (at your option) any later version. 14130803Smarcel 15130803Smarcel This program is distributed in the hope that it will be useful, 16130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 17130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18130803Smarcel GNU General Public License for more details. 19130803Smarcel 20130803Smarcel You should have received a copy of the GNU General Public License 21130803Smarcel along with this program; if not, write to the Free Software 22130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 23130803Smarcel Boston, MA 02111-1307, USA. */ 24130803Smarcel 25130803Smarcel#include "defs.h" 26130803Smarcel#include "tui/tui.h" 27130803Smarcel#include "tui/tui-data.h" 28130803Smarcel#include "symtab.h" 29130803Smarcel#include "gdbtypes.h" 30130803Smarcel#include "gdbcmd.h" 31130803Smarcel#include "frame.h" 32130803Smarcel#include "regcache.h" 33130803Smarcel#include "inferior.h" 34130803Smarcel#include "target.h" 35130803Smarcel#include "gdb_string.h" 36130803Smarcel#include "tui/tui-layout.h" 37130803Smarcel#include "tui/tui-win.h" 38130803Smarcel#include "tui/tui-windata.h" 39130803Smarcel#include "tui/tui-wingeneral.h" 40130803Smarcel#include "tui/tui-file.h" 41130803Smarcel#include "reggroups.h" 42130803Smarcel 43130803Smarcel#include "gdb_curses.h" 44130803Smarcel 45130803Smarcel 46130803Smarcel/***************************************** 47130803Smarcel** STATIC LOCAL FUNCTIONS FORWARD DECLS ** 48130803Smarcel******************************************/ 49130803Smarcelstatic void 50130803Smarceltui_display_register (struct tui_data_element *data, 51130803Smarcel struct tui_gen_win_info *win_info); 52130803Smarcel 53130803Smarcelstatic enum tui_status 54130803Smarceltui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group, 55130803Smarcel struct frame_info *frame, int refresh_values_only); 56130803Smarcel 57130803Smarcelstatic enum tui_status 58130803Smarceltui_get_register (struct gdbarch *gdbarch, struct frame_info *frame, 59130803Smarcel struct tui_data_element *data, int regnum, int *changedp); 60130803Smarcelstatic void tui_register_format 61130803Smarcel (struct gdbarch *, struct frame_info *, struct tui_data_element*, int); 62130803Smarcelstatic void tui_scroll_regs_forward_command (char *, int); 63130803Smarcelstatic void tui_scroll_regs_backward_command (char *, int); 64130803Smarcel 65130803Smarcel 66130803Smarcel 67130803Smarcel/***************************************** 68130803Smarcel** PUBLIC FUNCTIONS ** 69130803Smarcel******************************************/ 70130803Smarcel 71130803Smarcel/* Answer the number of the last line in the regs display. If there 72130803Smarcel are no registers (-1) is returned. */ 73130803Smarcelint 74130803Smarceltui_last_regs_line_no (void) 75130803Smarcel{ 76130803Smarcel int num_lines = (-1); 77130803Smarcel 78130803Smarcel if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 79130803Smarcel { 80130803Smarcel num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count / 81130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_column_count); 82130803Smarcel if (TUI_DATA_WIN->detail.data_display_info.regs_content_count % 83130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_column_count) 84130803Smarcel num_lines++; 85130803Smarcel } 86130803Smarcel return num_lines; 87130803Smarcel} 88130803Smarcel 89130803Smarcel 90130803Smarcel/* Answer the line number that the register element at element_no is 91130803Smarcel on. If element_no is greater than the number of register elements 92130803Smarcel there are, -1 is returned. */ 93130803Smarcelint 94130803Smarceltui_line_from_reg_element_no (int element_no) 95130803Smarcel{ 96130803Smarcel if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) 97130803Smarcel { 98130803Smarcel int i, line = (-1); 99130803Smarcel 100130803Smarcel i = 1; 101130803Smarcel while (line == (-1)) 102130803Smarcel { 103130803Smarcel if (element_no < 104130803Smarcel (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i)) 105130803Smarcel line = i - 1; 106130803Smarcel else 107130803Smarcel i++; 108130803Smarcel } 109130803Smarcel 110130803Smarcel return line; 111130803Smarcel } 112130803Smarcel else 113130803Smarcel return (-1); 114130803Smarcel} 115130803Smarcel 116130803Smarcel 117130803Smarcel/* Answer the index of the first element in line_no. If line_no is past 118130803Smarcel the register area (-1) is returned. */ 119130803Smarcelint 120130803Smarceltui_first_reg_element_no_inline (int line_no) 121130803Smarcel{ 122130803Smarcel if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) 123130803Smarcel <= TUI_DATA_WIN->detail.data_display_info.regs_content_count) 124130803Smarcel return ((line_no + 1) * 125130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 126130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_column_count; 127130803Smarcel else 128130803Smarcel return (-1); 129130803Smarcel} 130130803Smarcel 131130803Smarcel 132130803Smarcel/* Answer the index of the last element in line_no. If line_no is 133130803Smarcel past the register area (-1) is returned. */ 134130803Smarcelint 135130803Smarceltui_last_reg_element_no_in_line (int line_no) 136130803Smarcel{ 137130803Smarcel if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <= 138130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_content_count) 139130803Smarcel return ((line_no + 1) * 140130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1; 141130803Smarcel else 142130803Smarcel return (-1); 143130803Smarcel} 144130803Smarcel 145130803Smarcel/* Show the registers of the given group in the data window 146130803Smarcel and refresh the window. */ 147130803Smarcelvoid 148130803Smarceltui_show_registers (struct reggroup *group) 149130803Smarcel{ 150130803Smarcel enum tui_status ret = TUI_FAILURE; 151130803Smarcel struct tui_data_info *display_info; 152130803Smarcel 153130803Smarcel /* Make sure the curses mode is enabled. */ 154130803Smarcel tui_enable (); 155130803Smarcel 156130803Smarcel /* Make sure the register window is visible. If not, select an 157130803Smarcel appropriate layout. */ 158130803Smarcel if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible) 159130803Smarcel tui_set_layout_for_display_command (DATA_NAME); 160130803Smarcel 161130803Smarcel display_info = &TUI_DATA_WIN->detail.data_display_info; 162130803Smarcel if (group == 0) 163130803Smarcel group = general_reggroup; 164130803Smarcel 165130803Smarcel /* Say that registers should be displayed, even if there is a problem. */ 166130803Smarcel display_info->display_regs = TRUE; 167130803Smarcel 168130803Smarcel if (target_has_registers && target_has_stack && target_has_memory) 169130803Smarcel { 170130803Smarcel ret = tui_show_register_group (current_gdbarch, group, 171130803Smarcel get_current_frame (), 172130803Smarcel group == display_info->current_group); 173130803Smarcel } 174130803Smarcel if (ret == TUI_FAILURE) 175130803Smarcel { 176130803Smarcel display_info->current_group = 0; 177130803Smarcel tui_erase_data_content (NO_REGS_STRING); 178130803Smarcel } 179130803Smarcel else 180130803Smarcel { 181130803Smarcel int i; 182130803Smarcel 183130803Smarcel /* Clear all notation of changed values */ 184130803Smarcel for (i = 0; i < display_info->regs_content_count; i++) 185130803Smarcel { 186130803Smarcel struct tui_gen_win_info *data_item_win; 187130803Smarcel struct tui_win_element *win; 188130803Smarcel 189130803Smarcel data_item_win = &display_info->regs_content[i] 190130803Smarcel ->which_element.data_window; 191130803Smarcel win = (struct tui_win_element *) data_item_win->content[0]; 192130803Smarcel win->which_element.data.highlight = FALSE; 193130803Smarcel } 194130803Smarcel display_info->current_group = group; 195130803Smarcel tui_display_all_data (); 196130803Smarcel } 197130803Smarcel} 198130803Smarcel 199130803Smarcel 200130803Smarcel/* Set the data window to display the registers of the register group 201130803Smarcel using the given frame. Values are refreshed only when refresh_values_only 202130803Smarcel is TRUE. */ 203130803Smarcel 204130803Smarcelstatic enum tui_status 205130803Smarceltui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group, 206130803Smarcel struct frame_info *frame, int refresh_values_only) 207130803Smarcel{ 208130803Smarcel enum tui_status ret = TUI_FAILURE; 209130803Smarcel int nr_regs; 210130803Smarcel int allocated_here = FALSE; 211130803Smarcel int regnum, pos; 212130803Smarcel char title[80]; 213130803Smarcel struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; 214130803Smarcel 215130803Smarcel /* Make a new title showing which group we display. */ 216130803Smarcel snprintf (title, sizeof (title) - 1, "Register group: %s", 217130803Smarcel reggroup_name (group)); 218130803Smarcel xfree (TUI_DATA_WIN->generic.title); 219130803Smarcel TUI_DATA_WIN->generic.title = xstrdup (title); 220130803Smarcel 221130803Smarcel /* See how many registers must be displayed. */ 222130803Smarcel nr_regs = 0; 223130803Smarcel for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) 224130803Smarcel { 225130803Smarcel /* Must be in the group and have a name. */ 226130803Smarcel if (gdbarch_register_reggroup_p (gdbarch, regnum, group) 227130803Smarcel && gdbarch_register_name (gdbarch, regnum) != 0) 228130803Smarcel nr_regs++; 229130803Smarcel } 230130803Smarcel 231130803Smarcel if (display_info->regs_content_count > 0 && !refresh_values_only) 232130803Smarcel { 233130803Smarcel tui_free_data_content (display_info->regs_content, 234130803Smarcel display_info->regs_content_count); 235130803Smarcel display_info->regs_content_count = 0; 236130803Smarcel } 237130803Smarcel 238130803Smarcel if (display_info->regs_content_count <= 0) 239130803Smarcel { 240130803Smarcel display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN); 241130803Smarcel allocated_here = TRUE; 242130803Smarcel refresh_values_only = FALSE; 243130803Smarcel } 244130803Smarcel 245130803Smarcel if (display_info->regs_content != (tui_win_content) NULL) 246130803Smarcel { 247130803Smarcel if (!refresh_values_only || allocated_here) 248130803Smarcel { 249130803Smarcel TUI_DATA_WIN->generic.content = (void*) NULL; 250130803Smarcel TUI_DATA_WIN->generic.content_size = 0; 251130803Smarcel tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs); 252130803Smarcel display_info->regs_content 253130803Smarcel = (tui_win_content) TUI_DATA_WIN->generic.content; 254130803Smarcel display_info->regs_content_count = nr_regs; 255130803Smarcel } 256130803Smarcel 257130803Smarcel /* Now set the register names and values */ 258130803Smarcel pos = 0; 259130803Smarcel for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) 260130803Smarcel { 261130803Smarcel struct tui_gen_win_info *data_item_win; 262130803Smarcel struct tui_data_element *data; 263130803Smarcel const char *name; 264130803Smarcel 265130803Smarcel if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) 266130803Smarcel continue; 267130803Smarcel 268130803Smarcel name = gdbarch_register_name (gdbarch, regnum); 269130803Smarcel if (name == 0) 270130803Smarcel continue; 271130803Smarcel 272130803Smarcel data_item_win = 273130803Smarcel &display_info->regs_content[pos]->which_element.data_window; 274130803Smarcel data = 275130803Smarcel &((struct tui_win_element *) data_item_win->content[0])->which_element.data; 276130803Smarcel if (data) 277130803Smarcel { 278130803Smarcel if (!refresh_values_only) 279130803Smarcel { 280130803Smarcel data->item_no = regnum; 281130803Smarcel data->name = name; 282130803Smarcel data->highlight = FALSE; 283130803Smarcel } 284130803Smarcel if (data->value == (void*) NULL) 285130803Smarcel data->value = (void*) xmalloc (MAX_REGISTER_SIZE); 286130803Smarcel 287130803Smarcel tui_get_register (gdbarch, frame, data, regnum, 0); 288130803Smarcel } 289130803Smarcel pos++; 290130803Smarcel } 291130803Smarcel 292130803Smarcel TUI_DATA_WIN->generic.content_size = 293130803Smarcel display_info->regs_content_count + display_info->data_content_count; 294130803Smarcel ret = TUI_SUCCESS; 295130803Smarcel } 296130803Smarcel 297130803Smarcel return ret; 298130803Smarcel} 299130803Smarcel 300130803Smarcel/* Function to display the registers in the content from 301130803Smarcel 'start_element_no' until the end of the register content or the end 302130803Smarcel of the display height. No checking for displaying past the end of 303130803Smarcel the registers is done here. */ 304130803Smarcelvoid 305130803Smarceltui_display_registers_from (int start_element_no) 306130803Smarcel{ 307130803Smarcel struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; 308130803Smarcel 309130803Smarcel if (display_info->regs_content != (tui_win_content) NULL && 310130803Smarcel display_info->regs_content_count > 0) 311130803Smarcel { 312130803Smarcel int i = start_element_no; 313130803Smarcel int j, value_chars_wide, item_win_width, cur_y; 314130803Smarcel 315130803Smarcel int max_len = 0; 316130803Smarcel for (i = 0; i < display_info->regs_content_count; i++) 317130803Smarcel { 318130803Smarcel struct tui_data_element *data; 319130803Smarcel struct tui_gen_win_info *data_item_win; 320130803Smarcel char *p; 321130803Smarcel int len; 322130803Smarcel 323130803Smarcel data_item_win = &display_info->regs_content[i]->which_element.data_window; 324130803Smarcel data = &((struct tui_win_element *) 325130803Smarcel data_item_win->content[0])->which_element.data; 326130803Smarcel len = 0; 327130803Smarcel p = data->content; 328130803Smarcel if (p != 0) 329130803Smarcel while (*p) 330130803Smarcel { 331130803Smarcel if (*p++ == '\t') 332130803Smarcel len = 8 * ((len / 8) + 1); 333130803Smarcel else 334130803Smarcel len++; 335130803Smarcel } 336130803Smarcel 337130803Smarcel if (len > max_len) 338130803Smarcel max_len = len; 339130803Smarcel } 340130803Smarcel item_win_width = max_len + 1; 341130803Smarcel i = start_element_no; 342130803Smarcel 343130803Smarcel display_info->regs_column_count = 344130803Smarcel (TUI_DATA_WIN->generic.width - 2) / item_win_width; 345130803Smarcel if (display_info->regs_column_count == 0) 346130803Smarcel display_info->regs_column_count = 1; 347130803Smarcel item_win_width = 348130803Smarcel (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count; 349130803Smarcel 350130803Smarcel /* 351130803Smarcel ** Now create each data "sub" window, and write the display into it. 352130803Smarcel */ 353130803Smarcel cur_y = 1; 354130803Smarcel while (i < display_info->regs_content_count && 355130803Smarcel cur_y <= TUI_DATA_WIN->generic.viewport_height) 356130803Smarcel { 357130803Smarcel for (j = 0; 358130803Smarcel (j < display_info->regs_column_count && 359130803Smarcel i < display_info->regs_content_count); j++) 360130803Smarcel { 361130803Smarcel struct tui_gen_win_info * data_item_win; 362130803Smarcel struct tui_data_element * data_element_ptr; 363130803Smarcel 364130803Smarcel /* create the window if necessary */ 365130803Smarcel data_item_win = &display_info->regs_content[i] 366130803Smarcel ->which_element.data_window; 367130803Smarcel data_element_ptr = &((struct tui_win_element *) 368130803Smarcel data_item_win->content[0])->which_element.data; 369130803Smarcel if (data_item_win->handle != (WINDOW*) NULL 370130803Smarcel && (data_item_win->height != 1 371130803Smarcel || data_item_win->width != item_win_width 372130803Smarcel || data_item_win->origin.x != (item_win_width * j) + 1 373130803Smarcel || data_item_win->origin.y != cur_y)) 374130803Smarcel { 375130803Smarcel tui_delete_win (data_item_win->handle); 376130803Smarcel data_item_win->handle = 0; 377130803Smarcel } 378130803Smarcel 379130803Smarcel if (data_item_win->handle == (WINDOW *) NULL) 380130803Smarcel { 381130803Smarcel data_item_win->height = 1; 382130803Smarcel data_item_win->width = item_win_width; 383130803Smarcel data_item_win->origin.x = (item_win_width * j) + 1; 384130803Smarcel data_item_win->origin.y = cur_y; 385130803Smarcel tui_make_window (data_item_win, DONT_BOX_WINDOW); 386130803Smarcel scrollok (data_item_win->handle, FALSE); 387130803Smarcel } 388130803Smarcel touchwin (data_item_win->handle); 389130803Smarcel 390130803Smarcel /* Get the printable representation of the register 391130803Smarcel and display it. */ 392130803Smarcel tui_display_register (data_element_ptr, data_item_win); 393130803Smarcel i++; /* next register */ 394130803Smarcel } 395130803Smarcel cur_y++; /* next row; */ 396130803Smarcel } 397130803Smarcel } 398130803Smarcel} 399130803Smarcel 400130803Smarcel 401130803Smarcel/* Function to display the registers in the content from 402130803Smarcel 'start_element_no' on 'start_line_no' until the end of the register 403130803Smarcel content or the end of the display height. This function checks 404130803Smarcel that we won't display off the end of the register display. */ 405130803Smarcelvoid 406130803Smarceltui_display_reg_element_at_line (int start_element_no, int start_line_no) 407130803Smarcel{ 408130803Smarcel if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL && 409130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 410130803Smarcel { 411130803Smarcel int element_no = start_element_no; 412130803Smarcel 413130803Smarcel if (start_element_no != 0 && start_line_no != 0) 414130803Smarcel { 415130803Smarcel int last_line_no, first_line_on_last_page; 416130803Smarcel 417130803Smarcel last_line_no = tui_last_regs_line_no (); 418130803Smarcel first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2); 419130803Smarcel if (first_line_on_last_page < 0) 420130803Smarcel first_line_on_last_page = 0; 421130803Smarcel /* 422130803Smarcel ** If there is no other data displayed except registers, 423130803Smarcel ** and the element_no causes us to scroll past the end of the 424130803Smarcel ** registers, adjust what element to really start the display at. 425130803Smarcel */ 426130803Smarcel if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 && 427130803Smarcel start_line_no > first_line_on_last_page) 428130803Smarcel element_no = tui_first_reg_element_no_inline (first_line_on_last_page); 429130803Smarcel } 430130803Smarcel tui_display_registers_from (element_no); 431130803Smarcel } 432130803Smarcel} 433130803Smarcel 434130803Smarcel 435130803Smarcel 436130803Smarcel/* Function to display the registers starting at line line_no in the 437130803Smarcel data window. Answers the line number that the display actually 438130803Smarcel started from. If nothing is displayed (-1) is returned. */ 439130803Smarcelint 440130803Smarceltui_display_registers_from_line (int line_no, int force_display) 441130803Smarcel{ 442130803Smarcel if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 443130803Smarcel { 444130803Smarcel int line, element_no; 445130803Smarcel 446130803Smarcel if (line_no < 0) 447130803Smarcel line = 0; 448130803Smarcel else if (force_display) 449130803Smarcel { /* 450130803Smarcel ** If we must display regs (force_display is true), then make 451130803Smarcel ** sure that we don't display off the end of the registers. 452130803Smarcel */ 453130803Smarcel if (line_no >= tui_last_regs_line_no ()) 454130803Smarcel { 455130803Smarcel if ((line = tui_line_from_reg_element_no ( 456130803Smarcel TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0) 457130803Smarcel line = 0; 458130803Smarcel } 459130803Smarcel else 460130803Smarcel line = line_no; 461130803Smarcel } 462130803Smarcel else 463130803Smarcel line = line_no; 464130803Smarcel 465130803Smarcel element_no = tui_first_reg_element_no_inline (line); 466130803Smarcel if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) 467130803Smarcel tui_display_reg_element_at_line (element_no, line); 468130803Smarcel else 469130803Smarcel line = (-1); 470130803Smarcel 471130803Smarcel return line; 472130803Smarcel } 473130803Smarcel 474130803Smarcel return (-1); /* nothing was displayed */ 475130803Smarcel} 476130803Smarcel 477130803Smarcel 478130803Smarcel/* This function check all displayed registers for changes in values, 479130803Smarcel given a particular frame. If the values have changed, they are 480130803Smarcel updated with the new value and highlighted. */ 481130803Smarcelvoid 482130803Smarceltui_check_register_values (struct frame_info *frame) 483130803Smarcel{ 484130803Smarcel if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible) 485130803Smarcel { 486130803Smarcel struct tui_data_info *display_info 487130803Smarcel = &TUI_DATA_WIN->detail.data_display_info; 488130803Smarcel 489130803Smarcel if (display_info->regs_content_count <= 0 && display_info->display_regs) 490130803Smarcel tui_show_registers (display_info->current_group); 491130803Smarcel else 492130803Smarcel { 493130803Smarcel int i, j; 494130803Smarcel 495130803Smarcel for (i = 0; (i < display_info->regs_content_count); i++) 496130803Smarcel { 497130803Smarcel struct tui_data_element *data; 498130803Smarcel struct tui_gen_win_info *data_item_win_ptr; 499130803Smarcel int was_hilighted; 500130803Smarcel 501130803Smarcel data_item_win_ptr = &display_info->regs_content[i]-> 502130803Smarcel which_element.data_window; 503130803Smarcel data = &((struct tui_win_element *) 504130803Smarcel data_item_win_ptr->content[0])->which_element.data; 505130803Smarcel was_hilighted = data->highlight; 506130803Smarcel 507130803Smarcel tui_get_register (current_gdbarch, frame, data, 508130803Smarcel data->item_no, &data->highlight); 509130803Smarcel 510130803Smarcel if (data->highlight || was_hilighted) 511130803Smarcel { 512130803Smarcel tui_display_register (data, data_item_win_ptr); 513130803Smarcel } 514130803Smarcel } 515130803Smarcel } 516130803Smarcel } 517130803Smarcel} 518130803Smarcel 519130803Smarcel/* Display a register in a window. If hilite is TRUE, 520130803Smarcel then the value will be displayed in reverse video */ 521130803Smarcelstatic void 522130803Smarceltui_display_register (struct tui_data_element *data, 523130803Smarcel struct tui_gen_win_info *win_info) 524130803Smarcel{ 525130803Smarcel if (win_info->handle != (WINDOW *) NULL) 526130803Smarcel { 527130803Smarcel int i; 528130803Smarcel 529130803Smarcel if (data->highlight) 530130803Smarcel wstandout (win_info->handle); 531130803Smarcel 532130803Smarcel wmove (win_info->handle, 0, 0); 533130803Smarcel for (i = 1; i < win_info->width; i++) 534130803Smarcel waddch (win_info->handle, ' '); 535130803Smarcel wmove (win_info->handle, 0, 0); 536130803Smarcel if (data->content) 537130803Smarcel waddstr (win_info->handle, data->content); 538130803Smarcel 539130803Smarcel if (data->highlight) 540130803Smarcel wstandend (win_info->handle); 541130803Smarcel tui_refresh_win (win_info); 542130803Smarcel } 543130803Smarcel} 544130803Smarcel 545130803Smarcelstatic void 546130803Smarceltui_reg_next_command (char *arg, int from_tty) 547130803Smarcel{ 548130803Smarcel if (TUI_DATA_WIN != 0) 549130803Smarcel { 550130803Smarcel struct reggroup *group 551130803Smarcel = TUI_DATA_WIN->detail.data_display_info.current_group; 552130803Smarcel 553130803Smarcel group = reggroup_next (current_gdbarch, group); 554130803Smarcel if (group == 0) 555130803Smarcel group = reggroup_next (current_gdbarch, 0); 556130803Smarcel 557130803Smarcel if (group) 558130803Smarcel tui_show_registers (group); 559130803Smarcel } 560130803Smarcel} 561130803Smarcel 562130803Smarcelstatic void 563130803Smarceltui_reg_float_command (char *arg, int from_tty) 564130803Smarcel{ 565130803Smarcel tui_show_registers (float_reggroup); 566130803Smarcel} 567130803Smarcel 568130803Smarcelstatic void 569130803Smarceltui_reg_general_command (char *arg, int from_tty) 570130803Smarcel{ 571130803Smarcel tui_show_registers (general_reggroup); 572130803Smarcel} 573130803Smarcel 574130803Smarcelstatic void 575130803Smarceltui_reg_system_command (char *arg, int from_tty) 576130803Smarcel{ 577130803Smarcel tui_show_registers (system_reggroup); 578130803Smarcel} 579130803Smarcel 580130803Smarcelstatic struct cmd_list_element *tuireglist; 581130803Smarcel 582130803Smarcelstatic void 583130803Smarceltui_reg_command (char *args, int from_tty) 584130803Smarcel{ 585130803Smarcel printf_unfiltered ("\"tui reg\" must be followed by the name of a " 586130803Smarcel "tui reg command.\n"); 587130803Smarcel help_list (tuireglist, "tui reg ", -1, gdb_stdout); 588130803Smarcel} 589130803Smarcel 590130803Smarcelvoid 591130803Smarcel_initialize_tui_regs (void) 592130803Smarcel{ 593130803Smarcel struct cmd_list_element **tuicmd; 594130803Smarcel 595130803Smarcel tuicmd = tui_get_cmd_list (); 596130803Smarcel 597130803Smarcel add_prefix_cmd ("reg", class_tui, tui_reg_command, 598130803Smarcel "TUI commands to control the register window.", 599130803Smarcel &tuireglist, "tui reg ", 0, 600130803Smarcel tuicmd); 601130803Smarcel 602130803Smarcel add_cmd ("float", class_tui, tui_reg_float_command, 603130803Smarcel "Display only floating point registers\n", 604130803Smarcel &tuireglist); 605130803Smarcel add_cmd ("general", class_tui, tui_reg_general_command, 606130803Smarcel "Display only general registers\n", 607130803Smarcel &tuireglist); 608130803Smarcel add_cmd ("system", class_tui, tui_reg_system_command, 609130803Smarcel "Display only system registers\n", 610130803Smarcel &tuireglist); 611130803Smarcel add_cmd ("next", class_tui, tui_reg_next_command, 612130803Smarcel "Display next register group\n", 613130803Smarcel &tuireglist); 614130803Smarcel 615130803Smarcel if (xdb_commands) 616130803Smarcel { 617130803Smarcel add_com ("fr", class_tui, tui_reg_float_command, 618130803Smarcel "Display only floating point registers\n"); 619130803Smarcel add_com ("gr", class_tui, tui_reg_general_command, 620130803Smarcel "Display only general registers\n"); 621130803Smarcel add_com ("sr", class_tui, tui_reg_system_command, 622130803Smarcel "Display only special registers\n"); 623130803Smarcel add_com ("+r", class_tui, tui_scroll_regs_forward_command, 624130803Smarcel "Scroll the registers window forward\n"); 625130803Smarcel add_com ("-r", class_tui, tui_scroll_regs_backward_command, 626130803Smarcel "Scroll the register window backward\n"); 627130803Smarcel } 628130803Smarcel} 629130803Smarcel 630130803Smarcel 631130803Smarcel/***************************************** 632130803Smarcel** STATIC LOCAL FUNCTIONS ** 633130803Smarcel******************************************/ 634130803Smarcel 635130803Smarcelextern int pagination_enabled; 636130803Smarcel 637130803Smarcelstatic void 638130803Smarceltui_restore_gdbout (void *ui) 639130803Smarcel{ 640130803Smarcel ui_file_delete (gdb_stdout); 641130803Smarcel gdb_stdout = (struct ui_file*) ui; 642130803Smarcel pagination_enabled = 1; 643130803Smarcel} 644130803Smarcel 645130803Smarcel/* Get the register from the frame and make a printable representation 646130803Smarcel of it in the data element. */ 647130803Smarcelstatic void 648130803Smarceltui_register_format (struct gdbarch *gdbarch, struct frame_info *frame, 649130803Smarcel struct tui_data_element *data_element, int regnum) 650130803Smarcel{ 651130803Smarcel struct ui_file *stream; 652130803Smarcel struct ui_file *old_stdout; 653130803Smarcel const char *name; 654130803Smarcel struct cleanup *cleanups; 655130803Smarcel char *p, *s; 656130803Smarcel int pos; 657130803Smarcel struct type *type = gdbarch_register_type (gdbarch, regnum); 658130803Smarcel 659130803Smarcel name = gdbarch_register_name (gdbarch, regnum); 660130803Smarcel if (name == 0) 661130803Smarcel { 662130803Smarcel return; 663130803Smarcel } 664130803Smarcel 665130803Smarcel pagination_enabled = 0; 666130803Smarcel old_stdout = gdb_stdout; 667130803Smarcel stream = tui_sfileopen (256); 668130803Smarcel gdb_stdout = stream; 669130803Smarcel cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout); 670130803Smarcel if (TYPE_VECTOR (type) != 0 && 0) 671130803Smarcel { 672130803Smarcel char buf[MAX_REGISTER_SIZE]; 673130803Smarcel int len; 674130803Smarcel 675130803Smarcel len = register_size (current_gdbarch, regnum); 676130803Smarcel fprintf_filtered (stream, "%-14s ", name); 677130803Smarcel get_frame_register (frame, regnum, buf); 678130803Smarcel print_scalar_formatted (buf, type, 'f', len, stream); 679130803Smarcel } 680130803Smarcel else 681130803Smarcel { 682130803Smarcel gdbarch_print_registers_info (current_gdbarch, stream, 683130803Smarcel frame, regnum, 1); 684130803Smarcel } 685130803Smarcel 686130803Smarcel /* Save formatted output in the buffer. */ 687130803Smarcel p = tui_file_get_strbuf (stream); 688130803Smarcel 689130803Smarcel /* Remove the possible \n. */ 690130803Smarcel s = strrchr (p, '\n'); 691130803Smarcel if (s && s[1] == 0) 692130803Smarcel *s = 0; 693130803Smarcel 694130803Smarcel xfree (data_element->content); 695130803Smarcel data_element->content = xstrdup (p); 696130803Smarcel do_cleanups (cleanups); 697130803Smarcel} 698130803Smarcel 699130803Smarcel/* Get the register value from the given frame and format it for 700130803Smarcel the display. When changep is set, check if the new register value 701130803Smarcel has changed with respect to the previous call. */ 702130803Smarcelstatic enum tui_status 703130803Smarceltui_get_register (struct gdbarch *gdbarch, struct frame_info *frame, 704130803Smarcel struct tui_data_element *data, int regnum, int *changedp) 705130803Smarcel{ 706130803Smarcel enum tui_status ret = TUI_FAILURE; 707130803Smarcel 708130803Smarcel if (changedp) 709130803Smarcel *changedp = FALSE; 710130803Smarcel if (target_has_registers) 711130803Smarcel { 712130803Smarcel char buf[MAX_REGISTER_SIZE]; 713130803Smarcel 714130803Smarcel get_frame_register (frame, regnum, buf); 715130803Smarcel /* NOTE: cagney/2003-03-13: This is bogus. It is refering to 716130803Smarcel the register cache and not the frame which could have pulled 717130803Smarcel the register value off the stack. */ 718130803Smarcel if (register_cached (regnum) >= 0) 719130803Smarcel { 720130803Smarcel if (changedp) 721130803Smarcel { 722130803Smarcel int size = register_size (gdbarch, regnum); 723130803Smarcel char *old = (char*) data->value; 724130803Smarcel int i; 725130803Smarcel 726130803Smarcel for (i = 0; i < size; i++) 727130803Smarcel if (buf[i] != old[i]) 728130803Smarcel { 729130803Smarcel *changedp = TRUE; 730130803Smarcel old[i] = buf[i]; 731130803Smarcel } 732130803Smarcel } 733130803Smarcel 734130803Smarcel /* Reformat the data content if the value changed. */ 735130803Smarcel if (changedp == 0 || *changedp == TRUE) 736130803Smarcel tui_register_format (gdbarch, frame, data, regnum); 737130803Smarcel ret = TUI_SUCCESS; 738130803Smarcel } 739130803Smarcel } 740130803Smarcel return ret; 741130803Smarcel} 742130803Smarcel 743130803Smarcelstatic void 744130803Smarceltui_scroll_regs_forward_command (char *arg, int from_tty) 745130803Smarcel{ 746130803Smarcel tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1); 747130803Smarcel} 748130803Smarcel 749130803Smarcel 750130803Smarcelstatic void 751130803Smarceltui_scroll_regs_backward_command (char *arg, int from_tty) 752130803Smarcel{ 753130803Smarcel tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1); 754130803Smarcel} 755