# ifndef lint
static char *rcs_id =
    "@(#) $Header: /usr4/src/mpage/RCS/mp_args.c,v 2.10 90/06/20 17:56:33 slevy Exp $";
# endif

/*
 * mpage:    a program to reduce pages of print so that several pages
 *           of output appear on one printed page.
 *
 * Written by:
 *   ...!uunet!\                       Mark Hahn, Sr Systems Engineer
 *              >pyrdc!mark            Pyramid Technology Corporation
 * ...!pyramid!/                       Vienna, Va    (703)848-2050
 *
 *
 * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
 *  
 *     Permission is granted to anyone to make or distribute verbatim
 *     copies of this document as received, in any medium, provided
 *     that this copyright notice notice is preserved, and that the
 *     distributor grants the recipient permission for further
 *     redistribution as permitted by this notice.
 *
 */

/* $Log:    mp_args.c,v $
 * Revision 2.10  90/06/20  17:56:33  slevy
 * But do set "consumed" for -P option, the only one which isn't getopt-like.
 * 
 * Revision 2.9  90/06/20  17:51:37  slevy
 * Always set "consumed" flag in OPTARG macro.  Don't bother to set it
 * explicitly in individual option cases.
 * 
 * Revision 2.8  90/02/01  17:12:26  slevy
 * Add -r (reverse pages) and -j (print just selected sheets) options;
 * allow a space between options and their arguments a la getopt
 * EXCEPT for lousy "-P" option whose argument is optional, fie.
 * 
 * Revision 2.7  90/01/15  14:48:20  slevy
 * Add -S option to turn off new "square reduction" feature.
 * Also turn it off if printing landscape-shaped pages.
 * 
 * Revision 2.6  89/05/25  15:43:07  mark
 * checked in with -k by slevy at 90.01.15.14.03.56.
 * 
 * Revision 2.6  89/05/25  15:43:07  mark
 * added the -b options as a converse to the -o option.
 * 
 * Revision 2.5  89/05/25  10:42:39  mark
 * changes to print a page count on stderr after the print job is queued.
 * 
 * Revision 2.4  89/05/25  08:57:47  mark
 * rearranged the rcs header keywords for better readability.
 * 
 * Revision 2.3  89/05/22  14:41:03  mark
 * Fixed the type-o in the rcs identification string
 * 
 * Revision 2.2  89/05/22  14:38:06  mark
 * Added rcs identification usable with the "what" program
 * 
 * Revision 2.1  89/05/22  14:31:29  mark
 * New Major Revision
 * 
 * Revision 1.1  89/05/22  14:25:29  mark
 * Initial revision
 *  */

#include "mp_head.h"
#include <ctype.h>
#include <string.h>

/*
 * Function declarations
 */
static char **slice();



int
do_args(argc, argv, envflag)
 int argc;
 char **argv;
 int envflag;
{
    char *optstr;
    int consumed;
    int currarg;
    int opterrors;

#define OPTARG()  \
    { consumed = 1; if(*++optstr == '\0') optstr = argv[++currarg]; }

    opterrors = 0;
    for (currarg = 1; currarg < argc; currarg++) {
        if (*argv[currarg] != '-') {
            if (envflag)
                opterrors++;
            break;
        }
        optstr = argv[currarg];
        consumed = 0;
        while (!consumed && *++optstr) {
            switch (*optstr) {
                default:
                        fprintf(stderr, "%s: unknown option -%c\n",
                                        MPAGE, *optstr);
                        opterrors++;
                        break;
                case '1':
                        sheetindex = 0;
                        break;
                case '2':
                        sheetindex = 1;
                        break;
                case '4':
                        sheetindex = 2;
                        break;
                case '8':
                        sheetindex = 3;
                        break;
                case 'A':    /* A4 sized, european paper */
                        opt_a4 = 1;
                        break;
                case 'a':    /* itoggle between accross and updown */
                        sheetorder = sheetorder == LEFTRIGHT ?
                                     UPDOWN : LEFTRIGHT;
                        break;
                case 'c':    /* concat pages from different files on sheet */
                        opt_file = 1 - opt_file;
                        break;
                case 'f':    /* fold long lines */
                        opt_fold = 1 - opt_fold;
                        break;
                case 'h':
                        OPTARG();
                        opt_doheader = 1;
                        (void) strcpy(opt_header, optstr);
                        break;
                case 'H':
                        opt_mp_header = 1;
                        break;
                case 'I':
                        OPTARG();
                        opt_indent = atoi(optstr);
                        break;
                case 'j':    /* Just these sheets */
                        OPTARG();
                        if (isdigit(*optstr))
                            opt_first = strtol(optstr, &optstr, 10);
                        else
                            opt_first = 1;
                        opt_last = MAXINT;
                        if (*optstr == '-') {
                            if(isdigit(*++optstr))
                            opt_last = strtol(optstr, &optstr, 10);
                        }
                        if (*optstr == '/' || *optstr == '%')
                            opt_alt = atoi(++optstr);
                        break;
                case 'L':
                        OPTARG();
                        opt_lines = atoi(optstr);
                        break;
                case 'l':    /* landscape */
                        sheetaspect = sheetaspect == LANDSCAPE ?
                                      NORMAL : LANDSCAPE;
                        break;
                case 'm': {
                        int sm = 2*DEFAULTSMARGIN;
    
                        consumed = 1;
                        if (*++optstr == '\0') {
                            sheetmargin_left = sm;
#if defined(ALL_MARGINS)
                            sheetmargin_right = sm;
                            sheetmargin_top = sm;
                            sheetmargin_bottom = sm;
#endif
                            break;
                        }
                                
                        while (*optstr) {
                            if (isdigit(*optstr)) {
                                sm = *optstr - '0';
                                while (*++optstr && isdigit(*optstr))
                                    sm = sm*10 + *optstr - '0';
                            }
                            switch (*optstr) { 
                                case 'l': sheetmargin_left = sm;
                                          break;
                                case 'r': sheetmargin_right = sm;
                                          break;
                                case 't': sheetmargin_top = sm;
                                          break;
                                case 'b': sheetmargin_bottom = sm;
                                          break;
                                case '\0':sheetmargin_left = sm;
                                          sheetmargin_right = sm;
                                          sheetmargin_top = sm;
                                          sheetmargin_bottom = sm;
                                          break;
                                default:  fprintf(stderr,
                                             "%s: Unknown -m margin "
                                             "specifier: %c\n", MPAGE, *optstr);
                                          break;
                            }
                            if (*optstr)
                                optstr++;
                        }
                        break;
                    }
                case 'M': {
                        int pm = 2*DEFAULTPMARGIN;

                        consumed = 1;
                        if (*++optstr == '\0') {
                            pagemargin_left = pm;
#if defined(ALL_MARGINS)
                            pagemargin_right = pm;
                            pagemargin_top = pm;
                            pagemargin_bottom = pm;
#endif
                            break;
                        }
                                
                        while (*optstr) {
                            if (isdigit(*optstr)) {
                                pm = *optstr - '0';
                                while (isdigit(*++optstr))
                                    pm = pm*10 + *optstr - '0';
                            }
                            switch (*optstr) { 
                                case 'l': pagemargin_left = pm;
                                          break;
                                case 'r': pagemargin_right = pm;
                                          break;
                                case 't': pagemargin_top = pm;
                                          break;
                                case 'b': pagemargin_bottom = pm;
                                          break;
                                case '\0':pagemargin_left = pm;
                                          pagemargin_right = pm;
                                          pagemargin_top = pm;
                                          pagemargin_bottom = pm;
                                          break;
                                default:  fprintf(stderr,
                                             "%s: Unknown -M margin "
                                             "specifier: %c\n", MPAGE, *optstr);
                                          break;
                            }
                            if (*optstr)
                                optstr++;
                        }
                        break;
                    }
                case 'o':    /* toggle print outlines */
                        opt_outline = 1 - opt_outline;
                        break;
                case 'P':    /* Printer */
                        doprint=1;
                        consumed = 1;
                        if (*++optstr)
                            (void) strcpy(printer, optstr);
                        break;
                case 'p':    /* pr */
                        opt_pr = 1;
                        consumed = 1;
                        if (*++optstr)
                            (void) strcpy(prprog, optstr);
                        break;
                case 'r':
                        opt_reverse = 1;
                        break;
                case 'S':
                        opt_square = 0;
                        break;
                case 'U':    /* Letter sized, US paper */
                        opt_a4 = 0;
                        break;
                case 'v':    /* verbose (print page count) */
                        opt_verbose = 1 - opt_verbose;
                        break;
                case 'W':
                        OPTARG();
                        opt_width = atoi(optstr);
                        break;
            }
        }
    }
    set_page();

    if (opterrors)
        return -1;

    return currarg;

} /* do_args */



int
do_env()
{
    int argc;
    char **argv;
    char copy[LINESIZE];
    char *env;

    if (env = getenv("PRINTER"))
        strcpy(printer, env);

    if (env = getenv("MPAGE")) {
        strcpy(copy, env);
        argv = slice(copy, &argc);
        if (do_args(argc, argv, 1) < 0) {
            fprintf(stderr, "%s: error in environment \"%s\"\n", MPAGE, env);
            return 0;
        }
    }

    return 1;

} /* do_env */

#define ARGCNT	20

char *slc_argv[ARGCNT+1];

static char **
slice(string, cntp)
 char *string;
 int *cntp;
{
    int count;

    /*
     * mimic the shell for conformity
     */
    slc_argv[0] = MPAGE;
    count = 1;
    /*
     * while there are still characters to be processed
     */
    while (*string && count < ARGCNT) {
        /*
         * skip any leading or leftover white space
         */
        while (*string == ' ')
            string++;
        /*
         * make sure we had more than just white space before
         * we believe we actually have an argument
         */
        if (*string) {
            /*
             * point the next slot in argv to this string
             */
            slc_argv[count++] = string;
            /*
             * and go looking for the end of this string
             * which is delienated by a space or NULL
             */
            while (*string && *string != ' ')
                string++;
            /*
             * if this not the end of the string, then convert
             * the space into a NULL and move forward one byte.
             * if this is the end of the string, we already have
             * a suitable NULL byte for the string and it also
             * drops us out of all the loops
             */
            if (*string) {
                *string = 0;
                string++;
            }
        }
    }
    /*
     * return the count via the integer pointer we were given
     * and put a null pointer into the argv array for conformity
     */
    if (*string && count == ARGCNT)
        fprintf(stderr, "%s: to many options in MPAGE environment variable,"
                        " skipping '%s'\n", MPAGE, string);
    slc_argv[count] = 0;
    *cntp = count;

    return slc_argv;

} /* slice */
