[mod.sources] v06i081: MicroEmacs, Version 3.7

sources-request@mirror.UUCP (07/31/86)

Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence
Mod.sources: Volume 6, Issue 81
Archive-name: uEmacs/Part11

[  This is the latest revision of one of two programs named "MicroEmacs";
   when discussing these on the net, or in contacting the authors, make
   sure to mention the version number -- in this case 3.7 -- as that is
   the easiest way to distinguish between them.  Daniel will be posting
   uuencoded executables in net.micro.pc and net.micro.amiga; the file
   'readme' contains information on how to also get these from him
   directly.   --r$ ]

echo extracting - tcap.c
sed 's/^X//' > tcap.c << 'FRIDAY_NIGHT'
X/*	tcap:	Unix V5, V7 and BS4.2 Termcap video driver
X		for MicroEMACS
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 TERMCAP
X
X#define	MARGIN	8
X#define	SCRSIZ	64
X#define	NPAUSE	10			/* # times thru update to pause */
X#define BEL     0x07
X#define ESC     0x1B
X
Xextern int      ttopen();
Xextern int      ttgetc();
Xextern int      ttputc();
Xextern int	tgetnum();
Xextern int      ttflush();
Xextern int      ttclose();
Xextern int      tcapmove();
Xextern int      tcapeeol();
Xextern int      tcapeeop();
Xextern int      tcapbeep();
Xextern int	tcaprev();
Xextern int      tcapopen();
Xextern int      tput();
Xextern char     *tgoto();
X#if	COLOR
Xextern	int	tcapfcol();
Xextern	int	tcapbcol();
X#endif
X
X#define TCAPSLEN 315
Xchar tcapbuf[TCAPSLEN];
Xchar *UP, PC, *CM, *CE, *CL, *SO, *SE;
X
XTERM term = {
X	NULL,		/* these two values are set dynamically at open time */
X	NULL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        tcapopen,
X        ttclose,
X        ttgetc,
X        ttputc,
X        ttflush,
X        tcapmove,
X        tcapeeol,
X        tcapeeop,
X        tcapbeep,
X        tcaprev
X#if	COLOR
X	, tcapfcol,
X	tcapbcol
X#endif
X};
X
Xtcapopen()
X
X{
X        char *getenv();
X        char *t, *p, *tgetstr();
X        char tcbuf[1024];
X        char *tv_stype;
X        char err_str[72];
X
X        if ((tv_stype = getenv("TERM")) == NULL)
X        {
X                puts("Environment variable TERM not defined!");
X                exit(1);
X        }
X
X        if ((tgetent(tcbuf, tv_stype)) != 1)
X        {
X                sprintf(err_str, "Unknown terminal type %s!", tv_stype);
X                puts(err_str);
X                exit(1);
X        }
X
X 
X       if ((term.t_nrow=(short)tgetnum("li")-1) == -1){
X               puts("termcap entry incomplete (lines)");
X               exit(1);
X       }
X 
X       if ((term.t_ncol=(short)tgetnum("co")) == -1){
X               puts("Termcap entry incomplete (columns)");
X               exit(1);
X       }
X
X        p = tcapbuf;
X        t = tgetstr("pc", &p);
X        if(t)
X                PC = *t;
X
X        CL = tgetstr("cl", &p);
X        CM = tgetstr("cm", &p);
X        CE = tgetstr("ce", &p);
X        UP = tgetstr("up", &p);
X	SE = tgetstr("se", &p);
X	SO = tgetstr("so", &p);
X	if (SO != NULL)
X		revexist = TRUE;
X
X        if(CL == NULL || CM == NULL || UP == NULL)
X        {
X                puts("Incomplete termcap entry\n");
X                exit(1);
X        }
X
X	if (CE == NULL)		/* will we be able to use clear to EOL? */
X		eolexist = FALSE;
X		
X        if (p >= &tcapbuf[TCAPSLEN])
X        {
X                puts("Terminal description too big!\n");
X                exit(1);
X        }
X        ttopen();
X}
X
Xtcapmove(row, col)
Xregister int row, col;
X{
X        putpad(tgoto(CM, col, row));
X}
X
Xtcapeeol()
X{
X        putpad(CE);
X}
X
Xtcapeeop()
X{
X        putpad(CL);
X}
X
Xtcaprev(state)		/* change reverse video status */
X
Xint state;		/* FALSE = normal video, TRUE = reverse video */
X
X{
X	static int revstate = FALSE;
X	/* mustn't send SE unless SO already sent, and vice versa */
X
X#if 0
X	if (state) {
X		if ((SO != NULL) && (revstate == FALSE))
X			putpad(SO);
X	} else
X		if ((SE != NULL) && (revstate == TRUE))
X			putpad(SE);
X
X	revstate = state;
X#endif
X	if (state) {
X		if (SO != NULL)
X			putpad(SO);
X	} else
X		if (SE != NULL)
X			putpad(SE);
X}
X
X#if	COLOR
Xtcapfcol()	/* no colors here, ignore this */
X{
X}
X
Xtcapbcol()	/* no colors here, ignore this */
X{
X}
X#endif
X
Xtcapbeep()
X{
X	ttputc(BEL);
X}
X
Xputpad(str)
Xchar    *str;
X{
X	tputs(str, 1, ttputc);
X}
X
Xputnpad(str, n)
Xchar    *str;
X{
X	tputs(str, n, ttputc);
X}
X
X#else
X
Xhello()
X{
X}
X
X#endif TERMCAP
FRIDAY_NIGHT
echo extracting - termio.c
sed 's/^X//' > termio.c << 'FRIDAY_NIGHT'
X/*
X * The functions in this file negotiate with the operating system for
X * characters, and write characters in a barely buffered fashion on the display.
X * All operating systems.
X */
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if     AMIGA
X#define NEW 1006
X#define AMG_MAXBUF      1024
Xstatic long terminal;
Xstatic char     scrn_tmp[AMG_MAXBUF+1];
Xstatic int      scrn_tmp_p = 0;
X#endif
X
X#if     VMS
X#include        <stsdef.h>
X#include        <ssdef.h>
X#include        <descrip.h>
X#include        <iodef.h>
X#include        <ttdef.h>
X#include	<tt2def.h>
X
X#define NIBUF   128                     /* Input buffer size            */
X#define NOBUF   1024                    /* MM says bug buffers win!     */
X#define EFN     0                       /* Event flag                   */
X
Xchar    obuf[NOBUF];                    /* Output buffer                */
Xint     nobuf;                  /* # of bytes in above    */
Xchar    ibuf[NIBUF];                    /* Input buffer          */
Xint     nibuf;                  /* # of bytes in above  */
Xint     ibufi;                  /* Read index                   */
Xint     oldmode[3];                     /* Old TTY mode bits            */
Xint     newmode[3];                     /* New TTY mode bits            */
Xshort   iochan;                  /* TTY I/O channel             */
X#endif
X
X#if     CPM
X#include        <bdos.h>
X#endif
X
X#if     MSDOS & (LATTICE | MSDOS)
Xunion REGS rg;		/* cpu register for use of DOS calls */
Xint nxtchar = -1;	/* character held from type ahead    */
X#endif
X
X#if RAINBOW
X#include "rainbow.h"
X#endif
X
X#if	USG			/* System V */
X#include	<signal.h>
X#include	<termio.h>
Xstruct	termio	otermio;	/* original terminal characteristics */
Xstruct	termio	ntermio;	/* charactoristics to use inside */
X#endif
X
X#if V7 | BSD
X#undef	CTRL
X#include        <sgtty.h>        /* for stty/gtty functions */
X#include	<signal.h>
Xstruct  sgttyb  ostate;          /* saved tty state */
Xstruct  sgttyb  nstate;          /* values for editor mode */
Xstruct tchars	otchars;	/* Saved terminal special character set */
Xstruct tchars	ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
X				/* A lot of nothing */
X#if BSD
X#include <sys/ioctl.h>		/* to get at the typeahead */
Xextern	int rtfrmshell();	/* return from suspended shell */
X#define	TBUFSIZ	128
Xchar tobuf[TBUFSIZ];		/* terminal output buffer */
X#endif
X#endif
X
X/*
X * This function is called once to set up the terminal device streams.
X * On VMS, it translates TT until it finds the terminal, then assigns
X * a channel to it and sets it raw. On CPM it is a no-op.
X */
Xttopen()
X{
X	/* on all screens we are not sure of the initial position
X	   of the cursor					*/
X	ttrow = 999;
X	ttcol = 999;
X
X#if     AMIGA
X        terminal = Open("RAW:1/1/639/199/MicroEMACS 3.7/Amiga", NEW);
X#endif
X#if     VMS
X        struct  dsc$descriptor  idsc;
X        struct  dsc$descriptor  odsc;
X        char    oname[40];
X        int     iosb[2];
X        int     status;
X
X        odsc.dsc$a_pointer = "TT";
X        odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
X        odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
X        odsc.dsc$b_class        = DSC$K_CLASS_S;
X        idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
X        idsc.dsc$b_class        = DSC$K_CLASS_S;
X        do {
X                idsc.dsc$a_pointer = odsc.dsc$a_pointer;
X                idsc.dsc$w_length  = odsc.dsc$w_length;
X                odsc.dsc$a_pointer = &oname[0];
X                odsc.dsc$w_length  = sizeof(oname);
X                status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
X                if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
X                        exit(status);
X                if (oname[0] == 0x1B) {
X                        odsc.dsc$a_pointer += 4;
X                        odsc.dsc$w_length  -= 4;
X                }
X        } while (status == SS$_NORMAL);
X        status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
X        if (status != SS$_NORMAL)
X                exit(status);
X        status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
X                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                exit(status);
X        newmode[0] = oldmode[0];
X        newmode[1] = oldmode[1] | TT$M_NOECHO;
X        newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
X        newmode[2] = oldmode[2] | TT2$M_PASTHRU;
X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X                          newmode, sizeof(newmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                exit(status);
X        term.t_nrow = (newmode[1]>>24) - 1;
X        term.t_ncol = newmode[0]>>16;
X
X#endif
X#if     CPM
X#endif
X
X#if     MSDOS & (HP150 == 0) & LATTICE
X	/* kill the ctrl-break interupt */
X	rg.h.ah = 0x33;		/* control-break check dos call */
X	rg.h.al = 1;		/* set the current state */
X	rg.h.dl = 0;		/* set it OFF */
X	intdos(&rg, &rg);	/* go for it! */
X#endif
X
X#if	USG
X	ioctl(o, TCGETA, &otermio);	/* save old settings */
X	ntermio.c_iflag = 0;		/* setup new settings */
X	ntermio.c_oflag = 0;
X	ntermio.c_cflag = otermio.c_cflag;
X	ntermio.c_lflag = 0;
X	ntermio.c_line = otermio.c_line;
X	ntermio.c_cc[VMIN] = 1;
X	ntermio.c_cc[VTIME] = 0;
X	ioctl(0, TCSETA, &ntermio);	/* and activate them */
X#endif
X
X#if     V7 | BSD
X        gtty(0, &ostate);                       /* save old state */
X        gtty(0, &nstate);                       /* get base of new state */
X        nstate.sg_flags |= RAW;
X        nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
X        stty(0, &nstate);                       /* set mode */
X	ioctl(0, TIOCGETC, &otchars);		/* Save old characters */
X	ioctl(0, TIOCSETC, &ntchars);		/* Place new character into K */
X#if	BSD
X	/* provide a smaller terminal output buffer so that
X	   the type ahead detection works better (more often) */
X	setbuffer(stdout, &tobuf[0], TBUFSIZ);
X	signal(SIGTSTP,SIG_DFL);	/* set signals so that we can */
X	signal(SIGCONT,rtfrmshell);	/* suspend & restart emacs */
X#endif
X#endif
X}
X
X/*
X * This function gets called just before we go back home to the command
X * interpreter. On VMS it puts the terminal back in a reasonable state.
X * Another no-operation on CPM.
X */
Xttclose()
X{
X#if     AMIGA
X        amg_flush();
X        Close(terminal);
X#endif
X#if     VMS
X        int     status;
X        int     iosb[1];
X
X        ttflush();
X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X                 oldmode, sizeof(oldmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                exit(status);
X        status = SYS$DASSGN(iochan);
X        if (status != SS$_NORMAL)
X                exit(status);
X#endif
X#if     CPM
X#endif
X#if     MSDOS & (HP150 == 0) & LATTICE
X	/* restore the ctrl-break interupt */
X	rg.h.ah = 0x33;		/* control-break check dos call */
X	rg.h.al = 1;		/* set the current state */
X	rg.h.dl = 1;		/* set it ON */
X	intdos(&rg, &rg);	/* go for it! */
X#endif
X
X#if	USG
X	ioctl(0, TCSETA, &otermio);	/* restore terminal settings */
X#endif
X
X#if     V7 | BSD
X        stty(0, &ostate);
X	ioctl(0, TIOCSETC, &otchars);	/* Place old character into K */
X#endif
X}
X
X/*
X * Write a character to the display. On VMS, terminal output is buffered, and
X * we just put the characters in the big array, after checking for overflow.
X * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
X * MS-DOS (use the very very raw console output routine).
X */
Xttputc(c)
X#if     AMIGA
X        char c;
X#endif
X{
X#if     AMIGA
X        scrn_tmp[scrn_tmp_p++] = c;
X        if(scrn_tmp_p>=AMG_MAXBUF)
X                amg_flush();
X#endif
X#if     VMS
X        if (nobuf >= NOBUF)
X                ttflush();
X        obuf[nobuf++] = c;
X#endif
X
X#if     CPM
X        bios(BCONOUT, c, 0);
X#endif
X
X#if     MSDOS & MWC86
X        dosb(CONDIO, c, 0);
X#endif
X
X#if	MSDOS & (LATTICE | AZTEC) & ~IBMPC
X	bdos(6, c, 0);
X#endif
X
X#if RAINBOW
X        Put_Char(c);                    /* fast video */
X#endif
X
X
X#if     V7 | USG | BSD
X        fputc(c, stdout);
X#endif
X}
X
X#if	AMIGA
Xamg_flush()
X{
X        if(scrn_tmp_p)
X                Write(terminal,scrn_tmp,scrn_tmp_p);
X        scrn_tmp_p = 0;
X}
X#endif
X
X/*
X * Flush terminal buffer. Does real work where the terminal output is buffered
X * up. A no-operation on systems where byte at a time terminal I/O is done.
X */
Xttflush()
X{
X#if     AMIGA
X        amg_flush();
X#endif
X#if     VMS
X        int     status;
X        int     iosb[2];
X
X        status = SS$_NORMAL;
X        if (nobuf != 0) {
X                status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
X                         iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
X                if (status == SS$_NORMAL)
X                        status = iosb[0] & 0xFFFF;
X                nobuf = 0;
X        }
X        return (status);
X#endif
X
X#if     CPM
X#endif
X
X#if     MSDOS
X#endif
X
X#if     V7 | USG | BSD
X        fflush(stdout);
X#endif
X}
X
X/*
X * Read a character from the terminal, performing no editing and doing no echo
X * at all. More complex in VMS that almost anyplace else, which figures. Very
X * simple on CPM, because the system can do exactly what you want.
X */
Xttgetc()
X{
X#if     AMIGA
X        char ch;
X        amg_flush();
X        Read(terminal, &ch, 1);
X        return(255 & (int)ch);
X#endif
X#if     VMS
X        int     status;
X        int     iosb[2];
X        int     term[2];
X
X        while (ibufi >= nibuf) {
X                ibufi = 0;
X                term[0] = 0;
X                term[1] = 0;
X                status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
X                         iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
X                if (status != SS$_NORMAL)
X                        exit(status);
X                status = iosb[0] & 0xFFFF;
X                if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
X                        exit(status);
X                nibuf = (iosb[0]>>16) + (iosb[1]>>16);
X                if (nibuf == 0) {
X                        status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
X                                 iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
X                        if (status != SS$_NORMAL
X                        || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
X                                exit(status);
X                        nibuf = (iosb[0]>>16) + (iosb[1]>>16);
X                }
X        }
X        return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
X#endif
X
X#if     CPM
X        return (biosb(BCONIN, 0, 0));
X#endif
X
X#if RAINBOW
X        int Ch;
X
X        while ((Ch = Read_Keyboard()) < 0);
X
X        if ((Ch & Function_Key) == 0)
X                if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
X                        Ch &= 0xFF;
X
X        return Ch;
X#endif
X
X#if     MSDOS & MWC86
X        return (dosb(CONRAW, 0, 0));
X#endif
X
X#if	MSDOS & (LATTICE | MSC)
X	int c;		/* character read */
X
X	/* if a char already is ready, return it */
X	if (nxtchar >= 0) {
X		c = nxtchar;
X		nxtchar = -1;
X		return(c);
X	}
X
X	/* call the dos to get a char */
X	rg.h.ah = 7;		/* dos Direct Console Input call */
X	intdos(&rg, &rg);
X	c = rg.h.al;		/* grab the char */
X	return(c & 255);
X#endif
X
X#if	MSDOS & AZTEC
X	int c;		/* character read */
X
X	/* if a char already is ready, return it */
X	if (nxtchar >= 0) {
X		c = nxtchar;
X		nxtchar = -1;
X		return(c);
X	}
X
X	/* call the dos to get a char */
X	rg.h.ah = 7;		/* dos Direct Console I/O call */
X	sysint(33, &rg, &rg);
X	c = rg.h.al;		/* grab the char */
X	return(c & 255);
X#endif
X
X#if     V7 | USG | BSD
X        return(127 & fgetc(stdin));
X#endif
X}
X
X#if	TYPEAH
X/* typahead:	Check to see if any characters are already in the
X		keyboard buffer
X*/
X
Xtypahead()
X
X{
X#if	MSDOS & (LATTICE | AZTEC)
X	int c;		/* character read */
X	int flags;	/* cpu flags from dos call */
X
X#if	MSC
X	if (kbhit() != 0)
X		return(TRUE);
X	else
X		return(FALSE);
X#endif
X
X	if (nxtchar >= 0)
X		return(TRUE);
X
X	rg.h.ah = 6;	/* Direct Console I/O call */
X	rg.h.dl = 255;	/*         does console input */
X#if	LATTICE
X	flags = intdos(&rg, &rg);
X#else
X	flags = sysint(33, &rg, &rg);
X#endif
X	c = rg.h.al;	/* grab the character */
X
X	/* no character pending */
X	if ((flags & 64) != 0)
X		return(FALSE);
X
X	/* save the character and return true */
X	nxtchar = c;
X	return(TRUE);
X#endif
X
X#if	BSD
X	int x;	/* holds # of pending chars */
X
X	return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
X#endif
X	return(FALSE);
X}
X#endif
X
FRIDAY_NIGHT
echo extracting - vmsvt.c
sed 's/^X//' > vmsvt.c << 'FRIDAY_NIGHT'
X/*
X *  VMS terminal handling routines
X *
X *  Known types are:
X *    VT52, VT100, and UNKNOWN (which is defined to be an ADM3a)
X *    written by Curtis Smith
X */
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X#if     VMSVT
X
X#define	termdef	1			/* don't define "term" external */
X
X#include <ssdef.h>		/* Status code definitions		*/
X#include <descrip.h>		/* Descriptor structures		*/
X#include <iodef.h>		/* IO commands				*/
X#include <ttdef.h>		/* tty commands				*/
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern  int	vmsopen();
Xextern  int	vmseeol();
Xextern  int	vmseeop();
Xextern  int	vmsbeep();
Xextern  int	vmsmove();
Xextern	int	vmsrev();
Xextern  int	eolexist;
X#if	COLOR
Xextern	int	vmsfcol();
Xextern	int	vmsbcol();
X#endif
X
X#define	NROWS	24			/* # of screen rolls		*/
X#define	NCOLS	80			/* # of screen columns		*/
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define	NPAUSE	100			/* # times thru update to pause */
X
X/*
X * Dispatch table. All the
X * hard fields just point into the
X * terminal I/O code.
X */
XTERM    term    = {
X	NROWS - 1,
X	NCOLS,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        &vmsopen,
X        &ttclose,
X        &ttgetc,
X        &ttputc,
X        &ttflush,
X        &vmsmove,
X        &vmseeol,
X        &vmseeop,
X        &vmsbeep,
X        &vmsrev
X#if	COLOR
X	, &vmsfcol,
X	&vmsbcol
X#endif
X};
X
Xchar * termeop;			/* Erase to end of page string		*/
Xint eoppad;			/* Number of pad characters after eop	*/
Xchar * termeol;			/* Erase to end of line string		*/
Xint eolpad;			/* Number of pad characters after eol	*/
Xchar termtype;			/* Terminal type identifier		*/
X
X
X/*******
X *  ttputs - Send a string to ttputc
X *******/
X
Xttputs(string)
Xchar * string;
X{
X	while (*string != '\0')
X		ttputc(*string++);
X}
X
X
X/*******
X *  vmspad - Pad the output after an escape sequence
X *******/
X
Xvmspad(count)
Xint count;
X{
X	while (count-- > 0)
X		ttputc('\0');
X}
X
X
X/*******
X *  vmsmove - Move the cursor
X *******/
X
Xvmsmove(row, col)
X{
X	switch (termtype) {
X		case TT$_UNKNOWN:
X			ttputc('\033');
X			ttputc('=');
X			ttputc(row+' ');
X			ttputc(col+' ');
X			break;
X		case TT$_VT52:
X			ttputc('\033');
X			ttputc('Y');
X			ttputc(row+' ');
X			ttputc(col+' ');
X			break;
X                case TT$_VT100:         /* I'm assuming that all these  */
X                case TT$_VT101:         /* are a super set of the VT100 */
X                case TT$_VT102:         /* If I'm wrong, just remove    */
X                case TT$_VT105:         /* those entries that aren't.   */
X                case TT$_VT125:
X                case TT$_VT131:
X                case TT$_VT132:
X                case TT$_VT200_SERIES:
X			{
X				char buffer[24];
X
X				sprintf(buffer, "\033[%d;%dH", row+1, col+1);
X				ttputs(buffer);
X				vmspad(50);
X			}
X	}
X}
X
X/*******
X *  vmsrev - set the reverse video status
X *******/
X
Xvmsrev(status)
X
Xint status;	/* TRUE = reverse video, FALSE = normal video */
X{
X	switch (termtype) {
X		case TT$_UNKNOWN:
X			break;
X		case TT$_VT52:
X			break;
X		case TT$_VT100:
X			if (status) {
X				ttputc('\033');
X				ttputc('[');
X				ttputc('7');
X				ttputc('m');
X			} else {
X				ttputc('\033');
X				ttputc('[');
X				ttputc('m');
X			}
X			break;
X	}
X}
X
X#if	COLOR
X/*******
X *  vmsfcol - Set the forground color (not implimented)
X *******/
X 
Xvmsfcol()
X{
X}
X
X/*******
X *  vmsbcol - Set the background color (not implimented)
X *******/
X 
Xvmsbcol()
X{
X}
X#endif
X
X/*******
X *  vmseeol - Erase to end of line
X *******/
X
Xvmseeol()
X{
X	ttputs(termeol);
X	vmspad(eolpad);
X}
X
X
X/*******
X *  vmseeop - Erase to end of page (clear screen)
X *******/
X
Xvmseeop()
X{
X	ttputs(termeop);
X	vmspad(eoppad);
X}
X
X
X/*******
X *  vmsbeep - Ring the bell
X *******/
X
Xvmsbeep()
X{
X	ttputc('\007');
X}
X
X
X/*******
X *  vmsopen - Get terminal type and open terminal
X *******/
X
Xvmsopen()
X{
X	termtype = vmsgtty();
X	switch (termtype) {
X		case TT$_UNKNOWN:	/* Assume ADM3a	*/
X			eolexist = FALSE;
X			termeop = "\032";
X			eoppad = 0;
X			break;
X		case TT$_VT52:
X			termeol = "\033K";
X			eolpad = 0;
X			termeop = "\033H\033J";
X			eoppad = 0;
X			break;
X		case TT$_VT100:
X			revexist = TRUE;
X			termeol = "\033[K";
X			eolpad = 3;
X			termeop = "\033[;H\033[2J";
X			eoppad = 50;
X			break;
X		default:
X			puts("Terminal type not supported");
X			exit (SS$_NORMAL);
X	}
X        ttopen();
X}
X
X
Xstruct iosb {			/* I/O status block			*/
X	short	i_cond;		/* Condition value			*/
X	short	i_xfer;		/* Transfer count			*/
X	long	i_info;		/* Device information			*/
X};
X
Xstruct termchar {		/* Terminal characteristics		*/
X	char	t_class;	/* Terminal class			*/
X	char	t_type;		/* Terminal type			*/
X	short	t_width;	/* Terminal width in characters		*/
X	long	t_mandl;	/* Terminal's mode and length		*/
X	long	t_extend;	/* Extended terminal characteristics	*/
X};
X
X/*******
X *  vmsgtty - Get terminal type from system control block
X *******/
X
Xvmsgtty()
X{
X	short fd;
X	int status;
X	struct iosb iostatus;
X	struct termchar tc;
X	$DESCRIPTOR(devnam, "SYS$INPUT");
X
X	status = sys$assign(&devnam, &fd, 0, 0);
X	if (status != SS$_NORMAL)
X		exit (status);
X
X	status = sys$qiow(		/* Queue and wait		*/
X		0,			/* Wait on event flag zero	*/
X		fd,			/* Channel to input terminal	*/
X		IO$_SENSEMODE,		/* Get current characteristic	*/
X		&iostatus,		/* Status after operation	*/
X		0, 0,			/* No AST service		*/
X		&tc,			/* Terminal characteristics buf	*/
X		sizeof(tc),		/* Size of the buffer		*/
X		0, 0, 0, 0);		/* P3-P6 unused			*/
X
X					/* De-assign the input device	*/
X	if (sys$dassgn(fd) != SS$_NORMAL)
X		exit(status);
X
X	if (status != SS$_NORMAL)	/* Jump out if bad status	*/
X		exit(status);
X	if (iostatus.i_cond != SS$_NORMAL)
X		exit(iostatus.i_cond);
X
X	return tc.t_type;		/* Return terminal type		*/
X}
X
X#else
X
Xhellovms()
X
X{
X}
X
X#endif	VMSVT
FRIDAY_NIGHT
echo extracting - vt52.c
sed 's/^X//' > vt52.c << 'FRIDAY_NIGHT'
X/*
X * The routines in this file
X * provide support for VT52 style terminals
X * over a serial line. The serial I/O services are
X * provided by routines in "termio.c". It compiles
X * into nothing if not a VT52 style device. The
X * bell on the VT52 is terrible, so the "beep"
X * routine is conditionalized on defining BEL.
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     VT52
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	100			/* # times thru update to pause */
X#define BIAS    0x20                    /* Origin 0 coordinate bias.    */
X#define ESC     0x1B                    /* ESC character.               */
X#define BEL     0x07                    /* ascii bell character         */
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern  int     vt52move();
Xextern  int     vt52eeol();
Xextern  int     vt52eeop();
Xextern  int     vt52beep();
Xextern  int     vt52open();
Xextern	int	vt52rev();
X#if	COLOR
Xextern	int	vt52fcol();
Xextern	int	vt52bcol();
X#endif
X
X/*
X * Dispatch table. All the
X * hard fields just point into the
X * terminal I/O code.
X */
XTERM    term    = {
X        NROW-1,
X        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        &vt52open,
X        &ttclose,
X        &ttgetc,
X        &ttputc,
X        &ttflush,
X        &vt52move,
X        &vt52eeol,
X        &vt52eeop,
X        &vt52beep,
X        &vt52rev
X#if	COLOR
X	, &vt52fcol,
X	&vt52bcol
X#endif
X};
X
Xvt52move(row, col)
X{
X        ttputc(ESC);
X        ttputc('Y');
X        ttputc(row+BIAS);
X        ttputc(col+BIAS);
X}
X
Xvt52eeol()
X{
X        ttputc(ESC);
X        ttputc('K');
X}
X
Xvt52eeop()
X{
X        ttputc(ESC);
X        ttputc('J');
X}
X
Xvt52rev(status)	/* set the reverse video state */
X
Xint status;	/* TRUE = reverse video, FALSE = normal video */
X
X{
X	/* can't do this here, so we won't */
X}
X
X#if	COLOR
Xvt52fcol()	/* set the forground color [NOT IMPLIMENTED] */
X{
X}
X
Xvt52bcol()	/* set the background color [NOT IMPLIMENTED] */
X{
X}
X#endif
X
Xvt52beep()
X{
X#ifdef  BEL
X        ttputc(BEL);
X        ttflush();
X#endif
X}
X
X#endif
X
Xvt52open()
X{
X#if     V7 | BSD
X        register char *cp;
X        char *getenv();
X
X        if ((cp = getenv("TERM")) == NULL) {
X                puts("Shell variable TERM not defined!");
X                exit(1);
X        }
X        if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
X                puts("Terminal type not 'vt52'or 'z19' !");
X                exit(1);
X        }
X#endif
X        ttopen();
X}
FRIDAY_NIGHT
echo extracting - window.c
sed 's/^X//' > window.c << 'FRIDAY_NIGHT'
X/*
X * Window management. Some of the functions are internal, and some are
X * attached to keys that the user actually types.
X */
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X/*
X * Reposition dot in the current window to line "n". If the argument is
X * positive, it is that line. If it is negative it is that line from the
X * bottom. If it is 0 the window is centered (this is what the standard
X * redisplay code does). With no argument it defaults to 0. Bound to M-!.
X */
Xreposition(f, n)
X    {
X    if (f == FALSE)	/* default to 0 to center screen */
X	n = 0;
X    curwp->w_force = n;
X    curwp->w_flag |= WFFORCE;
X    return (TRUE);
X    }
X
X/*
X * Refresh the screen. With no argument, it just does the refresh. With an
X * argument it recenters "." in the current window. Bound to "C-L".
X */
Xrefresh(f, n)
X    {
X    if (f == FALSE)
X        sgarbf = TRUE;
X    else
X        {
X        curwp->w_force = 0;             /* Center dot. */
X        curwp->w_flag |= WFFORCE;
X        }
X
X    return (TRUE);
X    }
X
X/*
X * The command make the next window (next => down the screen) the current
X * window. There are no real errors, although the command does nothing if
X * there is only 1 window on the screen. Bound to "C-X C-N".
X *
X * with an argument this command finds the <n>th window from the top
X *
X */
Xnextwind(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X	register WINDOW *wp;
X	register int nwindows;		/* total number of windows */
X
X	if (f) {
X
X		/* first count the # of windows */
X		wp = wheadp;
X		nwindows = 1;
X		while (wp->w_wndp != NULL) {
X			nwindows++;
X			wp = wp->w_wndp;
X		}
X
X		/* if the argument is negative, it is the nth window
X		   from the bottom of the screen			*/
X		if (n < 0)
X			n = nwindows + n + 1;
X
X		/* if an argument, give them that window from the top */
X		if (n > 0 && n <= nwindows) {
X			wp = wheadp;
X			while (--n)
X				wp = wp->w_wndp;
X		} else {
X			mlwrite("Window number out of range");
X			return(FALSE);
X		}
X	} else
X		if ((wp = curwp->w_wndp) == NULL)
X			wp = wheadp;
X	curwp = wp;
X	curbp = wp->w_bufp;
X	upmode();
X	return (TRUE);
X}
X
X/*
X * This command makes the previous window (previous => up the screen) the
X * current window. There arn't any errors, although the command does not do a
X * lot if there is 1 window.
X */
Xprevwind(f, n)
X{
X	register WINDOW *wp1;
X	register WINDOW *wp2;
X	register int nwindows;	/* total # of windows */
X
X	/* if we have an argument, we mean the nth window from the bottom */
X	if (f)
X		return(nextwind(f, -n));
X
X	wp1 = wheadp;
X	wp2 = curwp;
X
X	if (wp1 == wp2)
X		wp2 = NULL;
X
X	while (wp1->w_wndp != wp2)
X		wp1 = wp1->w_wndp;
X
X	curwp = wp1;
X	curbp = wp1->w_bufp;
X	upmode();
X	return (TRUE);
X}
X
X/*
X * This command moves the current window down by "arg" lines. Recompute the
X * top line in the window. The move up and move down code is almost completely
X * the same; most of the work has to do with reframing the window, and picking
X * a new dot. We share the code by having "move down" just be an interface to
X * "move up". Magic. Bound to "C-X C-N".
X */
Xmvdnwind(f, n)
X    int n;
X    {
X    return (mvupwind(f, -n));
X    }
X
X/*
X * Move the current window up by "arg" lines. Recompute the new top line of
X * the window. Look to see if "." is still on the screen. If it is, you win.
X * If it isn't, then move "." to center it in the new framing of the window
X * (this command does not really move "."; it moves the frame). Bound to
X * "C-X C-P".
X */
Xmvupwind(f, n)
X    int n;
X    {
X    register LINE *lp;
X    register int i;
X
X    lp = curwp->w_linep;
X
X    if (n < 0)
X        {
X        while (n++ && lp!=curbp->b_linep)
X            lp = lforw(lp);
X        }
X    else
X        {
X        while (n-- && lback(lp)!=curbp->b_linep)
X            lp = lback(lp);
X        }
X
X    curwp->w_linep = lp;
X    curwp->w_flag |= WFHARD;            /* Mode line is OK. */
X
X    for (i = 0; i < curwp->w_ntrows; ++i)
X        {
X        if (lp == curwp->w_dotp)
X            return (TRUE);
X        if (lp == curbp->b_linep)
X            break;
X        lp = lforw(lp);
X        }
X
X    lp = curwp->w_linep;
X    i  = curwp->w_ntrows/2;
X
X    while (i-- && lp != curbp->b_linep)
X        lp = lforw(lp);
X
X    curwp->w_dotp  = lp;
X    curwp->w_doto  = 0;
X    return (TRUE);
X    }
X
X/*
X * This command makes the current window the only window on the screen. Bound
X * to "C-X 1". Try to set the framing so that "." does not have to move on the
X * display. Some care has to be taken to keep the values of dot and mark in
X * the buffer structures right if the distruction of a window makes a buffer
X * become undisplayed.
X */
Xonlywind(f, n)
X{
X        register WINDOW *wp;
X        register LINE   *lp;
X        register int    i;
X
X        while (wheadp != curwp) {
X                wp = wheadp;
X                wheadp = wp->w_wndp;
X                if (--wp->w_bufp->b_nwnd == 0) {
X                        wp->w_bufp->b_dotp  = wp->w_dotp;
X                        wp->w_bufp->b_doto  = wp->w_doto;
X                        wp->w_bufp->b_markp = wp->w_markp;
X                        wp->w_bufp->b_marko = wp->w_marko;
X                }
X                free((char *) wp);
X        }
X        while (curwp->w_wndp != NULL) {
X                wp = curwp->w_wndp;
X                curwp->w_wndp = wp->w_wndp;
X                if (--wp->w_bufp->b_nwnd == 0) {
X                        wp->w_bufp->b_dotp  = wp->w_dotp;
X                        wp->w_bufp->b_doto  = wp->w_doto;
X                        wp->w_bufp->b_markp = wp->w_markp;
X                        wp->w_bufp->b_marko = wp->w_marko;
X                }
X                free((char *) wp);
X        }
X        lp = curwp->w_linep;
X        i  = curwp->w_toprow;
X        while (i!=0 && lback(lp)!=curbp->b_linep) {
X                --i;
X                lp = lback(lp);
X        }
X        curwp->w_toprow = 0;
X        curwp->w_ntrows = term.t_nrow-1;
X        curwp->w_linep  = lp;
X        curwp->w_flag  |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Delete the current window, placing its space in the window above,
X * or, if it is the top window, the window below. Bound to C-X 0.
X */
X
Xdelwind(f,n)
X
Xint f, n;	/* arguments are ignored for this command */
X
X{
X	register WINDOW *wp;	/* window to recieve deleted space */
X	register WINDOW *lwp;	/* ptr window before curwp */
X	register int target;	/* target line to search for */
X
X	/* if there is only one window, don't delete it */
X	if (wheadp->w_wndp == NULL) {
X		mlwrite("Can not delete this window");
X		return(FALSE);
X	}
X
X	/* find window before curwp in linked list */
X	wp = wheadp;
X	lwp = NULL;
X	while (wp != NULL) {
X		if (wp == curwp)
X			break;
X		lwp = wp;
X		wp = wp->w_wndp;
X	}
X
X	/* find recieving window and give up our space */
X	wp = wheadp;
X	if (curwp->w_toprow == 0) {
X		/* find the next window down */
X		target = curwp->w_ntrows + 1;
X		while (wp != NULL) {
X			if (wp->w_toprow == target)
X				break;
X			wp = wp->w_wndp;
X		}
X		if (wp == NULL)
X			return(FALSE);
X		wp->w_toprow = 0;
X		wp->w_ntrows += target;
X	} else {
X		/* find the next window up */
X		target = curwp->w_toprow - 1;
X		while (wp != NULL) {
X			if ((wp->w_toprow + wp->w_ntrows) == target)
X				break;
X			wp = wp->w_wndp;
X		}
X		if (wp == NULL)
X			return(FALSE);
X		wp->w_ntrows += 1 + curwp->w_ntrows;
X	}
X
X	/* get rid of the current window */
X	if (--curwp->w_bufp->b_nwnd == 0) {
X		curwp->w_bufp->b_dotp = curwp->w_dotp;
X		curwp->w_bufp->b_doto = curwp->w_doto;
X		curwp->w_bufp->b_markp = curwp->w_markp;
X		curwp->w_bufp->b_marko = curwp->w_marko;
X	}
X	if (lwp == NULL)
X		wheadp = curwp->w_wndp;
X	else
X		lwp->w_wndp = curwp->w_wndp;
X	free((char *)curwp);
X	curwp = wp;
X	wp->w_flag |= WFHARD;
X	curbp = wp->w_bufp;
X	upmode();
X	return(TRUE);
X}
X
X/*
X
XSplit the current window.  A window smaller than 3 lines cannot be
Xsplit.  An argument of 1 forces the cursor into the upper window, an
Xargument of two forces the cursor to the lower window.  The only other
Xerror that is possible is a "malloc" failure allocating the structure
Xfor the new window.  Bound to "C-X 2". 
X
X */
Xsplitwind(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X        register WINDOW *wp;
X        register LINE   *lp;
X        register int    ntru;
X        register int    ntrl;
X        register int    ntrd;
X        register WINDOW *wp1;
X        register WINDOW *wp2;
X	char *malloc();
X
X        if (curwp->w_ntrows < 3) {
X                mlwrite("Cannot split a %d line window", curwp->w_ntrows);
X                return (FALSE);
X        }
X        if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
X                mlwrite("Cannot allocate WINDOW block");
X                return (FALSE);
X        }
X        ++curbp->b_nwnd;                        /* Displayed twice.     */
X        wp->w_bufp  = curbp;
X        wp->w_dotp  = curwp->w_dotp;
X        wp->w_doto  = curwp->w_doto;
X        wp->w_markp = curwp->w_markp;
X        wp->w_marko = curwp->w_marko;
X        wp->w_flag  = 0;
X        wp->w_force = 0;
X#if	COLOR
X	/* set the colors of the new window */
X	wp->w_fcolor = gfcolor;
X	wp->w_bcolor = gbcolor;
X#endif
X        ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
X        ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
X        lp = curwp->w_linep;
X        ntrd = 0;
X        while (lp != curwp->w_dotp) {
X                ++ntrd;
X                lp = lforw(lp);
X        }
X        lp = curwp->w_linep;
X        if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
X                /* Old is upper window. */
X                if (ntrd == ntru)               /* Hit mode line.       */
X                        lp = lforw(lp);
X                curwp->w_ntrows = ntru;
X                wp->w_wndp = curwp->w_wndp;
X                curwp->w_wndp = wp;
X                wp->w_toprow = curwp->w_toprow+ntru+1;
X                wp->w_ntrows = ntrl;
X        } else {                                /* Old is lower window  */
X                wp1 = NULL;
X                wp2 = wheadp;
X                while (wp2 != curwp) {
X                        wp1 = wp2;
X                        wp2 = wp2->w_wndp;
X                }
X                if (wp1 == NULL)
X                        wheadp = wp;
X                else
X                        wp1->w_wndp = wp;
X                wp->w_wndp   = curwp;
X                wp->w_toprow = curwp->w_toprow;
X                wp->w_ntrows = ntru;
X                ++ntru;                         /* Mode line.           */
X                curwp->w_toprow += ntru;
X                curwp->w_ntrows  = ntrl;
X                while (ntru--)
X                        lp = lforw(lp);
X        }
X        curwp->w_linep = lp;                    /* Adjust the top lines */
X        wp->w_linep = lp;                       /* if necessary.        */
X        curwp->w_flag |= WFMODE|WFHARD;
X        wp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Enlarge the current window. Find the window that loses space. Make sure it
X * is big enough. If so, hack the window descriptions, and ask redisplay to do
X * all the hard work. You don't just set "force reframe" because dot would
X * move. Bound to "C-X Z".
X */
Xenlargewind(f, n)
X{
X        register WINDOW *adjwp;
X        register LINE   *lp;
X        register int    i;
X
X        if (n < 0)
X                return (shrinkwind(f, -n));
X        if (wheadp->w_wndp == NULL) {
X                mlwrite("Only one window");
X                return (FALSE);
X        }
X        if ((adjwp=curwp->w_wndp) == NULL) {
X                adjwp = wheadp;
X                while (adjwp->w_wndp != curwp)
X                        adjwp = adjwp->w_wndp;
X        }
X        if (adjwp->w_ntrows <= n) {
X                mlwrite("Impossible change");
X                return (FALSE);
X        }
X        if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
X                lp = adjwp->w_linep;
X                for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
X                        lp = lforw(lp);
X                adjwp->w_linep  = lp;
X                adjwp->w_toprow += n;
X        } else {                                /* Shrink above.        */
X                lp = curwp->w_linep;
X                for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
X                        lp = lback(lp);
X                curwp->w_linep  = lp;
X                curwp->w_toprow -= n;
X        }
X        curwp->w_ntrows += n;
X        adjwp->w_ntrows -= n;
X        curwp->w_flag |= WFMODE|WFHARD;
X        adjwp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Shrink the current window. Find the window that gains space. Hack at the
X * window descriptions. Ask the redisplay to do all the hard work. Bound to
X * "C-X C-Z".
X */
Xshrinkwind(f, n)
X{
X        register WINDOW *adjwp;
X        register LINE   *lp;
X        register int    i;
X
X        if (n < 0)
X                return (enlargewind(f, -n));
X        if (wheadp->w_wndp == NULL) {
X                mlwrite("Only one window");
X                return (FALSE);
X        }
X        if ((adjwp=curwp->w_wndp) == NULL) {
X                adjwp = wheadp;
X                while (adjwp->w_wndp != curwp)
X                        adjwp = adjwp->w_wndp;
X        }
X        if (curwp->w_ntrows <= n) {
X                mlwrite("Impossible change");
X                return (FALSE);
X        }
X        if (curwp->w_wndp == adjwp) {           /* Grow below.          */
X                lp = adjwp->w_linep;
X                for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
X                        lp = lback(lp);
X                adjwp->w_linep  = lp;
X                adjwp->w_toprow -= n;
X        } else {                                /* Grow above.          */
X                lp = curwp->w_linep;
X                for (i=0; i<n && lp!=curbp->b_linep; ++i)
X                        lp = lforw(lp);
X                curwp->w_linep  = lp;
X                curwp->w_toprow += n;
X        }
X        curwp->w_ntrows -= n;
X        adjwp->w_ntrows += n;
X        curwp->w_flag |= WFMODE|WFHARD;
X        adjwp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*	Resize the current window to the requested size	*/
X
Xresize(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X	int clines;	/* current # of lines in window */
X	
X	/* must have a non-default argument, else ignore call */
X	if (f == FALSE)
X		return(TRUE);
X
X	/* find out what to do */
X	clines = curwp->w_ntrows;
X
X	/* already the right size? */
X	if (clines == n)
X		return(TRUE);
X
X	return(enlargewind(TRUE, n - clines));
X}
X
X/*
X * Pick a window for a pop-up. Split the screen if there is only one window.
X * Pick the uppermost window that isn't the current window. An LRU algorithm
X * might be better. Return a pointer, or NULL on error.
X */
XWINDOW  *
Xwpopup()
X{
X        register WINDOW *wp;
X
X        if (wheadp->w_wndp == NULL              /* Only 1 window        */
X        && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
X                return (NULL);
X        wp = wheadp;                            /* Find window to use   */
X        while (wp!=NULL && wp==curwp)
X                wp = wp->w_wndp;
X        return (wp);
X}
X
Xscrnextup(f, n)		/* scroll the next window up (back) a page */
X
X{
X	nextwind(FALSE, 1);
X	backpage(f, n);
X	prevwind(FALSE, 1);
X}
X
Xscrnextdw(f, n)		/* scroll the next window down (forward) a page */
X
X{
X	nextwind(FALSE, 1);
X	forwpage(f, n);
X	prevwind(FALSE, 1);
X}
X
Xsavewnd(f, n)		/* save ptr to current window */
X
X{
X	swindow = curwp;
X	return(TRUE);
X}
X
Xrestwnd(f, n)		/* restore the saved screen */
X
X{
X	register WINDOW *wp;
X
X	/* find the window */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp == swindow) {
X			curwp = wp;
X			curbp = wp->w_bufp;
X			upmode();
X			return (TRUE);
X		}
X		wp = wp->w_wndp;
X	}
X
X	mlwrite("[No such window exists]");
X	return(FALSE);
X}
FRIDAY_NIGHT
echo es.11 completed!
: That's all folks!