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

/*
   srtf.c 'search' and 'replace' in a text file
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "str_fun.h"
#include "fl_ut.h"
#include "refs.h"
#include "interf.h"
#include "srtf.h"


#define LZEILE_LEN 262144


#define MASKEN_LEN 10
#define SRCHREPL_LOG "srchrepl.log"
#define SR_TMP "sr.tmp"

 static char * lsrzeile;
 /* liest in der Textdatei */
 static char * ltxtzeile;
 static char * search_zeile;
 static char * replace_zeile;
 static char * puffer_zeile;
 /* Name der zu bearbeitenden Textdatei */
 static char text_name[PFAD_LEN + 1];
 static FILE * fptext;
 /* Name der Textdatei mit den 'search' and 'replace'-Texten */
 static char srtext_name[PFAD_LEN + 1];
 static FILE * fpsrtext;

 static char log_name[PFAD_LEN + 1];
 static FILE * fplog;

 static char temp_name[PFAD_LEN + 1];
 static FILE * fptemp;
 static int alles_ok;


 extern char textpfad[PFAD_LEN+1];
 extern char wrtxtbu[WRTXTBU_LEN+1];
 extern config_set one_config_set;


 static int hauptmenu_srtf(void);
 static int dateien_schliessen_srtf(void);
 static int dateien_oeffnen_srtf(void);
 static long sr_pruefen(void);
 static int ersetzen_schreiben(long sr_zeilen);

int srtf_main(void)
{
   // strcpy(temp_name,SR_TMP);
   strlimcpy(temp_name,textpfad,PFAD_LEN);
   strlimcat(temp_name,SR_TMP,PFAD_LEN);
   strlimcpy(log_name,textpfad,PFAD_LEN);
   strlimcat(log_name,SRCHREPL_LOG,PFAD_LEN);
     
     alles_ok = 1;
   
     if ((lsrzeile =  (char *) malloc((LZEILE_LEN + 1) * sizeof(char)))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot allocate memory for input_line_1\n");
         exit(1);
     }

     if ((ltxtzeile =  (char *) malloc((LZEILE_LEN + 1) * sizeof(char)))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot allocate memory for input_line_2\n");
         exit(1);
     }
     if ((search_zeile =  (char *) malloc((LZEILE_LEN +1) * sizeof(char)))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot allocate memory for search_buffer\n");
         exit(1);
     }
     if ((replace_zeile =  (char *) malloc((LZEILE_LEN + 1) * sizeof(char)))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot allocate memory for replace_buffer\n");
         exit(1);
     }
     if ((puffer_zeile =  (char *) malloc((LZEILE_LEN + 1) * sizeof(char)))==NULL)
     {
         fprintf(stderr,"\nERROR: Cannot allocate memory for text temp_buffer\n");
         exit(1);
     }

     if (hauptmenu_srtf())
     {
         if (isfile(text_name))
         {
            remove(text_name);
         }
         rename(temp_name,text_name);
     }
     free(lsrzeile);
     free(ltxtzeile);
     free(search_zeile);
     free(replace_zeile);
     free(puffer_zeile);
     return 0;
   
}


static int hauptmenu_srtf(void)
{
     char maske[MASKEN_LEN+1];
     static char ein[INPUT_BU_LEN+1];
     int taste;

     strcpy(ein,"menu");
     wrtxt("\nMenu: select filename extension (file to be modified) [txt/tbt/ ... /q]\n");
     taste = menu_wahl(ein,
       "[txt], [tbt], [asc], [doc], [tex], [arr], [bib] filename extension, [q] quit"
       );
     if (taste==8)
     {
         wrtxt("\n(aborted)\n");
         return 0;
     }
     if (taste==1)
     {
         strcpy(maske,"*.txt");
     }
     if (taste==2)
     {
         strcpy(maske,"*.tbt");
     }
     if (taste==3)
     {
         strcpy(maske,"*.asc");
     }
     if (taste==4)
     {
         strcpy(maske,"*.doc");
     }
     if (taste==5)
     {
         strcpy(maske,"*.tex");
     }
     if (taste==6)
     {
         strcpy(maske,"*.arr");
     }
     if (taste==7)
     {
         strcpy(maske,"*.bib");
     }


     if (!datei_suchen_mit_pfad(maske,textpfad,text_name))
     {
         wrtxt("\n(aborted)\n");
         return 0;
     }
     wrtxt("\n(Next file selection screen: macro file with 'search and "
      "replace' items)\n");
     anhalten();
     if (!datei_suchen_mit_pfad("*.sr",textpfad,srtext_name))
     {
         wrtxt("\n(no file selected)\n");
         return 0;
     }

     if (dateien_oeffnen_srtf())
     {
         long anzahl_zeilen;

         anzahl_zeilen = sr_pruefen();
         if (anzahl_zeilen > 0)
         {
            ersetzen_schreiben(anzahl_zeilen);
         }
         else
         {
             if (anzahl_zeilen==0)
             {
                sprintf(wrtxtbu,"\nProblem: file `%s' empty\n",
                   srtext_name);
                fprintf(fplog,"%s",wrtxtbu);
                wrtxt(wrtxtbu);
             }
             if (anzahl_zeilen==-1)
             {
                sprintf(wrtxtbu,"\nProblem in `%s': one input line contains > %i "
                   "characters, text file not processed!\n",
                          srtext_name,LZEILE_LEN);
                fprintf(fplog,"%s",wrtxtbu);
                wrtxt(wrtxtbu);
             }

             dateien_schliessen_srtf();
             
             return 0;
         }
         dateien_schliessen_srtf();
         sprintf(wrtxtbu,"\n(Report on 'search and replace' in %s)\n",log_name);
         wrtxt(wrtxtbu);
         // tastelesen();

     }
     else
     {
         return 0;
     }
     return 1;
}

static int dateien_oeffnen_srtf(void)
{

   if ((fptext = fopen(text_name,"rt"))==NULL)
   {
        sprintf(wrtxtbu,"ERROR: Cannot read %s",text_name);
        wrtxt(wrtxtbu);
        return 0;
   }

   if ((fpsrtext = fopen(srtext_name,"rt"))==NULL)
   {
        sprintf(wrtxtbu,"ERROR: Cannot read %s",srtext_name);
        wrtxt(wrtxtbu);
        fclose(fptext);
        return 0;
   }
   if ((fptemp = fopen(temp_name,"wt"))==NULL)
   {
        sprintf(wrtxtbu,"ERROR: Cannot create %s",temp_name);
        wrtxt(wrtxtbu);
        fclose(fptext);
        fclose(fpsrtext);
        return 0;
   }
   if ((fplog = fopen(log_name,"wt"))==NULL)
   {
        sprintf(wrtxtbu,"ERROR: Cannot create %s",log_name);
        wrtxt(wrtxtbu);
        fclose(fptext);
        fclose(fpsrtext);
        fclose(fptemp);
        return 0;
   }
   return 1;
}

static int dateien_schliessen_srtf(void)
{
    fclose(fptext);
    fclose(fpsrtext);
    fclose(fptemp);
    fclose(fplog);
    return 1;
}

static long sr_pruefen(void)
{
   long i;
   i=0;

   fprintf(fplog,"SEARCH AND REPLACE FOR REFERENCES VERSION %s\n",REFS_VERSION);
   while (fgets(lsrzeile,LZEILE_LEN,fpsrtext)!=NULL)
   {
      i++;
      if (strlen(lsrzeile) >= LZEILE_LEN - 1)
      {
          i=-1;
          break;
      }
   }
   return i;
}


static int ersetzen_schreiben(long sr_zeilen)
{
   long i,j;
   int code;
   char sep_string[2];
   int anzahl_worte;
   int neusuch;

   j = 0;

   while (fgets(ltxtzeile,LZEILE_LEN,fptext)!=NULL)
   {
     

      if ((j % 100)==0)
      {
         if (j==100) wrtxt("\n");
         if (j>0)
         {
           sprintf(wrtxtbu,"[%li] ",j);
           wrtxt(wrtxtbu);
         }
      }


     rewind(fpsrtext);
     j++;
     if (strlen(ltxtzeile) >= LZEILE_LEN - 1)
     {
         fprintf(fplog,
         "\nProblem: line %li in %s:\n",
         j,text_name);
         fprintf(fplog,
         "line too long, please edit %s and rerun 'search and replace'\n",
           text_name);
         alles_ok = 0;
     }

     rtrim(ltxtzeile,'\n');
     for (i=1;i<=sr_zeilen;i++)
     {
         strcpy(lsrzeile,"");

         neusuch = 0;

         if ((fgets(lsrzeile,LZEILE_LEN,fpsrtext)!=NULL) &&
              strlen(lsrzeile) > 2)
         {
            rtrim(lsrzeile,'\n');
            sep_string[0] = lsrzeile[0];
            sep_string[1] = '\0';
            anzahl_worte = countitem(lsrzeile,sep_string);
            extractitem(1,lsrzeile,sep_string,search_zeile);
            if (anzahl_worte > 1)
            {
                extractitem(2,lsrzeile,sep_string,replace_zeile);
                if (strcmp(replace_zeile,"\\n")==0)
                {
                   strcpy(replace_zeile,"\n");
                }
            }
            else
            {
                strcpy(replace_zeile,"");
            }
            for (;;)
            {
               code = serepl(ltxtzeile,
                              search_zeile,
                              replace_zeile,
                              LZEILE_LEN,
                              &neusuch,
                              puffer_zeile
                              );
               
               if (code==1)
               {
                  fprintf(fplog,"\nDone: line %li in `%s': `%s' changed into `%s'.\n",
                    j,text_name,search_zeile,replace_zeile);
                  fprintf(fplog,"-> %s\n",ltxtzeile);
                
               }
               
               /*
                  Write error conditions into a log file 
               */
               if (code==-1)
               {
                 fprintf(fplog,
                 "\nProblem: line %li in `%s' and line %li in `%s':\n",
                 j,text_name,i,srtext_name);
                 fprintf(fplog,
                 "'search and replace' not complete, target line too long.\n");
                 alles_ok = 0;
               }
               if (code!=1) break;
            }
         }
     }
     fprintf(fptemp,"%s\n",ltxtzeile);
   }

   if (alles_ok)
   {
     fprintf(fplog,"\nNo problems encountered!\n");
     if (j>=100)
     {
        wrtxt("\n");
     }
     wrtxt("\n(Completed)\n");
   }
   return 1;
}


