[comp.sources.misc] v20i002: scan - A directory menu program, Part02/03

pat@kai.com (Patrick J. Wolfe) (05/21/91)

Submitted-by: Patrick J. Wolfe <pat@kai.com>
Posting-number: Volume 20, Issue 2
Archive-name: scan/part02

#! /bin/sh
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  filemenu.c keymenu.c optionmenu.c readrc.c userfuncs.c
# Wrapped by kent@sparky on Tue May 21 00:34:20 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 2 (of 3)."'
if test -f 'filemenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'filemenu.c'\"
else
  echo shar: Extracting \"'filemenu.c'\" \(9892 characters\)
  sed "s/^X//" >'filemenu.c' <<'END_OF_FILE'
X/*
X *	Original Author:  Patrick Wolfe  (pat@kai.com, kailand!pat)
X *
X * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
X *
X * Permission is hereby granted to copy, distribute or otherwise 
X * use any part of this package as long as you do not try to make 
X * money from it or pretend that you wrote it.  This copyright 
X * notice must be maintained in any copy made.
X *
X * Use of this software constitutes acceptance for use in an AS IS 
X * condition. There are NO warranties with regard to this software.  
X * In no event shall the author be liable for any damages whatsoever 
X * arising out of or in connection with the use or performance of this 
X * software.  Any use of this software is at the user's own risk.
X *
X * If you make modifications to this software that you feel 
X * increases it usefulness for the rest of the community, please 
X * email the changes, enhancements, bug fixes as well as any and 
X * all ideas to me. This software is going to be maintained and 
X * enhanced as deemed necessary by the community.
X *              
X *              Patrick J. Wolfe
X *              uunet!uiucuxc!kailand!pwolfe
X *              pwolfe@kailand.kai.com
X */
X
X
X#include "config.h"
X#define CURSORCOL 56
X
Xextern SIGTYPE die();
Xextern struct key_entry keytab[];
Xextern struct dblock cwd[];
Xextern struct namelist lidlist[], gidlist[];
Xextern int opt_show_filetype, opt_rm_prompt, opt_pager_pause, hidden_ctr;
Xextern char *loginid, *editor, *pager, *shellpgm, *homedir, currdir[], prevdir[];
X
XWINDOW *headwin, *datawin, *helpwin;
Xlong sixmonthsago;
Xint lastptr, topptr, curptr, century = 19;
Xchar errormsg[256];
X
Xchar *monthtable[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
Xstatic char *dowtable[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
Xstatic char *helpline = "  Use arrow keys or j/k to move pointer - press \"?\" for help  ";
Xstatic int msgonscreen = 0;
X
X
X/* ---------------------------------------------------------------------------- */
X/*			menu processing routines				*/
X/* ---------------------------------------------------------------------------- */
X
X
Xint
Xread_cmdline (winptr, row, col, cmdline, maxlen, prompt)
XWINDOW *winptr;
Xint row, col, maxlen;
Xchar *cmdline, *prompt;
X{
Xint c;
Xint cmdlen = 0;
Xint promptlen = col + strlen(prompt);
X
Xwmove (winptr, row, col);
Xwclrtoeol (winptr);
Xwmove (winptr, row, col);
Xwstandout (winptr);
Xwaddstr (winptr, prompt);
Xwstandend (winptr);
Xwmove (winptr, row, promptlen);
Xwrefresh (winptr);
X
Xwhile (1) {
X	c = my_getch (winptr);
X	switch (c) {
X
X	case ControlU:				/* clear the command line */
X		if (cmdlen > 0) {
X			cmdlen = 0;
X			cmdline[cmdlen] = '\0';
X			wmove (winptr, row, promptlen);
X			wclrtoeol (winptr);
X			wmove (winptr, row, promptlen);
X			wrefresh (winptr);
X			}
X		break;
X
X	case ControlJ:
X	case ControlM:
X		return cmdlen;
X
X	case ControlH:
X	case Delete:
X		if (cmdlen > 0) {
X			cmdline[--cmdlen] = '\0';
X			wmove (winptr, row, promptlen + cmdlen);
X			wclrtoeol (winptr);
X			wmove (winptr, row, promptlen + cmdlen);
X			wrefresh (winptr);
X			}
X		break;
X
X	default:				/* type a command on the command entry line */
X		if ((isprint(c)) && (cmdlen < maxlen)) {
X			cmdline[cmdlen++] = c;
X			cmdline[cmdlen] = '\0';
X			wmove (winptr, row, promptlen + cmdlen - 1);
X			waddch (winptr, c);
X			wmove (winptr, row, promptlen + cmdlen);
X			wrefresh (winptr);
X			}
X		else	{
X			beep ();
X			}
X		}
X	}
X}
X
X
Xmsgupdate ()
X{
Xif ((! msgonscreen) && (errormsg[0] == '\0'))
X	return;
Xwmove (headwin, 2, 0);
Xwclrtoeol (headwin);
Xif (errormsg[0] != '\0') {
X	wmove (headwin, 2, 0);
X	wstandout (headwin);
X	waddstr (headwin, errormsg);
X	wstandend (headwin);
X	errormsg[0] = '\0';
X	msgonscreen = 1;
X	}
Xelse	{
X	msgonscreen = 0;
X	}
Xwrefresh (headwin);
X}
X
X
Xmenu_update ()
X{
Xstruct timeval tp;
Xstruct tm *today;
Xint row, ptr;
Xchar subname[256];
X
X/* get today's date */
Xgettimeofday (&tp, 0);
Xtoday = localtime (&tp.tv_sec);
Xsixmonthsago = tp.tv_sec - (60 * 60 * 24 * 180);		/* time 180 days (6 months) ago */
X
X/* update the date and time in the top header line */
Xmvwprintw (headwin, 0, 57, "%3s %3s %2d, %02d%02d  %2d:%02d", dowtable[today->tm_wday],
X	monthtable[today->tm_mon], today->tm_mday, century, today->tm_year, today->tm_hour, today->tm_min);
Xwrefresh (headwin);
Xmsgupdate ();
X
Xwmove (datawin, 0, 0);
Xwclrtobot (datawin);
X
X/* draw the menu lines on the screen */
Xfor (row = 0; (row < PAGESIZE) && ((topptr + row) <= lastptr) ; row++) {
X	ptr = topptr + row;
X
X	if (cwd[ptr].size == -1)
X		statfile (ptr);			/* only stat files if we need to */
X
X	wmove (datawin, row, 0);
X	if (cwd[ptr].selected)
X		wstandout (datawin);
X
X	if (cwd[ptr].size == -1) {
X		/* couldn't stat - display the error message stored in link */
X		mvwprintw (datawin, row, 0, "%-55s     ", cwd[ptr].link);
X		/* display file name */
X		if (strlen (cwd[ptr].name) < (COLS - 55)) {
X			wprintw (datawin, "%s", cwd[ptr].name);
X			}
X		else	{
X			strncpy (subname, cwd[ptr].name, COLS-58);
X			cwd[ptr].name[COLS-58] = '.';
X			cwd[ptr].name[COLS-57] = '.';
X			cwd[ptr].name[COLS-56] = '.';
X			cwd[ptr].name[COLS-55] = '\n';
X			waddstr (datawin, subname);
X			}
X		}
X	else	{
X		/* display perms, owner, group, size and modification time */
X		wprintw (datawin, "%10s  %-8s %-10s %9d  %-12s ", cwd[ptr].perms, lidlist[cwd[ptr].owner].name,
X				gidlist[cwd[ptr].group].name, cwd[ptr].size, cwd[ptr].modtime);
X
X		if (ptr == curptr) {
X			if (cwd[curptr].selected)
X				wstandend (datawin);
X			else
X				wstandout (datawin);
X	/* only highlight the pointer if the current file is NOT selected */
X			waddstr (datawin, "==>");
X			if (cwd[curptr].selected)
X				wstandout (datawin);
X			else
X				wstandend (datawin);
X			waddch (datawin, ' ');
X			}
X		else
X			waddstr (datawin, "    ");
X
X		/* display file name */
X		if (strlen (cwd[ptr].name) < (COLS - 55)) {
X			wprintw (datawin, "%s%s", cwd[ptr].name, cwd[ptr].link);
X			}
X		else	{
X			strncpy (subname, cwd[ptr].name, COLS-58);
X			cwd[ptr].name[COLS-58] = '.';
X			cwd[ptr].name[COLS-57] = '.';
X			cwd[ptr].name[COLS-56] = '.';
X			cwd[ptr].name[COLS-55] = '\n';
X			waddstr (datawin, subname);
X			}
X		}
X
X	if (cwd[ptr].selected)
X		wstandend (datawin);
X	}
X
X
Xwrefresh (datawin);
X}
X
X
Xmenu_move (distance)
Xint distance;
X{
Xint oldcur;
X
Xoldcur = curptr;
Xcurptr += distance;
X
Xif (curptr < 0) {	/* sanity check */
X	curptr = 0;
X	}
Xelse if (curptr > lastptr) {
X	curptr = lastptr;
X	}
X
X/* adjust top of screen, if neccessary */
Xif ((curptr < (topptr - PAGESIZE))
X || (curptr > (topptr + PAGESIZE + PAGESIZE))) {
X	topptr = curptr;	/* if moving further than one page, put the new current on top */
X	}
Xelse if (curptr < topptr) {
X	topptr -= PAGESIZE;	/* moving to previous page */
X	if (topptr < 0) {
X		topptr = 0;
X		}
X	}
Xelse if (curptr > (topptr + PAGESIZE - 1)) {
X	topptr += PAGESIZE;	/* moving to next page */
X	if (topptr > ((lastptr - PAGESIZE) + 1)) {
X		topptr = (lastptr - PAGESIZE) + 1;
X		if (topptr < 0) {
X			topptr = 0;
X			}
X		}
X	}
X/* if we staying on the same page, just move the pointer */
Xelse	{
X	msgupdate ();
X	/* erase the old pointer */
X	wmove (datawin, oldcur - topptr, CURSORCOL);
X	if (cwd[oldcur].selected == 1)
X		wstandout (datawin);
X	waddstr (datawin, "   ");
X	if (cwd[oldcur].selected == 1)
X		wstandend (datawin);
X	/* draw the new pointer */
X	wmove (datawin, curptr - topptr, CURSORCOL);
X	if (cwd[curptr].selected == 0)
X		wstandout (datawin);
X	waddstr (datawin, "==>");
X	if (cwd[curptr].selected == 0)
X		wstandend (datawin);
X	wrefresh (datawin);
X	return;
X	}
X
Xmenu_update ();
X}
X
X
Xmenu_scroll (distance)
Xint distance;
X{
Xtopptr += distance;
Xif (topptr > ((lastptr - PAGESIZE) + 1)) {
X	topptr = (lastptr - PAGESIZE) + 1;
X	}
Xif (topptr < 0) {
X	topptr = 0;
X	}
Xif (curptr < topptr) {
X	curptr = topptr;
X	}
Xelse if (curptr > (topptr + PAGESIZE - 1)) {
X	curptr = topptr;
X	}
Xmenu_update ();
X}
X
X
Xredraw_menu ()
X{
Xint len;
X
Xclear ();
Xrefresh ();
Xwmove (headwin, 0, 0);
Xwclrtobot (headwin);
X
X/* draw the header line */
Xwmove (headwin, 0, 0);
Xmvwprintw (headwin, 0, 0, "%-44s %-8s", PGM_VERSION, loginid);
Xmvwaddstr (headwin, 1, 0, "Directory: ");
Xlen = strlen(currdir);
Xif (len > COLS - 23) {
X	waddstr (headwin, "...");
X	waddstr (headwin, &currdir[(len - COLS) - 27]);
X	}
Xelse	{
X	waddstr (headwin, currdir);
X	}
Xwprintw (headwin, " - %3d files", lastptr + hidden_ctr + 1);
Xmvwprintw (headwin, 3, 0, "%-10s  %-8s %-10s %9s  %12s     %s",
X	"mode", "owner", "group", "size", "modified", "filename");
Xmvwprintw (headwin, 4, 0, "%-10s  %-8s %-10s %9s  %12s     %s",
X	"----", "-----", "-----", "----", "--------", "--------");
X
Xmenu_update ();
X
Xredraw_help ();
X}
X
X
Xredraw_help ()
X{
Xwmove (helpwin, 0, 0);
Xwclrtoeol (helpwin);
Xwmove (helpwin, 0, 0);
Xwstandout (helpwin);
Xwaddstr (helpwin, helpline);
Xwstandend (helpwin);
Xwrefresh (helpwin);
X}
X
X
Xmain_loop ()
X{
Xint c;
X
Xinitscr ();			/* initialize curses */
Xsignal (SIGHUP, die);		/* trap signal 1, hangup */
Xsignal (SIGINT, die);		/* trap signal 2, interrupt */
Xsignal (SIGQUIT, die);		/* trap signal 3, quit */
Xsignal (SIGTERM, die);		/* trap signal 15, software termination */
Xif (LINES < 10) {
X	fprintf (stderr, "\r\nterminal is too small - 10 lines minimum\r\n");
X	die ();
X	}
XPAGESIZE = LINES - 6;		/* size of file menu */
Xnoecho ();			/* curses should not echo keys as they are typed */
Xnonl ();			/* disable cr/lf mapping */
Xcrmode ();			/* turn on cbreak mode */
Xheadwin = newwin (5, COLS, 0, 0);
Xdatawin = newwin (PAGESIZE, COLS, 5, 0);
Xhelpwin = newwin (1, COLS, PAGESIZE + 5, 0);
X#ifdef SYSVcurses
Xidlok (datawin, TRUE);
X#endif
X
Xcurptr = topptr = 0;
X/* start off by reading the current directory */
Xdo_chdir (".");
X
Xwhile (1) {
X	c = my_getch (headwin);
X	if ((keytab[c].type == KEY_FUNC) && (keytab[c].pntr != (voidptr) NULL)) {
X		((Function *) keytab[c].pntr) (c);
X		}
X	else if ((keytab[c].type == KEY_CMD) && (keytab[c].pntr != (voidptr) NULL)) {
X		do_cmd ((char *) keytab[c].pntr, keytab[c].options);
X		}
X	else 	{
X		beep ();
X		}
X	}
X/* NOTREACHED */
X}
END_OF_FILE
  if test 9892 -ne `wc -c <'filemenu.c'`; then
    echo shar: \"'filemenu.c'\" unpacked with wrong size!
  fi
  # end of 'filemenu.c'
fi
if test -f 'keymenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'keymenu.c'\"
else
  echo shar: Extracting \"'keymenu.c'\" \(10562 characters\)
  sed "s/^X//" >'keymenu.c' <<'END_OF_FILE'
X
X/*
X * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
X *
X * Permission is hereby granted to copy, distribute or otherwise 
X * use any part of this package as long as you do not try to make 
X * money from it or pretend that you wrote it.  This copyright 
X * notice must be maintained in any copy made.
X *
X * Use of this software constitutes acceptance for use in an AS IS 
X * condition. There are NO warranties with regard to this software.  
X * In no event shall the author be liable for any damages whatsoever 
X * arising out of or in connection with the use or performance of this 
X * software.  Any use of this software is at the user's own risk.
X *
X * If you make modifications to this software that you feel 
X * increases it usefulness for the rest of the community, please 
X * email the changes, enhancements, bug fixes as well as any and 
X * all ideas to me. This software is going to be maintained and 
X * enhanced as deemed necessary by the community.
X *              
X *              Patrick J. Wolfe
X *              uunet!uiucuxc!kailand!pwolfe
X *              pwolfe@kailand.kai.com
X */
X
X#include "config.h"
Xextern struct funcname_entry funcname_table[];
Xextern struct keydef_entry keydef_table[];
Xextern struct key_entry keytab[];
Xextern int read_cmdline ();
X
Xstatic void redraw_data ();
X
Xint keydef_changed;		/* flag to indicate some options were changed */
Xstatic WINDOW *header_window, *data_window, *help_window;
Xstatic int top = 0;		/* index of top option on screen (retained between invokations) */
Xstatic int current = 0;		/* index of current option (retained between invokations) */
Xstatic int last = SIZEKEYTAB - 1;		/* index of last option in option_table (calculated when first run) */
X
Xstatic void
Xdefine_a_key (c1)
Xchar c1;
X{
Xvoidptr func;
Xint key, c, k, len, options;
Xchar *ptr2, command[256];
X
Xwmove (help_window, 0, 0);
Xwclrtobot (help_window);
Xwrefresh (help_window);
X
Xwmove (header_window, 2, 0);
Xwclrtobot (header_window);
Xwrefresh (header_window);
X
Xwmove (data_window, 0, 0);
Xwclrtobot (data_window);
Xmvwprintw (data_window, 3, 0, "Press the key you would like to %sefine,", (c1 == 'U' ? "Und" : "D"));
Xmvwaddstr (data_window, 4, 0, "or press \"q\" to not change anything");
Xwrefresh (data_window);
X
Xkey = my_getch (data_window);
Xif ((key == 'q') || (key == 'Q')) {
X	redraw_all ();
X	return;
X	}
X
Xif (c1 == 'U') {	/* undefine key and get out now */
X	keytab[key].type = KEY_UNDEF;
X	redraw_all ();
X	return;
X	}
X
Xwmove (header_window, 3, 0);
Xwclrtoeol (header_window);
Xmvwaddstr (header_window, 3, 0, "Defining key ");
X
Xif ((key >= '!') && (key <= '~')) {
X	waddch (header_window, '"');
X	waddch (header_window, key);
X	waddch (header_window, '"');
X	}
Xelse	{
X	for (k = 0; (keydef_table[k].name != NULL) && (keydef_table[k].value != key); k++);
X	if (keydef_table[k].name != NULL) {
X		waddstr (header_window, keydef_table[k].name);
X		}
X	}
Xwprintw (header_window, " (octal value %03o)", key);
Xwrefresh (header_window);
X
Xwmove (data_window, 3, 0);
Xwclrtoeol (data_window);
X
Xmvwaddstr (data_window, 3, 0, "Press C to make this key enter a command,");
Xmvwaddstr (data_window, 4, 0, "      F to make this key execute a builtin function");
Xmvwaddstr (data_window, 5, 0, "      Q to quit without defining a key");
Xwrefresh (data_window);
X
Xfor (c = my_getch (data_window); (c != 'c') && (c != 'C') && (c != 'f') && (c != 'F') && (c != 'q') && (c != 'Q'); c = my_getch (data_window));
X
Xwmove (data_window, 0, 0);
Xwclrtobot (data_window);
Xwrefresh (data_window);
Xwmove (header_window, 0, 0);
Xwclrtobot (header_window);
Xwrefresh (header_window);
X
Xif ((c == 'q') || (c == 'Q')) {		/* quit - do not define a key */
X	redraw_all ();
X	return;
X	}
X
Xif ((c == 'f') || (c == 'F')) {		/* defining a key to execute a builtin function */
X	func = (voidptr) function_menu ();
X	if (func != (voidptr) NULL) {
X		keytab[key].type = KEY_FUNC;
X		keytab[key].pntr = func;
X		keydef_changed = 1;
X		}
X	redraw_all ();
X	return;
X	}
X
Xwmove (data_window, 3, 0);		/* defining a key to execute a command */
Xwclrtobot (data_window);
Xoptions = 0;
X
Xmvwaddstr (data_window, 3, 0, "Pause and ask before running the command? (Y/N) ");
Xwrefresh (data_window);
Xfor (c = my_getch (data_window); (c != 'y') && (c != 'Y') && (c != 'n') && (c != 'N'); c = my_getch (data_window));
Xif ((c == 'y') || (c == 'Y')) {
X	waddch (data_window, 'Y');
X	options |= OPT_VERIFY;
X	}
Xelse
X	waddch (data_window, 'N');
X
Xmvwaddstr (data_window, 4, 0, "Pause after the command finishes? (Y/N) ");
Xwrefresh (data_window);
Xfor (c = my_getch (data_window); (c != 'y') && (c != 'Y') && (c != 'n') && (c != 'N'); c = my_getch (data_window));
Xif ((c == 'y') || (c == 'Y')) {
X	waddch (data_window, 'Y');
X	options |= OPT_WAIT;
X	}
Xelse
X	waddch (data_window, 'N');
X
Xmvwaddstr (data_window, 5, 0, "Append the names of the current file, all tagged files or no files to the command? (C/T/N)");
Xwrefresh (data_window);
Xfor (c = my_getch (data_window);
X	(c != 'c') && (c != 'C') && (c != 't') && (c != 'T') && (c != 'n') && (c != 'N');
X	c = my_getch (data_window));
Xif ((c == 'c') || (c == 'C')) {
X	waddch (data_window, 'C');
X	options |= OPT_TAGCUR;
X	}
Xelse if ((c == 't') || (c == 'T')) {
X	waddch (data_window, 'T');
X	options |= OPT_TAGALL;
X	}
Xelse
X	waddch (data_window, 'N');
X
Xlen = read_cmdline (data_window, 6, 0, command, COLS - 10, "Command? ");
Xif (len > 0) {
X	keytab[key].type = KEY_CMD;
X	keytab[key].options = options;
X	ptr2 = (char *) malloc(len + 1);
X	strcpy (ptr2, command);
X	keytab[key].pntr = (voidptr) ptr2;
X	keydef_changed = 1;
X	}
X
Xredraw_all ();
X}
X
X
Xstatic
Xdown_one_line ()
X{
Xif (current < last) {
X	current++;
X	if (current > (top + 14)) {
X		top += 14;
X		if (top >= (last - 14)) {
X			top = last - 14;
X			if (top < 0) {
X				top = 0;
X				}
X			}
X		}
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic
Xup_one_line ()
X{
Xif (current > 0) {
X	current--;
X	if (current < top) {
X		top -= 14;
X		if (top < 0) {
X			top = 0;
X			}
X		}
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic
Xdown_one_screen ()
X{
Xif (top < (last - 14)) {
X	top += 15;
X	if (top >= (last - 14)) {
X		top = last - 14;
X		if (top < 0) {
X			top = 0;
X			}
X		}
X	current = top;
X	redraw_data ();
X	}
Xelse if (current < last) {
X	current = last;
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic
Xup_one_screen ()
X{
Xif (top > 0) {
X	top -= 15;
X	if (top < 0) {
X		top = 0;
X		}
X	current = top + 14;
X	if (current > last) {
X		current = last;
X		}
X	redraw_data ();
X	}
Xelse if (current > 0) {
X	current = 0;
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic void
Xredraw_data ()
X{
Xint row, key, k;
X
Xwmove (data_window, 0, 0);
Xwclrtobot (data_window);
Xfor (row = 0, key = top; (key <= last) && (row < 15); key++, row++) {
X	if (key == current) {
X		wstandout (data_window);
X		}
X	
X	wmove (data_window, row, 0);
X	wprintw (data_window, "%03o", key);
X
X	if ((key >= '!') && (key <= '~')) {
X		mvwaddch (data_window, row, 7, key);
X		}
X	else	{
X		for (k = 0; (keydef_table[k].name != NULL) && (keydef_table[k].value != key); k++);
X		if (keydef_table[k].name != NULL) {
X			mvwaddstr (data_window, row, 7, keydef_table[k].name);
X			}
X		}
X
X	wmove (data_window, row, 25);
X	waddch (data_window, ' ');
X	if (keytab[key].type == KEY_FUNC) {
X		for (k = 0; (funcname_table[k].kfunc != NULL) && (funcname_table[k].kfunc != (Function *) keytab[key].pntr); k++);
X		if (funcname_table[k].kfunc == NULL) {
X			waddstr (data_window, "func UNKNOWN");
X			}
X		else	{
X			waddstr (data_window, "func ");
X			waddstr (data_window, funcname_table[k].name);
X			}
X		}
X	else if (keytab[key].type == KEY_CMD) {
X		waddstr (data_window, "cmd ");
X		if (keytab[key].options & OPT_TAGALL) {
X			waddstr (data_window, "-all ");
X			}
X		else if (keytab[key].options & OPT_TAGCUR) {
X			waddstr (data_window, "-cur ");
X			}
X		else	{
X			waddstr (data_window, "-none ");
X			}
X		if (keytab[key].options & OPT_VERIFY) {
X			waddstr (data_window, "-ver ");
X			}
X		else	{
X			waddstr (data_window, "-nover ");
X			}
X		if (keytab[key].options & OPT_WAIT) {
X			waddstr (data_window, "-wait ");
X			}
X		else	{
X			waddstr (data_window, "-nowait ");
X			}
X		if (keytab[key].options & OPT_WAITERR) {
X			waddstr (data_window, "-err ");
X			}
X		else	{
X			waddstr (data_window, "-noerr ");
X			}
X		waddstr (data_window, (char *) keytab[key].pntr);
X		}
X	else	{
X		waddstr (data_window, "undefined");
X		}
X
X	if (key == current) {
X		wstandend (data_window);
X		}
X	}
Xwrefresh (data_window);
X}
X
X
Xstatic
Xredraw_all ()
X{
Xwmove (header_window, 0, 0);
Xwclrtobot (header_window);
Xwmove (header_window, 1, 10);
Xwstandout (header_window);
Xwaddstr (header_window, PGM_VERSION);
Xwaddstr (header_window, " Key Definition Menu");
Xwstandend (header_window);
Xwmove (header_window, 3, 3);
Xwprintw (header_window, "%-5s  %-20s  %s", "key", "key name", "definition");
Xwmove (header_window, 4, 0);
Xwaddstr (header_window, "------------------------------------------------------------------------------");
Xwrefresh (header_window);
X
Xredraw_data ();
X
Xwmove (help_window, 0, 0);
Xwclrtobot (help_window);
Xwmove (help_window, 0, 0);
Xwaddstr (help_window, "+----------------------------------------------------------------------------+");
Xwmove (help_window, 1, 0);
Xwaddstr (help_window, "|     use ^F, ^B, j, k and/or the arrow keys to move around the display      |");
Xwmove (help_window, 2, 0);
Xwaddstr (help_window, "|     D = define a key, U = undefine a key, Q = return to previous menu      |");
Xwmove (help_window, 3, 0);
Xwaddstr (help_window, "+----------------------------------------------------------------------------+");
Xwrefresh (help_window);
X}
X
X
Xint
Xkeydef_menu ()
X{
Xint c;
Xkeydef_changed = 0;
X
Xheader_window = newwin (5, 80, 0, 0);
Xdata_window = newwin (15, 80, 5, 0);
Xhelp_window = newwin (4, 80, 20, 0);
X#ifdef SYSVcurses
Xidlok (data_window, TRUE);
X#endif
Xredraw_all ();
X
Xwhile (1) {
X	c = my_getch (header_window);
X	switch (c) {
X
X	case ControlB:
X	case KEY_PPAGE:
X	case KEY_PrevScreen:
X		up_one_screen ();
X		break;
X
X	case ControlF:
X	case KEY_NPAGE:
X	case KEY_NextScreen:
X		down_one_screen ();
X		break;
X
X	case 'D':
X	case 'U':
X		define_a_key (c);
X		break;
X
X	case 'k':
X	case KEY_UP:
X	case ControlP:
X		up_one_line ();
X		break;
X
X	case 'j':
X	case KEY_DOWN:
X	case ControlN:
X		down_one_line ();
X		break;
X	
X	case 'q':
X	case 'Q':
X		wmove (header_window, 0, 0);
X		wclrtobot (header_window);
X		wrefresh (header_window);
X		delwin (header_window);
X		wmove (data_window, 0, 0);
X		wclrtobot (data_window);
X		wrefresh (data_window);
X		delwin (data_window);
X		wmove (help_window, 0, 0);
X		wclrtobot (help_window);
X		wrefresh (help_window);
X		delwin (help_window);
X		return;
X
X	case ControlL:
X	case ControlR:
X		redraw_all ();
X		break;
X
X	default:
X		beep();
X		}
X	}
X}
END_OF_FILE
  if test 10562 -ne `wc -c <'keymenu.c'`; then
    echo shar: \"'keymenu.c'\" unpacked with wrong size!
  fi
  # end of 'keymenu.c'
fi
if test -f 'optionmenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'optionmenu.c'\"
else
  echo shar: Extracting \"'optionmenu.c'\" \(6422 characters\)
  sed "s/^X//" >'optionmenu.c' <<'END_OF_FILE'
X
X/*
X * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
X *
X * Permission is hereby granted to copy, distribute or otherwise 
X * use any part of this package as long as you do not try to make 
X * money from it or pretend that you wrote it.  This copyright 
X * notice must be maintained in any copy made.
X *
X * Use of this software constitutes acceptance for use in an AS IS 
X * condition. There are NO warranties with regard to this software.  
X * In no event shall the author be liable for any damages whatsoever 
X * arising out of or in connection with the use or performance of this 
X * software.  Any use of this software is at the user's own risk.
X *
X * If you make modifications to this software that you feel 
X * increases it usefulness for the rest of the community, please 
X * email the changes, enhancements, bug fixes as well as any and 
X * all ideas to me. This software is going to be maintained and 
X * enhanced as deemed necessary by the community.
X *              
X *              Patrick J. Wolfe
X *              uunet!uiucuxc!kailand!pwolfe
X *              pwolfe@kailand.kai.com
X */
X
X#include "config.h"
X
Xextern struct option_entry option_table[];
Xextern char *true_false[], *dot_order[], *dir_order[];
X
Xint options_changed;		/* flag to indicate some options were changed */
Xstatic WINDOW *header_window, *data_window, *help_window;
Xstatic int top = 0;		/* index of top option on screen (retained between invokations) */
Xstatic int current = 0;		/* index of current option (retained between invokations) */
Xstatic int last;		/* index of last option in option_table (calculated when first run) */
X
X
Xstatic void
Xredraw_data ()
X{
Xint i, j, k;
Xint *variable;
Xchar **value_table;
X
Xwmove (data_window, 0, 0);
Xwclrtobot (data_window);
Xif (last > -1) {
X	for (i = 0, j = top; (j <= last) && (i < 15); i++, j++) {
X		if (j == current) {
X			wstandout (data_window);
X			}
X
X		wmove (data_window, i, 3);
X		wprintw (data_window, "%-15s", option_table[j].name);
X
X		if (j == current) {
X			wstandend (data_window);
X			}
X		
X		waddstr (data_window, "   ");
X
X		variable = option_table[j].variable;
X		value_table = option_table[j].value_table;
X		for (k = 0; value_table[k] != NULL; k++) {
X			waddstr (data_window, "   ");
X			if (*variable == k) {
X				wstandout (data_window);
X				waddch (data_window, '>');
X				}
X			else	{
X				waddch (data_window, ' ');
X				}
X			wprintw (data_window, "%-10s", value_table[k]);
X			if (*variable == k) {
X				waddch (data_window, '<');
X				wstandend (data_window);
X				}
X			else	{
X				waddch (data_window, ' ');
X				}
X			}
X		}
X	}
Xwrefresh (data_window);
X}
X
X
Xstatic
Xright_one_value ()
X{
Xint *variable;
Xchar **value_table;
X
Xvariable = option_table[current].variable;
Xvalue_table = option_table[current].value_table;
Xif (value_table[*variable + 1] == NULL) {
X	beep ();
X	}
Xelse	{
X	*variable = *variable + 1;
X	options_changed = 1;
X	redraw_data ();
X	}
X}
X
X
Xstatic
Xleft_one_value ()
X{
Xint *variable;
X
Xvariable = option_table[current].variable;
Xif (*variable == 0) {
X	beep ();
X	}
Xelse	{
X	*variable = *variable - 1;
X	options_changed = 1;
X	redraw_data ();
X	}
X}
X
X
Xstatic
Xredraw_all ()
X{
Xwmove (header_window, 0, 0);
Xwclrtobot (header_window);
Xwmove (header_window, 1, 10);
Xwstandout (header_window);
Xwaddstr (header_window, PGM_VERSION);
Xwaddstr (header_window, " Options Menu");
Xwstandend (header_window);
Xwmove (header_window, 3, 3);
Xwprintw (header_window, "%-15s   %s", "option name", "values");
Xwmove (header_window, 4, 0);
Xwaddstr (header_window, "------------------------------------------------------------------------------");
Xwrefresh (header_window);
X
Xredraw_data ();
X
Xwmove (help_window, 0, 0);
Xwclrtobot (help_window);
Xwmove (help_window, 0, 0);
Xwaddstr (help_window, "+----------------------------------------------------------------------------+");
Xwmove (help_window, 1, 0);
Xwaddstr (help_window, "|       use arrow keys to select and change values of options                |");
Xwmove (help_window, 2, 0);
Xwaddstr (help_window, "|       press Q to return to the previous menu                               |");
Xwmove (help_window, 3, 0);
Xwaddstr (help_window, "+----------------------------------------------------------------------------+");
Xwrefresh (help_window);
X}
X
X
Xstatic
Xdown_one_line ()
X{
Xif (current < last) {
X	current++;
X	if (current > (top + 14)) {
X		top += 14;
X		if (top >= (last - 14)) {
X			top = last - 14;
X			if (top < 0) {
X				top = 0;
X				}
X			}
X		}
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic
Xup_one_line ()
X{
Xif (current > 0) {
X	current--;
X	if (current < top) {
X		top -= 14;
X		if (top < 0) {
X			top = 0;
X			}
X		}
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic
Xdown_one_screen ()
X{
Xif (top < (last - 14)) {
X	top += 15;
X	if (top >= (last - 14)) {
X		top = last - 14;
X		if (top < 0) {
X			top = 0;
X			}
X		}
X	current = top;
X	redraw_data ();
X	}
Xelse if (current < last) {
X	current = last;
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xstatic
Xup_one_screen ()
X{
Xif (top > 0) {
X	top -= 15;
X	if (top < 0) {
X		top = 0;
X		}
X	current = top + 14;
X	if (current > last) {
X		current = last;
X		}
X	redraw_data ();
X	}
Xelse if (current > 0) {
X	current = 0;
X	redraw_data ();
X	}
Xelse	{
X	beep();
X	}
X}
X
X
Xint
Xoptions_menu ()
X{
Xint c;
Xoptions_changed = 0;
X
X/* find index of last option */
Xfor (last = 0; option_table[last].name != NULL; last++);
Xlast--;
Xheader_window = newwin (5, 80, 0, 0);
Xdata_window = newwin (15, 80, 5, 0);
Xhelp_window = newwin (4, 80, 20, 0);
X#ifdef SYSVcurses
Xidlok (data_window, TRUE);
X#endif
Xredraw_all ();
X
Xwhile (1) {
X	c = my_getch (header_window);
X	switch (c) {
X
X	case ControlB:
X	case KEY_PPAGE:
X	case KEY_PrevScreen:
X		up_one_screen ();
X		break;
X
X	case ControlF:
X	case KEY_NPAGE:
X	case KEY_NextScreen:
X		down_one_screen ();
X		break;
X
X	case 'k':
X	case KEY_UP:
X	case ControlP:
X		up_one_line ();
X		break;
X
X	case 'j':
X	case KEY_DOWN:
X	case ControlN:
X		down_one_line ();
X		break;
X	
X	case 'h':
X	case KEY_LEFT:
X		left_one_value ();
X		break;
X	
X	case 'l':
X	case KEY_RIGHT:
X		right_one_value ();
X		break;
X
X	case 'q':
X	case 'Q':
X		wmove (header_window, 0, 0);
X		wclrtobot (header_window);
X		wrefresh (header_window);
X		delwin (header_window);
X		wmove (data_window, 0, 0);
X		wclrtobot (data_window);
X		wrefresh (data_window);
X		delwin (data_window);
X		wmove (help_window, 0, 0);
X		wclrtobot (help_window);
X		wrefresh (help_window);
X		delwin (help_window);
X		return;
X
X	case ControlL:
X	case ControlR:
X		redraw_all ();
X		break;
X
X	default:
X		beep();
X		}
X	}
X}
END_OF_FILE
  if test 6422 -ne `wc -c <'optionmenu.c'`; then
    echo shar: \"'optionmenu.c'\" unpacked with wrong size!
  fi
  # end of 'optionmenu.c'
fi
if test -f 'readrc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'readrc.c'\"
else
  echo shar: Extracting \"'readrc.c'\" \(12164 characters\)
  sed "s/^X//" >'readrc.c' <<'END_OF_FILE'
X/*
X *	readrc.c
X *
X * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
X *
X * Permission is hereby granted to copy, distribute or otherwise 
X * use any part of this package as long as you do not try to make 
X * money from it or pretend that you wrote it.  This copyright 
X * notice must be maintained in any copy made.
X *
X * Use of this software constitutes acceptance for use in an AS IS 
X * condition. There are NO warranties with regard to this software.  
X * In no event shall the author be liable for any damages whatsoever 
X * arising out of or in connection with the use or performance of this 
X * software.  Any use of this software is at the user's own risk.
X *
X * If you make modifications to this software that you feel 
X * increases it usefulness for the rest of the community, please 
X * email the changes, enhancements, bug fixes as well as any and 
X * all ideas to me. This software is going to be maintained and 
X * enhanced as deemed necessary by the community.
X *              
X *              Patrick J. Wolfe
X *              uunet!uiucuxc!kailand!pwolfe
X *              pwolfe@kailand.kai.com
X */
X
X
X#include "config.h"
X#include "readrc.h"
X
Xextern struct key_entry keytab[], default_keytab[];
Xextern int century;
Xextern char rcfilename[], *loginid, errormsg[];
X
Xint rcerrors = 0;
X
X
Xstatic void
Xrcerrmsg (filename, lineno, msg, arg)
Xint lineno;
Xchar *filename, *msg, *arg;
X{
Xrcerrors++;
Xif (rcerrors == 1) {
X	fprintf (stderr, "\r\nerror in scan initfile %s:\n", filename);
X	}
Xfprintf (stderr, "line %d:  %s", lineno, msg);
Xif (arg[0] != '\0') {
X	fprintf (stderr, ": \"%s\"", arg);
X	}
Xfputc ('\n', stderr);
X}
X
X
Xstatic void
Xsetoption (filename, lineno, ptr1)
Xchar *filename, *ptr1;
Xint lineno;
X{
Xint ctr, *variable;
Xchar *ptr2;
Xchar **value_table;
X
X/* skip whitespace */
Xfor (ptr1++; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
Xif (*ptr1 == '\n') {
X	rcerrmsg (filename, lineno, "missing option name", "");
X	return;
X	}
X
X/* find end of variable name */
Xfor (ptr2 = ptr1; (*ptr2 != '\n') && !isspace(*ptr2); *ptr2++);
Xif (*ptr2 == '\n') {
X	rcerrmsg (filename, lineno, "missing value", "");
X	return;
X	}
X*ptr2 = '\0';
X
X/* validate option name */
Xfor (ctr = 0; (option_table[ctr].name != NULL) && (strcmp (option_table[ctr].name, ptr1) != 0); ctr++);
Xif (option_table[ctr].name == NULL) {
X	rcerrmsg (filename, lineno, "invalid option name", ptr1);
X	return;
X	}
Xvariable = option_table[ctr].variable;
Xvalue_table = option_table[ctr].value_table;
X
X/* skip whitespace and equals sign */
Xfor (ptr1 = ptr2, ptr1++; (*ptr1 != '\n') && (isspace(*ptr1) || (*ptr1 == '=')); ptr1++);
Xif (*ptr1 == '\n') {
X	rcerrmsg (filename, lineno, "missing value", "");
X	return;
X	}
X
X/* find end of value */
Xfor (ptr2 = ptr1; (*ptr2 != '\n') && !isspace(*ptr2); *ptr2++);
X*ptr2 = '\0';
X
X/* check value table */
Xfor (ctr = 0; (value_table[ctr] != NULL) && (strcmp(value_table[ctr], ptr1) != 0); ctr++);
Xif (value_table[ctr] == NULL) {
X	rcerrmsg (filename, lineno, "invalid value", ptr1);
X	fputs ("\tvalue must be one of the following: ", stderr);
X	for (ctr = 0; value_table[ctr] != NULL; ctr++) {
X		fputc (' ', stderr);
X		fputs (value_table[ctr], stderr);
X		}
X	fputc ('\n', stderr);
X	return;
X	}
X
X/* make variable assignment */
X*variable = ctr;
X}
X
X
Xstatic void
Xkeyfuncdef (filename, lineno, ptr1, keynum)
Xint keynum, lineno;
Xchar *filename, *ptr1;
X{
Xint ctr;
Xchar *ptr2;
X
X/* skip whitespace */
Xfor (ptr1++; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
X
X/* find end of funcname */
Xfor (ptr2 = ptr1; (*ptr2 != '\n') && !isspace(*ptr2); *ptr2++);
X*ptr2 = '\0';
X
Xfor (ctr = 0; (funcname_table[ctr].kfunc != NULL) && (strcmp (ptr1, funcname_table[ctr].name) != 0); ctr++);
Xif (funcname_table[ctr].kfunc == NULL) {
X	rcerrmsg (filename, lineno, "unknown function", ptr1);
X	}
Xelse	{
X	keytab[keynum].type = KEY_FUNC;
X	keytab[keynum].options = 0;
X	keytab[keynum].pntr = (voidptr) funcname_table[ctr].kfunc;
X#ifdef DEBUG
X	fprintf (stderr, "keytab[%d] will call function %s\n", keynum, funcname_table[ctr].name);
X#endif
X	}
X}
X
X
Xstatic void
Xkeycmddef (filename, lineno, ptr1, keynum)
Xint keynum, lineno;
Xchar *filename, *ptr1;
X{
Xint len, options, eolreached = 0;
Xchar *ptr2;
X
X/*
X * by default:
X *	1. pause after the command finishes
X *	2. don't append any filenames
X *	3. don't verify command before executing it
X */
Xoptions = OPT_WAIT;	
X
X/* skip whitespace */
Xfor (ptr1++; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
Xif (*ptr1 == '\n') {
X	eolreached++;
X	}
X
Xwhile (!eolreached && (*ptr1 == '-')) {
X	/* find end of keyname */
X	for (ptr2 = ptr1; (*ptr2 != '\n') && (*ptr2 != ' '); *ptr2++);
X	if (*ptr2 == '\n') {
X		eolreached++;
X		continue;
X		}
X	*ptr2 = '\0';
X
X	/* process option */
X	if (strncmp (ptr1, "-tag", 4) == 0) {		/* process all tagged files */
X		options &= OPT_TAGCUR;
X		options |= OPT_TAGALL;
X		}
X	else if (strncmp (ptr1, "-cur", 4) == 0) {		/* process only the current file */
X		options &= OPT_TAGALL;
X		options |= OPT_TAGCUR;
X		}
X	else if (strncmp (ptr1, "-non", 4) == 0) {		/* process no files */
X		options &= OPT_TAGCUR;
X		options &= OPT_TAGALL;
X		}
X	else if (strncmp (ptr1, "-ver", 4) == 0) {		/* verify command before executing */
X		options |= OPT_VERIFY;
X		}
X	else if (strncmp (ptr1, "-nover", 6) == 0) {		/* don't verify */
X		options &= OPT_VERIFY;
X		}
X	else if (strncmp (ptr1, "-wait", 5) == 0) {		/* wait after the command finished */
X		options |= OPT_WAIT;
X		}
X	else if (strncmp (ptr1, "-nowait", 7) == 0) {	/* don't wait after the command finished */
X		options &= OPT_WAIT;
X		}
X	else	{
X		rcerrmsg (filename, lineno, "unrecognized option", ptr1);
X		return;
X		}
X
X	/* skip whitespace */
X	ptr1 = ptr2;
X	for (ptr1++; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
X	if (*ptr1 == '\n') {
X		eolreached++;
X		}
X	}
X
Xif (eolreached) {
X	rcerrmsg (filename, lineno, "missing command string", "");
X	}
Xelse	{
X	keytab[keynum].type = KEY_CMD;
X	keytab[keynum].options = options;
X	len = strlen (ptr1) + 1;
X	ptr2 = (char *) malloc(len);
X	keytab[keynum].pntr = (voidptr) ptr2;
X	strcpy ((char *) keytab[keynum].pntr, ptr1);
X	for (; (*ptr2 != '\n') && (*ptr2 != '\0'); ptr2++);
X	*ptr2 = '\0';	/* change the newline to a null */
X#ifdef DEBUG
X	fprintf (stderr, "keytab[%d] will execute command %s (options=%o)\n", keynum, ptr1, options);
X#endif
X	}
X}
X
X
Xstatic void
Xkeydef (filename, lineno, ptr1)
Xchar *filename, *ptr1;
Xint lineno;
X{
Xint keynum = 0, len, ctr1, eolreached = 0;
Xchar *ptr2;
X
X/* skip whitespace */
Xfor (ptr1++; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
X
X/* find end of keyname */
Xfor (ptr2 = ptr1; (*ptr2 != '\n') && (*ptr2 != ' '); *ptr2++);
Xif (*ptr2 == '\n') {
X	rcerrmsg (filename, lineno, "missing key type", "");
X	return;
X	}
X*ptr2 = '\0';
X
X/* validate keyname */
Xlen = strlen(ptr1);
Xif (len == 1) {
X	keynum = *ptr1;				/* just a single character */
X	}
Xelse if ((len >= 2) && (*ptr1 == '\\')) {	/* character in decimal backslash notation */
X	ptr1++; len--;
X	while (len > 0) {
X		keynum = (keynum * 10) + (*ptr1 - '0');
X		ptr1++; len--;
X		}
X	}
Xelse	{
X	for (ctr1 = 0; (keydef_table[ctr1].name != NULL) && (strcmp (keydef_table[ctr1].name, ptr1) != 0); ctr1++);
X	if (keydef_table[ctr1].name == NULL) {
X		rcerrmsg (filename, lineno, "invalid keyname", ptr1);
X		return;
X		}
X	keynum = keydef_table[ctr1].value;
X	}
X#ifdef DEBUG
Xfprintf (stderr, "keynum value is %d\n", keynum);
X#endif
X
X/* skip whitespace */
Xptr1 = ptr2;
Xfor (ptr1++; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
X
X/* find end of type */
Xfor (ptr2 = ptr1; (*ptr2 != '\n') && (*ptr2 != ' '); *ptr2++);
Xif (*ptr2 == '\n') {
X	eolreached++;
X	}
X*ptr2 = '\0';
X
Xif (strncmp (ptr1, "func", 4) == 0) {		/* builtin function */
X	if (! eolreached) {
X		keyfuncdef (filename, lineno, ptr2, keynum);
X		}
X	else	{
X		rcerrmsg (filename, lineno, "missing function name", "");
X		}
X	}
Xelse if (strncmp (ptr1, "cmd", 3) == 0) {		/* command string */
X	if (! eolreached) {
X		keycmddef (filename, lineno, ptr2, keynum);
X		}
X	else	{
X		rcerrmsg (filename, lineno, "missing command string", "");
X		}
X	}
Xelse if (strncmp (ptr1, "undef", 5) == 0) {		/* undefined */
X	keytab[keynum].type = KEY_UNDEF;
X	keytab[keynum].options = 0;
X	keytab[keynum].pntr = (voidptr) NULL;
X	}
Xelse	{
X	rcerrmsg (filename, lineno, "invalid key type", ptr1);
X	}
X}
X
X
Xint
Xreadrc (filename)
Xchar *filename;
X{
XFILE *fp;
Xint eolreached, linectr = 0;
Xchar line[1024], *ptr1, *ptr2;
X
Xif ((fp = fopen (filename, "r")) == NULL) {
X	if (errno != ENOENT) {
X		perror ("fopen");
X		fprintf (stderr, "scan:  cannot open initfile %s for input\n", filename);
X		sleep (5);
X		exit (1);
X		}
X	return;
X	}
X
Xwhile (fgets (line, 1024, fp) != NULL) {
X	linectr++;
X	eolreached = 0;
X
X	/* skip over leading white space */
X	for (ptr1 = line; (*ptr1 != '\n') && isspace(*ptr1); ptr1++);
X	if ((*ptr1 == '#') || (*ptr1 == '\n')) {
X		continue;	/* ignore comment or empty lines */
X		}
X
X	/* find end of cmd */
X	for (ptr2 = ptr1; (*ptr2 != '\n') && (*ptr2 != ' '); *ptr2++);
X	if (*ptr2 == '\n') {
X		eolreached++;
X		}
X	*ptr2 = '\0';
X
X	if (strncmp (ptr1, "key", 3) == 0) {	/* key definition cmd */
X		if (! eolreached) {
X			keydef (filename, linectr, ptr2);
X			}
X		else	{
X			rcerrmsg (filename, linectr, "missing key name", "");
X			}
X		}
X
X	else if (strncmp (ptr1, "set", 3) == 0) {	/* set option cmd */
X		if (! eolreached) {
X			setoption (filename, linectr, ptr2);
X			}
X		else	{
X			rcerrmsg (filename, linectr, "missing option name", "");
X			}
X		}
X
X	else	{
X		rcerrmsg (filename, linectr, "unrecognized initfile command", ptr1);
X		}
X	}
X
Xfclose (fp);
Xif (rcerrors) {
X	fprintf (stderr, "\r\n");
X	exit (1);
X	}
X}
X
X
Xint
Xwriterc ()
X{
Xstruct timeval tp;
Xstruct timezone tzp;
Xstruct tm *today;
X
XFILE *fp;
Xint ctr, ctr2, *variable;
Xchar **value_table;
X
Xif ((fp = fopen (rcfilename, "w")) == NULL) {
X	strcpy (errormsg, "count not open ");
X	strcat (errormsg, rcfilename);
X	strcat (errormsg, " file for writing ");
X	msgupdate ();
X	return;
X	}
X
Xgettimeofday (&tp, &tzp);
Xtoday = localtime (&tp.tv_sec);
Xfputs ("# Scan initialization file\n", fp);
Xfprintf (fp, "# written by %s at %02d:%02d:%02d on %02d/%02d/%02d%02d\n", loginid,
X	today->tm_hour, today->tm_min, today->tm_sec, today->tm_mon + 1, today->tm_mday,
X	century, today->tm_year);
X
X/* write out options that are different from the default values */
Xfputs ("\n# options\n", fp);
Xfor (ctr = 0; option_table[ctr].name != NULL; ctr++) {
X	if (*option_table[ctr].variable != option_table[ctr].default_value) {
X		variable = option_table[ctr].variable;
X		value_table = option_table[ctr].value_table;
X		fprintf (fp, "set %s %s\n", option_table[ctr].name, value_table[*variable]);
X		}
X	}
X
X/* write out key definitions that are different from the default values */
Xfputs ("\n# key definitions\n", fp);
Xfor (ctr = 0; ctr < SIZEKEYTAB; ctr++) {
X	if ((keytab[ctr].type != default_keytab[ctr].type)
X	 || (keytab[ctr].options != default_keytab[ctr].options)
X	 || (keytab[ctr].pntr != default_keytab[ctr].pntr)) {
X		fputs ("key ", fp);
X
X		/* print name of this key */
X		for (ctr2 = 0; (keydef_table[ctr2].name != NULL) && (keydef_table[ctr2].value != ctr); ctr2++);
X		if (keydef_table[ctr2].name != NULL) {
X			fprintf (fp, "%s", keydef_table[ctr2].name);
X			}
X		else if ((ctr >= '!') && (ctr <= '~')) {
X			fprintf (fp, "%c", ctr);
X			}
X		else	{
X			fprintf (fp, "\\%d", ctr);
X			}
X
X		if (keytab[ctr].type == KEY_FUNC) {
X
X			/* print name of this function */
X			for (ctr2 = 0; (funcname_table[ctr2].name != NULL)
X				&& (funcname_table[ctr2].kfunc != (Function *) keytab[ctr].pntr); ctr2++);
X			if (funcname_table[ctr2].name != NULL) {
X				fputs (" func ", fp);
X				fputs (funcname_table[ctr2].name, fp);
X				}
X			else	{
X				fprintf (stderr, "writerc: key \\0%o is type KEY_FUNC, but the function cannot be found in the name table\n", ctr);
X				fputs (" undef", fp);
X				}
X			}
X		else if (keytab[ctr].type == KEY_CMD) {
X			fputs (" cmd ", fp);
X			if (keytab[ctr].options & OPT_VERIFY) {
X				fputs ("-verify ", fp);
X				}
X			if ((keytab[ctr].options & OPT_WAIT) == 0) {
X				fputs ("-nowait ", fp);
X				}
X			if (keytab[ctr].options & OPT_TAGALL) {
X				fputs ("-tag ", fp);
X				}
X			else if (keytab[ctr].options & OPT_TAGCUR) {
X				fputs ("-cur ", fp);
X				}
X			fputs ((char *) keytab[ctr].pntr, fp);
X			}
X		else	{
X			fputs (" undef", fp);
X			}
X		fputc ('\n', fp);
X		}
X	}
X
Xfclose (fp);
X}
END_OF_FILE
  if test 12164 -ne `wc -c <'readrc.c'`; then
    echo shar: \"'readrc.c'\" unpacked with wrong size!
  fi
  # end of 'readrc.c'
fi
if test -f 'userfuncs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'userfuncs.c'\"
else
  echo shar: Extracting \"'userfuncs.c'\" \(11698 characters\)
  sed "s/^X//" >'userfuncs.c' <<'END_OF_FILE'
X/*
X * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
X *
X * Permission is hereby granted to copy, distribute or otherwise 
X * use any part of this package as long as you do not try to make 
X * money from it or pretend that you wrote it.  This copyright 
X * notice must be maintained in any copy made.
X *
X * Use of this software constitutes acceptance for use in an AS IS 
X * condition. There are NO warranties with regard to this software.  
X * In no event shall the author be liable for any damages whatsoever 
X * arising out of or in connection with the use or performance of this 
X * software.  Any use of this software is at the user's own risk.
X *
X * If you make modifications to this software that you feel 
X * increases it usefulness for the rest of the community, please 
X * email the changes, enhancements, bug fixes as well as any and 
X * all ideas to me. This software is going to be maintained and 
X * enhanced as deemed necessary by the community.
X *              
X *              Patrick J. Wolfe
X *              uunet!uiucuxc!kailand!pwolfe
X *              pwolfe@kailand.kai.com
X */
X
X#include "config.h"
X
Xextern SIGTYPE die();
Xextern struct dblock cwd[MAXDIRSIZE];
Xextern int opt_pager_pause, opt_rm_prompt, topptr, curptr, lastptr;
Xextern char *editor, *pager, *homedir, *shellpgm, prevdir[], errormsg[];
Xextern WINDOW *headwin, *datawin, *helpwin;
X
X
X/* ---------------------------------------------------------------------------- */
X/*			file processing user functions				*/
X/* ---------------------------------------------------------------------------- */
X
X
Xview_file (c)
Xchar c;
X{
Xint options = OPT_TAGCUR;
X
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	if (opt_pager_pause)
X		options |= OPT_WAIT;
X	do_cmd (pager, options);
X	}
X}
X
X
Xview_tagged (c)
Xchar c;
X{
Xint options = OPT_TAGALL;
X
Xif (opt_pager_pause)
X	options |= OPT_WAIT;
Xdo_cmd (pager, options);
X}
X
X
Xedit_file (c)
Xchar c;
X{
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	do_cmd (editor, OPT_TAGCUR);
X	}
X}
X
X
Xedit_tagged (c)
Xchar c;
X{
Xdo_cmd (editor, OPT_TAGALL);
X}
X
X
Xrm_file (c)
Xchar c;
X{
Xint options = OPT_TAGCUR | OPT_WAITERR;
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	if (opt_rm_prompt) {
X		options |= OPT_VERIFY;
X		}
X	if (cwd[curptr].type == S_IFDIR)
X		do_cmd ("rmdir", options);
X	else
X		do_cmd ("rm -f", options);
X	}
X}
X
X
Xrm_tagged (c)
Xchar c;
X{
Xint options = OPT_TAGALL | OPT_WAITERR;
Xint ctr1, ctr2;
X
Xif (opt_rm_prompt) {
X	options |= OPT_VERIFY;
X	}
X#ifdef RM_BREAKPOINT
Xelse	{	/* if too many files are being deleted, verify anyway */
X	for (ctr1 = ctr2 = 0; (ctr2 < RM_BREAKPOINT) && (ctr1 <= lastptr); ctr1++) {
X		if (cwd[ctr1].selected == 1) {
X			ctr2++;
X			}
X		}
X	if (ctr2 > RM_BREAKPOINT) {
X		options |= OPT_VERIFY;
X		}
X	}
X#endif
Xdo_cmd ("rm -f", options);
X}
X
X
Xexecute_file (c)	/* this routine executes the current file and returns to scan */
Xchar c;
X{
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	do_cmd (cwd[curptr].name, OPT_WAIT);
X	}
X}
X
X
Xexec_file (c2)		/* this routine replaces scan with the current file */
Xchar c2;
X{
Xint row = 2;
Xchar c;
X
Xif (cwd[curptr].size == -1) {
X	beep ();
X	return;
X	}
X
X/* clear the screen, reset the terminal to normal mode, and run the command */
Xwmove (helpwin, 0, 0);
Xwclrtobot (helpwin);
Xwmove (datawin, 0, 0);
Xwclrtobot (datawin);
Xwmove (headwin, row, 0);
Xwclrtobot (headwin);
X
X/* let the user know what we are doing */
Xmvwprintw (headwin, row, 0, "Execing the file: %s", cwd[curptr].name);
X
Xc = 'a';
Xwhile ((c != 'y') && (c != 'Y') && (c != 'N') && (c != 'n')) {
X	row++;
X	move (row, 0);
X	addstr ("Are you sure? ");
X	refresh ();
X	if ((c = my_getch (headwin)) == ERR) {
X		die ();
X		}
X	}
Xif ((c != 'y') && (c != 'Y')) {
X	redraw_menu ();
X	return;
X	}
X
Xsignal (SIGHUP, SIG_DFL);			/* trap signal 1, hangup */
Xsignal (SIGINT, SIG_DFL);			/* trap signal 2, interrupt */
Xsignal (SIGQUIT, SIG_DFL);			/* trap signal 3, quit */
Xsignal (SIGTERM, SIG_DFL);			/* trap signal 15, software termination */
Xendwin ();
X
Xexeclp (cwd[curptr].name, cwd[curptr].name, 0);
X
Xperror ("execlp");
Xfprintf (stderr, "scan: execlp %s failed - returning to the scan program...", cwd[curptr].name);
Xsleep (4);
X
Xinitscr ();				/* initialize curses */
Xsignal (SIGHUP, die);			/* trap signal 1, hangup */
Xsignal (SIGINT, die);			/* trap signal 2, interrupt */
Xsignal (SIGQUIT, die);			/* trap signal 3, quit */
Xsignal (SIGTERM, die);			/* trap signal 15, software termination */
Xnoecho ();				/* curses should not echo keys as they are typed */
Xnonl ();				/* disable cr/lf mapping */
Xcrmode ();				/* turn on cbreak mode */
Xheadwin = newwin (5, COLS, 0, 0);
Xdatawin = newwin (PAGESIZE, COLS, 5, 0);
Xhelpwin = newwin (1, COLS, 5 + PAGESIZE, 0);
X#ifdef SYSVcurses
Xidlok (datawin, TRUE);
X#endif
X
Xredraw_menu ();
X}
X
X
Xcommand_file (c)
Xchar c;
X{
Xchar	cmdline[256];
X
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	if (read_cmdline (helpwin, 0, 0, cmdline, COLS - 10, "command ? ") > 0) {
X		do_cmd (cmdline, OPT_TAGCUR | OPT_WAIT);
X		}
X	menu_update ();
X	redraw_help ();
X	}
X}
X
X
Xcommand_tagged (c)
Xchar c;
X{
Xchar	cmdline[256];
X
Xif (read_cmdline (helpwin, 0, 0, cmdline, COLS - 10, "command ? ") > 0) {
X	do_cmd (cmdline, OPT_TAGALL | OPT_WAIT);
X	}
Xmenu_update ();
Xredraw_help ();
X}
X
X
Xtoggle_tag (c)
Xchar c;
X{
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	cwd[curptr].selected = (cwd[curptr].selected * -1) + 1;
X	menu_update ();
X	}
X}
X
X
Xtag_all (c)
Xchar c;
X{
Xint ctr;
X
Xfor (ctr = 0; ctr <= lastptr; ctr++) {
X	if (cwd[ctr].size != -1) {
X		cwd[ctr].selected = 1;
X		}
X	}
Xmenu_update ();
X}
X
X
Xuntag_all (c)
Xchar c;
X{
Xint ctr;
X
Xfor (ctr = 0; ctr <= lastptr; ctr++) {
X	cwd[ctr].selected = 0;
X	}
Xmenu_update ();
X}
X
X
X/* ---------------------------------------------------------------------------- */
X/*			change directory routines				*/
X/* ---------------------------------------------------------------------------- */
X
X
Xcd_prompt (c)
Xchar c;
X{
Xchar	cmdline[256];
X
Xif (read_cmdline (helpwin, 0, 0, cmdline, COLS - 4, "cd ") > 0) {
X	do_chdir (cmdline);
X	}
Xelse	{
X	menu_update ();
X	redraw_help ();
X	}
X}
X
X
X
Xcd_file (c)
Xchar c;
X{
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	do_chdir (cwd[curptr].name);
X	}
X}
X
X
Xcd_or_edit (c)
Xchar c;
X{
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	if (cwd[curptr].type == S_IFDIR) {
X		do_chdir (cwd[curptr].name);
X		}
X	else	{
X		edit_file (c);
X		}
X	}
X}
X
X
Xcd_or_view (c)
Xchar c;
X{
Xif (cwd[curptr].size == -1) {
X	beep ();
X	}
Xelse	{
X	if (cwd[curptr].type == S_IFDIR) {
X		do_chdir (cwd[curptr].name);
X		}
X	else	{
X		view_file (c);
X		}
X	}
X}
X
X
Xcd_dot (c)
Xchar c;
X{
Xdo_chdir (".");
X}
X
X
Xcd_dotdot (c)
Xchar c;
X{
Xdo_chdir ("..");
X}
X
X
Xcd_home (c)
Xchar c;
X{
Xdo_chdir (homedir);
X}
X
X
Xcd_back (c)
Xchar c;
X{
Xdo_chdir (prevdir);
X}
X
X
Xcd_root (c)
Xchar c;
X{
Xdo_chdir ("/");
X}
X
X
X/* ---------------------------------------------------------------------------- */
X/*			screen movement routines				*/
X/* ---------------------------------------------------------------------------- */
X
X
Xnext_line (c)
Xchar c;
X{
Xif (curptr >= lastptr) {
X	if (lastptr < PAGESIZE)
X		strcpy (errormsg, "all files shown");
X	else
X		strcpy (errormsg, "last page shown");
X	msgupdate ();
X	}
Xelse
X	menu_move (1);
X}
X
X
Xprev_line (c)
Xchar c;
X{
Xif (curptr <= 0) {
X	if (lastptr < PAGESIZE)
X		strcpy (errormsg, "all files shown");
X	else
X		strcpy (errormsg, "first page shown");
X	msgupdate ();
X	}
Xelse
X	menu_move (-1);
X}
X
X
Xtop_line (c)
Xchar c;
X{
Xif (curptr > topptr)
X	menu_move ((curptr - topptr) * -1);
X}
X
X
Xmiddle_line (c)
Xchar c;
X{
Xint midline;
X
Xmidline = lastptr - topptr;	/* find line that is in the middle of the current screen */
Xif (midline > PAGESIZE)
X	midline = PAGESIZE;
Xmidline = (midline / 2) + topptr;
Xif (curptr > midline)
X	menu_move ((curptr - midline) * -1);
Xelse if (curptr < midline)
X	menu_move (midline - curptr);
X}
X
X
Xbottom_line (c)
Xchar c;
X{
Xint newline;
X
Xnewline = topptr + PAGESIZE - 1;
Xif (newline > lastptr)
X	newline = lastptr;
Xif (curptr < newline)
X	menu_move (newline - curptr);
X}
X
X
Xnext_page (c)
Xchar c;
X{
Xif ((topptr >= (lastptr - PAGESIZE)) && (curptr < lastptr))
X	menu_move (lastptr - curptr);
Xelse if (topptr >= (lastptr - PAGESIZE)) {
X	if (lastptr < PAGESIZE)
X		strcpy (errormsg, "all files shown");
X	else
X		strcpy (errormsg, "last page shown");
X	msgupdate ();
X	}
Xelse
X	menu_scroll (PAGESIZE);
X}
X
X
Xnext_halfpage (c)
Xchar c;
X{
Xif ((topptr >= (lastptr - PAGESIZE)) && (curptr < lastptr))
X	menu_move (lastptr - curptr);
Xelse if (topptr >= (lastptr - PAGESIZE)) {
X	if (lastptr < PAGESIZE)
X		strcpy (errormsg, "all files shown");
X	else
X		strcpy (errormsg, "last page shown");
X	msgupdate ();
X	}
Xelse
X	menu_scroll (PAGESIZE / 2);
X}
X
X
Xprev_page (c)
Xchar c;
X{
Xif ((topptr <= 0) && (curptr > 0))
X	menu_move (curptr * -1);
Xelse if (topptr <= 0) {
X	if (lastptr < PAGESIZE)
X		strcpy (errormsg, "all files shown");
X	else
X		strcpy (errormsg, "first page shown");
X	msgupdate ();
X	}
Xelse
X	menu_scroll (PAGESIZE * -1);
X}
X
X
Xprev_halfpage (c)
Xchar c;
X{
Xif ((topptr <= 0) && (curptr > 0))
X	menu_move (curptr * -1);
Xelse if (topptr <= 0) {
X	if (lastptr < PAGESIZE)
X		strcpy (errormsg, "all files shown");
X	else
X		strcpy (errormsg, "first page shown");
X	msgupdate ();
X	}
Xelse
X	menu_scroll ((PAGESIZE / 2) * -1);
X}
X
X
Xfirst_page (c)
Xchar c;
X{
Xtopptr = curptr = 0;
Xmenu_update ();
X}
X
X
Xlast_page (c)
Xchar c;
X{
Xtopptr = (lastptr - PAGESIZE) + 1;
Xif (topptr < 0) {
X	topptr = 0;
X	}
Xcurptr = lastptr;
Xmenu_update ();
X}
X
X/* ---------------------------------------------------------------------------- */
X/*				misc routines					*/
X/* ---------------------------------------------------------------------------- */
X
X
Xfork_shell (c)
Xchar c;
X{
Xdo_cmd (shellpgm, OPT_WAITERR);
X}
X
X
Xexit_pgm (c)
Xchar c;
X{
Xclear ();
Xrefresh ();
Xdie ();
X}
X
X
Xhelp_screen (c)
Xchar c;
X{
Xint	i, row = 0;
X
Xwmove (headwin, 3, 0);
Xwclrtobot (headwin);
Xmvwaddstr (headwin, 3, 15, PGM_VERSION);
Xwaddstr (headwin, " Help Screen");
Xwmove (headwin, 4, 0);
Xfor (i = 1; i < COLS; i += 10) {
X	waddstr (headwin, "----------");
X	}
Xwrefresh (headwin);
X
Xwmove (datawin, row, 0);
Xwclrtobot (datawin);
Xmvwaddstr (datawin, row++, 0, "^F,^B,^D,^U  - scroll through the menu");
Xmvwaddstr (datawin, row++, 0, "up,dn arrows - move current file pointer up or down through the file menu");
Xmvwaddstr (datawin, row++, 0, "g,G          - move to first or last page of the file menu");
Xmvwaddstr (datawin, row++, 0, "H,M,L        - move to top, middle, bottom file on the current page");
Xmvwaddstr (datawin, row++, 0, "d,u,b,~,/    - cd down,up,previous dir,home,root");
Xmvwaddstr (datawin, row++, 0, "c            - prompt for directory name and cd to it");
Xmvwaddstr (datawin, row++, 0, ".            - cd ., re-reads the current directory");
Xmvwaddstr (datawin, row++, 0, "Return       - if pointing at a file, edit it, or if a dir, cd to it");
Xmvwaddstr (datawin, row++, 0, "m            - toggle tagged status of the current file");
Xmvwaddstr (datawin, row++, 0, "T,U          - tag, untag all files");
Xmvwaddstr (datawin, row++, 0, "e, r, v      - edit, remove, view the current file");
Xmvwaddstr (datawin, row++, 0, "E, R, V      - edit, remove, view all tagged files");
Xmvwaddstr (datawin, row++, 0, "x,X          - prompt for cmd and execute passing current or tagged file(s)");
Xmvwaddstr (datawin, row++, 0, "!,%          - spawn a subshell in the current directory");
Xmvwaddstr (datawin, row++, 0, "^L,^R        - repaint the screen");
Xmvwaddstr (datawin, row++, 0, "S            - enter SETUP mode, for defining keys or changing options");
Xmvwaddstr (datawin, row, 0, "q,Q          - exit the SCAN program");
Xwrefresh (datawin);
X
Xwmove (helpwin, 0, 0);
Xwstandout (helpwin);
Xwaddstr (helpwin, "-------- Press any key to return to the previous menu ----------");
Xwstandend (helpwin);
Xwrefresh (helpwin);
X
Xmy_getch (headwin);
Xredraw_menu ();
X}
END_OF_FILE
  if test 11698 -ne `wc -c <'userfuncs.c'`; then
    echo shar: \"'userfuncs.c'\" unpacked with wrong size!
  fi
  # end of 'userfuncs.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.