[comp.windows.news] patches to psterm and libcps

sam@pixar.UUCP (06/08/87)

The shar enclosed below contains patches to psterm and a patch to ctops.c
(for -lcps).  All patches are for the 1.0 NeWS release.   Some of these
patches are BSD-specific; e.g. using the hostname() system call to set the
default icon label, and using the gethostbyname() and getservbyname() library
routines.

The psterm patches:

1. Rewrite the termcap string pattern matcher for performance.
2. Rewrite the i/o handling for better reliability (neither the CPS library
   nor psterm had handled i/o errors such as EWOULDBLOCK).
3. Check termcap descriptions for some special cases where a 1-1 inverse
   mapping often does not exist (i.e. multiple termcap capabilities may
   have the same value causing problems for things like so-se, us-ue, ...)
4. Add two command line options to set the frame and icon labels
   (-fl label and -il label).
5. Cause the default icon label to be the host name of the client.
6. Add a keyboard escape sequence that can be use to set the window's
   frame label (for folks that like to alias cd and have the cwd appear
   in the frame label).

A Makefile for use with 4BSD make is also included (Sun's use of the SV
make is a royal pain when porting the client code to non-SV machines.)

The changes to ctops.c:

1. Change 2 putc() loops to fwrite() calls (a big win when using the 4.3BSD
   fwrite() that does bcopy's).
2. Support host names on the right hand side of the ';' in the NEWSSERVER
   environment variable.  If you have NEWSSERVER set to ';foo', then the
   network address of ``foo'' will be looked up, and the /etc/services
   file will be consulted for a ``NeWS'' service.  This virtually eliminates
   any need for the setnewshost program; the (trivial) source of which is
   not included in the 1.0 distribution.
3. Support data types for the CCI.

This psterm appears to run much faster than the one on the 1.0 release
and has been much more robust, but it is still not as fast as xterm or
shelltool.  I've not had the time to figure out exactly where all the
time is being spent, but I'm committed to making it run much faster.

One ugly thing to be aware of.  The CPS library macro ps_flush_PostScript()
does an fflush() followed by a check of ferror().  If the file
descriptor is marked for non-blocking i/o, as in psterm, an EWOULDBLOCK
error will cause your program to exit w/o a clue.  This is common when
you have a fast client driving a server on a slow host (e.g. a CCI
driving a Sun-2).  The changes to psterm almost handle the stream to
the server properly, but not quite -- it is still possible to overrun
the standard I/O buffer.  I believe the correct solution here is either
to rewrite -lcps to avoid the use of standard i/o or, at least, provide
a non-blocking interface to the library.

Sun has assured me that distributing changes of this sort is fine.  I
look forward to fixes and/or additions to my code.

P.S. If you burst the shar in the psterm source directory (or a copy),
     the doit script can be used to apply all the patches.
-----
echo x - doit
sed 's/^X//' >doit <<'*-*-END-of-doit-*-*'
X#! /bin/sh
Xmv Makefile Makefile.sun; mv Makefile.bsd Makefile
Xpatch display.c display.c.patch
Xpatch io.c io.c.patch
Xpatch main.c main.c.patch
Xpatch screen.h screen.h.patch
Xpatch selection.c selection.c.patch
Xpatch signal.c signal.c.patch
Xpatch slave.c slave.c.patch
Xpatch tcap.cps tcap.cps.patch
Xpatch tcap_ops.c tcap_ops.c.patch
Xpatch tcap_parse.c tcap_parse.c.patch
Xpatch termcap.h termcap.h.patch
Xecho "apply ctops.c.patch before rebuilding"
*-*-END-of-doit-*-*
echo x - Makefile.bsd
sed 's/^X//' >Makefile.bsd <<'*-*-END-of-Makefile.bsd-*-*'
X#	Makefile	2.1	87/06/07
X#
XDESTDIR=
XNEWS=	/usr/NeWS
XCFLAGS=	-O -I../../include
XCPS=	${NEWS}/bin/cps
XSRCS= 	display.c io.c main.c selection.c signal.c slave.c \
X	tcap_ops.c tcap_parse.c
XOBJS= 	display.o io.o main.o selection.o signal.o slave.o \
X	tcap_ops.o tcap_parse.o
XLIBS=	-ltermcap ${NEWS}/lib/libcps.a
X
X.SUFFIXES: .h .cps
X.cps.h:
X	${CPS} $*.cps
X
Xpsterm:	${OBJS}
X	${CC} -o psterm ${LDFLAGS} ${OBJS} ${LIBS}
X
Xinstall: psterm
X	install psterm ${DESTDIR}/${NEWS}/bin/psterm
X
Xdisplay.o: tcap.h
X
Xclean:
X	rm -f *.o psterm tcap tcap.h tcap.h.BAK core a.out Makefile.bak
X
Xdepend:
X	for i in ${SRCS}; do \
X	    cc -M ${CFLAGS} $$i | sed 's/\.o//' | \
X	    awk ' { if ($$1 != prev) \
X		{ if (rec != "") print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X		else rec = rec " " $$2 } } \
X		END { print rec } ' >> makedep; done
X	echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ed - Makefile < eddep
X	rm eddep makedep
X	echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
X	echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
X	echo '# see make depend above' >> Makefile
X
X# DO NOT DELETE THIS LINE
X
Xdisplay: display.c ./screen.h /usr/include/sys/types.h
Xdisplay: display.c ./screen.h /usr/include/sys/types.h ./tcap.h
Xdisplay: /usr/include/stdio.h
Xio: io.c /usr/include/stdio.h /usr/include/errno.h /usr/include/fcntl.h
Xmain: main.c /usr/include/stdio.h /usr/include/sys/ioctl.h
Xmain: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
Xselection: selection.c ./screen.h /usr/include/sys/types.h ./tcap.h
Xselection: /usr/include/stdio.h
Xsignal: signal.c /usr/include/signal.h /usr/include/sgtty.h
Xsignal: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
Xsignal: /usr/include/sys/ttydev.h /usr/include/sys/wait.h
Xsignal: /usr/include/machine/machparam.h /usr/include/stdio.h
Xslave: slave.c /usr/include/stdio.h /usr/include/sgtty.h
Xslave: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
Xslave: /usr/include/sys/ttydev.h /usr/include/sys/errno.h
Xtcap_ops: tcap_ops.c /usr/include/stdio.h ./termcap.h /usr/include/sys/types.h
Xtcap_ops: ./screen.h /usr/include/sys/types.h
Xtcap_parse: tcap_parse.c /usr/include/stdio.h /usr/include/ctype.h ./termcap.h
Xtcap_parse: /usr/include/sys/types.h
X# DEPENDENCIES MUST END AT END OF FILE
X# IF YOU PUT STUFF HERE IT WILL GO AWAY
X# see make depend above
*-*-END-of-Makefile.bsd-*-*
echo x - ctops.c.patch
sed 's/^X//' >ctops.c.patch <<'*-*-END-of-ctops.c.patch-*-*'
X*** /tmp/d14201	Sun Jun  7 13:31:27 1987
X--- ctops.c	Sun Jun  7 13:31:22 1987
X***************
X*** 44,58 ****
X  
X  
X  #include <stdio.h>
X! #include <sys/types.h>
X  #include <sys/socket.h>
X  #include <sys/ioctl.h>
X  #include <netinet/in.h>
X  #include <net/if.h>
X  #include <ctype.h>
X  #include <varargs.h>
X  #include "encoding.h"
X  #include "psio.h"
X  
X  
X  FILE       *PostScript,
X--- 44,60 ----
X  
X  
X  #include <stdio.h>
X! #include <sys/param.h>
X  #include <sys/socket.h>
X  #include <sys/ioctl.h>
X  #include <netinet/in.h>
X+ #include <netinet/tcp.h>
X  #include <net/if.h>
X  #include <ctype.h>
X  #include <varargs.h>
X  #include "encoding.h"
X  #include "psio.h"
X+ #include <netdb.h>
X  
X  
X  FILE       *PostScript,
X***************
X*** 76,92 ****
X  	if (fd < 0)
X  	    return 0;
X  	if (server) {
X! 	    extern char *rindex();
X! 	    register char *t;
X! 	    if (semi = rindex(server, ';'))
X! 		*semi = 0;
X! 	    if (dot = rindex(server, '.')) {
X! 		*dot = 0;
X! 		sin.sin_port = htons(atoi(dot + 1));
X  	    }
X- 	    sin.sin_addr.s_addr = htonl(inet_addr(server));
X- 	    if (dot) *dot = '.';
X- 	    if (semi) *semi = ';';
X  	}
X  	else {
X  
X--- 78,101 ----
X  	if (fd < 0)
X  	    return 0;
X  	if (server) {
X! 	    extern char *index(), *rindex();
X! 	    struct servent *sp;
X! 	    if ((p = index(server, ';')) && (hp = gethostbyname(p+1)))
X! 		bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
X! 	    if (sp = getservbyname("NeWS", "tcp"))
X! 		sin.sin_port = sp->s_port;
X! 	    if (p == 0 || p != server) {
X! 		port = 0;
X! 		if (semi = rindex(server, ';'))
X! 		    *semi = 0;
X! 		if (dot = rindex(server, '.')) {
X! 		    *dot = 0;
X! 		    sin.sin_port = htons(atoi(dot + 1));
X! 		}
X! 		sin.sin_addr.s_addr = htonl(inet_addr(server));
X! 		if (dot) *dot = '.';
X! 		if (semi) *semi = ';';
X  	    }
X  	}
X  	else {
X  
X***************
X*** 142,147 ****
X--- 151,193 ----
X      }
X  }
X  
X+ #ifdef sun
X+ #define	DOUBLEFORMAT \
X+ 	struct { \
X+ 	    unsigned    sign:1; \
X+ 	    unsigned    exp:11; \
X+ 	    unsigned    mant:20; \
X+ 	    unsigned    mant2; \
X+ 	}
X+ #define	isfraction(e)	(1022 - 4 <= (e) && (e) <= 1022 + 15)
X+ #define	extractfraction(dp) \
X+     (((1<<31)|((dp)->u.mant<<11)|((dp)->u.mant2>>21))>>(1022+16-(dp)->u.exp))
X+ #endif
X+ #ifdef tahoe
X+ #define	DOUBLEFORMAT \
X+ 	struct { \
X+ 	    unsigned    sign:1; \
X+ 	    unsigned    exp:8; \
X+ 	    unsigned    mant:23; \
X+ 	    unsigned    mant2; \
X+ 	}
X+ #define	isfraction(e)	(128 - 4 <= (e) && (e) <= 128 + 15)
X+ #define	extractfraction(dp) \
X+     (((1<<31)|((dp)->u.mant<<8)|((dp)->u.mant2>>15))>>(128+16-(dp)->u.exp))
X+ #endif
X+ #ifdef vax
X+ #define	DOUBLEFORMAT \
X+ 	struct { \
X+ 	    unsigned    sign:1; \
X+ 	    unsigned    exp:8; \
X+ 	    unsigned    mant:23; \
X+ 	    unsigned    mant2; \
X+ 	}
X+ #define	isfraction(e)	(128 - 4 <= (e) && (e) <= 128 + 15)
X+ #define	extractfraction(dp) \
X+     (((1<<31)|((dp)->u.mant<<8)|((dp)->u.mant2>>15))>>(128+16-(dp)->u.exp))
X+ #endif
X+ 
X  pprintf(f, fmt, fmtlen, va_alist /* , arg2 ... */ )
X      register FILE *f;
X      register char *fmt;
X***************
X*** 186,192 ****
X  		goto continue_parse;
X  	    case 's':
X  		{
X! 		    register char *string = va_arg(arglist, char *);
X  		    if (width < 0)
X  			width = strlen(string);
X  		    if (width < 16)
X--- 232,238 ----
X  		goto continue_parse;
X  	    case 's':
X  		{
X! 		    char *string = va_arg(arglist, char *);
X  		    if (width < 0)
X  			width = strlen(string);
X  		    if (width < 16)
X***************
X*** 206,222 ****
X  			}
X  			putc(width, f);
X  		    }
X! 		    while (--width >= 0)
X! 			putc(*string++, f);
X  		}
X  		break;
X  	    case 'p':
X  		{
X! 		    register char *string = va_arg(arglist, char *);
X  		    if (width < 0)
X  			width = strlen(string);
X! 		    while (--width >= 0)
X! 			putc(*string++, f);
X  		}
X  		break;
X  	    case 'd':
X--- 252,266 ----
X  			}
X  			putc(width, f);
X  		    }
X! 		    fwrite(string, 1, width, f);
X  		}
X  		break;
X  	    case 'p':
X  		{
X! 		    char *string = va_arg(arglist, char *);
X  		    if (width < 0)
X  			width = strlen(string);
X! 		    fwrite(string, 1, width, f);
X  		}
X  		break;
X  	    case 'd':
X***************
X*** 245,252 ****
X--- 289,298 ----
X  			    if (an < (1 << 15))
X  				putc(enc_int + 1, f);
X  			    else {
X+ #ifdef notdef
X  				fprintf(stderr,
X  					"Warning: CPS is currently limited to 16 bit integers\n");
X+ #endif
X  				if (an < (1 << 23))
X  				    putc(enc_int + 2, f);
X  				else {
X***************
X*** 314,325 ****
X  	    case 'F':
X  		{
X  		    register union double_t {
X! 			struct {
X! 			    unsigned    sign:1;
X! 			    unsigned    exp:11;
X! 			    unsigned    mant:20;
X! 			    unsigned    mant2;
X! 			}           u;
X  			double      d;
X  		    }          *dp;
X  		    register    cnt;
X--- 360,366 ----
X  	    case 'F':
X  		{
X  		    register union double_t {
X! 			DOUBLEFORMAT	u;
X  			double      d;
X  		    }          *dp;
X  		    register    cnt;
X***************
X*** 334,344 ****
X  		    }
X  		    while (1) {
X  			register    exp = dp->u.exp;
X! 			if (1022 - 4 <= exp && exp <= 1022 + 15) {
X  			    register    n;
X  			    register    fractbytes = 2 << 2;
X  			    register    an;
X! 			    n = ((1 << 31) | (dp->u.mant << 11) | (dp->u.mant2 >> 21)) >> (1022 + 16 - dp->u.exp);
X  			    if ((n & 0377) == 0)
X  				n >>= 8, fractbytes -= 1 << 2;
X  			    if ((n & 0377) == 0)
X--- 375,385 ----
X  		    }
X  		    while (1) {
X  			register    exp = dp->u.exp;
X! 			if (isfraction(exp)) {
X  			    register    n;
X  			    register    fractbytes = 2 << 2;
X  			    register    an;
X! 			    n = extractfraction(dp);
X  			    if ((n & 0377) == 0)
X  				n >>= 8, fractbytes -= 1 << 2;
X  			    if ((n & 0377) == 0)
*-*-END-of-ctops.c.patch-*-*
echo x - display.c.patch
sed 's/^X//' >display.c.patch <<'*-*-END-of-display.c.patch-*-*'
X*** ../psterm.sun/display.c	Wed May 27 11:42:07 1987
X--- display.c	Sun Jun  7 13:25:19 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	display.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 65,71 ****
X  
X  u_short     CharsPerLine = CHARS_PER_LINE;
X  u_short     LinesPerScreen = LINES_PER_SCREEN;
X- char	   *contents = NULL;
X  struct pair Dot = {0, 0};
X  
X  static Repairing;
X--- 66,71 ----
X***************
X*** 118,124 ****
X  	     1);
X  }
X  
X! static
X  do_display_resize() {
X      register i;
X      tc_refresh(0);
X--- 118,125 ----
X  	     1);
X  }
X  
X! /* --------------- External Routines Below ------------------- */
X! 
X  do_display_resize() {
X      register i;
X      tc_refresh(0);
X***************
X*** 132,147 ****
X      tc_refresh(0);
X  }
X  
X- /* --------------- External Routines Below ------------------- */
X- 
X  extern int fFlag;
X  
X  FILE       *
X! tc_init_screen(term)
X      char *term;
X  {
X      register int i;
X      FILE       *f;
X      extern char *malloc();
X      extern FILE *ps_open_PostScript();
X  
X--- 133,151 ----
X      tc_refresh(0);
X  }
X  
X  extern int fFlag;
X  
X  FILE       *
X! tc_init_screen(term, framelabel, iconlabel)
X      char *term;
X+     char *framelabel;
X+     char *iconlabel;
X  {
X      register int i;
X      FILE       *f;
X+     char        frametitle[100];
X+     char        icontitle[100];
X+     char	host[100];
X      extern char *malloc();
X      extern FILE *ps_open_PostScript();
X  
X***************
X*** 159,164 ****
X--- 163,169 ----
X  	}
X      }
X  
X+     tc_init_selection();
X      lines = (struct line *) malloc(LinesPerScreen * sizeof(struct line));
X      screen = (struct screen *) malloc(LinesPerScreen * sizeof(struct screen));
X      for (i = 0; i < LinesPerScreen; i++) {
X***************
X*** 171,182 ****
X  	screen[i].lineptr = lines + i;
X  	screen[i].visible = 0;
X      }
X!     contents = malloc((LinesPerScreen * CharsPerLine) + 1);
X!     {
X! 	char        programtitle[100];
X! 	sprintf(programtitle, "%s terminal emulator", term);
X! 	Initialize(WIDTH, HEIGHT, CharsPerLine, LinesPerScreen, programtitle);
X      }
X      StartInput();
X      /* XXX - set up PostScript process for i/p etc. */
X      ps_flush_PostScript();
X--- 176,191 ----
X  	screen[i].lineptr = lines + i;
X  	screen[i].visible = 0;
X      }
X!     if (framelabel == NULL) {
X! 	sprintf(frametitle, "%s terminal emulator", term);
X! 	framelabel = frametitle;
X      }
X+     if (iconlabel == NULL) {
X+         gethostname(host, sizeof (host));
X+ 	iconlabel = host;
X+     }
X+     Initialize(WIDTH, HEIGHT, CharsPerLine, LinesPerScreen,
X+ 	framelabel, iconlabel);
X      StartInput();
X      /* XXX - set up PostScript process for i/p etc. */
X      ps_flush_PostScript();
X***************
X*** 187,192 ****
X--- 196,208 ----
X  #endif
X  }
X  
X+ do_label_change(label)
X+     char	*label;
X+ {
X+ 
X+     SetFrameLabel(label);
X+ }
X+ 
X  tc_refresh(full)
X      int         full;
X  {
X***************
X*** 302,387 ****
X  	EndRepair();
X  	Repairing = 0;
X      }
X!     ps_flush_PostScript();
X  }
X- 
X- #define REDISPLAY	0376
X- #define	SETSELECTIONAT		0200
X- #define	EXTENDSELECTIONTO	0201
X- #define	DESELECT		0202
X- #define	SELECTIONREQUEST	0203
X- 
X- int
X- do_specials(c, n)
X-     unsigned char        c[];
X- {
X-     register unsigned char *p, *d, **dp;
X-     register    n2;
X-     int		col, row, rank;
X- #define NEXTVAL		while (*p != '\n') ++p, --n; ++p, --n;
X- 
X-     for (p = c, n2 = n; --n2 >= 0;) {
X- 	switch (*p++) {
X- 	case REDISPLAY:
X- 	    /*-
X- 	     *  REDISPLAY - no following information,  and further
X- 	     *  REDISPLAY commands in same buffer can be ignored.
X- 	     */
X- 	    {
X- 		do_display_resize();
X- 		d = p - 1;
X- 		n--;
X- 		while (--n2 >= 0)
X- 		    if (*p == REDISPLAY)
X- 			n--, p++;
X- 		    else
X- 			*d++ = *p++;
X- 		break;
X- 	    }
X- 	    break;
X- 	case SETSELECTIONAT:
X- 	    /*-
X- 	     *  SETSELECTIONAT col row rank size mode preview
X- 	     */
X- 	    --n;
X- 	    col = atoi(p);
X- 	    NEXTVAL;
X- 	    row = atoi(p);
X- 	    NEXTVAL;
X- 	    rank = atoi(p);
X- 	    NEXTVAL;
X- 	    tc_select_at(col, row, rank);
X- 	    break;
X- 	case EXTENDSELECTIONTO:
X- 	    /*-
X- 	     *  EXTENDSELECTIONTO col row rank size mode preview
X- 	     */
X- 	    --n;
X- 	    col = atoi(p);
X- 	    NEXTVAL;
X- 	    row = atoi(p);
X- 	    NEXTVAL;
X- 	    rank = atoi(p);
X- 	    NEXTVAL;
X- 	    tc_extend_to(col, row, rank);
X- 	    break;
X- 	case DESELECT:
X- 	    /*-
X- 	     *  DESELECT rank
X- 	     */
X- 	    --n;
X- 	    rank = atoi(p);
X- 	    NEXTVAL;
X- 	    tc_deselect(rank);
X- 	    break;
X- 	case SELECTIONREQUEST:
X- 	    /*-
X- 	     *  SELECTIONREQUEST rank
X- 	     */
X- 	    fprintf(stderr, "got a SELECTIONREQUEST\n");
X- 	    break;
X- 	}
X-     }
X-     return (n);
X- }
X- 
X--- 318,322 ----
X  	EndRepair();
X  	Repairing = 0;
X      }
X!     FlushPostScript();
X  }
*-*-END-of-display.c.patch-*-*
echo x - io.c.patch
sed 's/^X//' >io.c.patch <<'*-*-END-of-io.c.patch-*-*'
X*** ../psterm.sun/io.c	Wed May 27 11:42:09 1987
X--- io.c	Sun Jun  7 13:17:00 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	io.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 31,117 ****
X  static char sccsid[] = "@(#)io.c 1.11 87/03/13 Copyright 1985 Sun Micro";
X  #endif
X  
X  /*
X   * Copyright (c) 1985 by Sun Microsystems, Inc. 
X   */
X  
X  
X! #include	<stdio.h>
X! #include	<errno.h>
X! #include	<fcntl.h>
X  
X! #ifdef REF
X! #define void    int
X! #endif
X! 
X! extern void tc_display();
X! extern      Mfd;
X! 
X! static void
X! kybd_in(c, n)
X!     unsigned char        c[];
X! {
X!     extern int do_specials();
X! 
X!     n = do_specials(c, n);
X!     if (n)
X! 	write(Mfd, c, n);
X  }
X  
X! static struct {
X!     int         fd;
X!     void        (*proc) ();
X!     char       *name;
X! }           rfiles[] = {
X!     {
X! 	            0, tc_display, "client"
X!     }          ,
X!     {
X! 	            0, kybd_in, "keyboard"
X!     }
X! };
X! 
X  terminal(cfd, kfd)
X  {
X!     int         j;
X!     int         rf0 = 0, max = 0;
X!     register int i;
X!     extern int  NoFork;
X  
X!     rfiles[0].fd = cfd;
X!     rfiles[1].fd = kfd;
X!     /*- if (!NoFork)
X!     	for (j = 0; j < (sizeof rfiles) / (sizeof rfiles[0]); j++) {
X!     	    int         i = fcntl(fileno(rfiles[j].fp), F_GETFL, 0);
X! 
X!     	    i |= FNDELAY;
X!     	    fcntl(fileno(rfiles[j].fp), F_SETFL, i);
X!     	} */
X!     for (i = 0; i < (sizeof rfiles) / (sizeof rfiles[0]); i++) {
X! 	rf0 |= (1 << rfiles[i].fd);
X! 	if (max < rfiles[i].fd)
X! 	    max = rfiles[i].fd;
X      }
X!     max++;
X!     while (1) {
X! 	int         rf = rf0;
X  	tc_refresh(0);
X! 	if (select(max, &rf, 0, 0, 0) < 0) {
X  	    perror("select");
X  	    break;
X  	}
X! 	for (i = 0; i < (sizeof rfiles) / (sizeof rfiles[0]); i++) {
X! 	    register    fd = rfiles[i].fd;
X! 	    extern int  errno;
X  	    errno = 0;
X! 	    if (rf & (1 << fd)) {
X! 		unsigned char        buf[2048];
X! 		register    n = read(fd, buf, sizeof buf);
X! 		if (n > 0)
X! 		    (rfiles[i].proc) (buf, n);
X  	    }
X! /*-	    if (errno && errno != EWOULDBLOCK)
X! 		perror("terminal"); */
X  	}
X      }
X  }
X--- 32,245 ----
X  static char sccsid[] = "@(#)io.c 1.11 87/03/13 Copyright 1985 Sun Micro";
X  #endif
X  
X+ 
X  /*
X   * Copyright (c) 1985 by Sun Microsystems, Inc. 
X   */
X  
X+ #include <stdio.h>
X+ #include <errno.h>
X+ #include <fcntl.h>
X  
X! #define	MAX(a,b)	((a)>(b)?(a):(b))
X! #define	KBDBUFSIZE	4096
X! #define	PTYBUFSIZE	8192
X  
X! static	char *kbdbuf, *kbdfront, *kbdback, *kbdend;
X! #define	BUFSETUP(which,size) { \
X!     which/**/buf = malloc(size); which/**/end = which/**/buf + size; \
X!     which/**/front = which/**/back = which/**/buf; \
X  }
X+ static	char *ptybuf;		/* buffer for reading from pty slave */
X+ static	int wfproto;		/* prototype for write select mask */
X+ extern	int Mfd;
X+ extern	int errno;
X+ extern	int NoFork;
X+ extern	char *malloc();
X+ extern	FILE *PostScript;
X  
X! /*
X!  * Input dispatcher: take data from postscript
X!  * program and pty, dispatching each to the
X!  * appropriate handler.
X!  */
X  terminal(cfd, kfd)
X  {
X!     register int n;
X!     int rf, wf, max, keyboard, display, pty, postscript;
X  
X!     keyboard = 1<<kfd;
X!     display = 1<<cfd;
X!     pty = 1<<Mfd;
X!     postscript = 1<<fileno(PostScript);
X!     if (!NoFork) {
X! 	(void) fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0)|FNDELAY);
X! 	(void) fcntl(kfd, F_SETFL, fcntl(kfd, F_GETFL, 0)|FNDELAY);
X      }
X!     max = MAX(kfd, cfd) + 1;
X!     BUFSETUP(kbd, KBDBUFSIZE);
X!     ptybuf = malloc(PTYBUFSIZE);
X!     wfproto = 0;
X!     for (;;) {
X  	tc_refresh(0);
X! 	rf = display, wf = wfproto;
X! 	if (kbdfront == kbdend)		/* no space to read from kbd */
X! 	    rf &= ~keyboard;
X! 	else
X! 	    rf |= keyboard;
X! 	if (select(max, &rf, &wf, 0, 0) < 0) {
X! 	    if (errno == EINTR)
X! 		continue;
X  	    perror("select");
X  	    break;
X  	}
X! 	/*
X! 	 * Flush PostScript descriptor.
X! 	 */
X! 	if (wf & postscript) {
X! 	    wfproto &= ~postscript;
X! 	    FlushPostScript();
X! 	}
X! 	/*
X! 	 * Try to flush pty, if clogged, before reading from keyboard.
X! 	 */
X! 	if (wf & pty) {
X! 	    wfproto &= ~pty;
X! 	    pty_out();
X! 	}
X! 	/*
X! 	 * Take keyboard input.
X! 	 */
X! 	if (rf & keyboard) {
X  	    errno = 0;
X! 	    n = read(kfd, kbdfront, kbdend-kbdfront);
X! 	    if (n < 0) {
X! 		if (errno != EWOULDBLOCK) {
X! 		    if (errno != ECONNRESET)
X! 			    perror("keyboard");
X! 		    break;
X! 		}
X! 	    } else if (n > 0)
X! 		kbd_input(n);
X! 	}
X! 	/*
X! 	 * Finally, take pty stuff and send it to the display.
X! 	 */
X! 	if (rf & display) {
X! 	    errno = 0;
X! 	    n = read(cfd, ptybuf, PTYBUFSIZE);
X! 	    if (n < 0) {
X! 		if (errno != EIO)
X! 			perror("pty");
X! 		break;
X  	    }
X! 	    tc_display(ptybuf, n);
X  	}
X      }
X+ }
X+ 
X+ /*
X+  * Flush PostScript destined for window.
X+  *
X+  * NOTE: Can't use ps_flush_PostScript()
X+  * because it does not handle errors (like EWOULDBLOCK).
X+  */
X+ FlushPostScript()
X+ {
X+     register FILE *fd = PostScript;
X+     register int n, cc;
X+ 
X+     n = fd->_ptr - fd->_base;
X+     if (n > 0) {
X+ 	cc = write(fileno(fd), fd->_base, n);
X+ 	if (cc < 0) {
X+ 	    if (errno != EWOULDBLOCK)	/* presume child died */
X+ 		exit(0);
X+ 	} else {
X+ 	    if (cc && cc != n)		/* adjust past stuff written */
X+ 	        bcopy(fd->_base + cc, fd->_base, n-cc);
X+ 	    fd->_ptr -= cc;
X+ 	    fd->_cnt += cc;
X+ 	}
X+ 	if (fd->_ptr != fd->_base)
X+ 	    wfproto |= 1<<fileno(fd);
X+     }
X+ }
X+ 
X+ /*
X+  * Flush output to pty.
X+  */
X+ static
X+ pty_out()
X+ {
X+ 	register int cc;
X+ 
X+ 	if ((cc = kbdfront - kbdback) > 0) {
X+ 	    cc = write(Mfd, kbdback, cc);
X+ 	    if (cc < 0) {
X+ 		if (errno != EWOULDBLOCK)
X+ 		    perror("master pty");
X+ 	    } else
X+ 		kbdback += cc;
X+ 	}
X+ 	if (kbdfront != kbdback)
X+ 	    wfproto |= 1<<Mfd;		/* must explicity reenable */
X+ 	else
X+ 	    kbdfront = kbdback = kbdbuf;
X+ }
X+ 
X+ #define EVENT_REPAIR		0376	/* window resized or damaged */
X+ #define	EVENT_SETSEL		0200	/* set selection start */
X+ #define	EVENT_EXTENDSEL		0201	/* extend current selection */
X+ #define	EVENT_DESELECT		0202	/* remove current selection */
X+ #define	EVENT_SELREQUEST	0203	/* request held selection */
X+ 
X+ /*
X+  * Handle keyboard input + postscript events.
X+  */
X+ static
X+ kbd_input(n)
X+     register int n;
X+ {
X+     register unsigned char *p, *d, **dp;
X+     register n2;
X+     int	col, row, rank;
X+ 
X+ #define NEXTVAL		while (*p != '\n') ++p, --n; ++p, --n;
X+     for (p = (unsigned char *)kbdfront, n2 = n; --n2 >= 0;) {
X+ 	switch (*p++) {
X+ 	case EVENT_REPAIR:
X+ 	    do_display_resize();
X+ 	    d = p - 1; n--;
X+ 	    while (--n2 >= 0)
X+ 		if (*p == EVENT_REPAIR)
X+ 		    n--, p++;
X+ 		else
X+ 		    *d++ = *p++;
X+ 	    break;
X+ 	case EVENT_SETSEL:		/* col row rank size mode preview */
X+ 	    --n; col = atoi(p);
X+ 	    NEXTVAL; row = atoi(p);
X+ 	    NEXTVAL; rank = atoi(p);
X+ 	    NEXTVAL; tc_select_at(col, row, rank);
X+ 	    break;
X+ 	case EVENT_EXTENDSEL:		/* col row rank size mode preview */
X+ 	    --n; col = atoi(p);
X+ 	    NEXTVAL; row = atoi(p);
X+ 	    NEXTVAL; rank = atoi(p);
X+ 	    NEXTVAL; tc_extend_to(col, row, rank);
X+ 	    break;
X+ 	case EVENT_DESELECT:		/* rank */
X+ 	    --n; rank = atoi(p);
X+ 	    NEXTVAL; tc_deselect(rank);
X+ 	    break;
X+ 	case EVENT_SELREQUEST:		/* rank */
X+ 	    fprintf(stderr, "got a SELECTIONREQUEST\n");
X+ 	    break;
X+ 	}
X+     }
X+     if (n > 0)
X+ 	kbdfront += n;
X+     if (kbdfront != kbdback)
X+ 	pty_out();
X  }
*-*-END-of-io.c.patch-*-*
echo x - main.c.patch
sed 's/^X//' >main.c.patch <<'*-*-END-of-main.c.patch-*-*'
X*** ../psterm.sun/main.c	Wed May 27 11:42:09 1987
X--- main.c	Sun Jun  7 13:17:18 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	main.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 39,117 ****
X  #include	<stdio.h>
X  #include	<sys/ioctl.h>
X  
X! static FILE *Client, *Keyboard;
X! int Persist;
X! int console;
X! static char *term = NULL;
X! static int seed = 0;
X! int NoFork;
X  
X- int fFlag;
X- 
X- static
X- setup(s_name, s_args, term)
X-     char *s_name;
X-     char **s_args;
X-     char *term;
X- {
X-     extern char *getenv();
X-     extern FILE * tc_init_screen();
X-     extern FILE * spawn_slave();
X- 
X-     initialise_signal();
X-     SetupTTYState();
X- /*  fprintf(stderr, "Signals\n"); */
X-     if (tc_initialize(term)) {
X- 	fprintf(stderr, "Cannot initialise %s\n", term);
X- 	exit (1);
X-     }
X- /*  fprintf(stderr, "terminal\n"); */
X-     if ((Keyboard = tc_init_screen(term)) == NULL) {
X- 	fprintf(stderr, "Cannot initialise %s\n", "screen");
X- 	exit (1);
X-     }
X- /*  fprintf(stderr, "screen\n"); */
X-     if ((Client = spawn_slave(s_name, s_args)) == NULL) {
X- 	fprintf(stderr, "Cannot spawn %s\n", s_name);
X- 	exit (1);
X-     }
X- /*  fprintf(stderr, "slave\n"); */
X- }
X- 
X- 
X  main(argc,argv)
X      int	argc;
X      char **argv;
X  {
X!     char *s_name, **s_args;
X! /*  fprintf(stderr, "Parsing args\n"); */
X  
X!     fFlag = 0;
X! 
X!     while (--argc > 0 && **++argv == '-') switch (*++*argv) {
X! 	case 'w':
X  	    Persist++;
X! 	    break;
X! 	case 'x':
X  	    NoFork++;
X! 	    break;
X! 	case 't':
X  	    if (--argc > 0)
X  		term = *++argv;
X! 	    break;
X! 	case 'C':
X  	    console++;
X! 	    break;
X! 	case 's':
X  	    if (--argc > 0)
X  		seed = atoi(*++argv);
X! 	    break;
X! 	case 'f':
X  	    fFlag++;
X! 	    break;
X! 	default:
X! 	    fprintf(stderr, "tcap: bad argument -%s\n", *argv);
X! 	    break;
X      }
X      if (argc > 0) {
X  	s_name = *argv;
X--- 40,103 ----
X  #include	<stdio.h>
X  #include	<sys/ioctl.h>
X  
X! int	Persist;
X! int	console;
X! static	char *term = NULL;
X! static	int seed = 0;
X! int	NoFork;
X! int	fFlag;
X  
X  main(argc,argv)
X      int	argc;
X      char **argv;
X  {
X!     char *s_name, **s_args, *argv0 = argv[0];
X!     FILE *Client, *Keyboard;
X!     char *framelabel = NULL, *iconlabel = NULL;
X!     extern char *getenv();
X!     extern FILE *tc_init_screen(), *spawn_slave();
X  
X!     for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
X! 	if (strcmp(argv[0], "-w") == 0) {
X  	    Persist++;
X! 	    continue;
X! 	}
X! 	if (strcmp(argv[0], "-x") == 0) {
X  	    NoFork++;
X! 	    continue;;
X! 	}
X! 	if (strcmp(argv[0], "-t") == 0) {
X  	    if (--argc > 0)
X  		term = *++argv;
X! 	    continue;
X! 	}
X! 	if (strcmp(argv[0], "-C") == 0) {
X  	    console++;
X! 	    continue;
X! 	}
X! 	if (strcmp(argv[0], "-s") == 0) {
X  	    if (--argc > 0)
X  		seed = atoi(*++argv);
X! 	    continue;
X! 	}
X! 	if (strcmp(argv[0], "-f") == 0) {
X  	    fFlag++;
X! 	    continue;
X! 	}
X! 	if (strcmp(argv[0], "-fl") == 0) {
X! 	    if (--argc > 0)
X! 		framelabel = *++argv;
X! 	    continue;
X! 	}
X! 	if (strcmp(argv[0], "-il") == 0) {
X! 	    if (--argc > 0)
X! 		iconlabel = *++argv;
X! 	    continue;
X! 	}
X! 	fprintf(stderr,
X! "Usage: %s [-w] [-x] [-f] [-t termtype] [-C] [-s seed] [-fl framelabel] [-il iconlabel] [command]\n",
X! 		argv0);
X! 	exit(-1);
X      }
X      if (argc > 0) {
X  	s_name = *argv;
X***************
X*** 125,139 ****
X  	s_args = def_argv;
X  	s_args[0] = s_name;
X      }
X- /*- {
X- 	char **av = s_args;
X- 
X- 	while (*av) {
X- 	    fprintf(stderr, "%s\t", *av);
X- 	    av++;
X- 	}
X- 	fprintf(stderr, "\n");
X-     } */
X      if (term == NULL && (term = getenv("TERM")) == NULL
X  	|| strcmp(term,"PostScript")==0
X  	|| strcmp(term,"emacswindow")==0
X--- 111,116 ----
X***************
X*** 152,166 ****
X  	term = "h19";
X  #endif
X      }
X!     if (strcmp(term, getenv("TERM"))) {
X! 	putenv("TERM", term);
X! 	unsetenv("TERMCAP");
X      }
X! /*- fprintf(stderr, "term is %s\n", term); */
X!     setup(s_name, s_args, term);
X! /*- fprintf(stderr, "Set up\n"); */
X      terminal(fileno(Client), fileno(Keyboard));
X!     exit (0);
X  }
X  
X  #ifndef HAVEPUTENV
X--- 129,150 ----
X  	term = "h19";
X  #endif
X      }
X!     putenv("TERM", term);
X!     if (tc_initialize(term)) {
X! 	fprintf(stderr, "Cannot initialise %s\n", term);
X! 	exit(1);
X      }
X!     if ((Keyboard = tc_init_screen(term, framelabel, iconlabel)) == NULL) {
X! 	fprintf(stderr, "Cannot initialise %s\n", "screen");
X! 	exit(1);
X!     }
X!     if ((Client = spawn_slave(s_name, s_args)) == NULL) {
X! 	fprintf(stderr, "Cannot spawn %s\n", s_name);
X! 	exit(1);
X!     }
X!     initialise_signal();
X      terminal(fileno(Client), fileno(Keyboard));
X!     exit(0);
X  }
X  
X  #ifndef HAVEPUTENV
X***************
X*** 190,255 ****
X      if (alloced)
X  	free(environ);
X      environ = new;
X-     alloced++;
X  }
X- 
X- unsetenv(name)
X- char       *name; {
X-     register    len;
X-     register char **ap;
X-     register char **new;
X-     extern char **environ;
X- 
X-     len = strlen(name);
X-     for (new = ap = environ; *ap; ap++) {
X- 	if (strncmp(*ap, name, len) != 0) {
X- 	    *new++ = *ap;
X- 	}
X-     }
X-     if (new < ap) {
X- 	*new = 0;
X-     }
X- }
X- 
X- #ifdef	notdef
X- #include	<stdio.h>
X- 
X- main(argc,argv)
X- char **argv;
X- {
X-     argc--; argv++;
X-     for (;argc--;argv++) {
X- 	printf("[%s]\n", *argv);
X- 	switch (*(*argv)++) {
X- 	    case '-':
X- 	        if (**argv)
X- 		    unsetenv(*argv);
X- 		break;
X- 	    case '+':
X- 	        if (**argv && argc > 0) {
X- 		    register char *name = *argv++;
X- 		    putenv(name, *argv);
X- 		    argc--;
X- 		} else {
X- 		    printf("No value for %s\n", *argv);
X- 		}
X- 		break;
X- 	    default:
X- 	        printf("unrecognised %s\n", *argv);
X- 	}
X- 	printenv();
X-     }
X- 	
X- }
X- 
X- printenv() {
X-     register char *p;
X-     register char **ap;
X-     extern char **environ;
X- 
X-     for (ap = environ; *ap; ap++) {
X- 	printf("%s\n", *ap);
X-     }
X- }
X- #endif	notdef
X  #endif
X--- 174,178 ----
*-*-END-of-main.c.patch-*-*
echo x - screen.h.patch
sed 's/^X//' >screen.h.patch <<'*-*-END-of-screen.h.patch-*-*'
X*** ../psterm.sun/screen.h	Wed May 27 11:42:11 1987
X--- screen.h	Sun Jun  7 12:54:23 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	screen.h	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 26,34 ****
X   * 2550 Garcia Avenue
X   * Mountain View, California  94043
X   */
X- 
X  /*
X!  * "@(#)screen.h 1.6 87/03/13
X   *
X   * Copyright (c) 1985 by Sun Microsystems, Inc.
X   */
X--- 27,34 ----
X   * 2550 Garcia Avenue
X   * Mountain View, California  94043
X   */
X  /*
X!  * "@(#)screen.h 1.1 86/12/15
X   *
X   * Copyright (c) 1985 by Sun Microsystems, Inc.
X   */
*-*-END-of-screen.h.patch-*-*
echo x - selection.c.patch
sed 's/^X//' >selection.c.patch <<'*-*-END-of-selection.c.patch-*-*'
X*** ../psterm.sun/selection.c	Wed May 27 11:42:09 1987
X--- selection.c	Sun Jun  7 13:17:35 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	selection.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 28,34 ****
X   */
X  
X  #ifndef lint
X! static char sccsid[] = "@(#)selection.c 1.6 87/03/27 Copyright 1987 Sun Micro";
X  #endif
X  
X  /*
X--- 29,35 ----
X   */
X  
X  #ifndef lint
X! static char sccsid[] = "@(#)selection.c 1.6 87/03/13 Copyright 1987 Sun Micro";
X  #endif
X  
X  /*
X***************
X*** 62,70 ****
X  extern u_short     CharsPerLine;
X  extern u_short     LinesPerScreen;
X  extern struct pair Dot;
X! extern char	  *contents;
X  
X  static u_char      rankModes[4] = { 0, PrimSelMode, SecnSelMode, 0 };
X  
X  /*
X   * For simplicity sake, selections are maintained as character properties.
X--- 63,77 ----
X  extern u_short     CharsPerLine;
X  extern u_short     LinesPerScreen;
X  extern struct pair Dot;
X! static char	  *contents = NULL;
X  
X  static u_char      rankModes[4] = { 0, PrimSelMode, SecnSelMode, 0 };
X+ 
X+ tc_init_selection()
X+ {
X+ 
X+ 	contents = (char *)malloc((CharsPerLine * LinesPerScreen) + 1);
X+ }
X  
X  /*
X   * For simplicity sake, selections are maintained as character properties.
*-*-END-of-selection.c.patch-*-*
echo x - signal.c.patch
sed 's/^X//' >signal.c.patch <<'*-*-END-of-signal.c.patch-*-*'
X*** ../psterm.sun/signal.c	Wed May 27 11:42:09 1987
X--- signal.c	Sun Jun  7 13:06:27 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	signal.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
*-*-END-of-signal.c.patch-*-*
echo x - slave.c.patch
sed 's/^X//' >slave.c.patch <<'*-*-END-of-slave.c.patch-*-*'
X*** ../psterm.sun/slave.c	Wed May 27 11:42:10 1987
X--- slave.c	Sun Jun  7 13:10:38 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	slave.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 31,36 ****
X--- 32,38 ----
X  static char sccsid[] = "@(#)slave.c 1.18 87/03/19 Copyright 1985 Sun Micro";
X  #endif
X  
X+ 
X  /*
X   * Copyright (c) 1985 by Sun Microsystems, Inc. 
X   */
X***************
X*** 45,94 ****
X   */
X  
X  #include	<stdio.h>
X- #include	<sys/file.h>
X  #include	<sgtty.h>
X  #include	<sys/errno.h>
X- #include	<sys/types.h>
X- #include	<sys/ioctl.h>
X  
X  int         pgrp;
X  
X  /* XXX - there should be a library routine to get a pty */
X- 
X  char        ptcname[] = "/dev/ptyXX";
X  char        ptsname[] = "/dev/ttyXX";
X  
X  int         Mfd, Sfd;
X  
X- extern u_short	CharsPerLine;
X- extern u_short	LinesPerScreen;
X  
X- static int		ld = NTTYDISC;
X- static int		lm = LCRTBS | LCRTERA | LCRTKIL | LCTLECH;
X- static int		gotstate = 0;
X- static char	erase, kill, *gp, *tp;
X- static struct	sgttyb sg;
X- #define	DEVTTY	"/dev/tty"
X- 
X- SetupTTYState()
X- {
X-     register int fd;
X- 
X-     if ((fd = open(DEVTTY, (O_RDWR | O_NDELAY), 0)) >= 0) {
X- 	if (ioctl(fd, TIOCGETP, &sg) == 0) {
X- 	    erase = sg.sg_erase, kill = sg.sg_kill;
X- 	    sg.sg_flags &= ~(ALLDELAY | RAW | CBREAK);
X- 	    (void) ioctl(fd, TIOCGETD, &ld);
X- 	    (void) ioctl(fd, TIOCLGET, &lm);
X- 	    gotstate = 1;
X- 	}
X- 	else {
X- 	    perror("psterm-TIOCGETP");
X- 	}
X- 	close(fd);
X-     }
X- }
X- 
X  FILE       *
X  spawn_slave(name, args)
X      char       *name;
X--- 47,64 ----
X***************
X*** 101,113 ****
X      extern int  errno;
X      extern int  console;
X      int         pid;
X!     char	*gp, *tp;
X!     int		fd;
X  
X!     if (gotstate && (fd = open(DEVTTY, (O_RDWR|O_NDELAY), 0)) >= 0) {
X! 	if (ioctl(fd, TIOCNOTTY, 0) == -1)
X! 		perror("psterm-TIOCNOTTY");
X! 	close(fd);
X      }
X      for (gp = "pqrst"; *gp; gp++)
X  	for (tp = "0123456789abcdef"; *tp; tp++) {
X--- 71,94 ----
X      extern int  errno;
X      extern int  console;
X      int         pid;
X!     int		ld = NTTYDISC;
X!     int		lm = LCRTBS | LCRTERA | LCRTKIL | LCTLECH;
X!     int		gotstate = 0;
X!     char	erase, kill, *gp, *tp;
X!     struct	sgttyb sg;
X  
X!     {
X! 	register int fd;
X! 
X! 	if ((fd = open("/dev/tty", 2, 0)) >= 0) {
X! 	    (void) ioctl(fd, TIOCGETP, &sg);
X! 	    erase = sg.sg_erase, kill = sg.sg_kill;
X! 	    (void) ioctl(fd, TIOCGETD, &ld);
X! 	    (void) ioctl(fd, TIOCLGET, &lm);
X! 	    (void) ioctl(fd, TIOCNOTTY, 0);
X! 	    close(fd);
X! 	    gotstate = 1;
X! 	}
X      }
X      for (gp = "pqrst"; *gp; gp++)
X  	for (tp = "0123456789abcdef"; *tp; tp++) {
X***************
X*** 120,131 ****
X  	    if ((Sfd = open(ptsname, 2)) >= 0)
X  		goto done;
X  	    close(Mfd);
X! 	}
X  done:
X      if (Mfd < 0 || Sfd < 0)
X  	return (NULL);
X!     if (ioctl(Sfd, TIOCHPCL, 0) == -1)
X! 	perror("psterm-TIOCHPCL");
X      (void) ioctl(Sfd, TIOCSETD, &ld);
X      if (gotstate) {
X  	(void) ioctl(Sfd, TIOCGETP, &sg);
X--- 101,111 ----
X  	    if ((Sfd = open(ptsname, 2)) >= 0)
X  		goto done;
X  	    close(Mfd);
X!     }
X  done:
X      if (Mfd < 0 || Sfd < 0)
X  	return (NULL);
X!     (void) ioctl(Sfd, TIOCHPCL, 0);
X      (void) ioctl(Sfd, TIOCSETD, &ld);
X      if (gotstate) {
X  	(void) ioctl(Sfd, TIOCGETP, &sg);
X***************
X*** 135,160 ****
X  	(void) ioctl(Sfd, TIOCSETP, &sg);
X      }
X      (void) ioctl(Sfd, TIOCLSET, &lm);
X- /*
X-  * set tty size to avoid problem of applications picking up 
X-  * the wrong size from termcap.
X-  */
X- #ifndef REF
X-     {
X- 	struct ttysize      ts;
X-     
X- 	ts.ts_lines = LinesPerScreen;
X- 	ts.ts_cols = CharsPerLine;
X- 	if ((ioctl(Sfd, TIOCSSIZE, &ts)) == -1)
X- 	    perror("psterm-TIOCSSIZE");
X-     }
X      if (console) {
X! #ifdef	TIOCCONS
X  	if (ioctl(Sfd, TIOCCONS, 0) < 0)
X- #endif
X  	    perror("tcap(TIOCCONS)");
X-     }
X  #endif
X      Master = fdopen(Mfd, "r");
X  
X      {
X--- 115,126 ----
X  	(void) ioctl(Sfd, TIOCSETP, &sg);
X      }
X      (void) ioctl(Sfd, TIOCLSET, &lm);
X      if (console) {
X! #ifdef TIOCCONS
X  	if (ioctl(Sfd, TIOCCONS, 0) < 0)
X  	    perror("tcap(TIOCCONS)");
X  #endif
X+     }
X      Master = fdopen(Mfd, "r");
X  
X      {
X***************
X*** 170,176 ****
X  	    return (NULL);
X  	}
X      }
X- /*- fprintf(stderr, "execvp(%s,%s,%s)\n", name, args[0], args[1]); */
X      if (pid == 0) {
X  	register int i;
X  	register int l = getdtablesize();
X--- 136,141 ----
X***************
X*** 180,187 ****
X  	dup2(Sfd, 2);
X  	for (i = 3; i < l; i++)
X  	    close(i);
X! 	if (ioctl(0, TIOCSPGRP, &pid) == -1)
X! 	    perror("psterm-TIOCSPGRP");
X  	execvp(name, args);
X  	perror(name);
X  	exit(errno);
X--- 145,151 ----
X  	dup2(Sfd, 2);
X  	for (i = 3; i < l; i++)
X  	    close(i);
X! 	ioctl(0, TIOCSPGRP, &pid);
X  	execvp(name, args);
X  	perror(name);
X  	exit(errno);
*-*-END-of-slave.c.patch-*-*
echo x - tcap.cps.patch
sed 's/^X//' >tcap.cps.patch <<'*-*-END-of-tcap.cps.patch-*-*'
X*** ../psterm.sun/tcap.cps	Wed May 27 11:42:13 1987
X--- tcap.cps	Sun Jun  7 12:57:17 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ %	tcap.cps	2.1	87/06/07
X  %
X  % NeWS is a product of Sun Microsystems, Inc. and is provided for
X  % unrestricted use provided that this legend is included on all tape
X***************
X*** 27,33 ****
X  % Mountain View, California  94043
X  %
X  %
X! % "@(#)tcap.cps 1.38 87/03/27
X  %
X  % Copyright (c) 1985 by Sun Microsystems, Inc.
X  %/
X--- 28,34 ----
X  % Mountain View, California  94043
X  %
X  %
X! % "@(#)tcap.cps 6.18 87/03/20
X  %
X  % Copyright (c) 1985 by Sun Microsystems, Inc.
X  %/
X***************
X*** 36,42 ****
X  cdef	StartWithFixedSize(yes)
X      /term_startwithfixedsize yes def
X  
X! cdef	Initialize(w,h,c,l,string label)
X      /lines_per_screen l def
X      100 dict begin		% XXX - is this necessary?
X      /errfile (%stdout) (w) file def
X--- 37,43 ----
X  cdef	StartWithFixedSize(yes)
X      /term_startwithfixedsize yes def
X  
X! cdef	Initialize(w,h,c,l,string framelabel, string iconlabel)
X      /lines_per_screen l def
X      100 dict begin		% XXX - is this necessary?
X      /errfile (%stdout) (w) file def
X***************
X*** 85,93 ****
X      ] def
X      /MyWindow framebuffer /new DefaultWindow send def
X      {
X! 	/FrameLabel label def
X  	/IconImage /terminal def
X! 	/IconLabel (PS Term!) def
X  	/FixFrame {(\376) print} def
X  	/PaintClient {(\376) print} def
X      } MyWindow send
X--- 86,94 ----
X      ] def
X      /MyWindow framebuffer /new DefaultWindow send def
X      {
X! 	/FrameLabel framelabel def
X  	/IconImage /terminal def
X! 	/IconLabel iconlabel def
X  	/FixFrame {(\376) print} def
X  	/PaintClient {(\376) print} def
X      } MyWindow send
X***************
X*** 190,195 ****
X--- 191,209 ----
X  	0 exch copyarea
X  	grestore
X      } def
X+     /SL {			% s SetFrameLabel
X+ 	{ /FrameLabel exch def
X+ 	  gsave
X+ 	  FrameCanvas setcanvas
X+ 	  BorderLeft 1 add
X+ 	  FrameHeight BorderTop sub 1 add
X+ 	  FrameWidth BorderLeft BorderRight add sub 2 sub
X+ 	  BorderTop 2 sub
X+ 	  rectpath FrameFillColor setcolor fill		% clear label area
X+ 	  /paintframelabel self send PaintFocus		% new label & focus
X+ 	  grestore
X+ 	} MyWindow send
X+     } def
X      /resetscale {
X  	5 dict begin	% local storage
X  	initgraphics
X***************
X*** 368,371 ****
X--- 382,386 ----
X  cdef CopyLines(yfrom, yby, w, nl) yby w yfrom nl CL
X  cdef BeginRepair() BRP
X  cdef EndRepair() ERP
X+ cdef SetFrameLabel(string str) str SL
X  cdef SetSelContents(r, s, l, cstring str)	str s l r setselcontents
*-*-END-of-tcap.cps.patch-*-*
echo x - tcap_ops.c.patch
sed 's/^X//' >tcap_ops.c.patch <<'*-*-END-of-tcap_ops.c.patch-*-*'
X*** ../psterm.sun/tcap_ops.c	Wed May 27 11:42:11 1987
X--- tcap_ops.c	Sun Jun  7 13:13:27 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	tcap_ops.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 57,77 ****
X   */
X  
X  #include	"screen.h"
X! extern u_short	CharsPerLine;
X! extern u_short LinesPerScreen;
X! extern struct pair Dot;
X  
X  static	u_short	TopLineOfScrollRegion, BottomLineOfScrollRegion;
X  static struct pair SavedCursor;
X  
X  static unsigned int PermanentModes = 0,  TemporaryModes = 0;
X  
X  tc_init_ops()
X  {
X      TopLineOfScrollRegion = 0;
X      BottomLineOfScrollRegion = LinesPerScreen - 1;
X  }
X  
X  static
X  trace(s, t)
X      register char *s;
X--- 58,124 ----
X   */
X  
X  #include	"screen.h"
X! extern	u_short	CharsPerLine;
X! extern	u_short LinesPerScreen;
X! extern	struct pair Dot;
X! extern	struct tcap T[];
X! extern	int Ts;
X! extern	char *malloc();
X! static	struct tcap *tc_lookup();
X  
X  static	u_short	TopLineOfScrollRegion, BottomLineOfScrollRegion;
X  static struct pair SavedCursor;
X+ static	u_short ScrollNLKludge = 0;
X  
X  static unsigned int PermanentModes = 0,  TemporaryModes = 0;
X  
X+ static	char *FrameLabel;
X+ static	u_short FLindex;
X+ static	int (*prevInput)();
X+ 
X  tc_init_ops()
X  {
X+     struct tcap *se, *ue, *me, *sf;
X+ 
X      TopLineOfScrollRegion = 0;
X      BottomLineOfScrollRegion = LinesPerScreen - 1;
X+     FrameLabel = malloc(CharsPerLine+1);
X+     /*
X+      * Beware of termcap entries that define ue and/or se identical
X+      * to me (turn off ALL attributes).  Since we just pattern
X+      * match, it's likely we won't get me_op in normal operation,
X+      * so force the entries here. (known for vt100)
X+      */
X+     se = tc_lookup("se"), ue = tc_lookup("ue"), me = tc_lookup("me");
X+     if (me) {
X+ 	if (ue && ue->t_size == me->t_size &&
X+ 	    bcmp(me->t_text, ue->t_text, ue->t_size) == 0)
X+ 	    ue->t_op = me->t_op;
X+ 	if (se && se->t_size == me->t_size &&
X+ 	    bcmp(me->t_text, se->t_text, se->t_size) == 0)
X+ 	    se->t_op = me->t_op;
X+     }
X+     /*
X+      * Check for sf == \n, if so we must kludge things so that
X+      * sf_op will call nl_op as needed (exists on bitgraph).
X+      */
X+     sf = tc_lookup("sf");
X+     if (sf && sf->t_size == 1 && sf->t_text[0] == '\n')
X+ 	ScrollNLKludge = 1;
X  }
X  
X+ static struct tcap *
X+ tc_lookup(key)
X+     char *key;
X+ {
X+     register struct tcap *tp;
X+ 
X+     for (tp = T; *tp->t_key; tp++)
X+ 	if (strcmp(tp->t_key, key) == 0)
X+ 	    return (tp);
X+     return ((struct tcap *)0);
X+ }
X+ 
X  static
X  trace(s, t)
X      register char *s;
X***************
X*** 125,181 ****
X      }
X      fprintf(stderr, "\n");
X  }
X! static int
X  showc(t)
X!     register struct tcap *t;
X  {
X      register unsigned Modes = PermanentModes | TemporaryModes;
X!     register char *c = t->t_text;
X  
X      trace("==", t);
X      TemporaryModes = 0;
X!     if (c)
X! 	while (*c) {
X! 	    if (' ' <= *c && *c < 0177) {
X! 		register struct line *l = screen[Dot.y].lineptr;
X  
X! 		if (l->changeposition > l->length)
X! 		    l->changeposition = l->length;
X! 		if (l->changeposition > Dot.x)
X! 		    l->changeposition = Dot.x;
X! 		while (l->length < Dot.x) {
X! 		    l->prop[l->length] = 0;
X! 		    l->body[l->length++] = ' ';
X! 		}
X! 		if (Modes & InsertMode) {
X! 		    register int i;
X! 
X! 		    if (l->length > Dot.x) {
X! 			if (l->length < CharsPerLine)
X! 			    l->length++;
X! 			for (i = l->length - 1; i > Dot.x; i--) {
X! 			    l->prop[i] = l->prop[i - 1];
X! 			    l->body[i] = l->body[i - 1];
X! 			}
X! 		    }
X! 		}
X! 		l->body[Dot.x] = *c;
X! 		l->prop[Dot.x] = (Modes & Attributes);
X! 		if (Dot.x >= l->length)
X  		    l->length++;
X! 		if (++Dot.x >= CharsPerLine) {
X! 		    if (Modes & AutoMarginMode) {
X! 			cr_op(t);
X! 			nl_op(t);
X! 			TemporaryModes |= WrapJustHappenedMode;
X! 		    }
X! 		    else {
X! 			Dot.x = CharsPerLine - 1;
X! 		    }
X  		}
X  	    }
X- 	    c++;
X  	}
X      ChangeScreen();
X  }
X  
X--- 172,227 ----
X      }
X      fprintf(stderr, "\n");
X  }
X! 
X  showc(t)
X!     struct tcap *t;
X  {
X+     register char *cp = t->t_text;
X+     register int n = t->t_size;
X      register unsigned Modes = PermanentModes | TemporaryModes;
X!     register struct line *l;
X!     register int c;
X  
X      trace("==", t);
X      TemporaryModes = 0;
X!     while (n-- > 0) {
X! 	c = *cp++;
X! 	if (c < ' ' || c >= 0177)
X! 		continue;
X! 	l = screen[Dot.y].lineptr;
X! 	if (l->changeposition > l->length)
X! 	    l->changeposition = l->length;
X! 	if (l->changeposition > Dot.x)
X! 	    l->changeposition = Dot.x;
X! 	while (l->length < Dot.x) {
X! 	    l->prop[l->length] = 0;
X! 	    l->body[l->length++] = ' ';
X! 	}
X! 	if (Modes & InsertMode) {
X! 	    register int i;
X  
X! 	    if (l->length > Dot.x) {
X! 		if (l->length < CharsPerLine)
X  		    l->length++;
X! 		for (i = l->length - 1; i > Dot.x; i--) {
X! 		    l->prop[i] = l->prop[i - 1];
X! 		    l->body[i] = l->body[i - 1];
X  		}
X  	    }
X  	}
X+ 	l->body[Dot.x] = c;
X+ 	l->prop[Dot.x] = (Modes & Attributes);
X+ 	if (Dot.x >= l->length)
X+ 	    l->length++;
X+ 	if (++Dot.x >= CharsPerLine) {
X+ 	    if (Modes & AutoMarginMode) {
X+ 		cr_op(t);
X+ 		nl_op(t);
X+ 		TemporaryModes |= WrapJustHappenedMode;
X+ 	    } else
X+ 		Dot.x = CharsPerLine - 1;
X+ 	}
X+     }
X      ChangeScreen();
X  }
X  
X***************
X*** 191,199 ****
X  	screen[i].lineptr = screen[i-1].lineptr;
X      }
X      screen[Dot.y].lineptr = old;
X!     for (i = 0; i <= old->length; i++) {
X  	old->prop[i] = 0;
X-     }
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = Dot.y
X--- 237,244 ----
X  	screen[i].lineptr = screen[i-1].lineptr;
X      }
X      screen[Dot.y].lineptr = old;
X!     for (i = 0; i <= old->length; i++)
X  	old->prop[i] = 0;
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = Dot.y
X***************
X*** 306,324 ****
X  cm_in(t)	/* Cursor motion */
X      register struct tcap *t;
X  {
X-     register int i = 0;
X-     register int j = 0;
X      register u_char c;
X      char        buf[128];
X!     int         xspec = 0;
X!     extern char * malloc();
X      
X!     if (t->t_text == NULL) return(0);
X!     t->t_temp = malloc(128);
X      /* Pre-process out parts of the % escapes */
X!     while ((c = t->t_text[i++]) != '\0') {
X  	if (c == '%') {
X! 	    register u_char c2 = t->t_text[i++];
X  
X  	    switch (c2) {
X  	    case '+':		/* Subtract next then %. */
X--- 351,366 ----
X  cm_in(t)	/* Cursor motion */
X      register struct tcap *t;
X  {
X      register u_char c;
X      char        buf[128];
X!     register	char *cp = t->t_text, *bp = buf;
X      
X!     if (cp == NULL)
X! 	return(0);
X      /* Pre-process out parts of the % escapes */
X!     while ((c = *cp++) != '\0') {
X  	if (c == '%') {
X! 	    register u_char c2 = *cp++;
X  
X  	    switch (c2) {
X  	    case '+':		/* Subtract next then %. */
X***************
X*** 325,334 ****
X  		switch (t->t_2nd + t->t_pc_r) {
X  		case 0:
X  		case 2:
X! 		    t->t_yi = t->t_text[i++];
X  		    break;
X  		case 1:
X! 		    t->t_xi = t->t_text[i++];
X  		    break;
X  		}
X  		c2 = '.';
X--- 367,376 ----
X  		switch (t->t_2nd + t->t_pc_r) {
X  		case 0:
X  		case 2:
X! 		    t->t_yi = *cp++;
X  		    break;
X  		case 1:
X! 		    t->t_xi = *cp++;
X  		    break;
X  		}
X  		c2 = '.';
X***************
X*** 336,349 ****
X  	    case '>':
X  		switch (t->t_2nd + t->t_pc_r) {
X  		case 1:
X! 		    t->t_xilim = t->t_text[i++];
X! 		    t->t_xi = t->t_text[i++];
X  		    t->t_xilim += t->t_xi + 1;
X  		    break;
X  		case 0:
X  		case 2:
X! 		    t->t_yilim = t->t_text[i++];
X! 		    t->t_yi = t->t_text[i++];
X  		    t->t_yilim += t->t_yi + 1;
X  		    break;
X  		}
X--- 378,391 ----
X  	    case '>':
X  		switch (t->t_2nd + t->t_pc_r) {
X  		case 1:
X! 		    t->t_xilim = *cp++;
X! 		    t->t_xi = *cp++;
X  		    t->t_xilim += t->t_xi + 1;
X  		    break;
X  		case 0:
X  		case 2:
X! 		    t->t_yilim = *cp++;
X! 		    t->t_yi = *cp++;
X  		    t->t_yilim += t->t_yi + 1;
X  		    break;
X  		}
X***************
X*** 372,380 ****
X  	    case '.':		/* binary character */
X  	percent_dot:
X  	    case '%':
X! 		xspec++;
X! 		buf[j++] = c;
X! 		buf[j++] = c2;
X  		t->t_2nd = !t->t_2nd;
X  		break;
X  	    default:		/* Bad % escape */
X--- 414,421 ----
X  	    case '.':		/* binary character */
X  	percent_dot:
X  	    case '%':
X! 		*bp++ = c;
X! 		*bp++ = c2;
X  		t->t_2nd = !t->t_2nd;
X  		break;
X  	    default:		/* Bad % escape */
X***************
X*** 382,401 ****
X  	    }
X  	}
X  	else {
X! 	    buf[j++] = c;
X  	}
X      }
X!     buf[j++] = '\0';
X!     if (j > 1) {
X! 	if ((t->t_text = malloc(j + 1)) == NULL) {
X  	    return (2);
X! 	}
X! 	else {
X! 	    strncpy(t->t_text, buf, j);
X! 	}
X! 	t->t_size = j - 1;
X!     }
X!     else {
X  	t->t_text = NULL;
X      }
X      t->t_2nd = 0;
X--- 423,438 ----
X  	    }
X  	}
X  	else {
X! 	    *bp++ = c;
X  	}
X      }
X!     *bp++ = '\0';
X!     if (bp-buf > 1) {
X! 	if ((t->t_text = malloc(bp-buf+1)) == NULL)
X  	    return (2);
X! 	strncpy(t->t_text, buf, bp-buf);
X! 	t->t_size = bp-buf - 1;
X!     } else {
X  	t->t_text = NULL;
X      }
X      t->t_2nd = 0;
X***************
X*** 445,452 ****
X      register struct tcap *t;
X  {
X      trace("cs", t);
X!     if (/* t->t_y < 0 ||  [[t->t_y is unsigned!]] */
X! 	t->t_y >= t->t_x || t->t_x >= LinesPerScreen)
X  	return;
X      Dot.x = 0;
X      Dot.y = t->t_y;
X--- 482,488 ----
X      register struct tcap *t;
X  {
X      trace("cs", t);
X!     if (t->t_y >= t->t_x || t->t_x >= LinesPerScreen)
X  	return;
X      Dot.x = 0;
X      Dot.y = t->t_y;
X***************
X*** 488,496 ****
X  	screen[i].lineptr = screen[i+1].lineptr;
X      }
X      screen[BottomLineOfScrollRegion].lineptr = old;
X!     for (i = 0; i <= old->length; i++) {
X  	old->prop[i] = 0;
X-     }
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = LinesPerScreen - 1;
X--- 524,531 ----
X  	screen[i].lineptr = screen[i+1].lineptr;
X      }
X      screen[BottomLineOfScrollRegion].lineptr = old;
X!     for (i = 0; i <= old->length; i++)
X  	old->prop[i] = 0;
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = LinesPerScreen - 1;
X***************
X*** 525,530 ****
X--- 560,575 ----
X  }
X  
X  static int
X+ el_op(t)	/* end frame label definition mode */
X+     register struct tcap *t;
X+ {
X+     FrameLabel[FLindex] = '\0';
X+     do_label_change(FrameLabel);
X+     t = T+Ts;
X+     t->t_op = prevInput;
X+ }
X+ 
X+ static int
X  ke_op(t)	/* leave keyboard transmit mode */
X      register struct tcap *t;
X  {
X***************
X*** 593,598 ****
X--- 638,656 ----
X  }
X  
X  static int
X+ lm_op(t)	/* label mode input */
X+     register struct tcap *t;
X+ {
X+     trace("lm", t);
X+     if (FLindex + t->t_size >= CharsPerLine)
X+ 	t->t_size = CharsPerLine - FLindex;
X+     if (t->t_size > 0) {
X+ 	strncpy(&FrameLabel[FLindex], t->t_text, t->t_size);
X+ 	FLindex += t->t_size;
X+     }
X+ }
X+ 
X+ static int
X  mb_op(t)	/* enable blink */
X      register struct tcap *t;
X  {
X***************
X*** 693,707 ****
X  {
X      register struct line *old = screen[TopLineOfScrollRegion].lineptr;
X      register int i;
X  
X      trace("sf", t);
X      for (i = TopLineOfScrollRegion; i < BottomLineOfScrollRegion; i++) {
X  	screen[i].lineptr = screen[i+1].lineptr;
X      }
X      screen[BottomLineOfScrollRegion].lineptr = old;
X!     for (i = 0; i <= old->length; i++) {
X  	old->prop[i] = 0;
X-     }
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = LinesPerScreen;
X--- 751,773 ----
X  {
X      register struct line *old = screen[TopLineOfScrollRegion].lineptr;
X      register int i;
X+     static int SFrecur = 0;
X  
X      trace("sf", t);
X+     /*
X+      * When sf is "\n", nl_op won't be called, so we emulate
X+      * it's actions here (beware of recursion).
X+      */
X+     if (ScrollNLKludge && !SFrecur) {
X+ 	SFrecur++; nl_op(t); SFrecur--;
X+ 	return;
X+     }
X      for (i = TopLineOfScrollRegion; i < BottomLineOfScrollRegion; i++) {
X  	screen[i].lineptr = screen[i+1].lineptr;
X      }
X      screen[BottomLineOfScrollRegion].lineptr = old;
X!     for (i = 0; i <= old->length; i++)
X  	old->prop[i] = 0;
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = LinesPerScreen;
X***************
X*** 709,714 ****
X--- 775,791 ----
X  }
X  
X  static int
X+ sl_op(t)	/* start defining new frame label */
X+     register struct tcap *t;
X+ {
X+     trace("sl", t);
X+     FLindex = 0;
X+     t = T+Ts;
X+     prevInput = t->t_op;
X+     t->t_op = lm_op;
X+ }
X+ 
X+ static int
X  sr_op(t)	/* scroll reverse */
X      register struct tcap *t;
X  {
X***************
X*** 720,728 ****
X  	screen[i].lineptr = screen[i-1].lineptr;
X      }
X      screen[TopLineOfScrollRegion].lineptr = old;
X!     for (i = 0; i <= old->length; i++) {
X  	old->prop[i] = 0;
X-     }
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = LinesPerScreen;
X--- 797,804 ----
X  	screen[i].lineptr = screen[i-1].lineptr;
X      }
X      screen[TopLineOfScrollRegion].lineptr = old;
X!     for (i = 0; i <= old->length; i++)
X  	old->prop[i] = 0;
X      old->length = 0;
X      old->changeposition = 0;
X      old->usedtobe = LinesPerScreen;
X***************
X*** 861,866 ****
X--- 937,944 ----
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"ei", s, ei_op, ei_in, NULL,   NULL, 0, 0, NULL, 0,
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X+     {"el", s, el_op, NULL,  NULL, "\033\\", 0, 0, NULL, 0, /* end label */
X+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"ke", s, ke_op, ke_in, NULL,   NULL, 0, 0, NULL, 0,
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"ks", s, ks_op, ks_in, NULL,   NULL, 0, 0, NULL, 0,
X***************
X*** 877,882 ****
X--- 955,962 ----
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"ll", s, ll_op, ll_in, NULL,   NULL, 0, 0, NULL, 0,
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X+     {"lm", s, lm_op,  NULL, NULL,   NULL, 0, 0, NULL, 0, /* label mode input */
X+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"mb", s, mb_op, mb_in, NULL,   NULL, 0, 0, NULL, 0,
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"md", s, md_op, md_in, NULL,   NULL, 0, 0, NULL, 0,
X***************
X*** 899,904 ****
X--- 979,986 ----
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"sf", s, sf_op, sf_in, NULL,   NULL, 0, 0, NULL, 0,
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X+     {"sl", s, sl_op, NULL,  NULL, "\033]l", 0, 0, NULL, 0, /* start label */
X+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"so", s, so_op, so_in, NULL,   NULL, 0, 0, NULL, 0,
X  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
X      {"sr", s, sr_op, sr_in, NULL,   NULL, 0, 0, NULL, 0,
X***************
X*** 919,922 ****
X  
X  /* T[Ts] is a special case - its the display-character operation */
X  int Ts = (sizeof T)/(sizeof T[0]) - 1;
X- 
X--- 1001,1003 ----
*-*-END-of-tcap_ops.c.patch-*-*
echo x - tcap_parse.c.patch
sed 's/^X//' >tcap_parse.c.patch <<'*-*-END-of-tcap_parse.c.patch-*-*'
X*** ../psterm.sun/tcap_parse.c	Wed May 27 11:42:11 1987
X--- tcap_parse.c	Sun Jun  7 13:15:25 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	tcap_parse.c	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 31,36 ****
X--- 32,38 ----
X  static	char sccsid[] = "@(#)tcap_parse.c 1.13 87/03/19 Copyright 1985 Sun Micro";
X  #endif
X  
X+ 
X  /*
X   * Copyright (c) 1985 by Sun Microsystems, Inc.
X   */
X***************
X*** 43,58 ****
X  		David Rosenthal,
X  		Sun Microsystems
X   */
X- 
X- /*
X-  *	The parser described here is VERY primitive - it uses an array of
X-  *	little state machines instead of one big one.  This is for two
X-  *	reasons:  I dont understand parsers very well and this way is
X-  *	easy to debug.  An expert should replace it.  The external
X-  *	interface is:
X-  *		tc_initialize(term)
X-  *		tc_display(buf, n)
X-  */
X      /* XXX - remember longest outstanding partial match? */
X      /* XXX - overlapping partial matches? */
X  
X--- 45,50 ----
X***************
X*** 60,242 ****
X  #include	<ctype.h>
X  #include	"termcap.h"
X  
X  /*  Import these from tcap_ops.c */
X  extern struct tcap T[];
X  extern int Ts;
X- 
X  /*
X!  * The next 2 variables help us to optimize the important special case
X!  * where we are just painting text and not doing any special command.
X!  * MatchInProgress means we are in the middle of parsing a command
X!  * sequence, so we have to call the parser.
X!  * TerminalIsBraindamaged means the terminal uses a printing character
X!  * to start an escape sequence, so we always have to call the parser.
X!  * If both these are false, we do a quick check to see if the character
X!  * is printable, and if so, display it without going through the parser.
X   */
X! 
X! static int MatchInProgress = 0;
X! static int TerminalIsBraindamaged = 0;
X! 
X! static
X! display_char(c)
X!     register u_char c;
X  {
X!     char buf[2];
X  
X!     buf[0] = c;
X!     buf[1] = '\0';
X!     T[Ts].t_text = buf;
X!     if (T[Ts].t_op) {
X! 	(*(T[Ts].t_op)) (T+Ts);
X!     } else
X! 	fputc(c, stderr);
X! }
X! 
X! static unsigned char *
X! termcap(c)
X!     register u_char c;
X! {
X!     register unsigned i;
X!     unsigned int ret = 0;
X!     static unsigned char tbuf[128];
X!     static u_short tind = 0;
X! 
X! #ifdef	notdef
X!     if (c < ' ')
X! 	fprintf(stderr, "[^%c]\n", c+0100);
X!     else
X!         fprintf(stderr, "[%c]\n", c);
X! #endif
X!     tbuf[tind++] = c;
X!     /* Examine each termcap to see if this could be a match */
X!     for (i = 0; i < Ts; i++) {
X! 	register unsigned j;
X! 	int         restart;
X! 
X! #define	MANY 8192
X! OnceMore:
X! 	j = T[i].t_index;
X! 	restart = 0;
X! 	if ((T[i].t_text == NULL) || (T[i].t_index == MANY)) {
X! 	    /* No text for this tcap */
X! 	    continue;
X! 	}
X! 	else if (T[i].t_text[j] == '%') {
X! 	    /* Maybe its a % match */
X! 	    int         val, lim;
X! 	    switch (T[i].t_text[j + 1]) {
X! 	    case 'd':		/* series of decimal digits */
X! 		lim = 127;
X! 		goto digit;
X! 	    case '2':		/* two decimal digits */
X! 		lim = 2;
X! 		goto digit;
X! 	    case '3':		/* three decimal digits */
X! 		lim = 3;
X! 	digit:
X! 		if (isdigit(c) && T[i].t_tempfill < lim) {
X! 		    T[i].t_temp[T[i].t_tempfill++] = c;
X! 		    goto plainmatch;
X! 		}
X! 		else if (T[i].t_tempfill > 0) {
X! 		    T[i].t_temp[T[i].t_tempfill] = '\0';
X! 		    val = atoi(T[i].t_temp);
X! 		    T[i].t_tempfill = 0;
X! 		    if (!isdigit(c)) {
X! 			restart = 1;
X! 		    }
X! 		    goto matched;
X! 		}
X! 		else
X! 		    goto nomatch;
X  		break;
X! 	    case '.':		/* binary character */
X! 		val = c;
X! 	matched:
X! 		switch (T[i].t_2nd + T[i].t_pc_r) {
X! 		case 0:
X! 		case 2:
X! 		    T[i].t_y = (val >= T[i].t_yilim ? val - T[i].t_yi : val);
X! 		    break;
X! 		case 1:
X! 		    T[i].t_x = (val >= T[i].t_xilim ? val - T[i].t_xi : val);
X! 		    break;
X! 		}
X! 		T[i].t_2nd = !T[i].t_2nd;
X! 		T[i].t_index += 2;
X! 		goto plainmatch;
X! 	    case '%':
X! 		if ((c & 0177) == '%') {
X! 		    T[i].t_index += 2;
X! 		    goto plainmatch;
X! 		}
X! 		else
X! 		    goto nomatch;
X! 	    default:
X! 		/* NOTREACHED */
X! 		abort();	/* XXX */
X! 	    }
X! 	}
X! 	else if ((c & 0177) == (T[i].t_text[j] & 0177)) {
X! 	    T[i].t_index++;
X!     plainmatch:
X! 	    /* Its a plain match */
X! 	    if (T[i].t_index >= T[i].t_size) {
X! 		/* Matched the whole string */
X! 		if (T[i].t_op) {
X! 		    /* Do the operation */
X! 		    (*(T[i].t_op)) (&(T[i]));
X! 		}
X! 		/* Eat the stored string */
X! 		tind = 0;
X! 		ret = 0;
X  		break;
X  	    }
X! 	    else {
X! 		/* This is a partial match */
X! 		ret++;
X! 	    }
X! 	    if (restart) {
X! 		/*
X! 		 * The end of a %d match is the only case where a
X! 		 * character must be pushed-back and re-parsed.
X! 		 */
X! 		register unsigned k;
X! 
X! 		tbuf[0] = c;
X! 		tind = 1;
X! 		ret = 0;
X! 		goto OnceMore;
X! 	    }
X  	}
X- 	else {
X-     nomatch:
X- 	    /* This match fails */
X- 	    T[i].t_index = MANY;
X- 	    T[i].t_tempfill = 0;
X- 	}
X      }
X!     if (ret == 0) {
X! 	/* No partial match outstanding */
X! 	register unsigned k;
X! 
X! 	tbuf[tind] = '\0';
X! 	tind = 0;
X! 	/* Reset all the counters */
X! 	for (k = 0; k < Ts; k++) {
X! 	    T[k].t_index = 0;
X! 	    T[k].t_tempfill = 0;
X! 	    T[k].t_2nd = 0;
X! 	}
X! 	MatchInProgress = 0;
X! 	return (tbuf);
X!     }
X!     else {
X! 	/* At least one partial match outstanding */
X! 	MatchInProgress = 1;
X! 	return (NULL);
X!     }
X  }
X  
X  static char *
X--- 52,108 ----
X  #include	<ctype.h>
X  #include	"termcap.h"
X  
X+ static	int TerminalIsBraindamaged = 0;
X  /*  Import these from tcap_ops.c */
X  extern struct tcap T[];
X  extern int Ts;
X  /*
X!  * Initialize the display system from the TERMCAP entry.
X!  * We parse the entry and build the tcap structures
X!  * describing the operations supported by this type of
X!  * terminal.  These descriptions are then used by tc_display()
X!  * in interpreting the data stream generated by the
X!  * application
X   */
X! int
X! tc_initialize(term)
X!     char *term;
X  {
X!     static char tcapbuf[1024], tcaparea[1024], *unpad();
X!     char       *areap = tcaparea;
X!     extern int tgetent(), tgetnum(), tgetflag();
X!     extern char *tgetstr();
X!     register struct tcap *tp;
X  
X!     if (tgetent(tcapbuf, term) == 1) {
X! 	for (tp = T; tp < T+Ts; tp++) {
X! 	    switch (tp->t_type) {
X! 	    case string:
X! 		tp->t_text = unpad(tgetstr(tp->t_key, &areap));
X! 		if (tp->t_text == NULL)
X! 		    tp->t_text = tp->t_deftext;
X! 		if (tp->t_text) {
X! 			tp->t_size = strlen(tp->t_text);
X! 			if (isprint(tp->t_text[0]))
X! 				TerminalIsBraindamaged = 1;
X! 		} else
X! 			tp->t_size = 0;
X  		break;
X! 	    case num:
X! 		tp->t_x = tgetnum(tp->t_key);
X  		break;
X+ 	    case bool:
X+ 		tp->t_x = tgetflag(tp->t_key);
X+ 		break;
X  	    }
X! 	    /* invoke any initialize routine */
X! 	    if (tp->t_in && (*tp->t_in)(tp))
X! 		return (1);
X  	}
X      }
X!     tc_init_ops();
X!     tc_init_stacks();
X!     return (0);
X  }
X  
X  static char *
X***************
X*** 243,255 ****
X  unpad(s)
X      register char *s;
X  {
X      if (s) {
X  	register pad = 0;
X  
X! 	while (isdigit(*s)) {
X! 	    pad++;
X! 	    s++;
X! 	}
X  	if (pad && *s == '*')
X  	    s++;
X      }
X--- 109,120 ----
X  unpad(s)
X      register char *s;
X  {
X+ 
X      if (s) {
X  	register pad = 0;
X  
X! 	while (isdigit(*s))
X! 	    pad++, s++;
X  	if (pad && *s == '*')
X  	    s++;
X      }
X***************
X*** 256,365 ****
X      return (s);
X  }
X  
X! #define TCAPBUFSIZE 1024
X! #define SPECIALSIZE 2
X  
X! static struct {
X!     char	*last;
X!     char	 str[3];
X! }   tcapSpecials[SPECIALSIZE] = {
X!     NULL,	"co",
X!     NULL,	"li"
X! };
X  
X! static void
X! tc_fix_tcap_ent(buf)
X!     char *buf;
X  {
X!     char *bp = buf, *index();
X!     int   i;
X!     
X!     /* for each item in buf ... */
X!     for (bp = index(bp, ':'); bp && *(bp+1); bp = index(bp, ':')) {
X! 	++bp;
X! 	/* for each special tcap code ... */
X! 	for (i = 0; i < SPECIALSIZE; i++) {
X! 	    if (strncmp(tcapSpecials[i].str, bp, 2) == 0) {
X! 		if (tcapSpecials[i].last)
X! 		    strncpy(tcapSpecials[i].last, "xx", 2);
X! 		tcapSpecials[i].last = bp;
X! 		break;
X! 	    }
X! 	}
X!     }
X  }
X  
X! /* The external interface of this module is the routines below */
X! 
X! /* Initialize the display system from the TERMCAP entry */
X! int
X! tc_initialize(term)
X!     char *term;
X  {
X!     static char tcapbuf[TCAPBUFSIZE];
X!     static char tcaparea[TCAPBUFSIZE];
X!     char       *areap = tcaparea;
X!     extern int tgetent(), tgetnum(), tgetflag();
X!     extern char *tgetstr();
X  
X!     if (tgetent(tcapbuf, term) == 1) {
X! 	register int i;
X! 
X! 	tc_fix_tcap_ent(tcapbuf);
X! 	for (i = 0; i < Ts; i++) {
X! 	    char *str;
X! 
X! 	    switch (T[i].t_type) {
X! 	    case string:
X! 		T[i].t_text = unpad((str = tgetstr(T[i].t_key, &areap)));
X! 		if (T[i].t_text == NULL) {
X! 		    T[i].t_text = T[i].t_deftext;
X  		}
X! 		T[i].t_size = 0;
X! 		if (T[i].t_text) while (T[i].t_text[T[i].t_size] != '\0')
X! 		    T[i].t_size++;
X  		/*
X! 		 * Check for brain damage (printable character starts
X! 		 * a command sequence).
X  		 */
X! 		if (T[i].t_text && isprint(T[i].t_text[0]))
X! 		    TerminalIsBraindamaged = 1;
X! 		break;
X! 	    case num:
X! 		T[i].t_x = tgetnum(T[i].t_key);
X! 		break;
X! 	    case bool:
X! 		T[i].t_x = tgetflag(T[i].t_key);
X! 		break;
X  	    }
X- 	    if (T[i].t_in)
X- 		if ((*(T[i].t_in)) (T + i))
X- 		    return (1);
X  	}
X!     }
X!     tc_init_ops();
X!     return (0);
X! }
X! 
X! /* Display the string "buf" */
X! tc_display(buf, n)
X!     unsigned char *buf;
X!     register int n;
X! {
X!     while (n--) {
X! 	/* For each character examine each tcap */
X! 	register unsigned char ch, *c;
X! 
X! 	ch = *buf++;
X! 	/* Handle the important case separately */
X! 	if (!TerminalIsBraindamaged && !MatchInProgress && isprint(ch))
X! 	    display_char(ch);
X! 	else if ((c = termcap(ch)) != NULL) {
X! 	    /* There are some characters to display */
X! 	    while (*c) {
X! 		display_char(*c);
X! 		c++;
X! 	    }
X  	}
X      }
X  }
X--- 121,347 ----
X      return (s);
X  }
X  
X! /*
X!  * Matching is performed with a push-down automata implemented
X!  * with dual stacks.  An initial stack is loaded with all the
X!  * potential matches from the termcap structure.  Matching then
X!  * takes place by popping each potential match off the ``current
X!  * stack'' and, if a successful match for the current character
X!  * occurs, pushing the match on the ``other stack''.  When the
X!  * ``current stack'' is empty (all elements have been examined),
X!  * the stacks are swapped and the process restarted.  This continues
X!  * until a completed match or the stack of potential matches has
X!  * been exhausted.
X!  */
X! static	struct	tcap **curstack, **cursp;	/* ``potential match'' stack */
X! static	struct tcap **otherstack, **othersp;	/* ``match this pass'' stack */
X! static	struct tcap **resetstack;		/* prototype curstack */
X! static	int stacksize;				/* # of potential matches */
X! static	int MatchInProgress;			/* for fast check */
X  
X! #define	AllocStack()	malloc(stacksize*sizeof (struct tcap *))
X! #define	PushMatch(tp)	(*--othersp = tp)
X! #define	PopMatch()	(*cursp++)
X! #define	PopMatched()	(*othersp++)
X! #define	SwapStacks() { \
X! 	struct tcap **t; \
X! 	t = curstack, curstack = otherstack, otherstack = t; \
X! 	cursp = othersp, othersp = otherstack + stacksize; \
X! 	MatchInProgress = 1; \
X! }
X! #define	ResetMatchStack() { \
X! 	bcopy(resetstack, curstack, stacksize*sizeof (struct tcap *)); \
X! 	cursp = curstack; \
X! 	MatchInProgress = 0; \
X! }
X! #define	FlushStack(sp, stack) { \
X! 	while (sp < stack+stacksize) { \
X! 	    tp = *sp++; \
X! 	    tp->t_index = 0; \
X! 	    tp->t_matched = 0; \
X! 	    tp->t_2nd = 0; \
X! 	} \
X! }
X! #define	FlushMatchStack()	FlushStack(cursp, curstack)
X! #define	FlushMatchedStack()	FlushStack(othersp, otherstack);
X! #define	MatchStackEmpty()	(cursp >= curstack+stacksize)
X! #define	MatchedStackEmpty()	(othersp >= otherstack+stacksize)
X  
X! /*
X!  * Reset the pattern matching stack and load
X!  * it with all the potential matching entries.
X!  */
X! static
X! tc_init_stacks()
X  {
X! 	register struct tcap *tp;
X! 
X! 	for (tp = T; tp < T+Ts; tp++)
X! 	    if (tp->t_text != NULL)
X! 		stacksize++;
X! 	curstack = (struct tcap **)AllocStack();
X! 	otherstack = (struct tcap **)AllocStack();
X! 	resetstack = (struct tcap **)AllocStack();
X! 	othersp = resetstack+stacksize;
X! 	for (tp = T; tp < T+Ts; tp++)
X! 	    if (tp->t_text != NULL)
X! 		    PushMatch(tp);
X! 	othersp = otherstack+stacksize;
X! 	ResetMatchStack();
X  }
X  
X! /*
X!  * Interpret data from the application.  We match data against
X!  * the ``escape sequences'' expected for this termcap description
X!  * and, if successful, invoke the routines used to emulate the
X!  * capabilities on the window.
X!  */
X! tc_display(cp, n)
X!     u_char *cp;
X!     register int n;
X  {
X!     register int c, j;
X!     register struct tcap *tp;
X!     static char dbuf[256], *dp = dbuf;
X!     int restart, lim;
X  
X!     /*
X!      * For each input character, look for potential
X!      * matches in the tcap structure.  For each possible
X!      * match, construct the resultant output buffer.
X!      * On first match process the operation (e.g. invoke
X!      * internal routine) and flush extraneous matches.
X!      * If input doesn't match any capability, send it to
X!      * the window.
X!      */
X!     while (n > 0) {
X! 	/*
X! 	 * Quick check.  If terminal has only non-printing
X! 	 * escape sequences and we're not in the midst of
X! 	 * a match, then process printable characters w/o
X! 	 * matching against the termcap strings.
X! 	 */
X! 	if (!TerminalIsBraindamaged && !MatchInProgress) {
X! 	    for (dp = (char *)cp; n > 0 && isprint(*cp); n--)
X! 		cp++;
X! 	    if ((char *)cp > dp) {
X! 		tp = T+Ts;
X! 		tp->t_text = dp;	/* use original storage */
X! 		tp->t_size = (char *)cp - dp;
X! 		(*tp->t_op)(tp);
X! 	    }
X! 	    dp = dbuf;
X! 	    if (n == 0)
X! 		break;
X! 	}
X! 	c = *dp++ = *cp++, n--;
X! 	while (!MatchStackEmpty()) {
X! 	    tp = PopMatch();
X! again:
X! 	    j = tp->t_index;
X! 	    restart = 0;
X! 	    /*
X! 	     * Check match against numeric %[d23] specification.
X! 	     */
X! 	    if (tp->t_text[j] == '%') {
X! 		switch (tp->t_text[j+1]) {
X! 		case 'd':			/* series of decimal digits */
X! 		    lim = 127;
X! 		    goto digit;
X! 		case '2':			/* two decimal digits */
X! 		    lim = 2;
X! 		    goto digit;
X! 		case '3':			/* three decimal digits */
X! 		    lim = 3;
X! 		    /* fall thru.. */
X! 	    digit:
X! 		    if (isdigit(c) && tp->t_matched < lim) {
X! 			if (tp->t_matched++ == 0)
X! 				tp->t_param = (c-'0');
X! 			else
X! 				tp->t_param = tp->t_param*10 + (c-'0');
X! 			goto plainmatch;
X! 		    } else if (tp->t_matched > 0) {
X! 			tp->t_matched = 0;
X! 			restart = !isdigit(c);
X! 			goto gotvalue;
X! 		    } else
X! 			goto nomatch;
X! 		    break;
X! 		case '.':			/* binary character */
X! 		    tp->t_param = c;
X! 	    gotvalue:
X! 		    switch (tp->t_2nd + tp->t_pc_r) {
X! 		    case 0:
X! 		    case 2:
X! 			if ((tp->t_y = tp->t_param) >= tp->t_yilim)
X! 			    tp->t_y -= tp->t_yi;
X! 			break;
X! 		    case 1:
X! 			if ((tp->t_x = tp->t_param) >= tp->t_xilim)
X! 			    tp->t_x -= tp->t_xi;
X! 			break;
X! 		    }
X! 		    tp->t_2nd = !tp->t_2nd;
X! 		    tp->t_index += 2;
X! 		    goto plainmatch;
X! 		case '%':
X! 		    if ((c & 0177) == '%') {
X! 			tp->t_index += 2;
X! 			goto plainmatch;
X! 		    } else
X! 			goto nomatch;
X! 		default:
X! 		    abort();	/* XXX */
X! 		    /* NOTREACHED */
X  		}
X! 	    } else if ((c & 0177) == (tp->t_text[j] & 0177)) {
X! 		tp->t_index++;
X!     plainmatch:					/* plain match */
X! 		if (tp->t_index >= tp->t_size) {/* match completed */
X! 		    if (tp->t_op)
X! 			(*tp->t_op)(tp);
X! 		    dp = dbuf;
X! 		    tp->t_index = 0;
X! 		    tp->t_matched = 0;
X! 		    tp->t_2nd = 0;
X! 		    goto done;
X! 		}
X  		/*
X! 		 * The end of a %d match is the only case where a
X! 		 * character must be pushed-back and re-parsed.
X  		 */
X! 		if (restart)
X! 		    goto again;
X! 		PushMatch(tp);			/* push partial match */
X! 	    } else {
X!     nomatch:					/* failed match */
X! 		tp->t_index = 0;
X! 		tp->t_matched = 0;
X! 		tp->t_2nd = 0;
X  	    }
X  	}
X! 	if (!MatchedStackEmpty()) {
X! 	    SwapStacks();
X! 	    continue;
X  	}
X+ done:
X+ 	/*
X+ 	 * Come here either because no partial matches were
X+ 	 * found in the table, or because a match completed.
X+ 	 * In the first case we send the input data off
X+ 	 * immediately.  In the second case we reset the
X+ 	 * state machines and go on to the next character.  
X+ 	 */
X+ 	if (dp - dbuf) {			/* flush output */
X+ 	    tp = T+Ts;
X+ 	    tp->t_text = dbuf;
X+ 	    tp->t_size = dp - dbuf;
X+ 	    (*tp->t_op)(tp);
X+ 	    dp = dbuf;
X+ 	}
X+ 	FlushMatchedStack();			/* reset partial matches */
X+ 	FlushMatchStack();			/* reset unchecked partials */
X+ 	ResetMatchStack();			/* re-init match stack */
X      }
X  }
*-*-END-of-tcap_parse.c.patch-*-*
echo x - termcap.h.patch
sed 's/^X//' >termcap.h.patch <<'*-*-END-of-termcap.h.patch-*-*'
X*** ../psterm.sun/termcap.h	Wed May 27 11:42:12 1987
X--- termcap.h	Sun Jun  7 12:54:22 1987
X***************
X*** 1,3 ****
X--- 1,4 ----
X+ /*	termcap.h	2.1	87/06/07	*/
X  /*
X   * NeWS is a product of Sun Microsystems, Inc. and is provided for
X   * unrestricted use provided that this legend is included on all tape
X***************
X*** 26,34 ****
X   * 2550 Garcia Avenue
X   * Mountain View, California  94043
X   */
X- 
X  /*
X!  * "@(#)termcap.h 1.5 87/03/13
X   *
X   * Copyright (c) 1985 by Sun Microsystems, Inc.
X   */
X--- 27,34 ----
X   * 2550 Garcia Avenue
X   * Mountain View, California  94043
X   */
X  /*
X!  * "@(#)termcap.h 1.1 86/12/12
X   *
X   * Copyright (c) 1985 by Sun Microsystems, Inc.
X   */
X***************
X*** 47,54 ****
X      char *	t_deftext;	/* Default text */
X      u_short	t_size;		/* Length of t_text */
X      u_short	t_index;	/* Posn. in t_text */
X!     char *	t_temp;		/* String for %match */
X!     u_short	t_tempfill;	/* Length of t_temp */
X      u_short	t_x;		/* Coordinate for cm= etc. */
X      u_short	t_xi;		/* Offset to subtract from t_x */
X      u_short	t_xilim;	/* If t_x >= t_xilim subtract t_xi */
X--- 47,54 ----
X      char *	t_deftext;	/* Default text */
X      u_short	t_size;		/* Length of t_text */
X      u_short	t_index;	/* Posn. in t_text */
X!     int		t_param;	/* parameter value for %match */
X!     u_short	t_matched;	/* Length of matched string */
X      u_short	t_x;		/* Coordinate for cm= etc. */
X      u_short	t_xi;		/* Offset to subtract from t_x */
X      u_short	t_xilim;	/* If t_x >= t_xilim subtract t_xi */
*-*-END-of-termcap.h.patch-*-*
exit