Minix1.5/commands/elvis/opts.c

Compare this file to the similar file:
Show the results in this format:

/* 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;
	}
}