Minix1.5/commands/elvis/opts.c
/* opts.c */
/* Author:
* Steve Kirkendall
* 16820 SW Tallac Way
* Beaverton, OR 97006
* kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
*/
/* This file contains the code that manages the run-time options -- The
* values that can be modified via the "set" command.
*/
#include "vi.h"
#ifndef NULL
#define NULL (char *)0
#endif
extern char *getenv();
/* These are the default values of all options */
char o_autoindent[1] = {FALSE};
char o_autowrite[1] = {FALSE};
#ifndef SET_NOCHARATTR
char o_charattr[1] = {FALSE};
#endif
char o_columns[3] = {80, 32, 255};
char o_exrefresh[1] = {TRUE};
char o_ignorecase[1] = {FALSE};
#ifdef M_SYSV
char o_keytime[3] = {0, 0, 2};
#else
char o_keytime[3] = {2, 0, 2};
#endif
char o_keywordprg[80] = KEYWORDPRG;
char o_lines[3] = {25, 2, 50}; /* More lines? Enlarge kbuf */
char o_magic[1] = {TRUE};
char o_paragraphs[30] = "PPppPApa";
char o_readonly[1] = {FALSE};
char o_report[3] = {5, 1, 127};
char o_scroll[3] = {12, 1, 127};
char o_sections[30] = "SEseSHsh";
char o_shell[60] = "/bin/sh";
char o_shiftwidth[3] = {8, 1, 255};
char o_sidescroll[3] = {8, 1, 40};
char o_sync[1] = {FALSE};
char o_tabstop[3] = {8, 1, 40};
char o_term[30] = "?";
char o_vbell[1] = {TRUE};
char o_wrapmargin[3] = {0, 0, 255};
char o_wrapscan[1] = {TRUE};
/* The following describes the names & types of all options */
#define BOOL 0
#define NUM 1
#define STR 2
#define SET 0x01
#define CANSET 0x02
struct
{
char *name; /* name of an option */
char *nm; /* short name of an option */
char type; /* type of an option */
char flags; /* boolean: has this option been set? */
char *value; /* value */
}
opts[] =
{
/* name type flags value */
{ "autoindent", "ai", BOOL, CANSET, o_autoindent },
{ "autowrite", "aw", BOOL, CANSET, o_autowrite },
#ifndef SET_NOCHARATTR
{ "charattr", "ca", BOOL, CANSET, o_charattr },
#endif
{ "columns", "co", NUM, SET, o_columns },
{ "exrefresh", "er", BOOL, CANSET, o_exrefresh },
{ "ignorecase", "ic", BOOL, CANSET, o_ignorecase },
{ "keytime", "kt", NUM, CANSET, o_keytime },
{ "keywordprg", "kp", STR, CANSET, o_keywordprg },
{ "lines", "li", NUM, SET, o_lines },
{ "magic", "mg", BOOL, CANSET, o_magic },
{ "paragraphs", "pa", STR, CANSET, o_paragraphs },
{ "readonly", "ro", BOOL, CANSET, o_readonly },
{ "report", "re", NUM, CANSET, o_report },
{ "scroll", "sc", NUM, CANSET, o_scroll },
{ "sections", "se", STR, CANSET, o_sections },
{ "shell", "sh", STR, CANSET, o_shell },
{ "shiftwidth", "sw", NUM, CANSET, o_shiftwidth },
{ "sidescroll", "ss", NUM, CANSET, o_sidescroll },
{ "sync", "sy", BOOL, CANSET, o_sync },
{ "tabstop", "ts", NUM, CANSET, o_tabstop },
{ "term", "te", STR, SET, o_term },
{ "vbell", "vb", BOOL, CANSET, o_vbell },
{ "wrapmargin", "wm", NUM, CANSET, o_wrapmargin },
{ "wrapscan", "ws", BOOL, CANSET, o_wrapscan },
{ NULL, NULL, 0, CANSET, NULL }
};
/* This function initializes certain options from environment variables, etc. */
initopts()
{
char *val;
int i;
/* set some stuff from environment variables */
if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
{
strcpy(o_shell, val);
}
if (val = getenv("TERM")) /* yes, ASSIGNMENT! */
{
strcpy(o_term, val);
}
/* set some stuff according to the screen size */
*o_lines = LINES;
*o_columns = COLS;
*o_scroll = LINES / 2 - 1;
/* disable the vbell option if we don't know how to do a vbell */
if (!VB)
{
for (i = 0; opts[i].value != o_vbell; i++)
{
}
opts[i].flags &= ~CANSET;
*o_vbell = FALSE;
}
}
/* This function lists the current values of all options */
dumpopts(all)
int all; /* boolean: dump all options, or just set ones? */
{
int i;
int col;
for (i = col = 0; opts[i].name; i++)
{
/* if not set and not all, ignore this option */
if (!all && !(opts[i].flags & SET))
{
continue;
}
/* align this option in one of the columns */
if (col > 52)
{
addch('\n');
col = 0;
}
else if (col > 26)
{
while (col < 52)
{
qaddch(' ');
col++;
}
}
else if (col > 0)
{
while (col < 26)
{
qaddch(' ');
col++;
}
}
switch (opts[i].type)
{
case BOOL:
if (!*opts[i].value)
{
qaddch('n');
qaddch('o');
col += 2;
}
addstr(opts[i].name);
col += strlen(opts[i].name);
break;
case NUM:
wprintw(stdscr, "%s=%-3d", opts[i].name, *opts[i].value & 0xff);
col += 4 + strlen(opts[i].name);
break;
case STR:
wprintw(stdscr, "%s=\"%s\"", opts[i].name, opts[i].value);
col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
break;
}
exrefresh();
}
if (col > 0)
{
addch('\n');
exrefresh();
}
}
/* This function saves the current configuarion of options to a file */
saveopts(fd)
int fd; /* file descriptor to write to */
{
int i;
/* HACK! refresh the screen so we can borrow its buffer */
refresh();
/* write each set options */
for (i = 0; opts[i].name; i++)
{
/* if unset or unsettable, ignore this option */
if (!(opts[i].flags & SET) || !(opts[i].flags & CANSET))
{
continue;
}
qaddstr("set ");
switch (opts[i].type)
{
case BOOL:
if (!*opts[i].value)
{
qaddch('n');
qaddch('o');
}
addstr(opts[i].name);
break;
case NUM:
wprintw(stdscr, "%s=%-3d", opts[i].name, *opts[i].value & 0xff);
break;
case STR:
wprintw(stdscr, "%s=\"%s\"", opts[i].name, opts[i].value);
break;
}
qaddch('\n');
}
/* write the buffered stuff to the file */
if (stdscr != kbuf)
{
write(fd, kbuf, (int)(stdscr - kbuf));
stdscr = kbuf;
}
}
/* This function changes the values of one or more options. */
setopts(assignments)
char *assignments; /* a string containing option assignments */
{
char *name; /* name of variable in assignments */
char *value; /* value of the variable */
char *scan; /* used for moving through strings */
int i, j;
/* for each assignment... */
for (name = assignments; *name; )
{
/* skip whitespace */
if (*name == ' ' || *name == '\t')
{
name++;
continue;
}
/* find the value, if any */
for (scan = name; *scan >= 'a' && *scan <= 'z'; scan++)
{
}
if (*scan == '=')
{
*scan++ = '\0';
if (*scan == '"')
{
value = ++scan;
while (*scan && *scan != '"')
{
scan++;
}
if (*scan)
{
*scan++ = '\0';
}
}
else
{
value = scan;
while (*scan && *scan != ' ' && *scan != '\t')
{
scan++;
}
if (*scan)
{
*scan++ = '\0';
}
}
}
else
{
if (*scan)
{
*scan++ = '\0';
}
value = NULL;
if (name[0] == 'n' && name[1] == 'o')
{
name += 2;
}
}
/* find the variable */
for (i = 0;
opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
i++)
{
}
/* change the variable */
if (!opts[i].name)
{
msg("invalid option name \"%s\"", name);
}
else if (!(opts[i].flags & CANSET))
{
msg("option \"%s\" can't be altered", name);
}
else if (value)
{
switch (opts[i].type)
{
case BOOL:
msg("option \"[no]%s\" is boolean", name);
break;
case NUM:
j = atoi(value);
if (j == 0 && *value != '0')
{
msg("option \"%s\" must have a numeric value", name);
}
else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
{
msg("option \"%s\" must have a value between %d and %d",
name, opts[i].value[1], opts[i].value[2] & 0xff);
}
else
{
*opts[i].value = atoi(value);
opts[i].flags |= SET;
}
break;
case STR:
strcpy(opts[i].value, value);
opts[i].flags |= SET;
break;
}
}
else /* valid option, no value */
{
if (opts[i].type == BOOL)
{
*opts[i].value = (name[-1] != 'o');
opts[i].flags |= SET;
}
else
{
msg("option \"%s\" must be given a value", name);
}
}
/* move on to the next option */
name = scan;
}
}