2004-02-07 Andrew Cagney <cagney@redhat.com>
[external/binutils.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
4    Foundation, Inc.
5
6    Contributed by Hewlett-Packard Company.
7
8    This file is part of GDB.
9
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
12    the Free Software Foundation; either version 2 of the License, or
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
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330,
23    Boston, MA 02111-1307, USA.  */
24
25 #include "defs.h"
26 #include "tui/tui.h"
27 #include "tui/tui-data.h"
28 #include "symtab.h"
29 #include "gdbtypes.h"
30 #include "gdbcmd.h"
31 #include "frame.h"
32 #include "regcache.h"
33 #include "inferior.h"
34 #include "target.h"
35 #include "gdb_string.h"
36 #include "tui/tui-layout.h"
37 #include "tui/tui-win.h"
38 #include "tui/tui-windata.h"
39 #include "tui/tui-wingeneral.h"
40 #include "tui/tui-file.h"
41
42 #ifdef HAVE_NCURSES_H       
43 #include <ncurses.h>
44 #else
45 #ifdef HAVE_CURSES_H
46 #include <curses.h>
47 #endif
48 #endif
49
50 /*****************************************
51 ** LOCAL DEFINITIONS                    **
52 ******************************************/
53 #define DOUBLE_FLOAT_LABEL_WIDTH    6
54 #define DOUBLE_FLOAT_LABEL_FMT      "%6.6s: "
55 #define DOUBLE_FLOAT_VALUE_WIDTH    30  /*min of 16 but may be in sci notation */
56
57 #define SINGLE_FLOAT_LABEL_WIDTH    6
58 #define SINGLE_FLOAT_LABEL_FMT      "%6.6s: "
59 #define SINGLE_FLOAT_VALUE_WIDTH    25  /* min of 8 but may be in sci notation */
60
61 #define SINGLE_LABEL_WIDTH    16
62 #define SINGLE_LABEL_FMT      "%10.10s: "
63 #define SINGLE_VALUE_WIDTH    20 /* minimum of 8 but may be in sci notation */
64
65 /* In the code HP gave Cygnus, this was actually a function call to a
66    PA-specific function, which was supposed to determine whether the
67    target was a 64-bit or 32-bit processor.  However, the 64-bit
68    support wasn't complete, so we didn't merge that in, so we leave
69    this here as a stub.  */
70 #define IS_64BIT 0
71
72 /*****************************************
73 ** STATIC DATA                          **
74 ******************************************/
75
76
77 /*****************************************
78 ** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
79 ******************************************/
80 static enum tui_status tui_set_regs_content
81   (int, int, struct frame_info *, enum tui_register_display_type, int);
82 static const char *tui_register_name (int);
83 static enum tui_status tui_get_register_raw_value (int, char *, struct frame_info *);
84 static void tui_set_register_element
85   (int, struct frame_info *, struct tui_data_element *, int);
86 static void tui_display_register (int, struct tui_gen_win_info *, enum precision_type);
87 static void tui_register_format
88   (char *, int, int, struct tui_data_element *, enum precision_type);
89 static enum tui_status tui_set_general_regs_content (int);
90 static enum tui_status tui_set_special_regs_content (int);
91 static enum tui_status tui_set_general_and_special_regs_content (int);
92 static enum tui_status tui_set_float_regs_content (enum tui_register_display_type, int);
93 static int tui_reg_value_has_changed
94   (struct tui_data_element *, struct frame_info *, char *);
95 static void tui_show_float_command (char *, int);
96 static void tui_show_general_command (char *, int);
97 static void tui_show_special_command (char *, int);
98 static void tui_v_show_registers_command_support (enum tui_register_display_type);
99 static void _tui_toggle_float_regs_command (char *, int);
100 static void tui_scroll_regs_forward_command (char *, int);
101 static void tui_scroll_regs_backward_command (char *, int);
102
103
104
105 /*****************************************
106 ** PUBLIC FUNCTIONS                     **
107 ******************************************/
108
109 /* Answer the number of the last line in the regs display.  If there
110    are no registers (-1) is returned.  */
111 int
112 tui_last_regs_line_no (void)
113 {
114   int num_lines = (-1);
115
116   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
117     {
118       num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
119                   TUI_DATA_WIN->detail.data_display_info.regs_column_count);
120       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
121           TUI_DATA_WIN->detail.data_display_info.regs_column_count)
122         num_lines++;
123     }
124   return num_lines;
125 }
126
127
128 /* Answer the line number that the register element at element_no is
129    on.  If element_no is greater than the number of register elements
130    there are, -1 is returned.  */
131 int
132 tui_line_from_reg_element_no (int element_no)
133 {
134   if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
135     {
136       int i, line = (-1);
137
138       i = 1;
139       while (line == (-1))
140         {
141           if (element_no <
142               (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
143             line = i - 1;
144           else
145             i++;
146         }
147
148       return line;
149     }
150   else
151     return (-1);
152 }
153
154
155 /* Answer the index of the first element in line_no.  If line_no is past
156    the register area (-1) is returned.  */
157 int
158 tui_first_reg_element_no_inline (int line_no)
159 {
160   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
161       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
162     return ((line_no + 1) *
163             TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
164       TUI_DATA_WIN->detail.data_display_info.regs_column_count;
165   else
166     return (-1);
167 }
168
169
170 /* Answer the index of the last element in line_no.  If line_no is
171    past the register area (-1) is returned.  */
172 int
173 tui_last_reg_element_no_in_line (int line_no)
174 {
175   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
176       TUI_DATA_WIN->detail.data_display_info.regs_content_count)
177     return ((line_no + 1) *
178             TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
179   else
180     return (-1);
181 }
182
183
184 /* Calculate the number of columns that should be used to display the
185    registers.  */
186 int
187 tui_calculate_regs_column_count (enum tui_register_display_type dpy_type)
188 {
189   int col_count, col_width;
190
191   if (IS_64BIT || dpy_type == TUI_DFLOAT_REGS)
192     col_width = DOUBLE_FLOAT_VALUE_WIDTH + DOUBLE_FLOAT_LABEL_WIDTH;
193   else
194     {
195       if (dpy_type == TUI_SFLOAT_REGS)
196         col_width = SINGLE_FLOAT_VALUE_WIDTH + SINGLE_FLOAT_LABEL_WIDTH;
197       else
198         col_width = SINGLE_VALUE_WIDTH + SINGLE_LABEL_WIDTH;
199     }
200   col_count = (TUI_DATA_WIN->generic.width - 2) / col_width;
201
202   return col_count;
203 }
204
205
206 /* Show the registers int the data window as indicated by dpy_type.  If
207    there is any other registers being displayed, then they are
208    cleared.  What registers are displayed is dependent upon dpy_type.  */
209 void
210 tui_show_registers (enum tui_register_display_type dpy_type)
211 {
212   enum tui_status ret = TUI_FAILURE;
213   int refresh_values_only = FALSE;
214
215   /* Say that registers should be displayed, even if there is a problem */
216   TUI_DATA_WIN->detail.data_display_info.display_regs = TRUE;
217
218   if (target_has_registers)
219     {
220       refresh_values_only =
221         (dpy_type == TUI_DATA_WIN->detail.data_display_info.regs_display_type);
222       switch (dpy_type)
223         {
224         case TUI_GENERAL_REGS:
225           ret = tui_set_general_regs_content (refresh_values_only);
226           break;
227         case TUI_SFLOAT_REGS:
228         case TUI_DFLOAT_REGS:
229           ret = tui_set_float_regs_content (dpy_type, refresh_values_only);
230           break;
231
232 /* could ifdef out */
233
234         case TUI_SPECIAL_REGS:
235           ret = tui_set_special_regs_content (refresh_values_only);
236           break;
237         case TUI_GENERAL_AND_SPECIAL_REGS:
238           ret = tui_set_general_and_special_regs_content (refresh_values_only);
239           break;
240
241 /* end of potential if def */
242
243         default:
244           break;
245         }
246     }
247   if (ret == TUI_FAILURE)
248     {
249       TUI_DATA_WIN->detail.data_display_info.regs_display_type = TUI_UNDEFINED_REGS;
250       tui_erase_data_content (NO_REGS_STRING);
251     }
252   else
253     {
254       int i;
255
256       /* Clear all notation of changed values */
257       for (i = 0; (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
258         {
259           struct tui_gen_win_info * data_item_win;
260
261           data_item_win = &TUI_DATA_WIN->detail.data_display_info.
262             regs_content[i]->which_element.data_window;
263           (&((struct tui_win_element *)
264              data_item_win->content[0])->which_element.data)->highlight = FALSE;
265         }
266       TUI_DATA_WIN->detail.data_display_info.regs_display_type = dpy_type;
267       tui_display_all_data ();
268     }
269   (tui_layout_def ())->regs_display_type = dpy_type;
270
271   return;
272 }
273
274
275 /* Function to display the registers in the content from
276    'start_element_no' until the end of the register content or the end
277    of the display height.  No checking for displaying past the end of
278    the registers is done here.  */
279 void
280 tui_display_registers_from (int start_element_no)
281 {
282   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
283       TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
284     {
285       int i = start_element_no;
286       int j, value_chars_wide, item_win_width, cur_y, label_width;
287       enum precision_type precision;
288
289       precision = (TUI_DATA_WIN->detail.data_display_info.regs_display_type
290                    == TUI_DFLOAT_REGS) ?
291         double_precision : unspecified_precision;
292       if (IS_64BIT ||
293           TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
294         {
295           value_chars_wide = DOUBLE_FLOAT_VALUE_WIDTH;
296           label_width = DOUBLE_FLOAT_LABEL_WIDTH;
297         }
298       else
299         {
300           if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
301               TUI_SFLOAT_REGS)
302             {
303               value_chars_wide = SINGLE_FLOAT_VALUE_WIDTH;
304               label_width = SINGLE_FLOAT_LABEL_WIDTH;
305             }
306           else
307             {
308               value_chars_wide = SINGLE_VALUE_WIDTH;
309               label_width = SINGLE_LABEL_WIDTH;
310             }
311         }
312       item_win_width = value_chars_wide + label_width;
313       /*
314          ** Now create each data "sub" window, and write the display into it.
315        */
316       cur_y = 1;
317       while (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count &&
318              cur_y <= TUI_DATA_WIN->generic.viewport_height)
319         {
320           for (j = 0;
321                (j < TUI_DATA_WIN->detail.data_display_info.regs_column_count &&
322                 i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); j++)
323             {
324               struct tui_gen_win_info * data_item_win;
325               struct tui_data_element * data_element_ptr;
326
327               /* create the window if necessary */
328               data_item_win = &TUI_DATA_WIN->detail.data_display_info.
329                 regs_content[i]->which_element.data_window;
330               data_element_ptr = &((struct tui_win_element *)
331                                  data_item_win->content[0])->which_element.data;
332               if (data_item_win->handle == (WINDOW *) NULL)
333                 {
334                   data_item_win->height = 1;
335                   data_item_win->width = (precision == double_precision) ?
336                     item_win_width + 2 : item_win_width + 1;
337                   data_item_win->origin.x = (item_win_width * j) + 1;
338                   data_item_win->origin.y = cur_y;
339                   tui_make_window (data_item_win, DONT_BOX_WINDOW);
340                   scrollok (data_item_win->handle, FALSE);
341                 }
342               touchwin (data_item_win->handle);
343
344               /*
345                  ** Get the printable representation of the register
346                  ** and display it
347                */
348               tui_display_register (
349                             data_element_ptr->item_no, data_item_win, precision);
350               i++;              /* next register */
351             }
352           cur_y++;              /* next row; */
353         }
354     }
355
356   return;
357 }
358
359
360 /* Function to display the registers in the content from
361    'start_element_no' on 'start_line_no' until the end of the register
362    content or the end of the display height.  This function checks
363    that we won't display off the end of the register display.  */
364 void
365 tui_display_reg_element_at_line (int start_element_no, int start_line_no)
366 {
367   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
368       TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
369     {
370       int element_no = start_element_no;
371
372       if (start_element_no != 0 && start_line_no != 0)
373         {
374           int last_line_no, first_line_on_last_page;
375
376           last_line_no = tui_last_regs_line_no ();
377           first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
378           if (first_line_on_last_page < 0)
379             first_line_on_last_page = 0;
380           /*
381              ** If there is no other data displayed except registers,
382              ** and the element_no causes us to scroll past the end of the
383              ** registers, adjust what element to really start the display at.
384            */
385           if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 &&
386               start_line_no > first_line_on_last_page)
387             element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
388         }
389       tui_display_registers_from (element_no);
390     }
391 }
392
393
394
395 /* Function to display the registers starting at line line_no in the
396    data window.  Answers the line number that the display actually
397    started from.  If nothing is displayed (-1) is returned.  */
398 int
399 tui_display_registers_from_line (int line_no, int force_display)
400 {
401   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
402     {
403       int line, element_no;
404
405       if (line_no < 0)
406         line = 0;
407       else if (force_display)
408         {                       /*
409                                    ** If we must display regs (force_display is true), then make
410                                    ** sure that we don't display off the end of the registers.
411                                  */
412           if (line_no >= tui_last_regs_line_no ())
413             {
414               if ((line = tui_line_from_reg_element_no (
415                  TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
416                 line = 0;
417             }
418           else
419             line = line_no;
420         }
421       else
422         line = line_no;
423
424       element_no = tui_first_reg_element_no_inline (line);
425       if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
426         tui_display_reg_element_at_line (element_no, line);
427       else
428         line = (-1);
429
430       return line;
431     }
432
433   return (-1);                  /* nothing was displayed */
434 }
435
436
437 /* This function check all displayed registers for changes in values,
438    given a particular frame.  If the values have changed, they are
439    updated with the new value and highlighted.  */
440 void
441 tui_check_register_values (struct frame_info *frame)
442 {
443   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
444     {
445       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0 &&
446           TUI_DATA_WIN->detail.data_display_info.display_regs)
447         tui_show_registers ((tui_layout_def ())->regs_display_type);
448       else
449         {
450           int i, j;
451           char raw_buf[MAX_REGISTER_SIZE];
452
453           for (i = 0;
454                (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
455             {
456               struct tui_data_element * data_element_ptr;
457               struct tui_gen_win_info * data_item_win_ptr;
458               int was_hilighted;
459
460               data_item_win_ptr = &TUI_DATA_WIN->detail.data_display_info.
461                 regs_content[i]->which_element.data_window;
462               data_element_ptr = &((struct tui_win_element *)
463                              data_item_win_ptr->content[0])->which_element.data;
464               was_hilighted = data_element_ptr->highlight;
465               data_element_ptr->highlight =
466                 tui_reg_value_has_changed (data_element_ptr, frame, &raw_buf[0]);
467               if (data_element_ptr->highlight)
468                 {
469                   int size;
470
471                   size = DEPRECATED_REGISTER_RAW_SIZE (data_element_ptr->item_no);
472                   for (j = 0; j < size; j++)
473                     ((char *) data_element_ptr->value)[j] = raw_buf[j];
474                   tui_display_register (
475                                         data_element_ptr->item_no,
476                                         data_item_win_ptr,
477                         ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
478                           TUI_DFLOAT_REGS) ?
479                          double_precision : unspecified_precision));
480                 }
481               else if (was_hilighted)
482                 {
483                   data_element_ptr->highlight = FALSE;
484                   tui_display_register (
485                                         data_element_ptr->item_no,
486                                         data_item_win_ptr,
487                         ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
488                           TUI_DFLOAT_REGS) ?
489                          double_precision : unspecified_precision));
490                 }
491             }
492         }
493     }
494   return;
495 }
496
497
498 /*
499    ** tui_toggle_float_regs().
500  */
501 void
502 tui_toggle_float_regs (void)
503 {
504   struct tui_layout_def * layout_def = tui_layout_def ();
505
506   if (layout_def->float_regs_display_type == TUI_SFLOAT_REGS)
507     layout_def->float_regs_display_type = TUI_DFLOAT_REGS;
508   else
509     layout_def->float_regs_display_type = TUI_SFLOAT_REGS;
510
511   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible &&
512       (TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_SFLOAT_REGS ||
513        TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS))
514     tui_show_registers (layout_def->float_regs_display_type);
515
516   return;
517 }                               /* tui_toggle_float_regs */
518
519
520 void
521 _initialize_tui_regs (void)
522 {
523   if (xdb_commands)
524     {
525       add_com ("fr", class_tui, tui_show_float_command,
526                "Display only floating point registers\n");
527       add_com ("gr", class_tui, tui_show_general_command,
528                "Display only general registers\n");
529       add_com ("sr", class_tui, tui_show_special_command,
530                "Display only special registers\n");
531       add_com ("+r", class_tui, tui_scroll_regs_forward_command,
532                "Scroll the registers window forward\n");
533       add_com ("-r", class_tui, tui_scroll_regs_backward_command,
534                "Scroll the register window backward\n");
535       add_com ("tf", class_tui, _tui_toggle_float_regs_command,
536                "Toggle between single and double precision floating point registers.\n");
537       add_cmd (TUI_FLOAT_REGS_NAME_LOWER,
538                class_tui,
539                _tui_toggle_float_regs_command,
540                "Toggle between single and double precision floating point \
541 registers.\n",
542                &togglelist);
543     }
544 }
545
546
547 /*****************************************
548 ** STATIC LOCAL FUNCTIONS                 **
549 ******************************************/
550
551
552 /*
553    ** tui_register_name().
554    **        Return the register name.
555  */
556 static const char *
557 tui_register_name (int reg_num)
558 {
559   return REGISTER_NAME (reg_num);
560 }
561 extern int pagination_enabled;
562
563 static void
564 tui_restore_gdbout (void *ui)
565 {
566   ui_file_delete (gdb_stdout);
567   gdb_stdout = (struct ui_file*) ui;
568   pagination_enabled = 1;
569 }
570
571 /*
572    ** tui_register_format
573    **        Function to format the register name and value into a buffer,
574    **        suitable for printing or display
575  */
576 static void
577 tui_register_format (char *buf, int buf_len, int reg_num,
578                     struct tui_data_element * data_element,
579                     enum precision_type precision)
580 {
581   struct ui_file *stream;
582   struct ui_file *old_stdout;
583   const char *name;
584   struct cleanup *cleanups;
585   char *p;
586   int pos;
587
588   name = REGISTER_NAME (reg_num);
589   if (name == 0)
590     {
591       strcpy (buf, "");
592       return;
593     }
594   
595   pagination_enabled = 0;
596   old_stdout = gdb_stdout;
597   stream = tui_sfileopen (buf_len);
598   gdb_stdout = stream;
599   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
600   gdbarch_print_registers_info (current_gdbarch, stream, deprecated_selected_frame,
601                                 reg_num, 1);
602
603   /* Save formatted output in the buffer.  */
604   p = tui_file_get_strbuf (stream);
605   pos = 0;
606   while (*p && *p == *name++ && buf_len)
607     {
608       *buf++ = *p++;
609       buf_len--;
610       pos++;
611     }
612   while (*p == ' ')
613     p++;
614   while (pos < 8 && buf_len)
615     {
616       *buf++ = ' ';
617       buf_len--;
618       pos++;
619     }
620   strncpy (buf, p, buf_len);
621
622   /* Remove the possible \n.  */
623   p = strchr (buf, '\n');
624   if (p)
625     *p = 0;
626
627   do_cleanups (cleanups);
628 }
629
630
631 #define NUM_GENERAL_REGS    32
632 /* Set the content of the data window to consist of the general
633    registers.  */
634 static enum tui_status
635 tui_set_general_regs_content (int refresh_values_only)
636 {
637   return (tui_set_regs_content (0,
638                               NUM_GENERAL_REGS - 1,
639                               deprecated_selected_frame,
640                               TUI_GENERAL_REGS,
641                               refresh_values_only));
642
643 }
644
645
646 #ifndef PCOQ_HEAD_REGNUM
647 #define START_SPECIAL_REGS  0
648 #else
649 #define START_SPECIAL_REGS    PCOQ_HEAD_REGNUM
650 #endif
651
652 /* Set the content of the data window to consist of the special
653    registers.  */
654 static enum tui_status
655 tui_set_special_regs_content (int refresh_values_only)
656 {
657   enum tui_status ret = TUI_FAILURE;
658   int end_reg_num;
659
660   end_reg_num = FP0_REGNUM - 1;
661   ret = tui_set_regs_content (START_SPECIAL_REGS,
662                             end_reg_num,
663                             deprecated_selected_frame,
664                             TUI_SPECIAL_REGS,
665                             refresh_values_only);
666
667   return ret;
668 }
669
670
671 /* Set the content of the data window to consist of the special
672    registers.  */
673 static enum tui_status
674 tui_set_general_and_special_regs_content (int refresh_values_only)
675 {
676   enum tui_status ret = TUI_FAILURE;
677   int end_reg_num = (-1);
678
679   end_reg_num = FP0_REGNUM - 1;
680   ret = tui_set_regs_content (
681          0, end_reg_num, deprecated_selected_frame, TUI_SPECIAL_REGS, refresh_values_only);
682
683   return ret;
684 }
685
686 /* Set the content of the data window to consist of the float
687    registers.  */
688 static enum tui_status
689 tui_set_float_regs_content (enum tui_register_display_type dpy_type,
690                             int refresh_values_only)
691 {
692   enum tui_status ret = TUI_FAILURE;
693   int start_reg_num;
694
695   start_reg_num = FP0_REGNUM;
696   ret = tui_set_regs_content (start_reg_num,
697                             NUM_REGS - 1,
698                             deprecated_selected_frame,
699                             dpy_type,
700                             refresh_values_only);
701
702   return ret;
703 }
704
705
706 /* Answer TRUE if the register's value has changed, FALSE otherwise.
707    If TRUE, new_value is filled in with the new value.  */
708 static int
709 tui_reg_value_has_changed (struct tui_data_element * data_element,
710                            struct frame_info *frame, char *new_value)
711 {
712   int has_changed = FALSE;
713
714   if (data_element->item_no != UNDEFINED_ITEM &&
715       tui_register_name (data_element->item_no) != (char *) NULL)
716     {
717       char raw_buf[MAX_REGISTER_SIZE];
718       int i;
719
720       if (tui_get_register_raw_value (data_element->item_no, raw_buf, frame) == TUI_SUCCESS)
721         {
722           int size = DEPRECATED_REGISTER_RAW_SIZE (data_element->item_no);
723           
724           for (i = 0; (i < size && !has_changed); i++)
725             has_changed = (((char *) data_element->value)[i] != raw_buf[i]);
726           if (has_changed && new_value != (char *) NULL)
727             {
728               for (i = 0; i < size; i++)
729                 new_value[i] = raw_buf[i];
730             }
731         }
732     }
733   return has_changed;
734 }
735
736
737
738 /* Get the register raw value.  The raw value is returned in reg_value.  */
739 static enum tui_status
740 tui_get_register_raw_value (int reg_num, char *reg_value, struct frame_info *frame)
741 {
742   enum tui_status ret = TUI_FAILURE;
743
744   if (target_has_registers)
745     {
746       get_frame_register (frame, reg_num, reg_value);
747       /* NOTE: cagney/2003-03-13: This is bogus.  It is refering to
748          the register cache and not the frame which could have pulled
749          the register value off the stack.  */
750       if (register_cached (reg_num) >= 0)
751         ret = TUI_SUCCESS;
752     }
753   return ret;
754 }
755
756
757
758 /* Function to initialize a data element with the input and the
759    register value.  */
760 static void
761 tui_set_register_element (int reg_num, struct frame_info *frame,
762                           struct tui_data_element * data_element,
763                           int refresh_value_only)
764 {
765   if (data_element != (struct tui_data_element *) NULL)
766     {
767       if (!refresh_value_only)
768         {
769           data_element->item_no = reg_num;
770           data_element->name = tui_register_name (reg_num);
771           data_element->highlight = FALSE;
772         }
773       if (data_element->value == NULL)
774         data_element->value = xmalloc (MAX_REGISTER_SIZE);
775       if (data_element->value != NULL)
776         tui_get_register_raw_value (reg_num, data_element->value, frame);
777     }
778 }
779
780
781 /* Set the content of the data window to consist of the registers
782    numbered from start_reg_num to end_reg_num.  Note that if
783    refresh_values_only is TRUE, start_reg_num and end_reg_num are
784    ignored.  */
785 static enum tui_status
786 tui_set_regs_content (int start_reg_num, int end_reg_num,
787                     struct frame_info *frame,
788                     enum tui_register_display_type dpy_type,
789                     int refresh_values_only)
790 {
791   enum tui_status ret = TUI_FAILURE;
792   int num_regs = end_reg_num - start_reg_num + 1;
793   int allocated_here = FALSE;
794
795   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0 &&
796       !refresh_values_only)
797     {
798       tui_free_data_content (TUI_DATA_WIN->detail.data_display_info.regs_content,
799                              TUI_DATA_WIN->detail.data_display_info.regs_content_count);
800       TUI_DATA_WIN->detail.data_display_info.regs_content_count = 0;
801     }
802   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0)
803     {
804       TUI_DATA_WIN->detail.data_display_info.regs_content =
805         tui_alloc_content (num_regs, DATA_WIN);
806       allocated_here = TRUE;
807     }
808
809   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL)
810     {
811       int i;
812
813       if (!refresh_values_only || allocated_here)
814         {
815           TUI_DATA_WIN->generic.content = NULL;
816           TUI_DATA_WIN->generic.content_size = 0;
817           tui_add_content_elements (&TUI_DATA_WIN->generic, num_regs);
818           TUI_DATA_WIN->detail.data_display_info.regs_content =
819             (tui_win_content) TUI_DATA_WIN->generic.content;
820           TUI_DATA_WIN->detail.data_display_info.regs_content_count = num_regs;
821         }
822       /*
823          ** Now set the register names and values
824        */
825       for (i = start_reg_num; (i <= end_reg_num); i++)
826         {
827           struct tui_gen_win_info * data_item_win;
828
829           data_item_win = &TUI_DATA_WIN->detail.data_display_info.
830             regs_content[i - start_reg_num]->which_element.data_window;
831           tui_set_register_element (
832                                    i,
833                                    frame,
834            &((struct tui_win_element *) data_item_win->content[0])->which_element.data,
835                                    !allocated_here && refresh_values_only);
836         }
837       TUI_DATA_WIN->detail.data_display_info.regs_column_count =
838         tui_calculate_regs_column_count (dpy_type);
839 #ifdef LATER
840       if (TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
841         {
842           /* delete all the windows? */
843           /* realloc content equal to data_content_count + regs_content_count */
844           /* append TUI_DATA_WIN->detail.data_display_info.data_content to content */
845         }
846 #endif
847       TUI_DATA_WIN->generic.content_size =
848         TUI_DATA_WIN->detail.data_display_info.regs_content_count +
849         TUI_DATA_WIN->detail.data_display_info.data_content_count;
850       ret = TUI_SUCCESS;
851     }
852
853   return ret;
854 }
855
856
857 /* Function to display a register in a window.  If hilite is TRUE,
858    than the value will be displayed in reverse video.  */
859 static void
860 tui_display_register (int reg_num,
861                      struct tui_gen_win_info * win_info,                /* the data item window */
862                      enum precision_type precision)
863 {
864   if (win_info->handle != (WINDOW *) NULL)
865     {
866       int i;
867       char buf[40];
868       int value_chars_wide, label_width;
869       struct tui_data_element * data_element_ptr = &((tui_win_content)
870                                     win_info->content)[0]->which_element.data;
871
872       if (IS_64BIT ||
873           TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
874         {
875           value_chars_wide = DOUBLE_FLOAT_VALUE_WIDTH;
876           label_width = DOUBLE_FLOAT_LABEL_WIDTH;
877         }
878       else
879         {
880           if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
881               TUI_SFLOAT_REGS)
882             {
883               value_chars_wide = SINGLE_FLOAT_VALUE_WIDTH;
884               label_width = SINGLE_FLOAT_LABEL_WIDTH;
885             }
886           else
887             {
888               value_chars_wide = SINGLE_VALUE_WIDTH;
889               label_width = SINGLE_LABEL_WIDTH;
890             }
891         }
892
893       buf[0] = (char) 0;
894       tui_register_format (buf,
895                           value_chars_wide + label_width,
896                           reg_num,
897                           data_element_ptr,
898                           precision);
899
900       if (data_element_ptr->highlight)
901         wstandout (win_info->handle);
902
903       wmove (win_info->handle, 0, 0);
904       for (i = 1; i < win_info->width; i++)
905         waddch (win_info->handle, ' ');
906       wmove (win_info->handle, 0, 0);
907       waddstr (win_info->handle, buf);
908
909       if (data_element_ptr->highlight)
910         wstandend (win_info->handle);
911       tui_refresh_win (win_info);
912     }
913 }
914
915
916 static void
917 tui_v_show_registers_command_support (enum tui_register_display_type dpy_type)
918 {
919
920   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
921     {                           /* Data window already displayed, show the registers */
922       if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != dpy_type)
923         tui_show_registers (dpy_type);
924     }
925   else
926     (tui_layout_def ())->regs_display_type = dpy_type;
927
928   return;
929 }
930
931
932 static void
933 tui_show_float_command (char *arg, int from_tty)
934 {
935   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible ||
936       (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_SFLOAT_REGS &&
937        TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_DFLOAT_REGS))
938     tui_v_show_registers_command_support ((tui_layout_def ())->float_regs_display_type);
939 }
940
941
942 static void
943 tui_show_general_command (char *arg, int from_tty)
944 {
945   tui_v_show_registers_command_support (TUI_GENERAL_REGS);
946 }
947
948
949 static void
950 tui_show_special_command (char *arg, int from_tty)
951 {
952   tui_v_show_registers_command_support (TUI_SPECIAL_REGS);
953 }
954
955
956 static void
957 _tui_toggle_float_regs_command (char *arg, int from_tty)
958 {
959   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
960     tui_toggle_float_regs ();
961   else
962     {
963       struct tui_layout_def * layout_def = tui_layout_def ();
964
965       if (layout_def->float_regs_display_type == TUI_SFLOAT_REGS)
966         layout_def->float_regs_display_type = TUI_DFLOAT_REGS;
967       else
968         layout_def->float_regs_display_type = TUI_SFLOAT_REGS;
969     }
970 }
971
972
973 static void
974 tui_scroll_regs_forward_command (char *arg, int from_tty)
975 {
976   tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
977 }
978
979
980 static void
981 tui_scroll_regs_backward_command (char *arg, int from_tty)
982 {
983   tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
984 }