/***********************************************************************
*
*      Projet  : DilibPro
*      Module  : Sgml
*      Fichier : SgmlCreateFree.c
*      Auteur  : J. Ducloy
*      Origine : J. Ducloy + V. Warth
*
*      Derniere mise a jour Janvier 99
*
*      $Id: SgmlNodeCreate.c,v 1.2 2005/06/22 13:57:07 parmentf Exp $
*
************************************************************************
*
* Copyright (c) 1994 CNRS/CRIN & INRIA Lorraine
* 
************************************************************************/

#include "SgmlNodePrivate.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Fonctions de création */

/*******************************************************************************
 *                              SgmlCreateNode
 *
 * - Constructeur generique d'objets SgmlNode
 *
 * - paramètre :
 *		- Ptype : type du noeud 
 *                         M:mark,
 *                          A:attribut,
 *                          D:donnees,L:liste d'attributs)
 *		
 * - Valeur retournée : un pointeur sur SgmlNode
 *
 *
 ******************************************************************************/

SgmlNode  *SgmlNodesFreeList;
char      *SgmlNodeFormatData;
char      *SgmlNodeFormatMark;
char      *SgmlNodeFormatComment;
char      *SgmlNodeFormatAtt;
char      *SgmlNodeFormatEmptyMark;
char      *XmlNodeFormatEmptyMark;
char      *SgmlNodeFormatDocTypeMarkup;

int        SgmlNumberOfNodes;

static int firstCall=1;

void SgmlCreateFreeInit()
{
  firstCall=0;
  SgmlNodeFormatData="%s";
  SgmlNodeFormatComment="<!--%s-->";
  SgmlNodeFormatMark="<%s%s>%s</%s>";
  SgmlNodeFormatEmptyMark="<%s%s>";
  XmlNodeFormatEmptyMark="<%s%s/>";
  SgmlNodeFormatAtt=" %s=\"%s\"";
  SgmlNodeFormatDocTypeMarkup="<!DOCTYPE %s %s [%s]>";
  SgmlNodesFreeList=NULL;
  SgmlNumberOfNodes=0;
}    

SgmlNode	*SgmlNodeBasicCreate()
{
  SgmlNode	*noeud;

  noeud = (SgmlNode *) malloc( sizeof(SgmlNode) );
  SgmlNumberOfNodes++;

  return(noeud); 
}

void SgmlNodeBasicFree(SgmlNode *n1)
{
  SgmlNext(n1)=SgmlNodesFreeList;
  SgmlNodesFreeList=n1;
}

SgmlNode	*SgmlCreateNode(char Ptype)
{
  SgmlNode	*noeud;

  if(firstCall)SgmlCreateFreeInit();

  if (SgmlNodesFreeList)
    {
      noeud=SgmlNodesFreeList;
      SgmlNodesFreeList=SgmlNext(noeud);
    }
  else
    {
      noeud=SgmlNodeBasicCreate();
    }

  noeud->type         = Ptype;
  noeud->cusType      = '\0';
  noeud->cusSubType   = '\0';
  noeud->subType      = '\0';
  noeud->appli        = '\0';
  noeud->format       = SgmlNodeFormatData;
  noeud->formatToFree = 0;
  noeud->father       = NULL;
  noeud->first        = NULL;
  noeud->last         = NULL;
  noeud->prev         = NULL;
  noeud->next         = NULL;
  noeud->info1        = NULL;
  noeud->info2.v      = NULL; 
  noeud->cus1.v       = NULL;
  /*
  noeud->cus2.v       = NULL;
  noeud->cus3.v       = NULL;
  */
  noeud->XmlNodeType  =XML_NODE_DILIB_V03;
  return(noeud); 
 
} /* end SgmlCreateNode */


SgmlNode *SgmlContainerCreate(char s1)
{
  SgmlNode *n1;
  n1=SgmlCreateNode('c');
  n1->subType=s1;
  return n1;
}
/* Fonctions de liberation */


/****************************************************************************** 
 *                              SgmlFree
 *
 * - Fonction récursive qui libère la place prise par une structure de
 *   type SgmlNode
 *
 * - Les paramètres :
 *		- noeud : pointeur sur la structure
 *		- mode  : 
 *
 *
 ******************************************************************************/

void    SgmlFreeContent(SgmlNode *noeud)
{

  /* liberations specifiques */

    switch (SgmlType(noeud))
      {
       case 'M' : 
          if (SgmlAttList(noeud)) 
	    {
	      SgmlFreeWithMode(SgmlAttList(noeud),'A');
	      SgmlRplaAttList(noeud,NULL);
	    }
          if (SgmlTag(noeud))     
	    {
	      free (SgmlTag(noeud));
	      SgmlRplaTag(noeud,NULL);
	    }
          break;
	case 'A' :
          if (SgmlAttId(noeud)) 
	    {
	      free (SgmlAttId(noeud));
	      SgmlRplaAttId(noeud,NULL);
	    }
	  if (SgmlAttVal(noeud))
	    {
	      free (SgmlAttVal(noeud));
	      SgmlRplaAttVal(noeud,NULL);
	    }
          break;
        case 'D':
        case 'C':
	  if(SgmlDataString(noeud)) 
	    {
	      free (SgmlDataString(noeud));
	      SgmlRplaDataString(noeud,NULL);
	    }
	  break;

      case 'l':
      case 'I':
      case 'c':
	return;
	    
       }

  /* libération du format */
    
  if ( noeud->formatToFree ) free (noeud->format);

  /* liberation des fils */

  if ( SgmlFirst(noeud) ) SgmlFreeWithMode(SgmlFirst(noeud),'B');
  SgmlFirst(noeud)=NULL;
  SgmlLast(noeud)=NULL;
}

void	SgmlFreeWithMode(SgmlNode *noeud,
			 char      mode)
      /*    mode = A  
                   liberation limitee au noeud et a ses fils
                   remise en etat des liens du voisinage apres liberation
            mode = B 
                   liberation transmise aux freres suivants du noeud
                   liberation "rapide" sans mise a jour des liens
      */
{
  SgmlNode	*r;
  SgmlNode	*l;


  SgmlFreeContent(noeud);




  /* mise a jour des liens */

  if ( SgmlType(noeud) == 'L' )
    {   SgmlNode *pere;
        if ((pere=SgmlFather(noeud))) SgmlAttList(pere) = NULL;
    }

  else /* if ( SgmlType(noeud) != 'R' )*/
    {
       if ( mode == 'A' ) /*  remise en etat des liens */
         { 
	   l = SgmlPrevious(noeud);
	   r = SgmlNext(noeud);

           if ( l && r )   
	     {
		SgmlNext(l) = r;
		SgmlPrevious(r) = l; 
	     }
           else if ( l ) 
	          {
		    SgmlNext(l) = NULL;
		    if (SgmlFather(noeud)) SgmlLast(SgmlFather(noeud)) = l;
		  }
           else if ( r ) 
		  {
		    SgmlPrevious(r) = NULL;
		    if (SgmlFather(noeud)) SgmlFirst(SgmlFather(noeud)) = r;
		  }
           else if (SgmlFather(noeud) )
		{
	          SgmlFirst(SgmlFather(noeud)) = NULL;
	          SgmlLast(SgmlFather(noeud)) = NULL;
		}
         } 
       else 
         {
          if ( SgmlNext(noeud) ) SgmlFreeWithMode( SgmlNext(noeud),'B');
         }
    }

  SgmlNodeBasicFree(noeud);
  
} /* end SgmlFreeWithMode */

void SgmlFree(SgmlNode *noeud)
{ if (noeud) SgmlFreeWithMode (noeud, 'A'); }

void SgmlFreeChildren(SgmlNode *node)
{
  if(node)
    {
      SgmlNode *c1;
      if((c1=SgmlFirst(node)))
	{
	  SgmlNode *c2;
	  do
	    {
	      c2=SgmlNext(c1);
	      SgmlFree(c1);
	    }while ((c1=c2));
	}
    }
}
