/*
 * File: text24th.c
 *   By: Dave Hiebeler
 *       August 1989
 *   Hacked by Andy Valencia, Jan. 2002
 *
 * Copyright 1990 David Hiebeler and Automatrix, Inc.
 * This code can be freely copied and modified for personal use, provided
 * the copyright notice is retained. This code cannot be sold for profit.
 *
 * This program reads in a standard text file and converts it into
 * a Forth "screen" file, where each screen is made of SCRSIZ characters.
 * Any lines longer than BLKCOLS characters are truncated (and a warning
 * is printed to stderr).
 *
 * If any lines in the file begin with the string "|xx...xx|", that prefix
 * will be stripped.  That is, if the file was generated using "4th2text"
 * with the "-n" option, the screen/line numbers will be removed when
 * converting back to Forth block format.  You can actually put anything,
 * not just digits, between the '|' characters, and it will be dropped.
 *
 * If a ^L (form feed) is found, the current block will be filled out
 * with spaces, and a new block started with the following text.
 *
 * Usage: text24th [-o <outfile>] <infile> [<infile>...]
 * Default is stdout for output.
 */
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include "defs.h"

/*
 * State shared with common routines
 */
static char *cmd;		/* Command name */
static FILE *infile, *outfile;	/* Input/output files */
static int line,		/* Current line # */
    shadows,			/* Whether shadows are in input */
    blknum;			/* Current block # */

static void
usage(void)
{
    fprintf(stderr,
     "Usage: %s [-o <outfile>] <infile> [<infile>...]\n", cmd);
    exit(1);
}

/*
 * spaces()
 *	Emit the indicated number of spaces
 */
static void
spaces(int x)
{
    while (x-- > 0) {
	(void)fputc(' ', outfile);
    }
}

/*
 * copy_screen()
 *	Pull in one screenfull of text, converting to block format
 */
static void
copy_screen(void)
{
    int x;
    char buf[1024], *p;

    while (fgets(buf, sizeof(buf), infile)) {
	/* A line with just ^L means flush to next screen */
	p = buf;
	if ((p[0] == '\f') && (p[1] == '\n')) {
	    break;
	}

	/* Trim leading | <foo> | */
	line += 1;
	if (*p == '|') {
	    ++p;
	    while (*p && (*p != '|')) {
		++p;
	    }
	    if (!*p) {
		fprintf(stderr, "Unmatched '|' on line %d\n", line);
		exit(1);
	    }
	}

	/* Trim off trailing \n */
	x = strlen(p);
	p[--x] = '\0';

	/* Handle long lines */
	if (x > BLKCOLS) {
	    fprintf(stderr, "Line %d too long, was truncated\n", line);
	    x = BLKCOLS;
	}

	/* Write out line, with trailing spaces */
	(void)fwrite(p, sizeof(char), x, outfile);
	spaces(BLKCOLS - x);

	/* Finish after a full screen */
	if ((line % BLKROWS) == 0) {
	    break;
	}
    }

    /*
     * Pad out end of screen with blank lines
     */
    while (line % BLKROWS) {
	spaces(BLKCOLS);
	line += 1;
    }

    /* Bump block # count */
    blknum += 1;
}

int
main(int argc, char **argv)
{
    int x;

    /* For usage messages */
    cmd = argv[0];

    /* Default output to stdout */
    outfile = stdout;

    /* Process options */
    while ((x = getopt(argc, argv, "o:s")) != EOF) {
	switch (x) {
	case 'o':
	    if (outfile != stdout) {
		fprintf(stderr, "Output specified twice.\n");
		exit(1);
	    }
	    outfile = fopen(argv[2], "w");
	    if (outfile == NULL) {
		perror(argv[2]);
		exit(1);
	    }
	    break;

	case 's':
	    shadows = 1;
	    break;
	}
    }

    for (x = optind; x < argc; ++x) {
	infile = fopen(argv[x], "r");
	if (infile == NULL) {
	    perror(argv[x]);
	    exit(1);
	}
	fprintf(stderr, "%d: %s\n", blknum, argv[x]);

	/*
	 * Copy across screens
	 */
	while (!feof(infile)) {
	    int y;

	    copy_screen();
	    for (y = 1; y < SCRBLK; ++y) {
		if (shadows) {
		    copy_screen();
		} else {
		    spaces(SCRSIZ);
		}
	    }
	    spaces(BLKRESID);
	}

	fclose(infile);
    }

    fclose(outfile);
    return(0);
}
