382 lines
7.7 KiB
C
382 lines
7.7 KiB
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;
|
|
}
|
|
}
|