/****************************************************************************************************************
 *
 *  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 "sg.h"

#define PrintKeyword(id) (short_print == 0 ? sg_keywords[id].print : sg_keywords[id].keyword)
#define Newline(file)    { if (short_print == 0) if (fprintf (file, "\n") == EOF) return EOF; }

static int size        = 19;
static int short_print = 0;

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

static int write_node (node, var, file, level)
SG_NodePtr  node;
int         var;
FILE       *file;
int         level;
{
  SG_PropertyPtr  property;
  unsigned char  *ptr;
  unsigned char   color;
  int             x;
  int             y;

  if (node != NULL) {

    if (node->right != NULL && var == 1)
      do {
	if (write_node (node, 0, file, level) == EOF) 
	  return EOF;

	node = node->right;
      } while (node != NULL);

    else {
      if (fprintf (file, "(") == EOF)
	return EOF;
      Newline (file);

      if (fprintf (file, ";") == EOF)
	return EOF;
      Newline (file);

      if (level == 0) {
	if (fprintf (file, "%s[1]", PrintKeyword (SG_GaMe)) == EOF)
	  return EOF;
	Newline (file);
      }

      goto sequence1;

    sequence  :

      if (fprintf (file, ";") == EOF)
	return EOF;
      Newline (file);
            
    sequence1 :

      switch (node->type) {

      case SG_EventType   :
      case SG_DiagramType :

	if ((ptr = node->setup) != NULL) {

	  color = ~(*ptr & 0xc0);
	    
	  while (*ptr != SG_EOS) {
	    if ((*ptr & 0xc0) != color && 
		! ((*ptr & 0xc0) == SG_SETEB && color == SG_SETEW) &&
		! ((*ptr & 0xc0) == SG_SETEW && color == SG_SETEB)) {
	      color = *ptr & 0xc0;
		
	      if (ptr != node->setup) {
		Newline (file);
	      }
		
	      switch (color) {
	      case SG_SETB  : 
		if (fprintf (file, "%s", PrintKeyword (SG_AddBlack))  == EOF)
		  return EOF;
		break;
	      case SG_SETW  : 
		if (fprintf (file, "%s", PrintKeyword (SG_AddWhite)) == EOF)
		  return EOF;
		break;
	      case SG_SETEB :
	      case SG_SETEW : 
		if (fprintf (file, "%s", PrintKeyword (SG_AddEmpty)) == EOF)
		  return EOF; 
		break;
	      }
	    }
	      
	    x = *ptr++ & 0x3f;
	    y = *ptr++ & 0x3f;

	    if (fprintf (file, "[%c%c]", 'a' - 1 + x , 'a' + size - y) == EOF)
	      return EOF;
			 
	  }
	    
	  Newline (file);
	}

	if (fprintf (file, "%s[%c]", 
		     PrintKeyword (SG_PLayer),
		     (node->player == SG_WhiteStone) ? 'W' : 'B') 
	    == EOF)
	  return EOF;
	Newline (file);

	break;

      case SG_MoveType :
	if (node->x == 0 && node->y == 0) {
	  if (fprintf (file, "%s[tt]", 
		       PrintKeyword ((node->color ==  SG_BlackStone) ? SG_Black : SG_White))
	      == EOF)
	    return EOF;
	  Newline (file);
	}

	else {
	  if (fprintf (file, "%s[%c%c]", 
		       PrintKeyword ((node->color ==  SG_BlackStone) ? SG_Black : SG_White),
		       'a' - 1 + node->x, 
		       'a' + size - node->y)
	      == EOF)
	    return EOF;
	  Newline (file);
	}

	break;
      }

      property = node->property;

      while (property != NULL) {
	switch (property->id) {
	
	case SG_VieW :
	  if (fprintf (file, "%s[%c%c][%c%c]",
		       PrintKeyword (SG_VieW),
		       'a' - 1 +    ((property->data.ivalue >> 16) & 0xff),
		       'a' + size - ((property->data.ivalue >> 24) & 0xff),
		       'a' - 1 +    ((property->data.ivalue      ) & 0xff),
		       'a' + size - ((property->data.ivalue >>  8) & 0xff))
	      == EOF)
	    return EOF;
	  Newline (file);
	  break;
	  
	case SG_SiZe :
	  size = property->data.ivalue;
	  if (fprintf (file, "%s[%d]", 
		       PrintKeyword (SG_SiZe),
		       property->data.ivalue)
	      == EOF)
	    return EOF;
	  Newline (file);
	  break;
	  
	case SG_KO :
	  if (fprintf (file, "%s[%c%c]",
		       PrintKeyword (SG_KO),
		       'a' - 1    + ((property->data.ivalue >> 8) & 0x3f),
		       'a' + size - (property->data.ivalue & 0x3f))
	      == EOF)
	    return EOF;
	  Newline (file);
	  break;
       
	case SG_Comment     :
	case SG_GameName    :
	case SG_GameComment :
	case SG_nodeName    :
	case SG_EVent       :
	case SG_ROund       :
	case SG_DaTe        :
	case SG_PlaCe       :
	case SG_REsult      :
	case SG_USer        :
	case SG_TiMe        :
	case SG_SOurce      :
	case SG_BlackRank   :
	case SG_WhiteRank   :
	case SG_BlackSpec   :
	case SG_WhiteSpec   :
	case SG_HAndicap    :
	case SG_KoMi        :
	case SG_PlayerBlack :
	case SG_PlayerWhite :
	case SG_BlackLeft   :
	case SG_WhiteLeft   :

	  if ((ptr = property ->data.pvalue) != NULL && strcmp ((char *) ptr, "") != 0) {
	    if (fprintf (file, "%s[", PrintKeyword (property->id)) == EOF)
	      return EOF;

	    while (*ptr != '\0') {
	      if (*ptr == ']')
		if (putc ('\\', file) == EOF) return EOF;
	      if (putc ((char) *ptr, file) == EOF) return EOF;
	      ptr++;
	    }

	    if (fprintf (file, "]") == EOF) return EOF; Newline (file);
	  }
	  break;

	case SG_Letters :
	case SG_Marked  :
	  if ((ptr = property->data.pvalue) != NULL) {
	    if (fprintf (file, "%s", 
			 PrintKeyword (property->id))
		== EOF)
	      return EOF;
    
	    while (*ptr != SG_EOS) {
	      x = *ptr++ & 0x3f;
	      y = *ptr++ & 0x3f;
	      
	      if (x != 0 || y != 0)
		if (fprintf (file, "[%c%c]", 'a' - 1 + x , 'a' + size - y) == EOF)
		  return EOF;
	    }

	    Newline (file);
	  }
	  break;
	}

	property = property->next;
      }

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

	if (node->right != NULL) {
	  if (write_node (node, 1, file, level + 1) == EOF) 
	    return EOF;
	}
	else
	  goto sequence;
      }

      if (fprintf (file, ")") == EOF)
	return EOF;
      Newline (file);
    }
  }

  return 0;
}

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

int SG_WriteTree (node, file, shrt)
SG_NodePtr  node;
FILE       *file;
int         shrt;
{
  short_print = shrt;
  size        = 19;

  return write_node (node, 1, file, 0);
}

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