2004-02-07 Andrew Cagney <cagney@redhat.com>
[platform/upstream/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 _tuiSetRegsContent
81   (int, int, struct frame_info *, enum tui_register_display_type, int);
82 static const char *_tuiRegisterName (int);
83 static enum tui_status _tuiGetRegisterRawValue (int, char *, struct frame_info *);
84 static void _tuiSetRegisterElement
85   (int, struct frame_info *, struct tui_data_element *, int);
86 static void _tuiDisplayRegister (int, struct tui_gen_win_info *, enum precision_type);
87 static void _tuiRegisterFormat
88   (char *, int, int, struct tui_data_element *, enum precision_type);
89 static enum tui_status _tuiSetGeneralRegsContent (int);
90 static enum tui_status _tuiSetSpecialRegsContent (int);
91 static enum tui_status _tuiSetGeneralAndSpecialRegsContent (int);
92 static enum tui_status _tuiSetFloatRegsContent (enum tui_register_display_type, int);
93 static int _tuiRegValueHasChanged
94   (struct tui_data_element *, struct frame_info *, char *);
95 static void _tuiShowFloat_command (char *, int);
96 static void _tuiShowGeneral_command (char *, int);
97 static void _tuiShowSpecial_command (char *, int);
98 static void _tui_vShowRegisters_commandSupport (enum tui_register_display_type);
99 static void _tuiToggleFloatRegs_command (char *, int);
100 static void _tuiScrollRegsForward_command (char *, int);
101 static void _tuiScrollRegsBackward_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   register int numLines = (-1);
115
116   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
117     {
118       numLines = (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         numLines++;
123     }
124   return numLines;
125 }
126
127
128 /* Answer the line number that the register element at elementNo is
129    on.  If elementNo is greater than the number of register elements
130    there are, -1 is returned.  */
131 int
132 tui_line_from_reg_element_no (int elementNo)
133 {
134   if (elementNo < 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 (elementNo <
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 lineNo.  If lineNo is past
156    the register area (-1) is returned.  */
157 int
158 tui_first_reg_element_no_inline (int lineNo)
159 {
160   if ((lineNo * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
161       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
162     return ((lineNo + 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 /*
171    ** tuiLastRegElementNoInLine()
172    **        Answer the index of the last element in lineNo.  If lineNo is past
173    **        the register area (-1) is returned.
174  */
175 int
176 tuiLastRegElementNoInLine (int lineNo)
177 {
178   if ((lineNo * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
179       TUI_DATA_WIN->detail.data_display_info.regs_content_count)
180     return ((lineNo + 1) *
181             TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
182   else
183     return (-1);
184 }                               /* tuiLastRegElementNoInLine */
185
186
187 /* Calculate the number of columns that should be used to display the
188    registers.  */
189 int
190 tui_calculate_regs_column_count (enum tui_register_display_type dpyType)
191 {
192   int colCount, colWidth;
193
194   if (IS_64BIT || dpyType == TUI_DFLOAT_REGS)
195     colWidth = DOUBLE_FLOAT_VALUE_WIDTH + DOUBLE_FLOAT_LABEL_WIDTH;
196   else
197     {
198       if (dpyType == TUI_SFLOAT_REGS)
199         colWidth = SINGLE_FLOAT_VALUE_WIDTH + SINGLE_FLOAT_LABEL_WIDTH;
200       else
201         colWidth = SINGLE_VALUE_WIDTH + SINGLE_LABEL_WIDTH;
202     }
203   colCount = (TUI_DATA_WIN->generic.width - 2) / colWidth;
204
205   return colCount;
206 }                               /* tuiCalulateRegs_column_count */
207
208
209 /* Show the registers int the data window as indicated by dpyType.  If
210    there is any other registers being displayed, then they are
211    cleared.  What registers are displayed is dependent upon dpyType.  */
212 void
213 tui_show_registers (enum tui_register_display_type dpyType)
214 {
215   enum tui_status ret = TUI_FAILURE;
216   int refreshValuesOnly = FALSE;
217
218   /* Say that registers should be displayed, even if there is a problem */
219   TUI_DATA_WIN->detail.data_display_info.display_regs = TRUE;
220
221   if (target_has_registers)
222     {
223       refreshValuesOnly =
224         (dpyType == TUI_DATA_WIN->detail.data_display_info.regs_display_type);
225       switch (dpyType)
226         {
227         case TUI_GENERAL_REGS:
228           ret = _tuiSetGeneralRegsContent (refreshValuesOnly);
229           break;
230         case TUI_SFLOAT_REGS:
231         case TUI_DFLOAT_REGS:
232           ret = _tuiSetFloatRegsContent (dpyType, refreshValuesOnly);
233           break;
234
235 /* could ifdef out */
236
237         case TUI_SPECIAL_REGS:
238           ret = _tuiSetSpecialRegsContent (refreshValuesOnly);
239           break;
240         case TUI_GENERAL_AND_SPECIAL_REGS:
241           ret = _tuiSetGeneralAndSpecialRegsContent (refreshValuesOnly);
242           break;
243
244 /* end of potential if def */
245
246         default:
247           break;
248         }
249     }
250   if (ret == TUI_FAILURE)
251     {
252       TUI_DATA_WIN->detail.data_display_info.regs_display_type = TUI_UNDEFINED_REGS;
253       tui_erase_data_content (NO_REGS_STRING);
254     }
255   else
256     {
257       int i;
258
259       /* Clear all notation of changed values */
260       for (i = 0; (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
261         {
262           struct tui_gen_win_info * dataItemWin;
263
264           dataItemWin = &TUI_DATA_WIN->detail.data_display_info.
265             regs_content[i]->which_element.data_window;
266           (&((struct tui_win_element *)
267              dataItemWin->content[0])->which_element.data)->highlight = FALSE;
268         }
269       TUI_DATA_WIN->detail.data_display_info.regs_display_type = dpyType;
270       tui_display_all_data ();
271     }
272   (tui_layout_def ())->regs_display_type = dpyType;
273
274   return;
275 }
276
277
278 /* Function to display the registers in the content from
279    'startElementNo' until the end of the register content or the end
280    of the display height.  No checking for displaying past the end of
281    the registers is done here.  */
282 void
283 tui_display_registers_from (int startElementNo)
284 {
285   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
286       TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
287     {
288       register int i = startElementNo;
289       int j, valueCharsWide, itemWinWidth, curY, labelWidth;
290       enum precision_type precision;
291
292       precision = (TUI_DATA_WIN->detail.data_display_info.regs_display_type
293                    == TUI_DFLOAT_REGS) ?
294         double_precision : unspecified_precision;
295       if (IS_64BIT ||
296           TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
297         {
298           valueCharsWide = DOUBLE_FLOAT_VALUE_WIDTH;
299           labelWidth = DOUBLE_FLOAT_LABEL_WIDTH;
300         }
301       else
302         {
303           if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
304               TUI_SFLOAT_REGS)
305             {
306               valueCharsWide = SINGLE_FLOAT_VALUE_WIDTH;
307               labelWidth = SINGLE_FLOAT_LABEL_WIDTH;
308             }
309           else
310             {
311               valueCharsWide = SINGLE_VALUE_WIDTH;
312               labelWidth = SINGLE_LABEL_WIDTH;
313             }
314         }
315       itemWinWidth = valueCharsWide + labelWidth;
316       /*
317          ** Now create each data "sub" window, and write the display into it.
318        */
319       curY = 1;
320       while (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count &&
321              curY <= TUI_DATA_WIN->generic.viewport_height)
322         {
323           for (j = 0;
324                (j < TUI_DATA_WIN->detail.data_display_info.regs_column_count &&
325                 i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); j++)
326             {
327               struct tui_gen_win_info * dataItemWin;
328               struct tui_data_element * dataElementPtr;
329
330               /* create the window if necessary */
331               dataItemWin = &TUI_DATA_WIN->detail.data_display_info.
332                 regs_content[i]->which_element.data_window;
333               dataElementPtr = &((struct tui_win_element *)
334                                  dataItemWin->content[0])->which_element.data;
335               if (dataItemWin->handle == (WINDOW *) NULL)
336                 {
337                   dataItemWin->height = 1;
338                   dataItemWin->width = (precision == double_precision) ?
339                     itemWinWidth + 2 : itemWinWidth + 1;
340                   dataItemWin->origin.x = (itemWinWidth * j) + 1;
341                   dataItemWin->origin.y = curY;
342                   tui_make_window (dataItemWin, DONT_BOX_WINDOW);
343                   scrollok (dataItemWin->handle, FALSE);
344                 }
345               touchwin (dataItemWin->handle);
346
347               /*
348                  ** Get the printable representation of the register
349                  ** and display it
350                */
351               _tuiDisplayRegister (
352                             dataElementPtr->item_no, dataItemWin, precision);
353               i++;              /* next register */
354             }
355           curY++;               /* next row; */
356         }
357     }
358
359   return;
360 }
361
362
363 /*
364    ** tuiDisplayRegElementAtLine().
365    **        Function to display the registers in the content from
366    **        'startElementNo' on 'startLineNo' until the end of the
367    **        register content or the end of the display height.
368    **        This function checks that we won't display off the end
369    **        of the register display.
370  */
371 void
372 tuiDisplayRegElementAtLine (int startElementNo, int startLineNo)
373 {
374   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
375       TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
376     {
377       register int elementNo = startElementNo;
378
379       if (startElementNo != 0 && startLineNo != 0)
380         {
381           register int lastLineNo, firstLineOnLastPage;
382
383           lastLineNo = tui_last_regs_line_no ();
384           firstLineOnLastPage = lastLineNo - (TUI_DATA_WIN->generic.height - 2);
385           if (firstLineOnLastPage < 0)
386             firstLineOnLastPage = 0;
387           /*
388              ** If there is no other data displayed except registers,
389              ** and the elementNo causes us to scroll past the end of the
390              ** registers, adjust what element to really start the display at.
391            */
392           if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 &&
393               startLineNo > firstLineOnLastPage)
394             elementNo = tui_first_reg_element_no_inline (firstLineOnLastPage);
395         }
396       tui_display_registers_from (elementNo);
397     }
398
399   return;
400 }                               /* tuiDisplayRegElementAtLine */
401
402
403
404 /* Function to display the registers starting at line lineNo in the
405    data window.  Answers the line number that the display actually
406    started from.  If nothing is displayed (-1) is returned.  */
407 int
408 tui_display_registers_from_line (int lineNo, int forceDisplay)
409 {
410   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
411     {
412       int line, elementNo;
413
414       if (lineNo < 0)
415         line = 0;
416       else if (forceDisplay)
417         {                       /*
418                                    ** If we must display regs (forceDisplay is true), then make
419                                    ** sure that we don't display off the end of the registers.
420                                  */
421           if (lineNo >= tui_last_regs_line_no ())
422             {
423               if ((line = tui_line_from_reg_element_no (
424                  TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
425                 line = 0;
426             }
427           else
428             line = lineNo;
429         }
430       else
431         line = lineNo;
432
433       elementNo = tui_first_reg_element_no_inline (line);
434       if (elementNo < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
435         tuiDisplayRegElementAtLine (elementNo, line);
436       else
437         line = (-1);
438
439       return line;
440     }
441
442   return (-1);                  /* nothing was displayed */
443 }
444
445
446 /* This function check all displayed registers for changes in values,
447    given a particular frame.  If the values have changed, they are
448    updated with the new value and highlighted.  */
449 void
450 tui_check_register_values (struct frame_info *frame)
451 {
452   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
453     {
454       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0 &&
455           TUI_DATA_WIN->detail.data_display_info.display_regs)
456         tui_show_registers ((tui_layout_def ())->regs_display_type);
457       else
458         {
459           int i, j;
460           char rawBuf[MAX_REGISTER_SIZE];
461
462           for (i = 0;
463                (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
464             {
465               struct tui_data_element * dataElementPtr;
466               struct tui_gen_win_info * dataItemWinPtr;
467               int wasHilighted;
468
469               dataItemWinPtr = &TUI_DATA_WIN->detail.data_display_info.
470                 regs_content[i]->which_element.data_window;
471               dataElementPtr = &((struct tui_win_element *)
472                              dataItemWinPtr->content[0])->which_element.data;
473               wasHilighted = dataElementPtr->highlight;
474               dataElementPtr->highlight =
475                 _tuiRegValueHasChanged (dataElementPtr, frame, &rawBuf[0]);
476               if (dataElementPtr->highlight)
477                 {
478                   int size;
479
480                   size = DEPRECATED_REGISTER_RAW_SIZE (dataElementPtr->item_no);
481                   for (j = 0; j < size; j++)
482                     ((char *) dataElementPtr->value)[j] = rawBuf[j];
483                   _tuiDisplayRegister (
484                                         dataElementPtr->item_no,
485                                         dataItemWinPtr,
486                         ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
487                           TUI_DFLOAT_REGS) ?
488                          double_precision : unspecified_precision));
489                 }
490               else if (wasHilighted)
491                 {
492                   dataElementPtr->highlight = FALSE;
493                   _tuiDisplayRegister (
494                                         dataElementPtr->item_no,
495                                         dataItemWinPtr,
496                         ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
497                           TUI_DFLOAT_REGS) ?
498                          double_precision : unspecified_precision));
499                 }
500             }
501         }
502     }
503   return;
504 }
505
506
507 /*
508    ** tuiToggleFloatRegs().
509  */
510 void
511 tuiToggleFloatRegs (void)
512 {
513   struct tui_layout_def * layoutDef = tui_layout_def ();
514
515   if (layoutDef->float_regs_display_type == TUI_SFLOAT_REGS)
516     layoutDef->float_regs_display_type = TUI_DFLOAT_REGS;
517   else
518     layoutDef->float_regs_display_type = TUI_SFLOAT_REGS;
519
520   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible &&
521       (TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_SFLOAT_REGS ||
522        TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS))
523     tui_show_registers (layoutDef->float_regs_display_type);
524
525   return;
526 }                               /* tuiToggleFloatRegs */
527
528
529 void
530 _initialize_tuiRegs (void)
531 {
532   if (xdb_commands)
533     {
534       add_com ("fr", class_tui, _tuiShowFloat_command,
535                "Display only floating point registers\n");
536       add_com ("gr", class_tui, _tuiShowGeneral_command,
537                "Display only general registers\n");
538       add_com ("sr", class_tui, _tuiShowSpecial_command,
539                "Display only special registers\n");
540       add_com ("+r", class_tui, _tuiScrollRegsForward_command,
541                "Scroll the registers window forward\n");
542       add_com ("-r", class_tui, _tuiScrollRegsBackward_command,
543                "Scroll the register window backward\n");
544       add_com ("tf", class_tui, _tuiToggleFloatRegs_command,
545                "Toggle between single and double precision floating point registers.\n");
546       add_cmd (TUI_FLOAT_REGS_NAME_LOWER,
547                class_tui,
548                _tuiToggleFloatRegs_command,
549                "Toggle between single and double precision floating point \
550 registers.\n",
551                &togglelist);
552     }
553 }
554
555
556 /*****************************************
557 ** STATIC LOCAL FUNCTIONS                 **
558 ******************************************/
559
560
561 /*
562    ** _tuiRegisterName().
563    **        Return the register name.
564  */
565 static const char *
566 _tuiRegisterName (int regNum)
567 {
568   return REGISTER_NAME (regNum);
569 }
570 extern int pagination_enabled;
571
572 static void
573 tui_restore_gdbout (void *ui)
574 {
575   ui_file_delete (gdb_stdout);
576   gdb_stdout = (struct ui_file*) ui;
577   pagination_enabled = 1;
578 }
579
580 /*
581    ** _tuiRegisterFormat
582    **        Function to format the register name and value into a buffer,
583    **        suitable for printing or display
584  */
585 static void
586 _tuiRegisterFormat (char *buf, int bufLen, int regNum,
587                     struct tui_data_element * dataElement,
588                     enum precision_type precision)
589 {
590   struct ui_file *stream;
591   struct ui_file *old_stdout;
592   const char *name;
593   struct cleanup *cleanups;
594   char *p;
595   int pos;
596
597   name = REGISTER_NAME (regNum);
598   if (name == 0)
599     {
600       strcpy (buf, "");
601       return;
602     }
603   
604   pagination_enabled = 0;
605   old_stdout = gdb_stdout;
606   stream = tui_sfileopen (bufLen);
607   gdb_stdout = stream;
608   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
609   gdbarch_print_registers_info (current_gdbarch, stream, deprecated_selected_frame,
610                                 regNum, 1);
611
612   /* Save formatted output in the buffer.  */
613   p = tui_file_get_strbuf (stream);
614   pos = 0;
615   while (*p && *p == *name++ && bufLen)
616     {
617       *buf++ = *p++;
618       bufLen--;
619       pos++;
620     }
621   while (*p == ' ')
622     p++;
623   while (pos < 8 && bufLen)
624     {
625       *buf++ = ' ';
626       bufLen--;
627       pos++;
628     }
629   strncpy (buf, p, bufLen);
630
631   /* Remove the possible \n.  */
632   p = strchr (buf, '\n');
633   if (p)
634     *p = 0;
635
636   do_cleanups (cleanups);
637 }
638
639
640 #define NUM_GENERAL_REGS    32
641 /*
642    ** _tuiSetGeneralRegsContent().
643    **      Set the content of the data window to consist of the general registers.
644  */
645 static enum tui_status
646 _tuiSetGeneralRegsContent (int refreshValuesOnly)
647 {
648   return (_tuiSetRegsContent (0,
649                               NUM_GENERAL_REGS - 1,
650                               deprecated_selected_frame,
651                               TUI_GENERAL_REGS,
652                               refreshValuesOnly));
653
654 }                               /* _tuiSetGeneralRegsContent */
655
656
657 #ifndef PCOQ_HEAD_REGNUM
658 #define START_SPECIAL_REGS  0
659 #else
660 #define START_SPECIAL_REGS    PCOQ_HEAD_REGNUM
661 #endif
662
663 /*
664    ** _tuiSetSpecialRegsContent().
665    **      Set the content of the data window to consist of the special registers.
666  */
667 static enum tui_status
668 _tuiSetSpecialRegsContent (int refreshValuesOnly)
669 {
670   enum tui_status ret = TUI_FAILURE;
671   int endRegNum;
672
673   endRegNum = FP0_REGNUM - 1;
674   ret = _tuiSetRegsContent (START_SPECIAL_REGS,
675                             endRegNum,
676                             deprecated_selected_frame,
677                             TUI_SPECIAL_REGS,
678                             refreshValuesOnly);
679
680   return ret;
681 }                               /* _tuiSetSpecialRegsContent */
682
683
684 /*
685    ** _tuiSetGeneralAndSpecialRegsContent().
686    **      Set the content of the data window to consist of the special registers.
687  */
688 static enum tui_status
689 _tuiSetGeneralAndSpecialRegsContent (int refreshValuesOnly)
690 {
691   enum tui_status ret = TUI_FAILURE;
692   int endRegNum = (-1);
693
694   endRegNum = FP0_REGNUM - 1;
695   ret = _tuiSetRegsContent (
696          0, endRegNum, deprecated_selected_frame, TUI_SPECIAL_REGS, refreshValuesOnly);
697
698   return ret;
699 }                               /* _tuiSetGeneralAndSpecialRegsContent */
700
701 /*
702    ** _tuiSetFloatRegsContent().
703    **        Set the content of the data window to consist of the float registers.
704  */
705 static enum tui_status
706 _tuiSetFloatRegsContent (enum tui_register_display_type dpyType, int refreshValuesOnly)
707 {
708   enum tui_status ret = TUI_FAILURE;
709   int startRegNum;
710
711   startRegNum = FP0_REGNUM;
712   ret = _tuiSetRegsContent (startRegNum,
713                             NUM_REGS - 1,
714                             deprecated_selected_frame,
715                             dpyType,
716                             refreshValuesOnly);
717
718   return ret;
719 }                               /* _tuiSetFloatRegsContent */
720
721
722 /*
723    ** _tuiRegValueHasChanged().
724    **        Answer TRUE if the register's value has changed, FALSE otherwise.
725    **        If TRUE, newValue is filled in with the new value.
726  */
727 static int
728 _tuiRegValueHasChanged (struct tui_data_element * dataElement,
729                         struct frame_info *frame,
730                         char *newValue)
731 {
732   int hasChanged = FALSE;
733
734   if (dataElement->item_no != UNDEFINED_ITEM &&
735       _tuiRegisterName (dataElement->item_no) != (char *) NULL)
736     {
737       char rawBuf[MAX_REGISTER_SIZE];
738       int i;
739
740       if (_tuiGetRegisterRawValue (
741                          dataElement->item_no, rawBuf, frame) == TUI_SUCCESS)
742         {
743           int size = DEPRECATED_REGISTER_RAW_SIZE (dataElement->item_no);
744           
745           for (i = 0; (i < size && !hasChanged); i++)
746             hasChanged = (((char *) dataElement->value)[i] != rawBuf[i]);
747           if (hasChanged && newValue != (char *) NULL)
748             {
749               for (i = 0; i < size; i++)
750                 newValue[i] = rawBuf[i];
751             }
752         }
753     }
754   return hasChanged;
755 }                               /* _tuiRegValueHasChanged */
756
757
758
759 /*
760    ** _tuiGetRegisterRawValue().
761    **        Get the register raw value.  The raw value is returned in regValue.
762  */
763 static enum tui_status
764 _tuiGetRegisterRawValue (int regNum, char *regValue, struct frame_info *frame)
765 {
766   enum tui_status ret = TUI_FAILURE;
767
768   if (target_has_registers)
769     {
770       get_frame_register (frame, regNum, regValue);
771       /* NOTE: cagney/2003-03-13: This is bogus.  It is refering to
772          the register cache and not the frame which could have pulled
773          the register value off the stack.  */
774       if (register_cached (regNum) >= 0)
775         ret = TUI_SUCCESS;
776     }
777   return ret;
778 }                               /* _tuiGetRegisterRawValue */
779
780
781
782 /*
783    ** _tuiSetRegisterElement().
784    **       Function to initialize a data element with the input and
785    **       the register value.
786  */
787 static void
788 _tuiSetRegisterElement (int regNum, struct frame_info *frame,
789                         struct tui_data_element * dataElement,
790                         int refreshValueOnly)
791 {
792   if (dataElement != (struct tui_data_element *) NULL)
793     {
794       if (!refreshValueOnly)
795         {
796           dataElement->item_no = regNum;
797           dataElement->name = _tuiRegisterName (regNum);
798           dataElement->highlight = FALSE;
799         }
800       if (dataElement->value == NULL)
801         dataElement->value = xmalloc (MAX_REGISTER_SIZE);
802       if (dataElement->value != NULL)
803         _tuiGetRegisterRawValue (regNum, dataElement->value, frame);
804     }
805
806   return;
807 }                               /* _tuiSetRegisterElement */
808
809
810 /*
811    ** _tuiSetRegsContent().
812    **        Set the content of the data window to consist of the registers
813    **        numbered from startRegNum to endRegNum.  Note that if
814    **        refreshValuesOnly is TRUE, startRegNum and endRegNum are ignored.
815  */
816 static enum tui_status
817 _tuiSetRegsContent (int startRegNum, int endRegNum,
818                     struct frame_info *frame,
819                     enum tui_register_display_type dpyType,
820                     int refreshValuesOnly)
821 {
822   enum tui_status ret = TUI_FAILURE;
823   int numRegs = endRegNum - startRegNum + 1;
824   int allocatedHere = FALSE;
825
826   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0 &&
827       !refreshValuesOnly)
828     {
829       tui_free_data_content (TUI_DATA_WIN->detail.data_display_info.regs_content,
830                              TUI_DATA_WIN->detail.data_display_info.regs_content_count);
831       TUI_DATA_WIN->detail.data_display_info.regs_content_count = 0;
832     }
833   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0)
834     {
835       TUI_DATA_WIN->detail.data_display_info.regs_content =
836         tui_alloc_content (numRegs, DATA_WIN);
837       allocatedHere = TRUE;
838     }
839
840   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL)
841     {
842       int i;
843
844       if (!refreshValuesOnly || allocatedHere)
845         {
846           TUI_DATA_WIN->generic.content = NULL;
847           TUI_DATA_WIN->generic.content_size = 0;
848           tui_add_content_elements (&TUI_DATA_WIN->generic, numRegs);
849           TUI_DATA_WIN->detail.data_display_info.regs_content =
850             (tui_win_content) TUI_DATA_WIN->generic.content;
851           TUI_DATA_WIN->detail.data_display_info.regs_content_count = numRegs;
852         }
853       /*
854          ** Now set the register names and values
855        */
856       for (i = startRegNum; (i <= endRegNum); i++)
857         {
858           struct tui_gen_win_info * dataItemWin;
859
860           dataItemWin = &TUI_DATA_WIN->detail.data_display_info.
861             regs_content[i - startRegNum]->which_element.data_window;
862           _tuiSetRegisterElement (
863                                    i,
864                                    frame,
865            &((struct tui_win_element *) dataItemWin->content[0])->which_element.data,
866                                    !allocatedHere && refreshValuesOnly);
867         }
868       TUI_DATA_WIN->detail.data_display_info.regs_column_count =
869         tui_calculate_regs_column_count (dpyType);
870 #ifdef LATER
871       if (TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
872         {
873           /* delete all the windows? */
874           /* realloc content equal to data_content_count + regs_content_count */
875           /* append TUI_DATA_WIN->detail.data_display_info.dataContent to content */
876         }
877 #endif
878       TUI_DATA_WIN->generic.content_size =
879         TUI_DATA_WIN->detail.data_display_info.regs_content_count +
880         TUI_DATA_WIN->detail.data_display_info.data_content_count;
881       ret = TUI_SUCCESS;
882     }
883
884   return ret;
885 }                               /* _tuiSetRegsContent */
886
887
888 /*
889    ** _tuiDisplayRegister().
890    **        Function to display a register in a window.  If hilite is TRUE,
891    **        than the value will be displayed in reverse video
892  */
893 static void
894 _tuiDisplayRegister (int regNum,
895                      struct tui_gen_win_info * winInfo,         /* the data item window */
896                      enum precision_type precision)
897 {
898   if (winInfo->handle != (WINDOW *) NULL)
899     {
900       int i;
901       char buf[40];
902       int valueCharsWide, labelWidth;
903       struct tui_data_element * dataElementPtr = &((tui_win_content)
904                                     winInfo->content)[0]->which_element.data;
905
906       if (IS_64BIT ||
907           TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
908         {
909           valueCharsWide = DOUBLE_FLOAT_VALUE_WIDTH;
910           labelWidth = DOUBLE_FLOAT_LABEL_WIDTH;
911         }
912       else
913         {
914           if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
915               TUI_SFLOAT_REGS)
916             {
917               valueCharsWide = SINGLE_FLOAT_VALUE_WIDTH;
918               labelWidth = SINGLE_FLOAT_LABEL_WIDTH;
919             }
920           else
921             {
922               valueCharsWide = SINGLE_VALUE_WIDTH;
923               labelWidth = SINGLE_LABEL_WIDTH;
924             }
925         }
926
927       buf[0] = (char) 0;
928       _tuiRegisterFormat (buf,
929                           valueCharsWide + labelWidth,
930                           regNum,
931                           dataElementPtr,
932                           precision);
933
934       if (dataElementPtr->highlight)
935         wstandout (winInfo->handle);
936
937       wmove (winInfo->handle, 0, 0);
938       for (i = 1; i < winInfo->width; i++)
939         waddch (winInfo->handle, ' ');
940       wmove (winInfo->handle, 0, 0);
941       waddstr (winInfo->handle, buf);
942
943       if (dataElementPtr->highlight)
944         wstandend (winInfo->handle);
945       tui_refresh_win (winInfo);
946     }
947   return;
948 }                               /* _tuiDisplayRegister */
949
950
951 static void
952 _tui_vShowRegisters_commandSupport (enum tui_register_display_type dpyType)
953 {
954
955   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
956     {                           /* Data window already displayed, show the registers */
957       if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != dpyType)
958         tui_show_registers (dpyType);
959     }
960   else
961     (tui_layout_def ())->regs_display_type = dpyType;
962
963   return;
964 }                               /* _tui_vShowRegisters_commandSupport */
965
966
967 static void
968 _tuiShowFloat_command (char *arg, int fromTTY)
969 {
970   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible ||
971       (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_SFLOAT_REGS &&
972        TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_DFLOAT_REGS))
973     _tui_vShowRegisters_commandSupport ((tui_layout_def ())->float_regs_display_type);
974
975   return;
976 }                               /* _tuiShowFloat_command */
977
978
979 static void
980 _tuiShowGeneral_command (char *arg, int fromTTY)
981 {
982   _tui_vShowRegisters_commandSupport (TUI_GENERAL_REGS);
983 }
984
985
986 static void
987 _tuiShowSpecial_command (char *arg, int fromTTY)
988 {
989   _tui_vShowRegisters_commandSupport (TUI_SPECIAL_REGS);
990 }
991
992
993 static void
994 _tuiToggleFloatRegs_command (char *arg, int fromTTY)
995 {
996   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
997     tuiToggleFloatRegs ();
998   else
999     {
1000       struct tui_layout_def * layoutDef = tui_layout_def ();
1001
1002       if (layoutDef->float_regs_display_type == TUI_SFLOAT_REGS)
1003         layoutDef->float_regs_display_type = TUI_DFLOAT_REGS;
1004       else
1005         layoutDef->float_regs_display_type = TUI_SFLOAT_REGS;
1006     }
1007
1008
1009   return;
1010 }                               /* _tuiToggleFloatRegs_command */
1011
1012
1013 static void
1014 _tuiScrollRegsForward_command (char *arg, int fromTTY)
1015 {
1016   tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
1017 }
1018
1019
1020 static void
1021 _tuiScrollRegsBackward_command (char *arg, int fromTTY)
1022 {
1023   tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
1024 }