#ifndef lint
static char Sccsid[] = "@(#)putrcd.c	3.1    DeltaDate 8/3/90    ExtrDate 10/6/90";
#endif

/*      PUTRCD.C        */
/*      This subroutine is used to format print a record
 *      Input is :
 *          1) An optional pointer to the header to be printed
 *          2) A pointer to the field structures defining the record
 *          3) A pointer to the record
 *          4) The output file
 *          5) The format of the output
 *          6) The width of a line on the output device
 *          7) The line spacing
 *      It returns the number of lines printed.
 *      The format is specified in "printdb.c"
 */
#include "stdio.h"
#include "cardfile.h"

putrcd(first, rcd, file, fmt, width, space)
char    *first, *rcd;
FILE    *file;
char    *fmt;
int     width, space;
{
    char        *fmt_ptr;
    char        *fld_ptr[MAXFLDS+2];
    char        fmtspec[25];
    int         i, field;
    int		max_flds;
    int         atcol, tocol;
    int         state;
    char	*getfield();
#define COPY    0
#define ESC     1
#define FIELD   2
    
    if (first != 0) {
        fprintf(file, "          %s", first);
        for (i=0; i<space; i++)
            putc('\n', file);
    }
    rcd[strlen(rcd)-1] = '\0';  /* throw away \n */
    getfield(rcd, ":"); /* throw away flag */
    i = 1;
    /* get position of all fields */
    while ((fld_ptr[i++]=getfield(0, ":")) != NULL) ;
    max_flds = --i;
    /* analyze format string */
    state = COPY;
    atcol = 1;
    fmt_ptr = fmt;
    while (*fmt != '\0') {
        switch (state) {
        case COPY:
            if (*fmt == '%') {
                state = ESC;
            } else {
                putc(*fmt, file);
                ++atcol;
            }
            ++fmt;
            break;
        case ESC:
            if (*fmt == 'n') {                          /* %n */
                for (i=0; i<space; i++)
                    putc('\n', file);
                atcol = 1;
                state = COPY;
            } else if (*fmt == 'f') {                   /* %f */
                putc('\f', file);
                atcol = 1;
                state = COPY;
            } else if (*fmt == 't') {                   /* %t */
                if (*(fmt+1) == '(') {          /* %t(NN) */
                    fmt += 2;   /* point past '(' */
                    tocol = atoi(fmt);
                    if (tocol < atcol) {
                        fmt_error(fmt_ptr, fmt-fmt_ptr);
                        return(-1);
                    }
                    while (atcol++ < tocol) {   /* space to correct column */
                        putc(' ', file);
                    }
                    /* move past column specifier in format */
                    while (*fmt >'0' && *fmt <= '9') {
                        ++fmt;
                    }
                } else {                        /* %t */
                    putc('\t', file);
                    atcol += 8 - (atcol-1)%8;
                }
                state = COPY;
            } else if (*fmt == '%') {                   /* %% */
                state = COPY;
                ++atcol;
                putc('%', file);
            } else if (*fmt >= '0' && *fmt <= '9') {    /* %NN */
                state = FIELD;
                field = atoi(fmt);
		if (field > max_flds) {
		    fmt_error(fmt_ptr, fmt-fmt_ptr);
		    return(-1);
		}
                while (*(fmt+1) >= '0' && *(fmt+1) <= '9')
                    ++fmt;
            } else {
                fmt_error(fmt_ptr, fmt-fmt_ptr);
                return(-1);
            }
            ++fmt;
            break;
        case FIELD:
            strcpy(fmtspec, "%s");
            if (*fmt == '(') {  /* special format */
                ++fmt;
                strncpy(fmtspec, fmt, (i = strchr(fmt, ')') - fmt));
                fmtspec[i] = '\0';
                fmt += i + 1;
                if(putfield(file, fld_ptr[field], fmtspec, &atcol, width) == -1)
                    return(-1);
            } else {            /* default string format */
                if(putfield(file, fld_ptr[field], fmtspec, &atcol, width) == -1)
                    return(-1);
                if (*fmt == '.') {
                    ++fmt;
                }
            }
            state = COPY;
            break;
        }
    }
    return(0);
}

    
/*
 * Print a field in default format
 */
putfield(outfile, fld, outfmt, colptr, width)
FILE    *outfile;
char    *fld;
char    *outfmt;
int     *colptr;
int     width;
{
    int         cleft;          /* number of characters left on line */
    char        format[64];
    char        outstr[512];
    double      atof();
    long        atol();

    if (fld == NULL)
        return(0);
    cleft = width - *colptr;
    while (strlen(fld) > cleft) {       /*break field if too long for 1 line */
        if (*(fld+cleft) == ' ' || *(fld+cleft) == ',' || cleft <= 10) {
            if (cleft <= 10)
                cleft = width - *colptr;        /* reset to use full line */
            sprintf(format, "%%.%ds\n", cleft);
            fprintf(outfile, format, fld);
            fld += cleft;
            cleft = width;
            *colptr = 1;
            continue;
        }
        --cleft;
    }
    switch (outfmt[strlen(outfmt)-1]) {
    case 's':
        sprintf(outstr, outfmt, fld);
        break;
    case 'f':
    case 'e':
    case 'E':
    case 'g':
    case 'G':
        sprintf(outstr, outfmt, atof(fld));
        break;
    case 'd':
    case 'u':
    case 'o':
    case 'x':
    case 'X':
        sprintf(outstr, outfmt, atoi(fld));
        break;
    default:
        printf("unknown format '%s'\n", outfmt);
        return(-1);
    }
    *colptr += strlen(outstr);
    fprintf(outfile, "%s", outstr);
    return(0);
}


fmt_error(fmt, col)
char    *fmt;
int     col;
{
    char	str[200];

    sprintf(str, "format='%s'   Error near column %d", fmt, col);
    msg(str);
    sleep(4);
}
