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