/*
 *      fhist - file history and comparison tools
 *      Copyright (C) 1991-1994, 1998-2000, 2002, 2008 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 <ac/libintl.h>
#include <ac/stdio.h>

#include <cmalloc.h>
#include <compare.h>
#include <error_intl.h>
#include <fcheck.h>
#include <fhist.h>
#include <fileio.h>
#include <list.h>
#include <subroutine.h>


/*
 * List information about a single edit.
 * The information is written to the usual output file.
 */

static void
listone(FILE *fp, long edit, POS *pp, FILE *of, const char *ofn)
{
        char            *cp;            /* current line */
        long            tempedit;       /* edit number */

        cp = get_a_line(fp, pp->p_pos, T_BEGINEDIT, sc.historyname);
        if (cp == NULL)
        {
                sub_context_ty  *scp;

                scp = sub_context_new();
                sub_var_set_long(scp, "Number", edit);
                fatal_intl
                (
                        scp,
                        i18n("position failed to beginning of edit $number")
                );
        }
        cp = getnumber(cp, &tempedit);
        if ((cp == NULL) || (edit != tempedit))
        {
                sub_context_ty  *scp;

                scp = sub_context_new();
                sub_var_set_long(scp, "Number", edit);
                fatal_intl
                (
                        scp,
                        i18n("bad number at beginning of edit $number")
                );
        }
        cp = get_a_line(fp, NOSEEK, T_REMARK, sc.historyname);
        if (cp == NULL)
                fatal_intl(0, i18n("cannot read identification line"));

        /*
         * If the quick flag was specified, then only list the raw
         * edit number, otherwise list the number and the names.
         */
        if (fc.quickflag)
                fprintf(of, "%ld\n", edit);
        else {
                fprintf(of, "Edit %ld:   %s", edit, cp);
                if (pp->p_names) {
                        fputs("Named: ", of);
                        fputs(pp->p_names, of);
                        fputs("\n", of);
                }
        }

        while ((cp = get_a_line(fp, NOSEEK, T_REMARK, sc.historyname)) != 0)
                writefx(of, cp, sc.linelen, ofn);
}


/*
 * List out information about the edits.
 * If no edit names are given, then all edits are displayed.
 * If one edit name is given, then just that edit is displayed.
 * If two edit names are given, then the specified range of edits is displayed.
 *
 * 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
listhistory(char *editname1, char *editname2, char *outputname)
{
        FILE    *fp;            /* history file */
        FILE    *of;            /* output file */
        POS     *pp;            /* current edit position entry */
        POS     *postable;      /* position table */
        long    begedit;        /* beginning edit number to display */
        long    endedit;        /* ending edit number to display */
        int     step;           /* step value for loop */

        fp = openhistoryfile(OHF_READ);
        begedit = sc.lastedit;
        endedit = sc.firstedit;
        if (editname1) {
                begedit = findeditnumber(fp, editname1);
                endedit = begedit;
        }
        if (editname2)
                endedit = findeditnumber(fp, editname2);
        if (outputname)
        {
                of = fopen_and_check(outputname, "w");
        }
        else
        {
                of = stdout;
                outputname = gettext("standard output");
        }
        postable = readpostable(fp);
        if (!fc.quickflag)
                fprintf(of, "Module \"%s\":\n", sc.modulename);
        pp = postable + (sc.lastedit - begedit + 1);
        step = 1;
        if (begedit > endedit)
                step = -1;
        for (;;)
        {
                listone(fp, begedit, pp, of, outputname);
                if (begedit == endedit)
                        break;
                begedit += step;
                pp -= step;
                fputs("\n", of);
        }
        cm_free(postable);
        fclose_and_check(fp, sc.historyname);
        fflush_and_check(of, outputname);
        fclose_and_check(of, outputname);
}
