/*   -*- coding: utf-8 -*-  */

/***********************************************************************
*
* Module   : SxmlNode
* Fichier  : SxmlNodeUnIndent.c
* Auteur   : Ducloy 
* $Id: SxmlNodeUnIndent.c,v 1.2 2005/01/19 15:48:01 parmentf Exp $
************************************************************************
*
* Copyright (c) 1998 CNRS/CRIN & INRIA Lorraine
* 
************************************************************************/
/**
   @file

   @brief The SxmlNodeUnIndent function

   @see SxmlUnIndent

   @since 1998
   @author &copy; INIST-CNRS
   @author Jacques DUCLOY
 */
#include "SxmlNode.h"
#include "Except.h"

SxmlUnIndentManager *SxmlUnIndentManagerCreate()
{
  SxmlUnIndentManager *manager;
  if(!(manager=(SxmlUnIndentManager *)malloc(sizeof(SxmlUnIndentManager))))
    {
       ExceptSetError("SxmlParser","MA", "memory allocation failed in SxmlUnIndentManagerCreate","","",2);
       return NULL;
    }
  manager->mode='p';
  manager->bufClean=NewBuffer();
  manager->dict=NULL;
  return manager;
};

char *SxmlNodeUnIndentFindNotSpace(char *str)
{
  char *begStr;
  begStr=str;
  while((*begStr==' ')||(*begStr=='\n')||(*begStr=='\t'))begStr++;
  if (*begStr=='\0') return NULL;
  return begStr;
}

char *SxmlUnIndentIsIndent(SxmlNode *firstOrAfter)
{
  char *str;
  if (!firstOrAfter) return NULL;
  if (!(SxmlIsText(firstOrAfter))) return NULL;
  str=SxmlNodeValue(firstOrAfter);
  if (str[0]!='\n') return NULL;
  if (SxmlNodeUnIndentFindNotSpace(str)) return NULL;
  return str;
}

StrDict *SxmlNodeUnIndentSetDict (SxmlUnIndentManager *manager, char *pathDict)
{
  manager->dict=StrDictFromFile(pathDict);
  return manager->dict;
}

SxmlNode *SxmlNodeUnIndentElement(SxmlUnIndentManager *manager, SxmlNode *x1)
{
  SxmlNode *x2;
  
  x2=SxmlFirstChild(x1);
  while(x2)
    {
      SxmlNode *x3;
      x3=SxmlNextSibling(x2);
      if (SxmlUnIndentIsIndent(x2)) SxmlFree(x2);
      else SxmlNodeUnIndent(manager, x2);
      x2=x3;
    }
  return x1;
}

int SxmlNodeUnIndentTextStr(SxmlUnIndentManager *manager, SxmlNode *x1, int noFirstSpace)
{
  char *str;
  char *begStr;
  int   spaceBegin;
  str=SxmlNodeValue(x1);
  begStr=str;
  spaceBegin=0;
  while ((*begStr==' ')||(*begStr=='\n')||(*begStr=='\t')) {begStr++; spaceBegin=1;}
  if (noFirstSpace==1) BufferReset(manager->bufClean);
  else
    {
      if (spaceBegin==1) BufferStrcpy(manager->bufClean," ");
      else BufferReset(manager->bufClean);
    }
  BufferTextCleanCat(manager->bufClean, 's', begStr);
  SxmlReplaceValue(x1,BufferString(manager->bufClean));
  if (SxmlNextSibling(x1))
    {
      if (BufferTailCmp(manager->bufClean," ")==0) return 1;
      else return 0;
    }
  else
    {
      if (BufferTailCmp(manager->bufClean," ")==0) BufferTailCut(manager->bufClean,1);
      return 0;
    }
}

SxmlNode *SxmlNodeUnIndentParElement(SxmlUnIndentManager *manager, SxmlNode *x1)
{
  SxmlNode *x2;
  
  if (!x1)return NULL;
  x2=SxmlFirstChild(x1);
  if (!x2)return NULL;
  if (SxmlUnIndentIsIndent(x2))
    {
      SxmlNode *x3;
      x3=SxmlNextSibling(x2);
      SxmlFree(x2);
      x2=x3;
    }
  if (SxmlIsText(x2))
    {
      SxmlNodeUnIndentTextStr(manager, x2, 1);
    }
  while(x2)
    {
      SxmlNode *x3;
      x3=SxmlNextSibling(x2);
      if (SxmlUnIndentIsIndent(x2)) 
	{
	  if (!x3) SxmlFree(x2);
	  else SxmlReplaceValue(x2," ");
	}
      else
	{
	    if (SxmlIsText(x2))
	      {
		SxmlNodeUnIndentTextStr(manager, x2, 0);
	      }
	    else SxmlNodeUnIndent(manager, x2);
	}
      x2=x3;
    }
  return x1;
}

SxmlNode *SxmlNodeUnIndent(SxmlUnIndentManager *manager, SxmlNode *x1)
{
  char *str;
  char *begStr;
  char *targetStr;

  if (!x1)return NULL;

  switch (SxmlNodeType(x1))
    {
    case SXML_NODE_TEXT:
    case SXML_NODE_COMMENT:
    case SXML_NODE_CDATA_SECTION:
    case SXML_NODE_PROCESSING_INSTRUCTION:
    case SXML_NODE_ENTITY_DECLARATION:
      str=SxmlNodeValue(x1);
      if (!str)
	{
	  SxmlFree(x1);
	  return NULL;
	}
      
      begStr=str;
      BufferReset(manager->bufClean);
      if (manager->mode=='s') while((*begStr==' ')||(*begStr=='\n')||(*begStr=='\t'))begStr++;
      if (manager->mode=='s') targetStr=BufferTextCleanCat(manager->bufClean, 's', begStr);
      else targetStr=BufferTextCleanCat(manager->bufClean, 'p', begStr);
      if ((manager->mode=='s') && (BufferTailCmp(manager->bufClean," ")==0)) BufferTailCut(manager->bufClean,1);
      SxmlReplaceValue(x1,BufferString(manager->bufClean));
      return x1;

    case SXML_NODE_ELEMENT:
    case SXML_NODE_DOCUMENT_TYPE:
      if (manager->dict)
	{
	  char *fieldType;
	  fieldType=StrDictSearch(manager->dict, SxmlNodeName(x1));
	  if (!fieldType)return SxmlNodeUnIndentElement(manager, x1);
	  switch (*fieldType)
	    {
	    case 'p':        /* Paragrah */
	      return SxmlNodeUnIndentParElement(manager, x1);
	      break;
	    default:
	      break;
	    }
	}
      return SxmlNodeUnIndentElement(manager, x1);

    default:
      return x1;
    }
}

SxmlNode *SxmlNodeUnIndentDocument(SxmlUnIndentManager *manager, SxmlNode *x1)    /* unIndent at Document level */
{
  SxmlNode *ret;
  if (SxmlIsText(x1))
    {
      char *str;
      char *begStr;
      str=SxmlNodeValue(x1);
      if (!str)return NULL;
      begStr=SxmlNodeUnIndentFindNotSpace(str);
      if (!begStr)return NULL;
    }
  ret=SxmlNodeUnIndent(manager, x1);
  return ret;
}
