/****************************************************************************
*
*      Projet  : DilibPro
*      Module  : Sgml
*      Fichier : SgmlNode.h
*      Auteur  : J. Ducloy
*      Origine : J. Ducloy
*
*      Derniere mise a jour Novembre 2001
*
************************************************************************
* 
*     Copyrigth (C) 1995 CRIN - CNRS & INRIA Lorraine
*
****************************************************************************/
#ifndef _SGML_NODE_H_
#define _SGML_NODE_H_

struct SgmlNode_Struct
   {
     /*  DILIB SGML type part */
	char	type;     /* DILIB specification
                             D : Data
			     M : Mark
			     A : Att 
			     L : Latt
                             C : Comment
                             P : Processing instructions
                             T : DTD Doc Type
                             e : DTD Element
                             g : DTD group
                             a : DTD AttList

                             I : iterator
                             l : lisp node

                             c : container

                             X : XmlNode
			   */
	char    subType;  /* for type  M:
			             S : Standard,
                                     R : Record,
				     E : Empty
                             for type C:
                                     C : true comment
                                     D : DTD (ou element de DTD) -- deprecated
                             for type e or g:

                             for type c:
                                     i : integer
                                     l : long (integer)
                                     d : double

                                     B : dilib Buffer
                                     A : Sgml Array
                                     R : RegExp
                                     X : SgmlXml node (pointer on)
                                     p : dilibPath
                                     
			  */

     /*  Xml type part */
     /*    type byte (managed by Sgml Kernel)     */ 
     unsigned int XmlNodeType: 8 ; 
     unsigned int XmlSubType:8 ;       /* see XmlNode.h */

      /* type byte which are dedicated to applications */

	char    cusType;
        char    cusSubType;
        char    appli;    

      /*            main pointers (managed by kernel)       */

        struct  SgmlNode_Struct *father;               
	struct	SgmlNode_Struct *first;
	struct	SgmlNode_Struct *last;
	struct	SgmlNode_Struct *prev;
	struct	SgmlNode_Struct *next;

     /*  specific XML */
     struct     XmlNode_Struct *W3CnextNode;  

	/*        printing pointer                     */
         
        char   *format;

     /*           common data (managed by kernel)     */


     char	          *info1;  /* name */
     char              *xmlValue;
     struct  SgmlNode_Struct *XmlAttributes;

	union	uvl_type
	  {
	    char *v; 
	    struct SgmlNode_Struct *n;
	    long l;
	  }               info2;
     /*          application data area  */

        union	uvni_type 
	  {
	    char *v; 
	    struct SgmlNode_Struct *n;
	    long i;
            double d;
            char tc[4];
	  }               cus1;



	/*      free  purpose   indicators                 */

        unsigned int formatToFree: 1;
     /* XML use only */
       unsigned int valueToFree: 1;
        unsigned int nameToFree: 1;
     unsigned int unParsed:            1;
     unsigned int isTempData:        1;
     unsigned int xmlNodeTypeSpecific: 1; /* defined by formal type */
     unsigned int XmlNodeSpecific:     1; /* defined at sugType level */
   };

typedef struct SgmlNode_Struct SgmlNode ;

#define XML_NODE_DILIB_V03 22

struct SgmlTreeIterator_struct
{
  SgmlNode *root;
  SgmlNode *next;
};

typedef struct SgmlTreeIterator_struct SgmlTreeIterator;

/*         codes retour de procedure  */

#define SgmlSTOP 0
#define SgmlCONTINUE 1
#define SgmlPRINT 2


#define SgmlMark    SgmlNode
#define SgmlComment SgmlNode
#define SgmlData    SgmlNode
#define SgmlLeaf    SgmlNode

#define SgmlHasTag(n,t)  ((n)?((t)?((strcmp(SgmlTag(n),(t))==0)?(t):NULL):NULL):NULL)
#define SgmlType(x)          x->type
#define SgmlSubType(x)       x->subType
#define SgmlNodeCodeAppli(x) x->appli
#define SgmlNodeSetCodeAppli(x,c)    {x->appli=c;}

#define SgmlNodeFormat(x)          x->format
#define SgmlNodeFormatToFree(x)    x->formatToFree

#define SgmlFirst(x)         x->first
#define SgmlLast(x)          x->last
#define SgmlNext(x)          x->next
#define SgmlPrevious(x)      x->prev
#define SgmlFather(x)        x->father

#define SgmlCustom(x)        x->cus1.v
#define SgmlCusType(x)       (x->cusType)
#define SgmlCusSubType(x)    (x->cusSubType)

#define SgmlTag(x)      x->info1

#define SgmlMarkAttVal(n,t) ((n)?((t)?SgmlGetAttValById((n),(t)):NULL):NULL)

#define SgmlAttId(x)    x->info1
#define SgmlAttVal(x)   x->info2.v
#define SgmlAttList(x)  x->info2.n

#define SgmlDataString(x)     x->info1

#define SgmlTypeData(x) x->type == 'D'
#define SgmlIsData(n) SgmlTypeData(n)
#define SgmlIsMark(x)   (x->type== 'M')

SgmlNode *SgmlCommentCreate();

#define SgmlCommentString(x)     SgmlDataString(x)

/* Fonction de creation de base */

SgmlNode	*SgmlCreateNode(char);

/* Fonctions de liberation */

void    SgmlNodeBasicFree();
void	SgmlFree();
void    SgmlFreeContent();
void	SgmlFreeWithMode(SgmlNode*,char);
void    SgmlFreeChildren();
#define SgmlFreeAllChilds(n1) SgmlFreeChildren(n1)
#define SgmlSetToFree(n1)  ((n1)->appli='F')
#define SgmlIsToBeFreed(x) (((n1)->appli=='F')?1:NULL)
void    SgmlFreeMarkedChild();

/* Fonctions relatives aux donnees (PCDATA)     */

     SgmlNode        *SgmlDataCreate();
     SgmlNode        *SgmlCreateData();
     SgmlNode        *SgmlPutData();
#define SgmlDataPutString(n,s) SgmlPutData(n,s)
     char            *SgmlDataStrCat();
#define SgmlDataStrcat SgmlDataStrCat
     char            *SgmlDataStrncpy();

SgmlNode        *SgmlAddData();

#define SgmlCustomNode(x)            (x?x->cus1.n:NULL)
#define SgmlCustomSetNode(x,n1)       (x->cus1.n=(n1))
/*
#define SgmlCustom1Node(x)       (x?x->cus1.n:NULL)
#define SgmlCustom2Node(x)       (x?x->cus2.n:NULL)
#define SgmlCustom3Node(x)       (x?x->cus3.n:NULL)

#define SgmlCustom1String(x)     (x?x->cus1.v:NULL)
#define SgmlCustom2String(x)     (x?x->cus2.v:NULL)
#define SgmlCustom3String(x)     (x?x->cus3.v:NULL)

#define SgmlCustom1Int(x)        (x?x->cus1.i:0)
#define SgmlCustom2Int(x)        (x?x->cus2.i:0)
#define SgmlCustom3Int(x)        (x?x->cus3.i:0)

#define SgmlCustom1Char(x,y)        (x?x->cus1.tc[y]:0)
#define SgmlCustom2Char(x,y)        (x?x->cus2.tc[y]:0)
#define SgmlCustom3Char(x,y)        (x?x->cus3.tc[y]:0)
*/
/* Fonction de creation de base */

SgmlNode	*SgmlAddLast();
SgmlNode	*SgmlAddFirst();
SgmlNode        *SgmlCopyChildren();

SgmlNode        *SgmlInsertAfter();
SgmlNode        *SgmlInsertBefore();

int              SgmlCard();
char            *SgmlCardStr();

#define SgmlAddSon SgmlAddLast
#define SgmlAddChild SgmlAddLast

/* Fonctions relatives aux noeuds de type Mark, attributs... */

SgmlNode	*SgmlCreateMark();
SgmlNode        *SgmlSetEmpty();
SgmlNode        *XmlSetEmpty();
SgmlNode        *SgmlSetTag();
SgmlNode	*SgmlCreateAtt();
SgmlNode	*SgmlCreateAttList();
SgmlNode        *SgmlNewAttList();
SgmlNode        *SgmlAddAtt();
SgmlNode        *SgmlSetAtt();
SgmlNode        *SgmlGetSonNumber();
#define SgmlGetChildNumber(x,n) SgmlGetSonNumber(c,n)
SgmlNode        *SgmlCreateEmptyMark();
SgmlNode        *XmlCreateEmptyMark();

/*        fonction sur les leaf */

SgmlNode        *SgmlCreateLeaf();
char            *SgmlLeafStrncpy();
char            *SgmlLeafStrCat();
#define SgmlLeafStrcat SgmlLeafStrCat
SgmlNode        *SgmlCreateLeafStrncpy();
char            *SgmlLeafGetData();
#define SgmlAddLeaf(n,t,s) SgmlAddSon(n,SgmlCreateLeaf(t,s))
#define SgmlLeafPutString(n,s) SgmlDataPutString(SgmlFirst(n),s)

/*  Fonctions de structuration  */

SgmlNode        *SgmlCopy();
SgmlNode        *SgmlCut();
void             SgmlCutAndFree();
SgmlNode        *SgmlReplace();
SgmlNode        *SgmlReplaceContent();




SgmlNode        *SgmlInsertTagBeforeGreater();
SgmlNode        *SgmlAddSonTagBeforeGreater();

/* fonctions de tri */

SgmlNode *SgmlInsertSortedUniq();
SgmlNode *SgmlInsertSorted();
SgmlNode *SgmlAddSonSorted();
SgmlNode *SgmlAddSonSortedUniq();
SgmlNode *SgmlInsertSortedReverse();
SgmlNode *SgmlAddSonSortedReverse();
/* Fonctions de Tests */

int SgmlEqualAtt ();
int SgmlEqualMark ();
int SgmlEqualSubTree ();
int SgmlEqualListSubTree ();
int SgmlCmp ();

/* Predicats de type */

SgmlNode *SgmlIsLeaf();
SgmlNode *SgmlIsEmpty();

/* Fonctions de visualisation */

void	SgmlPrintAtt();
void	SgmlPrint();
void    SgmlFilePrint();
void    SgmlFilePrintAtt();

void SgmlToEdNode();
void SgmlToEdRoot();
void SgmlToEdList();

/* Fonctions de conversion  */

int       SgmlStrLen();
char     *SgmlToString();
SgmlNode *SgmlFromString();
void      SgmlCatToString();

/* Fonctions E/S simplifiees  */

SgmlNode *SgmlFromFile();
SgmlNode *SgmlToFile();

/* Fonctions de recherche ou remplacement */

SgmlNode *SgmlGetNextGid();
#define   SgmlGetNextTag(x,y)  (SgmlGetNextGid(x,y))
SgmlNode *SgmlGetPreviousTag();
SgmlNode *SgmlGetSonTag();
#define   SgmlGetChildTag(x,y)  (SgmlGetSonTag(x,y))
#define   SgmlFirstChildTag(x,y)  (SgmlGetSonTag(x,y))
SgmlNode *SgmlLastChildTag();
SgmlNode *SgmlGetLastChildTag();
SgmlNode *SgmlGetSonTagGreater();
char     *SgmlGetFirstData();
SgmlNode *SgmlRepFirstData();
SgmlNode *SgmlGetAttById();
char     *SgmlGetAttValById();
SgmlNode *SgmlGetChildTagAtt();
SgmlNode *SgmlGetNextTagAtt();
char     *SgmlHasAtt();

/* Iterateurs simples */

#define SgmlIterGetNext(n1)         ((n1)->last)
#define SgmlIterSetNext(n1,n2)      (((n1)->last)=(n2))
#define SgmlIterGetStr(n1)          ((n1)->info1)
#define SgmlIterSetStr(n1,s1)       (((n1)->info1)=(s1))
#define SgmlIterGetNode(n1)         ((n1)->first)
#define SgmlIterSetNode(n1,n2)      (((n1)->first)=(n2))

SgmlNode *SgmlIterCreate();
SgmlNode *SgmlIterTagInit();
SgmlNode *SgmlIterTagCreate();
SgmlNode *SgmlIterTagNext();



/* Iterateurs sur arbre */

SgmlTreeIterator  *SgmlTreeIteratorCreate();
SgmlTreeIterator  *SgmlTreeIteratorInit();
SgmlNode          *SgmlTreeNextNode();
char              *SgmlTreeNextData();

/* les containers */

SgmlNode *SgmlContainerCreate(char);
#define   SgmlContainerGetCont(n1)         ((n1)->first)
#define   SgmlContainerSetCont(n1,n2)      (((n1)->first)=(n2))

/* les listes a la lisp */

#define SgmlLispCar(l) ((l)->first)
#define SgmlLispCdr(l) ((l)->last)
#define SgmlLispSetcar(l,s) (((l)->first)=(s))
#define SgmlLispSetcdr(l,s) (((l)->last)=(s))
#define SgmlLispIterator(l)      ((l)->info2.n)
#define SgmlLispSetIterator(l,v) (((l)->info2.n)=(v))
#define SgmlLispGetFreeCount(l1) ((l1)->cus1.i)
#define SgmlLispSetFreeCount(l1,v) (((l1)->cus1.i)=(v))
#define SgmlLispIncrFreeCount(l1)  (((l1)->cus1.i)++)
#define SgmlLispDecrFreeCount(l1)  (--((l1)->cus1.i))

SgmlNode *SgmlLispEmptyList();
SgmlNode *SgmlLispCons();
SgmlNode *SgmlLispNcons();
SgmlNode *SgmlLispIterInit();
SgmlNode *SgmlLispIterNext();
SgmlNode *SgmlLispAddLast();
SgmlNode *SgmlLispIterSetLast();
void      SgmlLispFree();

/* Iterators old (deprecated) */

#define SgmlDo(node,_DILIB_son,block)                               \
             { SgmlNode *_DILIB_son;                                \
             if((_DILIB_son=SgmlFirst(node)))                       \
             do block while( (_DILIB_son=SgmlNext(_DILIB_son)));}



#define SgmlDoTagEqual(node,tag,son,block)                 \
             { SgmlNode *son;                              \
             if(son=SgmlFirst(node))                       \
             do {                                          \
                if (strcmp(SgmlTag(son),tag)==0) block ;   \
               } while (son=SgmlNext(son));}


#define SgmlDoAtt(node,_DILIB_att,_DILIB_val,block)                       \
           { SgmlNode *SgmlDAlatt;                          \
             SgmlNode *SgmlDAson;                           \
             char *_DILIB_val;                                     \
             char *_DILIB_att;                                     \
             if((SgmlDAlatt=SgmlAttList(node)))               \
               {if ((SgmlDAson=SgmlFirst(SgmlDAlatt)))        \
                   { do { _DILIB_att = SgmlAttId(SgmlDAson);       \
                          _DILIB_val = SgmlAttVal(SgmlDAson);      \
                          block;                            \
                        }                                   \
                     while ((SgmlDAson=SgmlNext(SgmlDAson)));  \
		     }}} 



#endif  /* _SGML_NODE_H_  */



