/*
    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
*/

/*
  sortix04.c
  sorts (index) file of 'abstrpix_rec'
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "refs.h"
#include "str_fun.h"
#include "fl_ut.h"
#include "interf.h"

  /* Indexdatei fuer Abstracts sortieren */

#define SORTARR04 10001
  /* so gross ist der Sortierarray fuer 32-Bit-Anwendungen */


 static FILE * sourcefile;
 static FILE * workfiles[4];
 static int filecnt, filenumber;
 static abstrpix_rec * strlist;  /* Die zu sortierenden Daten im Array */
 static int strcnt;
 static char filename[DATEINAME_LEN + 1];
 static int i,j;
 static char workfile_name[4] [DATEINAME_LEN + 1];

 extern char wrtxtbu[WRTXTBU_LEN + 1];


 static void mergeworkfiles(void);
 static int shsort_ix04(int n_i, abstrpix_rec a[]);



static void mergeworkfiles(void)
{
    FILE * mergedfile;
    int doneflags[4];
    int donecnt;
    abstrpix_rec topstrings[4];  /* struct anpassen */
    int min;
    long i_rec[4];
    long n_rec[4];
    donecnt = 0;

    for (i=1;i<=filecnt;i++)
    {
       fclose(workfiles[i]);
       i_rec[i]=0;
       if((workfiles[i]=fopen(workfile_name[i],"r+b"))==NULL)
       {
          sprintf(wrtxtbu,"Cannot open workfile %s\n",workfile_name[i]);
          wrtxt(wrtxtbu);
       }
       fseek(workfiles[i],0L,SEEK_END);
       n_rec[i]=ftell(workfiles[i])/sizeof(strlist[0]);
       rewind(workfiles[i]);
       if (!iseof(workfiles[i]))
       {
          doneflags[i] = 0;
          fread(&topstrings[i],sizeof(topstrings[0]),1,workfiles[i]);
          i_rec[i]++;
       }
       else
       {
          doneflags[i] = 1;
          donecnt++;
       }
    }

    strcpy(filename,"workfile.   ");

    j = filenumber;
    for (i=1;i<=3;i++)
    {
      filename[12-i] = '0' + (j % 10);
      j = j / 10;
    }

    filenumber++;
    if((mergedfile=fopen(filename,"wb"))==NULL)
    {
        fprintf(stderr,"\nProblem: Unable to open 'mergedfile'\n");
        exit(1);
    }
    while (donecnt < filecnt)
    {
      min = 1;
      while (doneflags[min]) min++;
      i = 1;
      while (i <= filecnt)
      {
         if ((!doneflags[i]) && (strcmp(topstrings[min].kennziffer,topstrings[i].kennziffer) > 0)) min = i; /* Vergleich */
         i++;
      }
      if (fwrite(&topstrings[min],sizeof(topstrings[0]),1,mergedfile) < 1) schreibfehler();
      if (i_rec[min] >= n_rec[min])
      {
         doneflags[min]=1;
         donecnt++;
      }
      else
      {
         fread(&topstrings[min],sizeof(topstrings[0]),1,workfiles[min]);
         i_rec[min]++;
      }
    }
    for (i=1;i<=filecnt;i++)
    {
       fclose(workfiles[i]);
       remove(workfile_name[i]);
    }
    fclose(mergedfile);
    strcpy(workfile_name[1],filename);
    if ((workfiles[1]=fopen(filename,"r+b"))==NULL)
    {
        fprintf(stderr,"\nProblem: Unable to open 'workfiles[1]'\n");
        exit(1);
    }
    rewind(workfiles[1]);
    filecnt = 1;
}

void domerge04(char * ein04_name, char * aus04_name)
{
   long n_rec, i_rec;
   if ((sourcefile=fopen(ein04_name,"rb"))==NULL)
   {
        fprintf(stderr,"\nProblem: Unable to open 'sourcefile'\n");
        exit(1);
   }
   fseek(sourcefile,0L,SEEK_END);

   if ((strlist = (abstrpix_rec *) malloc(SORTARR04 * sizeof(abstrpix_rec)))==NULL)  /* struct anpassen */
   {
        fprintf(stderr,"\nProblem: SORTIX04.C Cannot allocate enough "
           "memory for strlist\n");
        exit(1);
   }

   n_rec = ftell(sourcefile)/sizeof(strlist[0]);
   sprintf(wrtxtbu,"(Sorting %li records)\n",n_rec);
   wrtxt(wrtxtbu);
   rewind(sourcefile);
   filecnt=0;
   strcnt=0;
   filenumber=0;
   i_rec = 0;
   do
   {
      strcnt++;
      i_rec++;
      fread(&strlist[strcnt],sizeof(strlist[0]),1,sourcefile);
      if ((strcnt == SORTARR04 - 1) || (i_rec>=n_rec))
      {
         if (strcnt>1) shsort_ix04(strcnt,strlist);
         strcpy(filename,"workfile.   ");

         j = filenumber;
         for (i=1;i<=3;i++)
         {
           filename[12-i] = '0' + (j % 10);
           j = j / 10;
         }
         sprintf(wrtxtbu,"(%li (%.1f%%) done)\n",i_rec, 100.0*i_rec/n_rec);
         wrtxt(wrtxtbu);
         filenumber++;
         filecnt++;
         if ((workfiles[filecnt]=fopen(filename,"w+b"))==NULL)
         {
            fprintf(stderr,"\nProblem: Unable to open 'workfiles.nnn'\n");
            exit(1);
         }
         
         strcpy(workfile_name[filecnt],filename);
         rewind(workfiles[filecnt]);
         for (i=1;i<=strcnt;i++)
         {
            if (fwrite(&strlist[i],sizeof(strlist[0]),1,workfiles[filecnt]) < 1) schreibfehler();
         }
         if (filecnt==3) mergeworkfiles();
         strcnt = 0;
      }

   }  while (i_rec < n_rec);

   fclose (sourcefile);
   mergeworkfiles();
   rewind(workfiles[1]);

   fclose(workfiles[1]);
   wrtxt("(Sorting complete)\n");
   if (isfile(aus04_name)) remove(aus04_name);

   if(rename(workfile_name[1],aus04_name)!=0)
   {
        fprintf(stderr,"\nProblem: Unable to rename 'workfiles[1]'\n");
        exit(1);
   }
   free(strlist);
}



static int shsort_ix04(int n_i, abstrpix_rec a[])
{
      int i, j, h;
      abstrpix_rec v;
      for (h=1;h<=n_i/9;h=3*h+1);
      for(; h>0; h/=3)
        for (i=h+1;i <=n_i ; i+=1)
        {
           v = a[i]; j = i;
           while(j>h && strcmp(a[j-h].kennziffer,v.kennziffer) > 0)
           {  a[j] = a[j-h]; j -= h; }
           a[j] = v;
        }
        return 0;
}



#undef SORTARR04

