/****************************************************************************************************************
 *
 *  Copyright (c) 1992 by Antoine Dumesnil de Maricourt. All rights reserved.
 *
 *  This program is distributed in the hope that it will be useful.
 *  Use and copying of this software and preparation of derivative works
 *  based upon this software are permitted, so long as the following
 *  conditions are met:
 *       o credit to the authors is acknowledged following current
 *         academic behaviour
 *       o no fees or compensation are charged for use, copies, or
 *         access to this software
 *       o this copyright notice is included intact.
 *  This software is made available AS IS, and no warranty is made about 
 *  the software or its performance. 
 * 
 *  Bug descriptions, use reports, comments or suggestions are welcome.
 *  Send them to    dumesnil@etca.fr   or to:
 *       
 *       Antoine de Maricourt
 *       ETCA CREA-SP
 *       16 bis, avenue Prieur de la Cote d'Or
 *       94114 Arcueil Cedex
 *       France
 */

#include "xgoban.h"

#include <X11/Shell.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

/*******************************************************************************************************
 */

void ShowTmpProperty (node)
SG_NodePtr node;
{
  SG_NodePtr     tmp;
  char           mark     = 'A';
  char           letter   = 'a';
  Position       x;
  Position       y;
  SG_PropertyPtr property;
  unsigned char *ptr;
  Arg            arg;

  if (node != NULL) {
    property = node->property;
    
    while (property != NULL) {

      switch (property->id) {
	
      case SG_Comment :
	if (property->data.pvalue != NULL)
	  { XtSetArg (arg, XtNstring, (XtArgVal) property->data.pvalue); XtSetValues (c_comment, &arg, 1); }
	break;

      case SG_Letters :
	if ((ptr = property->data.pvalue) != NULL) {

	  while (*ptr != SG_EOS) {
	    x = (*ptr++ & 0x3f);
	    y = (*ptr++ & 0x3f);
	    
	    if (x != 0 || y != 0) {
	      GbSetMark (w_goban, x, y, letter, 0);
	      if (w_second_goban != NULL) 
		GbSetMark (w_second_goban, x, y, letter, 0);
	      letter++;
	    }
	  }
	}
	break;

      case SG_Marked :
	if ((ptr = property->data.pvalue) != NULL) {

	  while (*ptr != SG_EOS) {
	    x = (*ptr++ & 0x3f);
	    y = (*ptr++ & 0x3f);
	    
	    if (x != 0 || y != 0) {
	      GbSetMark (w_goban, x, y, 0, GbMTriangleMark);
	      if (w_second_goban != NULL) 
		GbSetMark (w_second_goban, x, y, 0, GbMTriangleMark);
	    }
	  }
	}
	break;

      case SG_nodeName :

	if (property->data.pvalue != NULL) {
	  XtSetArg (arg, XtNtitle, (XtArgVal) property->data.pvalue); 
	  XtSetValues (c_toplevel, &arg, 1);
	}
	break;

      case SG_GameName :

	if (property->data.pvalue != NULL) {
	  XtSetArg (arg, XtNtitle, (XtArgVal) property->data.pvalue); 
	  XtSetValues (w_toplevel, &arg, 1);
	}
	break;
      }

      property = property->next;
    }

    switch (node->type) {
      
    case SG_EventType   :
    case SG_DiagramType :
      break;
      
    case SG_MoveType :
      tmp = node;

      while (tmp->left != NULL)
	tmp = tmp->left;
      
      if (tmp->right != NULL)
	while (tmp != NULL) {
	  if (tmp->type == SG_MoveType && tmp->color == node->color && tmp->x != 0 && tmp->y != 0) {
	    GbSetMark (w_goban, tmp->x, tmp->y, mark, 0);
	    
	    if (w_second_goban != NULL) 
	      GbSetMark (w_second_goban, tmp->x, tmp->y, mark, 0);
	  }
	  
	  mark++;
	  tmp = tmp->right;
	}
      
      else if (autonum == TRUE) {
	GbSetNum   (w_goban, node->x, node->y, node->num);

	if (w_second_goban != NULL) 
	  GbSetNum   (w_second_goban, node->x, node->y, node->num);
      }

      break;
    }
  }

  ShowCursor (node);
}

/*******************************************************************************************************
 */

void ShowProperty (node)
SG_NodePtr node;
{
  unsigned char *setup;
  int            color;
  int            x;
  int            y;
  int            view = 0;
  SG_PropertyPtr property;
  Position       top;
  Position       left;
  Position       bottom;
  Position       right;
  Arg            args[4];
  long           value;

  if (node != NULL) {
    property = node->property;
    
    while (property != NULL) {
      switch (property->id) {
	
      case SG_SiZe :
	XtSetArg (args[0], XtNgameSize, property->data.ivalue); 
	XtSetValues (w_goban, args, 1);
	if (w_second_goban != NULL) 
	  XtSetValues (w_second_goban, args, 1);
	break;
	
      case SG_GameName : 
	if (property->data.pvalue != NULL) {
	  XtSetArg (args[0], XtNtitle, property->data.pvalue); 
	  XtSetValues (w_goban, args, 1);
	  if (w_second_goban != NULL) 
	    XtSetValues (w_second_goban, args, 1);
	}
	break;
	
      case SG_VieW :
	XtSetArg (args[0], XtNviewTop   , &top   );
	XtSetArg (args[1], XtNviewLeft  , &left  );
	XtSetArg (args[2], XtNviewBottom, &bottom);
	XtSetArg (args[3], XtNviewRight , &right );

	XtGetValues (w_goban, args, 4);
	if (w_second_goban != NULL) 
	  XtGetValues (w_second_goban, args, 4);

	value = ((long) top << 24) + ((long) left << 16) + ((long) bottom << 8) + ((long) right);

	SG_MakeProperty (node, SG_unVieW, value);
	
	XtSetArg (args[0], XtNviewTop   , (Position) ((property->data.ivalue >> 24))       );
	XtSetArg (args[1], XtNviewLeft  , (Position) ((property->data.ivalue >> 16) & 0xff));
	XtSetArg (args[2], XtNviewBottom, (Position) ((property->data.ivalue >>  8) & 0xff));
	XtSetArg (args[3], XtNviewRight , (Position) ((property->data.ivalue      ) & 0xff));
	
	XtSetValues (w_goban, args, 4);
	if (w_second_goban != NULL) 
	  XtSetValues (w_second_goban, args, 4);
	
	view++;

	break;
      }
      
      property = property->next;
    }
    
    switch (node->type) {
      
    case SG_EventType   :
      GbClearBoard (w_goban);
      if (w_second_goban != NULL) 
	GbClearBoard (w_second_goban);

      if (view == 0) {
	XtSetArg (args[0], XtNviewTop   , 19);
	XtSetArg (args[1], XtNviewLeft  ,  0);
	XtSetArg (args[2], XtNviewBottom,  0);
	XtSetArg (args[3], XtNviewRight , 19);
	
	XtSetValues (w_goban, args, 4);
	if (w_second_goban != NULL) 
	  XtSetValues (w_second_goban, args, 4);
      }

    case SG_DiagramType :
      if ((setup = node->setup) != NULL)
	while (*setup != SG_EOS) {
	  color = (*setup & 0xc0);
	  x     = (*setup++ & 0x3f);
	  y     = (*setup++ & 0x3f);
	  
	  switch (color) {
	  case SG_SETB  : GbSetPoint (w_goban, x, y, GbBlackStone); break;
	  case SG_SETW  : GbSetPoint (w_goban, x, y, GbWhiteStone); break;
	  case SG_SETEB :
	  case SG_SETEW : GbSetPoint (w_goban, x, y, GbEmptyPoint); break;
	  }

	  if (w_second_goban != NULL) 
	    switch (color) {
	    case SG_SETB  : GbSetPoint (w_second_goban, x, y, GbBlackStone); break;
	    case SG_SETW  : GbSetPoint (w_second_goban, x, y, GbWhiteStone); break;
	    case SG_SETEB :
	    case SG_SETEW : GbSetPoint (w_second_goban, x, y, GbEmptyPoint); break;
	    }
	}
      break;
      
    case SG_MoveType :
      x     = node->x;
      y     = node->y;
      color = (int) ((node->color == SG_BlackStone) ? GbBlackStone : GbWhiteStone);

      GbSetPoint (w_goban, x, y, color);
      if (w_second_goban != NULL)       
	GbSetPoint (w_second_goban, x, y, color);

      if ((setup = node->setup) != NULL)
	while (*setup != SG_EOS) {
	  x     = (*setup++ & 0x3f);
	  y     = (*setup++ & 0x3f);
	  
	  GbSetPoint (w_goban, x, y, GbEmptyPoint);
	  if (w_second_goban != NULL) 
	    GbSetPoint (w_second_goban, x, y, GbEmptyPoint);
	}
	
      break;
    }
    
    ShowTmpProperty  (node);
  }
}

/*******************************************************************************************************
 */

void HideTmpProperty (node)
SG_NodePtr node;
{
  SG_PropertyPtr  property;
  String          text;
  unsigned char  *ptr;
  int             x;
  int             y;
  Arg             arg;

  if (edit == True) {
    XtSetArg (arg, XtNstring, &text); XtGetValues (c_comment, &arg, 1);

    if (node != NULL) {
      property = SG_GetProperty (node, SG_Comment);

      if (property != NULL && strcmp (property->data.pvalue, text) != 0) {
	SG_strcpy (&property->data.pvalue, text, '\0');
	modified = True;
      }

      else if (strcmp (text, "") != 0 && property == NULL) {
	SG_MakeProperty (node, SG_Comment, text);
	modified = True;
      }
    }
  }

  if (node != NULL) {
    property = node->property;

    while (property != NULL) {
      switch (property->id) {
	
      case SG_Comment  : XtSetArg (arg, XtNstring, (XtArgVal) ""); XtSetValues (c_comment , &arg, 1); break;
      case SG_nodeName : XtSetArg (arg, XtNtitle , (XtArgVal) ""); XtSetValues (c_toplevel, &arg, 1); break;
      case SG_GameName : 
	XtSetArg (arg, XtNtitle , (XtArgVal) ApplicationName); XtSetValues (w_toplevel, &arg, 1); break;

      case SG_Marked   :
      case SG_Letters  :
	if ((ptr = property->data.pvalue) != NULL) {

	  while (*ptr != SG_EOS) {
	    x = (*ptr++ & 0x3f);
	    y = (*ptr++ & 0x3f);
	    
	    if (x != 0 || y != 0) {
	      GbSetMark (w_goban, x, y, 0, 0);
	      if (w_second_goban != NULL) 
		GbSetMark (w_second_goban, x, y, 0, 0);
	    }
	  }
	}
	break;
      }
      
      property = property->next;
    }
    
    switch (node->type) {
      
    case SG_MoveType    :
      while (node->left != NULL)
	node = node->left;
      
      while (node != NULL) {
	if (node->type == SG_MoveType) {
	  GbSetMark (w_goban, node->x, node->y, 0, 0);

	  if (w_second_goban != NULL) 
	    GbSetMark (w_second_goban, node->x, node->y, 0, 0);
	}
	
	node = node->right;
      } 

      break;
    }
  }
}

/*******************************************************************************************************
 */

void HideProperty (node)
SG_NodePtr node;
{
  Arg            args[5];
  unsigned char *setup;
  int            color;
  int            x;
  int            y;
  SG_PropertyPtr property;

  if (node != NULL) {
    property = node->property;
    
    while (property != NULL) {
      switch (property->id) {

      case SG_unVieW :
	XtSetArg (args[0], XtNviewTop   , (Position) ((property->data.ivalue >> 24)));
	XtSetArg (args[1], XtNviewLeft  , (Position) ((property->data.ivalue >> 16) & 0xff));
	XtSetArg (args[2], XtNviewBottom, (Position) ((property->data.ivalue >>  8) & 0xff));
	XtSetArg (args[3], XtNviewRight , (Position) ((property->data.ivalue      ) & 0xff));

	XtSetValues (w_goban, args, 4);
	if (w_second_goban != NULL) 
	  XtSetValues (w_second_goban, args, 4);
	break;
      }
      
      property = property->next;
    }
    
    switch (node->type) {
      
    case SG_EventType   :
      XtSetArg (args[0], XtNgameSize  , 19);
      XtSetArg (args[1], XtNviewTop   , 19);
      XtSetArg (args[2], XtNviewLeft  , 1 );
      XtSetArg (args[3], XtNviewBottom, 1 );
      XtSetArg (args[4], XtNviewRight , 19);

      XtSetValues (w_goban, args, 5);
      if (w_second_goban != NULL) 
	XtSetValues (w_second_goban, args, 5);

    case SG_DiagramType :
      
      if ((setup = node->setup) != NULL)
	while (*setup != SG_EOS) {
	  color = (*setup & 0xc0);
	  x     = (*setup++ & 0x3f);
	  y     = (*setup++ & 0x3f);
	  
	  switch (color) {
	  case SG_SETB  :
	  case SG_SETW  : GbSetPoint (w_goban, x, y, GbEmptyPoint); break;
	  case SG_SETEB : GbSetPoint (w_goban, x, y, GbBlackStone); break;
	  case SG_SETEW : GbSetPoint (w_goban, x, y, GbWhiteStone); break;
	  }
	  
	  if (w_second_goban != NULL) 
	    switch (color) {
	    case SG_SETB  :
	    case SG_SETW  : GbSetPoint (w_second_goban, x, y, GbEmptyPoint); break;
	    case SG_SETEB : GbSetPoint (w_second_goban, x, y, GbBlackStone); break;
	    case SG_SETEW : GbSetPoint (w_second_goban, x, y, GbWhiteStone); break;
	    }
	}
      break;
      
    case SG_MoveType :
      x     = node->x;
      y     = node->y;

      GbSetPoint (w_goban, x, y, GbEmptyPoint);
      if (w_second_goban != NULL) 
	GbSetPoint (w_second_goban, x, y, GbEmptyPoint);
      
      if ((setup = node->setup) != NULL) {
	color = (int) ((node->color == SG_BlackStone) ? GbWhiteStone : GbBlackStone);

	while (*setup != SG_EOS) {
	  x     = (*setup++ & 0x3f);
	  y     = (*setup++ & 0x3f);
	  
	  GbSetPoint (w_goban, x, y, color);
	  if (w_second_goban != NULL) 
	    GbSetPoint (w_second_goban, x, y, color);
	}
      }

      break;
    }
    
    HideTmpProperty (node);
  }
}

/*******************************************************************************************************
 */
