/* Data/register window display.

   Copyright (C) 1998-2004, 2007-2012 Free Software Foundation, Inc.

   Contributed by Hewlett-Packard Company.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "tui/tui.h"
#include "tui/tui-data.h"
#include "tui/tui-wingeneral.h"
#include "tui/tui-regs.h"
#include "tui/tui-windata.h"

#include "gdb_string.h"
#include "gdb_curses.h"


/*****************************************
** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
******************************************/



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


/* Answer the index first element displayed.  If none are displayed,
   then return (-1).  */
int
tui_first_data_item_displayed (void)
{
  int element_no = (-1);
  int i;

  for (i = 0; 
       i < TUI_DATA_WIN->generic.content_size && element_no < 0;
       i++)
    {
      struct tui_gen_win_info *data_item_win;

      data_item_win = &((tui_win_content)
			TUI_DATA_WIN->generic.content)[i]->which_element.data_window;
      if (data_item_win->handle != (WINDOW *) NULL 
	  && data_item_win->is_visible)
	element_no = i;
    }

  return element_no;
}


/* Answer the index of the first element in line_no.  If line_no is
   past the data area (-1) is returned.  */
int
tui_first_data_element_no_in_line (int line_no)
{
  int first_element_no = (-1);

  /* First see if there is a register on line_no, and if so, set the
     first element number.  */
  if ((first_element_no = tui_first_reg_element_no_inline (line_no)) == -1)
    { /* Looking at the general data, the 1st element on line_no.  */
    }

  return first_element_no;
}


/* Function to delete all the item windows in the data window.  This
   is usually done when the data window is scrolled.  */
void
tui_delete_data_content_windows (void)
{
  int i;
  struct tui_gen_win_info *data_item_win_ptr;

  for (i = 0; (i < TUI_DATA_WIN->generic.content_size); i++)
    {
      data_item_win_ptr = &((tui_win_content)
			    TUI_DATA_WIN->generic.content)[i]->which_element.data_window;
      tui_delete_win (data_item_win_ptr->handle);
      data_item_win_ptr->handle = (WINDOW *) NULL;
      data_item_win_ptr->is_visible = FALSE;
    }
}


void
tui_erase_data_content (char *prompt)
{
  werase (TUI_DATA_WIN->generic.handle);
  tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
  if (prompt != (char *) NULL)
    {
      int half_width = (TUI_DATA_WIN->generic.width - 2) / 2;
      int x_pos;

      if (strlen (prompt) >= half_width)
	x_pos = 1;
      else
	x_pos = half_width - strlen (prompt);
      mvwaddstr (TUI_DATA_WIN->generic.handle,
		 (TUI_DATA_WIN->generic.height / 2),
		 x_pos,
		 prompt);
    }
  wrefresh (TUI_DATA_WIN->generic.handle);
}


/* This function displays the data that is in the data window's
   content.  It does not set the content.  */
void
tui_display_all_data (void)
{
  if (TUI_DATA_WIN->generic.content_size <= 0)
    tui_erase_data_content (NO_DATA_STRING);
  else
    {
      tui_erase_data_content ((char *) NULL);
      tui_delete_data_content_windows ();
      tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
      tui_display_registers_from (0);

      /* Then display the other data.  */
      if (TUI_DATA_WIN->detail.data_display_info.data_content !=
	  (tui_win_content) NULL 
	  && TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
	{
	}
    }
}


/* Function to display the data starting at line, line_no, in the data
   window.  */
void
tui_display_data_from_line (int line_no)
{
  int _line_no = line_no;

  if (line_no < 0)
    _line_no = 0;

  tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);

  /* There is no general data, force regs to display (if there are
     any).  */
  if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0)
    tui_display_registers_from_line (_line_no, TRUE);
  else
    {
      int regs_last_line = tui_last_regs_line_no ();


      /* Display regs if we can.  */
      if (tui_display_registers_from_line (_line_no, FALSE) < 0)
	{ /* _line_no is past the regs display, so calc where the
	     start data element is.  */
	  if (regs_last_line < _line_no)
	    { /* Figure out how many lines each element is to obtain
		 the start element_no.  */
	    }
	}
      else
	{ /* Calculate the starting element of the data display, given
	     regs_last_line and how many lines each element is, up to
	     _line_no.  */
	}
      /* Now display the data , starting at element_no.  */
    }
}


/* Display data starting at element element_no.  */
void
tui_display_data_from (int element_no, int reuse_windows)
{
  int first_line = (-1);

  if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
    first_line = tui_line_from_reg_element_no (element_no);
  else
    { /* Calculate the first_line from the element number.  */
    }

  if (first_line >= 0)
    {
      tui_erase_data_content ((char *) NULL);
      if (!reuse_windows)
	tui_delete_data_content_windows ();
      tui_display_data_from_line (first_line);
    }
}


/* Function to redisplay the contents of the data window.  */
void
tui_refresh_data_win (void)
{
  tui_erase_data_content ((char *) NULL);
  if (TUI_DATA_WIN->generic.content_size > 0)
    {
      int first_element = tui_first_data_item_displayed ();

      if (first_element >= 0)	/* Re-use existing windows.  */
	tui_display_data_from (first_element, TRUE);
    }
}


/* Function to check the data values and hilite any that have
   changed.  */
void
tui_check_data_values (struct frame_info *frame)
{
  tui_check_register_values (frame);

  /* Now check any other data values that there are.  */
  if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
    {
      int i;

      for (i = 0; 
	   TUI_DATA_WIN->detail.data_display_info.data_content_count; 
	   i++)
	{
#ifdef LATER
	  tui_data_element_ptr data_element_ptr;
	  struct tui_gen_win_info *data_item_win_ptr;
	  Opaque new_value;

	  data_item_ptr = &TUI_DATA_WIN->detail.data_display_info.
	    data_content[i]->which_element.data_window;
	  data_element_ptr = &((tui_win_content)
			       data_item_win_ptr->content)[0]->which_element.data;
	  if value
	    has changed (data_element_ptr, frame, &new_value)
	    {
	      data_element_ptr->value = new_value;
	      update the display with the new value, hiliting it.
	    }
#endif
	}
    }
}


/* Scroll the data window vertically forward or backward.  */
void
tui_vertical_data_scroll (enum tui_scroll_direction scroll_direction,
			  int num_to_scroll)
{
  int first_element_no;
  int first_line = (-1);

  first_element_no = tui_first_data_item_displayed ();
  if (first_element_no 
      < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
    first_line = tui_line_from_reg_element_no (first_element_no);
  else
    { /* Calculate the first line from the element number which is in
        the general data content.  */
    }

  if (first_line >= 0)
    {
      if (scroll_direction == FORWARD_SCROLL)
	first_line += num_to_scroll;
      else
	first_line -= num_to_scroll;
      tui_erase_data_content ((char *) NULL);
      tui_delete_data_content_windows ();
      tui_display_data_from_line (first_line);
    }
}


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