/*
    REFERENCES -- bibliographic software
    Copyright (C) 1995-2007  Volker Kiefel

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

/*
    ix03_fun.c -- documentation in ix01_fun.c
    index functions for keywords thesaurus
*/

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

#include "refs.h"
#include "ix03_fun.h"
#include "str_fun.h"
#include "fl_ut.h"
#include "interf.h"

extern char wrtxtbu[WRTXTBU_LEN + 1];

FILE * ix03file;

void mrgeix03(char * srcl_name, char * srcsh_name, char * destin_name)
{
   FILE * srcl;
   FILE * srcsh;
   FILE * destin;
   long i,j;
   long max_srcl, max_srcsh;
   int done_srcl, done_srcsh;

   keylistpix_rec top_srcl, top_srcsh;
   int doneall;
   done_srcl = 0; done_srcsh = 0;

   if ((srcl=fopen(srcl_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open SRCL\n");
      exit(1);
   }

   if(setvbuf(srcl,NULL,_IOFBF,20000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for srcl\n");
      exit(1);
   }

   if ((srcsh=fopen(srcsh_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open SRCSH\n");
      exit(1);
   }

   if (setvbuf(srcsh,NULL,_IOFBF,4000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for srcsh\n");
      exit(1);
   }

   if ((destin=fopen(destin_name,"wb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open DESTIN\n");
      exit(1);
   }

   if (setvbuf(destin,NULL,_IOFBF,25000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for destin\n");
      exit(1);
   }


   fseek(srcl,0L,SEEK_END); max_srcl=ftell(srcl)/sizeof(top_srcl);
   rewind(srcl);
   fseek(srcsh,0L,SEEK_END); max_srcsh=ftell(srcsh)/sizeof(top_srcsh);
   rewind(srcsh);

   /* wrtxt("(Rebuilding index file: adding keys) "); */
   i=0;j=0;
   doneall = 0;

   if (i >= max_srcl) done_srcl = 1;
   if (i < max_srcl)
   {

       fread(&top_srcl,sizeof(top_srcl),1,srcl);
       i++;
   }

   if (j >= max_srcsh) done_srcsh = 1;
   if (j < max_srcsh)
   {
        fread(&top_srcsh,sizeof(top_srcsh),1,srcsh);
        j++;
   }

   do
   {
      if ((!done_srcsh) && (done_srcl))
      {
        if (fwrite(&top_srcsh,sizeof(top_srcsh),1,destin) < 1) schreibfehler();
        if (j >= max_srcsh) done_srcsh = 1;
        if (j < max_srcsh)
        {
           fread(&top_srcsh,sizeof(top_srcsh),1,srcsh);
           j++;
        }
      }

      else if ((done_srcsh) && (!done_srcl))
      {
        if (fwrite(&top_srcl,sizeof(top_srcl),1,destin) < 1) schreibfehler();
        if (i >= max_srcl) done_srcl = 1;
        if (i < max_srcl)
        {
           fread(&top_srcl,sizeof(top_srcl),1,srcl);
           i++;
        }
      }

      else if (strcmp_fun(top_srcl.keywordsfield,top_srcsh.keywordsfield,SSTRING) < 0)
      {
           if (fwrite(&top_srcl,sizeof(top_srcl),1,destin) < 1) schreibfehler();
           if (i >= max_srcl) done_srcl = 1;
           if (i < max_srcl)
           {
              fread(&top_srcl,sizeof(top_srcl),1,srcl);
              i++;
           }
      }

      else // ..if ((top_srcl <= top_srcsh))
      {
            if (fwrite(&top_srcsh,sizeof(top_srcsh),1,destin) < 1) schreibfehler();
            if (j >= max_srcsh) done_srcsh = 1;
            if (j < max_srcsh)
            {
               fread(&top_srcsh,sizeof(top_srcsh),1,srcsh);
               j++;
            }
      }
      if (done_srcsh && done_srcl)
          doneall=1;
   } while (!doneall);
   fclose(srcl); fclose(srcsh); fclose(destin);
}


int read_ix03(char * datname)
{
  if ((ix03file=fopen(datname,"rb"))==NULL)
  {
     sprintf(wrtxtbu,"ERROR: Cannot open index file %s for reading\n",datname);
     wrtxt(wrtxtbu);
     return 0;
  }
  return 1;
}

int read_write_ix03(char * datname)
{
  if ((ix03file=fopen(datname,"r+b"))==NULL)
  {
     sprintf(wrtxtbu,"ERROR: Cannot open index file %s for reading and writing\n",datname);
     wrtxt(wrtxtbu);
     return 0;
  }
  return 1;
}

int close_ix03(void)
{
   fclose(ix03file);
   return 1;
}


long locate_ix03(const char * keyval, keylistpix_rec * recd)
{
   long l, r, x, n;
   l = 0;
   fseek(ix03file,0L,SEEK_END);
   n = (ftell(ix03file)/sizeof(keylistpix_rec)) -1;  /* Groesster Wert mit Pos. n-1 */
   r = n;
   while (r >= l)
   {
      x = (l + r)/2;
      fseek(ix03file,x*sizeof(keylistpix_rec),SEEK_SET);
      if (fread(recd,sizeof(keylistpix_rec),1,ix03file)!=1)
      {
         fprintf(stderr,"\nProblem in locate_ix03(): "
             "Unable to read index file\n");
         exit(1);
      }

      if (strcmp_fun(keyval,recd->keywordsfield,SSTRING) < 0) r = x-1; else l = x+1;
      if (strcmp_fun(keyval,recd->keywordsfield,SSTRING) == 0)
      {
         fseek(ix03file,-(long) sizeof(keylistpix_rec),SEEK_CUR);
         return x;
      }
   }
   return -1;
}



void deleteix03(char * ixfile_name, char * srcsh_name, char * destin_name)
{
   FILE * srcsh;
   FILE * destin;
   long i,keyfound;

   keylistpix_rec rec_ix, rec_srcsh;
   long max_ixfile, max_srcsh;

   if ((ix03file=fopen(ixfile_name,"r+b"))==NULL)
   {
       fprintf(stderr,"\nProblem: Cannot open SRCL\n");
       exit(1);
   }

   if(setvbuf(ix03file,NULL,_IOFBF,20000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for ix03file\n");
      exit(1);
   }

   if ((srcsh=fopen(srcsh_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open SRCSH\n");
      exit(1);
   }

   if (setvbuf(srcsh,NULL,_IOFBF,4000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for srcsh\n");
      exit(1);
   }

   if ((destin=fopen(destin_name,"wb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open DESTIN\n");
      exit(1);
   }

   if (setvbuf(destin,NULL,_IOFBF,25000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for destin\n");
      exit(1);
   }
   fseek(ix03file,0L,SEEK_END); max_ixfile=ftell(ix03file)/sizeof(keylistpix_rec); rewind(ix03file);
   fseek(srcsh,0L,SEEK_END); max_srcsh=ftell(srcsh)/sizeof(keylistpix_rec); rewind(srcsh);

   for (i=0;i<=max_srcsh-1;i++)
   {

      fread(&rec_srcsh,sizeof(keylistpix_rec),1,srcsh);
      keyfound =locate_ix03(rec_srcsh.keywordsfield,&rec_ix);
      if (keyfound >= 0)
      {
          rec_ix.keywords_rptr = -1;
          if (fwrite(&rec_ix,sizeof(keylistpix_rec),1,ix03file) < 1) schreibfehler();
      }
   }
   fflush(ix03file);
   rewind(ix03file);
   /* wrtxt("(Rebuilding index file: deleting keys) "); */
   for (i=0;i<=max_ixfile-1;i++)
   {
      fread(&rec_ix,sizeof(keylistpix_rec),1,ix03file);
      if (rec_ix.keywords_rptr > -1) 
      {
        if (fwrite(&rec_ix,sizeof(keylistpix_rec),1,destin) < 1) schreibfehler();
      }
   }
   fclose(ix03file);fclose(srcsh); fclose(destin);

}


void appendix03(char * destin_name, char * src_name)
{
   FILE * src;
   FILE * destin;
   long i;

   long  max_src;
   keylistpix_rec recd;

   if ((src=fopen(src_name,"rb"))==NULL)
   {
       fprintf(stderr,"\nProblem: Cannot open SRCL\n");
       exit(1);
   }

   if(setvbuf(src,NULL,_IOFBF,10000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for srcl\n");
      exit(1);
   }

   if ((destin=fopen(destin_name,"r+b"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open DESTIN\n");
      exit(1);
   }

   if (setvbuf(destin,NULL,_IOFBF,10000)!=0)
   {
      fprintf(stderr,"\nProblem: Failed to set up buffer for destin\n");
      exit(1);
   }

   fseek(src,0L,SEEK_END); max_src=ftell(src)/sizeof(keylistpix_rec); rewind(src);

   fseek(destin,0L,SEEK_END);
   rewind(src);
   for (i=0;i<=max_src-1;i++)
   {
      fread(&recd,sizeof(keylistpix_rec),1,src);
      if (fwrite(&recd,sizeof(keylistpix_rec),1,destin) < 1) schreibfehler();
   }
   fclose(src); fclose(destin);
}



int ok_appix03(char * destin_name, char * src_name)
{
   FILE * src;
   FILE * destin;
   keylistpix_rec src_rec, destin_rec;
   if ((src=fopen(src_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open SRCL\n");
      exit(1);
   }
   if ((destin=fopen(destin_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nProblem: Cannot open DESTIN\n");
      exit(1);
   }
   rewind(src);
   fseek(destin,-(long) sizeof(keylistpix_rec),SEEK_END);
   fread(&src_rec,sizeof(keylistpix_rec),1,src);
   fread(&destin_rec,sizeof(keylistpix_rec),1,destin);
   /* uncomment for debugging
   sprintf(wrtxtbu,"(src %s, destin %s)\n",src_rec.keywordsfield,destin_rec.keywordsfield);
   wrtxt(wrtxtbu);
   */
   fclose(src); fclose(destin);
   if (strcmp_fun(destin_rec.keywordsfield,src_rec.keywordsfield,SSTRING) < 1)
      return 1;
   else return 0;
}


long scanseq_ix03(const char * keyval, keylistpix_rec * recd, char * ix_name)
{
   FILE * ix_fp;
   long i, n;

   if ( filesize(ix_name) < sizeof(keylistpix_rec) )
   {
       return -1;
   }

   if ((ix_fp=fopen(ix_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nProblem in scanseq_ix03: "
           "cannot open %s\n",ix_name);
      exit(1);
   }
   if (setvbuf(ix_fp,NULL,_IOFBF,5000)!=0)
   {
      fprintf(stderr,"\nProblem in scanseq_ix03: cannot set up "
          "buffer for reading %s\n",ix_name);
      exit(1);
   }
   fseek(ix_fp,-(long) sizeof(keylistpix_rec),SEEK_END);
   n = (ftell(ix_fp)/sizeof(keylistpix_rec));
   rewind(ix_fp);
   for (i=0;i<=n;i++)
   {
      if (fread(recd,sizeof(keylistpix_rec),1,ix_fp)!=1)
      {
         fprintf(stderr,"\nProblem in scanseq_ix03: cannot "
             "read record in %s\n",ix_name);
         exit(1);
      }
      if (strcmp_fun(keyval,recd->keywordsfield,SSTRING)==0)
      {
          fseek(ix_fp,-(long) sizeof(keylistpix_rec),SEEK_CUR);
          fclose(ix_fp);
          return i;
      }
   }
   fclose(ix_fp);
   return -1;
}

