/*************************************************************************
 ***                        option.c                     (JJB TEMPLAR) ***
 *** Date modifications begun: 7/8/89.                                 ***
 *** Last modified: 26/8/89.                                           ***
 *************************************************************************/
/*** Process command line options.                                     ***
 *************************************************************************/

#include "less.h"

#include <libraries/dosextens.h>
#include <workbench/workbench.h>
#include <proto/icon.h>

extern APTR             WBenchMsg;      /* A lie, to ... etc */
extern struct IconBase  *IconBase;
extern char             *_ProgramName;

extern int  gotenv();

#define DEF_F_NBUFS     5   /* Default for f_nbufs. This value has been
    * hard coded into some of the printf statements, so if you change it,
    * don't forget to modify them too. */

int     f_nbufs     = DEF_F_NBUFS;  /* Number of buffers to use. */
int     top_scroll  = 0;            /* Repaint screen from top? */
int     pr_type     = PR_SHORT;     /* Type of prompt (short, medium, long) */
int     quit_at_eof = 0;            /* Quit after hitting end of file twice */
int     squeeze     = 0;            /* Squeeze multiple blank lines into 1 */
int     back_scroll = 30;           /* Repaint screen on backwards movement */
int     twiddle     = 1;            /* Display "~" for lines after EOF */
int     fast_line   = 1;            /* Ignore special characters? */
int     scroll_bar  = 0;            /* Use scroll bar? */
int     maxim       = 0;            /* Open maximum window? */
int     quiet       = 0;            /* Don't use me audio bell? */

extern int  nbufs;
extern char version[];

extern int  pat_opt;        /* Flag that new pattern has been set */
extern char pat[];          /* Holds pattern. User may crash if pattern is
                             * too long */

char    *usage[] = {
"[32m",version,"[33m :text display program.[m\n",
"[32mUSAGE:[m ",NULL," [<{+|-}{mode}>] [#{num}] <filename>\n",
"    where [32mfilename[m = the name of a file to read.\n",
"          [32mmode[m = f         [+] fast line mode (ignore's special chars).\n",
"                 t         [+] twiddle mode (marks lines after EOF with ~).\n",
"                 b         [+] back scroll.\n",
"                 T         [-] top scroll.\n",
"                 q         [-] quit after two attempts to go past EOF.\n",
"                 s         [-] squeeze multiple blank lines together.\n",
"                 S         [-] scroll bar.\n",
"                 p{s|m|l}  [s] prompt type (short|medium|long).\n",
"                 m         [-] maximise window size.\n",
"                 P{str}    [ ] set default search pattern to str (max 20).\n",
"                 Q         [-] be quiet (use DisplayBeep for bell).\n",
"    '+' means turn mode on, '-' means turn mode off, defaults are above.\n",
"          [32mnum[m = number of buffers to use [min/default = 5].\n",
"[32mNOTE:[m [] - optional, <> - 1 or more, {} - mandatory.\n"};

char    *tooltypes[] = {
    "FAST",
    "TWIDDLE",
    "BACKSCROLL",
    "TOPSCROLL",
    "QUITEOF",
    "SQUEEZE",
    "SCROLLBAR",
    "PROMPT",
    "NUMBUFS",
    "MAXIM",
    "PATTERN",
    "QUIET"};

void    doenv();
int     toolval(char *);

int     toolval(val) /*==================================================*/
char    *val;
{
    return((MatchToolValue(val,"ON"))? 1: 0);
}

int     getint(cp) /*====================================================*/
register char   *cp;
{
register char   *st = cp;
register int    ret,place;
  /*** Don't swallow whitespace ------------------------------------------
    while (*st == ' ') *st++;
    cp = st;
   ------------------------------------------------------------------- ***/
    while ((*cp >= '0') && (*cp <= '9')) *cp++;
    ret = 0;    place = 1;
    while (--cp >= st) {
        ret += (*cp - '0') * place;
        place *= 10;
    }
    return(ret);
}

void    opticon(fname) /*================================================*/
char    *fname;
{
register struct DiskObject *icon;
register char   *val;
register int    j;

  /* Fails if no library, from CLI, or no icon */
    if (!IconBase || !WBenchMsg || !(icon = GetDiskObject(fname)))
        return;

    for (j = 0; j < sizeof(tooltypes)/4; j++) {
        val = (char *)FindToolType(icon->do_ToolTypes,tooltypes[j]);
        if (val) switch (j) {
            case (0): fast_line   = toolval(val);       break;
            case (1): twiddle     = toolval(val);       break;
            case (2): back_scroll = toolval(val) * 30;  break;
            case (3): top_scroll  = toolval(val);       break;
            case (4): quit_at_eof = toolval(val);       break;
            case (5): squeeze     = toolval(val);       break;
            case (6): scroll_bar  = toolval(val);       break;
            case (7): switch (*val) {
                    case ('S'): pr_type = PR_SHORT;     break;
                    case ('M'): pr_type = PR_MEDIUM;    break;
                    case ('L'): pr_type = PR_LONG;      break;
                }
                break;
            case (8): f_nbufs = getint(val);
                      if (f_nbufs < DEF_F_NBUFS) f_nbufs = DEF_F_NBUFS;
                      break;
            case (9): maxim       = toolval(val);       break;
            case (10):  pat_opt = 1;
                        strcpy(pat,val);
                        break;
            case (11): quiet      = toolval(val);       break;
        }
    }
    FreeDiskObject(icon);
}

void    doopts(argc,argv) /*=============================================*/
register int    argc;     /* main processes filenames. This routine     */
register char   *argv[];  /* just does the options (+|-|#)c             */
{
register int    on,j;
    doenv();                /* Check ENV:ty */
    if (!argc) {            /* From WB. Get args from program's icon */
        opticon(_ProgramName);
        return;
    }
    while (--argc) {
        on = 0;            /* '-' turns option off */
        switch (argv[argc][0]) {
            case ('+'): on = 1;     /* And fall through */
            case ('-'): switch (argv[argc][1]) {
                    case ('f'): fast_line = on;     break;
                    case ('t'): twiddle = on;       break;
                    case ('b'): back_scroll = on*30;    break;
                    case ('s'): squeeze = on;       break;
                    case ('q'): quit_at_eof = on;   break;
                    case ('T'): top_scroll = on;    break;
                    case ('S'): scroll_bar = on;    break;
                    case ('p'): switch (argv[argc][2]) {
                            case ('s'): pr_type = PR_SHORT;  break;
                            case ('m'): pr_type = PR_MEDIUM; break;
                            case ('l'): pr_type = PR_LONG;   break;
                        }
                        break;
                    case ('m'): maxim = on;         break;
                    case ('P'): pat_opt = 1;
                                strcpy(pat,&argv[argc][2]);
                                break;
                    case ('Q'): quiet = on;         break;
                }
                break;
            case ('#'): f_nbufs = getint(&argv[argc][1]);
                        if (f_nbufs < DEF_F_NBUFS) {
                            printf("WARNING: # doesn't go less than 5!\n");
                            f_nbufs = DEF_F_NBUFS;
                        }
                        break;
            case ('?'): usage[4] = argv[0];
                        for (j = 0; j < sizeof(usage)/4; j++) printf(usage[j]);
                        cleanup(NULL,0);
        }
    }
}

void    doenv() /*=======================================================*/
{               /* This function could be cleaned up a bit!              */
BPTR    file;
char    buf[80];
int     len;
register int    on,j;
register char   *name;

    if (!gotenv()) return;                           /* Didn't find ENV: */
    if (!(file = Open("ENV:ty",MODE_OLDFILE))) return; /* No ty variable */
    if ((len = Read(file,buf,79)) <= 0) {
        Close(file);                  /* Either empty file, or DOS error */
        return;
    }
    Close(file);
    buf[len] = 0;       name = buf;
    while (*name) {
        on = 0;
        switch (*name++) {
            case ('+'): on = 1;
            case ('-'): switch (*name) {
                    case ('f'): fast_line = on;     break;
                    case ('t'): twiddle = on;       break;
                    case ('b'): back_scroll = on*30;    break;
                    case ('s'): squeeze = on;       break;
                    case ('q'): quit_at_eof = on;   break;
                    case ('T'): top_scroll = on;    break;
                    case ('S'): scroll_bar = on;    break;
                    case ('p'): switch (*(++name)) {
                            case ('s'): pr_type = PR_SHORT;  break;
                            case ('m'): pr_type = PR_MEDIUM; break;
                            case ('l'): pr_type = PR_LONG;   break;
                        }
                        break;
                    case ('m'): maxim = on;         break;
                    case ('P'): pat_opt = 1;    j = 0;      name++;
                                while (*name && (*name != ' '))
                                    pat[j++] = *name++;
                                pat[j] = 0;
                                break;
                    case ('Q'): quiet = on;         break;
                    default: name--;
                }
                if (*name) name++;
                break;
            case ('#'): f_nbufs = getint(name);
                        if (f_nbufs < DEF_F_NBUFS) {
                            printf("WARNING: # doesn't go less than 5!\n");
                            f_nbufs = DEF_F_NBUFS;
                        }
                        break;
	}
    }
}
