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