/* TN5250 - An implementation of the 5250 telnet protocol.
 * Copyright (C) 2005 James Rich
 * 
 * This file is part of TN5250.
 *
 * TN5250 is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1, or (at your option)
 * any later version.
 * 
 * TN5250 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA
 * 
 */
#include "tn5250-private.h"

Tn5250Menubar *
tn5250_menubar_new ()
{
  Tn5250Menubar *This = tn5250_new (Tn5250Menubar, 1);
  if (This == NULL)
    {
      return NULL;
    }
  memset (This, 0, sizeof (Tn5250Menubar));
  This->next = NULL;
  This->prev = NULL;
  This->menuitem_list = NULL;
  This->menuitem_count = 0;
  This->table = NULL;
  This->id = -1;
  return (This);
}


Tn5250Menubar *
tn5250_menubar_copy (Tn5250Menubar * This)
{
  Tn5250Menubar *menu = tn5250_new (Tn5250Menubar, 1);

  if (menu == NULL)
    {
      return NULL;
    }
  memcpy (menu, This, sizeof (Tn5250Menubar));
  menu->next = NULL;
  menu->prev = NULL;
  return menu;
}


void
tn5250_menubar_destroy (Tn5250Menubar * This)
{
  free (This);
}


Tn5250Menubar *
tn5250_menubar_list_destroy (Tn5250Menubar * list)
{
  Tn5250Menubar *iter, *next;

  if ((iter = list) != NULL)
    {
      do
	{
	  next = iter->next;
	  tn5250_menubar_destroy (iter);
	  iter = next;
	}
      while (iter != list);
    }
  return NULL;
}


Tn5250Menubar *
tn5250_menubar_list_add (Tn5250Menubar * list, Tn5250Menubar * node)
{
  node->prev = node->next = NULL;

  if (list == NULL)
    {
      node->next = node->prev = node;
      return node;
    }
  node->next = list;
  node->prev = list->prev;
  node->prev->next = node;
  node->next->prev = node;
  return list;
}


Tn5250Menubar *
tn5250_menubar_list_remove (Tn5250Menubar * list, Tn5250Menubar * node)
{
  if (list == NULL)
    {
      return NULL;
    }
  if ((list->next == list) && (list == node))
    {
      node->next = node->prev = NULL;
      return NULL;
    }
  if (list == node)
    {
      list = list->next;
    }

  node->next->prev = node->prev;
  node->prev->next = node->next;
  node->prev = node->next = NULL;
  return list;
}


Tn5250Menubar *
tn5250_menubar_list_find_by_id (Tn5250Menubar * list, int id)
{
  Tn5250Menubar *iter;

  if ((iter = list) != NULL)
    {
      do
	{
	  if (iter->id == id)
	    {
	      return iter;
	    }
	  iter = iter->next;
	}
      while (iter != list);
    }
  return NULL;
}


Tn5250Menubar *
tn5250_menubar_list_copy (Tn5250Menubar * This)
{
  Tn5250Menubar *new_list = NULL, *iter, *new_menubar;
  if ((iter = This) != NULL)
    {
      do
	{
	  new_menubar = tn5250_menubar_copy (iter);
	  if (new_menubar != NULL)
	    {
	      new_list = tn5250_menubar_list_add (new_list, new_menubar);
	    }
	  iter = iter->next;
	}
      while (iter != This);
    }
  return new_list;
}


Tn5250Menubar *
tn5250_menubar_hit_test (Tn5250Menubar * list, int x, int y)
{
  Tn5250Menubar *iter;

  if ((iter = list) != NULL)
    {
      do
	{
	  /* We want to find a hit for any column in the menubar row */
	  /*
	   * if ((x >= iter->column)
	   *   && (x <= (iter->column + (iter->itemsize * iter->items)))
	   *   && (y >= iter->row) && (y <= (iter->row + iter->height - 1)))
	   */
	  if ((y >= iter->row) && (y <= (iter->row + iter->height - 1)))
	    {
	      return iter;
	    }
	  iter = iter->next;
	}
      while (iter != list);
    }
  return NULL;
}


void
tn5250_menubar_select_next (Tn5250Menubar * This, int *x, int *y)
{
  Tn5250Menuitem *menuitem =
    tn5250_menuitem_hit_test (This->menuitem_list, *x, *y);

  if (menuitem == NULL)
    {
      menuitem = This->menuitem_list->prev;
    }

  menuitem->selected = 0;
  menuitem = menuitem->next;
  menuitem->selected = 1;
  *y = tn5250_menuitem_start_row (menuitem);
  *x = tn5250_menuitem_start_col (menuitem);
  return;
}


void
tn5250_menubar_select_prev (Tn5250Menubar * This, int *x, int *y)
{
  Tn5250Menuitem *menuitem =
    tn5250_menuitem_hit_test (This->menuitem_list, *x, *y);

  if (menuitem == NULL)
    {
      menuitem = This->menuitem_list;
    }

  menuitem->selected = 0;
  menuitem = menuitem->prev;
  menuitem->selected = 1;
  *y = tn5250_menuitem_start_row (menuitem);
  *x = tn5250_menuitem_start_col (menuitem);
  return;
}


/***** lib5250/tn5250_menu_add_menuitem
 * NAME
 *    tn5250_menu_add_menuitem
 * SYNOPSIS
 *    tn5250_menu_add_menuitem (This, menuitem);
 * INPUTS
 *    Tn5250Menubar *      This       -
 *    Tn5250Menuitem *     menuitem   -
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
void
tn5250_menu_add_menuitem (Tn5250Menubar * This, Tn5250Menuitem * menuitem)
{
  menuitem->id = This->menuitem_count++;
  menuitem->menubar = This;
  This->menuitem_list = tn5250_menuitem_list_add (This->menuitem_list,
						  menuitem);

  TN5250_LOG (("adding menu item: menuitem->id: %d\n", menuitem->id));
  return;
}


Tn5250Menuitem *
tn5250_menuitem_new ()
{
  Tn5250Menuitem *This = tn5250_new (Tn5250Menuitem, 1);
  if (This == NULL)
    {
      return NULL;
    }
  memset (This, 0, sizeof (Tn5250Menuitem));
  This->next = NULL;
  This->prev = NULL;
  This->id = -1;
  This->size = 0;
  This->available = 0;
  This->selected = 0;
  return (This);
}


Tn5250Menuitem *
tn5250_menuitem_list_add (Tn5250Menuitem * list, Tn5250Menuitem * node)
{
  node->prev = node->next = NULL;

  if (list == NULL)
    {
      node->next = node->prev = node;
      return node;
    }
  node->next = list;
  node->prev = list->prev;
  node->prev->next = node;
  node->next->prev = node;
  return list;
}


Tn5250Menuitem *
tn5250_menuitem_list_remove (Tn5250Menuitem * list, Tn5250Menuitem * node)
{
  if (list == NULL)
    {
      return NULL;
    }
  if ((list->next == list) && (list == node))
    {
      node->next = node->prev = NULL;
      return NULL;
    }
  if (list == node)
    {
      list = list->next;
    }

  node->next->prev = node->prev;
  node->prev->next = node->next;
  node->prev = node->next = NULL;
  return list;
}


int
tn5250_menuitem_new_row (Tn5250Menuitem * This)
{
  unsigned char menutype = tn5250_menubar_type (This->menubar);

  switch (menutype)
    {
    case MENU_TYPE_MENUBAR:
      if (This->prev == This)
	{
	  return (This->menubar->row);
	}
      else
	{
	  return (This->prev->row);
	}
      break;
    case MENU_TYPE_SINGLE_SELECT_FIELD:
    case MENU_TYPE_MULTIPLE_SELECT_FIELD:
    case MENU_TYPE_SINGLE_SELECT_LIST:
    case MENU_TYPE_MULTIPLE_SELECT_LIST:
    case MENU_TYPE_SINGLE_SELECT_FIELD_PULL_DOWN:
    case MENU_TYPE_MULTIPLE_SELECT_FIELD_PULL_DOWN:
    case MENU_TYPE_PUSH_BUTTONS:
    case MENU_TYPE_PUSH_BUTTONS_PULL_DOWN:
      if (This->prev == This)
	{
	  return (This->menubar->row);
	}
      else
	{
	  return (This->prev->row + 1);
	}
      break;
    default:
      TN5250_LOG (("Invalid selection field type!!\n"));
      break;
    }
  return 0;
}


int
tn5250_menuitem_new_col (Tn5250Menuitem * This)
{
  unsigned char menutype = tn5250_menubar_type (This->menubar);

  switch (menutype)
    {
    case MENU_TYPE_MENUBAR:
      if (This->prev == This)
	{
	  return (This->menubar->column + 1);
	}
      else
	{
	  return (This->prev->column + This->prev->size + 1);
	}
      break;
    case MENU_TYPE_SINGLE_SELECT_FIELD:
    case MENU_TYPE_MULTIPLE_SELECT_FIELD:
    case MENU_TYPE_SINGLE_SELECT_LIST:
    case MENU_TYPE_MULTIPLE_SELECT_LIST:
    case MENU_TYPE_SINGLE_SELECT_FIELD_PULL_DOWN:
    case MENU_TYPE_MULTIPLE_SELECT_FIELD_PULL_DOWN:
    case MENU_TYPE_PUSH_BUTTONS:
    case MENU_TYPE_PUSH_BUTTONS_PULL_DOWN:
      return (This->menubar->column + 1);
      break;
    default:
      TN5250_LOG (("Invalid selection field type!!\n"));
      break;
    }
  return 0;
}


Tn5250Menuitem *
tn5250_menuitem_list_find_by_id (Tn5250Menuitem * list, int id)
{
  Tn5250Menuitem *iter;

  if ((iter = list) != NULL)
    {
      do
	{
	  if (iter->id == id)
	    {
	      return iter;
	    }
	  iter = iter->next;
	}
      while (iter != list);
    }
  return NULL;
}


Tn5250Menuitem *
tn5250_menuitem_hit_test (Tn5250Menuitem * list, int x, int y)
{
  Tn5250Menuitem *iter;

  if ((iter = list) != NULL)
    {
      do
	{
	  if ((x >= iter->column) && (x <= (iter->column + iter->size))
	      && (iter->row == y))
	    {
	      return iter;
	    }
	  iter = iter->next;
	}
      while (iter != list);
    }
  return NULL;
}


syntax highlighted by Code2HTML, v. 0.9.1