From pa.dec.com!decwrl!uunet!sparky!kent Sun Aug 11 15:54:53 PDT 1991
Article: 2604 of comp.sources.misc
Newsgroups: comp.sources.misc
Path: pa.dec.com!decwrl!uunet!sparky!kent
From: Andy Knight x445 <aknight@ourgang.Prime.COM>
Subject:  v21i094:  mced - C-shell history command line editor, Part01/01
Message-ID: <1991Aug7.030614.904@sparky.IMD.Sterling.COM>
X-Md4-Signature: d9e02bf7859903a6f74c83ff0eed07b8
Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield)
Organization: Sterling Software, IMD
Date: Wed, 7 Aug 1991 03:06:14 GMT
Approved: kent@sparky.imd.sterling.com
Lines: 1311

Submitted-by: Andy Knight <aknight@ourgang.Prime.COM>
Posting-number: Volume 21, Issue 94
Archive-name: mced/part01
Environment: UNIX, C-shell

McEd is a utility which allows you to browse, edit and execute
commands from your C-shell history list. It is not a shell itself,
but it executes the commands in your current shell as if you had
typed them in.  The editing functions are based on gnuemacs,
with a vi mode possibly sometime in the future.

+==============================================================  \ / ==+
|                             Andy Knight, Computervision    _ ,-   -  |
| |\/|  _ |/     o  _ |_ -----Bedford, MA------------------<[o]> / \   |
| |  | (_ |\ |\| | (_)| | |   aknight@ourgang.prime.com      |         |
+================= __) ==================================== / \ =======+

#! /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:
#	main.c
#	emacs_edit.c
#	getch.c
#	Makefile
#	README
#	mced.1
#	getch.h
#	config.h
# This archive created: Fri Aug  2 10:01:23 1991
export PATH; PATH=/bin:$PATH
echo shar: extracting "'main.c'" '(7282 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'main.c'
X/* 
X * This software is Copyright (c) 1991 by Andy Knight
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 *              Andy Knight 
X *              aknight@ourgang.prime.com 
X */
X
X#include "config.h"
X
Xchar hfile[20], cfile[20];
Xchar vern[] = "#";
Xchar spc[] = " ";
Xchar prompt[] = "%McEd% ";
Xchar *hist[MAX_H_READ], cstr[MAX_CH], sstr[30];
Xint edit_mode, x_pos, savex_pos, xend, cur_cmd, last_hline, xbeg = 7;
Xint index_cmd();
XFILE *fptr;
XSIGTYPE die_curses(), die_normal();
XWINDOW *win;
Xvoid my_wmove(), eat_white(), add_hline(), cmd_to_win(), win_to_cmd();
Xvoid my_waddstr(), my_winsch(), my_wdelch(), case_lower(), case_upper();
Xvoid edit_line(), openrd(), openwr();
X
X#ifdef SYSVcurses
X    struct termio tio, tin;
X#else
X    struct tchars tco, tcn;
X#endif
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    register i;
X    int slen, pid;
X    unsigned msize;
X
X    signal(SIGINT,die_normal);      /* die cleanly */
X/*
X * get the shell process id (pid) to match $$ in the = alias
X */
X
X    pid = getppid();
X    sprintf(hfile,"/tmp/eh%d",pid);
X    sprintf(cfile,"/tmp/ec%d",pid);
X    openrd(hfile);
X/*
X * read the history lines into the hist[] array,
X * previous mced invocation commands (ie. "=")are not copied, once
X * the command is read into cstr the newline is replaced with '\0'
X * and then it is copied into hist[last_hline]
X */
X    for (last_hline = 0; fgets(cstr, (MAX_CH), fptr) != NULL;)
X    {
X        if (cstr[0] != '=') /* "=" must be used in the alias for this to work*/
X	{
X	    slen = strlen(cstr);
X	    if (slen > MIN_CMD_LEN)
X	    {
X	    	msize = (unsigned) (slen * sizeof(char));
X	    	cstr[slen - 1] = '\0';
X		hist[last_hline] = (char *) malloc(msize);
X		strcpy(hist[last_hline], cstr);
X		++last_hline;
X	    }
X	}
X    }
X    --last_hline;
X    cur_cmd = last_hline;
X/*
X * close and delete history temp file
X */
X    fclose(fptr);
X    unlink(hfile);
X
X/*
X * check for existence of history before going on
X */
X    if (last_hline < 0)
X    {
X	fprintf(stderr,"No valid history\n");
X	die_normal();
X    }
X
X/*
X * copy search string from command line
X */
X    if (argc > 1)
X    {
X	strcpy(sstr, argv[1]);
X	if (argc > 2)
X	{
X	    for (i = 3; i <= argc; i++)
X	    {
X		strcat(sstr, spc);
X		strcat(sstr, argv[i - 1]);
X	    }
X	}
X	cur_cmd = index_cmd(cur_cmd,-1);
X    }
X    strcpy(cstr, hist[cur_cmd]);
X/*
X * edit command and execute
X */
X    edit_cmd();
X    openwr(cfile);
X    fprintf(fptr, "%s\n", vern);
X    fprintf(fptr, "%s\n", cstr);
X    fclose(fptr);
X    printf("\n");
X}
X
X
Xint index_cmd(tcur_cmd,direc)
Xint tcur_cmd, direc;
X{
X    register i, slen;
X    slen = strlen(sstr);
X    for (i = 0; i <= last_hline; i++)
X    {
X	if (tcur_cmd < 0) tcur_cmd = last_hline;
X	if (tcur_cmd > last_hline) tcur_cmd = 0;
X	if (strncmp(hist[tcur_cmd], sstr, slen) == 0)
X	    return(tcur_cmd);
X	tcur_cmd += direc;
X    }
X    return(cur_cmd);
X}
X
X
Xvoid openrd(fname)
Xchar fname[];
X{
X    int fd;
X    fd = open(fname, 0);
X    if (fd == (int) -1)
X    {
X	perror(fname);
X	fprintf(stderr,"To execute mced use \"=\" with the following alias:\n");
X	fprintf(stderr,"alias = \"history -h 50 >\\! /tmp/eh$$;mced \\!*;");
X	fprintf(stderr,"source -h /tmp/ec$$;source /tmp/ec$$;/bin/rm /tmp/ec$$\"\n");
X	die_normal();
X    }
X    else
X    {
X	close(fd);
X	fptr = fopen(fname, "r");
X    }
X}
X
X
Xvoid openwr(fname)
Xchar fname[];
X{
X    if ((fptr = fopen(fname, "w")) == NULL)
X    {
X	perror(fname);
X	exit(0);
X    }
X}
X
X
XSIGTYPE die_normal()
X{
X    signal(SIGINT,SIG_IGN);
X    signal(SIGINT,die_normal);
X    openwr(cfile);
X    fprintf(fptr, "%s\n", vern);
X    fclose(fptr);
X    exit(0);
X}
X
X
Xvoid add_hline()	/*add next hist line on delete at EOL*/
X{
X    if(cur_cmd < last_hline)
X    {
X	++cur_cmd;
X	savex_pos = x_pos;
X	my_waddstr(hist[cur_cmd]);	
X	x_pos = savex_pos;
X	my_wmove(x_pos);
X    }
X    else
X	beep();
X}
X
X
Xvoid my_wmove(i)
Xint i;
X{
X    int which_line;
X    which_line = ((i < COLS) ? 0 : 1);
X    wmove(win,which_line,(i - which_line * COLS));
X}
X
X
Xvoid my_winsch(in_char)
Xint in_char;
X{
X    int wrap_char;
X    if ((xend + 1) >= (COLS * 2))
X    {
X	beep();
X    }
X    else if(xend > COLS && x_pos < COLS)	/* wraparound */
X    {
X	++xend;
X	wmove(win,0,COLS-1);
X	wrap_char = winch(win);
X	wmove(win,1,0);
X	winsch(win,wrap_char);
X	my_wmove(x_pos);
X	winsch(win,in_char);
X	my_wmove(++x_pos);
X    }
X    else
X    {
X	++xend;
X	winsch(win,in_char);
X	my_wmove(++x_pos);
X    }
X}
X
X
Xvoid my_wdelch()
X{
X    int wrap_char;
X    --xend;
X    if(xend >= COLS && x_pos < COLS)	/* wraparound */
X    {
X	wmove(win,1,0);
X	wrap_char = winch(win);
X	wdelch(win);
X	my_wmove(x_pos);
X	wdelch(win);
X	wmove(win,0,COLS-1);
X	winsch(win,wrap_char);
X	my_wmove(x_pos);
X    }
X    else
X    {
X	wdelch(win);
X    }
X}
X
X
Xvoid my_waddstr(strng)
Xchar strng[];
X{
X    register i, len;
X    len = strlen(strng);
X    for(i=0;i < len;i++)
X    {
X	my_winsch((int)strng[i]);
X    }
X}
X
X
Xvoid cmd_to_win()	/*write prompt and command to window*/
X{
X    my_wmove(0);
X    wclear(win);
X    waddstr(win,prompt);
X    xend = x_pos = xbeg;
X    my_waddstr(cstr);
X}
X
X
Xvoid win_to_cmd()	/*get the edited line from the window*/
X{
X    int i;
X    my_wmove(xbeg);
X    for(i=0;i <= (xend - xbeg);i++)
X    {
X	my_wmove(xbeg+i);
X	cstr[i] = winch(win);
X    }
X    cstr[xend - xbeg] = '\0';
X}
X
X
Xvoid case_upper()
X{
X    int i;
X    for(i=0;i <= (xend - xbeg);i++)
X    {
X	if(islower(cstr[i]))
X	    cstr[i] = toupper(cstr[i]);
X    }
X}
X
X
Xvoid case_lower()
X{
X    int i;
X    for(i=0;i <= (xend - xbeg);i++)
X    {
X	if(isupper(cstr[i]))
X	    cstr[i] = tolower(cstr[i]);
X    }
X}
X
X
XSIGTYPE die_curses()	/* interrupt signal */
X{
X    signal(SIGINT,SIG_IGN);
X    signal(SIGINT,die_curses);
X#ifdef SYSVcurses 
X    if(ioctl(0, TCSETA, &tio) != 0)
X	perror("ioctl");
X#else 
X    if(ioctl(0, TIOCSETC, &tco) != 0)
X	perror("ioctl");
X#endif
X    nocbreak();
X    echo();
X    endwin();
X    openwr(cfile);
X    fprintf(fptr, "%s\n", vern);
X    fclose(fptr);
X    printf("\n");
X    exit(0);
X}
X
X
Xvoid eat_white(direc,destruc)	/*eat up initial whitespace*/
Xint direc,destruc;
X{
X    int lim;
X    if(direc == -1) 
X	lim = xbeg;
X    else
X	lim = xend;
X    if(destruc == NO)
X    {
X	for(;isspace(winch(win));)
X	{
X	    if(x_pos != lim)
X	    {
X		x_pos += direc;
X		my_wmove(x_pos);
X	    }
X	    else
X		return;
X	}
X	return;
X    }
X    else	/* actually delete */
X    {
X	for(;isspace(winch(win));)
X	{
X	    if(x_pos != lim)
X	    {
X		my_wdelch();
X		x_pos += direc;
X		my_wmove(x_pos);
X		if(!(isspace(winch(win))) && direc == 1)
X		    my_wmove(--x_pos);
X	    }
X	    else
X		return;
X	}
X	return;
X    }
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'emacs_edit.c'" '(7488 characters)'
if test -f 'emacs_edit.c'
then
	echo shar: will not over-write existing file "'emacs_edit.c'"
else
sed 's/^X//' << \SHAR_EOF > 'emacs_edit.c'
X/*
X * This software is Copyright (c) 1991 by Andy Knight
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 *		Andy Knight
X *		aknight@ourgang.prime.com
X */
X
X#include "config.h"
X
Xextern char *hist[], cstr[];
Xextern int xbeg, cur_cmd, last_hline, pwolfe_getch();
Xextern int edit_mode, x_pos, savex_pos, xend;
X
Xextern void my_wmove(), add_hline(), cmd_to_win(), win_to_cmd();
Xextern void my_waddstr(), my_winsch(), case_upper();
Xextern void my_wdelch(), case_lower(), eat_white();
Xextern SIGTYPE die_curses(), die_normal();
Xextern WINDOW *win;
X
X#ifdef SYSVcurses
X    extern struct termio tio, tin;
X#else
X    extern struct tchars tco, tcn;
X#endif
X
X
Xedit_cmd()
X{
X    int edch, tch, i, tmp_cmd;
X    fprintf(stdout,"\n");
X    if(initscr() == ERR)
X    {
X	fprintf(stderr, "Curses won't initialize - help!\n");
X	die_normal();
X    }
X    signal(SIGINT,die_curses);      /* die cleanly */
X    cbreak();
X    noecho();
X#ifdef SYSVcurses
X    win = newwin(2,COLS,0,0);
X#else
X    clearok(curscr, FALSE);	/* SYSV curses clears it anyway ;-( */
X    win = newwin(2,COLS,LINES-2,0);
X#endif
X
X    cmd_to_win();
X    wrefresh(win);
X
X#ifdef SYSVcurses		/* disable STOP/START (CTRL-S) */
X    if(ioctl(0, TCGETA, &tio) != 0)
X	perror("ioctl");
X    tin = tio;
X    tin.c_iflag &= ~IXON;
X    if(ioctl(0, TCSETA, &tin) != 0)
X	perror("ioctl");
X#else
X    if(ioctl(0, TIOCGETC, &tco) != 0)
X	perror("ioctl");
X    tcn = tco;
X    tcn.t_stopc = -1;
X    if(ioctl(0, TIOCSETC, &tcn) != 0)
X	perror("ioctl");
X#endif
X    edit_mode = EMACS_MODE;
X    for (; (edch = pwolfe_getch(win)) != '\n';)
X    {
X	switch (edch)
X	{
X	    case ControlU:
X	    case Sun_R3:
X		wclear(win);
X		wrefresh(win);
X		die_curses();
X		break;
X	    case ControlW:	/*Delete word backwards*/
X	    case EscapeDEL:
X	    case Sun_R1:
X		if(x_pos > xbeg)
X		{
X		    my_wmove(--x_pos);
X		    eat_white(-1,YES);
X		    for(;!(isspace(winch(win))) && (x_pos >= xbeg);)
X		    {
X			my_wdelch();
X			if(x_pos == xbeg)
X			    break;
X			else
X			    my_wmove(--x_pos);
X		    }
X		    if(x_pos > xbeg)
X		    	my_wmove(++x_pos);
X		}
X		else
X		    beep();
X		break;
X	    case EscapeB:	/*move back to beginning of previous word*/
X	    case Sun_R4:
X		if(x_pos > xbeg)
X		{
X		    my_wmove(--x_pos);
X		    eat_white(-1,NO);
X		    for(;!(isspace(winch(win))) && (x_pos > xbeg);)
X		    {
X		    	my_wmove(--x_pos);
X		    }
X		    if(x_pos > xbeg)
X		    	my_wmove(++x_pos);
X		}
X		else
X		    beep();
X		break;
X	    case EscapeD:	/*delete forward to beginning of next word*/
X		if(x_pos < xend)
X		{
X		    eat_white(1,YES);
X		    for(;!(isspace(winch(win))) && (x_pos < xend);)
X		    {
X			my_wdelch();
X		    }
X		}
X		else
X		    add_hline();
X		break;
X	    case EscapeF:	/*move forward to beginning of next word*/
X	    case Sun_R6:
X		if(x_pos < xend)
X		{
X		    eat_white(1,NO);
X		    for(;!(isspace(winch(win))) && (x_pos < xend);)
X		    {
X		    	my_wmove(++x_pos);
X		    }
X		}
X		else
X		    beep();
X		break;
X	    case ControlL:	/* redraw win */
X		savex_pos = x_pos;
X		win_to_cmd();
X		wclear(win);
X		wrefresh(win);
X		cmd_to_win();
X		x_pos = savex_pos;
X		my_wmove(x_pos);
X		break;
X	    case BackSpace:
X	    case KEY_LEFT:
X	    case ControlB:
X	    case KEY_BACKSPACE:
X	    case Sun_R10:
X		if(x_pos > xbeg)
X		    my_wmove(--x_pos);
X		else
X		    beep();
X		break;
X	    case EscapeM:	/* move cursor to middle */
X	    case Sun_R11:
X		x_pos = xbeg + (xend-xbeg)/2;
X		my_wmove(x_pos);
X		break;
X	    case ControlF:
X	    case KEY_RIGHT:
X	    case Sun_R12:
X		if(x_pos < xend)
X		    my_wmove(++x_pos);
X		else
X		    beep();
X		break;
X	    case KEY_UP:	/* move upward in history list */
X	    case ControlP:
X	    case Sun_R8:
X		if(cur_cmd > 0)
X		{
X		    --cur_cmd;
X		    strcpy(cstr, hist[cur_cmd]);
X		    wclear(win);
X		    cmd_to_win();
X		    my_wmove(x_pos);
X		}
X		else
X		    beep();
X		break;
X	    case KEY_DOWN:	/* move downward in history list */
X	    case ControlN:
X	    case Sun_R14:
X		if(cur_cmd < last_hline)
X		{
X		    ++cur_cmd;
X		    strcpy(cstr, hist[cur_cmd]);
X		    wclear(win);
X		    cmd_to_win();
X		    my_wmove(x_pos);
X		}
X		else
X		    beep();
X		break;
X	    case ControlR:	/*search history list backwards*/
X		if((tmp_cmd = index_cmd(cur_cmd - 1,-1)) != cur_cmd)
X		{
X		    cur_cmd = tmp_cmd;
X		    strcpy(cstr, hist[cur_cmd]);
X		    wclear(win);
X		    cmd_to_win();
X		    my_wmove(x_pos);
X		}
X		else
X		    beep();
X		break;
X	    case ControlS:	/*search history list forwards*/
X		if((tmp_cmd = index_cmd(cur_cmd + 1,1)) != cur_cmd)
X		{
X		    cur_cmd = tmp_cmd;
X		    strcpy(cstr, hist[cur_cmd]);
X		    wclear(win);
X		    cmd_to_win();
X		    my_wmove(x_pos);
X		}
X		else
X		    beep();
X		break;
X	    case ControlA:
X	    case Sun_R7:
X		my_wmove(xbeg);
X		x_pos = xbeg;
X		break;
X	    case ControlE:
X	    case Sun_R13:
X	    case Sun_R9:
X		my_wmove(xend);
X		x_pos = xend;
X		break;
X	    case ControlK:	/*delete to end of line*/
X		if(x_pos < xend)
X		{
X		    for(i = xend; i > x_pos; i--)
X		    {
X			my_wdelch();
X		    }
X		}
X		else
X                    add_hline();
X		break;
X	    case Delete:	/*delete character before cursor*/
X		if(x_pos > xbeg)
X		{
X		    my_wmove(--x_pos);
X		    my_wdelch();
X		}
X		else
X		    beep();
X		break;
X	    case ControlD:	/*delete current character*/
X		if(x_pos < xend)
X		{
X		    my_wdelch();
X		}
X		else
X		    add_hline();
X		break;
X	    case EscapeL:	/*lower case whole command*/
X	    case Sun_R2:
X		savex_pos = x_pos;
X		win_to_cmd();
X		case_lower();
X		cmd_to_win();
X		x_pos = savex_pos;
X		my_wmove(x_pos);
X		break;
X	    case EscapeU:	/*upper case whole command*/
X		savex_pos = x_pos;
X		win_to_cmd();
X		case_upper();
X		cmd_to_win();
X		x_pos = savex_pos;
X		my_wmove(x_pos);
X		break;
X	    case EscapeC:	/* toggle case of current character */
X	    case Sun_R5:
X		tch = winch(win);
X		if(isupper(tch))
X		{
X		    wdelch(win);
X		    winsch(win,tolower(tch));
X		}
X		else if(islower(tch))
X		{
X		    wdelch(win);
X		    winsch(win,toupper(tch));
X		}
X		if(x_pos < xend)
X		    my_wmove(++x_pos);
X		break;
X	    case ControlT:	/* transpose characters */
X		if(x_pos > xbeg && x_pos != COLS)
X		{
X		    if(x_pos == xend)
X		    	my_wmove(--x_pos);
X		    my_wmove(--x_pos);
X		    tch = winch(win);
X		    wdelch(win);
X		    my_wmove(++x_pos);
X		    winsch(win,tch);
X		    my_wmove(++x_pos);
X		}
X		else
X		    beep();
X		break;
X	    default:		/* insert character */
X		if(isprint(edch))
X		{
X		    my_winsch(edch);
X		}
X		else
X		    beep();
X		break;
X	}
X	wrefresh(win);
X	if (xend == xbeg)
X	    die_curses();
X    }
X    win_to_cmd();
X#ifdef SYSVcurses	/* reset tty */
X    if(ioctl(0, TCSETA, &tio) != 0)
X	perror("ioctl");
X#else
X    if(ioctl(0, TIOCSETC, &tco) != 0)
X	perror("ioctl");
X#endif
X    nocbreak();
X    echo();
X    endwin();
X    return;	/* finished, execute command */
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'getch.c'" '(2907 characters)'
if test -f 'getch.c'
then
	echo shar: will not over-write existing file "'getch.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getch.c'
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/*****************************************************************
X * Modifications made by aknight to support emacs escape functions,
X * Sun R function keys and vi escape, wiped out un-needed stuff 
X * for vt120, vt220
X *****************************************************************/
X
X#include "config.h"
X
X#define NORMAL	100
X#define ESCAPE	200
X#define FKEY	300
X
Xextern int edit_mode;
X
X
Xint
Xpwolfe_getch (winptr)
XWINDOW *winptr;
X{
Xchar c;
Xint state = NORMAL;
Xint fkeycount = 0;
X
Xwhile (1) {
X	c = wgetch (winptr);	/* call the real getch() */
X	switch (state) {
X
X	case FKEY:
X		switch (c) {
X
X		/* numeric function keys */
X		case '0': case '1': case '2': case '3': case '4':
X		case '5': case '6': case '7': case '8': case '9':
X			fkeycount = (fkeycount * 10) + (c - '0');
X			break;
X		
X/* lines deleted, aknight*/
X
X		case 'A':	return KEY_UP;
X		case 'B':	return KEY_DOWN;
X		case 'C':	return KEY_RIGHT;
X		case 'D':	return KEY_LEFT;
X
X/* added by aknight, R1 - R15 keys on Sun*/
X		case 'z':
X			return fkeycount + 1000;
X
X		default:
X			beep();
X			state = NORMAL;
X			}
X		break;
X
X	case ESCAPE:
X		switch (c) {
X		case 'O':
X		case '[':
X			state = FKEY;
X			fkeycount = 0;
X			break;
X/* added by aknight, Escape - key functions */
X		case 'f':
X			return EscapeF;
X		case 'b':
X			return EscapeB;
X		case 'd':
X			return EscapeD;
X		case 'c':
X			return EscapeC;
X		case 'l':
X			return EscapeL;
X		case 'u':
X			return EscapeU;
X		case 'm':
X			return EscapeM;
X		case Delete:
X			return EscapeDEL;
X
X		default:
X			state = NORMAL;
X			beep();
X			}
X		break;
X
X	default:
X		switch (c) {
X		case Escape:
X			state = ESCAPE;
X/* added by aknight for possible future use*/
X			if(edit_mode == VI_MODE)
X				return Escape;
X			break;
X
X		case CSI:
X			state = FKEY;
X			fkeycount = 0;
X			break;
X
X		default:
X			return (c);
X			}
X		}
X	}
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(971 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X#	Makefile for mced
X#
X#	To install this utility do the following:
X#	    1) Fill in the make variables, below.
X#	    2) Type "make install" on the command line.
X#	    3) Type "make clean" on the command line to clean up after install.
X#
X#
X#
X# definitions for EMACS EDIT mode:
XLDFLAGS = -lcurses -ltermcap
XOBJECTS = main.o emacs_edit.o getch.o
X#
X# definitions for VI EDIT mode: #not implemented!(7/91)#
X#LDFLAGS = -lcurses -ltermcap
X#OBJECTS = main.o vi_edit.o getch.o
X#
X# Where to stick the executable on install
XBINDIR=/usr/local/bin
X#
X# Where to stick the man page on install
XMANDIR=/usr/local/man/man1
X##
XCFLAGS = -O	## do not use optimizer on SunOS 4.0.3S ##
X#CC = /usr/5bin/cc
X
Xmced : $(OBJECTS)
X	$(CC) $(TARGET_ARCH) $(CFLAGS) $(OBJECTS) -o $@ $(LDFLAGS)
X
Xman : mced.1
X	cat mced.1 | nroff -man | more
X
Xinstall : mced
X	install -s -c mced $(BINDIR)
X	install -m 644 mced.1 $(MANDIR)/mced.1
X	ln -s $(MANDIR)/mced.1 $(MANDIR)/=.1
X
Xclean : 
X	rm -f mced core $(OBJECTS)
X
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'README'" '(1952 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XDESCRIPTION:
X
XMcEd is a utility which allows you to browse, edit and execute
Xcommands from your C-shell history list. It is not a shell itself, 
Xbut it executes the commands in your current shell as if you had 
Xtyped them in.  The editing functions are based on gnuemacs, 
Xwith a vi mode possibly sometime in the future. 
X	
X
XUSAGE:
X
XAfter making the executable, Put the following
Xsomewhat lengthly :-) alias for "=" in your .cshrc:
X 
Xalias = "history -h 50 >\! /tmp/eh$$;mced \!*;
Xsource -h /tmp/ec$$;source /tmp/ec$$;/bin/rm /tmp/ec$$"
X(one line)
X
X``='' now copies the commands in your history list into memory
Xand allows you to browse and edit, <CR> executes the command.
XSee the man page for details on editing.
X
XIf possible, avoid using SYSV curses. If you have no choice,
Xyou must put #define SYSVcurses somewhere near the top of config.h.
X
X
X/*
X * This software is Copyright (c) 1991 by Andy Knight
X * (getch.c and getch.h 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 *              Andy Knight
X *              aknight@ourgang.prime.com
X */
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'mced.1'" '(2719 characters)'
if test -f 'mced.1'
then
	echo shar: will not over-write existing file "'mced.1'"
else
sed 's/^X//' << \SHAR_EOF > 'mced.1'
X.TH McEd 1
X.SH NAME
Xmced \- McKnight's unix history Command line Editor
X.SH SYNOPSIS
X.B "= [string]"
X.SH DESCRIPTION
X.I "mced"
Xis a utility giving the C-shell added history flexibility with 
Xbrowsing and editing functions for commands in the history list.
X.I "mced"
Xis driven by an alias which should be defined as follows: 
X
Xalias = "history -h 99 >\\! /tmp/eh$$;mced \\!*;source -h /tmp/ec$$;
Xsource /tmp/ec$$;/bin/rm /tmp/ec$$"
X
X``='' now copies the commands in your history list into memory
Xand positions you at the most recent command, or ``= <string>''
Xpositions you at the first command that begins with <string>.
XThe command is now edited emacs style, and executed by a <CR>,
XCTRL-U and CTRL-W are used to cancel and delete just as in the C-shell.
XShort commands are filtered out of the history list, the
Xminimum length is set with MIN_CMD_LEN, defined in config.h.
XIf you use tcsh, ksh, bash etc. you will probably not have much use for 
Xmced, as these shells have similar history editing built-in.
X
X.SH MOVING AROUND IN THE HISTORY LIST
XThe up and down arrow keys index you through the history list,
Xif <string> is used on the command line, CTRL-R and CTRL-S search for 
Xthe next occurrence. 
X
X.SH 
X
X.SH CURSOR MOVEMENT
XThe standard emacs control and escape characters 
X(CTRL-A, CTRL-B, CTRL-E, CTRL-F, ESC-B, ESC-F) 
Xand arrow keys are used to move around on the command line.
XESC-M moves to the middle of the command line.
X.SH EDITING SUMMARY
X.I "mced"
X.RS +.6i
X.nf
X.ta 2.5i
X.sp
XEditing functions
X.sp
Xbeginning of line	CTRL-A
Xbackward char		CTRL-B
Xdelete char		CTRL-D
Xend of line		CTRL-E
Xforward char    	CTRL-F
Xkill to end of line	CTRL-K
Xredraw command		CTRL-L
Xdown history		CTRL-N
Xup history		CTRL-P
Xsearch backward		CTRL-R
Xsearch forward		CTRL-S
Xtranspose characters	CTRL-T
Xbackward delete char	Delete
Xbackward delete word	ESC-Delete, CTRL-W
Xbackward word		ESC-B
Xchange case character	ESC-C **
Xdelete word forward	ESC-D
Xforward word		ESC-F
Xdowncase command	ESC-L **
Xmiddle cursor		ESC-M **
Xupcase command		ESC-U **
Xexecute command		<CR>
Xquit			CTRL-U, CTRL-C
X
X** Function behaves differently than in gnuemacs
X
XLines may be joined together by doing a delete at the end
Xof the command line.
X
XKey mappings for sun R function keys around the arrow keys
Xare defined to do some cursor movement and other functions,
Xsee source for details (emacs_edit.c)
X
XThere is currently no undo function.
X
XThe window for the command always occupies the last two lines
Xon your screen, the command length cannot go beyond this. 
X
X.SH AUTHOR
XAndy (Mc)Knight, CV;
Xaknight@ourgang.prime.com
X.sp
Xgetch.c and getch.h were stolen
Xfrom scan, written by Patrick J. Wolfe
X.SH SEE ALSO
X.BR tcsh(1),
X.BR gnuemacs(1),
X.BR csh_builtins(1)
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'getch.h'" '(2932 characters)'
if test -f 'getch.h'
then
	echo shar: will not over-write existing file "'getch.h'"
else
sed 's/^X//' << \SHAR_EOF > 'getch.h'
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/*************************************************************
X * Modifications made by aknight to add definitions for escape
X * functions and Sun R function keys, also wiped out sections
X * for SYSVcurses, VT120, VT220
X ************************************************************/
X#ifndef SYSVcurses
X/* System V curses key names and codes returned by getch */
X#define KEY_DOWN        0402
X#define KEY_UP          0403
X#define KEY_LEFT        0404
X#define KEY_RIGHT       0405
X#define KEY_BACKSPACE   0407
X#endif /* NOT SYSVcurses */
X
X/* ascii control codes */
X#define ControlA	001
X#define ControlB	002
X#define ControlC	003
X#define ControlD	004
X#define ControlE	005
X#define ControlF	006
X#define ControlG	007
X#define ControlH	010
X#define BackSpace	010
X#define ControlI	011
X#define Tab		011
X#define ControlJ	012
X#define LineFeed	012
X#define ControlK	013
X#define ControlL	014
X#define ControlM	015
X#define Return		015
X#define ControlN	016
X#define ControlO	017
X#define ControlP	020
X#define ControlQ	021
X#define ControlR	022
X#define ControlS	023
X#define ControlT	024
X#define ControlU	025
X#define ControlV	026
X#define ControlW	027
X#define ControlX	030
X#define ControlY	031
X#define ControlZ	032
X#define Escape		033
X#define Control[	033
X#define Delete		0177
X#define Del		0177
X#define CSI		0233
X
X/* added by aknight */
X
X#define EscapeD		1001
X#define EscapeF		1002
X#define EscapeB		1003
X#define EscapeDEL	1004
X#define EscapeM		1005
X#define EscapeC		1006
X#define EscapeU		1007
X#define EscapeL		1008
X
X#define Sun_R1		1208
X#define Sun_R2		1209
X#define Sun_R3		1210
X#define Sun_R4		1211
X#define Sun_R5		1212
X#define Sun_R6		1213
X#define Sun_R7		1214
X#define Sun_R8		1215
X#define Sun_R9		1216
X#define Sun_R10		1217
X#define Sun_R11		1218
X#define Sun_R12		1219
X#define Sun_R13		1220
X#define Sun_R14		1221
X#define Sun_R15		1222
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'config.h'" '(1224 characters)'
if test -f 'config.h'
then
	echo shar: will not over-write existing file "'config.h'"
else
sed 's/^X//' << \SHAR_EOF > 'config.h'
X/*
X *	configuration file for mced
X */
X
X#define MIN_CMD_LEN 5   /* Min number of
X                           characters in command
X                           line to be considered
X                           worthy */
X
X#define MAX_CH 300      /* Max number of
X                           characters in command
X                           line */
X
X#define MAX_H_READ 250  /* Max number of history
X                           lines possible to
X                           read */
X
X
X/*
X * the following is from config.h for scan by Patrick J. Wolfe:
X */
X
X/*
X *      Define "SIGTYPE" to the type of the value returned by the "signal"
X *      system call.  On BSD 4.2 systems, it's "void".  On BSD 4.3 and SVR3
X *      systems, it's "int".
X *
X *	Define "SYSVcurses" if your system has System V curses.
X */
X
X#define SIGTYPE int
X
X#define beep()  fprintf (stderr, "\007");
X
X#define YES 1
X#define NO  0
X 
X#define EMACS_MODE 1	/* dont edit these, see the Makefile */
X#define VI_MODE 0	/* to select emacs mode or vi mode     */
X
X
X#include "getch.h"
X
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <signal.h>
X#include <curses.h>
X#include <errno.h>
X
X#ifdef SYSVcurses
X#include <termio.h>
X#else
X#include <sys/ioctl.h>
X#endif
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
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.


