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


/*
   btch_fun.c: write/edit/process/convert BBT-, TBT-files
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "refs.h"
#include "str_fun.h"
#include "fl_ut.h"
#include "ix01_fun.h"
#include "sortbbf1.h"
#include "sortbbf2.h"
// #include "rglobal.h"
#include "interf.h"
#include "bbf_fun.h"
#include "initial.h"

#define TMP_BBDOLLAR "tmp.bb$"  /* name for tmpbbt_name */
#define TMP_BDOLLARDOLLAR "tmp.b$$"  /* name for out_bbt_name */
#define BBTZEILE_LEN 32000

 extern char textpfad[PFAD_LEN+1];
 extern char rdbpfad[PFAD_LEN+1];

 extern char journal_name[PFAD_LEN + 1];
 extern char journal_pix_name[PFAD_LEN + 1];
 extern char autorjl_name[PFAD_LEN + 1];
 extern char autorbu_name[PFAD_LEN + 1];
 extern char book_name[PFAD_LEN + 1];

 static char tmpbbt_name[PFAD_LEN + 1];


 extern char wrtxtbu[WRTXTBU_LEN + 1];

 extern journal_rec one_journal_rec;
 extern config_set one_config_set;

 extern FILE * fpjournal;
 extern FILE * fpautorjl;
 extern FILE * fpautorbu;
 extern FILE * fpbuch;

 extern FILE * ix01file;
 
 static FILE * tmpbbt;
 static FILE * fptext;
 static FILE * fpbbt;

 static char * zeile;
 static char * ex_zeile;
 static char * exex_zeile;

 static int btch_initialize(void);
 static int btch_aufraeumen(void);
 static int db_oeffnen(void);
 static void db_schliessen(void);
 static long verschluesseln(char * zeile);

 

static int btch_initialize(void)
{
   strlimcpy(tmpbbt_name,rdbpfad,PFAD_LEN);
   strlimcat(tmpbbt_name,TMP_BBDOLLAR,PFAD_LEN);
   if  ((zeile = (char *) malloc((BBTZEILE_LEN+1) * sizeof(char)))==NULL)
   {
      fprintf(stderr,"\nERROR in 'BatchT'-functions: cannot allocate memory for zeile\n");
      exit(1);
   }
   if  ((ex_zeile = (char *) malloc((BBTZEILE_LEN+1) * sizeof(char)))==NULL)
   {
      fprintf(stderr,"\nERROR in 'BatchT'-functions: cannot allocate memory for ex_zeile\n");
      exit(1);
   }
   if  ((exex_zeile = (char *) malloc((BBTZEILE_LEN+1) * sizeof(char)))==NULL)
   {
      fprintf(stderr,"\nERROR in 'BatchT'-functions: cannot allocate memory for exex_zeile\n");
      exit(1);
   }
    return 1;
}

static int btch_aufraeumen(void)
{
   free(zeile);
   free(ex_zeile);
   free(exex_zeile);
   if (isfile(tmpbbt_name))
   {
      remove(tmpbbt_name);
   }
   return 1;
}

int text2bbt(void)
{
   int ok, textpos, anzahl_token;
   char bbt_name[PFAD_LEN + 1];
   char datei[PFAD_LEN +1];
   char ex_datei[PFAD_LEN + 1];
   char pfad_wildcard[PFAD_LEN + 1]; /* 1st parameter in datei_suchen() */
   char text_name[PFAD_LEN + 1];
   bbatchtable_rec one_bbt_rec;

   ok = 1;
   textpos = 2;
   btch_initialize();
   
   /* begin: get file names */
   strlimcpy(pfad_wildcard,textpfad,PFAD_LEN);
   strlimcat(pfad_wildcard,"*.tbt",PFAD_LEN);
   // datei_suchen(pfad_wildcard,datei);
   datei_suchen(textpfad,"*.tbt",datei);
   if (strlen(datei) <= strlen(".tbt"))
   {
     sprintf(wrtxtbu,"\nProblem: cannot convert %s\n",datei);
     btch_aufraeumen(); 
     return 0;
   }
   strlimcpy(text_name,textpfad,PFAD_LEN);
   strlimcat(text_name,datei,PFAD_LEN);
   
   extract_subs(ex_datei,datei,0,strlen(datei)-strlen(".tbt"));
   strlimcat(ex_datei,".bbt",PFAD_LEN);
   strlimcpy(bbt_name,rdbpfad,PFAD_LEN);
   strlimcat(bbt_name,ex_datei,PFAD_LEN);
   /* end: get file names */

   if ((fpbbt=fopen(bbt_name,"wb"))==NULL)
   {
      sprintf(wrtxtbu,"\nERROR: Cannot create %s\n",bbt_name);
      wrtxt(wrtxtbu);
      btch_aufraeumen(); 
      return 0;
   }
   if ((fptext=fopen(text_name,"r"))==NULL)
   {
      fclose(fpbbt);
      sprintf(wrtxtbu,"\nERROR: Cannot open %s\n",text_name);
      wrtxt(wrtxtbu);
      btch_aufraeumen(); 
      return 0;
   }

   while (fgets(zeile,BBTZEILE_LEN,fptext)!=NULL)
   {
      memset(&one_bbt_rec,0,sizeof(one_bbt_rec));
      if (strlen(zeile) > BBTZEILE_LEN)
      {
         wrtxt("\n(Problem: line too long, conversion not completed)\n");
         ok = 0;   
         break;
      }
      if (zeile[0]!='*') continue;
      rtrim(zeile,'\n');
      anzahl_token=countitem(zeile,"*");
      if (anzahl_token < 1) continue;
      if (anzahl_token < textpos)
      {
         strcpy(one_bbt_rec.sortierfeld,"");
      }
      else
      {
         extractitem((int) textpos,zeile,"*",ex_zeile);
         trim(ex_zeile,' ');
         ex_zeile[SORTIERFELD_LEN]='\0';
         strcpy(one_bbt_rec.sortierfeld,ex_zeile);
      }
      extractitem(1,zeile,"*",ex_zeile);
      trim(ex_zeile,' ');
      if (strlen(ex_zeile)>KENNZIFFER_LEN) continue;
      if (strlen(ex_zeile)==0) continue; /* records with empty fields ignored */
      ex_zeile[KENNZIFFER_LEN]='\0';
      strcpy(one_bbt_rec.kennziffer,ex_zeile);

      if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt) < 1) schreibfehler();
   }
   if (ok==1)
   {
     sprintf(wrtxtbu,"\n(File `%s'\n  converted into `%s')\n",
       text_name,bbt_name);
     wrtxt(wrtxtbu);
     
     sprintf(wrtxtbu,"Batch file `%s'\n  converted into `%s'",
       text_name,bbt_name);
     protokollieren(wrtxtbu);
   }
   fclose(fpbbt);
   fclose(fptext);
   btch_aufraeumen(); 
   return 1;
}

int bbt2text(void)
{
   int ok;
   char bbt_name[PFAD_LEN + 1];
   char datei[PFAD_LEN +1];
   char ex_datei[PFAD_LEN + 1];
   char pfad_wildcard[PFAD_LEN + 1]; /* 1st parameter in datei_suchen() */
   char text_name[PFAD_LEN + 1];
   bbatchtable_rec one_bbt_rec;
   long i,  byte_zeiger, anzahl_records;

   ok = 1;
   btch_initialize();
   /* begin: get file names */
   strlimcpy(pfad_wildcard,rdbpfad,PFAD_LEN);
   strlimcat(pfad_wildcard,"*.bbt",PFAD_LEN);
   // datei_suchen(pfad_wildcard,datei);
   datei_suchen(rdbpfad,"*.bbt",datei);
   if (strlen(datei) <= strlen(".bbt"))
   {
     sprintf(wrtxtbu,"\nProblem: cannot convert %s\n",datei);
     btch_aufraeumen(); 
     return 0;
   }
   strlimcpy(bbt_name,rdbpfad,PFAD_LEN);
   strlimcat(bbt_name,datei,PFAD_LEN);

   extract_subs(ex_datei,datei,0,strlen(datei)-strlen(".bbt"));
   strlimcat(ex_datei,".tbt",PFAD_LEN);
   strlimcpy(text_name,textpfad,PFAD_LEN);
   strlimcat(text_name,ex_datei,PFAD_LEN);

   /* end: get file names */

   if ((fpbbt=fopen(bbt_name,"rb"))==NULL)
   {
       sprintf(wrtxtbu,"\nCannot read %s\n",bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return 0;
   }

   if ((fptext=fopen(text_name,"w"))==NULL)
   {
       sprintf(wrtxtbu,"\nCannot create %s\n",text_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen(); 
       return 0;
   }
   fseek(fpbbt,0L,SEEK_END);
   byte_zeiger = ftell(fpbbt);
   anzahl_records = byte_zeiger / sizeof(one_bbt_rec);
   anzahl_records--;
   rewind(fpbbt);
   for (i=0;i<=anzahl_records;i++)
   {
      fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt);
      fprintf(fptext,"* %-*s * %-*s *\n",
         KENNZIFFER_LEN,
         one_bbt_rec.kennziffer,
         SORTIERFELD_LEN,
         one_bbt_rec.sortierfeld);
   }
   
   sprintf(wrtxtbu,"\n(File `%s'\n  converted into `%s')\n",
       bbt_name,text_name);
   wrtxt(wrtxtbu);
   sprintf(wrtxtbu,"\nBatch file `%s'\n  converted into `%s'",
       bbt_name,text_name);
   protokollieren(wrtxtbu);
   fclose(fpbbt);
   fclose(fptext);
   
   btch_aufraeumen(); 
   return 1;
}

void copy_all_records(void)
{
   bbatchtable_rec one_bbt_rec;
   long i, anzahl_records, byte_zeiger;
   char eingabe[PFAD_LEN + 1];
   char bbt_name[PFAD_LEN + 1];
   refspix_rec ix01rec;

   btch_initialize();
   if (!dateivornamen_holen(eingabe,"Please enter filename for bbt-file, "
      "`.bbt' will be appended"))
   {
      wrtxt("\n(No valid filename, creating bbt-file aborted)\n");
      btch_aufraeumen();
      return;
   }
   strlimcpy(bbt_name,rdbpfad,PFAD_LEN);
   strlimcat(bbt_name,eingabe,PFAD_LEN);
   strlimcat(bbt_name,".bbt",PFAD_LEN);
   
   if (isfile(bbt_name))
   {
      if (!do_overwrite_yn())
      {
         btch_aufraeumen();
         wrtxt("\n(Creating bbt-file aborted)\n");
         return;
      }
   }

   if ((ix01file=fopen(journal_pix_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nERROR: Cannot read %s\n",journal_pix_name);
      btch_aufraeumen();
      return;
   }
   if ((fpbbt=fopen(bbt_name,"wb"))==NULL)
   {
      fprintf(stderr,"\nERROR: Cannot create %s\n",bbt_name);
      btch_aufraeumen();
      fclose(fpbbt);
      return;
   }
   fseek(ix01file,0L,SEEK_END);
   byte_zeiger = ftell(ix01file);
   anzahl_records = byte_zeiger / sizeof(ix01rec);
   anzahl_records--;

   rewind(ix01file);
   // memset(&one_bbt_rec,0,sizeof(one_bbt_rec));
   memset(&ix01rec,0,sizeof(ix01rec));
   sprintf(wrtxtbu,"\n(Writing %s with all reference numbers)\n",bbt_name);
   wrtxt(wrtxtbu);
   for (i=0;i<=anzahl_records;i++)
   {
       memset(&one_bbt_rec,0,sizeof(one_bbt_rec));
       fread(&ix01rec,sizeof(ix01rec),1,ix01file);
       strncpy(one_bbt_rec.kennziffer,ix01rec.kennziffer,KENNZIFFER_LEN+1);
       if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt) < 1) schreibfehler();
   }
   fclose(fpbbt);
   fclose(ix01file);
   sprintf(wrtxtbu,"\n(Completed, %s created)\n",bbt_name);
   wrtxt(wrtxtbu);
   sprintf(wrtxtbu,"\nBatch file `%s'\n  with all reference "
     "numbers created",bbt_name);
   protokollieren(wrtxtbu);
   btch_aufraeumen();
}


int enternameyear(void)
{
    long byte_zeiger, ix_zeiger, anzahl_records, i;
    char                bbt_name[PFAD_LEN +  1];
    bbatchtable_rec     one_bbt_rec;
    refspix_rec         ix01rec;
    journal_rec         one_journal_rec;
    author_rec          one_aued_rec;

    char sortierstring[SORTIERFELD_LEN+20];

    btch_initialize();
    if (!datei_suchen_mit_pfad("*.BBT",
                                rdbpfad,
                                bbt_name))
    {
       btch_aufraeumen();
       return 0;
    }

    if (filesize(bbt_name) < sizeof(one_bbt_rec))
    {
       sprintf(wrtxtbu,"\n(%s is empty, aborted)\n",bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return 0;
    }
    if ((fpbbt=fopen(bbt_name,"rb"))==NULL)
    {
        sprintf(wrtxtbu,"\n(ERROR: Cannot read %s)\n",bbt_name);
        wrtxt(wrtxtbu);
        btch_aufraeumen();
        return 0;
    }
    if (setvbuf(fpbbt,NULL,_IOFBF,15000)!=0)
    {
        sprintf(wrtxtbu,"\n(ERROR: Unable to allocate memory for buffering %s)\n",bbt_name);
        wrtxt(wrtxtbu);
        fclose(fpbbt);
        btch_aufraeumen();
        return 0;
    }
    if ((tmpbbt=fopen(tmpbbt_name,"wb"))==NULL)
    {
        sprintf(wrtxtbu,"\n(ERROR: Cannot create %s)\n",tmpbbt_name);
        wrtxt(wrtxtbu);
        fclose(fpbbt);
        btch_aufraeumen();
        return 0;
    }
    if (setvbuf(tmpbbt,NULL,_IOFBF,12000)!=0)
    {
        sprintf(wrtxtbu,"\n(ERROR: Unable to allocate memory "
          "for buffering %s)\n",tmpbbt_name);
        wrtxt(wrtxtbu);
        fclose(fpbbt);
        fclose(tmpbbt);
        btch_aufraeumen();
        return 0;
    }

    if (!db_oeffnen())
    {
        fclose(fpbbt);
        fclose(tmpbbt);
        btch_aufraeumen();
        return 0;
    }
    fseek(fpbbt,0L,SEEK_END);
    byte_zeiger = ftell(fpbbt);
    anzahl_records = byte_zeiger / sizeof(one_bbt_rec);
    anzahl_records--;
    rewind(fpbbt);
    sprintf(wrtxtbu,"\n(Searching names and publication years "
     "for %li references)\n",anzahl_records+1);
    wrtxt(wrtxtbu);
    for (i=0;i<=anzahl_records;i++)
    {
       fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt);
       ix_zeiger = locate_ix01(one_bbt_rec.kennziffer,&ix01rec);
       if (ix_zeiger!=-1)
       {
          byte_zeiger = ix01rec.journal_rptr * sizeof(one_journal_rec);
          fseek(fpjournal,byte_zeiger,SEEK_SET);
          fread(&one_journal_rec,sizeof(one_journal_rec),1,fpjournal);
          if ((!strcmp(one_journal_rec.reftyp,"j1")) ||
            (!strcmp(one_journal_rec.reftyp,"b2")) ||
            (!strcmp(one_journal_rec.reftyp,"m1")))
          {
            byte_zeiger = ix01rec.autorjl_rptr * sizeof(one_aued_rec);
            fseek(fpautorjl,byte_zeiger,SEEK_SET);
            fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);
          }
          else if (!strcmp(one_journal_rec.reftyp,"b1"))
          {
            byte_zeiger = ix01rec.autorbu_rptr * sizeof(one_aued_rec);
            fseek(fpautorbu,byte_zeiger,SEEK_SET);
            fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
          }
          else /* ... j2, b3, m2 */
          {
            strlimcpy(one_aued_rec.au_nachname,one_journal_rec.instau,
              AUNAME_LEN);
            strcpy(one_aued_rec.au_vornamen,"");
          }
          sprintf(sortierstring,"%*s%*s%*s",
              -AUNAME_LEN,one_aued_rec.au_nachname,
              -AUVORNAMEN_LEN,one_aued_rec.au_vornamen,
              -JAHRGANG_LEN,one_journal_rec.jahrgang
                  );
          sortierstring[SORTIERFELD_LEN] = '\0';
          upper(sortierstring);
          strncpy(one_bbt_rec.sortierfeld,sortierstring,SORTIERFELD_LEN+1);

          if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,tmpbbt) < 1) schreibfehler();
       }
       /* begin new for version 4.1g */
       else
       {
          strlimcpy(one_bbt_rec.sortierfeld,"..",SORTIERFELD_LEN);
          strlimcat(one_bbt_rec.sortierfeld,one_bbt_rec.kennziffer,
            SORTIERFELD_LEN);
          strlimcat(one_bbt_rec.sortierfeld,"..",
            SORTIERFELD_LEN);
          if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,tmpbbt) < 1) schreibfehler();
       }
       /* end new for version 4.1g */
    }
    sprintf(wrtxtbu,"Author and year data written into text field\n"
      "  of `%s' batch file",bbt_name);
    protokollieren(wrtxtbu);
    fclose(fpbbt);
    fclose(tmpbbt);
    db_schliessen();
    remove(bbt_name);
    rename(tmpbbt_name,bbt_name);
    btch_aufraeumen();
    return 1;
}

static int db_oeffnen(void)
{
     if ((fpjournal=fopen(journal_name,"rb"))==NULL)
     {
        sprintf(wrtxtbu,"\n(ERROR: Cannot read %s)\n",journal_name);
        wrtxt(wrtxtbu);
        return 0;
     }
     if ((ix01file=fopen(journal_pix_name,"rb"))==NULL)
     {
        sprintf(wrtxtbu,"\n(ERROR: Cannot read %s)\n",journal_pix_name);
        wrtxt(wrtxtbu);
        fclose(fpjournal);
        return 0;
     }
     if ((fpautorjl=fopen(autorjl_name,"rb"))==NULL)
     {
        fclose(fpjournal);
        fclose(ix01file);
        sprintf(wrtxtbu,"\n(ERROR: Cannot read %s)\n",autorjl_name);
        wrtxt(wrtxtbu);
        return 0;
     }
     if ((fpautorbu=fopen(autorbu_name,"rb"))==NULL)
     {
        fclose(fpjournal);
        fclose(ix01file);
        fclose(fpautorjl);
        sprintf(wrtxtbu,"\n(ERROR: Cannot read %s)\n",autorbu_name);
        wrtxt(wrtxtbu);
        return 0;
     }
   return 1;
}

static void db_schliessen(void)
{
  fclose(fpjournal);
  fclose(ix01file);
  fclose(fpautorjl);
  fclose(fpautorbu);
}

void sortbbt_recno(void)
{
    char bbt_name[PFAD_LEN +  1];
    btch_initialize();
    if (!datei_suchen_mit_pfad("*.BBT",rdbpfad,bbt_name))
    {
       wrtxt("\n(Please press any key)\n");
       btch_aufraeumen();
       return;
    }

    if (filesize(bbt_name) <= sizeof(bbatchtable_rec))
    {
       sprintf(wrtxtbu,"\n(%s is empty or contains "
         "only one record)\n",bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return;
    }
    wrtxt("\n");
    domergebbf1(bbt_name,tmpbbt_name);
    remove(bbt_name);
    rename(tmpbbt_name,bbt_name);
    sprintf(wrtxtbu,"Batch file sorted (reference numbers):\n  `%s'",bbt_name);
    protokollieren(wrtxtbu);
    wrtxt("\n");
    btch_aufraeumen();
}

void sortbbt_text(void)
{
    char     bbt_name[PFAD_LEN +  1];
    btch_initialize();
    if (!datei_suchen_mit_pfad("*.BBT",rdbpfad,bbt_name))
    {
       wrtxt("\n(Please press any key)\n");
       btch_aufraeumen();
       return;
    }

    if (filesize(bbt_name) <= sizeof(bbatchtable_rec))
    {
       sprintf(wrtxtbu,"\n(%s is empty or contains "
         "only one record)\n",bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return;
    }
    wrtxt("\n");
    domergebbf2(bbt_name,tmpbbt_name);
    remove(bbt_name);
    rename(tmpbbt_name,bbt_name);
    sprintf(wrtxtbu,"Batch file sorted (text field):\n  `%s'",bbt_name);
    protokollieren(wrtxtbu);
    wrtxt("\n");
    btch_aufraeumen();
}

int remove_double_but_1st(void)
{
    long anzahl_records, i, j;
    char bbt_name[PFAD_LEN + 1];
    bbatchtable_rec new_bbt_rec, old_bbt_rec;
    int schon_vorhanden;
    long byte_zeiger;

    btch_initialize();

    
    if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_name))
    {
       wrtxt("\n(aborted)\n");
       return 0;
    }
    if ((fpbbt=fopen(bbt_name,"rb"))==NULL)
    {
       fprintf(stderr,"\nERROR: unable to read %s\n",bbt_name);
       exit(1);
    }
    if ((tmpbbt=fopen(tmpbbt_name,"wb"))==NULL)
    {
       fprintf(stderr,"\nERROR: unable to create %s\n",tmpbbt_name);
       exit(1);
    }

    fseek(fpbbt,0L,SEEK_END);
    byte_zeiger = ftell(fpbbt);
    anzahl_records = byte_zeiger / sizeof(new_bbt_rec);
    anzahl_records--;
    rewind(fpbbt);
    wrtxt("\n(Extracting duplicate records from BBT-file)\n");
    if (anzahl_records<=0)
    {
       fclose(fpbbt);
       fclose(tmpbbt);
       wrtxt("\n(Aborted, bbt-files with less than 2 records are "
         "not processed)\n");
       return 0;
    }
    fread(&new_bbt_rec,sizeof(new_bbt_rec),1,fpbbt);
    if (fwrite(&new_bbt_rec,sizeof(new_bbt_rec),1,tmpbbt) < 1) schreibfehler();
    old_bbt_rec = new_bbt_rec;
    for (i=1;i<=anzahl_records;i++)
    {
        byte_zeiger = i * sizeof(new_bbt_rec);
        fseek(fpbbt,byte_zeiger,SEEK_SET);
        fread(&new_bbt_rec,sizeof(new_bbt_rec),1,fpbbt);
        schon_vorhanden = 0;
        fseek(fpbbt,0L,SEEK_SET);
        for (j=0;j<i;j++)
        {
           fread(&old_bbt_rec,sizeof(old_bbt_rec),1,fpbbt);
           if (!strcmp(new_bbt_rec.kennziffer,old_bbt_rec.kennziffer))
           {
              schon_vorhanden=1;
              break;
           }
        }
        if (!schon_vorhanden)
        {
           if (fwrite(&new_bbt_rec,sizeof(new_bbt_rec),1,tmpbbt) < 1) schreibfehler();
        }
    }

    fclose(fpbbt);
    fclose(tmpbbt);
    remove(bbt_name);
    rename(tmpbbt_name,bbt_name);

    sprintf(wrtxtbu,"Duplicate records removed (only 1st occurrence of each "
      "\n  reference number preserved)\n  in `%s'",bbt_name);
    protokollieren(wrtxtbu);

    wrtxt("\n(Completed)\n");
    btch_aufraeumen();
    return 1;
}

int write_urid(void)
{
     long byte_zeiger, i, j, anzahl_records, ix_zeiger;
     bbatchtable_rec     one_bbt_rec;
     char bbt_name[PFAD_LEN +1];
     refspix_rec         ix01rec;
     journal_rec         one_journal_rec;
     author_rec          one_aued_rec;
     buch_rec            one_buch_rec;
     long titel_kennung, autoren_kennung;
     char kennstring[SORTIERFELD_LEN+1];
     int caseins;  /* 0: case insensitive 1: case sensitive */
     int taste;
     static char ein[INPUT_BU_LEN+1];

     btch_initialize();
     strcpy(ein,"menu");
     wrtxt("\nMenu: write unique case identifier case sensitive/insensitive [s/i/q]\n");
     taste = menu_wahl(ein,
       "[s] case sensitive\n"
       "[i] case insensitive\n"
       "[q] quit"
       );
     
     if (taste==3) 
     {
        btch_aufraeumen();
        return 0;
     }
     if (taste==1) 
     {
        caseins = 0;
     }
     else 
     {
        caseins = 1;
     }

     if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_name))
     {
       btch_aufraeumen();
       wrtxt("\n(aborted)\n");
       return 0;
     }
     if (filesize(bbt_name) < sizeof(one_bbt_rec))
     {
        sprintf(wrtxtbu,"\n(File %s is empty, aborted)\n",
          bbt_name);
        wrtxt(wrtxtbu);
        btch_aufraeumen();
        return 0;
     }

     if ((fpbbt=fopen(bbt_name,"rb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot read %s\n",bbt_name);
         exit(1);
     }
     if (setvbuf(fpbbt,NULL,_IOFBF,5000)!=0)
     {
         fprintf(stderr,"\nERROR: Unable to allocate memory " 
           "for buffering %s\n",bbt_name);
         exit(1);
     }
     if ((tmpbbt=fopen(tmpbbt_name,"wb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot create %s\n",tmpbbt_name);
         exit(1);
     }
     if (setvbuf(tmpbbt,NULL,_IOFBF,2000)!=0)
     {
         fprintf(stderr,"\nERROR: Unable to allocate memory " 
           "for buffering %s\n",tmpbbt_name);
         exit(1);
     }
     if ((fpjournal=fopen(journal_name,"rb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot read %s\n",journal_name);
         exit(1);
     }
     if ((ix01file=fopen(journal_pix_name,"rb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot read %s\n",journal_pix_name);
         exit(1);
     }
     if ((fpautorjl=fopen(autorjl_name,"rb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot read %s\n",autorjl_name);
         exit(1);
     }
     if ((fpautorbu=fopen(autorbu_name,"rb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot read %s\n",autorbu_name);
         exit(1);
     }
     if ((fpbuch=fopen(book_name,"rb"))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot read %s\n",book_name);
         exit(1);
     }
     fseek(fpbbt,0L,SEEK_END);
     byte_zeiger = ftell(fpbbt);
     anzahl_records = byte_zeiger / sizeof(one_bbt_rec);
     anzahl_records--;
     rewind(fpbbt);
     wrtxt("\n(Writing unique identifiers)\n");
     for (i=0;i<=anzahl_records;i++)
     {
         titel_kennung = 0;
         autoren_kennung = 0;
         memset(&one_bbt_rec,0,sizeof(one_bbt_rec));
         fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt);
         ix_zeiger = locate_ix01(one_bbt_rec.kennziffer,&ix01rec);
         if (ix_zeiger>-1)
         {
            byte_zeiger = ix01rec.journal_rptr*sizeof(one_journal_rec);
            fseek(fpjournal,byte_zeiger,SEEK_SET);
            fread(&one_journal_rec,sizeof(one_journal_rec),1,fpjournal);

            if ((!strcmp(one_journal_rec.reftyp,"j1")) ||
                (!strcmp(one_journal_rec.reftyp,"m1")))
            {
                if (caseins) upper (one_journal_rec.reftyp);
                if (caseins) upper (one_journal_rec.titel);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.titel);
                if (caseins) upper (one_journal_rec.seite_von);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_von);
                if (caseins) upper (one_journal_rec.seite_bis);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_bis);
                byte_zeiger = ix01rec.autorjl_rptr * sizeof(one_aued_rec);
                fseek(fpautorjl,byte_zeiger,SEEK_SET);
                fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);
                fseek(fpautorjl,byte_zeiger,SEEK_SET);
                for (j=1;j <= one_aued_rec.au_n;j++)
                {
                  fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);

                  if (caseins) upper (one_aued_rec.au_nachname);
                  autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_nachname);
                  if (caseins) upper (one_aued_rec.au_vornamen);
                   autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_vornamen);
                    if (j >= 20) break;
                }

            }  /* Ende j1, m1 */
            
            if ((!strcmp(one_journal_rec.reftyp,"j2")) ||
              (!strcmp(one_journal_rec.reftyp,"m2")))
            {
                if (caseins) upper (one_journal_rec.reftyp);
                if (caseins) upper (one_journal_rec.titel);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.titel);
                if (caseins) upper (one_journal_rec.seite_von);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_von);
                if (caseins) upper (one_journal_rec.seite_bis);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_bis);
                // byte_zeiger = ix01rec.autorjl_rptr * sizeof(one_aued_rec);
                // fseek(fpautorjl,byte_zeiger,SEEK_SET);
                // fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);
                // fseek(fpautorjl,byte_zeiger,SEEK_SET);
                // for (j=1;j <= one_aued_rec.au_n;j++)
                // {
                //   fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);

                //   if (caseins) upper (one_aued_rec.au_nachname);
                //   autoren_kennung = autoren_kennung +
                //        verschluesseln(one_aued_rec.au_nachname);
                //   if (caseins) upper (one_aued_rec.au_vornamen);
                //    autoren_kennung = autoren_kennung +
                //        verschluesseln(one_aued_rec.au_vornamen);
                //     if (j >= 20) break;
                // }
                if (caseins) upper (one_journal_rec.instau);
                autoren_kennung = verschluesseln(one_journal_rec.instau);

            }  /* Ende j2, m2 */
            
            else if (!strcmp(one_journal_rec.reftyp,"b1"))
            {
                if (caseins) upper (one_journal_rec.reftyp);
                byte_zeiger = ix01rec.buch_rptr*sizeof(one_buch_rec);
                fseek(fpbuch,byte_zeiger,SEEK_SET);
                if (fread(&one_buch_rec,sizeof(one_buch_rec),1,fpbuch)!=1)
                {
                   fprintf(stderr,"\nERROR: cannot read %s\n",book_name);
                   exit(1);
                }
                if (caseins) upper (one_buch_rec.titel_bu);
                titel_kennung = titel_kennung +
                    verschluesseln(one_buch_rec.titel_bu);
                if (caseins) upper (one_buch_rec.verlag);
                titel_kennung = titel_kennung +
                    verschluesseln(one_buch_rec.verlag);
                if (caseins) upper (one_journal_rec.seite_von);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_von);
                if (caseins) upper (one_journal_rec.seite_bis);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_bis);
                if (caseins) upper (one_journal_rec.band);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.band);
                byte_zeiger = ix01rec.autorbu_rptr * sizeof(one_aued_rec);
                fseek(fpautorbu,byte_zeiger,SEEK_SET);
                fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
                fseek(fpautorbu,byte_zeiger,SEEK_SET);
                for (j=1;j <= one_aued_rec.au_n;j++)
                {
                  fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
                  if (caseins) upper (one_aued_rec.au_nachname);
                  autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_nachname);
                  if (caseins) upper (one_aued_rec.au_vornamen);
                  autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_vornamen);
                    if (j >= 20) break;
                }
            }  /* Ende b1 */
            else if (!strcmp(one_journal_rec.reftyp,"b2"))
            {
                if (caseins) upper (one_journal_rec.reftyp);
                byte_zeiger = ix01rec.buch_rptr*sizeof(one_buch_rec);
                fseek(fpbuch,byte_zeiger,SEEK_SET);
                if (fread(&one_buch_rec,sizeof(one_buch_rec),1,fpbuch)!=1)
                {
                   fprintf(stderr,"\nERROR: cannot read %s\n",book_name);
                   exit(1);
                }
                if (caseins) upper (one_buch_rec.titel_bu);
                titel_kennung = titel_kennung +
                    verschluesseln(one_buch_rec.titel_bu);
                if (caseins) upper (one_buch_rec.verlag);
                titel_kennung = titel_kennung +
                    verschluesseln(one_buch_rec.verlag);
                if (caseins) upper (one_journal_rec.titel);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.titel);
                if (caseins) upper (one_journal_rec.seite_von);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_von);
                if (caseins) upper (one_journal_rec.seite_bis);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_bis);
                if (caseins) upper (one_journal_rec.band);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.band);

                byte_zeiger = ix01rec.autorjl_rptr * sizeof(one_aued_rec);
                fseek(fpautorjl,byte_zeiger,SEEK_SET);
                fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);
                fseek(fpautorjl,byte_zeiger,SEEK_SET);
                for (j=1;j <= one_aued_rec.au_n;j++)
                {
                  fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorjl);
                  if (caseins) upper (one_aued_rec.au_nachname);
                  autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_nachname);
                   if (caseins) upper (one_aued_rec.au_vornamen);
                   autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_vornamen);
                    if (j >= 20) break;
                }

                byte_zeiger = ix01rec.autorbu_rptr * sizeof(one_aued_rec);
                fseek(fpautorbu,byte_zeiger,SEEK_SET);
                fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
                fseek(fpautorbu,byte_zeiger,SEEK_SET);
                for (j=1;j <= one_aued_rec.au_n;j++)
                {
                  fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
                  if (caseins) upper (one_aued_rec.au_nachname);
                  autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_nachname);
                  if (caseins) upper (one_aued_rec.au_vornamen);
                   autoren_kennung = autoren_kennung +
                       verschluesseln(one_aued_rec.au_vornamen);
                    if (j >= 20) break;
                }


            }  /* Ende b2 */
            else if (!strcmp(one_journal_rec.reftyp,"b3"))
            {
                if (caseins) upper (one_journal_rec.reftyp);
                byte_zeiger = ix01rec.buch_rptr*sizeof(one_buch_rec);
                fseek(fpbuch,byte_zeiger,SEEK_SET);
                if (fread(&one_buch_rec,sizeof(one_buch_rec),1,fpbuch)!=1)
                {
                   fprintf(stderr,"\nERROR: cannot read %s\n",book_name);
                   exit(1);
                }
                if (caseins) upper (one_buch_rec.titel_bu);
                titel_kennung = titel_kennung +
                    verschluesseln(one_buch_rec.titel_bu);
                if (caseins) upper (one_buch_rec.verlag);
                titel_kennung = titel_kennung +
                    verschluesseln(one_buch_rec.verlag);
                if (caseins) upper (one_journal_rec.seite_von);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_von);
                if (caseins) upper (one_journal_rec.seite_bis);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.seite_bis);
                if (caseins) upper (one_journal_rec.band);
                titel_kennung = titel_kennung +
                    verschluesseln(one_journal_rec.band);
                // byte_zeiger = ix01rec.autorbu_rptr * sizeof(one_aued_rec);
                // fseek(fpautorbu,byte_zeiger,SEEK_SET);
                // fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
                // fseek(fpautorbu,byte_zeiger,SEEK_SET);
                // for (j=1;j <= one_aued_rec.au_n;j++)
                // {
                //   fread(&one_aued_rec,sizeof(one_aued_rec),1,fpautorbu);
                //   if (caseins) upper (one_aued_rec.au_nachname);
                //   autoren_kennung = autoren_kennung +
                //        verschluesseln(one_aued_rec.au_nachname);
                //   if (caseins) upper (one_aued_rec.au_vornamen);
                //   autoren_kennung = autoren_kennung +
                //        verschluesseln(one_aued_rec.au_vornamen);
                //     if (j >= 20) break;
                // }
                if (caseins) upper (one_buch_rec.insted);
                autoren_kennung = verschluesseln(one_buch_rec.insted);
            }  /* Ende b3 */
            
            sprintf(kennstring,"%s-%03lX-%08lX-%08lX",
                    one_journal_rec.reftyp,
                    verschluesseln(one_journal_rec.jahrgang),
                    titel_kennung,
                    autoren_kennung
                   );
            strcpy(one_bbt_rec.sortierfeld,kennstring);
            strcpy(one_bbt_rec.kennziffer,ix01rec.kennziffer);
            if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,tmpbbt) < 1) schreibfehler();
         }
     }
     fclose(fpbbt);
     fclose(tmpbbt);
     fclose(fpjournal);
     close_ix01();
     fclose(fpautorjl);
     fclose(fpautorbu);
     fclose(fpbuch);
     remove(bbt_name);
     rename(tmpbbt_name,bbt_name);
     wrtxt("\n(Completed)\n");
     sprintf(wrtxtbu,"Unique identifiers writen into text fields of\n"
       "  `%s'",bbt_name);
     protokollieren(wrtxtbu);
     btch_aufraeumen();
    return 1;
}

static long verschluesseln(char * zeile)
{
    unsigned char zeichen;
    unsigned int i;
    unsigned int laenge;
    long zaehler;

    zaehler = 0;
    if (strlen(zeile) == 0) return 0L;
    laenge = strlen (zeile);
    for (i=0;i<laenge;i++)
    {
       zeichen = zeile[i];
       if (zeichen != ' ' &&
           zeichen != '.' &&
           zeichen != ',' &&
           zeichen != '?' &&
           zeichen != '-' &&
           zeichen != '\"' &&
           zeichen != '\'' &&
           zeichen != '-' &&
           zeichen != ')' &&
           zeichen != '(' &&
           zeichen != '!' &&
           zeichen != ';'
           )
       zaehler = zaehler + zeichen;
    }
    return zaehler;
}

void extract_range(void)
{
   char bbt_name[PFAD_LEN + 1];
   bbatchtable_rec one_bbt_rec;
   long i,  byte_zeiger;
   long ix_unten, ix_oben, ix_temp;
   refspix_rec ix01rec;


   btch_initialize();
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_name))
   {
      wrtxt("\n(No file selected)\n");
      btch_aufraeumen();
      return;
   }
   if (filesize(bbt_name) < (2 * sizeof(one_bbt_rec)))
   {
      sprintf(wrtxtbu,"\n(File %s with less than 2 records, aborted)\n",
        bbt_name);
      wrtxt(wrtxtbu);
      btch_aufraeumen();
      return;
   }
   if ((fpbbt=fopen(bbt_name,"rb"))==NULL)
   {
       sprintf(wrtxtbu,"\nCannot read %s\n",bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return;
   }
   rewind(fpbbt);
   fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt);
   if (!read_ix01(journal_pix_name))
   {
      fclose(fpbbt);
      exit(1);
   }
   ix_unten = locate_ix01(one_bbt_rec.kennziffer,&ix01rec);
   if (ix_unten == -1)
   {
       sprintf(wrtxtbu,"\nReference number `%s' not in database\n",
         one_bbt_rec.kennziffer);
       wrtxt(wrtxtbu);
       fclose(fpbbt);
       close_ix01();
       btch_aufraeumen();
       return;
   }
   fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt);
   ix_oben = locate_ix01(one_bbt_rec.kennziffer,&ix01rec);
   if (ix_oben== -1)
   {
       sprintf(wrtxtbu,"\nReference number `%s' not in database\n",
         one_bbt_rec.kennziffer);
       wrtxt(wrtxtbu);
       fclose(fpbbt);
       close_ix01();
       btch_aufraeumen();
       return;
   }
   if (ix_oben==ix_unten)
   {
       sprintf(wrtxtbu,"\nTwo identical reference numbers, aborted\n");
       wrtxt(wrtxtbu);
       fclose(fpbbt);
       close_ix01();
       btch_aufraeumen();
       return;
   }
   if (ix_oben < ix_unten)
   {
     ix_temp = ix_oben;
     ix_oben = ix_unten;
     ix_unten = ix_temp;
   }
   
   if ((tmpbbt=fopen(tmpbbt_name,"wb"))==NULL)
   {
       sprintf(wrtxtbu,"\nCannot write/create %s\n",bbt_name);
       wrtxt(wrtxtbu);
       fclose(fpbbt);
       close_ix01();
       btch_aufraeumen();
       return;
   }
   byte_zeiger = ix_unten *  sizeof(ix01rec);
   fseek(ix01file,byte_zeiger,SEEK_SET);
   for (i=ix_unten;i<=ix_oben;i++)
   {
      fread(&ix01rec,sizeof(ix01rec),1,ix01file);
      memset(&one_bbt_rec,0,sizeof(one_bbt_rec));
      strlimcpy(one_bbt_rec.kennziffer,ix01rec.kennziffer,KENNZIFFER_LEN);
      if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,tmpbbt) < 1) schreibfehler();
   }
   close_ix01();
   fclose(fpbbt);
   fclose(tmpbbt);
   remove(bbt_name);
   rename(tmpbbt_name,bbt_name);

   sprintf(wrtxtbu,"\n(Completed: file\n  `%s'\nwith "
     "range of record numbers)\n",
     bbt_name);
   wrtxt(wrtxtbu);
   sprintf(wrtxtbu,"Batch file `%s'\n"
     "  with range of reference numbers written",bbt_name);
   protokollieren(wrtxtbu);
   btch_aufraeumen();
   return;
}

void remove_double_keys(void)
{
    char bbt_name[PFAD_LEN + 1];

    btch_initialize();
    if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_name))
    {
       wrtxt("\n(No file selected)\n");
       btch_aufraeumen();
       return;
    }
    if (filesize(bbt_name) <= sizeof(bbatchtable_rec))
    {
       sprintf(wrtxtbu,"\n(File `%s' is empty or contains "
         "only one record)\n",bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return;
    }
    wrtxt("\n");
    domergebbf1(bbt_name,tmpbbt_name);
    remove(bbt_name);
    dupl_ex_bbf(tmpbbt_name,bbt_name);
    remove(tmpbbt_name);
    wrtxt("\n");
    sprintf(wrtxtbu,"Duplicate records removed (records sorted by "
      "reference number)\n  in `%s'",bbt_name);
    protokollieren(wrtxtbu);
    btch_aufraeumen();
    return;
}

int extract_text_duplicates(void)
{
   // static char eingabe[PFAD_LEN + 1];
   bbatchtable_rec new_bbt_rec, old_bbt_rec;
   char in_bbt_name[PFAD_LEN + 1];
   FILE * fpinbbt;
   char out_bbt_name[PFAD_LEN + 1];
   FILE * fpoutbbt;
   int records_transferred;
   long i, anzahl_records;
       /* last comparison equal: 0 no 1 yes */
   int lce;
       /* in_bbt_name sorted? 0 no 1 yes */
   int in_sortiert;

   btch_initialize();
  
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,in_bbt_name))
   {
      wrtxt("\n(Aborted, no file selected)\n");
      btch_aufraeumen();
      return 0;
   }
   strlimcpy(out_bbt_name,rdbpfad,PFAD_LEN);
   strlimcat(out_bbt_name,TMP_BDOLLARDOLLAR,PFAD_LEN);

   if (filesize(in_bbt_name) < sizeof(new_bbt_rec)*2)
   {
       sprintf(wrtxtbu,"\n(File `%s' contains < 2 records, "
         "please press any key)\n",in_bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return 0;
   }

   if ((fpinbbt=fopen(in_bbt_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nERROR: unable to read %s\n",in_bbt_name);
      exit(1);
   }

   memset(&new_bbt_rec,0L,sizeof(new_bbt_rec));
   memset(&old_bbt_rec,0L,sizeof(old_bbt_rec));

   in_sortiert = 1;
   fseek(fpinbbt,0L,SEEK_END);
   anzahl_records = ftell(fpinbbt)/sizeof(new_bbt_rec);
   anzahl_records--;
   rewind(fpinbbt);

   for (i=0;i<=anzahl_records;i++)
   {
      fread(&new_bbt_rec,sizeof(new_bbt_rec),1,fpinbbt);
      if (strcmp_fun(old_bbt_rec.sortierfeld,
                     new_bbt_rec.sortierfeld,
                     SSTRING) > 0)
      {
           in_sortiert = 0;
           break;
      }
      old_bbt_rec = new_bbt_rec;
   }
   fclose(fpinbbt);

   if (in_sortiert==0)
   {
     sprintf(wrtxtbu,"\n(Sorting `%s')\n",in_bbt_name);
     wrtxt(wrtxtbu);
     domergebbf2(in_bbt_name,tmpbbt_name);
     remove(in_bbt_name);
     rename(tmpbbt_name,in_bbt_name);
     wrtxt("\n");
   }
   else
   {
      sprintf(wrtxtbu,"\n(Data in %s found sorted)\n",in_bbt_name);
      wrtxt(wrtxtbu);
   }
   if ((fpinbbt=fopen(in_bbt_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nERROR: unable to read `%s'\n",in_bbt_name);
      exit(1);
   }
   if ((fpoutbbt=fopen(out_bbt_name,"wb"))==NULL)
   {
      fprintf(stderr,"\nERROR: unable to create/write into `%s'\n",
        out_bbt_name);
      exit(1);
   }
   rewind(fpinbbt);
   memset(&new_bbt_rec,0L,sizeof(new_bbt_rec));
   memset(&old_bbt_rec,0L,sizeof(old_bbt_rec));
   lce = 0;
   records_transferred = 0;
   for (i=0;i<=anzahl_records;i++)
   {
      fread(&new_bbt_rec,sizeof(new_bbt_rec),1,fpinbbt);

      if (strcmp(new_bbt_rec.sortierfeld,old_bbt_rec.sortierfeld)==0)
      {
         lce = 1;
         if (i>0) 
         {
            if (fwrite(&old_bbt_rec,sizeof(old_bbt_rec),1,fpoutbbt) < 1) schreibfehler();
            records_transferred = 1;
         }
         if (i==anzahl_records)
         {
            if (fwrite(&new_bbt_rec,sizeof(new_bbt_rec),1,fpoutbbt) < 1) schreibfehler();
            records_transferred = 1;
         }
      }

      if (strcmp(new_bbt_rec.sortierfeld,old_bbt_rec.sortierfeld)!=0 &&
         lce==1)
      {
          lce = 0;
          if (fwrite(&old_bbt_rec,sizeof(old_bbt_rec),1,fpoutbbt) < 1) schreibfehler();
          records_transferred = 1;

      }
      else if (strcmp(new_bbt_rec.sortierfeld,old_bbt_rec.sortierfeld)!=0 &&
         lce==0)
      {
         lce = 0;
      }
      old_bbt_rec = new_bbt_rec;
   }
   fclose(fpinbbt);
   fclose(fpoutbbt);
   
   if (records_transferred==1)
   {
     if (isfile(in_bbt_name))
     {
         sprintf(wrtxtbu,"\n(Extraction of duplicate records in `%s' completed)\n",
           in_bbt_name);
         wrtxt(wrtxtbu);
        remove(in_bbt_name);
        sprintf(wrtxtbu,"Duplicate (text field) records from `%s'\n"
          "  transferred into new version of \n  `%s'\n"
          "  i. e. all unique (text field) records removed",
          in_bbt_name,in_bbt_name);
        protokollieren(wrtxtbu);
     }
     rename(out_bbt_name,in_bbt_name);
   } else
   {
     if (isfile(out_bbt_name))
     {
        wrtxt("\n(No duplicate records found)\n");
        remove(out_bbt_name);
        sprintf(wrtxtbu,"No duplicate records found in batch table\n"
          "  `%s'",
          in_bbt_name);
        protokollieren(wrtxtbu);

     }
   }
   
   
   btch_aufraeumen();
   return 1;
}

int invertbbt_order(void)
{
   char bbt_name[PFAD_LEN + 1];
   long i, anzahl_records;
   bbatchtable_rec one_bbt_rec;

   
   btch_initialize();
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_name))
   {
      btch_aufraeumen();
      wrtxt("\n(Aboerted)\n");
      return 0;
   }
   if (filesize(bbt_name) < sizeof(one_bbt_rec)*2)
   {
       sprintf(wrtxtbu,"\n(File %s contains < 2 records, aborted)\n",
       bbt_name);
       wrtxt(wrtxtbu);
       btch_aufraeumen();
       return 0;
   }
   if ((fpbbt=fopen(bbt_name,"rb"))==NULL)
   {
      fprintf(stderr,"\nERROR: unable to read %s\n",bbt_name);
      exit(1);
   }
   if ((tmpbbt=fopen(tmpbbt_name,"wb"))==NULL)
   {
      fprintf(stderr,"\nERROR: unable to create/write "
        "into %s\n",tmpbbt_name);
      exit(1);
   }
   fseek(fpbbt,0L,SEEK_END);
   anzahl_records = ftell(fpbbt)/sizeof(one_bbt_rec);
   anzahl_records--;
   for (i=anzahl_records;i>=0;i--)
   {
      fseek(fpbbt,i*sizeof(one_bbt_rec),SEEK_SET);
      fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fpbbt);
      if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,tmpbbt) < 1) schreibfehler();
   }
   fclose(tmpbbt);
   fclose(fpbbt);
   if (isfile(bbt_name))
   {
       remove(bbt_name);
       rename(tmpbbt_name,bbt_name);
       wrtxt("\n(Completed)\n");
   }
   else
   {
       wrtxt("\n(Renaming failed)\n");
       
   }
   sprintf(wrtxtbu,"Order of records in batch file\n"
     "  `%s' inverted",bbt_name);
   protokollieren(wrtxtbu); 
   btch_aufraeumen();
   return 1;
}

int bbt_set_union(void)
{
   char bbt_a_name[PFAD_LEN +1];
   char bbt_b_name[PFAD_LEN +1];
   char bbt_c_name[PFAD_LEN +1];
   char bbt_c_vorname[PFAD_LEN +1];
   FILE * fp_a_bbt; 
   FILE * fp_b_bbt; 
   FILE * fp_c_bbt; 
   bbatchtable_rec one_bbt_rec;
   long i,  byte_zeiger, anzahl_records;
   
   // btch_initialize();
   wrtxt("\nPlease select bbt-file `A'\n");
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_a_name))
   {
      wrtxt("\n(aborted)\n");
      return 0;
   }
   wrtxt("\nPlease select bbt-file `B'\n");
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_b_name))
   {
      wrtxt("\n(aborted)\n");
      return 0;
   }
   if (strcmp(bbt_a_name,bbt_b_name)==0)
   {
      wrtxt("\nProblem: the file `");
      wrtxt(bbt_b_name);
      wrtxt("'was selected twice, aborted\n");
      return 0;
   }
   if (!dateivornamen_holen(bbt_c_vorname,
         "Please enter name for bbt-file `C', `.bbt' will be appended"))
   {
       wrtxt("\nAborted, no valid file name entered\n");
       return 0;
   }
   strlimcpy(bbt_c_name,rdbpfad,PFAD_LEN); 
   strlimcat(bbt_c_name,bbt_c_vorname,PFAD_LEN);
   strlimcat(bbt_c_name,".bbt",PFAD_LEN);
   if (isfile(bbt_c_name))
   {
      wrtxt("\nAborted, `C': `");
      wrtxt(bbt_c_name);
      wrtxt("'already exists\n");
      return 0;
   }
   if ((fp_a_bbt=fopen(bbt_a_name,"rb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot read `%s'\n",bbt_a_name);
      wrtxt(wrtxtbu);
      return 0;
   }
   if ((fp_b_bbt=fopen(bbt_b_name,"rb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot read `%s'\n",bbt_b_name);
      wrtxt(wrtxtbu);
      fclose(fp_a_bbt);
      return 0;
   }
   if ((fp_c_bbt=fopen(bbt_c_name,"wb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot write `%s'\n",bbt_c_name);
      wrtxt(wrtxtbu);
      fclose(fp_a_bbt);
      fclose(fp_b_bbt);
      return 0;
   }
       
   fseek(fp_a_bbt,0L,SEEK_END);
   byte_zeiger = ftell(fp_a_bbt);
   anzahl_records = byte_zeiger / sizeof(one_bbt_rec);
   anzahl_records--;
   rewind(fp_a_bbt);
   for (i=0;i<=anzahl_records;i++)
   {
      fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fp_a_bbt);
      if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,fp_c_bbt) < 1) schreibfehler();
   }
   fseek(fp_b_bbt,0L,SEEK_END);
   byte_zeiger = ftell(fp_b_bbt);
   anzahl_records = byte_zeiger / sizeof(one_bbt_rec);
   anzahl_records--;
   rewind(fp_b_bbt);
   for (i=0;i<=anzahl_records;i++)
   {
      fread(&one_bbt_rec,sizeof(one_bbt_rec),1,fp_b_bbt);
      if (fwrite(&one_bbt_rec,sizeof(one_bbt_rec),1,fp_c_bbt) < 1) schreibfehler();
   }
   fclose(fp_a_bbt);
   fclose(fp_b_bbt);
   fclose(fp_c_bbt);
    
   wrtxt("\n(Completed, `");
   wrtxt(bbt_c_name);
   wrtxt("' written)\n");

   return 1;
}

int bbt_set_intersection(void)
{
   char bbt_a_name[PFAD_LEN +1];
   char bbt_b_name[PFAD_LEN +1];
   char bbt_c_name[PFAD_LEN +1];
   char bbt_c_vorname[PFAD_LEN +1];
   FILE * fp_a_bbt; 
   FILE * fp_b_bbt; 
   FILE * fp_c_bbt; 
   bbatchtable_rec one_bbt_rec_a;
   bbatchtable_rec one_bbt_rec_b;
   bbatchtable_rec one_bbt_rec_c;
   int refno_found_in_b; /* 0: not found, 1: found in bbt file b */
   long i,j,  byte_zeiger_a, anzahl_records_a,  byte_zeiger_b, anzahl_records_b;
   
   // btch_initialize();
   wrtxt("\nPlease select bbt-file `A'\n");
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_a_name))
   {
      wrtxt("\n(aborted)\n");
      return 0;
   }
   wrtxt("\nPlease select bbt-file `B'\n");
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_b_name))
   {
      wrtxt("\n(aborted)\n");
      return 0;
   }
   if (strcmp(bbt_a_name,bbt_b_name)==0)
   {
      wrtxt("\nProblem: the file `");
      wrtxt(bbt_b_name);
      wrtxt("'was selected twice, aborted\n");
      return 0;
   }
   if (!dateivornamen_holen(bbt_c_vorname,
         "Please enter name for bbt-file `C', `.bbt' will be appended"))
   {
       wrtxt("\nAborted, no valid file name entered\n");
       return 0;
   }
   strlimcpy(bbt_c_name,rdbpfad,PFAD_LEN); 
   strlimcat(bbt_c_name,bbt_c_vorname,PFAD_LEN);
   strlimcat(bbt_c_name,".bbt",PFAD_LEN);
   if (isfile(bbt_c_name))
   {
      wrtxt("\nAborted, `C': `");
      wrtxt(bbt_c_name);
      wrtxt("'already exists\n");
      return 0;
   }
   if ((fp_a_bbt=fopen(bbt_a_name,"rb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot read `%s'\n",bbt_a_name);
      wrtxt(wrtxtbu);
      return 0;
   }
   if ((fp_b_bbt=fopen(bbt_b_name,"rb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot read `%s'\n",bbt_b_name);
      wrtxt(wrtxtbu);
      fclose(fp_a_bbt);
      return 0;
   }
   if ((fp_c_bbt=fopen(bbt_c_name,"wb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot write `%s'\n",bbt_c_name);
      wrtxt(wrtxtbu);
      fclose(fp_a_bbt);
      fclose(fp_b_bbt);
      return 0;
   }
       
   fseek(fp_a_bbt,0L,SEEK_END);
   byte_zeiger_a = ftell(fp_a_bbt);
   anzahl_records_a = byte_zeiger_a / sizeof(one_bbt_rec_a);
   anzahl_records_a--;
   rewind(fp_a_bbt);

   fseek(fp_b_bbt,0L,SEEK_END);
   byte_zeiger_b = ftell(fp_b_bbt);
   anzahl_records_b = byte_zeiger_b / sizeof(one_bbt_rec_b);
   anzahl_records_b--;
   /* rewind(fp_b_bbt); */


   for (i=0;i<=anzahl_records_a;i++)
   {
      fread(&one_bbt_rec_a,sizeof(one_bbt_rec_a),1,fp_a_bbt);
      refno_found_in_b = 0; 
      rewind(fp_b_bbt);
      for (j=0;j<=anzahl_records_b;j++)
      {
        fread(&one_bbt_rec_b,sizeof(one_bbt_rec_b),1,fp_b_bbt);
        if (strcmp(one_bbt_rec_b.kennziffer,one_bbt_rec_a.kennziffer)==0)
        {
           refno_found_in_b = 1;
        }
      }
      /* decision: refno found in A _and_ B */
      if (refno_found_in_b == 1)
      {
        one_bbt_rec_c = one_bbt_rec_a;
        if (fwrite(&one_bbt_rec_c,sizeof(one_bbt_rec_c),1,fp_c_bbt) < 1) schreibfehler();
      }
   }

   fclose(fp_a_bbt);
   fclose(fp_b_bbt);
   fclose(fp_c_bbt);
   
   if (filesize(bbt_c_name) < sizeof(one_bbt_rec_c))
   {
     remove(bbt_c_name);
     wrtxt("\n(Resulting bbt-file `");
     wrtxt(bbt_c_name);
     wrtxt("' is empty (deleted))\n");
   } else
   {
     wrtxt("\n(Completed, `");
     wrtxt(bbt_c_name);
     wrtxt("' written)\n");
   }

   return 1;

}

int bbt_set_difference(void)
{
   char bbt_a_name[PFAD_LEN +1];
   char bbt_b_name[PFAD_LEN +1];
   char bbt_c_name[PFAD_LEN +1];
   char bbt_c_vorname[PFAD_LEN +1];
   FILE * fp_a_bbt; 
   FILE * fp_b_bbt; 
   FILE * fp_c_bbt; 
   bbatchtable_rec one_bbt_rec_a;
   bbatchtable_rec one_bbt_rec_b;
   bbatchtable_rec one_bbt_rec_c;
   int refno_found_in_b; /* 0: not found, 1: found in bbt file b */
   long i,j,  byte_zeiger_a, anzahl_records_a,  byte_zeiger_b, anzahl_records_b;
   
   // btch_initialize();
   wrtxt("\nPlease select bbt-file `A'\n");
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_a_name))
   {
      wrtxt("\n(aborted)\n");
      return 0;
   }
   wrtxt("\nPlease select bbt-file `B'\n");
   if (!datei_suchen_mit_pfad("*.bbt",rdbpfad,bbt_b_name))
   {
      wrtxt("\n(aborted)\n");
      return 0;
   }
   if (strcmp(bbt_a_name,bbt_b_name)==0)
   {
      wrtxt("\nProblem: the file `");
      wrtxt(bbt_b_name);
      wrtxt("'was selected twice, aborted\n");
      return 0;
   }
   if (!dateivornamen_holen(bbt_c_vorname,
         "Please enter name for bbt-file `C', `.bbt' will be appended"))
   {
       wrtxt("\nAborted, no valid file name entered\n");
       return 0;
   }
   strlimcpy(bbt_c_name,rdbpfad,PFAD_LEN); 
   strlimcat(bbt_c_name,bbt_c_vorname,PFAD_LEN);
   strlimcat(bbt_c_name,".bbt",PFAD_LEN);
   if (isfile(bbt_c_name))
   {
      wrtxt("\nAborted, `C': `");
      wrtxt(bbt_c_name);
      wrtxt("'already exists\n");
      return 0;
   }
   if ((fp_a_bbt=fopen(bbt_a_name,"rb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot read `%s'\n",bbt_a_name);
      wrtxt(wrtxtbu);
      return 0;
   }
   if ((fp_b_bbt=fopen(bbt_b_name,"rb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot read `%s'\n",bbt_b_name);
      wrtxt(wrtxtbu);
      fclose(fp_a_bbt);
      return 0;
   }
   if ((fp_c_bbt=fopen(bbt_c_name,"wb"))==NULL)
   {
      sprintf(wrtxtbu,"Warning: cannot write `%s'\n",bbt_c_name);
      wrtxt(wrtxtbu);
      fclose(fp_a_bbt);
      fclose(fp_b_bbt);
      return 0;
   }
       
   fseek(fp_a_bbt,0L,SEEK_END);
   byte_zeiger_a = ftell(fp_a_bbt);
   anzahl_records_a = byte_zeiger_a / sizeof(one_bbt_rec_a);
   anzahl_records_a--;
   rewind(fp_a_bbt);

   fseek(fp_b_bbt,0L,SEEK_END);
   byte_zeiger_b = ftell(fp_b_bbt);
   anzahl_records_b = byte_zeiger_b / sizeof(one_bbt_rec_b);
   anzahl_records_b--;
   /* rewind(fp_b_bbt); */


   for (i=0;i<=anzahl_records_a;i++)
   {
      fread(&one_bbt_rec_a,sizeof(one_bbt_rec_a),1,fp_a_bbt);
      refno_found_in_b = 0; 
      rewind(fp_b_bbt);
      for (j=0;j<=anzahl_records_b;j++)
      {
        fread(&one_bbt_rec_b,sizeof(one_bbt_rec_b),1,fp_b_bbt);
        if (strcmp(one_bbt_rec_b.kennziffer,one_bbt_rec_a.kennziffer)==0)
        {
           refno_found_in_b = 1;
        }
      }
      /* decision: refno found in A but _not_ in B */
      if (refno_found_in_b == 0)
      {
        one_bbt_rec_c = one_bbt_rec_a;
        if (fwrite(&one_bbt_rec_c,sizeof(one_bbt_rec_c),1,fp_c_bbt) < 1) schreibfehler();
      }
   }

   fclose(fp_a_bbt);
   fclose(fp_b_bbt);
   fclose(fp_c_bbt);
   
   if (filesize(bbt_c_name) < sizeof(one_bbt_rec_c))
   {
     remove(bbt_c_name);
     wrtxt("\n(Resulting bbt-file `");
     wrtxt(bbt_c_name);
     wrtxt("' is empty (deleted))\n");
   } else
   {
     wrtxt("\n(Completed, `");
     wrtxt(bbt_c_name);
     wrtxt("' written)\n");
   }

   return 1;

}
