/**********************************************************************
*
*  projet   : DilibPro
*  module   : Dam  (Dilib Acces Method)
*  fichier  : DamHfd.c
*  Auteur   : Jacques DUCLOY
*  Date     : Octobre 93
*  $Id: DamHfd.c,v 1.3 2005/06/22 12:43:08 parmentf Exp $
*
***********************************************************************
* 
*     Copyright (C) 1975 CRIN - CNRS & INRIA Lorraine
*
***********************************************************************/
#include <string.h>
#include <stdlib.h>
#include "DamHfd.h"
#include "SgmlPath.h"

void DamHfdSetFirstKey(DamHfd *hfd)
{
  SgmlNode *hfdStruct;
  int iKey;
  char *digit;
  SgmlTreeIterator *it1;

  hfdStruct=SgmlGetSonTag(hfd->desc, "struct");
  it1=SgmlTreeIteratorCreate();
  SgmlTreeIteratorInit(it1,hfdStruct);
  iKey=0;
  while (SgmlTreeNextData(it1))iKey++;
  if(!hfd->key)
    {
      hfd->key=malloc(iKey+1);
      hfd->regKey=malloc(iKey+1);
    }
  SgmlTreeIteratorInit(it1,hfdStruct);
  iKey=0;
  while ((digit=SgmlTreeNextData(it1)))hfd->key[iKey++]=digit[0];
  hfd->key[iKey++]=0;
}

char *DamHfdNextKey(DamHfd *hfd)
{
  int lastPos;
  SgmlNode *lastDigit;
  char     *rDigit;
  char *posDigit;
  char c;

  lastPos = strlen(hfd->key);
  lastDigit=SgmlLast(SgmlLast(SgmlGetSonTag(hfd->desc, "struct")));
  strcpy(hfd->regKey, hfd->key);
 
  while(lastPos--)
    {
      posDigit=strchr((rDigit=SgmlLeafGetData(lastDigit)),hfd->key[lastPos]);
      if ((c=*(posDigit+1)))
	{
	  hfd->regKey[lastPos]=c;
	  return (hfd->regKey);
	}
      else
	{
	  hfd->regKey[lastPos]=rDigit[0];
	  if (SgmlPrevious(lastDigit))lastDigit=SgmlPrevious(lastDigit);
	  else lastDigit=SgmlLast(SgmlPrevious(SgmlFather(lastDigit)));
	}
    }
  return NULL;
}

char *DamHfdPreviousKey(DamHfd *hfd)
{
  int lastPos;
  SgmlNode *lastDigit;
  char     *rDigit;
  char *posDigit;
  char c;

  lastPos = strlen(hfd->key);
  lastDigit=SgmlLast(SgmlLast(SgmlGetSonTag(hfd->desc, "struct")));
  strcpy(hfd->regKey, hfd->key);
 
  while(lastPos--)
    {
      posDigit=strchr((rDigit=SgmlLeafGetData(lastDigit)),hfd->key[lastPos]);
      if (posDigit>rDigit)
	{
	  c=*(posDigit-1);
	  hfd->regKey[lastPos]=c;
	  return (hfd->regKey);
	}
      else
	{
	  hfd->regKey[lastPos]=rDigit[strlen(rDigit)];
	  if (SgmlPrevious(lastDigit))lastDigit=SgmlPrevious(lastDigit);
	  else lastDigit=SgmlLast(SgmlPrevious(SgmlFather(lastDigit)));
	}
    }
  return NULL;
  
}

/****************** DamHfdOpenReadKey *********************************/

DamHCB *DamHfdOpenReadKey(char *name)
{
  DamHCB *hcb;
  SgmlNode *desc;
  SgmlNode *hfdDescName;
  char *path;
  DamFile *hcs;

  hcb=NULL;

  hcs=DamFileCreate();
  path = malloc(strlen(name)+5);
  strcpy (path,name);
  strcat (path,".hcs");
  if (DamFileOpen(hcs,path))
    {
      desc = SgmlCopy(DamFileNextSgml(hcs));
      SgmlPathStrSearchFirst(desc,"/hfd/name",hfdDescName);
      SgmlLeafPutString(hfdDescName, name);
      hcb=DamHCB_Create(desc);
      hcb->pathNameBuffer=malloc(DamHCB_PathNameSize(hcb));
      hcb->currentPath=malloc(DamHCB_PathNameSize(hcb));
      strcpy(hcb->currentPath,"");
      DamHfdSetFirstKey(hcb);
      hcb->isRunning=0;
    }
  DamFile_Free(hcs);
  free(path);
  return hcb;
}

/****************** DamHfdOpenPath ************************************/

int DamHfdOpenPath(DamHfd *hfd, char *path)
{
  if (strcmp(path,DamHfdCurrentPath(hfd))==0) return 1;
  if (DamFileOpen(hfd->damFile, path)) 
    {
      strcpy(DamHfdCurrentPath(hfd),path);
      return 1;
    }
  return 0;
}

/****************** DamHfdOpenPathCont ********************************/

int DamHfdOpenPathCont(DamHfd *hfd, char *path, char *tag)
{
  if (strcmp(path,DamHfdCurrentPath(hfd))==0) return 1;
  if (DamFileOpenReadCont(hfd->damFile, path)) 
    {
      strcpy(DamHfdCurrentPath(hfd),path);
      DamFileSetRecordTag(hfd->damFile, tag);
      return 1;
    }
  return 0;
}

/****************** DamHfdRecordReadKey *******************************/

/**
   Returns the record of the @a hfd which key equals @a key.
 */
DamRecord *DamHfdRecordReadKey(DamHfd *hfd, char *key)
{
     char    *path;
     path=DamHfdGetPath(hfd,key);
     hfd->isRunning=1;
     if (DamHfdOpenPath(hfd,path) )
       {
	 DamRecord *rec;
	 if((rec=DamFileGetRecordKey(hfd->damFile,key)))
	   {
	     strcpy(hfd->key,key);
	     return rec;
	   }
	 else return NULL;
       }
     else return NULL;
}

/************** DamHfdSgmlReadKey *************************************/


SgmlNode *DamHfdSgmlReadKey(DamHfd *hfd, char *key)
{
     char    *path;
     hfd->isRunning=1;
     path=DamHfdGetPath(hfd,key);
     if (DamHfdOpenPath(hfd,path) )
       {
	 SgmlNode *rec;
	 if((rec=DamFileGetSgmlKey(hfd->damFile,key)))
	   {
	     strcpy(hfd->key,key);
	     return rec;
	   }
	 else return NULL;
       }
     else return NULL;
}

/****************** DamHfdRecordReadNext ******************************/


DamRecord *DamHfdRecordReadNext(DamHfd *hfd, char *key)
{
  if(hfd->isRunning)
    {
      return DamHfdRecordReadKey(hfd, DamHfdNextKey(hfd));
    }
  else 
    {
      hfd->isRunning=1;
      return DamHfdRecordReadKey(hfd, hfd->key);
    }
}

/************** DamHfdSgmlReadNext ************************************/


SgmlNode *DamHfdSgmlReadNext(DamHfd *hfd, char *key)
{
  if(hfd->isRunning)
    {
      return DamHfdSgmlReadKey(hfd, DamHfdNextKey(hfd));
    }
  else 
    {
      hfd->isRunning=1;
      return DamHfdSgmlReadKey(hfd, hfd->key);
    }
}


/************** DamHfdSgmlReadPrevious ********************************/


SgmlNode *DamHfdSgmlReadPrevious(DamHfd *hfd, char *key)
{
  if(hfd->isRunning)
    {
      return DamHfdSgmlReadKey(hfd, DamHfdPreviousKey(hfd));
    }
  else 
    {
      hfd->isRunning=1;
      return 
	DamHfdSgmlReadKey(hfd, 
			  SgmlLeafGetData(SgmlGetSonTag(hfd->desc, 
							"lastKey")));
    }
}

