/*
 * fhist - file history and comparison tools
 * Copyright (C) 1991-1994, 1998, 2000, 2002, 2008, 2010, 2012 Peter Miller
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

#include <common/ac/stdio.h>
#include <common/ac/stdlib.h>
#include <common/ac/string.h>
#include <libexplain/fclose.h>
#include <libexplain/fopen.h>

#include <common/compare.h>
#include <common/error_intl.h>
#include <common/fcheck.h>
#include <common/fileio.h>
#include <common/str.h>

#include <fhist/breaks.h>
#include <fhist/fhist.h>
#include <fhist/prune.h>
#include <fhist/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(const 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)
    {
        explain_fclose_or_die(fp);
        fp = 0;
        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 = explain_fopen_or_die(tempname, "w+b");
    fprintf(ofp, HEADERFORMAT, T_HEADER, 0L, 0L, 0L, 0L);
    copypos = pp[sc.lastedit - firstkeepedit].p_pos;
    seekf(fp, copypos);
    copyfx(fp, ofp, sc.tablepos - copypos);
    explain_fclose_or_die(fp);
    fp = 0;
    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, 0u);
    fprintf(ofp, HEADERFORMAT, T_HEADER, firstkeepedit, sc.lastedit,
        0L, newtablepos);
    explain_fclose_or_die(ofp);
    ofp = 0;
    breaksoff();
    if (renamefiles(EXT_HISTORY))
        exit(1);
    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();
}


/* vim: set ts=8 sw=4 et : */
