
/*
   ** tuiRegs.c
   **         This module contains functions to support display of registers
   **         in the data window.
 */


#include "defs.h"
#include "tui.h"
#include "tuiData.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "gdbcmd.h"
#include "frame.h"
#include "inferior.h"
#include "target.h"
#include "tuiLayout.h"
#include "tuiWin.h"


/*****************************************
** LOCAL DEFINITIONS                    **
******************************************/
#define DOUBLE_FLOAT_LABEL_WIDTH    6
#define DOUBLE_FLOAT_LABEL_FMT      "%6.6s: "
#define DOUBLE_FLOAT_VALUE_WIDTH    30	/*min of 16 but may be in sci notation */

#define SINGLE_FLOAT_LABEL_WIDTH    6
#define SINGLE_FLOAT_LABEL_FMT      "%6.6s: "
#define SINGLE_FLOAT_VALUE_WIDTH    25	/* min of 8 but may be in sci notation */

#define SINGLE_LABEL_WIDTH    10
#define SINGLE_LABEL_FMT      "%10.10s: "
#define SINGLE_VALUE_WIDTH    14	/* minimum of 8 but may be in sci notation */

/* In the code HP gave Cygnus, this was actually a function call to a
   PA-specific function, which was supposed to determine whether the
   target was a 64-bit or 32-bit processor.  However, the 64-bit
   support wasn't complete, so we didn't merge that in, so we leave
   this here as a stub.  */
#define IS_64BIT 0

/*****************************************
** STATIC DATA                          **
******************************************/


/*****************************************
** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
******************************************/
static TuiStatus _tuiSetRegsContent
  (int, int, struct frame_info *, TuiRegisterDisplayType, int);
static char *_tuiRegisterName (int);
static TuiStatus _tuiGetRegisterRawValue (int, char *, struct frame_info *);
static void _tuiSetRegisterElement
  (int, struct frame_info *, TuiDataElementPtr, int);
static void _tuiDisplayRegister (int, TuiGenWinInfoPtr, enum precision_type);
static void _tuiRegisterFormat
  (char *, int, int, TuiDataElementPtr, enum precision_type);
static TuiStatus _tuiSetGeneralRegsContent (int);
static TuiStatus _tuiSetSpecialRegsContent (int);
static TuiStatus _tuiSetGeneralAndSpecialRegsContent (int);
static TuiStatus _tuiSetFloatRegsContent (TuiRegisterDisplayType, int);
static int _tuiRegValueHasChanged
  (TuiDataElementPtr, struct frame_info *, char *);
static void _tuiShowFloat_command (char *, int);
static void _tuiShowGeneral_command (char *, int);
static void _tuiShowSpecial_command (char *, int);
static void _tui_vShowRegisters_commandSupport (va_list);
static void _tuiToggleFloatRegs_command (char *, int);
static void _tuiScrollRegsForward_command (char *, int);
static void _tuiScrollRegsBackward_command (char *, int);
static void _tui_vShowRegisters_commandSupport (va_list);



/*****************************************
** PUBLIC FUNCTIONS                     **
******************************************/

/*
   ** tuiLastRegsLineNo()
   **        Answer the number of the last line in the regs display.
   **        If there are no registers (-1) is returned.
 */
int
#ifdef __STDC__
tuiLastRegsLineNo (void)
#else
tuiLastRegsLineNo ()
#endif
{
  register int numLines = (-1);

  if (dataWin->detail.dataDisplayInfo.regsContentCount > 0)
    {
      numLines = (dataWin->detail.dataDisplayInfo.regsContentCount /
		  dataWin->detail.dataDisplayInfo.regsColumnCount);
      if (dataWin->detail.dataDisplayInfo.regsContentCount %
	  dataWin->detail.dataDisplayInfo.regsColumnCount)
	numLines++;
    }
  return numLines;
}				/* tuiLastRegsLineNo */


/*
   ** tuiLineFromRegElementNo()
   **        Answer the line number that the register element at elementNo is
   **        on.  If elementNo is greater than the number of register elements
   **        there are, -1 is returned.
 */
int
#ifdef __STDC__
tuiLineFromRegElementNo (
			  int elementNo)
#else
tuiLineFromRegElementNo (elementNo)
     int elementNo;
#endif
{
  if (elementNo < dataWin->detail.dataDisplayInfo.regsContentCount)
    {
      int i, line = (-1);

      i = 1;
      while (line == (-1))
	{
	  if (elementNo <
	      (dataWin->detail.dataDisplayInfo.regsColumnCount * i))
	    line = i - 1;
	  else
	    i++;
	}

      return line;
    }
  else
    return (-1);
}				/* tuiLineFromRegElementNo */


/*
   ** tuiFirstRegElementNoInLine()
   **        Answer the index of the first element in lineNo.  If lineNo is
   **        past the register area (-1) is returned.
 */
int
#ifdef __STDC__
tuiFirstRegElementNoInLine (
			     int lineNo)
#else
tuiFirstRegElementNoInLine (lineNo)
     int lineNo;
#endif
{
  if ((lineNo * dataWin->detail.dataDisplayInfo.regsColumnCount)
      <= dataWin->detail.dataDisplayInfo.regsContentCount)
    return ((lineNo + 1) *
	    dataWin->detail.dataDisplayInfo.regsColumnCount) -
      dataWin->detail.dataDisplayInfo.regsColumnCount;
  else
    return (-1);
}				/* tuiFirstRegElementNoInLine */


/*
   ** tuiLastRegElementNoInLine()
   **        Answer the index of the last element in lineNo.  If lineNo is past
   **        the register area (-1) is returned.
 */
int
#ifdef __STDC__
tuiLastRegElementNoInLine (
			    int lineNo)
#else
tuiLastRegElementNoInLine (lineNo)
     int lineNo;
#endif
{
  if ((lineNo * dataWin->detail.dataDisplayInfo.regsColumnCount) <=
      dataWin->detail.dataDisplayInfo.regsContentCount)
    return ((lineNo + 1) *
	    dataWin->detail.dataDisplayInfo.regsColumnCount) - 1;
  else
    return (-1);
}				/* tuiLastRegElementNoInLine */


/*
   ** tuiCalculateRegsColumnCount
   **        Calculate the number of columns that should be used to display
   **        the registers.
 */
int
#ifdef __STDC__
tuiCalculateRegsColumnCount (
			      TuiRegisterDisplayType dpyType)
#else
tuiCalculateRegsColumnCount (dpyType)
     TuiRegisterDisplayType dpyType;
#endif
{
  int colCount, colWidth;

  if (IS_64BIT || dpyType == TUI_DFLOAT_REGS)
    colWidth = DOUBLE_FLOAT_VALUE_WIDTH + DOUBLE_FLOAT_LABEL_WIDTH;
  else
    {
      if (dpyType == TUI_SFLOAT_REGS)
	colWidth = SINGLE_FLOAT_VALUE_WIDTH + SINGLE_FLOAT_LABEL_WIDTH;
      else
	colWidth = SINGLE_VALUE_WIDTH + SINGLE_LABEL_WIDTH;
    }
  colCount = (dataWin->generic.width - 2) / colWidth;

  return colCount;
}				/* tuiCalulateRegsColumnCount */


/*
   ** tuiShowRegisters().
   **        Show the registers int the data window as indicated by dpyType.
   **        If there is any other registers being displayed, then they are
   **        cleared.  What registers are displayed is dependent upon dpyType.
 */
void
#ifdef __STDC__
tuiShowRegisters (
		   TuiRegisterDisplayType dpyType)
#else
tuiShowRegisters (dpyType)
     TuiRegisterDisplayType dpyType;
#endif
{
  TuiStatus ret = TUI_FAILURE;
  int refreshValuesOnly = FALSE;

  /* Say that registers should be displayed, even if there is a problem */
  dataWin->detail.dataDisplayInfo.displayRegs = TRUE;

  if (target_has_registers)
    {
      refreshValuesOnly =
	(dpyType == dataWin->detail.dataDisplayInfo.regsDisplayType);
      switch (dpyType)
	{
	case TUI_GENERAL_REGS:
	  ret = _tuiSetGeneralRegsContent (refreshValuesOnly);
	  break;
	case TUI_SFLOAT_REGS:
	case TUI_DFLOAT_REGS:
	  ret = _tuiSetFloatRegsContent (dpyType, refreshValuesOnly);
	  break;

/* could ifdef out */

	case TUI_SPECIAL_REGS:
	  ret = _tuiSetSpecialRegsContent (refreshValuesOnly);
	  break;
	case TUI_GENERAL_AND_SPECIAL_REGS:
	  ret = _tuiSetGeneralAndSpecialRegsContent (refreshValuesOnly);
	  break;

/* end of potential if def */

	default:
	  break;
	}
    }
  if (ret == TUI_FAILURE)
    {
      dataWin->detail.dataDisplayInfo.regsDisplayType = TUI_UNDEFINED_REGS;
      tuiEraseDataContent (NO_REGS_STRING);
    }
  else
    {
      int i;

      /* Clear all notation of changed values */
      for (i = 0; (i < dataWin->detail.dataDisplayInfo.regsContentCount); i++)
	{
	  TuiGenWinInfoPtr dataItemWin;

	  dataItemWin = &dataWin->detail.dataDisplayInfo.
	    regsContent[i]->whichElement.dataWindow;
	  (&((TuiWinElementPtr)
	     dataItemWin->content[0])->whichElement.data)->highlight = FALSE;
	}
      dataWin->detail.dataDisplayInfo.regsDisplayType = dpyType;
      tuiDisplayAllData ();
    }
  (tuiLayoutDef ())->regsDisplayType = dpyType;

  return;
}				/* tuiShowRegisters */


/*
   ** tuiDisplayRegistersFrom().
   **        Function to display the registers in the content from
   **        'startElementNo' until the end of the register content or the
   **        end of the display height.  No checking for displaying past
   **        the end of the registers is done here.
 */
void
#ifdef __STDC__
tuiDisplayRegistersFrom (
			  int startElementNo)
#else
tuiDisplayRegistersFrom (startElementNo)
     int startElementNo;
#endif
{
  if (dataWin->detail.dataDisplayInfo.regsContent != (TuiWinContent) NULL &&
      dataWin->detail.dataDisplayInfo.regsContentCount > 0)
    {
      register int i = startElementNo;
      int j, valueCharsWide, charsWide, itemWinWidth, curY, labelWidth;
      enum precision_type precision;

      precision = (dataWin->detail.dataDisplayInfo.regsDisplayType
		   == TUI_DFLOAT_REGS) ?
	double_precision : unspecified_precision;
      if (IS_64BIT ||
	  dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_DFLOAT_REGS)
	{
	  valueCharsWide = DOUBLE_FLOAT_VALUE_WIDTH;
	  labelWidth = DOUBLE_FLOAT_LABEL_WIDTH;
	}
      else
	{
	  if (dataWin->detail.dataDisplayInfo.regsDisplayType ==
	      TUI_SFLOAT_REGS)
	    {
	      valueCharsWide = SINGLE_FLOAT_VALUE_WIDTH;
	      labelWidth = SINGLE_FLOAT_LABEL_WIDTH;
	    }
	  else
	    {
	      valueCharsWide = SINGLE_VALUE_WIDTH;
	      labelWidth = SINGLE_LABEL_WIDTH;
	    }
	}
      itemWinWidth = valueCharsWide + labelWidth;
      /*
         ** Now create each data "sub" window, and write the display into it.
       */
      curY = 1;
      while (i < dataWin->detail.dataDisplayInfo.regsContentCount &&
	     curY <= dataWin->generic.viewportHeight)
	{
	  for (j = 0;
	       (j < dataWin->detail.dataDisplayInfo.regsColumnCount &&
		i < dataWin->detail.dataDisplayInfo.regsContentCount); j++)
	    {
	      TuiGenWinInfoPtr dataItemWin;
	      TuiDataElementPtr dataElementPtr;

	      /* create the window if necessary */
	      dataItemWin = &dataWin->detail.dataDisplayInfo.
		regsContent[i]->whichElement.dataWindow;
	      dataElementPtr = &((TuiWinElementPtr)
				 dataItemWin->content[0])->whichElement.data;
	      if (dataItemWin->handle == (WINDOW *) NULL)
		{
		  dataItemWin->height = 1;
		  dataItemWin->width = (precision == double_precision) ?
		    itemWinWidth + 2 : itemWinWidth + 1;
		  dataItemWin->origin.x = (itemWinWidth * j) + 1;
		  dataItemWin->origin.y = curY;
		  makeWindow (dataItemWin, DONT_BOX_WINDOW);
		}
	      /*
	         ** Get the printable representation of the register
	         ** and display it
	       */
	      _tuiDisplayRegister (
			    dataElementPtr->itemNo, dataItemWin, precision);
	      i++;		/* next register */
	    }
	  curY++;		/* next row; */
	}
    }

  return;
}				/* tuiDisplayRegistersFrom */


/*
   ** tuiDisplayRegElementAtLine().
   **        Function to display the registers in the content from
   **        'startElementNo' on 'startLineNo' until the end of the
   **        register content or the end of the display height.
   **        This function checks that we won't display off the end
   **        of the register display.
 */
void
#ifdef __STDC__
tuiDisplayRegElementAtLine (
			     int startElementNo,
			     int startLineNo)
#else
tuiDisplayRegElementAtLine (startElementNo, startLineNo)
     int startElementNo;
     int startLineNo;
#endif
{
  if (dataWin->detail.dataDisplayInfo.regsContent != (TuiWinContent) NULL &&
      dataWin->detail.dataDisplayInfo.regsContentCount > 0)
    {
      register int elementNo = startElementNo;

      if (startElementNo != 0 && startLineNo != 0)
	{
	  register int lastLineNo, firstLineOnLastPage;

	  lastLineNo = tuiLastRegsLineNo ();
	  firstLineOnLastPage = lastLineNo - (dataWin->generic.height - 2);
	  if (firstLineOnLastPage < 0)
	    firstLineOnLastPage = 0;
	  /*
	     ** If there is no other data displayed except registers,
	     ** and the elementNo causes us to scroll past the end of the
	     ** registers, adjust what element to really start the display at.
	   */
	  if (dataWin->detail.dataDisplayInfo.dataContentCount <= 0 &&
	      startLineNo > firstLineOnLastPage)
	    elementNo = tuiFirstRegElementNoInLine (firstLineOnLastPage);
	}
      tuiDisplayRegistersFrom (elementNo);
    }

  return;
}				/* tuiDisplayRegElementAtLine */



/*
   ** tuiDisplayRegistersFromLine().
   **        Function to display the registers starting at line lineNo in
   **        the data window.  Answers the line number that the display
   **        actually started from.  If nothing is displayed (-1) is returned.
 */
int
#ifdef __STDC__
tuiDisplayRegistersFromLine (
			      int lineNo,
			      int forceDisplay)
#else
tuiDisplayRegistersFromLine (lineNo, forceDisplay)
     int lineNo;
     int forceDisplay;
#endif
{
  int elementNo;

  if (dataWin->detail.dataDisplayInfo.regsContentCount > 0)
    {
      int line, elementNo;

      if (lineNo < 0)
	line = 0;
      else if (forceDisplay)
	{			/*
				   ** If we must display regs (forceDisplay is true), then make
				   ** sure that we don't display off the end of the registers.
				 */
	  if (lineNo >= tuiLastRegsLineNo ())
	    {
	      if ((line = tuiLineFromRegElementNo (
		 dataWin->detail.dataDisplayInfo.regsContentCount - 1)) < 0)
		line = 0;
	    }
	  else
	    line = lineNo;
	}
      else
	line = lineNo;

      elementNo = tuiFirstRegElementNoInLine (line);
      if (elementNo < dataWin->detail.dataDisplayInfo.regsContentCount)
	tuiDisplayRegElementAtLine (elementNo, line);
      else
	line = (-1);

      return line;
    }

  return (-1);			/* nothing was displayed */
}				/* tuiDisplayRegistersFromLine */


/*
   ** tuiCheckRegisterValues()
   **        This function check all displayed registers for changes in
   **        values, given a particular frame.  If the values have changed,
   **        they are updated with the new value and highlighted.
 */
void
#ifdef __STDC__
tuiCheckRegisterValues (
			 struct frame_info *frame)
#else
tuiCheckRegisterValues (frame)
     struct frame_info *frame;
#endif
{
  if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
    {
      if (dataWin->detail.dataDisplayInfo.regsContentCount <= 0 &&
	  dataWin->detail.dataDisplayInfo.displayRegs)
	tuiShowRegisters ((tuiLayoutDef ())->regsDisplayType);
      else
	{
	  int i, j;
	  char rawBuf[MAX_REGISTER_RAW_SIZE];

	  for (i = 0;
	       (i < dataWin->detail.dataDisplayInfo.regsContentCount); i++)
	    {
	      TuiDataElementPtr dataElementPtr;
	      TuiGenWinInfoPtr dataItemWinPtr;
	      int wasHilighted;

	      dataItemWinPtr = &dataWin->detail.dataDisplayInfo.
		regsContent[i]->whichElement.dataWindow;
	      dataElementPtr = &((TuiWinElementPtr)
			     dataItemWinPtr->content[0])->whichElement.data;
	      wasHilighted = dataElementPtr->highlight;
	      dataElementPtr->highlight =
		_tuiRegValueHasChanged (dataElementPtr, frame, &rawBuf[0]);
	      if (dataElementPtr->highlight)
		{
		  for (j = 0; j < MAX_REGISTER_RAW_SIZE; j++)
		    ((char *) dataElementPtr->value)[j] = rawBuf[j];
		  _tuiDisplayRegister (
					dataElementPtr->itemNo,
					dataItemWinPtr,
			((dataWin->detail.dataDisplayInfo.regsDisplayType ==
			  TUI_DFLOAT_REGS) ?
			 double_precision : unspecified_precision));
		}
	      else if (wasHilighted)
		{
		  dataElementPtr->highlight = FALSE;
		  _tuiDisplayRegister (
					dataElementPtr->itemNo,
					dataItemWinPtr,
			((dataWin->detail.dataDisplayInfo.regsDisplayType ==
			  TUI_DFLOAT_REGS) ?
			 double_precision : unspecified_precision));
		}
	    }
	}
    }
  return;
}				/* tuiCheckRegisterValues */


/*
   ** tuiToggleFloatRegs().
 */
void
#ifdef __STDC__
tuiToggleFloatRegs (void)
#else
tuiToggleFloatRegs ()
#endif
{
  TuiLayoutDefPtr layoutDef = tuiLayoutDef ();

  if (layoutDef->floatRegsDisplayType == TUI_SFLOAT_REGS)
    layoutDef->floatRegsDisplayType = TUI_DFLOAT_REGS;
  else
    layoutDef->floatRegsDisplayType = TUI_SFLOAT_REGS;

  if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible &&
      (dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_SFLOAT_REGS ||
       dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_DFLOAT_REGS))
    tuiShowRegisters (layoutDef->floatRegsDisplayType);

  return;
}				/* tuiToggleFloatRegs */


void
_initialize_tuiRegs (void)
{
  if (tui_version && xdb_commands)
    {
      add_com ("fr", class_tui, _tuiShowFloat_command,
	       "Display only floating point registers\n");
      add_com ("gr", class_tui, _tuiShowGeneral_command,
	       "Display only general registers\n");
      add_com ("sr", class_tui, _tuiShowSpecial_command,
	       "Display only special registers\n");
      add_com ("+r", class_tui, _tuiScrollRegsForward_command,
	       "Scroll the registers window forward\n");
      add_com ("-r", class_tui, _tuiScrollRegsBackward_command,
	       "Scroll the register window backward\n");
      add_com ("tf", class_tui, _tuiToggleFloatRegs_command,
	       "Toggle between single and double precision floating point registers.\n");
      add_cmd (TUI_FLOAT_REGS_NAME_LOWER,
	       class_tui,
	       _tuiToggleFloatRegs_command,
	       "Toggle between single and double precision floating point \
registers.\n",
	       &togglelist);
    }

  return;
}				/* _initialize_tuiRegs */


/*****************************************
** STATIC LOCAL FUNCTIONS                 **
******************************************/

#if 0
static char *reg_names[] = REGISTER_NAMES;
#endif

/*
   ** _tuiRegisterName().
   **        Return the register name.
 */
static char *
#ifdef __STDC__
_tuiRegisterName (
		   int regNum)
#else
_tuiRegisterName (regNum)
     int regNum;
#endif
{
#if 0
  if (reg_names[regNum] != (char *) NULL && *(reg_names[regNum]) != (char) 0)
    return reg_names[regNum];
  else
    return ((char *) NULL);
#else
  return REGISTER_NAME(regNum);
#endif
}				/* tuiGetRegisterName */


/*
   ** _tuiRegisterFormat
   **        Function to format the register name and value into a buffer,
   **        suitable for printing or display
 */
static void
#ifdef __STDC__
_tuiRegisterFormat (
		     char *buf,
		     int bufLen,
		     int regNum,
		     TuiDataElementPtr dataElement,
		     enum precision_type precision)
#else
_tuiRegisterFormat (buf, bufLen, regNum, dataElement, precision)
     char *buf;
     int bufLen;
     int regNum;
     TuiDataElementPtr dataElement;
     enum precision_type precision;
#endif
{
  char tmpBuf[15];
  char *fmt;
  struct ui_file *stream;

  stream = tui_sfileopen (bufLen);
  pa_do_strcat_registers_info (regNum, 0, stream, precision);
  strcpy (buf, tui_file_get_strbuf (stream));
  ui_file_delete (stream);

  return;
}				/* _tuiRegisterFormat */


#define NUM_GENERAL_REGS    32
/*
   ** _tuiSetGeneralRegsContent().
   **      Set the content of the data window to consist of the general registers.
 */
static TuiStatus
#ifdef __STDC__
_tuiSetGeneralRegsContent (
			    int refreshValuesOnly)
#else
_tuiSetGeneralRegsContent (refreshValuesOnly)
     int refreshValuesOnly;
#endif
{
  return (_tuiSetRegsContent (0,
			      NUM_GENERAL_REGS - 1,
			      selected_frame,
			      TUI_GENERAL_REGS,
			      refreshValuesOnly));

}				/* _tuiSetGeneralRegsContent */


#define START_SPECIAL_REGS    /* PCOQ_HEAD_REGNUM */ 0
/*
   ** _tuiSetSpecialRegsContent().
   **      Set the content of the data window to consist of the special registers.
 */
static TuiStatus
#ifdef __STDC__
_tuiSetSpecialRegsContent (
			    int refreshValuesOnly)
#else
_tuiSetSpecialRegsContent (refreshValuesOnly)
     int refreshValuesOnly;
#endif
{
  TuiStatus ret = TUI_FAILURE;
  int i, endRegNum;

  endRegNum = FP0_REGNUM - 1;
#if 0
  endRegNum = (-1);
  for (i = START_SPECIAL_REGS; (i < ARCH_NUM_REGS && endRegNum < 0); i++)
    if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
      endRegNum = i - 1;
#endif
  ret = _tuiSetRegsContent (START_SPECIAL_REGS,
			    endRegNum,
			    selected_frame,
			    TUI_SPECIAL_REGS,
			    refreshValuesOnly);

  return ret;
}				/* _tuiSetSpecialRegsContent */


/*
   ** _tuiSetGeneralAndSpecialRegsContent().
   **      Set the content of the data window to consist of the special registers.
 */
static TuiStatus
#ifdef __STDC__
_tuiSetGeneralAndSpecialRegsContent (
				      int refreshValuesOnly)
#else
_tuiSetGeneralAndSpecialRegsContent (refreshValuesOnly)
     int refreshValuesOnly;
#endif
{
  TuiStatus ret = TUI_FAILURE;
  int i, endRegNum = (-1);

  endRegNum = FP0_REGNUM - 1;
#if 0
  endRegNum = (-1);
  for (i = 0; (i < ARCH_NUM_REGS && endRegNum < 0); i++)
    if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
      endRegNum = i - 1;
#endif
  ret = _tuiSetRegsContent (
	 0, endRegNum, selected_frame, TUI_SPECIAL_REGS, refreshValuesOnly);

  return ret;
}				/* _tuiSetGeneralAndSpecialRegsContent */

/*
   ** _tuiSetFloatRegsContent().
   **        Set the content of the data window to consist of the float registers.
 */
static TuiStatus
#ifdef __STDC__
_tuiSetFloatRegsContent (
			  TuiRegisterDisplayType dpyType,
			  int refreshValuesOnly)
#else
_tuiSetFloatRegsContent (dpyType, refreshValuesOnly)
     TuiRegisterDisplayType dpyType;
     int refreshValuesOnly;
#endif
{
  TuiStatus ret = TUI_FAILURE;
  int i, startRegNum;

  startRegNum = FP0_REGNUM;
#if 0
  startRegNum = (-1);
  for (i = ARCH_NUM_REGS - 1; (i >= 0 && startRegNum < 0); i--)
    if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) != TYPE_CODE_FLT)
      startRegNum = i + 1;
#endif
  ret = _tuiSetRegsContent (startRegNum,
			    ARCH_NUM_REGS - 1,
			    selected_frame,
			    dpyType,
			    refreshValuesOnly);

  return ret;
}				/* _tuiSetFloatRegsContent */


/*
   ** _tuiRegValueHasChanged().
   **        Answer TRUE if the register's value has changed, FALSE otherwise.
   **        If TRUE, newValue is filled in with the new value.
 */
static int
#ifdef __STDC__
_tuiRegValueHasChanged (
			 TuiDataElementPtr dataElement,
			 struct frame_info *frame,
			 char *newValue)
#else
_tuiRegValueHasChanged (dataElement, frame, newValue)
     TuiDataElementPtr dataElement;
     struct frame_info *frame;
     char *newValue;
#endif
{
  int hasChanged = FALSE;

  if (dataElement->itemNo != UNDEFINED_ITEM &&
      _tuiRegisterName (dataElement->itemNo) != (char *) NULL)
    {
      char rawBuf[MAX_REGISTER_RAW_SIZE];
      int i;

      if (_tuiGetRegisterRawValue (
			 dataElement->itemNo, rawBuf, frame) == TUI_SUCCESS)
	{
	  for (i = 0; (i < MAX_REGISTER_RAW_SIZE && !hasChanged); i++)
	    hasChanged = (((char *) dataElement->value)[i] != rawBuf[i]);
	  if (hasChanged && newValue != (char *) NULL)
	    {
	      for (i = 0; (i < MAX_REGISTER_RAW_SIZE); i++)
		newValue[i] = rawBuf[i];
	    }
	}
    }
  return hasChanged;
}				/* _tuiRegValueHasChanged */



/*
   ** _tuiGetRegisterRawValue().
   **        Get the register raw value.  The raw value is returned in regValue.
 */
static TuiStatus
#ifdef __STDC__
_tuiGetRegisterRawValue (
			  int regNum,
			  char *regValue,
			  struct frame_info *frame)
#else
_tuiGetRegisterRawValue (regNum, regValue, frame)
     int regNum;
     char *regValue;
     struct frame_info *frame;
#endif
{
  TuiStatus ret = TUI_FAILURE;

  if (target_has_registers)
    {
      read_relative_register_raw_bytes_for_frame (regNum, regValue, frame);
      ret = TUI_SUCCESS;
    }

  return ret;
}				/* _tuiGetRegisterRawValue */



/*
   ** _tuiSetRegisterElement().
   **       Function to initialize a data element with the input and
   **       the register value.
 */
static void
#ifdef __STDC__
_tuiSetRegisterElement (
			 int regNum,
			 struct frame_info *frame,
			 TuiDataElementPtr dataElement,
			 int refreshValueOnly)
#else
_tuiSetRegisterElement (regNum, frame, dataElement, refreshValueOnly)
     int regNum;
     struct frame_info *frame;
     TuiDataElementPtr dataElement;
     int refreshValueOnly;
#endif
{
  if (dataElement != (TuiDataElementPtr) NULL)
    {
      if (!refreshValueOnly)
	{
	  dataElement->itemNo = regNum;
	  dataElement->name = _tuiRegisterName (regNum);
	  dataElement->highlight = FALSE;
	}
      if (dataElement->value == (Opaque) NULL)
	dataElement->value = (Opaque) xmalloc (MAX_REGISTER_RAW_SIZE);
      if (dataElement->value != (Opaque) NULL)
	_tuiGetRegisterRawValue (regNum, dataElement->value, frame);
    }

  return;
}				/* _tuiSetRegisterElement */


/*
   ** _tuiSetRegsContent().
   **        Set the content of the data window to consist of the registers
   **        numbered from startRegNum to endRegNum.  Note that if
   **        refreshValuesOnly is TRUE, startRegNum and endRegNum are ignored.
 */
static TuiStatus
#ifdef __STDC__
_tuiSetRegsContent (
		     int startRegNum,
		     int endRegNum,
		     struct frame_info *frame,
		     TuiRegisterDisplayType dpyType,
		     int refreshValuesOnly)
#else
_tuiSetRegsContent (startRegNum, endRegNum, frame, dpyType, refreshValuesOnly)
     int startRegNum;
     int endRegNum;
     struct frame_info *frame;
     TuiRegisterDisplayType dpyType;
     int refreshValuesOnly;
#endif
{
  TuiStatus ret = TUI_FAILURE;
  int numRegs = endRegNum - startRegNum + 1;
  int allocatedHere = FALSE;

  if (dataWin->detail.dataDisplayInfo.regsContentCount > 0 &&
      !refreshValuesOnly)
    {
      freeDataContent (dataWin->detail.dataDisplayInfo.regsContent,
		       dataWin->detail.dataDisplayInfo.regsContentCount);
      dataWin->detail.dataDisplayInfo.regsContentCount = 0;
    }
  if (dataWin->detail.dataDisplayInfo.regsContentCount <= 0)
    {
      dataWin->detail.dataDisplayInfo.regsContent =
	allocContent (numRegs, DATA_WIN);
      allocatedHere = TRUE;
    }

  if (dataWin->detail.dataDisplayInfo.regsContent != (TuiWinContent) NULL)
    {
      int i;

      if (!refreshValuesOnly || allocatedHere)
	{
	  dataWin->generic.content = (OpaquePtr) NULL;
	  dataWin->generic.contentSize = 0;
	  addContentElements (&dataWin->generic, numRegs);
	  dataWin->detail.dataDisplayInfo.regsContent =
	    (TuiWinContent) dataWin->generic.content;
	  dataWin->detail.dataDisplayInfo.regsContentCount = numRegs;
	}
      /*
         ** Now set the register names and values
       */
      for (i = startRegNum; (i <= endRegNum); i++)
	{
	  TuiGenWinInfoPtr dataItemWin;

	  dataItemWin = &dataWin->detail.dataDisplayInfo.
	    regsContent[i - startRegNum]->whichElement.dataWindow;
	  _tuiSetRegisterElement (
				   i,
				   frame,
	   &((TuiWinElementPtr) dataItemWin->content[0])->whichElement.data,
				   !allocatedHere && refreshValuesOnly);
	}
      dataWin->detail.dataDisplayInfo.regsColumnCount =
	tuiCalculateRegsColumnCount (dpyType);
#ifdef LATER
      if (dataWin->detail.dataDisplayInfo.dataContentCount > 0)
	{
	  /* delete all the windows? */
	  /* realloc content equal to dataContentCount + regsContentCount */
	  /* append dataWin->detail.dataDisplayInfo.dataContent to content */
	}
#endif
      dataWin->generic.contentSize =
	dataWin->detail.dataDisplayInfo.regsContentCount +
	dataWin->detail.dataDisplayInfo.dataContentCount;
      ret = TUI_SUCCESS;
    }

  return ret;
}				/* _tuiSetRegsContent */


/*
   ** _tuiDisplayRegister().
   **        Function to display a register in a window.  If hilite is TRUE,
   **        than the value will be displayed in reverse video
 */
static void
#ifdef __STDC__
_tuiDisplayRegister (
		      int regNum,
		      TuiGenWinInfoPtr winInfo,		/* the data item window */
		      enum precision_type precision)
#else
_tuiDisplayRegister (regNum, winInfo, precision)
     int regNum;
     TuiGenWinInfoPtr winInfo;	/* the data item window */
     enum precision_type precision;
#endif
{
  if (winInfo->handle != (WINDOW *) NULL)
    {
      char buf[100];
      int valueCharsWide, labelWidth;
      TuiDataElementPtr dataElementPtr = &((TuiWinContent)
				    winInfo->content)[0]->whichElement.data;

      if (IS_64BIT ||
	  dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_DFLOAT_REGS)
	{
	  valueCharsWide = DOUBLE_FLOAT_VALUE_WIDTH;
	  labelWidth = DOUBLE_FLOAT_LABEL_WIDTH;
	}
      else
	{
	  if (dataWin->detail.dataDisplayInfo.regsDisplayType ==
	      TUI_SFLOAT_REGS)
	    {
	      valueCharsWide = SINGLE_FLOAT_VALUE_WIDTH;
	      labelWidth = SINGLE_FLOAT_LABEL_WIDTH;
	    }
	  else
	    {
	      valueCharsWide = SINGLE_VALUE_WIDTH;
	      labelWidth = SINGLE_LABEL_WIDTH;
	    }
	}

      buf[0] = (char) 0;
      _tuiRegisterFormat (buf,
			  valueCharsWide + labelWidth,
			  regNum,
			  dataElementPtr,
			  precision);
      if (dataElementPtr->highlight)
	wstandout (winInfo->handle);

      werase (winInfo->handle);
      wmove (winInfo->handle, 0, 0);
      waddstr (winInfo->handle, buf);

      if (dataElementPtr->highlight)
	wstandend (winInfo->handle);
      tuiRefreshWin (winInfo);
    }
  return;
}				/* _tuiDisplayRegister */


static void
#ifdef __STDC__
_tui_vShowRegisters_commandSupport (
				     va_list args)
#else
_tui_vShowRegisters_commandSupport (args)
     va_list args;
#endif
{
  TuiRegisterDisplayType dpyType = va_arg (args, TuiRegisterDisplayType);

  if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
    {				/* Data window already displayed, show the registers */
      if (dataWin->detail.dataDisplayInfo.regsDisplayType != dpyType)
	tuiShowRegisters (dpyType);
    }
  else
    (tuiLayoutDef ())->regsDisplayType = dpyType;

  return;
}				/* _tui_vShowRegisters_commandSupport */


static void
#ifdef __STDC__
_tuiShowFloat_command (
			char *arg,
			int fromTTY)
#else
_tuiShowFloat_command (arg, fromTTY)
     char *arg;
     int fromTTY;
#endif
{
  if (m_winPtrIsNull (dataWin) || !dataWin->generic.isVisible ||
      (dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_SFLOAT_REGS &&
       dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_DFLOAT_REGS))
    tuiDo ((TuiOpaqueFuncPtr) _tui_vShowRegisters_commandSupport,
	   (tuiLayoutDef ())->floatRegsDisplayType);

  return;
}				/* _tuiShowFloat_command */


static void
#ifdef __STDC__
_tuiShowGeneral_command (
			  char *arg,
			  int fromTTY)
#else
_tuiShowGeneral_command (arg, fromTTY)
     char *arg;
     int fromTTY;
#endif
{
  tuiDo ((TuiOpaqueFuncPtr) _tui_vShowRegisters_commandSupport,
	 TUI_GENERAL_REGS);

  return;
}				/* _tuiShowGeneral_command */


static void
#ifdef __STDC__
_tuiShowSpecial_command (
			  char *arg,
			  int fromTTY)
#else
_tuiShowSpecial_command (arg, fromTTY)
     char *arg;
     int fromTTY;
#endif
{
  tuiDo ((TuiOpaqueFuncPtr) _tui_vShowRegisters_commandSupport,
	 TUI_SPECIAL_REGS);

  return;
}				/* _tuiShowSpecial_command */


static void
#ifdef __STDC__
_tuiToggleFloatRegs_command (
			      char *arg,
			      int fromTTY)
#else
_tuiToggleFloatRegs_command (arg, fromTTY)
     char *arg;
     int fromTTY;
#endif
{
  if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
    tuiDo ((TuiOpaqueFuncPtr) tuiToggleFloatRegs);
  else
    {
      TuiLayoutDefPtr layoutDef = tuiLayoutDef ();

      if (layoutDef->floatRegsDisplayType == TUI_SFLOAT_REGS)
	layoutDef->floatRegsDisplayType = TUI_DFLOAT_REGS;
      else
	layoutDef->floatRegsDisplayType = TUI_SFLOAT_REGS;
    }


  return;
}				/* _tuiToggleFloatRegs_command */


static void
#ifdef __STDC__
_tuiScrollRegsForward_command (
				char *arg,
				int fromTTY)
#else
_tuiScrollRegsForward_command (arg, fromTTY)
     char *arg;
     int fromTTY;
#endif
{
  tuiDo ((TuiOpaqueFuncPtr) tui_vScroll, FORWARD_SCROLL, dataWin, 1);

  return;
}				/* _tuiScrollRegsForward_command */


static void
#ifdef __STDC__
_tuiScrollRegsBackward_command (
				 char *arg,
				 int fromTTY)
#else
_tuiScrollRegsBackward_command (arg, fromTTY)
     char *arg;
     int fromTTY;
#endif
{
  tuiDo ((TuiOpaqueFuncPtr) tui_vScroll, BACKWARD_SCROLL, dataWin, 1);

  return;
}				/* _tuiScrollRegsBackward_command */
