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