//------------------------------------------------------------------------------
//   skoro XML handler by  M.Lisztwan                                          -
//------------------------------------------------------------------------------
/* $Id: cxml.c,v 1.1 2008/10/16 14:34:16 mastny Exp $ */

#pragma hdrstop

#include "cxml.h"
#ifdef __BORLANDC__
#include "alloc.h"
#else
#include "stdlib.h"
#endif

#include "string.h"

//------------------------------------------------------------------------------
#ifdef __BORLANDC__
#pragma package(smart_init)
#endif
//------------------------------------------------------------------------------

TCXMLnode *CxmlCreateNodeL(const char * aName,const int aNameL, TNodeType NodeType, const char * aData,const int aDataL )
{
TCXMLnode * n=(TCXMLnode *)malloc(sizeof(TCXMLnode));
if(n==NULL)return n;
n->Type=NodeType;
n->Subnodes=NULL;
n->SubnodesCnt=0;


switch (NodeType)
 {
 case ntElement :
         {
         if(aName)
           {
           if((n->Name=(char *)malloc(aNameL+1))==NULL){free(n); return NULL;};
           memcpy(n->Name,aName,aNameL);
           n->Name[aNameL]=0;
           }
         else
           {
           free( n);
           return NULL;
           }
         n->Data=NULL;
         }break;
 case ntAttribute :
         {
         if(aName)
           {
           if((n->Name=(char *)malloc(aNameL+1))==NULL){free (n); return NULL;};
           memcpy(n->Name,aName,aNameL);
           n->Name[aNameL]=0;
           }
         else
           {
           free (n);
           return NULL;
           }
         if(aData)
           {
           if((n->Data=(char *)malloc(aDataL+1))==NULL){free (n->Name); free( n); return NULL;};
           memcpy(n->Data,aData,aDataL);
           n->Data[aDataL]=0;
           }
         else
           {
           free( n->Name);
           free( n);
           return NULL;
           }
         }break;
 case ntText :
         {
           {
           int l;
           char * nn="#Text";
           if((n->Name=(char *)malloc(l=strlen(nn)+1))==NULL)
             {
             free(n);
             return NULL;
             }
           memcpy(n->Name,nn,l);
           }
         if(aData)
           {
           if((n->Data=(char *)malloc(aDataL+1))==NULL)
             {
             free(n->Name);
             free(n);
             return NULL;
             }
           memcpy(n->Data,aData,aDataL);
           n->Data[aDataL]=0;
           }
         else
           {free( n->Name); free(n); return NULL;};
         }break;
  }
return n;
}

//------------------------------------------------------------------------------

TCXMLnode *CxmlCreateNode(const char * aName, TNodeType NodeType, const char * aData)
{
TCXMLnode * n=(TCXMLnode *)malloc(sizeof(TCXMLnode));
if(n==NULL)return n;
n->Type=NodeType;
n->Subnodes=NULL;
n->SubnodesCnt=0;


switch (NodeType)
 {
 case ntElement :
         {
         if(aName)
           {
           int l;
           if((n->Name=(char *)malloc(l=strlen(aName)+1))==NULL){free(n); return NULL;};
           memcpy(n->Name,aName,l);
           }
         else
           {free( n); return NULL;};
         n->Data=NULL;

         }break;
 case ntAttribute :
         {
         if(aName)
           {
           int l;
           if((n->Name=(char *)malloc(l=strlen(aName)+1))==NULL){free (n); return NULL;};
           memcpy(n->Name,aName,l);
           }
         else
           {free (n); return NULL;};
         if(aData)
           {
           int l;
           if((n->Data=(char *)malloc(l=strlen(aData)+1))==NULL){free (n->Name); free( n); return NULL;};
           memcpy(n->Data,aData,l);
           }
         else
           {free( n->Name); free( n); return NULL;};
         }break;
 case ntText :
         {
           {
           int l;
           char * nn="#Text";
           if((n->Name=(char *)malloc(l=strlen(nn)+1))==NULL){free( n); return NULL;};
           memcpy(n->Name,nn,l);
           }
         if(aData)
           {
           int l;
           if((n->Data=(char *)malloc(l=strlen(aData)+1))==NULL){free(n->Name); free(n); return NULL;};
           memcpy(n->Data,aData,l);
           }
         else
           {free( n->Name); free(n); return NULL;};
         }break;
  }
return n;
}

//------------------------------------------------------------------------------
TCXMLnode *CxmlAddChild(TCXMLnode *node,TCXMLnode *cnode)
{
if( node==NULL || cnode==NULL) return NULL;
if( node->SubnodesCnt==0)
  {
  if((node->Subnodes=(TCXMLnode **)malloc( sizeof(TCXMLnode *)))==NULL)return NULL;
  node->Subnodes[0]=cnode;
  }
else
  {
   if((node->Subnodes=(TCXMLnode **)realloc(node->Subnodes, (node->SubnodesCnt+1)*sizeof(TCXMLnode *)))==NULL)return NULL;

  //  if((void*)(node->Subnodes=(TCXMLnode **)realloc( (node->SubnodesCnt+1)*sizeof(TCXMLnode*)))==NULL)return NULL;
  node->Subnodes[node->SubnodesCnt]=cnode;
  }
  node->SubnodesCnt++;
return cnode;
}

//------------------------------------------------------------------------------
TCXMLnode * CxmlDestroyNode(TCXMLnode *node)
{
int i;
if(node==NULL)return NULL;
if(node->Name!=NULL){free(node->Name);};
if(node->Data!=NULL){free(node->Data);};
for( i=0;i<node->SubnodesCnt;i++)CxmlDestroyNode(node->Subnodes[i]);
if(node->SubnodesCnt>0)free(node->Subnodes);
free(node);
return NULL;
}

//------------------------------------------------------------------------------
char *AddTxt2buffer(char ** buffer, int * bl, int * wc,char * txt)
{
char * b=*buffer;
int l=strlen(txt);

if(*wc+l+1>=*bl)
  {
  b=(char *)realloc(*buffer,*wc+l+1024);
  if(b==NULL)return NULL;
  *bl=*wc+l+1024;
  *buffer=b;
  }
memcpy(*buffer+*wc,txt,l);
*wc=*wc+l;
return b;
}
//------------------------------------------------------------------------------

char * doNodeToText(TCXMLnode *node,char ** buffer, int * bl, int * wc)
{
char * b;
if(node==NULL)return NULL;
switch (node->Type)
 {
 case ntElement :
         {
         int nebyltextanielement=1;
         int i;
//         if(*wc!=0) b=AddTxt2buffer(buffer,bl, wc,"\n");
//         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,"<");
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,node->Name);
         if(b==NULL)return NULL;
         for(i=0;i<node->SubnodesCnt;i++)
           {
           if(node->Subnodes[i]->Type==ntAttribute)
              {
              b=doNodeToText(node->Subnodes[i],buffer, bl,wc);
              if(b==NULL)return NULL;
              }
           }
         b=AddTxt2buffer(buffer,bl, wc,">");
         if(b==NULL)return NULL;
         for(i=0;i<node->SubnodesCnt;i++)
           {
           if(node->Subnodes[i]->Type!=ntAttribute)
              {
              if(nebyltextanielement&&(node->Subnodes[i]->Type==ntElement))
                {
                nebyltextanielement=0;
                b=AddTxt2buffer(buffer,bl, wc,"\n");
                if(b==NULL)return NULL;
                }
              if(node->Subnodes[i]->Type==ntText)
                {
                nebyltextanielement=0;
                }
              b=doNodeToText(node->Subnodes[i],buffer, bl,wc);
              if(b==NULL)return NULL;
              }
           }
         b=AddTxt2buffer(buffer,bl, wc,"</");
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,node->Name);
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,">\n");
         if(b==NULL)return NULL;
         }break;
 case ntAttribute :
         {
         b=AddTxt2buffer(buffer,bl, wc," ");
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,node->Name);
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,"=\"");
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,node->Data);
         if(b==NULL)return NULL;
         b=AddTxt2buffer(buffer,bl, wc,"\"");
         if(b==NULL)return NULL;
         }break;
 case ntText :
         {
         b=AddTxt2buffer(buffer,bl, wc,node->Data);
         if(b==NULL)return NULL;
         }break;
  }
return *buffer;
}

//------------------------------------------------------------------------------

char * CxmlNodeToText(TCXMLnode *node, int *writtenchars)
{
int bufferlength=0;
char *buffer= NULL;
char*b;
*writtenchars=0;

b= doNodeToText(node,&buffer, &bufferlength, writtenchars);
if(b!=NULL)
 {
 buffer[*writtenchars]=0;
 }
else
 {
 *writtenchars=0;
 }
return b;
}
//------------------------------------------------------------------------------


int FindTag(char * s,int * begin, int * end)
{
int i;
int kkonec=-1;
int found=0;
 for(i=*begin;i<=*end-1;i++)
   {
   if(s[i]=='<')
     {
     *begin=i;
     found=1;
     if(s[i+1]!='/')kkonec=1;
     break;
     }
   }
if(found)
  {
  found=0;
  for(i=*begin;i<=*end;i++)
    {
    if(s[i]=='>')
      {
      *end=i;
      found=1;
      break;
      }
    }
  }
return found*kkonec;
}

//------------------------------------------------------------------------------
char *GetTagName(char * s,int begin, int end,int * delka)
{
int i;
* delka=0;

if( s[begin+1]=='/')begin++;

for(i=begin +1;i<=end-1;i++)
   {
   if(s[i]==' '||s[i]=='>')break;
   (*delka)++;
   }
return s+begin+1;
}
//------------------------------------------------------------------------------

int FindAttrib(char * s,int begin,int end,char **name, int* dname, char**value,int*dvalue)
{
int i;
int j;
int k;
int found=-1;
 for(i=begin;i<=end;i++)
   {
   if(s[i]=='=')
     {
     for(j=i;j>=begin;j--)
       {
       if(s[j]==' ')
         {
         *name=s+j+1;
         *dname=i-j-1;
         for(k=i+2;k<=end;k++)
            {
            if(s[k]=='"')
              {
              *value=s+i+2;
              *dvalue=k-i-2;
              found=i;
              break;
              }
            }
         break;
         }
       }
     break;
     }
   }
   return found;
   }

//------------------------------------------------------------------------------
int cmpstrL( char * name0,int name0d,char *name1, int name1d)
{
int i;
if(name0d!=name1d)return 0;
for(i=0;i<name0d;i++)
  {
  if(name0[i]!=name1[i])return 0;
  }
return 1;
}
//------------------------------------------------------------------------------
int FillSubNodeAttribs(TCXMLnode *node, char * s,int begin, int end)
{
char * name;
char * value;
int dname,dvalue,r;
TCXMLnode * n;

while((r=FindAttrib(s,begin,end,&name, &dname, &value,&dvalue))>=0)
  {
  n=CxmlCreateNodeL(name,dname,ntAttribute,value,dvalue);
  if(n==NULL)return 0;
  n=CxmlAddChild(node,n);
  if(n==NULL)
    {
    CxmlDestroyNode(n);
    return 0;
    }
  begin=r+dvalue+2;
  }

return 1;
  }
//------------------------------------------------------------------------------
int ProcessSpaceTo1stTag(TCXMLnode *node, char * s,int begin, int end)
{

 TCXMLnode * n;
      //pokud je predtim text tak ko ulozim

     if(end>begin ||(end==begin && s[begin]!='\n'))
       {
       n=CxmlCreateNodeL(NULL,0,ntText, s+begin ,end-begin+1);
       if(n==NULL)return 0;
       n=CxmlAddChild(node,n);
       if(n==NULL)
         {
         CxmlDestroyNode(n);
         return 0;
         }
       }


return 1;
}
//------------------------------------------------------------------------------
int FillSubNodeS(TCXMLnode *node, char * s,int begin, int end)
{
int tagbegin0, tagend0;
int tagbegin1, tagend1;
int tagfound;
int endtagfound;
 TCXMLnode * n;
 char * tagname0, *tagname1;
 int tagname0d,tagname1d;
do{
tagbegin0=begin;
tagend0=end;
 tagfound=FindTag(s,&tagbegin0, &tagend0);
   if(tagfound>0)
     {
//     if(!ProcessSpaceTo1stTag(node,s,begin,tagbegin0-1))return 0;
//     zruseno kvuli odsazeni nitrnich uzlu
     // --
     tagname0=GetTagName(s,tagbegin0, tagend0,&tagname0d);
     tagbegin1=tagend0;
     tagend1=end;
     for(;;)
      {
      endtagfound=FindTag(s,&tagbegin1, &tagend1);
      if(endtagfound<0)//1
       {
       tagname1=GetTagName(s,tagbegin1, tagend1,&tagname1d);
       if(cmpstrL(tagname0,tagname0d,tagname1,tagname1d))
         {
         // naselsem konec
         n=CxmlCreateNodeL(tagname0,tagname0d,ntElement,NULL,0);
         if(n==NULL)return 0;
         n=CxmlAddChild(node,n);
         if(n==NULL)
           {
           CxmlDestroyNode(n);
           return 0;
           }
         if(!FillSubNodeAttribs(n,s,tagbegin0,tagend0))return 0;
         if(!FillSubNodeS(n,s,tagend0+1, tagbegin1-1))return 0;


         begin=tagend1+1;
         break;
         }
       else
         {
         tagbegin1=tagend1;
         tagend1=end;
         }
       }
     else
       {
       if(endtagfound>0)
         {
         tagbegin1=tagend1;
         tagend1=end;
         }
       else
         {
         // chyba ve zdroji dat neni ukoncen <>
         begin=tagend1+1;
         break;
         }
       }
      }
     }
   if(tagfound==0 && end-begin>=0) //>0
     {
     // v oblasti hledani neni zadny zacatek tagu
      if(!(end-begin==0 && s[begin]=='\n'))
         {
       n=CxmlCreateNodeL(NULL,0,ntText, s+begin ,end-begin+1);
       if(n==NULL)return 0;
       n=CxmlAddChild(node,n);
       if(n==NULL)
         {
         CxmlDestroyNode(n);
         return 0;
         }
       }
     }

  }while(tagfound);
 return 1;
}
//------------------------------------------------------------------------------
TCXMLnode * CxmlTextToNode(char * s,int length)
{
TCXMLnode * n;
TCXMLnode * h;
TCXMLnode * res=NULL;

int i;
n=CxmlCreateNode("",ntElement,NULL);
if(n==NULL)return NULL;
if(!FillSubNodeS(n,s,0,length-1))
  {
  CxmlDestroyNode(n);
  return NULL;
  }
h=CxmlCreateNode("",ntElement,NULL);
if(h==NULL)
  {
  CxmlDestroyNode(n);
  return NULL;
  }
for(i=0;i<n->SubnodesCnt;i++)
   {
   if(n->Subnodes[i]->Type==ntElement)
     {
     res=n->Subnodes[i];
     n->Subnodes[i]=h;
     }
   }
CxmlDestroyNode(n);

return res;
}

//------------------------------------------------------------------------------
char *CxmlGetName(TCXMLnode *node)
{
  if(node){
    return(node->Name);
  }else{
    return(NULL);
  }
}

//------------------------------------------------------------------------------
int CxmlGetNumAttribs(TCXMLnode *node)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntAttribute)n++;
    }
  }
return n;
}
//------------------------------------------------------------------------------
int CxmlGetNumElements(TCXMLnode *node)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntElement)n++;
    }
  }
return n;
}
//------------------------------------------------------------------------------
int CxmlGetNumTexts(TCXMLnode *node)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntText)n++;
    }
  }
return n;
}
//------------------------------------------------------------------------------
TCXMLnode * CxmlGetSubNodeI(TCXMLnode *node,int index)
{
if(node)
  {
  if(index>=0 && index<node->SubnodesCnt)
    {
    return node->Subnodes[index];
    }
  }
return NULL;
}

//------------------------------------------------------------------------------
TCXMLnode * CxmlGetSubTextI(TCXMLnode *node,int index)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntText)
      {
      if(n==index) return(node->Subnodes[i]);
      n++;
      }
    }
  }
return NULL;
}

//------------------------------------------------------------------------------
char *CxmlGetSubTextIText(TCXMLnode *node,int index)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntText)
      {
      if(n==index) return(node->Subnodes[i]->Data);
      n++;
      }
    }
  }
return NULL;
}

//------------------------------------------------------------------------------
TCXMLnode * CxmlGetSubElemnetN(TCXMLnode *node,char * Name)
{
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntElement)
      if(strcmp( node->Subnodes[i]->Name,Name)==0)
        return(node->Subnodes[i]);
    }
  }
return NULL;
}
//------------------------------------------------------------------------------
char*  CxmlGetAttribute(TCXMLnode *node,char * Name)
{
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntAttribute)
      if(strcmp( node->Subnodes[i]->Name,Name)==0)
        return node->Subnodes[i]->Data;
    }
  }
return NULL;

}
//------------------------------------------------------------------------------
TCXMLnode * CxmlGetSubElemnetI(TCXMLnode *node,int index)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntElement)
      {
      if(n==index) return(node->Subnodes[i]);
      n++;
      }
    }
  }
return NULL;
}
//------------------------------------------------------------------------------
void CxmlTextFree(char* p)
{
free(p);
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------

TCXMLnodeW *CxmlCreateNodeLW(const wchar_t * aName,const int aNameL, TNodeType NodeType, const wchar_t * aData,const int aDataL )
{
TCXMLnodeW * n=(TCXMLnodeW *)malloc(sizeof(TCXMLnodeW));
if(n==NULL)return n;
n->Type=NodeType;
n->Subnodes=NULL;
n->SubnodesCnt=0;


switch (NodeType)
 {
 case ntElement :
         {
         if(aName)
           {
           if((n->Name=(wchar_t *)malloc((aNameL+1)*sizeof(wchar_t)))==NULL){free(n); return NULL;};
           memcpy(n->Name,aName,aNameL*sizeof(wchar_t));
           n->Name[aNameL]=0;
           }
         else
           {
           free( n);
           return NULL;
           }
         n->Data=NULL;
         }break;
 case ntAttribute :
         {
         if(aName)
           {
           if((n->Name=(wchar_t *)malloc((aNameL+1)*sizeof(wchar_t)))==NULL){free (n); return NULL;};
           memcpy(n->Name,aName,aNameL*sizeof(wchar_t));
           n->Name[aNameL]=0;
           }
         else
           {
           free (n);
           return NULL;
           }
         if(aData)
           {
           if((n->Data=(wchar_t *)malloc((aDataL+1)*sizeof(wchar_t)))==NULL){free (n->Name); free( n); return NULL;};
           memcpy(n->Data,aData,aDataL*sizeof(wchar_t));
           n->Data[aDataL]=0;
           }
         else
           {
           free( n->Name);
           free( n);
           return NULL;
           }
         }break;
 case ntText :
         {
           {
           int l;
           wchar_t * nn=L"#Text";
           if((n->Name=(wchar_t *)malloc((l=wcslen(nn)+1)*sizeof(wchar_t)))==NULL)
             {
             free(n);
             return NULL;
             }
           memcpy(n->Name,nn,l*sizeof(wchar_t));
           }
         if(aData)
           {
           if((n->Data=(wchar_t *)malloc((aDataL+1)*sizeof(wchar_t)))==NULL)
             {
             free(n->Name);
             free(n);
             return NULL;
             }
           memcpy(n->Data,aData,aDataL*sizeof(wchar_t));
           n->Data[aDataL]=0;
           }
         else
           {free( n->Name); free(n); return NULL;};
         }break;
  }
return n;
}

//------------------------------------------------------------------------------

TCXMLnodeW *CxmlCreateNodeW(const wchar_t * aName, TNodeType NodeType, const wchar_t * aData)
{
TCXMLnodeW * n=(TCXMLnodeW *)malloc(sizeof(TCXMLnodeW));
if(n==NULL)return n;
n->Type=NodeType;
n->Subnodes=NULL;
n->SubnodesCnt=0;


switch (NodeType)
 {
 case ntElement :
         {
         if(aName)
           {
           int l;
           if((n->Name=(wchar_t *)malloc((l=wcslen(aName)+1)*sizeof(wchar_t)))==NULL){free(n); return NULL;};
           memcpy(n->Name,aName,l*sizeof(wchar_t));
           }
         else
           {free( n); return NULL;};
         n->Data=NULL;

         }break;
 case ntAttribute :
         {
         if(aName)
           {
           int l;
           if((n->Name=(wchar_t *)malloc((l=wcslen(aName)+1)*sizeof(wchar_t)))==NULL){free (n); return NULL;};
           memcpy(n->Name,aName,l*sizeof(wchar_t));
           }
         else
           {free (n); return NULL;};
         if(aData)
           {
           int l;
           if((n->Data=(wchar_t *)malloc((l=wcslen(aData)+1)*sizeof(wchar_t)))==NULL){free (n->Name); free( n); return NULL;};
           memcpy(n->Data,aData,l*sizeof(wchar_t));
           }
         else
           {free( n->Name); free( n); return NULL;};
         }break;
 case ntText :
         {
           {
           int l;
           wchar_t * nn=L"#Text";
           if((n->Name=(wchar_t *)malloc((l=wcslen(nn)+1)*sizeof(wchar_t)))==NULL){free( n); return NULL;};
           memcpy(n->Name,nn,l*sizeof(wchar_t));
           }
         if(aData)
           {
           int l;
           if((n->Data=(wchar_t *)malloc((l=wcslen(aData)+1)*sizeof(wchar_t)))==NULL){free(n->Name); free(n); return NULL;};
           memcpy(n->Data,aData,l*sizeof(wchar_t));
           }
         else
           {free( n->Name); free(n); return NULL;};
         }break;
  }
return n;
}

//------------------------------------------------------------------------------
TCXMLnodeW *CxmlAddChildW(TCXMLnodeW *node,TCXMLnodeW *cnode)
{
if( node==NULL || cnode==NULL) return NULL;
if( node->SubnodesCnt==0)
  {
  if((node->Subnodes=(TCXMLnodeW **)malloc( sizeof(TCXMLnodeW *)))==NULL)return NULL;
  node->Subnodes[0]=cnode;
  }
else
  {
   if((node->Subnodes=(TCXMLnodeW **)realloc(node->Subnodes, (node->SubnodesCnt+1)*sizeof(TCXMLnodeW *)))==NULL)return NULL;

  //  if((void*)(node->Subnodes=(TCXMLnodeW **)realloc( (node->SubnodesCnt+1)*sizeof(TCXMLnodeW*)))==NULL)return NULL;
  node->Subnodes[node->SubnodesCnt]=cnode;
  }
  node->SubnodesCnt++;
return cnode;
}

//------------------------------------------------------------------------------
TCXMLnodeW * CxmlDestroyNodeW(TCXMLnodeW *node)
{
int i;
if(node==NULL)return NULL;
if(node->Name!=NULL){free(node->Name);};
if(node->Data!=NULL){free(node->Data);};
for( i=0;i<node->SubnodesCnt;i++)CxmlDestroyNodeW(node->Subnodes[i]);
if(node->SubnodesCnt>0)free(node->Subnodes);
free(node);
return NULL;
}

//------------------------------------------------------------------------------
wchar_t *AddTxt2bufferW(wchar_t ** buffer, int * bl, int * wc,wchar_t * txt)
{
wchar_t * b=*buffer;
int l=wcslen(txt);

if(*wc+l+1>=*bl)
  {
  b=(wchar_t *)realloc(*buffer,(*wc+l+1024)*sizeof(wchar_t));
  if(b==NULL)return NULL;
  *bl=*wc+l+1024;
  *buffer=b;
  }
memcpy(*buffer+*wc,txt,l*sizeof(wchar_t));
*wc=*wc+l;
return b;
}
//------------------------------------------------------------------------------

wchar_t * doNodeToTextW(TCXMLnodeW *node,wchar_t ** buffer, int * bl, int * wc)
{
wchar_t * b;
if(node==NULL)return NULL;
switch (node->Type)
 {
 case ntElement :
         {
         int nebyltextanielement=1;
         int i;
//         if(*wc!=0) b=AddTxt2buffer(buffer,bl, wc,"\n");
//         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,L"<");
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,node->Name);
         if(b==NULL)return NULL;
         for(i=0;i<node->SubnodesCnt;i++)
           {
           if(node->Subnodes[i]->Type==ntAttribute)
              {
              b=doNodeToTextW(node->Subnodes[i],buffer, bl,wc);
              if(b==NULL)return NULL;
              }
           }
         b=AddTxt2bufferW(buffer,bl, wc,L">");
         if(b==NULL)return NULL;
         for(i=0;i<node->SubnodesCnt;i++)
           {
           if(node->Subnodes[i]->Type!=ntAttribute)
              {
              if(nebyltextanielement&&(node->Subnodes[i]->Type==ntElement))
                {
                nebyltextanielement=0;
                b=AddTxt2bufferW(buffer,bl, wc,L"\n");
                if(b==NULL)return NULL;
                }
              if(node->Subnodes[i]->Type==ntText)
                {
                nebyltextanielement=0;
                }
              b=doNodeToTextW(node->Subnodes[i],buffer, bl,wc);
              if(b==NULL)return NULL;
              }
           }
         b=AddTxt2bufferW(buffer,bl, wc,L"</");
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,node->Name);
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,L">\n");
         if(b==NULL)return NULL;
         }break;
 case ntAttribute :
         {
         b=AddTxt2bufferW(buffer,bl, wc,L" ");
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,node->Name);
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,L"=\"");
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,node->Data);
         if(b==NULL)return NULL;
         b=AddTxt2bufferW(buffer,bl, wc,L"\"");
         if(b==NULL)return NULL;
         }break;
 case ntText :
         {
         b=AddTxt2bufferW(buffer,bl, wc,node->Data);
         if(b==NULL)return NULL;
         }break;
  }
return *buffer;
}

//------------------------------------------------------------------------------

wchar_t * CxmlNodeToTextW(TCXMLnodeW *node, int *writtenchars)
{
int bufferlength=0;
wchar_t *buffer= NULL;
wchar_t*b;
*writtenchars=0;

b= doNodeToTextW(node,&buffer, &bufferlength, writtenchars);
if(b!=NULL)
 {
 buffer[*writtenchars]=0;
 }
else
 {
 *writtenchars=0;
 }
return b;
}
//------------------------------------------------------------------------------


int FindTagW(wchar_t * s,int * begin, int * end)
{
int i;
int kkonec=-1;
int found=0;
 for(i=*begin;i<=*end-1;i++)
   {
   if(s[i]=='<')
     {
     *begin=i;
     found=1;
     if(s[i+1]!='/')kkonec=1;
     break;
     }
   }
if(found)
  {
  found=0;
  for(i=*begin;i<=*end;i++)
    {
    if(s[i]=='>')
      {
      *end=i;
      found=1;
      break;
      }
    }
  }
return found*kkonec;
}

//------------------------------------------------------------------------------
wchar_t *GetTagNameW(wchar_t * s,int begin, int end,int * delka)
{
int i;
* delka=0;

if( s[begin+1]==L'/')begin++;

for(i=begin +1;i<=end-1;i++)
   {
   if(s[i]==L' '||s[i]==L'>')break;
   (*delka)++;
   }
return s+begin+1;
}
//------------------------------------------------------------------------------

int FindAttribW(wchar_t * s,int begin,int end,wchar_t **name, int* dname, wchar_t**value,int*dvalue)
{
int i;
int j;
int k;
int found=-1;
 for(i=begin;i<=end;i++)
   {
   if(s[i]==L'=')
     {
     for(j=i;j>=begin;j--)
       {
       if(s[j]==L' ')
         {
         *name=s+j+1;
         *dname=i-j-1;
         for(k=i+2;k<=end;k++)
            {
            if(s[k]==L'"')
              {
              *value=s+i+2;
              *dvalue=k-i-2;
              found=i;
              break;
              }
            }
         break;
         }
       }
     break;
     }
   }
   return found;
   }

//------------------------------------------------------------------------------
int cmpstrLW( wchar_t * name0,int name0d,wchar_t *name1, int name1d)
{
int i;
if(name0d!=name1d)return 0;
for(i=0;i<name0d;i++)
  {
  if(name0[i]!=name1[i])return 0;
  }
return 1;
}
//------------------------------------------------------------------------------
int FillSubNodeAttribsW(TCXMLnodeW *node, wchar_t * s,int begin, int end)
{
wchar_t * name;
wchar_t * value;
int dname,dvalue,r;
TCXMLnodeW * n;

while((r=FindAttribW(s,begin,end,&name, &dname, &value,&dvalue))>=0)
  {
  n=CxmlCreateNodeLW(name,dname,ntAttribute,value,dvalue);
  if(n==NULL)return 0;
  n=CxmlAddChildW(node,n);
  if(n==NULL)
    {
    CxmlDestroyNodeW(n);
    return 0;
    }
  begin=r+dvalue+2;
  }

return 1;
  }
//------------------------------------------------------------------------------
int ProcessSpaceTo1stTagW(TCXMLnodeW *node, wchar_t * s,int begin, int end)
{

 TCXMLnodeW * n;
      //pokud je predtim text tak ko ulozim

     if(end>begin ||(end==begin && s[begin]!=L'\n'))
       {
       n=CxmlCreateNodeLW(NULL,0,ntText, s+begin ,end-begin+1);
       if(n==NULL)return 0;
       n=CxmlAddChildW(node,n);
       if(n==NULL)
         {
         CxmlDestroyNodeW(n);
         return 0;
         }
       }


return 1;
}
//------------------------------------------------------------------------------
int FillSubNodeSW(TCXMLnodeW *node, wchar_t * s,int begin, int end)
{
int tagbegin0, tagend0;
int tagbegin1, tagend1;
int tagfound;
int endtagfound;
 TCXMLnodeW * n;
 wchar_t * tagname0, *tagname1;
 int tagname0d,tagname1d;
do{
tagbegin0=begin;
tagend0=end;
 tagfound=FindTagW(s,&tagbegin0, &tagend0);
   if(tagfound>0)
     {
//     if(!ProcessSpaceTo1stTag(node,s,begin,tagbegin0-1))return 0;
//     zruseno kvuli odsazeni nitrnich uzlu
     // --
     tagname0=GetTagNameW(s,tagbegin0, tagend0,&tagname0d);
     tagbegin1=tagend0;
     tagend1=end;
     for(;;)
      {
      endtagfound=FindTagW(s,&tagbegin1, &tagend1);
      if(endtagfound<0)//1
       {
       tagname1=GetTagNameW(s,tagbegin1, tagend1,&tagname1d);
       if(cmpstrLW(tagname0,tagname0d,tagname1,tagname1d))
         {
         // naselsem konec
         n=CxmlCreateNodeLW(tagname0,tagname0d,ntElement,NULL,0);
         if(n==NULL)return 0;
         n=CxmlAddChildW(node,n);
         if(n==NULL)
           {
           CxmlDestroyNodeW(n);
           return 0;
           }
         if(!FillSubNodeAttribsW(n,s,tagbegin0,tagend0))return 0;
         if(!FillSubNodeSW(n,s,tagend0+1, tagbegin1-1))return 0;


         begin=tagend1+1;
         break;
         }
       else
         {
         tagbegin1=tagend1;
         tagend1=end;
         }
       }
     else
       {
       if(endtagfound>0)
         {
         tagbegin1=tagend1;
         tagend1=end;
         }
       else
         {
         // chyba ve zdroji dat neni ukoncen <>
         begin=tagend1+1;
         break;
         }
       }
      }
     }
   if(tagfound==0 && end-begin>=0) //>0
     {
     // v oblasti hledani neni zadny zacatek tagu
      if(!(end-begin==0 && s[begin]=='\n'))
         {
       n=CxmlCreateNodeLW(NULL,0,ntText, s+begin ,end-begin+1);
       if(n==NULL)return 0;
       n=CxmlAddChildW(node,n);
       if(n==NULL)
         {
         CxmlDestroyNodeW(n);
         return 0;
         }
       }
     }

  }while(tagfound);
 return 1;
}
//------------------------------------------------------------------------------
TCXMLnodeW * CxmlTextToNodeW(wchar_t * s,int length)
{
TCXMLnodeW * n;
TCXMLnodeW * h;
TCXMLnodeW * res=NULL;

int i;
n=CxmlCreateNodeW(L"",ntElement,NULL);
if(n==NULL)return NULL;
if(!FillSubNodeSW(n,s,0,length-1))
  {
  CxmlDestroyNodeW(n);
  return NULL;
  }
h=CxmlCreateNodeW(L"",ntElement,NULL);
if(h==NULL)
  {
  CxmlDestroyNodeW(n);
  return NULL;
  }
for(i=0;i<n->SubnodesCnt;i++)
   {
   if(n->Subnodes[i]->Type==ntElement)
     {
     res=n->Subnodes[i];
     n->Subnodes[i]=h;
     }
   }
CxmlDestroyNodeW(n);

return res;
}

//------------------------------------------------------------------------------
wchar_t *CxmlGetNameW(TCXMLnodeW *node)
{
  if(node){
    return(node->Name);
  }else{
    return(NULL);
  }
}

//------------------------------------------------------------------------------
int CxmlGetNumAttribsW(TCXMLnodeW *node)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntAttribute)n++;
    }
  }
return n;
}
//------------------------------------------------------------------------------
int CxmlGetNumElementsW(TCXMLnodeW *node)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntElement)n++;
    }
  }
return n;
}
//------------------------------------------------------------------------------
int CxmlGetNumTextsW(TCXMLnodeW *node)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntText)n++;
    }
  }
return n;
}
//------------------------------------------------------------------------------
TCXMLnodeW * CxmlGetSubNodeIW(TCXMLnodeW *node,int index)
{
if(node)
  {
  if(index>=0 && index<node->SubnodesCnt)
    {
    return node->Subnodes[index];
    }
  }
return NULL;
}

//------------------------------------------------------------------------------
TCXMLnodeW * CxmlGetSubTextIW(TCXMLnodeW *node,int index)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntText)
      {
      if(n==index) return(node->Subnodes[i]);
      n++;
      }
    }
  }
return NULL;
}

//------------------------------------------------------------------------------
wchar_t *CxmlGetSubTextITextW(TCXMLnodeW *node,int index)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntText)
      {
      if(n==index) return(node->Subnodes[i]->Data);
      n++;
      }
    }
  }
return NULL;
}

//------------------------------------------------------------------------------
TCXMLnodeW * CxmlGetSubElemnetNW(TCXMLnodeW *node,wchar_t * Name)
{
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntElement)
      if(wcscmp( node->Subnodes[i]->Name,Name)==0)
        return(node->Subnodes[i]);
    }
  }
return NULL;
}
//------------------------------------------------------------------------------
wchar_t*  CxmlGetAttributeW(TCXMLnodeW *node,wchar_t * Name)
{
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntAttribute)
      if(wcscmp( node->Subnodes[i]->Name,Name)==0)
        return node->Subnodes[i]->Data;
    }
  }
return NULL;

}
//------------------------------------------------------------------------------
TCXMLnodeW * CxmlGetSubElemnetIW(TCXMLnodeW *node,int index)
{
int n=0;
if(node)
  {
  int i;
  for(i=0;i<node->SubnodesCnt;i++)
    {
    if(node->Subnodes[i]->Type==ntElement)
      {
      if(n==index) return(node->Subnodes[i]);
      n++;
      }
    }
  }
return NULL;
}
//------------------------------------------------------------------------------
void CxmlTextFreeW(wchar_t* p)
{
free(p);
}
//------------------------------------------------------------------------------



