/* FPDIO.C Copyright (C) 1994 Fergus Patrick Duniho */

#ifndef _FPDIO_C
#define _FPDIO_C

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#define RdOpen(X,Y) X=FDOpen(Y, "r")
#define WrOpen(X,Y) X=FDOpen(Y, "w")
#define ApOpen(X,Y) X=FDOpen(Y, "a")
#define nextline(X) next(X, '\n')

void wrapwrite (FILE *fptr, int ind, int lm, int rm, char *s, ...);
int wrdlen(char *s);
int fgetp (FILE *fptr);
unsigned int getp (unsigned int min, unsigned int max);
FILE *FDOpen (const char *fn, const char *mode);
int HowMany (char *fname, char c0);
char *clone_line (FILE *fptr, int max);
int getline (FILE *fptr, char *line, int max);
int yes ();
int find (FILE *fptr, char *str);
int next (FILE *fptr, char c0);
int nextnon (FILE *fptr, char c0);

void wrapwrite (FILE *fptr, int ind, int lm, int rm, char *s, ...) {
    va_list ap;
    int i, j;

    va_start(ap, s);
    for (j = ind; ; j = lm) {
        for (i = 0; i < j; i++)
            fputc (' ', fptr);
        for (i = j; i < rm; i++)
            switch (*s) {
                case 0:     /* End of string reached */
                    if ((s = va_arg(ap, char *)) == 0) {
                        fputc ('\n', fptr);
                        va_end(ap);
                        return;
                    }
                    if ((i + wrdlen(s)) >= rm)
                        i = rm;
                    else if (i > j)
                        fputc (' ', fptr);
                    break;
                case ' ':     /* End of word reached */
                    if ((i + wrdlen(++s)) >= rm)
                        i = rm;
                    else if (i > j)
                        fputc (' ', fptr);
                    break;
                case '\n':    /* End of line reached */
                    i = rm;
                    s++;
                    break;
                default:
                    fputc (*s++, fptr);
            }
        fputc ('\n', fptr);
        if ((*s == '\0') && ((s = va_arg(ap, char *)) == 0)) {
            va_end(ap);
            return;
        }
    }
}

int wrdlen(char *s) {
    int r;

    for (r = 0; *s != ' ' && *s != '\n' && *s != '\0'; r++, s++);
    return r;
}

int fgetp (FILE *fptr) {
    int c, tot = 0;

    while (!isdigit(c = getc(fptr)))
        if (c == EOF)
            return EOF;
    do {
        tot *= 10;
        tot += (c - '0');
    } while (isdigit(c = getc(fptr)));
    if (c != '\n')
        ungetc (c, fptr);
    return tot;
}

unsigned int getp (unsigned int min, unsigned int max) {
    unsigned int i;

    for (;;) {
        i = fgetp(stdin);
        if ((i < min) || (i > max))
            fprintf (stderr, "Please enter an integer between %d and %d.\n", min, max);
        else
            return i;
    }
}

FILE *FDOpen (const char *fn, const char *mode) {
    FILE *fptr;

    if ((fptr = fopen(fn, mode)) == NULL) {
        fprintf (stderr, "Could not open %s.", fn);
        exit (2);
    }
    return fptr;
}

int HowMany (char *fname, char c) {
    FILE *fptr;
    int cnt = 0;

    RdOpen (fptr, fname);
    while (next(fptr, c))
        cnt++;
    fclose (fptr);
    return cnt;
}

char *clone_line (FILE *fptr, int max) {
    char *s, *r = 0;

    s = (char *)malloc(max + 1);
    if (getline(fptr, s, max))
        r = strdup(s);
    free (s);
    return r;
}

int getline (FILE *fptr, char *line, int max) {
    int flag;

    while (max--) {
        *line = fgetc(fptr);
        if (*line == '\n' || *line == EOF)
            break;
        line++;
    }
    flag = (*line != EOF);
    if (flag && (*line != '\n'))
        ungetc (*line, fptr);
    *line = '\0';
    return flag;
}

int yes () {
    int c;

    for (;;) {
        c = fgetc(stdin);
        while (fgetc(stdin) != '\n');
        if (c == 'y' || c == 'Y')
            return 1;
        if (c == 'n' || c == 'N')
            return 0;
        puts ("Please answer y or n.");
    }
}

int find (FILE *fptr, char *str) {
    char *s;
    fpos_t *position;

    do {
        fgetpos (fptr, position);
        s = str;
        while (*s == fgetc(fptr))
            s++;
    } while ((*s != '\0') && next(fptr, '\n') && nextnon(fptr, '\n'));
    if (*s == '\0') {
        fsetpos (fptr, position);
        return 1;
    }
    return 0;
}

int next (FILE *fptr, char c0) {
    int c1;
    while ((c1 = fgetc(fptr)) != c0)
        if (c1 == EOF)
            return 0;
    return 1;
}

int nextnon (FILE *fptr, char c0) {
    int c1;
    while ((c1 = getc(fptr)) == c0)
        if (c1 == EOF)
            return 0;
    ungetc (c1, fptr);
    return 1;
}

#endif /* _FPDIO_C */
