menunix for 4.2 BSD (final posting of source)

Gary Perlman perlman at wanginst.UUCP
Wed Jan 23 11:58:26 AEST 1985


> I haven't finished compiling menunix, but I DID notice that the sources did
> not extract properly, mostly due to the fact that there were imbedded
> control characters in literals which seem to have been stripped out by mailers
> (because the author did not use \xxx to indicate control characters.)
> 
> menu.h:		#define ESC ''	/* this should be '\033' */
> 
> file.c,menu.c,image.c,linedit.c:  in each case, the string "" should be
>        replaced with "\007" wherever it occurs.
> 
> Actually, image.c is included, but not used anywhere.  I am fairly sure that
> this is all that needs to be fixed, since the number of additions makes the
> character count correct (if you were typing in the control character itself
> instead of the \xxx sequence instead).

I am very sorry for fouling up so many times.
I never new that mailers ate control characters.
I am posting yet another version, with the above fixes.
It is just another example of old software not being up to par.
I appreciate that the above person was constructive.

Gary Perlman/Wang Institute/Tyngsboro, MA/01879/(617) 649-9731

#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	src
# This archive created: Tue Jan 22 20:57:36 1985
# By:	Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
export PATH; PATH=/bin:$PATH
if test ! -d 'src'
then
	echo shar: creating directory "'src'"
	mkdir 'src'
fi
echo shar: entering directory "'src'"
cd 'src'
echo shar: extracting "'menu.defs'" '(865 characters)'
if test -f 'menu.defs'
then
	echo shar: over-writing existing file "'menu.defs'"
fi
cat << \SHAR_EOF > 'menu.defs'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
char	menudir[100] = MENUDIR;
char	maildir[100] = "/usr/spool/mail";
char	*mailfile;
struct MENU *savemenu;
int	anchored = 0;
int	newmenu;
int	ttyspeed;

char	response[BUFSIZ];
char	*command[MAXCOM];
char	commandbuffer[MAXCOM][BUFSIZ];
int	docmode = 0;
int	progmode = 1;
struct	VAR variables[MAXVAR];
int	nvar = 0;
WINDOW *lmenu, *timewin, *history;
struct MENU *menu, *rootmenu, *stdmenu;
struct MENU *readmenu ();

short	uid, gid;
char	escapechar = '\\';
char	varchar    = '$';
char	shellchar  = '!';
char	popchar    = ',';
char	unixchar   = '.';
char	dotdotchar = '0';
char	quitchar   = '`';
char	modechar   = '_';
int	flipped    = 0;
char	dirpath[MAXDEPTH][NAMESIZ];
int	pathlength = 0;
char	pwdname[BUFSIZ];
WINDOW	*filewin;
int	nonames;
int	page = 1;
struct FILENT filent[MAXENTRIES];
SHAR_EOF
if test 865 -ne "`wc -c 'menu.defs'`"
then
	echo shar: error transmitting "'menu.defs'" '(should have been 865 characters)'
fi
echo shar: extracting "'menu.h'" '(2600 characters)'
if test -f 'menu.h'
then
	echo shar: over-writing existing file "'menu.h'"
fi
cat << \SHAR_EOF > 'menu.h'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#ifndef MENU_H
#define MENU_H
#include <curses.h>
#include <ctype.h>
FILE	*xopen ();
char	*getargs (), *copy (), *interpolate (), *getresponse ();
extern	char	menudir[100];
extern	char	maildir[100];
extern	char	*mailfile;
extern	int	anchored;
extern	int	newmenu;
extern	int	ttyspeed;

#define	MAXOPTION    15
#define	MAXCOM       10
#define	COMMAND       0
#define MAXVAR      100
#define	OUT_OF_RANGE -2
#define	INDENT        5
#define MENUTOP       1
#define MENUBOTTOM   23
#define HISTORY    (MAXOPTION+1)
#define TIMELINE   (MENUBOTTOM)
#define INFOLINE   (MENUBOTTOM-2)
#define RESPLINE   (MENUBOTTOM-1)
#define	NOTICES    (HISTORY-1)
#define RIGHTMENU  (COLS/2)
#define GETRETURN  {printf("press RETURN to continue");while(getchar()!='\n');}
extern char	response[BUFSIZ];
extern char	*command[MAXCOM];
extern char	commandbuffer[MAXCOM][BUFSIZ];
extern int	docmode;
extern int	progmode;
struct	VAR
	{
	char	*name;
	char	*value;
	};
extern struct VAR variables[MAXVAR];
extern int	nvar;
extern WINDOW *lmenu, *timewin, *history;
struct MENU
	{
	char	*menuname;
	char	*display[MAXOPTION];
	char	*program[MAXOPTION];
	char	*arguments[MAXOPTION];
	char	selector[MAXOPTION];
	int	noptions;
	struct MENU *nextmenu[MAXOPTION]; 
	struct MENU *parent;
	char	nowait[MAXOPTION];
	};
extern struct MENU *menu;
extern struct MENU *rootmenu;
extern struct MENU *stdmenu;
extern struct MENU *savemenu;
extern struct MENU *readmenu ();

extern short	uid, gid;
#define	ESC       ''
#define	BACKSPACE ''
#define ESCAPE    '\\'
#define RETURN    '\n'
#define MODECHANGE -2
#define RUN	   -1
extern char	escapechar;
extern char	varchar    ;
extern char	shellchar  ;
extern char	popchar    ;
extern char	unixchar   ;
extern char	dotdotchar ;
extern char	quitchar   ;
extern char	modechar   ;
extern int	flipped    ;
#include <sys/types.h>
#include <sys/dir.h>
#ifdef MAXNAMLEN
#define NAMESIZ MAXNAMLEN
#else
#define NAMESIZ 16
#endif
#include <sys/stat.h>
#define MAXDEPTH 10
extern char	dirpath[MAXDEPTH][NAMESIZ];
extern int	pathlength ;
extern char	pwdname[BUFSIZ];
extern WINDOW	*filewin;
#define MAXENTRIES 250
extern int	nonames;
extern int	page ;
#define	DIRFILE        3
#define	PLAINFILE      1
#define PROGFILE       2
#define	PAGESIZE       9
struct FILENT
	{
	char	f_name[NAMESIZ];
	char	f_protect[12];
	off_t	f_size;
	};
extern struct FILENT filent[MAXENTRIES];
#define begin(c) (c == '[')
#define end(c)  (c == ']' || c == '\n' || c == NULL)
#define separator(c) (c == ':')
#define skipspace(ptr) while (isspace (*ptr)) ptr++;
#endif MENU_H
SHAR_EOF
if test 2600 -ne "`wc -c 'menu.h'`"
then
	echo shar: error transmitting "'menu.h'" '(should have been 2600 characters)'
fi
echo shar: extracting "'display.c'" '(2770 characters)'
if test -f 'display.c'
then
	echo shar: over-writing existing file "'display.c'"
fi
cat << \SHAR_EOF > 'display.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
leftdisplay (menu) struct MENU *menu;
	{
	int i;
	extern	int flipped;
	if (menu == NULL) return;
	wclear (lmenu);
	if (trueval ("highlight")) wstandout (lmenu);
	mvwprintw (lmenu, 0, 0, "[%s]", menu->menuname);
	if (trueval ("highlight")) wstandend (lmenu);
	for (i = 0; i < menu->noptions; i++)
		{
		if (menu->nextmenu[i])
			{
			if (trueval ("highlight")) wstandout (lmenu);
			mvwprintw (lmenu, i+1, INDENT, "[%s]", menu->display[i]);
			if (trueval ("highlight")) wstandend (lmenu);
			}
		else
			{
			mvwprintw (lmenu, i+1, INDENT, menu->display[i]);
			wprintw (lmenu, " (%s)", menu->program[i]);
			}
		if (iscntrl (menu->selector[i]))
		mvwprintw (lmenu, i+1, 0,"^%c",menu->selector[i]-1+'A');
		else mvwaddch (lmenu, i+1, 0, menu->selector[i]);
		}
	wrefresh (lmenu);
	newmenu = 0;
	}

lastcomm ()
	{
	int	i;
	wclear (history);
	for (i = 1; ; i++)
		if (!*variables[i].value) continue;
		else if (ERR == mvwprintw (history, i-1, 0, "%c%s %s",
			varchar, variables[i].name, variables[i].value)) break;
	wrefresh (history);
	}

#include <time.h>
char	*months[] =	{ "January", "February", "March", "April",
			"May", "June", "July", "August",
			"September", "October", "November", "December" };

char	*days[] =	{ "Sunday", "Monday", "Tuesday", "Wednesday",
			"Thursday", "Friday", "Saturday"};
printtime ()
	{
	struct	tm *date;
	long	clock;
	int	hour;

	time (&clock);
	date = (struct tm *) localtime (&clock);
	if ((hour = date->tm_hour) > 12) hour %= 12;
	if (date->tm_sec == 0)
		checkmail (mailfile);
	mvwprintw (timewin, 0, 0, "%s, %s %d.  %d:%02d:%02d",
		days[date->tm_wday], months[date->tm_mon], date->tm_mday,
		hour, date->tm_min, date->tm_sec);
	wrefresh (timewin);
	}

checkmail (mailfile) char *mailfile;
	{
	struct	stat statbuf;
	if (stat (mailfile, &statbuf)) return;
	if (statbuf.st_size)
	    {
	    if (statbuf.st_atime > statbuf.st_mtime)
		mvprintw (NOTICES-1, RIGHTMENU, "You have mail");
	    else
		mvprintw (NOTICES-1, RIGHTMENU, "You have new mail");
	    printw (" (%d bytes)", statbuf.st_size);
		clrtoeol ();
	    }
	refresh ();
	}

display (menu) struct MENU *menu;
	{
	int i;
	if (menu == NULL) return;
	clear (); refresh ();
	printtime ();
	nonames = newdir ();
	page = vdir (page, nonames);
	leftdisplay (menu);
	lastcomm ();
	checkmail (mailfile);
	if (docmode)
		{
		mvprintw (NOTICES-3, RIGHTMENU, "Next selection gets documentation");
		clrtoeol ();
		}
	if (anchored)
		{
		mvprintw (NOTICES-2, RIGHTMENU, "On a diversion from ");
		if (trueval ("highlight")) standout ();
		printw ("[%s]", savemenu->menuname);
		if (trueval ("highlight")) standend ();
		clrtoeol ();
		}
	/* mvwprintw (lmenu, 0, 0, "[%s]", menu->menuname); */
	refresh ();
	}
SHAR_EOF
if test 2770 -ne "`wc -c 'display.c'`"
then
	echo shar: error transmitting "'display.c'" '(should have been 2770 characters)'
fi
echo shar: extracting "'init.c'" '(3653 characters)'
if test -f 'init.c'
then
	echo shar: over-writing existing file "'init.c'"
fi
cat << \SHAR_EOF > 'init.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
struct MENU *
readmenu (filename, header) char *filename; char *header;
	{
	char	*copy ();
	FILE	*ioptr;
	char	line[BUFSIZ];
	char	file[100];
	char	*p, *getvalue ();
	struct MENU *menu = (struct MENU *) calloc (1, sizeof (struct MENU));
	sprintf (file, "%s/%s", menudir, filename);
	if (menu == NULL)
		{ fprintf (stderr, "readmenu: out of space\n"); exit (1); }
	ioptr = xopen (file, "r");
	menu->menuname = copy (header);
	while (p = fgets (line, BUFSIZ, ioptr))
		{
		while (p = getvalue (p, menu));
		if (++menu->noptions > MAXOPTION)
			{
			fprintf (stderr, "readmenu: Too many options\n");
			exit (1);
			}
		}
	fclose (ioptr);
	return (menu);
	}
char *
getvalue (line, menu) char *line; struct MENU *menu;
	{
	char	valuebuf[BUFSIZ];
	char	designator, *value = valuebuf;
	*value = NULL;
	skipspace (line);
	if (!begin (*line++)) return (NULL);
	skipspace (line);
	designator = *line;
	while (!separator (*line))
		if (end (*line)) goto check;
		else line++;
	line++;
	while (!end (*line)) *value++ = *line++;
	*value = NULL;
	line++;
check:
	if (designator != 's')
		value = copy (valuebuf);
	switch (designator)
	    {
	    case 'd': menu->display[menu->noptions] = value; break;
	    case 's': menu->selector[menu->noptions] = *valuebuf; break;
	    case 'm': menu->nextmenu[menu->noptions]
		    = readmenu (value, menu->display[menu->noptions]);
		    menu->nextmenu[menu->noptions]->parent = menu;
		    break;
	    case 'p': menu->program[menu->noptions] = value; break;
	    case 'a': menu->arguments[menu->noptions] = value; break;
	    case 'w': menu->nowait[menu->noptions] = TRUE; break;
	    default:
		fprintf (stderr, "getvalue: bad designator '%c'\n", designator);
	    }
	return (line);
	}

readvar ()
	{
	char	line[BUFSIZ], *lineptr;
	char	namebuf[BUFSIZ], *nameptr;
	char	valuebuf[BUFSIZ], *valueptr;
	char	*interpolate ();
	char	*getenv ();
	FILE	*ioptr;
	int	i;
	for (i = 0; i < MAXCOM; i++)
		{
		variables[i].value = commandbuffer[i];
		variables[i].name  = copy (" ");
		*variables[i].name = '0' + i;
		}
	nvar = MAXCOM;
	variables[nvar].name	= copy ("dir");
	variables[nvar++].value	= pwdname;
	variables[nvar].name	= copy ("menu");
	variables[nvar++].value	= copy (menudir);
	variables[nvar].name	= copy ("home");
	variables[nvar++].value	= getenv ("HOME");
	variables[nvar].name	= copy ("user");
	variables[nvar++].value	= getenv ("USER");
	sprintf (line, "%s/%s", maildir, getenv ("USER"));
	variables[nvar].name	= copy ("mail");
	variables[nvar++].value	= mailfile = copy (line);
	sprintf (line, "%s/%s", getenv ("HOME"), ".menuvar");
	if (access (line, 4))
		sprintf (line, "%s/setup/menunix", getenv ("HOME"));
	if (ioptr = fopen (line, "r"))
	    {
	    while (fgets (line, BUFSIZ, ioptr))
		{
		lineptr = line;
		nameptr = namebuf; *nameptr = NULL;
		valueptr = valuebuf; *valueptr = NULL;
		skipspace (lineptr);
		while (isalnum (*lineptr))
			*nameptr++ = *lineptr++;
		*nameptr = NULL;
		skipspace (lineptr);
		if (*lineptr == '=') lineptr++;
		skipspace (lineptr);
		while (*lineptr != '\n')
			*valueptr++ = *lineptr++;
		*valueptr = NULL;
		variables[nvar].name = copy (namebuf);
		variables[nvar].value = copy (interpolate (valuebuf));
		nvar++;
		}
	    fclose (ioptr);
	    }
	variables[nvar].name	= copy ("editor");
	variables[nvar++].value = copy ("ex");
	variables[nvar].name	= copy ("printdotfiles");
	variables[nvar++].value	= copy ("true");
	variables[nvar].name	= copy ("highlight");
	variables[nvar++].value	= copy ("false");
	variables[nvar].name	= copy ("shell");
	variables[nvar++].value	= copy (getenv ("SHELL"));
	}
SHAR_EOF
if test 3653 -ne "`wc -c 'init.c'`"
then
	echo shar: error transmitting "'init.c'" '(should have been 3653 characters)'
fi
echo shar: extracting "'utility.c'" '(1177 characters)'
if test -f 'utility.c'
then
	echo shar: over-writing existing file "'utility.c'"
fi
cat << \SHAR_EOF > 'utility.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
FILE *
xopen (name, mode) char *name, *mode;
	{
	FILE	*ioptr = fopen (name, mode);
	if (ioptr == NULL)
		{
		fprintf (stderr, "Can't open %s\n", name);
		exit (1);
		}
	}

syscall (command) char *command;
	{
	char	*alias (), *interpolate ();
	char	*c = alias (interpolate (command), "|;");
	char	*getval (), *shell = getval ("shell");
	char	shellcomm[BUFSIZ];
	*shellcomm = NULL;
	if (strcmp (shell, "/bin/sh"))
		sprintf (shellcomm, "%s -c \"%s\"", shell, c);
	nocrmode (); echo ();
	printf ("%s\n", c);
	system (*shellcomm ? shellcomm : c);
	crmode (); noecho ();
	}
char *
copy (string) char *string;
	{
	char	*copy = (char *) malloc (strlen (string) + 1);
	if (copy == NULL)
		{
		clear (); refresh ();
		printf ("You have run out of space\n");
		endwin ();
		exit (1);
		}
	strcpy (copy, string);
	return (copy);
	}

#include <signal.h>
#include <setjmp.h>
jmp_buf env;
timeout () { longjmp (env, 1); }
timegetc (secs)
	{
	int	c;
	extern	timeout ();
	signal (SIGALRM, timeout);
	alarm (secs);
	if (setjmp (env)) return (0);
	c = getchar ();
	signal (SIGALRM, SIG_IGN);
	alarm (0);
	return (c);
	}
SHAR_EOF
if test 1177 -ne "`wc -c 'utility.c'`"
then
	echo shar: error transmitting "'utility.c'" '(should have been 1177 characters)'
fi
echo shar: extracting "'run.c'" '(1483 characters)'
if test -f 'run.c'
then
	echo shar: over-writing existing file "'run.c'"
fi
cat << \SHAR_EOF > 'run.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
run (chosenmenu, chosen) struct MENU *chosenmenu;
	{
	char	syscommand[BUFSIZ];
	char	buf[BUFSIZ], *bufptr = buf;
	char	*strptr;
	int	i;
	if (!chosenmenu->program[chosen]) return;
	if (*chosenmenu->program[chosen] == '-')
		{
		internalrun (chosenmenu, chosen);
		return;
		}
	mvprintw (INFOLINE, 0, "COMMAND: %s %s", chosenmenu->program[chosen],
		chosenmenu->arguments[chosen]);
	clrtoeol ();
	if (docmode)
		{
		docmode = 0;
		strptr = chosenmenu->program[chosen];
		sprintf (variables[COMMAND].value, "man %s", strptr);
		mvprintw (RESPLINE, 0, "Getting documentation on %s, please wait", strptr);
		clrtoeol ();
		move (MENUBOTTOM, 0);
		refresh ();
		syscall (variables[COMMAND].value);
		GETRETURN
		display (menu);
		return;
		}
	if (chosenmenu->arguments[chosen])
		{
		if ((strptr = getargs (chosenmenu->arguments[chosen], NULL)) == NULL)
			{ noecho (); crmode (); return; }
		else sprintf (variables[COMMAND].value, "%s %s", 
			chosenmenu->program[chosen], strptr);
		}
	else sprintf (variables[COMMAND].value, "%s", chosenmenu->program[chosen]);
	clear (); refresh ();
	syscall (variables[COMMAND].value);
	if (!chosenmenu->nowait[chosen]) GETRETURN
	if (anchored)
	    {
	    anchored = 0;
	    display (menu = savemenu);
	    return;
	    }
	for (i = MAXCOM-1; i > 0; i--)
		variables[i].value = variables[i-1].value;
	variables[COMMAND].value = variables[MAXCOM-1].value;
	display (menu);
	}
SHAR_EOF
if test 1483 -ne "`wc -c 'run.c'`"
then
	echo shar: error transmitting "'run.c'" '(should have been 1483 characters)'
fi
echo shar: extracting "'file.c'" '(7008 characters)'
if test -f 'file.c'
then
	echo shar: over-writing existing file "'file.c'"
fi
cat << \SHAR_EOF > 'file.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"

#define	inodir(entry) (entry->d_ino)
#ifdef MAXNAMLEN

#define	namedir(entry) (entry->d_name)

#else

#define	DIR	FILE
#define	opendir(path) fopen (path, "r")
#define closedir(dirp) fclose (dirp)
struct direct *
readdir (dirp)
DIR 	*dirp;
	{
	static	struct	direct	entry;
	if (dirp == NULL) return (NULL);
	for (;;)
		{
		if (fread (&entry, sizeof (struct direct), 1, dirp) == 0) return (NULL);
		if (entry.d_ino) return (&entry);
		}
	}
char	*strncpy ();
char *
namedir (entry)
struct	direct	*entry;
	{
	static	char	name[NAMESIZ];
	return (strncpy (name, entry->d_name, DIRSIZ));
	}

#endif

char *
prname (s, dirpath, pathlength) char *s; char dirpath[MAXDEPTH][NAMESIZ];
	{
	int	i;
	strcpy (s, "/");
	for (i = 0; i < pathlength; i++)
		{
		strcat (s, dirpath[i]);
		strcat (s, "/");
		}
	return (s);
	}

char *
pwd (s) char *s;
	{
	char	*pwd;
	char	pathname[MAXDEPTH][NAMESIZ];
	ino_t	inode[MAXDEPTH];
	struct	direct *dirent;
	struct	stat statbuf;
	dev_t	dotdevno;
	ino_t	rootinode;
	DIR	*ioptr;
	int	i;

	pathlength = 0;
	if (stat ("/", &statbuf)) printf ("Can't stat /\n");;
	rootinode = statbuf.st_ino;
	if (stat (".", &statbuf)) printf ("Can't stat .\n");
	dotdevno = statbuf.st_dev;
	for (;;)
	{
	if ((ioptr = opendir (".")) == NULL)
		{
		printf ("Can't open current directory");
		return (NULL);
		}
	if ((dirent = readdir (ioptr)) == NULL)
	    {
	    closedir (ioptr);
	    return (NULL);
	    }
	else inode[pathlength] = inodir(dirent);
	dirent = readdir (ioptr); /* skip over .. */
	if (pathlength)
	    while (dirent = readdir (ioptr))
		if (inodir(dirent) == inode[pathlength-1])
		    {
		    strcpy (pathname[pathlength-1], namedir(dirent));
		    break;
		    }
	closedir (ioptr);
	if (inode[pathlength] == rootinode)
	    {
	    chdir ("/");
	    ioptr = opendir ("/", "r");
	    while (dirent = readdir (ioptr))
		{
		if (stat (namedir(dirent), &statbuf)) continue;
		if (statbuf.st_dev == dotdevno)
		    {
		    strcpy (dirpath[0], namedir (dirent));
		    pathlength++;
		    for (i = 1; i < pathlength; i++)
			strcpy (dirpath[i], pathname[pathlength-i-1]);
		    if (pathlength == 1 && dirpath[0][0] == '.')
		    pathlength = 0;
		    chdir (pwd = prname (s, dirpath, pathlength));
		    closedir (ioptr);
		    return (pwd);
		    }
		}
	    }
	pathlength++;
	closedir (ioptr);
	chdir ("..");
	}
	}

cd (dirname) char *dirname;
	{
	char	vardir[BUFSIZ];
	char	*interpolate ();
	char	*getenv ();
	int	i;
	if (!dirname) return (-1);
	if (!*dirname) dirname = getenv ("HOME");
	if (chdir (dirname))
		{
		sprintf (vardir, "%c%s", varchar, dirname);
		dirname = interpolate (vardir);
		if (*dirname == NULL) return (-1);
		if (chdir (dirname = interpolate (vardir))) return (-1);
		}
	if (!strcmp (dirname, ".")) return (0);
	if (*dirname == '/' || *dirname == '.')
		{
		pwd (pwdname);
		return (0);
		}
	if (!strcmp (dirname, ".."))
		if (pathlength) pathlength--;
		else return (0);
	else strcpy (dirpath[pathlength++], dirname);
	prname (pwdname, dirpath, pathlength);
	return (0);
	}

newdir ()
	{
	char	*name;
	int	flecmp ();
	int	nonames;
	struct	direct *d;
	struct	stat buf;
	DIR	*ioptr = opendir (".");
	if (ioptr == NULL) return (0);
	nonames = 0;
	while (d = readdir (ioptr))
		{
		name = namedir (d);
		if (!strcmp (name, ".")) continue;
		if (!strcmp (name, "..")) continue;
		if ((!trueval ("printdotfiles")) && *name == '.')
			continue;
		if (stat (name, &buf))
			{
			printf ("Can't stat %s", name);
			getchar ();
			continue;
			}
		strcpy (filent[nonames].f_name, name);
		setmode (filent[nonames].f_protect, &buf);
		filent[nonames].f_size = buf.st_size;
		if (++nonames == MAXENTRIES) break;
		}
	qsort (filent, nonames, sizeof (struct FILENT), flecmp);
	closedir (ioptr);
	return (nonames);
	}

#define UNSET '-'
#define UPPER 'A'-'a'
setmode (s, statbuf) char *s; struct stat *statbuf;
	{
	int	i;
	short	mode = statbuf->st_mode;
	for (i = 1; i < 10; i++) s[i] = UNSET;
	s[10] = NULL;
	switch (mode & S_IFMT)
		{
		case S_IFREG: s[0] = '-'; break;
		case S_IFDIR: s[0] = 'd'; break;
		case S_IFCHR: s[0] = 'c'; break;
#ifdef S_IFBLK
		case S_IFBLK: s[0] = 'b'; break;
#endif
#ifdef S_IFMPC
		case S_IFMPC: s[0] = 'C'; break;
#endif
#ifdef S_IFMPB
		case S_IFMPB: s[0] = 'B'; break;
#endif
		default: s[0] = '?';
		}
	for (i = 0; i < 9; i+=3)
		{
		if (mode & (S_IREAD  >> i)) s[i + 1] = 'r';
		if (mode & (S_IWRITE >> i)) s[i + 2] = 'w';
		if (mode & (S_IEXEC  >> i)) s[i + 3] = 'x';
		}
	if (uid == statbuf->st_uid)
		{
		for (i = 1; i <= 3; i++)
			if (s[i] != UNSET) s[i] += UPPER;
		}
	else if (gid == statbuf->st_gid)
		{
		for (i = 4; i <= 6; i++)
			if (s[i] != UNSET) s[i] += UPPER;
		}
	else for (i = 7; i <= 9; i++)
		if (s[i] != UNSET) s[i] += UPPER;
	}

flecmp (f1, f2) struct FILENT *f1, *f2;
	{
	int	strcmp ();
	if (f1->f_protect[0] == 'd' && f2->f_protect[0] != 'd') return (-1);
	if (f2->f_protect[0] == 'd' && f1->f_protect[0] != 'd') return (1);
	return (strcmp (f1->f_name, f2->f_name));
	}

vdir (page, nonames)
	{
	int	i;
	int	reali;
	char	pagecount[10];
	int	npages = nonames/PAGESIZE + (nonames%PAGESIZE?1:0);
	if (page < 1) page = npages;
	else if (page > npages) page = 1;
	wclear (filewin);
	for (i = 0; i < PAGESIZE; i++)
		{
		if ((reali = i + (page-1)*PAGESIZE) == nonames) break;
		mvwprintw (filewin,1+i, 0, "%c", '1'+i);
		if (filent[reali].f_protect[0] == 'd') /* directory */
			{
			if (trueval ("highlight")) wstandout (filewin);
			mvwprintw (filewin,1+i, INDENT, "%s/",
				filent[reali].f_name);
			if (trueval ("highlight")) wstandend (filewin);
			}
		else	mvwprintw (filewin,1+i, INDENT, "%s",
				filent[reali].f_name);
		mvwprintw (filewin, 1+i, 20, "%9d %10s",
			filent[reali].f_size, filent[reali].f_protect);
		}
	if (trueval ("highlight")) wstandout (filewin);
	mvwprintw (filewin,0,0, "%s", pwdname);
	if (trueval ("highlight")) wstandend (filewin);
	sprintf (pagecount, "%d/%d", page, npages);
	mvwprintw (filewin,0,COLS/2-5, "%5s", pagecount);
	wrefresh (filewin);
	return (page);
	}

fileprocess (c) char c;
    {
    char	*getargs (), *getval ();
    char	*strptr;
    int	i = c - '1' + (page-1)*PAGESIZE;
    if (i >= nonames)
	{
	putchar (7);
	return;
	}
    mvwprintw (filewin, 1+c-'1', 2, "<-");
    wrefresh (filewin);
    if (filent[i].f_protect[0] == 'd' && access (filent[i].f_name, 1) == 0)
	{
	cd (filent[i].f_name);
	nonames = newdir ();
	page = vdir (page=1, nonames);
	}
    else if (access (filent[i].f_name, 1) == 0)
	{
	sprintf (command, "%s ", filent[i].f_name);
	if ((strptr = getargs ("{arguments?}", NULL)) == NULL) return;
	strcat (command, strptr);
	clear (); refresh ();
	syscall (command);
	GETRETURN
	clear (); refresh ();
	flipped = 0;
	display (menu);
	}
    else if (access (filent[i].f_name, 4) == 0)
	{
	sprintf (command, "$editor %s", filent[i].f_name);
	move (LINES-1, 0); clrtoeol (); refresh ();
	syscall (command);
	clear (); refresh ();
	flipped = 0;
	display (menu);
	}
	else putchar (7);
    }
SHAR_EOF
if test 7008 -ne "`wc -c 'file.c'`"
then
	echo shar: error transmitting "'file.c'" '(should have been 7008 characters)'
fi
echo shar: extracting "'internalrun.c'" '(5036 characters)'
if test -f 'internalrun.c'
then
	echo shar: over-writing existing file "'internalrun.c'"
fi
cat << \SHAR_EOF > 'internalrun.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
#define skipspace(ptr) while (isspace (*ptr)) ptr++;
internalrun (chosenmenu, chosen) struct MENU *chosenmenu;
    {
    char	syscommand[BUFSIZ];
    char	buf[BUFSIZ], *bufptr = buf;
    char	*strptr;
    char	comm = chosenmenu->program[chosen][1];
    int	i;
    if (docmode && comm != 'd')
	{
	docmode = 0;
	docinternal (comm);
	flipped = 1;
	return;
	}
    switch (comm)
	{
	case 'f':
		if (flipped) leftdisplay (menu);
		else leftdisplay (stdmenu);
		flipped = !flipped;
		return;
	case 'p':
		popchar = chosenmenu->selector[chosen];
		flipped = 0;
		menu = menu->parent;
		if (ttyspeed > B9600)
			leftdisplay (menu);
		else newmenu = 1;
		return;
	case 'x':
		finish (0);
	case 'a':
		if (anchored)
			{
			menu = savemenu;
			newmenu = 1;
			if (ttyspeed > B9600)
			    leftdisplay (menu);
			move (NOTICES-2, RIGHTMENU); clrtoeol (); refresh ();
			}
		else	{
			savemenu = menu;
			mvprintw (NOTICES-2, RIGHTMENU, "On a diversion from ");
			if (trueval ("highlight")) standout ();
			printw ("[%s]", savemenu->menuname);
			if (trueval ("highlight")) standend ();
			refresh ();
			menu = rootmenu;
			if (ttyspeed > B9600)
			    leftdisplay (menu);
			else newmenu = 1;
			}
		anchored = !anchored;
		flipped = 0;
		return;
	case 'u':
		unixchar = chosenmenu->selector[chosen];
		if (anchored)
		    {
		    move (NOTICES-2, RIGHTMENU);
		    clrtoeol ();
		    refresh ();
		    }
		anchored = flipped = 0;
		menu = rootmenu;
		if (ttyspeed > B9600)
		    leftdisplay (menu);
		else newmenu = 1;
		return;
	case 'c':
		mvprintw (INFOLINE, 0, chosenmenu->display[chosen]);
		clrtoeol ();
		if (cd (getargs (chosenmenu->arguments[chosen], NULL)))
			{
			mvprintw (INFOLINE,0, "Can't change directory");
			clrtoeol ();
			refresh ();
			}
		else page = vdir (page=1, nonames = newdir ());
		return;
	case '0':
		dotdotchar = chosenmenu->selector[chosen];
		cd ("..");
		page = vdir (page=1, nonames=newdir ());
		return;
	case '+':
		page = vdir (++page, nonames);
		return;
	case '-':
		page = vdir (--page, nonames);
		return;
	case 'r': display (menu); flipped = 0; return;
	case 'd':
		if (docmode = !docmode)
		  mvprintw (NOTICES-3, RIGHTMENU, "Next selection gets documentation");
		else
		  mvprintw (NOTICES-3, RIGHTMENU, "Next selection runs program");
		clrtoeol ();
		refresh ();
		return;
	case 's': 
		shellchar = chosenmenu->selector[chosen];
		mvprintw (INFOLINE, 0, chosenmenu->display[chosen]);
		clrtoeol ();
		strptr = getargs (chosenmenu->arguments[chosen], NULL);
		if (strptr == NULL) return;
		while (isspace (*strptr)) strptr++;
		if (*strptr != NULL)
		    strcpy (variables[COMMAND].value, alias (strptr, "|;"));
		syscall (variables[COMMAND].value);
		GETRETURN
		display (menu);
		return;
	case 'v':
		varchar = chosenmenu->selector[chosen];
		mvprintw (INFOLINE, 0, "Setting variable");
		clrtoeol ();
		refresh ();

		if ((strptr = getargs ("{name}", NULL)) == NULL)
			return;
		else strptr = copy (strptr);
		skipspace (strptr);
		for (i = 0; i < nvar; i++)
			if (!strcmp (strptr, variables[i].name)) break;
		if (i == nvar)
		    {
		    if (nvar+1 > MAXVAR)
			    {
			    mvprintw (INFOLINE, 0,"No room for more variables");
			    clrtoeol ();
			    refresh ();
			    return;
			    }
		    mvprintw (INFOLINE, 0, "Setting new variable");
		    variables[i].name = copy (strptr);
		    }
		else
			mvprintw (INFOLINE, 0, "Changing old variable");
		clrtoeol ();
		refresh ();
		if ((strptr = getargs ("{value}", variables[i].value)) == NULL)
			return;
		else strptr = copy (strptr);
		skipspace (strptr);
		variables[i].value = strptr;
		mvprintw (INFOLINE, 0, "%c%s=%s",
			varchar, variables[i].name, variables[i].value);
		clrtoeol ();
		refresh ();
		lastcomm ();
		if (i == nvar) nvar++;
		return;
	case 'i':
		mvprintw (INFOLINE, 0, chosenmenu->display[chosen]);
		clrtoeol ();
		strptr = getargs (chosenmenu->arguments[chosen], NULL);
		if (*strptr)
		    {
		    mvprintw (INFOLINE, 0, interpolate (strptr));
		    clrtoeol ();
		    refresh ();
		    }
		else
		    {
		    FILE *popen(), *ioptr;
		    if (ioptr = popen ("/usr/ucb/more", "w"))
			{
			clear (); refresh ();
			nocrmode (); echo ();
			for (i = 0; i < nvar; i++)
			    fprintf (ioptr, "%10s=%s\n",
				variables[i].name, variables[i].value);
			pclose (ioptr);
			GETRETURN
			clear (); refresh ();
			crmode (); noecho ();
			display (menu);
			}
		    }
		return;
	default:
		mvprintw (INFOLINE, 0, "Unknown internal command\n");
		clrtoeol ();
		refresh ();
		return;
	}
    }

docinternal (command) char command;
	{
	FILE	*fopen (), *ioptr;
	char	*getval (), *menu = getval ("menu");
	char	docfile[BUFSIZ];
	char	line[BUFSIZ];
	sprintf (docfile, "%s/../doc/internal", menu);
	move (HISTORY, 0); clrtobot (); move (HISTORY, 0); refresh ();
	if (ioptr = fopen (docfile, "r"))
		{
		while (fgets (line, BUFSIZ, ioptr))
			if (*line == command)
				fputs (line+1, stdout);
		fclose (ioptr);
		}
	GETRETURN
	display (stdmenu);
	}
SHAR_EOF
if test 5036 -ne "`wc -c 'internalrun.c'`"
then
	echo shar: error transmitting "'internalrun.c'" '(should have been 5036 characters)'
fi
echo shar: extracting "'input.c'" '(2232 characters)'
if test -f 'input.c'
then
	echo shar: over-writing existing file "'input.c'"
fi
cat << \SHAR_EOF > 'input.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"

char *
getval (name) char *name;
	{
	int	i = 0;
	for (i = 0; i < nvar; i++)
		if (!strcmp (variables[i].name, name)) break;
	if (i == nvar) return (NULL);
	return (variables[i].value);
	}

trueval (name)
	{
	char	*v = getval (name);
	if (v == NULL) return (0);
	if (*v == NULL) return (1);
	if (strlen (v) == 1)
		if (*v == 't' || *v == 'y' || *v == '1') return (1);
		else return (0);
	else if (!strcmp (v, "true") || !strcmp (v, "yes")) return (1);
	return (0);
	}

char *
interpolate (s) char *s;
	{
	static	char	interbuf[BUFSIZ];
	char	*getval ();
	char	*sptr = s;
	char	*bufptr = interbuf;
	char	namebuf[BUFSIZ], *nameptr = namebuf;
	int	i;
	*bufptr = NULL;
	while (*sptr)
		{
		if (*sptr == varchar)
			{
			nameptr = namebuf;
			sptr++;
			while (isalnum (*sptr)) *nameptr++ = *sptr++;
			*nameptr = NULL;
			strcpy (bufptr, getval (namebuf));
			while (*bufptr) bufptr++;
			}
		else if	(*sptr == escapechar)
			{
			sptr++;
			*bufptr++ = *sptr++;
			}
		else	*bufptr++ = *sptr++;
		}
	*bufptr = NULL;
	return (interbuf);
	}

#define	begingeneric(c) (c == '{')
#define	endgeneric(c)   (c == '}' || end(c))
char *
getargs (args, initial) char *args, *initial;
	{
	static	char	arglist[BUFSIZ];
	char	genericbuf[100];
	char	*generic;
	char	*arglistptr = arglist;
	*arglistptr = NULL;
	if (args == NULL) return (arglist);
	for(;;)
		{
		while (!begingeneric (*args))
			if (*args == NULL)
				{
				*arglistptr = NULL;
				return (arglist);
				}
			else *arglistptr++ = *args++;
		*arglistptr = NULL;
		generic = genericbuf;
		while (!endgeneric (*args))
			*generic++ = *args++;
		*generic++ = *args++;
		*generic = NULL;
		if (trueval ("highlight")) standout ();
		mvprintw (RESPLINE, 0, genericbuf);
		if (trueval ("highlight")) standend ();
		printw (": ");
		clrtoeol (); refresh ();
		if (initial) strcpy (response, initial);
		else *response = NULL;
		if (getresponse (response) == NULL) return (NULL);
		move (LINES-1, 0); clrtoeol (); refresh ();
		strcat (arglist, response);
		while (*arglistptr) arglistptr++;
		}
	}

char *
getresponse (s) char *s;
	{
	char	*linedit ();
	int	x, y;
	getyx (stdscr, y, x);
	return (linedit (s, y, x));
	}
SHAR_EOF
if test 2232 -ne "`wc -c 'input.c'`"
then
	echo shar: error transmitting "'input.c'" '(should have been 2232 characters)'
fi
echo shar: extracting "'menu.c'" '(2718 characters)'
if test -f 'menu.c'
then
	echo shar: over-writing existing file "'menu.c'"
fi
cat << \SHAR_EOF > 'menu.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.defs"
main (argc, argv) char **argv;
	{
	initial (argc, argv);
	process ();
	}

#include <signal.h>
char	*getenv ();
initial (argc, argv) char **argv;
	{
	int	i;
	struct	sgttyb ttystat;
	extern	finish (), howquit ();
	char	*term	=getenv ("TERM");
	WINDOW	*subwin ();
	if (!movecursor (term))
		{
		printf ("This terminal (%s) can't run menus\n");
		exit (1);
		}
	initscr ();
	signal (SIGINT, howquit);
	uid = getuid ();
	gid = getgid ();
	gtty (fileno (stdout), &ttystat);
	ttyspeed = ttystat.sg_ospeed;
	pwd (pwdname);
	nonames = newdir ();
	if (argc > 1) strcpy (menudir, argv[1]);
	readvar ();
	rootmenu = menu->parent = menu = readmenu ("UNIX", "UNIX");
	stdmenu = readmenu ("CONTROL", "CONTROL");
	lmenu = subwin (stdscr, MAXOPTION+1, RIGHTMENU-1, 0, 0);
	filewin = subwin (stdscr, PAGESIZE+1, COLS/2, 0, COLS/2);
	history = subwin (stdscr, INFOLINE-HISTORY-1, 0, HISTORY, 0);
	timewin = subwin (stdscr, 1, 0, NOTICES, RIGHTMENU);
	display (menu);
	crmode (); noecho ();
	}

process ()
	{
	int	c;
	int	chosen;
	for (;;)
		{
		if ((c = timegetc (1)) == 0)
			{
			if (newmenu) leftdisplay (menu);
			printtime ();
			}
		else if (isdigit (c) && c != '0')
			(fileprocess (c));
		else if ((chosen = choose (c, stdmenu)) != OUT_OF_RANGE)
			run (stdmenu, chosen);
		else if ((chosen = choose (c, menu)) == OUT_OF_RANGE)
			{
			mvprintw (INFOLINE, 0, "BREAK to quit.  Type & for [CONTROL] commands");
			clrtoeol ();
			refresh ();
			putchar (7);
			}
		else if (menu->nextmenu[chosen])
			{
			menu = menu->nextmenu[chosen];
			if (ttyspeed > B9600)
				leftdisplay (menu);
			else newmenu = 1;
			flipped = 0;
			}
		else run (menu, chosen);
		}
	}

finish ()
	{
	signal (SIGINT, SIG_IGN);
	alarm (0);
	clear ();
	refresh ();
	endwin ();
	exit (0);
	}

howquit ()
	{
	extern	finish (), howquit ();
	alarm (0);
	signal (SIGINT, finish);
	if (trueval ("highlight")) standout ();
	mvprintw (INFOLINE, 0, "Type RETURN to return to menu, BREAK to exit");
	signal (SIGINT, finish);
	if (trueval ("highlight")) standend ();
	clrtoeol (); refresh ();
	crmode ();
	while (getchar () != '\n') putchar (7);
	signal (SIGINT, howquit);
	move (INFOLINE, 0); clrtoeol (); refresh ();
	display (menu);
	process ();
	}

choose (ch, thismenu) struct MENU *thismenu;
	{
	int	i;
	int	chosen = OUT_OF_RANGE;
	for (i = 0; i < thismenu->noptions; i++)
		if (ch == thismenu->selector[i]) chosen = i;
	if (chosen == OUT_OF_RANGE) return (chosen);
	if (thismenu == stdmenu) return (chosen);
	for (i = 0; i < thismenu->noptions; i++)
		mvwprintw (lmenu, i + 1, 2, "  ");
	if (!newmenu) mvwprintw (lmenu, chosen + 1, 2, "<-");
	wrefresh (lmenu);
	return (chosen);
	}

SHAR_EOF
if test 2718 -ne "`wc -c 'menu.c'`"
then
	echo shar: error transmitting "'menu.c'" '(should have been 2718 characters)'
fi
echo shar: extracting "'CW'" '(211 characters)'
if test -f 'CW'
then
	echo shar: over-writing existing file "'CW'"
fi
cat << \SHAR_EOF > 'CW'
/* Copyright (c) 1981 Gary Perlman  All rights reserved */
/* Permission to copy this software is granted provided */
/* this notice accompanies all distributions and it is  */
/* not used for material gain. */
SHAR_EOF
if test 211 -ne "`wc -c 'CW'`"
then
	echo shar: error transmitting "'CW'" '(should have been 211 characters)'
fi
echo shar: extracting "'movecursor.c'" '(242 characters)'
if test -f 'movecursor.c'
then
	echo shar: over-writing existing file "'movecursor.c'"
fi
cat << \SHAR_EOF > 'movecursor.c'
movecursor (term) char *term;
	{
	char	bp[1024];
	char	*ptr = bp;
	if (tgetent (bp, term) != 1) return (0);
	while (*ptr)
		{
		while (*ptr && *ptr != ':') ptr++;
		if (ptr[1] == 'c' && ptr[2] == 'm') return (1);
		ptr++;
		}
	return (0);
	}
SHAR_EOF
if test 242 -ne "`wc -c 'movecursor.c'`"
then
	echo shar: error transmitting "'movecursor.c'" '(should have been 242 characters)'
fi
echo shar: extracting "'image.c'" '(592 characters)'
if test -f 'image.c'
then
	echo shar: over-writing existing file "'image.c'"
fi
cat << \SHAR_EOF > 'image.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
/* this function is used to create a screen image in a file */
/* I used it to make diagrams but it is not really useful */
#include <curses.h>
#include <ctype.h>
image ()
	{
	int i, j;
	char c;
	FILE *ioptr;
	char file[100];
	sprintf (file, "image.%d", getpid ());
	ioptr = fopen (file, "w");
	for (i = 0; i < 24; i++)
		{
		for (j = 0; j < 80; j++)
			{
			c = stdscr->_y[i][j];
			if (isascii (c))
			    fputc (stdscr->_y[i][j], ioptr);
			else fputc (' ', ioptr);
			}
		fputc ('\n', ioptr);
		}
	fclose (ioptr);
	putchar (7);
	}
SHAR_EOF
if test 592 -ne "`wc -c 'image.c'`"
then
	echo shar: error transmitting "'image.c'" '(should have been 592 characters)'
fi
echo shar: extracting "'Makefile'" '(474 characters)'
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
#Copyright (c) 1981 Gary Perlman  All rights reserved
#
# Be sure to change MENUDIR (where all menus are kept)
#
MENUDIR="/b/faculty/perlman/menunix/menus"
#
OBJS = menu.o init.o internalrun.o file.o display.o run.o\
	input.o linedit.o utility.o alias.o movecursor.o
LIBES = -lcurses -ltermlib
DESTDIR = .
menu: $(OBJS)
	cc -o $(DESTDIR)/menunix $(OBJS) $(LIBES)
$(OBJS): menu.h
menu.o: menu.defs
	@echo Menus should be in $(MENUDIR)
	cc -D'MENUDIR=$(MENUDIR)' -O -c menu.c
SHAR_EOF
if test 474 -ne "`wc -c 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 474 characters)'
fi
echo shar: extracting "'linedit.c'" '(6649 characters)'
if test -f 'linedit.c'
then
	echo shar: over-writing existing file "'linedit.c'"
fi
cat << \SHAR_EOF > 'linedit.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include "menu.h"
WINDOW	*subwin ();
WINDOW	*feedback;
int	neveredited = 1;
char *
linedit (s, y, x) char *s;
    {
    char	*cursormode ();
    if (neveredited)
	{
	if ((feedback = subwin (stdscr, 1, 0, LINES-1, 0)) == NULL)
	    return (NULL);
	neveredited = 0;
	}
    return (cursormode (s, y, x, feedback));
    }

char *
cursormode (s, y, base_x, feedback) char *s; WINDOW *feedback;
	{
	extern	char	varchar;
	char	command = 0;
	char	saved_s[BUFSIZ];
	char	saved[2][BUFSIZ];
	int	x = 0;
	int	answer;
	int	max_x = strlen (s) - 1;
	int	other = 0;
	strcpy (saved_s, s);
	strcpy (saved[0], s);
	strcpy (saved[1], s);
	if (*s == NULL) command = 'I'; /* auto insert */
	else
	    {
	    mvwprintw (feedback, 0, 0,
		"Cursor mode: quit with 'q', insert with 'i', undo with 'u'");
	    wclrtoeol (feedback); wrefresh (feedback);
	    }
	move (y, base_x);
	ctrlprintw (s);
	clrtoeol ();
	move (y, x+base_x);
	refresh ();
	do	{
		strcpy (saved[other], s);
		switch (command)
			{
			case 0: break;
			case ' ': /* forward one character */
			case 'l':
			case 12:
			case '+':
				if (++x > max_x) putchar (7);
				break;
			case '-': /* backward one character */
			case 'h':
			case 8: /* backspace ughh */
				 if (--x < 0) putchar (7);
				break;
			case '^':
			case 'H': /* all the way to left */
				x = 0;
				break;
			case '$':
			case 'L': /* all the way to right */
				x = max_x;
				break;
			case 'W': /* forward one word */
			case 'w':
				if (x == max_x)
					{
					putchar (7);
					break;
					}
				while (isspace (s[x])) x++;
				while (x < max_x && !isspace (s[x])) x++;
				while (isspace (s[x])) x++;
				break;
			case 'B': /* backward one word */
			case 'b':
				if (x == 0)
					{
					putchar (7);
					break;
					}
				while (x && !isspace (s[x])) x--;
				while (x && isspace (s[x])) x--;
				while (x && !isspace (s[x])) x--;
				if (isspace (s[x])) x++;
				break;
			case 'C': /*change to end of line */
				clrtoeol (); refresh ();
				s[x] = NULL;
				max_x = --x;
				if (max_x < 0) max_x = 0;
			case 'A': /* append after end */
				x = max_x;
			case 'a': /* append after cursor */
				other = !other;
				if (*s == NULL) x--;
				if ((answer = insert (s, y, base_x, feedback, x+1)) == RUN)
					return (s);
				x = answer - 1;
				max_x = strlen (s) - 1;
				break;
			case 'r': /* replace char */
				if (*s == NULL) putchar (7);
				else	{
					other = !other;
					s[x] = getchar ();
					}
				break;
			case 'D':
			case '0':
				other = !other;
				s[x] = NULL;
				max_x = --x;
				break;
			case 'x': /* delete character */
				other = !other;
				strcpy (s+x, s+x+1);
				max_x--;
				break;
			case 'X': /* delete line  and auto insert */
				*s = NULL;
				move (y, base_x);
				clrtoeol ();
				refresh ();
			case 'I': /* insert before start */
				x = 0;
			case 'i': /* insert before  cursor */
				other = !other;
				if ((answer = insert (s, y, base_x, feedback, x)) == RUN)
					return (s);
				x = answer;
				max_x = strlen (s) - 1;
				break;
			case 'U': /* undo all stuff on line */
				other = !other;
				strcpy (s, saved_s);
				max_x = strlen (s) - 1;
				x = 0;
				break;
			case 'u': /* undo last change */
				other = !other;
				strcpy (s, saved[other]);
				max_x = strlen (s) - 1;
				x = 0;
				break;
			case 'Q':
				wclear (feedback);
				wrefresh (feedback);
				mvprintw (y, base_x, "Line-edit escaped");
				clrtoeol ();
				refresh ();
				return (NULL);
			default: putchar (7);
			}
		if (max_x < 0) x = max_x = 0;
		else if (x > max_x) x = max_x;
		else if (x < 0) x = 0;
		move (y, base_x);
		ctrlprintw (s);
		clrtoeol ();
		move (y, x+base_x);
		refresh ();
		} while ((command = getchar ()) != 'q' && command != '\n');
	return (s);
	}

insert (s, y, base_x, feedback, x) char *s; WINDOW *feedback;
	{
	int	i;
	char	before_cursor[BUFSIZ], after_cursor[BUFSIZ];
	char	insert_cursor[BUFSIZ];
	char	*ptr = insert_cursor;
	int	max_x = strlen (s) - 1;
	before_cursor[0] = insert_cursor[0] = after_cursor[0] = NULL;
	mvwprintw (feedback, 0, 0,
	    "Adding text: quit with ESC, select files with '_'");
	wclrtoeol (feedback); wrefresh (feedback);
	if (*s)
		{
		sprintf (before_cursor, "%.*s", x, s);
		strcpy (after_cursor, s+x);
		}
	else max_x = 0;
	move (y, base_x);
	ctrlprintw (s);
	move (y, x+base_x);
	refresh ();
	while ((*ptr = getchar ()) != ESC && *ptr != '\n')
	    {
	    if (*ptr == modechar)
		{
		mvwprintw (feedback, 0, 0,
		    "Selecting files: quit with '_', select files by number");
		wclrtoeol (feedback);
		wrefresh (feedback);
		*ptr = NULL;
		while ((i = getfile ()) != MODECHANGE && i != RUN)
			{
			sprintf (ptr, "%s ", filent[i].f_name);
			i = strlen (filent[i].f_name) + 1;
			x += i;
			ptr += i;
			move (y, base_x);
			ctrlprintw (before_cursor);
			ctrlprintw (insert_cursor);
			ctrlprintw (after_cursor);
			clrtoeol ();
			move (y, x+base_x);
			refresh ();
			}
		mvwprintw (feedback, 0, 0, "Adding text: quit with ESC");
		wclrtoeol (feedback);
		wrefresh (feedback);
		}
	    else if (*ptr == 8) /* backspace */
		    {
		    if (ptr > insert_cursor)
			    {
			    *ptr = NULL;
			    ptr--;
			    *ptr = NULL;
			    x--;
			    }
		    else
			    {
			    putchar (7);
			    ptr = insert_cursor;
			    *ptr = NULL;
			    }
		    }
	    else if (*ptr == ESCAPE)
		    {
		    *ptr++ = getchar ();
		    *ptr = NULL;
		    x++;
		    }
	    else	{
		    ptr++;
		    *ptr = NULL;
		    x++;
		    }
	    move (y, base_x);
	    ctrlprintw (before_cursor);
	    ctrlprintw (insert_cursor);
	    ctrlprintw (after_cursor);
	    clrtoeol ();
	    move (y, x+base_x);
	    refresh ();
	    if (i == RUN) break;
	    }
	if (*ptr == '\n') i = RUN;
	*ptr = NULL;
	sprintf (s, "%s%s%s", before_cursor, insert_cursor, after_cursor);
	strcpy (s, interpolate (s));
	mvwprintw (feedback, 0, 0,"Cursor mode: quit with 'q', abort with 'Q'");
	wclrtoeol (feedback); wrefresh (feedback);
	if (i == RUN) return (RUN);
	return (x);
	}

getfile ()
	{
	char	c;
	int	i;
	for (;;)
		{
		c = getchar ();
		if (c == '+')
			page = vdir (++page, nonames);
		else if (c == '-')
			page = vdir (--page, nonames);
		else if (isdigit (c) && c != '0')
			if ((i = c - '1' + (page-1)*PAGESIZE) >= nonames)
				putchar (7);
			else	{
				mvwprintw (filewin, 1+c-'1', 2, "<-");
				wrefresh (filewin);
				return (i);
				}
		else if (c == RETURN) return (RUN);
		else if (c == modechar) return (MODECHANGE);
		else putchar (7);
		}
	}

ctrlprintw (s) char *s;
	{
	while (*s)
		{
		if (iscntrl (*s))
			{
			standout ();
			addch (*s-1+'A');
			standend ();
			}
		else addch (*s);
		s++;
		}
	}
SHAR_EOF
if test 6649 -ne "`wc -c 'linedit.c'`"
then
	echo shar: error transmitting "'linedit.c'" '(should have been 6649 characters)'
fi
echo shar: extracting "'alias.c'" '(889 characters)'
if test -f 'alias.c'
then
	echo shar: over-writing existing file "'alias.c'"
fi
cat << \SHAR_EOF > 'alias.c'
/*Copyright (c) 1981 Gary Perlman  All rights reserved*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
char *
alias (s, delim) char *s, *delim;
	{
	static	char	aliased[BUFSIZ];
	char	*alias = aliased;
	char	name[BUFSIZ], *nameptr = name;
	char	*getval (), *val;
	struct	stat status;
    checkalias:
	*alias = NULL;
	while (isspace (*s)) *alias++ = *s++;
	nameptr = name;
	*nameptr = NULL;
	while (isalnum (*s) || *s == '_')
		*nameptr++ = *s++;
	*nameptr = NULL;
	if (val = getval (name)) /* has a value */
	    if ((stat (val, &status) == 0) /* can get status */
		&& ((status.st_mode & S_IFMT) == S_IFDIR)) /* directory file */
		    strcpy (alias, name);
	    else strcpy (alias, val);
	else
	    strcpy (alias, name);
	while (*alias) alias++;
	while (*s)
		if (index (delim, *alias++ = *s++)) goto checkalias;
	*alias = NULL;
	return (aliased);
	}
SHAR_EOF
if test 889 -ne "`wc -c 'alias.c'`"
then
	echo shar: error transmitting "'alias.c'" '(should have been 889 characters)'
fi
echo shar: done with directory "'src'"
chdir ..
#	End of shell archive
exit 0



More information about the Comp.sources.unix mailing list