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