/*
 *	fhist - file history and comparison tools
 *	Copyright (C) 1991-1994, 1998, 2000, 2002 Peter Miller;
 *	All rights reserved.
 *
 *	Derived from a work
 *	Copyright (C) 1990 David I. Bell.
 *
 *	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, USA.
 *
 * MANIFEST: functions to prune away old edits from the edit history file.
 */

#include <ac/stdio.h>
#include <ac/string.h>

#include <breaks.h>
#include <compare.h>
#include <error_intl.h>
#include <fcheck.h>
#include <fhist.h>
#include <fileio.h>
#include <prune.h>
#include <str.h>
#include <subroutine.h>


/*
 * Prune old edits from the history file to save on disk space.
 * This removes all edits up until the specified edit number.
 *
 * The history (.e) file is binary, because we need to seek in it.
 * The source (.s) file is text, because we don't need to seek in it.
 * The input files are text, by definition.
 * The output files are text, by definition.
 */

void
prunehistory(char *editname)
{
    FILE            *fp;		/* input history file */
    FILE            *ofp;		/* output history file */
    POS             *pp;		/* current entry in position table */
    long            lastprunededit;	/* last edit number to be pruned */
    long            firstkeepedit;	/* first edit number to keep */
    long            prunecount;		/* number of edits being pruned */
    long            copypos;		/* starting position to copy from */
    long            newtablepos;	/* position of new position table */
    long            edit;		/* current edit number */
    long            shift;		/* amount to shift data up by */
    char            tempname[1024];	/* temporary name of new edit file */

    strcpy(tempname, sc.basename);
    strcat(tempname, EXT_NEW);
    fp = openhistoryfile(OHF_READ);
    firstkeepedit = findeditnumber(fp, editname);
    lastprunededit = firstkeepedit - 1;
    prunecount = firstkeepedit - sc.firstedit;
    if (prunecount <= 0)
    {
	fclose_and_check(fp, sc.historyname);
	if (fc.verbosity)
	{
	    sub_context_ty  *scp;

	    scp = sub_context_new();
	    sub_var_set_charstar(scp, "Module", sc.modulename);
	    error_intl(scp, i18n("no edits pruned from module \"$module\""));
	    sub_context_delete(scp);
	}
	return;
    }
    if (!sc.forceupdateflag)
    {
	sub_context_ty	*scp;
	string_ty	*s;

	scp = sub_context_new();
	sub_var_set_charstar(scp, "Module", sc.modulename);
	sub_var_set_long(scp, "Number1", sc.firstedit);
	sub_var_set_long(scp, "Number2", sc.lastedit);
	s =
	    subst_intl
	    (
	       	scp,
		i18n
		(
		    "the edit history for module \"$module\" currently has "
		    "edits $number1 to $number2."
		)
	    );
	printf("%s\n", s->str_text);
	str_free(s);

	sub_var_set_long(scp, "Number1", sc.firstedit);
	if (sc.firstedit == lastprunededit)
	{
	    s =
	       	subst_intl
	       	(
		    scp,
		    i18n("do you wish to irretrievably discard edit $number1?")
	       	);
	}
	else
	{
	    sub_var_set_long(scp, "Number2", sc.lastedit);
	    s =
	       	subst_intl
	       	(
		    scp,
         i18n("do you wish to irretrievably discard edit $number1 to $number2?")
		);
	}
	sub_context_delete(scp);
	printf("%s ", s->str_text);
	str_free(s);

	if (queryuser())
	    return;
    }
    pp = readpostable(fp);
    pp++;			/* ignore unused entry */

    /*
     * This will be the new history file,
     * so create it binary.
     */
    ofp = fopen_and_check(tempname, "w+b");
    fprintf(ofp, HEADERFORMAT, T_HEADER, 0L, 0L, 0L, 0L);
    copypos = pp[sc.lastedit - firstkeepedit].p_pos;
    seekf(fp, copypos, sc.historyname);
    copyfx(fp, ofp, sc.tablepos - copypos, sc.historyname, tempname);
    fclose_and_check(fp, sc.historyname);
    newtablepos = ftell(ofp);
    shift = sc.tablepos - newtablepos;
    for (edit = sc.lastedit; edit >= firstkeepedit; edit--, pp++)
    {
	fprintf(ofp, (pp->p_names ? "%c %ld %ld %s\n" : "%c %ld %ld\n"),
    	    T_POSITION, edit, pp->p_pos - shift, pp->p_names);
    }
    fprintf(ofp, "%c %ld\n", T_EOF, ftell(ofp));
    seekf(ofp, 0L, tempname);
    fprintf(ofp, HEADERFORMAT, T_HEADER, firstkeepedit, sc.lastedit,
	0L, newtablepos);
    fflush_and_check(ofp, tempname);
    fclose_and_check(ofp, tempname);
    breaksoff();
    if (renamefiles(EXT_HISTORY))
    {
	sub_context_ty	*scp;

	scp = sub_context_new();
	sub_errno_set(scp);
	sub_var_set_charstar(scp, "File_Name", sc.historyname);
	fatal_intl
	(
	    scp,
	    i18n("rename failed for edit history file \"$filename\": $errno")
	);
    }
    if (fc.verbosity)
    {
	sub_context_ty	*scp;

	scp = sub_context_new();
	sub_var_set_charstar(scp, "Module", sc.modulename);
	sub_var_set_long(scp, "Number", prunecount);
	error_intl(scp, i18n("pruned $number edits from module \"$module\""));
	sub_context_delete(scp);
    }
    breakson();
}
