[comp.sources.misc] memacs 3.8i 5 of 11

allbery@ncoast.UUCP (06/18/87)

:
#!/bin/sh
# shar+ created from directory /usr2/davidsen/emacs38i
# 13:42 on Thu Jun 11, 1987 by davidsen
echo 'x - hp110.c (text)'
sed << 'E!O!F' 's/^X//' > hp110.c
X/*
X *	HP110:	Hewlett Packard 110 Screen Driver
X */
X
X#define	termdef	1			/* don't define "term" external */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if     HP110
X
X#define NROW    16                      /* Screen size.                 */
X#define NCOL    80                      /* Edit if you want to.         */
X#define	NPAUSE	100			/* # times thru update to pause */
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define BEL     0x07                    /* BEL character.               */
X#define ESC     0x1B                    /* ESC character.               */
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern  int     h110move();
Xextern  int     h110eeol();
Xextern  int     h110eeop();
Xextern  int     h110beep();
Xextern  int     h110open();
Xextern	int	h110rev();
Xextern	int	h110cres();
Xextern	int	h110close();
Xextern	int	h110kopen();
Xextern	int	h110kclose();
X
X#if	COLOR
Xextern	int	h110fcol();
Xextern	int	h110bcol();
X
Xint	cfcolor = -1;		/* current forground color */
Xint	cbcolor = -1;		/* current background color */
X#endif
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM    term    = {
X	NROW-1,
X        NROW-1,
X        NCOL,
X        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        h110open,
X        h110close,
X	h110kopen,
X	h110kclose,
X        ttgetc,
X        ttputc,
X        ttflush,
X        h110move,
X        h110eeol,
X        h110eeop,
X        h110beep,
X	h110rev,
X	h110cres
X#if	COLOR
X	, h110fcol,
X	h110bcol
X#endif
X};
X
X#if	COLOR
Xh110fcol(color)		/* set the current output color */
X
Xint color;	/* color to set */
X
X{
X	if (color == cfcolor)
X		return;
X	ttputc(ESC);
X	ttputc('[');
X	h110parm(color+30);
X	ttputc('m');
X	cfcolor = color;
X}
X
Xh110bcol(color)		/* set the current background color */
X
Xint color;	/* color to set */
X
X{
X	if (color == cbcolor)
X		return;
X	ttputc(ESC);
X	ttputc('[');
X	h110parm(color+40);
X	ttputc('m');
X        cbcolor = color;
X}
X#endif
X
Xh110move(row, col)
X{
X        ttputc(ESC);
X        ttputc('[');
X        h110parm(row+1);
X        ttputc(';');
X        h110parm(col+1);
X        ttputc('H');
X}
X
Xh110eeol()
X{
X        ttputc(ESC);
X        ttputc('[');
X	ttputc('0');
X        ttputc('K');
X}
X
Xh110eeop()
X{
X#if	COLOR
X	h110fcol(gfcolor);
X	h110bcol(gbcolor);
X#endif
X        ttputc(ESC);
X        ttputc('[');
X	ttputc('0');
X        ttputc('J');
X}
X
Xh110rev(state)		/* change reverse video state */
X
Xint state;	/* TRUE = reverse, FALSE = normal */
X
X{
X#if	COLOR
X	int ftmp, btmp;		/* temporaries for colors */
X#endif
X
X	ttputc(ESC);
X	ttputc('[');
X	ttputc(state ? '7': '0');
X	ttputc('m');
X#if	COLOR
X	if (state == FALSE) {
X		ftmp = cfcolor;
X		btmp = cbcolor;
X		cfcolor = -1;
X		cbcolor = -1;
X		h110fcol(ftmp);
X		h110bcol(btmp);
X	}
X#endif
X}
X
Xh110cres()	/* change screen resolution */
X
X{
X	return(TRUE);
X}
X
Xspal()		/* change pallette register */
X
X{
X	/*   not here */
X}
X
Xh110beep()
X{
X        ttputc(BEL);
X        ttflush();
X}
X
Xh110parm(n)
Xregister int    n;
X{
X        register int q,r;
X
X        q = n/10;
X        if (q != 0) {
X		r = q/10;
X		if (r != 0) {
X			ttputc((r%10)+'0');
X		}
X		ttputc((q%10) + '0');
X        }
X        ttputc((n%10) + '0');
X}
X
Xh110open()
X{
X	strcpy(sres, "15LINE");
X	revexist = TRUE;
X        ttopen();
X}
X
Xh110close()
X
X{
X#if	COLOR
X	h110fcol(7);
X	h110bcol(0);
X#endif
X	ttclose();
X}
X
Xh110kopen()
X
X{
X}
X
Xh110kclose()
X
X{
X}
X
X#if	FLABEL
Xfnclabel(f, n)		/* label a function key */
X
Xint f,n;	/* default flag, numeric argument [unused] */
X
X{
X	/* on machines with no function keys...don't bother */
X	return(TRUE);
X}
X#endif
X#else
Xh110hello()
X{
X}
X#endif
E!O!F
newsize=`wc -c < hp110.c`
if [ $newsize -ne 3750 ]
then echo "File hp110.c was $newsize bytes, 3750 expected"
fi
echo 'x - hp150.c (text)'
sed << 'E!O!F' 's/^X//' > hp150.c
X/*
X * The routines in this file provide support for HP150 screens
X * and routines to access the Keyboard through KEYCODE mode.
X * It compiles into nothing if not an HP150 screen device.
X * added by Daniel Lawrence
X */
X
X#define	termdef	1			/* don't define "term" external */
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X#if     HP150
X
X#define NROW    24                      /* Screen size.                 */
X#define NCOL    80                      /* Edit if you want to.         */
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define	NPAUSE	15			/* # times thru update to pause */
X#define BEL     0x07                    /* BEL character.               */
X#define ESC     0x1B                    /* ESC character.               */
X
Xextern  int     openhp();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern	int	hpflush();
Xextern  int     closehp();
Xextern	int	hp15kopen();
Xextern	int	hp15kclose();
Xextern  int     hp15move();
Xextern  int     hp15eeol();
Xextern  int     hp15eeop();
Xextern  int     hp15beep();
Xextern	int	gethpkey();
Xextern	int	hp15rev();
Xextern	int	hp15cres();
X#if	COLOR
Xextern	int	hp15fcol();
Xextern	int	hp15bcol();
X#endif
X
X/* weird to ascii translation table */
X
Xchar trans[][2] = {
X	0x24,	9,	/* tab */
X	0x25,	13,	/* ret */
X	0x27,	8,	/* backspace */
X	0x30,	48,	/* zero */
X	0x31,	49,	/* one */
X	0x32,	50,	/* two */
X	0x33,	51,	/* three */
X	0x34,	52,	/* four */
X	0x35,	53,	/* five */
X	0x36,	54,	/* six */
X	0x37,	55,	/* seven */
X	0x38,	56,	/* eight */
X	0x39,	57,	/* nine */
X	0x50,	13,	/* enter */
X	0x54,	27,	/* break -> ESC */
X	0x55,	27,	/* esc */
X	0x58,	24,	/* stop -> ^X */
X	0x70,	45,	/* N-minus */
X	0x71,	42,	/* N-asterisk */
X	0x72,	43,	/* N-plus */
X	0x73,	47,	/* N-slash */
X	0x74,	44,	/* N-comma */
X	0x75,	13,	/* N-enter */
X	0x76,	9,	/* N-tab */
X	0x77,	46	/* N-period */
X};
X
X#define NTRANS	sizeof(trans) / 2
X
Xunion REGS r;		/* register set for bios and dos (AGIOS) calls */
Xint capslock = 0;	/* caps lock flag */
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM    term    = {
X	NROW-1,
X        NROW-1,
X        NCOL,
X        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X	openhp,
X        closehp,
X	hp15kopen,
X	hp15kclose,
X	gethpkey,
X        ttputc,
X        hpflush,
X        hp15move,
X        hp15eeol,
X        hp15eeop,
X        hp15beep,
X        hp15rev,
X        hp15cres
X#if	COLOR
X	, hp15fcol,
X	hp15bcol
X#endif
X};
X
Xhp15move(row, col)
X{
X        ttputc(ESC);
X        ttputc('&');
X        ttputc('a');
X        hp15parm(col);
X        ttputc('c');
X        hp15parm(row);
X        ttputc('R');
X}
X
Xhpflush()
X
X{
X
X}
X
Xhp15eeol()
X{
X        ttputc(ESC);
X        ttputc('K');
X}
X
Xhp15eeop()
X{
X        ttputc(ESC);
X        ttputc('J');
X}
X
Xhp15rev(status)		/* change the reverse video status */
X
Xint status;	/* TRUE = on, FALSE = off */
X
X{
X	ttputc(ESC);
X	ttputc('&');
X	ttputc('d');
X	ttputc((status != FALSE) ? 'B': '@');
X}
X
Xhp15cres()	/* change screen resolution */
X
X{
X	return(TRUE);
X}
X
Xspal()		/* change pallette register */
X
X{
X	/*   not here */
X}
X
Xhp15beep()
X{
X        ttputc(BEL);
X        ttflush();
X}
X
Xhp15parm(n)
Xregister int    n;
X{
X        register int    q;
X
X        q = n/10;
X        if (q != 0)
X                hp15parm(q);
X        ttputc((n%10) + '0');
X}
X
X#if	COLOR
Xhp15fcol()	/* we really can't do colors here, so just ignore it */
X{
X}
X
Xhp15bcol()	/* we really can't do colors here, so just ignore it */
X{
X}
X#endif
X
Xgethpkey()	/* get a key from the HP keyboard while in keycode mode */
X
X{
X	static int keepflag = 0;	/* kept ahead char flag */
X	static int keepchar = 0;	/* kept ehead flag */
X	int c;
X	int devid;			/* device ID */
X	int ctype;			/* type of character gotten */
X	int shiftb;			/* state of shift keys */
X	int i;
X	
X	/* if we are in an extended char sequence, finish it */
X	if (keepflag != 0) {
X		keepflag = 0;
X		return(keepchar);
X	}
X
X	/* grab the next 4 char sequence */
Xnext:	shiftb = ttgetc();
X	devid = ttgetc();
X	c = ttgetc();
X	ttgetc();		/* skip null byte */
X	
X	/* make sure we are from the keyboard */
X	if (devid != 192)
X		goto next;
X
X	/* if normal ascii, return it */
X	if ((shiftb & 0x80) == 0) {
X		if (capslock && c >= 'a' && c <= 'z')
X			c -= 32;
X		return(c);
X	}
X
X	/* check specifically for the caps lock key */
X	if (c == 0x56) {
X		capslock = ~capslock;
X		goto next;
X	}
X
X	/* check to see if it needs translation */
X	for (i=0; i < NTRANS; i++)
X		if (trans[i][0] == c)
X			return((int)trans[i][1]);
X
X	/* other wise, shove it in the keep char and return the leadin code */
X	keepchar = c;
X	keepflag = 1;
X	return(0);
X}
X
Xopenhp()		/* open the HP150 screen for input */
X
X{
X	strcpy(sres, "NORMAL");
X	revexist = TRUE;
X}
X
Xclosehp()		/* close the HP150 screen for input */
X
X{
X}
X
Xhp15kopen()		/* open the HP150 keyboard for input */
X
X{
X	/* define key charectoristics with AGIOS call (0, 40) */
X	defkey();
X
X	/* Turn on RAW mode with MSDOS call 44h */
X	rawon();
X
X	/* Turn off Control-C checking  MS-DOS 33h */
X	ckeyoff();
X
X	/* Turn on keycode mode with AGIOS call (0,43) */
X	keycon();
X
X	/* display the application softkey labels */
X	dsplbls();
X}
X
Xhp15kclose()		/* close the HP150 keyboard for input */
X
X{
X	/* define key charectoristics with AGIOS call (0, 40) */
X	undefkey();
X	
X	/* Turn off RAW mode with MSDOS call 44h */
X	rawoff();
X
X	/* Turn on Control-C checking  MS-DOS 33h */
X	ckeyon();
X
X	/* Turn off keycode mode with AGIOS call (0,43) */
X	keycoff();
X}
X
Xrawon()		/* put the HP150 keyboard into RAW mode */
X
X{
X	/* get the IO control info */
X
X	r.x.ax = 0x4400;	/* IO ctrl get device information */
X	r.x.bx = 0x0001;	/* File handle; 1 for console */
X	intdos(&r, &r);		/* go fer it */
X
X	r.h.dh = 0;		/* clear high byte for put */
X	r.h.dl |= 0x20;		/* set raw bit */
X
X	/* and put it back */
X
X	r.x.ax = 0x4401;	/* IO ctrl put device information */
X	r.x.bx = 0x0001;	/* File handle; 1 for console */
X	intdos(&r, &r);		/* go fer it */
X}
X
Xrawoff()	/* put the HP150 keyboard into COOKED mode */
X
X{
X	/* get the IO control info */
X
X	r.x.ax = 0x4400;	/* IO ctrl get device information */
X	r.x.bx = 0x0001;	/* File handle; 1 for console */
X	intdos(&r, &r);		/* go fer it */
X
X	r.h.dh = 0;		/* clear high byte for put */
X	r.h.dl &= 0xdf;		/* set raw bit */
X
X	/* and put it back */
X
X	r.x.ax = 0x4401;	/* IO ctrl put device information */
X	r.x.bx = 0x0001;	/* File handle; 1 for console */
X	intdos(&r, &r);		/* go fer it */
X}
X
X
Xckeyoff()	/* turn control-C trapping off */
X
X{
X	r.h.ah = 0x33;	/* ctrl-break check */
X	r.h.al = 1;	/* set the state of the ctrl-break check */
X	r.h.dl = 0;	/* turn it off */
X	intdos(&r, &r);
X}
X
Xckeyon()	/* turn control-C trapping on */
X
X{
X	r.h.ah = 0x33;	/* ctrl-break check */
X	r.h.al = 1;	/* set the state of the ctrl-break check */
X	r.h.dl = 1;	/* turn it on */
X	intdos(&r, &r);
X}
X
Xagios(buf, len)	/* perform an AGIOS call */
X
Xchar *buf;	/* sequence of bytes in command */
Xint len;	/* length of command in bytes */
X
X{
X	r.x.ax = 0x4403;	/* I/O ctrl write */
X	r.x.bx = 1;		/* console handle */
X	r.x.cx = len;		/* buffer length */
X	r.x.dx = (unsigned)buf;	/* buffer address */
X	return(intdos(&r, &r));	/* do it */
X}
X
Xkeycon()	/* turn keycode mode on */
X
X{
X	static char cmd[] = {43, 0, 1};
X
X	return(agios(&cmd[0], 3));
X}
X
Xkeycoff()	/* turn keycode mode off */
X
X{
X	static char cmd[] = {43, 0, 0};
X
X	return(agios(&cmd[0], 3));
X}
X
Xdefkey()	/* change all special keys to intercept mode */
X
X{
X	static char cmd[] = {40, 0, 2, 0, 0xfe, 0};
X
X	return(agios(&cmd[0], 6));
X}
X
Xundefkey()	/* change all special keys to intercept mode */
X
X{
X	static char cmd[] = {40, 0, 0, 0, 0xfe, 0};
X
X	return(agios(&cmd[0], 6));
X}
X
Xdsplbls()	/* display the application softkey labels on the screen */
X
X{
X	static char cmd[] = {11, 0};
X
X	return(agios(&cmd[0], 2));
X}
X
X#if	FLABEL
Xfnclabel(f, n)		/* label a function key */
X
Xint f,n;	/* default flag, numeric argument */
X
X{
X	register int status;	/* return status */
X	register int i;		/* loop index */
X	char lbl[17];	/* returned label contents */
X	/* AGIOS command buffer */
X	static char cmd[] = {8, 0, 1, 0, 7, 7, 7, 7, 10, 0, 10, 0};
X	/*                   code  key#  ptr to      top    bottom
X	                                 label string  attribute */
X	union {		/* union to cast ptr into AGIOS arg string */
X		char *ptr;	/* pointer to arg string */
X		char cstr[4];
X	} ptru;
X
X	/* must have a numeric argument */
X	if (f == FALSE) {
X		mlwrite("%Need function key number");
X		return(FALSE);
X	}
X
X	/* and it must be a legal key number */
X	if (n < 1 || n > 8) {
X		mlwrite("%Function key number out of range");
X		return(FALSE);
X	}
X
X	/* get the string to send */
X	status = mlreply("Label contents: ", &lbl[0], 17);
X	if (status != TRUE)
X		return(status);
X
X	/* pad the label out */
X	for (i=0; i < 17; i++) {
X		if (lbl[i] == 0)
X			break;
X	}
X	for (; i < 16; i++)
X		lbl[i] = ' ';
X	lbl[16] = 0;
X
X	/* set up the parameters */
X	cmd[2] = n;			/* function key number */
X	ptru.ptr = &lbl[0];		/* set up pointer to label string */
Xforce:	cmd[4] = ptru.cstr[0];
X	cmd[5] = ptru.cstr[1];
X	cmd[6] = ptru.cstr[2];
X	cmd[7] = ptru.cstr[3];
X
X	/* and send it out */
X	agios(&cmd[0], 12);
X	return(TRUE);
X}
X#endif
X#else
X
Xh15hello()
X
X{
X}
X#endif
E!O!F
newsize=`wc -c < hp150.c`
if [ $newsize -ne 9192 ]
then echo "File hp150.c was $newsize bytes, 9192 expected"
fi
echo 'x - ibmpc.c (text)'
sed << 'E!O!F' 's/^X//' > ibmpc.c
X/*
X * The routines in this file provide support for the IBM-PC and other
X * compatible terminals. It goes directly to the graphics RAM to do
X * screen output. It compiles into nothing if not an IBM-PC driver
X * Supported monitor cards include CGA, MONO and EGA.
X */
X
X#define	termdef	1			/* don't define "term" external */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if     IBMPC
X#define NROW	43			/* Max Screen size.		*/
X#define NCOL    80                      /* Edit if you want to.         */
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define	NPAUSE	200			/* # times thru update to pause */
X#define BEL     0x07                    /* BEL character.               */
X#define ESC     0x1B                    /* ESC character.               */
X#define	SPACE	32			/* space character		*/
X
X#define	SCADC	0xb8000000L		/* CGA address of screen RAM	*/
X#define	SCADM	0xb0000000L		/* MONO address of screen RAM	*/
X#define SCADE	0xb8000000L		/* EGA address of screen RAM	*/
X
X#define MONOCRSR 0x0B0D			/* monochrome cursor	    */
X#define CGACRSR 0x0607			/* CGA cursor		    */
X#define EGACRSR 0x0709			/* EGA cursor		    */
X
X#define	CDCGA	0			/* color graphics card		*/
X#define	CDMONO	1			/* monochrome text card		*/
X#define	CDEGA	2			/* EGA color adapter		*/
X#define	CDSENSE	9			/* detect the card type		*/
X
X#define NDRIVE	3			/* number of screen drivers	*/
X
Xint dtype = -1;				/* current display type		*/
Xchar drvname[][8] = {			/* screen resolution names	*/
X	"CGA", "MONO", "EGA"
X};
Xlong scadd;				/* address of screen ram	*/
Xint *scptr[NROW];			/* pointer to screen lines	*/
Xint sline[NCOL];			/* screen line image		*/
Xint egaexist = FALSE;			/* is an EGA card available?	*/
Xextern union REGS rg;			/* cpu register for use of DOS calls */
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern  int     ibmmove();
Xextern  int     ibmeeol();
Xextern  int     ibmeeop();
Xextern  int     ibmbeep();
Xextern  int     ibmopen();
Xextern	int	ibmrev();
Xextern	int	ibmcres();
Xextern	int	ibmclose();
Xextern	int	ibmputc();
Xextern	int	ibmkopen();
Xextern	int	ibmkclose();
X
X#if	COLOR
Xextern	int	ibmfcol();
Xextern	int	ibmbcol();
X
Xint	cfcolor = -1;		/* current forground color */
Xint	cbcolor = -1;		/* current background color */
Xint	ctrans[] =		/* ansi to ibm color translation table */
X	{0, 4, 2, 6, 1, 5, 3, 7};
X#endif
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM    term    = {
X	NROW-1,
X        NROW-1,
X        NCOL,
X        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        ibmopen,
X        ibmclose,
X	ibmkopen,
X	ibmkclose,
X        ttgetc,
X	ibmputc,
X        ttflush,
X        ibmmove,
X        ibmeeol,
X        ibmeeop,
X        ibmbeep,
X	ibmrev,
X	ibmcres
X#if	COLOR
X	, ibmfcol,
X	ibmbcol
X#endif
X};
X
Xextern union REGS rg;
X
X#if	COLOR
Xibmfcol(color)		/* set the current output color */
X
Xint color;	/* color to set */
X
X{
X	cfcolor = ctrans[color];
X}
X
Xibmbcol(color)		/* set the current background color */
X
Xint color;	/* color to set */
X
X{
X        cbcolor = ctrans[color];
X}
X#endif
X
Xibmmove(row, col)
X{
X	rg.h.ah = 2;		/* set cursor position function code */
X	rg.h.dl = col;
X	rg.h.dh = row;
X	rg.h.bh = 0;		/* set screen page number */
X	int86(0x10, &rg, &rg);
X}
X
Xibmeeol()	/* erase to the end of the line */
X
X{
X	int attr;	/* attribute byte mask to place in RAM */
X	int *lnptr;	/* pointer to the destination line */
X	int i;
X	int ccol;	/* current column cursor lives */
X	int crow;	/*	   row	*/
X
X	/* find the current cursor position */
X	rg.h.ah = 3;		/* read cursor position function code */
X	rg.h.bh = 0;		/* current video page */
X	int86(0x10, &rg, &rg);
X	ccol = rg.h.dl;		/* record current column */
X	crow = rg.h.dh;		/* and row */
X
X	/* build the attribute byte and setup the screen pointer */
X#if	COLOR
X	if (dtype != CDMONO)
X		attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
X	else
X		attr = 0x0700;
X#else
X	attr = 0x0700;
X#endif
X	lnptr = &sline[0];
X	for (i=0; i < term.t_ncol; i++)
X		*lnptr++ = SPACE | attr;
X
X	if (flickcode && (dtype == CDCGA)) {
X		/* wait for vertical retrace to be off */
X		while ((inp(0x3da) & 8))
X			;
X	
X		/* and to be back on */
X		while ((inp(0x3da) & 8) == 0)
X			;
X	}			
X
X	/* and send the string out */
X	movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2);
X
X}
X
Xibmputc(ch)	/* put a character at the current position in the
X		   current colors */
X
Xint ch;
X
X{
X	rg.h.ah = 14;		/* write char to screen with current attrs */
X	rg.h.al = ch;
X#if	COLOR
X	if (dtype != CDMONO)
X		rg.h.bl = cfcolor;
X	else
X		rg.h.bl = 0x07;
X#else
X	rg.h.bl = 0x07;
X#endif
X	int86(0x10, &rg, &rg);
X}
X
Xibmeeop()
X{
X	int attr;		/* attribute to fill screen with */
X
X	rg.h.ah = 6;		/* scroll page up function code */
X	rg.h.al = 0;		/* # lines to scroll (clear it) */
X	rg.x.cx = 0;		/* upper left corner of scroll */
X	rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
X				/* lower right corner of scroll */
X#if	COLOR
X	if (dtype != CDMONO)
X		attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
X	else
X		attr = 0;
X#else
X	attr = 0;
X#endif
X	rg.h.bh = attr;
X	int86(0x10, &rg, &rg);
X}
X
Xibmrev(state)		/* change reverse video state */
X
Xint state;	/* TRUE = reverse, FALSE = normal */
X
X{
X	/* This never gets used under the IBM-PC driver */
X}
X
Xibmcres(res)	/* change screen resolution */
X
Xchar *res;	/* resolution to change to */
X
X{
X	int i;		/* index */
X
X	for (i = 0; i < NDRIVE; i++)
X		if (strcmp(res, drvname[i]) == 0) {
X			scinit(i);
X			return(TRUE);
X		}
X	return(FALSE);
X}
X
Xspal()	/* reset the pallette registers */
X
X{
X	/* nothin here now..... */
X}
X
Xibmbeep()
X{
X#if	MWC86
X	putcnb(BEL);
X#else
X	bdos(6, BEL, 0);
X#endif
X}
X
Xibmopen()
X{
X	scinit(CDSENSE);
X	revexist = TRUE;
X        ttopen();
X}
X
Xibmclose()
X
X{
X#if	COLOR
X	ibmfcol(7);
X	ibmbcol(0);
X#endif
X	/* if we had the EGA open... close it */
X	if (dtype == CDEGA)
X		egaclose();
X
X	ttclose();
X}
X
Xibmkopen()	/* open the keyboard */
X
X{
X}
X
Xibmkclose()	/* close the keyboard */
X
X{
X}
X
Xscinit(type)	/* initialize the screen head pointers */
X
Xint type;	/* type of adapter to init for */
X
X{
X	union {
X		long laddr;	/* long form of address */
X		int *paddr;	/* pointer form of address */
X	} addr;
X	int i;
X
X	/* if asked...find out what display is connected */
X	if (type == CDSENSE)
X		type = getboard();
X
X	/* if we have nothing to do....don't do it */
X	if (dtype == type)
X		return(TRUE);
X
X	/* if we try to switch to EGA and there is none, don't */
X	if (type == CDEGA && egaexist != TRUE)
X		return(FALSE);
X
X	/* if we had the EGA open... close it */
X	if (dtype == CDEGA)
X		egaclose();
X
X	/* and set up the various parameters as needed */
X	switch (type) {
X		case CDMONO:	/* Monochrome adapter */
X				scadd = SCADM;
X				newsize(TRUE, 25);
X				break;
X
X		case CDCGA:	/* Color graphics adapter */
X				scadd = SCADC;
X				newsize(TRUE, 25);
X				break;
X
X		case CDEGA:	/* Enhanced graphics adapter */
X				scadd = SCADE;
X				egaopen();
X				newsize(TRUE, 43);
X				break;
X	}
X
X	/* reset the $sres environment variable */
X	strcpy(sres, drvname[type]);
X	dtype = type;
X
X	/* initialize the screen pointer array */
X	for (i = 0; i < NROW; i++) {
X		addr.laddr = scadd + (long)(NCOL * i * 2);
X		scptr[i] = addr.paddr;
X	}
X}
X
X/* getboard:	Determine which type of display board is attached.
X		Current known types include:
X
X		CDMONO	Monochrome graphics adapter
X		CDCGA	Color Graphics Adapter
X		CDEGA	Extended graphics Adapter
X*/
X
X/* getbaord:	Detect the current display adapter
X		if MONO		set to MONO
X		   CGA		set to CGA	EGAexist = FALSE
X		   EGA		set to CGA	EGAexist = TRUE
X*/
X
Xint getboard()
X
X{
X	int type;	/* board type to return */
X
X	type = CDCGA;
X	int86(0x11, &rg, &rg);
X	if ((((rg.x.ax >> 4) & 3) == 3))
X		type = CDMONO;
X
X	/* test if EGA present */
X	rg.x.ax = 0x1200;
X	rg.x.bx = 0xff10;
X	int86(0x10,&rg, &rg);		/* If EGA, bh=0-1 and bl=0-3 */
X	egaexist = !(rg.x.bx & 0xfefc);	/* Yes, it's EGA */
X	return(type);
X}
X
Xegaopen()	/* init the computer to work with the EGA */
X
X{
X	/* put the beast into EGA 43 row mode */
X	rg.x.ax = 3;
X	int86(16, &rg, &rg);
X
X	rg.h.ah = 17;		/* set char. generator function code */
X	rg.h.al = 18;		/*  to 8 by 8 double dot ROM         */
X	rg.h.bl = 0;		/* block 0                           */
X	int86(16, &rg, &rg);
X
X	rg.h.ah = 18;		/* alternate select function code    */
X	rg.h.al = 0;		/* clear AL for no good reason       */
X	rg.h.bl = 32;		/* alt. print screen routine         */
X	int86(16, &rg, &rg);
X
X	rg.h.ah = 1;		/* set cursor size function code */
X	rg.x.cx = 0x0607;	/* turn cursor on code */
X	int86(0x10, &rg, &rg);
X
X	outp(0x3d4, 10);	/* video bios bug patch */
X	outp(0x3d5, 6);
X}
X
Xegaclose()
X
X{
X	/* put the beast into 80 column mode */
X	rg.x.ax = 3;
X	int86(16, &rg, &rg);
X}
X
Xscwrite(row, outstr, forg, bacg)	/* write a line out*/
X
Xint row;	/* row of screen to place outstr on */
Xchar *outstr;	/* string to write out (must be term.t_ncol long) */
Xint forg;	/* forground color of string to write */
Xint bacg;	/* background color */
X
X{
X	int attr;	/* attribute byte mask to place in RAM */
X	int *lnptr;	/* pointer to the destination line */
X	int i;
X
X	/* build the attribute byte and setup the screen pointer */
X#if	COLOR
X	if (dtype != CDMONO)
X		attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
X	else
X		attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
X#else
X	attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
X#endif
X	lnptr = &sline[0];
X	for (i=0; i<term.t_ncol; i++)
X		*lnptr++ = (outstr[i] & 255) | attr;
X
X	if (flickcode && (dtype == CDCGA)) {
X		/* wait for vertical retrace to be off */
X		while ((inp(0x3da) & 8))
X			;
X	
X		/* and to be back on */
X		while ((inp(0x3da) & 8) == 0)
X			;
X	}
X
X	/* and send the string out */
X	movmem(&sline[0], scptr[row],term.t_ncol*2);
X}
X
X#if	FLABEL
Xfnclabel(f, n)		/* label a function key */
X
Xint f,n;	/* default flag, numeric argument [unused] */
X
X{
X	/* on machines with no function keys...don't bother */
X	return(TRUE);
X}
X#endif
X#else
Xibmhello()
X{
X}
X#endif
E!O!F
newsize=`wc -c < ibmpc.c`
if [ $newsize -ne 9998 ]
then echo "File ibmpc.c was $newsize bytes, 9998 expected"
fi
echo 'x - input.c (text)'
sed << 'E!O!F' 's/^X//' > input.c
X/*	INPUT:	Various input routines for MicroEMACS 3.7
X		written by Daniel Lawrence
X		5/9/86						*/
X
X#include	<stdio.h>
X#include	"estruct.h"
X#include	"edef.h"
X
X/*
X * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
X * ABORT. The ABORT status is returned if the user bumps out of the question
X * with a ^G. Used any time a confirmation is required.
X */
X
Xmlyesno(prompt)
X
Xchar *prompt;
X
X{
X	char c;			/* input character */
X	char buf[NPAT];		/* prompt to user */
X
X	for (;;) {
X		/* build and prompt the user */
X		strcpy(buf, prompt);
X		strcat(buf, " [y/n]? ");
X		mlwrite(buf);
X
X		/* get the responce */
X		c = tgetc();
X
X		if (c == ectoc(abortc))		/* Bail out! */
X			return(ABORT);
X
X		if (c=='y' || c=='Y')
X			return(TRUE);
X
X		if (c=='n' || c=='N')
X			return(FALSE);
X	}
X}
X
X/*
X * Write a prompt into the message line, then read back a response. Keep
X * track of the physical position of the cursor. If we are in a keyboard
X * macro throw the prompt away, and return the remembered response. This
X * lets macros run at full speed. The reply is always terminated by a carriage
X * return. Handle erase, kill, and abort keys.
X */
X
Xmlreply(prompt, buf, nbuf)
X    char *prompt;
X    char *buf;
X{
X	return(nextarg(prompt, buf, nbuf, ctoec('\n')));
X}
X
Xmlreplyt(prompt, buf, nbuf, eolchar)
X
Xchar *prompt;
Xchar *buf;
Xint eolchar;
X
X{
X	return(nextarg(prompt, buf, nbuf, eolchar));
X}
X
X/*	ectoc:	expanded character to character
X		colapse the CTRL and SPEC flags back into an ascii code   */
X
Xectoc(c)
X
Xint c;
X
X{
X	if (c & CTRL)
X		c = c & ~(CTRL | 0x40);
X	if (c & SPEC)
X		c= c & 255;
X	return(c);
X}
X
X/*	ctoec:	character to extended character
X		pull out the CTRL and SPEC prefixes (if possible)	*/
X
Xctoec(c)
X
Xint c;
X
X{
X        if (c>=0x00 && c<=0x1F)
X                c = CTRL | (c+'@');
X        return (c);
X}
X 
X/* get a command name from the command line. Command completion means
X   that pressing a <SPACE> will attempt to complete an unfinished command
X   name if it is unique.
X*/
X
Xint (*getname())()
X
X{
X#if	ST520 & LATTICE
X#define register		
X#endif
X	register int cpos;	/* current column on screen output */
X	register int c;
X	register char *sp;	/* pointer to string for output */
X	register NBIND *ffp;	/* first ptr to entry in name binding table */
X	register NBIND *cffp;	/* current ptr to entry in name binding table */
X	register NBIND *lffp;	/* last ptr to entry in name binding table */
X	char buf[NSTRING];	/* buffer to hold tentative command name */
X	int (*fncmatch())();
X
X	/* starting at the beginning of the string buffer */
X	cpos = 0;
X
X	/* if we are executing a command line get the next arg and match it */
X	if (clexec) {
X		if (macarg(buf) != TRUE)
X			return(FALSE);
X		return(fncmatch(&buf[0]));
X	}
X
X	/* build a name string from the keyboard */
X	while (TRUE) {
X		c = tgetc();
X
X		/* if we are at the end, just match it */
X		if (c == 0x0d) {
X			buf[cpos] = 0;
X
X			/* and match it off */
X			return(fncmatch(&buf[0]));
X
X		} else if (c == ectoc(abortc)) {	/* Bell, abort */
X			ctrlg(FALSE, 0);
X			TTflush();
X			return( (int (*)()) NULL);
X
X		} else if (c == 0x7F || c == 0x08) {	/* rubout/erase */
X			if (cpos != 0) {
X				TTputc('\b');
X				TTputc(' ');
X				TTputc('\b');
X				--ttcol;
X				--cpos;
X				TTflush();
X			}
X
X		} else if (c == 0x15) {	/* C-U, kill */
X			while (cpos != 0) {
X				TTputc('\b');
X				TTputc(' ');
X				TTputc('\b');
X				--cpos;
X				--ttcol;
X			}
X
X			TTflush();
X
X		} else if (c == ' ') {
X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
X	/* attempt a completion */
X	buf[cpos] = 0;		/* terminate it for us */
X	ffp = &names[0];	/* scan for matches */
X	while (ffp->n_func != NULL) {
X		if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
X			/* a possible match! More than one? */
X			if ((ffp + 1)->n_func == NULL ||
X			   (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) {
X				/* no...we match, print it */
X				sp = ffp->n_name + cpos;
X				while (*sp)
X					TTputc(*sp++);
X				TTflush();
X				return(ffp->n_func);
X			} else {
X/* << << << << << << << << << << << << << << << << << */
X	/* try for a partial match against the list */
X
X	/* first scan down until we no longer match the current input */
X	lffp = (ffp + 1);
X	while ((lffp+1)->n_func != NULL) {
X		if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
X			break;
X		++lffp;
X	}
X
X	/* and now, attempt to partial complete the string, char at a time */
X	while (TRUE) {
X		/* add the next char in */
X		buf[cpos] = ffp->n_name[cpos];
X
X		/* scan through the candidates */
X		cffp = ffp + 1;
X		while (cffp <= lffp) {
X			if (cffp->n_name[cpos] != buf[cpos])
X				goto onward;
X			++cffp;
X		}
X
X		/* add the character */
X		TTputc(buf[cpos++]);
X	}
X/* << << << << << << << << << << << << << << << << << */
X			}
X		}
X		++ffp;
X	}
X
X	/* no match.....beep and onward */
X	TTbeep();
Xonward:;
X	TTflush();
X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
X		} else {
X			if (cpos < NSTRING-1 && c > ' ') {
X				buf[cpos++] = c;
X				TTputc(c);
X			}
X
X			++ttcol;
X			TTflush();
X		}
X	}
X}
X
X/*	tgetc:	Get a key from the terminal driver, resolve any keyboard
X		macro action					*/
X
Xint tgetc()
X
X{
X	int c;	/* fetched character */
X
X	/* if we are playing a keyboard macro back, */
X	if (kbdmode == PLAY) {
X
X		/* if there is some left... */
X		if (kbdptr < kbdend)
X			return((int)*kbdptr++);
X
X		/* at the end of last repitition? */
X		if (--kbdrep < 1) {
X			kbdmode = STOP;
X#if	VISMAC == 0
X			/* force a screen update after all is done */
X			update(FALSE);
X#endif
X		} else {
X
X			/* reset the macro to the begining for the next rep */
X			kbdptr = &kbdm[0];
X			return((int)*kbdptr++);
X		}
X	}
X
X	/* fetch a character from the terminal driver */
X	c = TTgetc();
X
X	/* record it for $lastkey */
X	lastkey = c;
X
X	/* save it if we need to */
X	if (kbdmode == RECORD) {
X		*kbdptr++ = c;
X		kbdend = kbdptr;
X
X		/* don't overrun the buffer */
X		if (kbdptr == &kbdm[NKBDM - 1]) {
X			kbdmode = STOP;
X			TTbeep();
X		}
X	}
X
X	/* and finally give the char back */
X	return(c);
X}
X
X/*	GET1KEY:	Get one keystroke. The only prefixs legal here
X			are the SPEC and CTRL prefixes.
X								*/
X
Xget1key()
X
X{
X	int    c;
X#if	AMIGA
X	int	d;
X#endif
X
X	/* get a keystroke */
X        c = tgetc();
X
X#if	MSDOS | ST520
X	if (c == 0) {				/* Apply SPEC prefix	*/
X	        c = tgetc();
X	        if (c>=0x00 && c<=0x1F)		/* control key? */
X        	        c = CTRL | (c+'@');
X		return(SPEC | c);
X	}
X#endif
X
X#if	AMIGA
X	/* apply SPEC prefix */
X	if ((unsigned)c == 155) {
X		c = tgetc();
X
X		/* first try to see if it is a cursor key */
X		if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T')
X			return(SPEC | c);
X
X		/* next, a 2 char sequence */
X		d = tgetc();
X		if (d == '~')
X			return(SPEC | c);
X
X		/* decode a 3 char sequence */
X		c = d + 32;
X		/* if a shifted function key, eat the tilde */
X		if (d >= '0' && d <= '9')
X			d = tgetc();
X		return(SPEC | c);
X	}
X#endif
X
X#if  WANGPC
X	if (c == 0x1F) {			/* Apply SPEC prefix    */
X	        c = tgetc();
X		return(SPEC | c);
X	}
X#endif
X
X        if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
X                c = CTRL | (c+'@');
X        return (c);
X}
X
X/*	GETCMD:	Get a command from the keyboard. Process all applicable
X		prefix keys
X							*/
Xgetcmd()
X
X{
X	int c;		/* fetched keystroke */
X
X	/* get initial character */
X	c = get1key();
X
X	/* process META prefix */
X	if (c == metac) {
X		c = get1key();
X	        if (islower(c))		/* Force to upper */
X        	        c ^= DIFCASE;
X	        if (c>=0x00 && c<=0x1F)		/* control key */
X	        	c = CTRL | (c+'@');
X		return(META | c);
X	}
X
X	/* process CTLX prefix */
X	if (c == ctlxc) {
X		c = get1key();
X	        if (c>='a' && c<='z')		/* Force to upper */
X        	        c -= 0x20;
X	        if (c>=0x00 && c<=0x1F)		/* control key */
X	        	c = CTRL | (c+'@');
X		return(CTLX | c);
X	}
X
X	/* otherwise, just return it */
X	return(c);
X}
X
X/*	A more generalized prompt/reply function allowing the caller
X	to specify the proper terminator. If the terminator is not
X	a return ('\n') it will echo as "<NL>"
X							*/
Xgetstring(prompt, buf, nbuf, eolchar)
X
Xchar *prompt;
Xchar *buf;
Xint eolchar;
X
X{
X	register int cpos;	/* current character position in string */
X	register int c;
X	register int quotef;	/* are we quoting the next char? */
X
X	cpos = 0;
X	quotef = FALSE;
X
X	/* prompt the user for the input string */
X	mlwrite(prompt);
X
X	for (;;) {
X		/* get a character from the user */
X		c = get1key();
X
X		/* If it is a <ret>, change it to a <NL> */
X		if (c == (CTRL | 0x4d))
X			c = CTRL | 0x40 | '\n';
X
X		/* if they hit the line terminate, wrap it up */
X		if (c == eolchar && quotef == FALSE) {
X			buf[cpos++] = 0;
X
X			/* clear the message line */
X			mlwrite("");
X			TTflush();
X
X			/* if we default the buffer, return FALSE */
X			if (buf[0] == 0)
X				return(FALSE);
X
X			return(TRUE);
X		}
X
X		/* change from command form back to character form */
X		c = ectoc(c);
X
X		if (c == ectoc(abortc) && quotef == FALSE) {
X			/* Abort the input? */
X			ctrlg(FALSE, 0);
X			TTflush();
X			return(ABORT);
X		} else if ((c==0x7F || c==0x08) && quotef==FALSE) {
X			/* rubout/erase */
X			if (cpos != 0) {
X				outstring("\b \b");
X				--ttcol;
X
X				if (buf[--cpos] < 0x20) {
X					outstring("\b \b");
X					--ttcol;
X				}
X
X				if (buf[cpos] == '\n') {
X					outstring("\b\b  \b\b");
X					ttcol -= 2;
X				}
X				TTflush();
X			}
X
X		} else if (c == 0x15 && quotef == FALSE) {
X			/* C-U, kill */
X			while (cpos != 0) {
X				outstring("\b \b");
X				--ttcol;
X
X				if (buf[--cpos] < 0x20) {
X					outstring("\b \b");
X					--ttcol;
X				}
X			}
X			TTflush();
X
X		} else if (c == quotec && quotef == FALSE) {
X			quotef = TRUE;
X		} else {
X			quotef = FALSE;
X			if (cpos < nbuf-1) {
X				buf[cpos++] = c;
X
X				if ((c < ' ') && (c != '\n')) {
X					outstring("^");
X					++ttcol;
X					c ^= 0x40;
X				}
X
X				if (c != '\n') {
X					if (disinp)
X						TTputc(c);
X				} else {	/* put out <NL> for <ret> */
X					outstring("<NL>");
X					ttcol += 3;
X				}
X				++ttcol;
X				TTflush();
X			}
X		}
X	}
X}
X
Xoutstring(s)	/* output a string of characters */
X
Xchar *s;	/* string to output */
X
X{
X	if (disinp)
X		while (*s)
X			TTputc(*s++);
X}
E!O!F
newsize=`wc -c < input.c`
if [ $newsize -ne 9954 ]
then echo "File input.c was $newsize bytes, 9954 expected"
fi
echo 'x - isearch.c (text)'
sed << 'E!O!F' 's/^X//' > isearch.c
X/*
X * The functions in this file implement commands that perform incremental
X * searches in the forward and backward directions.  This "ISearch" command
X * is intended to emulate the same command from the original EMACS 
X * implementation (ITS).  Contains references to routines internal to
X * SEARCH.C.
X *
X * REVISION HISTORY:
X *
X *	D. R. Banks 9-May-86
X *	- added ITS EMACSlike ISearch
X *
X *	John M. Gamble 5-Oct-86
X *	- Made iterative search use search.c's scanner() routine.
X *	  This allowed the elimination of bakscan().
X *	- Put isearch constants into estruct.h
X *	- Eliminated the passing of 'status' to scanmore() and
X *	  checknext(), since there were no circumstances where
X *	  it ever equalled FALSE.
X */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if	ISRCH
X
Xextern int scanner();			/* Handy search routine */
Xextern int eq();			/* Compare chars, match case */
X
X/* A couple of "own" variables for re-eat */
X
Xint	(*saved_get_char)();		/* Get character routine */
Xint	eaten_char = -1;		/* Re-eaten char */
X
X/* A couple more "own" variables for the command string */
X
Xint	cmd_buff[CMDBUFLEN];		/* Save the command args here */
Xint	cmd_offset;			/* Current offset into command buff */
Xint	cmd_reexecute = -1;		/* > 0 if re-executing command */
X
X
X/*
X * Subroutine to do incremental reverse search.  It actually uses the
X * same code as the normal incremental search, as both can go both ways.
X */
X 
Xint risearch(f, n)
X{
X    LINE *curline;			/* Current line on entry	      */
X    int  curoff;			/* Current offset on entry	      */
X
X    /* remember the initial . on entry: */
X
X    curline = curwp->w_dotp;		/* Save the current line pointer      */
X    curoff  = curwp->w_doto;		/* Save the current offset	      */
X
X    /* Make sure the search doesn't match where we already are:		      */
X
X    backchar(TRUE, 1);			/* Back up a character		      */
X
X    if (!(isearch(f, -n)))		/* Call ISearch backwards	      */
X    {					/* If error in search:		      */
X	curwp->w_dotp = curline;	/* Reset the line pointer	      */
X	curwp->w_doto = curoff;		/*  and the offset to original value  */
X	curwp->w_flag |= WFMOVE;	/* Say we've moved		      */
X	update(FALSE);			/* And force an update		      */
X	mlwrite ("[search failed]");	/* Say we died			      */
X    } else mlerase ();			/* If happy, just erase the cmd line  */
X}
X
X/* Again, but for the forward direction */
X
Xint fisearch(f, n)
X{
X    LINE *curline;			/* Current line on entry	      */
X    int  curoff;			/* Current offset on entry	      */
X
X    /* remember the initial . on entry: */
X
X    curline = curwp->w_dotp;		/* Save the current line pointer      */
X    curoff  = curwp->w_doto;		/* Save the current offset	      */
X
X    /* do the search */
X
X    if (!(isearch(f, n)))		/* Call ISearch forwards	      */
X    {					/* If error in search:		      */
X	curwp->w_dotp = curline;	/* Reset the line pointer	      */
X	curwp->w_doto = curoff;		/*  and the offset to original value  */
X	curwp->w_flag |= WFMOVE;	/* Say we've moved		      */
X	update(FALSE);			/* And force an update		      */
X	mlwrite ("[search failed]");	/* Say we died			      */
X    } else mlerase ();			/* If happy, just erase the cmd line  */
X}
X
X/*
X * Subroutine to do an incremental search.  In general, this works similarly
X * to the older micro-emacs search function, except that the search happens
X * as each character is typed, with the screen and cursor updated with each
X * new search character.
X *
X * While searching forward, each successive character will leave the cursor
X * at the end of the entire matched string.  Typing a Control-S or Control-X
X * will cause the next occurrence of the string to be searched for (where the
X * next occurrence does NOT overlap the current occurrence).  A Control-R will
X * change to a backwards search, META will terminate the search and Control-G
X * will abort the search.  Rubout will back up to the previous match of the
X * string, or if the starting point is reached first, it will delete the
X * last character from the search string.
X *
X * While searching backward, each successive character will leave the cursor
X * at the beginning of the matched string.  Typing a Control-R will search
X * backward for the next occurrence of the string.  Control-S or Control-X
X * will revert the search to the forward direction.  In general, the reverse
X * incremental search is just like the forward incremental search inverted.
X *
X * In all cases, if the search fails, the user will be feeped, and the search
X * will stall until the pattern string is edited back into something that
X * exists (or until the search is aborted).
X */
X 
Xisearch(f, n)
X{
X    int			status;		/* Search status */
X    int			col;		/* prompt column */
X    register int	cpos;		/* character number in search string  */
X    register int	c;		/* current input character */
X    register int	expc;		/* function expanded input char	      */
X    char		pat_save[NPAT];	/* Saved copy of the old pattern str  */
X    LINE		*curline;	/* Current line on entry	      */
X    int			curoff;		/* Current offset on entry	      */
X    int			init_direction;	/* The initial search direction	      */
X
X    /* Initialize starting conditions */
X
X    cmd_reexecute = -1;		/* We're not re-executing (yet?)      */
X    cmd_offset = 0;			/* Start at the beginning of the buff */
X    cmd_buff[0] = '\0';		/* Init the command buffer	      */
X    strncpy (pat_save, pat, NPAT);	/* Save the old pattern string	      */
X    curline = curwp->w_dotp;		/* Save the current line pointer      */
X    curoff  = curwp->w_doto;		/* Save the current offset	      */
X    init_direction = n;			/* Save the initial search direction  */
X
X    /* This is a good place to start a re-execution: */
X
Xstart_over:
X
X    /* ask the user for the text of a pattern */
X    col = promptpattern("ISearch: ");		/* Prompt, remember the col   */
X
X    cpos = 0;					/* Start afresh		      */
X    status = TRUE;				/* Assume everything's cool   */
X
X    /*
X       Get the first character in the pattern.  If we get an initial Control-S
X       or Control-R, re-use the old search string and find the first occurrence
X     */
X
X    c = ectoc(expc = get_char());		/* Get the first character    */
X    if ((c == IS_FORWARD) ||
X        (c == IS_REVERSE) ||
X        (c == IS_VMSFORW))			/* Reuse old search string?   */
X    {
X    	for (cpos = 0; pat[cpos] != 0; cpos++)	/* Yup, find the length	      */
X    	    col = echochar(pat[cpos],col);	/*  and re-echo the string    */
X	if (c == IS_REVERSE) {			/* forward search?	      */
X	    n = -1;				/* No, search in reverse      */
X	    backchar (TRUE, 1);			/* Be defensive about EOB     */
X	} else
X	    n = 1;				/* Yes, search forward	      */
X	status = scanmore(pat, n);		/* Do the search	      */
X	c = ectoc(expc = get_char());		/* Get another character      */
X    }
X
X    /* Top of the per character loop */
X        	
X    for (;;)					/* ISearch per character loop */
X    {
X	/* Check for special characters first: */
X	/* Most cases here change the search */
X
X	if (expc == metac)			/* Want to quit searching?    */
X	    return (TRUE);			/* Quit searching now	      */
X
X	switch (c)				/* dispatch on the input char */
X	{
X	  case IS_ABORT:			/* If abort search request    */
X	    return(FALSE);			/* Quit searching again	      */
X
X	  case IS_REVERSE:			/* If backward search	      */
X	  case IS_FORWARD:			/* If forward search	      */
X	  case IS_VMSFORW:			/*  of either flavor	      */
X	    if (c == IS_REVERSE)		/* If reverse search	      */
X		n = -1;				/* Set the reverse direction  */
X	    else				/* Otherwise, 		      */
X		n = 1;				/*  go forward		      */
X	    status = scanmore(pat, n);		/* Start the search again     */
X	    c = ectoc(expc = get_char());	/* Get the next char	      */
X	    continue;				/* Go continue with the search*/
X
X	  case IS_NEWLINE:			/* Carriage return	      */
X	    c = '\n';				/* Make it a new line	      */
X	    break;				/* Make sure we use it	      */
X
X	  case IS_QUOTE:			/* Quote character	      */
X	  case IS_VMSQUOTE:			/*  of either variety	      */
X	    c = ectoc(expc = get_char());	/* Get the next char	      */
X
X	  case IS_TAB:				/* Generically allowed	      */
X	  case '\n':				/*  controlled characters     */
X	    break;				/* Make sure we use it	      */
X
X	  case IS_BACKSP:			/* If a backspace:            */
X	  case IS_RUBOUT:			/*  or if a Rubout:	      */
X	    if (cmd_offset <= 1)		/* Anything to delete?	      */
X		return (TRUE);			/* No, just exit	      */
X	    --cmd_offset;			/* Back up over the Rubout    */
X	    cmd_buff[--cmd_offset] = '\0';	/* Yes, delete last char   */
X	    curwp->w_dotp = curline;		/* Reset the line pointer     */
X	    curwp->w_doto = curoff;		/*  and the offset	      */
X	    n = init_direction;			/* Reset the search direction */
X	    strncpy (pat, pat_save, NPAT);	/* Restore the old search str */
X	    cmd_reexecute = 0;			/* Start the whole mess over  */
X	    goto start_over;			/* Let it take care of itself */
X
X	  /* Presumably a quasi-normal character comes here */
X
X	  default:				/* All other chars    	      */
X	    if (c < ' ')			/* Is it printable?	      */
X	    {					/* Nope.		      */
X		reeat (c);			/* Re-eat the char	      */
X		return (TRUE);			/* And return the last status */
X	    }
X	}  /* Switch */
X
X	/* I guess we got something to search for, so search for it	      */
X
X	pat[cpos++] = c;			/* put the char in the buffer */
X	if (cpos >= NPAT)			/* too many chars in string?  */
X	{					/* Yup.  Complain about it    */
X	    mlwrite("? Search string too long");
X	    return(TRUE);			/* Return an error	      */
X	}
X	pat[cpos] = 0;				/* null terminate the buffer  */
X	col = echochar(c,col);			/* Echo the character	      */
X	if (!status) {				/* If we lost last time	      */
X	    TTputc(BELL);		/* Feep again		      */
X	    TTflush();			/* see that the feep feeps    */
X	} else					/* Otherwise, we must have won*/
X	    if (!(status = checknext(c, pat, n))) /* See if match	      */
X		status = scanmore(pat, n);	/*  or find the next match    */
X	c = ectoc(expc = get_char());		/* Get the next char	      */
X    } /* for {;;} */
X}
X
X/*
X * Trivial routine to insure that the next character in the search string is
X * still true to whatever we're pointing to in the buffer.  This routine will
X * not attempt to move the "point" if the match fails, although it will 
X * implicitly move the "point" if we're forward searching, and find a match,
X * since that's the way forward isearch works.
X *
X * If the compare fails, we return FALSE and assume the caller will call
X * scanmore or something.
X */
X
Xint checknext (chr, patrn, dir)	/* Check next character in search string */
Xchar	chr;			/* Next char to look for		 */
Xchar	*patrn;			/* The entire search string (incl chr)   */
Xint	dir;			/* Search direction			 */
X{
X    register LINE *curline;		/* current line during scan	      */
X    register int curoff;		/* position within current line	      */
X    register int buffchar;		/* character at current position      */
X    int status;				/* how well things go		      */
X
X
X    /* setup the local scan pointer to current "." */
X
X    curline = curwp->w_dotp;		/* Get the current line structure     */
X    curoff  = curwp->w_doto;		/* Get the offset within that line    */
X
X    if (dir > 0)			/* If searching forward		      */
X    {
X    	if (curoff == llength(curline)) /* If at end of line		      */
X    	{
X	    curline = lforw(curline);	/* Skip to the next line	      */
X	    if (curline == curbp->b_linep)
X		return (FALSE);		/* Abort if at end of buffer	      */
X	    curoff = 0;			/* Start at the beginning of the line */
X	    buffchar = '\n';		/* And say the next char is NL	      */
X	} else
X	    buffchar = lgetc(curline, curoff++); /* Get the next char	      */
X	if (status = eq(buffchar, chr))	/* Is it what we're looking for?      */
X	{
X	    curwp->w_dotp = curline;	/* Yes, set the buffer's point	      */
X	    curwp->w_doto = curoff;	/*  to the matched character	      */
X	    curwp->w_flag |= WFMOVE;	/* Say that we've moved		      */
X	}
X	return (status);		/* And return the status	      */
X    } else				/* Else, if reverse search:	      */
X	return (match_pat (patrn));	/* See if we're in the right place    */
X}
X
X/*
X * This hack will search for the next occurrence of <pat> in the buffer, either
X * forward or backward.  It is called with the status of the prior search
X * attempt, so that it knows not to bother if it didn't work last time.  If
X * we can't find any more matches, "point" is left where it was before.  If
X * we do find a match, "point" will be at the end of the matched string for
X * forward searches and at the beginning of the matched string for reverse
X * searches.
X */
X 
Xint scanmore(patrn, dir)	/* search forward or back for a pattern	      */
Xchar	*patrn;			/* string to scan for			      */
Xint	dir;			/* direction to search			      */
X{
X	int	sts;			/* search status		      */
X
X    	if (dir < 0)				/* reverse search?	      */
X    	{
X		rvstrcpy(tap, patrn);		/* Put reversed string in tap */
X		sts = scanner(tap, REVERSE, PTBEG);
X	}
X	else
X		sts = scanner(patrn, FORWARD, PTEND);	/* Nope. Go forward   */
X
X	if (!sts)
X	{
X		TTputc(BELL);	/* Feep if search fails       */
X		TTflush();		/* see that the feep feeps    */
X	}
X
X	return(sts);				/* else, don't even try	      */
X}
X
X/*
X * The following is a worker subroutine used by the reverse search.  It
X * compares the pattern string with the characters at "." for equality. If
X * any characters mismatch, it will return FALSE.
X *
X * This isn't used for forward searches, because forward searches leave "."
X * at the end of the search string (instead of in front), so all that needs to
X * be done is match the last char input.
X */
X
Xint match_pat (patrn)	/* See if the pattern string matches string at "."   */
Xchar	*patrn;		/* String to match to buffer			     */
X{
X    register int  i;			/* Generic loop index/offset	      */
X    register int buffchar;		/* character at current position      */
X    register LINE *curline;		/* current line during scan	      */
X    register int curoff;		/* position within current line	      */
X
X    /* setup the local scan pointer to current "." */
X
X    curline = curwp->w_dotp;		/* Get the current line structure     */
X    curoff  = curwp->w_doto;		/* Get the offset within that line    */
X
X    /* top of per character compare loop: */
X
X    for (i = 0; i < strlen(patrn); i++)	/* Loop for all characters in patrn   */
X    {
X    	if (curoff == llength(curline)) /* If at end of line		      */
X    	{
X	    curline = lforw(curline);	/* Skip to the next line	      */
X	    curoff = 0;			/* Start at the beginning of the line */
X	    if (curline == curbp->b_linep)
X		return (FALSE);		/* Abort if at end of buffer	      */
X	    buffchar = '\n';		/* And say the next char is NL	      */
X	} else
X	    buffchar = lgetc(curline, curoff++); /* Get the next char	      */
X	if (!eq(buffchar, patrn[i]))	/* Is it what we're looking for?      */
X	    return (FALSE);		/* Nope, just punt it then	      */
X    }
X    return (TRUE);			/* Everything matched? Let's celebrate*/
X}
X
X/* Routine to prompt for I-Search string. */
X
Xint promptpattern(prompt)
Xchar *prompt;
X{
X    char tpat[NPAT+20];
X
X    strcpy(tpat, prompt);		/* copy prompt to output string */
X    strcat(tpat, " [");			/* build new prompt string */
X    expandp(pat, &tpat[strlen(tpat)], NPAT/2);	/* add old pattern */
X    strcat(tpat, "]<META>: ");
X
X    /* check to see if we are executing a command line */
X    if (!clexec) {
X	mlwrite(tpat);
X    }
X    return(strlen(tpat));
X}
X
X/* routine to echo i-search characters */
X
Xint echochar(c,col)
Xint	c;	/* character to be echoed */
Xint	col;	/* column to be echoed in */
X{
X    movecursor(term.t_nrow,col);		/* Position the cursor	      */
X    if ((c < ' ') || (c == 0x7F))		/* Control character?	      */
X    {
X	switch (c)				/* Yes, dispatch special cases*/
X	{
X	  case '\n':				/* Newline		      */
X	    TTputc('<');
X	    TTputc('N');
X	    TTputc('L');
X	    TTputc('>');
X	    col += 3;
X	    break;
X
X	  case '\t':				/* Tab			      */
X	    TTputc('<');
X	    TTputc('T');
X	    TTputc('A');
X	    TTputc('B');
X	    TTputc('>');
X	    col += 4;
X	    break;
X
X	  case 0x7F:				/* Rubout:		      */
X	    TTputc('^');		/* Output a funny looking     */
X	    TTputc('?');		/*  indication of Rubout      */
X	    col++;				/* Count the extra char       */
X	    break;
X
X	  default:				/* Vanilla control char       */
X	    TTputc('^');		/* Yes, output prefix	      */
X    	    TTputc(c+0x40);		/* Make it "^X"		      */
X	    col++;				/* Count this char	      */
X	}
X    } else
X	TTputc(c);			/* Otherwise, output raw char */
X    TTflush();				/* Flush the output	      */
X    return(++col);				/* return the new column no   */
X}
X
X/*
X * Routine to get the next character from the input stream.  If we're reading
X * from the real terminal, force a screen update before we get the char. 
X * Otherwise, we must be re-executing the command string, so just return the
X * next character.
X */
X
Xint get_char ()
X{
X    int	c;				/* A place to get a character	      */
X
X    /* See if we're re-executing: */
X
X    if (cmd_reexecute >= 0)		/* Is there an offset?		      */
X	if ((c = cmd_buff[cmd_reexecute++]) != 0)
X	    return (c);			/* Yes, return any character	      */
X
X    /* We're not re-executing (or aren't any more).  Try for a real char      */
X
X    cmd_reexecute = -1;		/* Say we're in real mode again	      */
X    update(FALSE);			/* Pretty up the screen		      */
X    if (cmd_offset >= CMDBUFLEN-1)	/* If we're getting too big ...	      */
X    {
X	mlwrite ("? command too long");	/* Complain loudly and bitterly	      */
X	return (metac);			/* And force a quit		      */
X    }
X    c = get1key();		/* Get the next character	      */
X    cmd_buff[cmd_offset++] = c; /* Save the char for next time        */
X    cmd_buff[cmd_offset] = '\0';/* And terminate the buffer	      */
X    return (c);				/* Return the character		      */
X}
X
X/*
X * Hacky routine to re-eat a character.  This will save the character to be
X * re-eaten by redirecting the input call to a routine here.  Hack, etc.
X */
X
X/* Come here on the next term.t_getchar call: */
X
Xint uneat()
X{
X    int c;
X
X    term.t_getchar = saved_get_char;	/* restore the routine address	      */
X    c = eaten_char;			/* Get the re-eaten char	      */
X    eaten_char = -1;			/* Clear the old char		      */
X    return(c);				/* and return the last char	      */
X}
X
Xint reeat(c)
Xint	c;
X{
X    if (eaten_char != -1)		/* If we've already been here	      */
X	return/*(NULL)*/;		/* Don't do it again		      */
X    eaten_char = c;			/* Else, save the char for later      */
X    saved_get_char = term.t_getchar;	/* Save the char get routine	      */
X    term.t_getchar = uneat;		/* Replace it with ours		      */
X}
X#else
Xisearch()
X{
X}
X#endif
E!O!F
newsize=`wc -c < isearch.c`
if [ $newsize -ne 18697 ]
then echo "File isearch.c was $newsize bytes, 18697 expected"
fi
	bill davidsen		(wedu@ge-crd.arpa)
  {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me