sources-request@mirror.UUCP (01/27/87)
Submitted by: emoryu1!arnold (Arnold D. Robbins) Mod.sources: Volume 8, Issue 5 Archive-name: se/Part05 Here is the second release of the Georgia Tech Screen Editor, 'se'. There were enough changes that a whole new posting is warranted. Major Changes: All Georgia Tech specific stuff removed. It understands window size changes on 4.3BSD and ATT Unix PC/3B1 Support for the shared library on the ATT Unix PC/3B1 Considerable source code reorganization in certain files. Enjoy, Arnold Robbins #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # term.c # libchangetty # pat export PATH; PATH=/bin:$PATH echo shar: extracting "'term.c'" '(37533 characters)' if test -f 'term.c' then echo shar: will not over-write existing file "'term.c'" else cat << \SHAR_EOF > 'term.c' #ifndef lint static char RCSid[] = "$Header: term.c,v 1.7 86/11/12 11:37:30 arnold Exp $"; #endif /* * $Log: term.c,v $ * Revision 1.7 86/11/12 11:37:30 arnold * Fixed winsize() to verify that cols and rows not 0 before assigning * them to Nrows and Ncols. * * Revision 1.6 86/10/14 11:10:36 arnold * Reorganization of window handling stuff. Added (untested) code for sun. * * Revision 1.5 86/10/07 14:50:48 arnold * Changed setterm to set_term, to avoid Unix/PC shared library conflict. * Fixed winsize() to set Nrows and Ncols on first call, as well. * * Revision 1.4 86/09/19 12:15:28 arnold * Fixes to BSD windowing for real 4.3, from BRL. * * Revision 1.3 86/07/17 17:23:19 arnold * Massive reorganization and cleaning up. Terminal initialization * stuff moved here, and homogenized. * * Revision 1.2 86/07/14 17:19:33 arnold * Added code that notices whether or not the window we are runnng in has * changed sizes. It definitely works on the Unix PC, and should work on * BRL Unix and 4.3 BSD. * * Revision 1.1 86/05/06 13:38:53 osadr * Initial revision * * */ /* ** term.c ** ** provide terminal functions for se ** ** If HARD_TERMS is *not* defined, which is the default, se will ** use the termlib library, which provides terminal independant operations. ** This makes se both smaller, and more flexible. ** ** If HARD_TERMS is defined, then se will use the original code, which ** had terminal types hard-wired into the code. This would be useful for ** a system which does not have the termlib library. ** ** On System V systems, we have two possibilities. Release 1 did not have ** the terminfo package, so we assume that if it is Release 1, someone will ** have ported the BSD termlib library. If it is Release 2, then the new ** terminfo package is there, and we wil use it. ** ** This file is large. It is organized as follows. ** ** Routines that do not care whether or not HARD_TERMS is defined. ** Routines that are only if HARD_TERMS is NOT defined. These contain: ** BSD/termlib routines ** System V/terminfo routines ** Routines idenpendant of BSD/System V ** Routines that are only if HARD_TERMS is defined. ** Routines that have regular and conditonal code mixed. */ #include "se.h" #include "extern.h" /* outc -- write a character to the terminal */ int outc (c) char c; { twrite (1, &c, 1); } #ifndef HARD_TERMS #if defined (BSD) || !defined (S5R2) /* * code for using BSD termlib -- getting capabilities, and writing them out. */ /* capabilities from termcap */ static int AM; /* automatic margins, i.e. wraps at column 80 */ static char *VS; /* visual start -- e.g. clear status line */ static char *VE; /* visual end -- e.g. restore status line */ static char *TI; /* terminal init -- whatever needed for screen ops */ static char *TE; /* terminal ops end */ static char *CM; /* cursor motion, used by tgoto() */ static char *CE; /* clear to end of line */ static char *DL; /* hardware delete line */ static char *AL; /* hardware add (insert) line */ static char *CL; /* clear screen */ extern char PC; /* Pad character, usually '\0' */ static char *pcstr; extern char *tgoto (), *tgetstr (); /* termlib routines */ static char caps[128]; /* space for decoded capability strings */ static char *addr_caps; /* address of caps for relocation */ #define TERMBUFSIZ 1024+1 static char termbuf[TERMBUFSIZ]; /* getdescrip --- get descriptions out of termcap entry */ static getdescrip () { int i; static struct _table { char *name; char **ptr_to_cap; } table[] = { "vs", & VS, "ve", & VE, "ti", & TI, "te", & TE, "cm", & CM, "ce", & CE, "dl", & DL, "al", & AL, "cl", & CL, "pc", & pcstr, NULL, NULL }; AM = tgetflag ("am"); /* only boolean se needs */ /* get string values */ for (i = 0; table[i].name != NULL; i++) *(table[i].ptr_to_cap) = tgetstr (table[i].name, & addr_caps); } /* setcaps -- get the capabilities from termcap file into termbuf */ static setcaps (term) char *term; { switch (tgetent (termbuf, term)) { case -1: error (NO, "se: couldn't open termcap file."); case 0: error (NO, "se: no termcap entry for %s terminals.", term); case 1: addr_caps = caps; getdescrip (); /* get terminal description */ Nrows = tgetnum ("li"); Ncols = tgetnum ("co"); break; default: error (YES, "in setcaps: can't happen.\n"); } return (OK); } #else /* use the new terminfo package */ /* * Do NOT include <curses.h>, since it redefines * USG, ERR, and OK, to values inconsistent with what * we use. */ /* fix a problem in /usr/include/term.h */ #include <termio.h> typedef struct termio SGTTY; #include <term.h> /* should be all we really need */ #define AM auto_right_margin #define TI enter_ca_mode #define TE exit_ca_mode #define VS cursor_visible #define VE cursor_normal #define CL clear_screen #define CE clr_eol #define DL delete_line #define AL insert_line /* setcaps -- get the capabilities from the terminfo database */ static setcaps (term) char *term; { int ret = 0; setupterm (term, 1, & ret); if (ret != 1) return (ERR); Nrows = lines; Ncols = columns; return (OK); } #endif /* t_init -- put out terminal initialization string */ t_init () { if (VS) tputs (VS, 1, outc); if (TI) tputs (TI, 1, outc); /* terminal initializations */ } /* t_exit -- put out strings to turn off whatever modes we had turned on */ t_exit () { /* terminal exiting strings */ if (TE) tputs (TE, 1, outc); if (VE) tputs (VE, 1, outc); tflush (); /* force it out */ } /* winsize --- get the size of the window from the windowing system */ /* also arrange to catch the windowing signal */ #include <signal.h> #ifdef SIGWIND /* UNIX PC */ #include <sys/font.h> #include <sys/window.h> #define WINSIG SIGWIND #define WINIOCTL WIOCGETD #define WINSTRUCT uwdata #define COLS (w.uw_width / w.uw_hs) #define ROWS (w.uw_height / w.uw_vs) #endif #ifdef SIGWINCH /* 4.3 BSD and/or Sun 3.x */ #define WINSIG SIGWINCH #ifdef sun #undef NEWLINE /* shouldn't hurt; these are in sun include files */ #undef TAB #include <sys/types.h> #include <sys/ioctl.h> #include <sys/tty.h> #define WINIOCTL TIOCGSIZE #define WINSTRUCT ttysize #define COLS w.ts_cols #define ROWS w.ts_lines #else #include <sys/ioctl.h> #define WINIOCTL TIOCGWINSZ #define WINSTRUCT winsize #define COLS w.ws_col #define ROWS w.ws_row #endif #endif static struct WINSTRUCT w; winsize () { #if defined(SIGWIND) || defined(SIGWINCH) static int first = 1; static char savestatus[MAXCOLS]; int row, oldstatus = Nrows - 1; int cols, rows; signal (WINSIG, winsize); if (ioctl (0, WINIOCTL, (char *) & w) != -1) { cols = COLS; rows = ROWS; if (first) { first = 0; if (cols && rows) { Ncols = cols; Nrows = rows; } return; /* don't redraw screen */ } else if (Ncols == cols && Nrows == rows) { /* only position changed */ #ifdef SIGWIND remark ("window repositioned"); #endif return; } else { if (cols && rows) { Ncols = cols; Nrows = rows; } } } else return; move_ (Screen_image[oldstatus], savestatus, MAXCOLS); clrscreen (); Toprow = 0; Botrow = Nrows - 3; Cmdrow = Botrow + 1; Sclen = -1; for (row = 0; row < Nrows; row++) move_ (Blanks, Screen_image[row], MAXCOLS); /* clear screen */ First_affected = Topln; adjust_window (Curln, Curln); updscreen (); /* reload from buffer */ loadstr (savestatus, Nrows - 1, 0, Ncols); remark ("window size change"); tflush (); #endif } #else /* begin terminal dependant routines */ /* addspos --- position cursor to (row, col) on ADDS Consul 980 */ static addspos (row, col) int row, col; { char coord; int ntabs, where; if (Currow != row || col < Curcol - 7) { twrite (1, "\013", 1); /* VT */ coord = '@' + row; twrite (1, &coord, 1); Currow = row; Curcol = 0; } if (col > Curcol + 2) { ntabs = (col + 2) / 5; /* from beginning */ where = ntabs * 5; ntabs -= Curcol / 5; /* from Curcol */ if (ntabs + abs (where - col) <= 4) { for (; ntabs > 0; ntabs--) twrite (1, "\t", 1); Curcol = where; } } if (col > Curcol + 4) { where = col - Curcol; twrite (1, "\033\005", 2); /* ESC ENQ */ coord = '0' + (where / 10); twrite (1, &coord, 1); coord = '0' + (where % 10); twrite (1, &coord, 1); Curcol = col; } while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } /* admpos --- position cursor to (row, col) on ADM-3A and ADM-31 terminals */ static admpos (row, col) int row, col; { int dist; char coord; dist = col - Curcol; if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs. position */ { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { twrite (1, "\033=", 2); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); Currow = row; Curcol = col; } } /* ansipos --- position cursor on ANSI X something-or-other terminals */ static ansipos (row, col) register int row, col; { register int dist; char absseq[20], relseq[50]; int absp = 0; register int relp = 0; register int trow, tcol; /*** Build relative positioning string--handle row first ***/ trow = Currow; tcol = Curcol; if (row >= trow && row <= trow + 3) for (; trow < row; trow++) relseq[relp++] = '\012'; else if (row < trow && row >= trow - 1) for (; trow > row; trow--) { relseq[relp++] = '\033'; relseq[relp++] = 'M'; } else if (row >= trow) { relseq[relp++] = '\033'; relseq[relp++] = '['; dist = row - trow; if (dist >= 10) relseq[relp++] = '0' + dist / 10; relseq[relp++] = '0' + dist % 10; relseq[relp++] = 'B'; trow = row; } else /* row < trow */ { relseq[relp++] = '\033'; relseq[relp++] = '['; dist = trow - row; if (dist >= 10) relseq[relp++] = '0' + dist / 10; relseq[relp++] = '0' + dist % 10; relseq[relp++] = 'A'; trow = row; } /*** Now do the column part of relative positioning ***/ if (col >= tcol - 2 && col <= tcol + 2) ; /* skip coarse positioning -- just do the fine stuff */ else { if (col <= 4) { relseq[relp++] = '\015'; tcol = 0; } dist = col - tcol; if (col < 72 && dist > 2 && dist < 8 && (col + 1) % 8 <= 2) { relseq[relp++] = '\t'; tcol = ((tcol + 8) / 8) * 8; } } dist = col - tcol; if (dist < 0) dist = -dist; if (dist == 0) ; else if (dist < 4) /* 4 chars for abs. position */ { while (tcol < col) { relseq[relp++] = Screen_image[trow][tcol]; tcol++; } while (tcol > col) { relseq[relp++] = '\b'; tcol--; } } else if (col >= tcol) { relseq[relp++] = '\033'; relseq[relp++] = '['; if (dist >= 10) relseq[relp++] = '0' + dist / 10; relseq[relp++] = '0' + dist % 10; relseq[relp++] = 'C'; tcol = col; } else /* if (col < tcol) */ { relseq[relp++] = '\033'; relseq[relp++] = '['; if (dist >= 10) relseq[relp++] = '0' + dist / 10; relseq[relp++] = '0' + dist % 10; relseq[relp++] = 'D'; tcol = col; } /*** If relative positioning will do it, forget absolute ***/ if (relp <= 5) twrite (1, relseq, relp); else { absseq[absp++] = '\033'; absseq[absp++] = '['; if (row >= 9) absseq[absp++] = '0' + (row + 1) / 10; absseq[absp++] = '0' + (row + 1) % 10; absseq[absp++] = ';'; if (col >= 9) absseq[absp++] = '0' + (col + 1) / 10; absseq[absp++] = '0' + (col + 1) % 10; absseq[absp++] = 'H'; if (absp >= relp) twrite (1, relseq, relp); else twrite (1, absseq, absp); } Curcol = col; Currow = row; } /* anppos --- position cursor on Allen & Paul model 1 */ static anppos (row, col) int row, col; { char coord; if (row == Currow) /* if close, just sneak right or left */ { if (col == Curcol + 1) twrite (1, "\t", 1); else if (col == Curcol + 2) twrite (1, "\t\t", 2); else if (col == Curcol - 1) twrite (1, "\b", 1); else if (col == Curcol - 2) twrite (1, "\b\b", 2); else { twrite (1, "\033C", 2); coord = col + ' '; twrite (1, &coord, 1); } } else if (col == Curcol) /* if close, sneak up or down */ { if (row == Currow + 1) twrite (1, "\012", 1); else if (row == Currow + 2) twrite (1, "\012\012", 2); else if (row == Currow - 1) twrite (1, "\013", 1); else if (row == Currow - 2) twrite (1, "\013\013", 2); else { /* because of bug in anp software, abs row pos is not working. * the following code was replaced to compensate: * * twrite (1, "\033R", 2); * coord = row + ' '; * twrite (1, &coord, 1); */ twrite (1, "\033P", 2); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); } } else /* resort to absolute positioning */ { twrite (1, "\033P", 2); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); } Currow = row; Curcol = col; } /* b200coord --- transmit a coordinate for Beehive 200 cursor addressing */ static b200coord (coord) int coord; { char acc; int tens, units; tens = coord / 10; units = coord - 10 * tens; acc = units + 16 * tens; twrite (1, & acc, 1); } /* beepos --- position cursor on Beehive terminal */ static beepos (row, col) int row, col; { if (row == Currow + 1 && col == 0 && Term_type != SBEE) { twrite (1, "\r\n", 2); /* CR LF */ Curcol = 0; Currow++; } else if (row == 0 && col == 0) /* home cursor */ { twrite (1, "\033H", 2); Currow = Curcol = 0; } else if (row == Currow && col > Curcol && col <= Curcol + 4) while (Curcol != col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } else if (row == Currow && col < Curcol && col >= Curcol - 4) while (Curcol != col) { twrite (1, "\b", 1); Curcol--; } else /* resort to absolute addressing */ { twrite (1, "\033F", 2); if (Term_type == BEE200 || Term_type == SOL) { b200coord (row); b200coord (col); } else if (Term_type == BEE150) { char r, c; r = row + ' '; c = col + ' '; twrite (1, &r, 1); twrite (1, &c, 1); } else /* is superbee */ { sbeecoord (col); sbeecoord (row); } Currow = row; Curcol = col; } } /* cgpos --- position cursor on Chromatics CG */ static cgpos (row, col) int row, col; { char i, j; if (row == Currow + 1 && col == 0) { twrite (1, "\r\n", 2); /* CR LF */ Curcol = 0; Currow++; } else if (row == 0 && col == 0) /* home cursor */ { twrite (1, "\034", 1); /* FS */ Currow = Curcol = 0; } else if (row == Currow && col > Curcol && col <= Curcol + 7) while (Curcol != col) { twrite (1, "\035", 1); /* GS */ Curcol++; } else if (row == Currow && col < Curcol && col >= Curcol - 7) while (Curcol != col) { twrite (1, "\b", 1); Curcol--; } else { /* resort to absolute addressing */ twrite (1, "\001U", 2); /* SOH U */ i = 511 - (10 * row); j = 6 * col; cgcoord (j); cgcoord (i); Currow = row; Curcol = col; } } /* cgcoord --- output a decimal coordinate for Chromatics CG */ static cgcoord (i) int i; { int units, tens, hundreds; char coords[4]; units = i % 10; i /= 10; tens = i % 10; i /= 10; hundreds = i % 10; coords[0] = hundreds + 16 + ' '; coords[1] = tens + 16 + ' '; coords[2] = units + 16 + ' '; coords[3] = EOS; twrite (1, coords, 3); } /* gt40pos --- position cursor to (row, col) on DEC GT40 with Waugh software */ static gt40pos (row, col) int row, col; { char coord; if (row != Currow && col != Curcol) /* absolute positioning */ { twrite (1, "\033", 1); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); Currow = row; Curcol = col; } else if (row != Currow) /* col must = Curcol */ { /* vertical positioning */ twrite (1, "\006", 1); /* ACK */ coord = row + ' '; twrite (1, &coord, 1); Currow = row; } else if (abs (col - Curcol) < 2) uhcm (col); else { twrite (1, "\025", 1); /* NACK */ coord = col + ' '; twrite (1, &coord, 1); Curcol = col; } } /* h19pos --- position cursor on Heath H19 (DEC VT52 compatible, supposedly) */ static h19pos (row, col) int row, col; { int dist; char coord; dist = col - Curcol; if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs. position */ { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { twrite (1, "\033Y", 2); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); Currow = row; Curcol = col; } } /* hp21pos --- position cursor on HP 2621 terminal */ static hp21pos (row, col) int row, col; { int units, tens; if (row == Currow && col == 0) { twrite (1, "\r\n", 2); /* CR LF */ Curcol = 0; Currow++; } else if (row == 0 && col == 0) /* home cursor */ { twrite (1, "\033H", 2); Currow = Curcol = 0; } else if (row == Currow && col > Curcol && col <= Curcol + 4) while (Curcol != col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } else if (row == Currow && col < Curcol && col >= Curcol - 4) while (Curcol != col) { twrite (1, "\b", 1); Curcol--; } else if (2 * abs (Currow - row) + abs (Curcol - col) <= 7) { while (Currow < row) { twrite (1, "\033B", 2); Currow++; } while (Currow > row) { twrite (1, "\033A", 2); Currow--; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } while (Curcol < col) { twrite (1, & Screen_image[Currow][Curcol], 1); Curcol++; } } else { /* resort to absolute addressing */ char c; twrite (1, "\033&a", 3); units = row % 10; tens = row / 10; if (tens != 0) { c = tens + '0'; twrite (1, &c, 1); } c = units + '0'; twrite (1, &c, 1); twrite (1, "y", 1); units = col % 10; tens = col / 10; if (tens != 0) { c = tens + '0'; twrite (1, &c, 1); } c = units + '0'; twrite (1, &c, 1); twrite (1, "C", 1); Currow = row; Curcol = col; } } /* hazpos --- position cursor on Hazeltine 1510 */ static hazpos (row, col) int row, col; { int dist; char c; dist = col - Curcol; if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs. position */ { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { twrite (1, "\033\021", 2); c = col; twrite (1, &c, 1); c = row; twrite (1, &c, 1); Currow = row; Curcol = col; } } /* ibmpos --- position cursor on IBM 3101 terminal */ static ibmpos (row, col) int row, col; { int dist; static char abspos[] = "\033\Y\0\0"; dist = col - Curcol; if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs pos */ { while (Curcol < col) { twrite (1, & Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { abspos[2] = row + ' '; abspos[3] = col + ' '; twrite (1, abspos, 4); Currow = row; Curcol = col; } } /* iscpos --- position cursor on ISC 8001 color terminal */ static iscpos (row, col) int row, col; { char r, c; if (row == 0 && col == 0) twrite (1, "\b", 1); else { twrite (1, "\003", 1); /* ETX */ r = row; c = col; twrite (1, & r, 1); twrite (1, & c, 1); } Currow = row; Curcol = col; } /* netpos --- position cursor on Netron terminal */ static netpos (row, col) int row, col; { static char abspos[] = "\033=\0\0"; abspos[2] = (char) row; abspos[3] = (char) col; twrite (1, abspos, 4); Currow = row; Curcol = col; } /* pepos --- position cursor on Perkin-Elmer 550 & 1100 terminals */ static pepos (row, col) int row, col; { char coord; /* get on correct row first */ if (Currow == row) ; /* already on correct row; nothing to do */ else if (row == Currow - 1) { twrite (1, "\033A", 2); /* cursor up */ Currow--; } else if (row == Currow + 1) { twrite (1, "\033B", 2); /* cursor down */ Currow++; } else { /* vertical absolute positioning */ twrite (1, "\033X", 2); coord = row + ' '; twrite (1, & coord, 1); } /* now perform horizontal motion */ if (abs (col - Curcol) > 3) /* do absolute horizontal position */ { twrite (1, "\033Y", 2); coord = col + ' '; twrite (1, &coord, 1); Curcol = col; } else uhcm (col); } /* sbeecoord --- transmit a coordinate for Superbee terminal */ static sbeecoord (coord) int coord; { char r, c; r = (coord / 10) + ' '; c = (coord % 10) + ' '; twrite (1, & r, 1); twrite (1, & c, 1); } /* trspos --- position cursor on TRS80 Model 1 */ static trspos (row, col) int row, col; { while (Currow != row) { if (Currow > row) { twrite (1, "\033", 1); Currow--; } else { twrite (1, "\032", 1); /* SUB */ Currow++; } } if (Curcol != col) { if (col > Curcol) while (col > Curcol) { twrite (1, "\031", 1); /* EM */ Curcol++; } else if (col < Curcol / 2) { twrite (1, "\035", 1); /* GS */ Curcol = 0; while (Curcol < col) { twrite (1, "\031", 1); /* EM */ Curcol++; } } else while (col < Curcol) { twrite (1, "\030", 1); /* CAN */ Curcol--; } } } /* tvtpos --- position cursor on Allen's TV Typetwriter II */ static tvtpos (row, col) int row, col; { register int horirel, horiabs, vertrel, vertabs; horirel = col - Curcol; if (horirel < 0) horirel = -horirel; horiabs = col; if (row <= Currow) vertrel = Currow - row; else vertrel = Nrows - (row - Currow); if (row == 0) vertabs = 0; else vertabs = Nrows - row; if (1 + horiabs + vertabs <= horirel + vertrel) { twrite (1, "\014", 1); Currow = Curcol = 0; } while (Currow != row) { twrite (1, "\013", 1); Currow--; if (Currow < 0) Currow = Nrows - 1; } if (Curcol > col) for (; Curcol != col; Curcol--) twrite (1, "\b", 1); else for (; Curcol != col; Curcol++) twrite (1, "\t", 1); } /* regentpos --- position cursor on ADDS Regent 100 */ static regentpos (row, col) int row, col; { int dist; char coord; dist = col - Curcol; if (dist < 0) dist = -dist; if (dist > 4 || Currow != row) { twrite (1, "\033Y", 2); coord = ' ' + row; twrite (1, &coord, 1); coord = ' ' + col; twrite (1, &coord, 1); Currow = row; Curcol = col; } else { while (row < Currow) { twrite (1, "\032", 1); /* SUB, cursor up */ Currow--; } while (row > Currow) { twrite (1, "\n", 1); Currow++; Curcol = 1; } if (col > Curcol) while (col != Curcol) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } else if ((Curcol - col) * 2 >= Ncols) while (col != Curcol) { twrite (1, "\006", 1); /* ACK, cursor right */ if (Curcol == Ncols) Curcol = 1; else Curcol++; } else while (col != Curcol) { twrite (1, "\b", 1); Curcol--; } } } /* vipos --- position cursor on Visual 200 & 50 */ static vipos (row, col) register int row, col; { register int dist; register char coord; if (row == Currow + 1 && col < 3) { twrite (1, "\015\012", 2); Currow++; Curcol = 0; } dist = col - Curcol; if (Term_type == VI200 && row == Currow && col < 72 && dist > 2 && dist < 8 && (col + 1) % 8 < 2) { twrite (1, "\t", 1); Curcol = ((Curcol + 7) / 8) * 8; dist = col - Curcol; } if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs. position */ { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { twrite (1, "\033Y", 2); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); Currow = row; Curcol = col; } } /* vcpos --- position cursor Volker-Craig 4404 (ADM3A mode) */ static vcpos (row, col) int row, col; { int dist; char coord; dist = col - Curcol; if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs. position */ { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { twrite (1, "\033=", 2); coord = row + ' '; twrite (1, &coord, 1); coord = col + ' '; twrite (1, &coord, 1); Currow = row; Curcol = col; } } /* espritpos --- position cursor on Hazeltine Esprit */ static espritpos (row, col) int row, col; { int dist; char c; dist = col - Curcol; if (dist < 0) dist = -dist; if (row == Currow && dist < 4) /* 4 chars for abs. position */ { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } else { twrite (1, "\033\021", 2); c = col >= 32 ? col : col + '`'; twrite (1, &c, 1); c = row >= 32 ? row : row + '`'; twrite (1, &c, 1); Currow = row; Curcol = col; } } /* uhcm --- universal horizontal cursor motion */ static uhcm (col) int col; { while (Curcol < col) { twrite (1, &Screen_image[Currow][Curcol], 1); Curcol++; } while (Curcol > col) { twrite (1, "\b", 1); Curcol--; } } /* senddelay --- send NULs to delay n milliseconds */ senddelay (n) int n; { register int q; q = (long) n * Tspeed / 1000l; while (q > 0) { twrite (1, "\0\0\0\0\0\0\0\0\0\0", q > 10 ? 10 : q); q -= 10; } } /* decode_mnemonic --- decode a terminal type mnemonic */ static int decode_mnemonic (str) char str[]; { int i; int strbsr (); static struct { char *s; int t; } stab[] = { "950", TVI950, "adm31", ADM31, "adm3a", ADM3A, "anp", ANP, "b150", BEE150, "b200", BEE200, "cg", CG, "consul", ADDS980, "esprit", ESPRIT, "fox", FOX, "gt40", GT40, "h19", H19, "haz", HAZ1510, "hp21", HP21, "hz1510", HAZ1510, "ibm", IBM, "isc", ISC8001, "netron", NETRON, "regent", ADDS100, "regent40", ADDS100, /* kludge */ "sbee", SBEE, "sol", SOL, "trs80", TRS80, "ts1", TS1, "tvt", TVT, "vc4404", VC4404, "vi200", VI200, "vi300", VI300, "vi50", VI50, }; i = strbsr ((char *)stab, sizeof (stab), sizeof (stab[0]), str); if (i == EOF) return (ERR); else return (stab[i].t); } #endif /* terminal handling functions used throughout the editor */ /* send --- send a printable character, predict cursor position */ send (chr) char chr; { if (Currow == Nrows - 1 && Curcol == Ncols - 1) return; /* anything in corner causes scroll... */ #ifndef HARD_TERMS outc (chr); #else twrite (1, &chr, 1); #endif if (Curcol == Ncols - 1) { #ifndef HARD_TERMS if (AM) /* terminal wraps when hits last column */ #else if (Term_type != TVT && Term_type != NETRON && Term_type != ESPRIT && Term_type != VI300) #endif { Curcol = 0; Currow++; } } else /* cursor not at extreme right */ Curcol++; } /* clrscreen --- clear entire screen */ clrscreen () { Curcol = Currow = 0; /* clearing screen homes cursor to upper left corner */ /* on all terminals */ #ifndef HARD_TERMS tputs (CL, 1, outc); #else switch (Term_type) { case ADDS980: case ADDS100: case GT40: case CG: case ISC8001: case ANP: case NETRON: twrite (1, "\014", 1); break; case FOX: twrite (1, "\033K", 2); /* clear display and all tabs */ break; case TVT: twrite (1, "\014\017", 2); /* home, erase to end of screen */ break; case BEE150: case BEE200: case SBEE: case SOL: case H19: twrite (1, "\033E", 2); break; case HAZ1510: case ESPRIT: twrite (1, "\033\034", 2); break; case ADM3A: case VC4404: case TVI950: twrite (1, "\032", 1); break; case TS1: twrite (1, "\033*", 2); break; case ADM31: twrite (1, "\033+", 2); break; case IBM: twrite (1, "\033L", 2); break; case HP21: twrite (1, "\033H\033J", 4); /* home cursor, erase to end of screen */ break; case TRS80: twrite (1, "\034\037", 2); break; case VI200: twrite (1, "\033v", 2); break; case VI300: twrite (1, "\033[H\033[J", 6); /* home cursor, clear screen */ break; case VI50: twrite (1, "\033v", 2); senddelay (30); break; } senddelay (20); #endif } /* position_cursor --- position terminal's cursor to (row, col) */ position_cursor (row, col) int row, col; { if (row < Nrows && row >= 0 /* within vertical range? */ && col < Ncols && col >= 0 /* within horizontal range? */ && (row != Currow || col != Curcol))/* not already there? */ #ifndef HARD_TERMS { if (row == Currow && abs (Curcol - col) <= 4) { /* short motion in current line */ if (Curcol < col) for (; Curcol != col; Curcol++) twrite (1, &Screen_image[Currow][Curcol], 1); else for (; Curcol != col; Curcol--) twrite (1, "\b", 1); } else { #if defined (USG) && defined(S5R2) tputs (tparm (cursor_address, row, col), 1, outc); #else tputs (tgoto (CM, col, row), 1, outc); #endif Currow = row; Curcol = col; } } #else switch (Term_type) { case ADDS980: addspos (row, col); break; case ADDS100: regentpos (row, col); break; case HP21: hp21pos (row, col); break; case FOX: pepos (row, col); break; case TVT: tvtpos (row, col); break; case GT40: gt40pos (row, col); break; case BEE150: case BEE200: case SBEE: case SOL: beepos (row, col); break; case VC4404: vcpos (row, col); break; case HAZ1510: hazpos (row, col); break; case ESPRIT: espritpos (row, col); break; case CG: cgpos (row, col); break; case ISC8001: iscpos (row, col); break; case ADM3A: case ADM31: case TS1: case TVI950: admpos (row, col); break; case IBM: ibmpos (row, col); break; case ANP: anppos (row, col); break; case NETRON: netpos (row, col); break; case H19: h19pos (row, col); break; case TRS80: trspos (row, col); break; case VI200: case VI50: vipos (row, col); break; case VI300: ansipos (row, col); break; } #endif } /* setscreen --- initialize screen and associated descriptive variables */ setscreen () { register int row, col; #ifndef HARD_TERMS t_init (); /* put out the 'ti' and 'vs' capabilities */ #endif clrscreen (); /* clear physical screen, set cursor position */ Toprow = 0; Botrow = Nrows - 3; /* 1 for 0-origin, 1 for status, 1 for cmd */ Cmdrow = Botrow + 1; Topln = 1; Sclen = -1; /* make sure we assume nothing on the screen */ for (row = 0; row < Nrows; row++) /* now clear virtual screen */ for (col = 0; col < Ncols; col++) Screen_image[row][col] = ' '; for (col = 0; col < Ncols; col++) /* and clear out status line */ Msgalloc[col] = NOMSG; Insert_mode = NO; } /* inslines --- insert 'n' lines on the screen at 'row' */ inslines (row, n) int row, n; { register int i; int delay; position_cursor (row, 0); #ifdef HARD_TERMS if (Term_type == VI300) { char pseq[10]; register int pp = 0; pseq[pp++] = '\033'; pseq[pp++] = '['; if (n >= 10) pseq[pp++] = '0' + n / 10; pseq[pp++] = '0' + n % 10; pseq[pp++] = 'L'; twrite (1, pseq, pp); delay = 0; } else #endif for (i = 0; i < n; i++) { #ifndef HARD_TERMS tputs (AL, n, outc); tflush (); #else switch (Term_type) { case VI200: twrite (1, "\033L", 2); delay = 0; break; case VI50: case H19: twrite (1, "\033L", 2); delay = 32; break; case ESPRIT: twrite (1, "\033\032", 2); delay = 32; break; case TS1: case TVI950: twrite (1, "\033E", 2); delay = 0; break; case ADDS100: twrite (1, "\033M", 2); delay = 96; break; default: error (YES, "in inslines: shouldn't happen"); } if (delay != 0) senddelay (delay); #endif } for (i = Nrows - 1; i - n >= Currow; i--) move_ (Screen_image[i - n], Screen_image[i], Ncols); for (; i >= Currow; i--) move_ (Blanks, Screen_image[i], Ncols); } /* dellines --- delete 'n' lines beginning at 'row' */ dellines (row, n) int row, n; { register int i; int delay; position_cursor (row, 0); #ifdef HARD_TERMS if (Term_type == VI300) { char pseq[10]; register int pp = 0; pseq[pp++] = '\033'; pseq[pp++] = '['; if (n >= 10) pseq[pp++] = '0' + n / 10; pseq[pp++] = '0' + n % 10; pseq[pp++] = 'M'; twrite (1, pseq, pp); delay = 0; } else #endif for (i = 0; i < n; i++) { #ifndef HARD_TERMS tputs (DL, n, outc); tflush (); #else switch (Term_type) { case VI200: twrite (1, "\033M", 2); delay = 0; break; case VI50: twrite (1, "\033M", 2); delay = 32; break; case H19: twrite (1, "\033M", 2); delay = 32; break; case TS1: case TVI950: twrite (1, "\033R", 2); delay = 0; break; case ESPRIT: twrite (1, "\033\023", 2); delay = 32; break; case ADDS100: twrite (1, "\033l", 2); delay = 96; break; default: error (YES, "in dellines: shouldn't happen"); } if (delay != 0) senddelay (delay); #endif } for (i = Currow; i + n < Nrows; i++) move_ (Screen_image[i + n], Screen_image[i], Ncols); for (; i < Nrows; i++) move_ (Blanks, Screen_image[i], Ncols); } /* hwinsdel --- return 1 if the terminal has hardware insert/delete */ int hwinsdel () { if (No_hardware == YES) return (NO); #ifndef HARD_TERMS return (AL != NULL && DL != NULL); #else switch (Term_type) { case VI300: case VI200: case VI50: case ESPRIT: case H19: case TS1: case TVI950: case ADDS100: return 1; } return 0; #endif } /* clear_to_eol --- clear screen to end-of-line */ clear_to_eol (row, col) int row, col; { register int c, flag; register int hardware = NO; #ifdef HARD_TERMS switch (Term_type) { case BEE200: case BEE150: case FOX: case SBEE: case ADDS100: case HP21: case IBM: case ANP: case NETRON: case H19: case TS1: case TRS80: case ADM31: case VI200: case VI300: case VI50: case VC4404: case ESPRIT: case TVI950: hardware = YES; break; default: hardware = (Term_type == ADDS980 && row < Nrows - 1) || (Term_type == TVT && row > 0); } #else hardware = (CE != NULL); #endif flag = NO; for (c = col; c < Ncols; c++) if (Screen_image[row][c] != ' ') { Screen_image[row][c] = ' '; if (hardware) flag = YES; else { position_cursor (row, c); send (' '); } } if (flag == YES) { position_cursor (row, col); #ifndef HARD_TERMS tputs (CE, 1, outc); #else switch (Term_type) { case BEE200: case BEE150: case SBEE: case ADDS100: case HP21: case H19: case VC4404: case TS1: case TVI950: case VI50: twrite (1, "\033K", 2); break; case FOX: case IBM: twrite (1, "\033I", 2); break; case ADDS980: twrite (1, "\n", 1); Currow++; Curcol = 0; break; case ANP: twrite (1, "\033L", 2); break; case NETRON: twrite (1, "\005", 1); break; case TRS80: twrite (1, "\036", 1); break; case ADM31: twrite (1, "\033T", 2); break; case VI200: twrite (1, "\033x", 2); break; case VI300: twrite (1, "\033[K", 3); break; case ESPRIT: twrite (1, "\033\017", 2); break; case TVT: twrite (1, "\013\012", 2); break; } /* end switch */ #endif } /* end if (flag == YES) */ } /* set_term -- initialize terminal parameters and actual capabilities */ set_term (type) char *type; { if (type == NULL) error (NO, "se: terminal type not available"); if (type[0] == EOS) error (NO, "in set_term: can't happen."); Ncols = Nrows = -1; #ifdef HARD_TERMS if ((Term_type = decode_mnemonic (type)) == ERR) error (NO, "se: could not find terminal in internal database"); switch (Term_type) { case ADDS980: case FOX: case HAZ1510: case ADDS100: case BEE150: case ADM3A: case IBM: case HP21: case H19: case ADM31: case VI200: case VC4404: case ESPRIT: case TS1: case TVI950: case VI50: case VI300: Nrows = 24; Ncols = 80; break; case ANP: Nrows = 24; Ncols = 96; break; case SOL: case NETRON: case TRS80: Nrows = 16; Ncols = 64; break; case TVT: Nrows = 16; Ncols = 63; break; case GT40: Nrows = 32; Ncols = 73; break; case CG: Nrows = 51; Ncols = 85; break; case ISC8001: Nrows = 48; Ncols = 80; break; case BEE200: case SBEE: Nrows = 25; Ncols = 80; break; } #else if (setcaps (type) == ERR) error (NO, "se: could not find terminal in system database"); PC = pcstr ? pcstr[0] : EOS; if (*tgoto (CM, 0, 0) == 'O') /* OOPS returned.. */ error (NO, "se: terminal does not have cursor motion."); /* * first, get it from the library. then check the * windowing system, if there is one. */ winsize (); #endif if (Nrows == -1) error (NO, "se: could not determine number of rows"); if (Ncols == -1) error (NO, "se: could not determine number of columns"); return OK; } SHAR_EOF fi # end of overwriting check if test ! -d 'libchangetty' then echo shar: creating directory "'libchangetty'" mkdir 'libchangetty' fi echo shar: entering directory "'libchangetty'" cd 'libchangetty' echo shar: extracting "'changetty.c'" '(5555 characters)' if test -f 'changetty.c' then echo shar: will not over-write existing file "'changetty.c'" else cat << \SHAR_EOF > 'changetty.c' #ifndef lint static char RCSid[] = "$Header: changetty.c,v 1.2 86/07/11 15:23:06 osadr Exp $"; #endif /* * $Log: changetty.c,v $ * Revision 1.2 86/07/11 15:23:06 osadr * Removed Georgia Tech specific code. * * Revision 1.1 86/05/06 13:31:06 osadr * Initial revision * * */ /* ** changetty.c ** ** Localize in one place all the data and functions ** needed to change to and from cbreak mode for ** the se screen editor. ** ** Only functions available to rest of se are: ** ttyedit(), ttynormal(), and getspeed(). ** ** If USG is defined, we use the System V TTY driver. ** Otherwise (the default) we use the Berkeley terminal driver. ** ** If we are using System V, then the Release 2 version does not ** need ospeed. If not release 2, we assume Release 1 that someone ** have moved the BSD termlib to. */ #include "../ascii.h" #include "../constdefs.h" #ifdef USG #include <termio.h> #else #include <sgtty.h> #endif #if defined (BSD) || ! defined (S5R2) extern short ospeed; /* from the termlib library */ static int set_ospeed = NO; #endif #ifdef USG /* all the info needed for the System V terminal driver */ typedef struct termio TTYINFO; /* S5 control flags */ #else /* all the info needed for the Berkeley terminal driver */ typedef struct junk { /* terminal information */ struct sgttyb sgttyb; /* V7 control flags */ struct tchars tchars; /* V7 control characters */ short local; /* local mode settings */ struct ltchars ltchars; /* local control characters */ } TTYINFO; #endif static TTYINFO OldTtyInfo; /* initial state of terminal */ static TTYINFO NewTtyInfo; /* modified state for editing */ static int first = YES; /* first time anything called */ static init() { if (gttyinfo(1, &OldTtyInfo) == -1) /* get current state */ error ("couldn't get TTY info from system. get help!\n"); NewTtyInfo = OldTtyInfo; /* copy it */ mttyinfo(&NewTtyInfo); /* change, but don't reset terminal */ /* really should check the return value here ... */ } ttyedit() /* set the terminal to correct modes for editing */ { if (first == YES) { first = NO; init(); } sttyinfo(1, &NewTtyInfo); /* make the change */ /* really should check the return value here too ... */ } ttynormal() /* set the terminal to correct modes for normal use */ { if (first) { first = NO; init(); } sttyinfo(1, &OldTtyInfo); /* make the change */ } /* getspeed --- find out the terminal speed in characters/second */ /* this routine only used if terminal types are hardwired */ /* into se, however, since it will be in an archive, the */ /* loader won't grab it if it isn't needed. */ int getspeed(fd) int fd; { register int i; TTYINFO ttybuf; static struct brstruct { int unixrate; int cps; int baudrate; } stab[] = { B0, 0, 0, B50, 5, 50, B75, 8, 75, B110, 10, 110, B134, 14, 134, B150, 15, 150, B200, 20, 200, B300, 30, 300, B600, 60, 600, B1200, 120, 1200, B1800, 180, 1800, B2400, 240, 2400, B4800, 480, 4800, B9600, 960, 9600 }; if (first) /* might as well set it here, too */ { first = NO; init(); } if (gttyinfo(fd, &ttybuf) == -1) return 960; for (i = 0; i < sizeof(stab) / sizeof(struct brstruct); i++) #ifdef USG if (stab[i].unixrate == (ttybuf.c_cflag & 017)) #else if (stab[i].unixrate == (ttybuf.sgttyb.sg_ospeed)) #endif return stab[i].cps; return 960; } /* gttyinfo --- make all necessary calls to obtain terminal status */ static int gttyinfo(fd, buf) int fd; /* file descriptor of terminal */ TTYINFO *buf; /* terminal info buffer to be filled in */ { #ifdef USG if (ioctl(fd, TCGETA, buf) < 0) #else if (gtty(fd, &(buf->sgttyb)) < 0 || ioctl(fd, TIOCGETC, &(buf->tchars)) < 0 || ioctl(fd, TIOCLGET, &(buf->local)) < 0 || ioctl(fd, TIOCGLTC, &(buf->ltchars)) < 0) #endif { return -1; } #if defined (BSD) || ! defined (S5R2) if (set_ospeed == NO) { set_ospeed = YES; #ifdef BSD ospeed = (buf->sgttyb).sg_ospeed; #else ospeed = buf->c_cflag & 017; /* tty speed, see termio(7) */ #endif } #endif return 0; } /* mttyinfo --- modify a TTYINFO structure for interactive operation */ static int mttyinfo(buf) TTYINFO *buf; /* buffer containing TTYINFO to be modified */ { #ifdef USG buf->c_cc[0] = DLE; /* interrupt */ buf->c_cc[1] = -1; /* ignore quit */ buf->c_cc[4] = 1; /* min # chars to read */ buf->c_cc[5] = 1; /* min time to wait */ buf->c_iflag &= ~(INLCR|IGNCR|ICRNL); /* allow CR to come thru */ buf->c_lflag |= ISIG|NOFLSH; /* keep these bits */ buf->c_lflag &= ~(ICANON|XCASE|ECHO|ECHOE|ECHOK|ECHONL); #else static struct tchars newtchars = {DLE, -1, DC1, DC3, EOT, -1}; static struct ltchars newltchars = {-1, -1, -1, -1, -1, -1}; buf->sgttyb.sg_flags |= (CBREAK); /* keep these bits */ buf->sgttyb.sg_flags &= ~(ECHO|CRMOD|LCASE|RAW|ALLDELAY); buf->tchars = newtchars; /* buf->local |= (LLITOUT); /* Dan Forsyth says to comment out */ buf->local &= ~(LCRTBS|LCRTERA|LPRTERA|LTOSTOP|LFLUSHO|LCRTKIL| #ifndef BSD4_2 LINTRUP| #endif LCTLECH|LPENDIN); buf->ltchars = newltchars; #endif return 0; } /* sttyinfo --- make all necessary calls to set terminal status */ static int sttyinfo(fd, buf) int fd; /* file descriptor of terminal */ TTYINFO *buf; /* terminal info buffer */ { #ifdef USG if (ioctl(fd, TCSETAW, buf) < 0) #else if (ioctl(fd, TIOCSETN, &(buf->sgttyb)) < 0 || ioctl(fd, TIOCSETC, &(buf->tchars)) < 0 || ioctl(fd, TIOCLSET, &(buf->local)) < 0 || ioctl(fd, TIOCSLTC, &(buf->ltchars)) < 0) #endif return -1; return 0; } SHAR_EOF fi # end of overwriting check echo shar: extracting "'makefile'" '(734 characters)' if test -f 'makefile' then echo shar: will not over-write existing file "'makefile'" else cat << \SHAR_EOF > 'makefile' # # $Header: makefile,v 1.2 86/07/11 15:23:24 osadr Exp $ # # $Log: makefile,v $ # Revision 1.2 86/07/11 15:23:24 osadr # Changed to ensure the proper 'ar' program is used. # # Revision 1.1 86/05/06 13:31:30 osadr # Initial revision # # # # makefile for libchangetty.a -- terminal resetting functions TARGET= libchangetty.a SRCS= changetty.c OBJS= changetty.o PRINTS= $(SRCS) makefile CFLAGS= -O `cat ../flags` $(TARGET): $(OBJS) ../flags /bin/ar ruv $(TARGET) $(OBJS) if test -r /usr/bin/ranlib; then /usr/bin/ranlib $(TARGET); fi clean: rm -fr $(OBJS) clobber: clean rm -fr $(TARGET) print2 print: prt $(PRINTS) | lpr -b 'tty lib' touch print2 print2: $(PRINTS) prt $? | lpr -b 'new tty lib' touch print2 SHAR_EOF fi # end of overwriting check echo shar: done with directory "'libchangetty'" cd .. if test ! -d 'pat' then echo shar: creating directory "'pat'" mkdir 'pat' fi echo shar: entering directory "'pat'" cd 'pat' echo shar: extracting "'pat.c'" '(11312 characters)' if test -f 'pat.c' then echo shar: will not over-write existing file "'pat.c'" else cat << \SHAR_EOF > 'pat.c' #ifndef lint static char RCSid[] = "$Header: pat.c,v 1.2 86/07/11 15:24:44 osadr Exp $"; #endif /* * $Log: pat.c,v $ * Revision 1.2 86/07/11 15:24:44 osadr * Removed Georgia Tech-ism of changeable pattern characters. * * Revision 1.1 86/05/06 13:32:49 osadr * Initial revision * * */ /* ** pat.c ** ** pattern matching subroutines for the se screen editor. ** ** routines declared static are not necessary for the rest ** of the editor, therefore make them static in the name ** of modularity. */ #include <stdio.h> #include <ctype.h> #include "../constdefs.h" /* Definitions used only for pattern matching */ #define AND '&' #define CCL '[' #define CCLEND ']' #define CHAR 'a' #define CLOSIZE 1 #define CLOSURE '*' #define DASH '-' #define DITTO 0200 #define EOL '$' #define NCCL 'n' #define NEWLINE '\n' #define TAB '\t' #define ANY '.' #define BOL '^' #define NOTINCCL '^' #define START_TAG '(' #define STOP_TAG ')' #define ESCAPE '\\' /* Array dimensions and other limit values */ #define MAXLINE 128 #define MAXPAT 128 /* Pattern matching subroutines: */ /* match () --- find match anywhere on line */ match (lin, pat) register char lin[]; register char pat[]; { int junk[9]; register char *pc; for (pc = lin; *pc != EOS; pc++) if (amatch (lin, pc - lin, pat, junk, junk) >= 0) return (YES); return (NO); } /* amatch() --- (recursive) look for match starting at lin[from] */ amatch(lin, from, pat, tagbeg, tagend) int from, tagbeg[], tagend[]; char lin[], pat[]; { char *ch, *lastc; register char *ppat; int k; lastc = lin + from; /* next unexamined input character */ for (ppat = pat; *ppat != EOS; ppat += patsiz (ppat)) if (*ppat == CLOSURE) /* a closure entry */ { ppat++; for (ch = lastc; *ch != EOS; ) /* match as many as possible */ if (omatch (lin, &ch, ppat) == NO) break; /* * ch now points to character that made us fail * try to match rest of pattern against rest of input * shrink the closure by 1 after each failure */ for (ppat += patsiz (ppat); ch >= lastc; ch--) /* successful match of rest of pattern */ if ((k = amatch (lin, ch - lin, ppat, tagbeg, tagend)) >= 0) break; lastc = lin + k; /* if k < 0, failure */ /* if k >= 0, success */ break; } else if (*ppat == START_TAG) tagbeg[*(ppat + 1)] = lastc - lin; else if (*ppat == STOP_TAG) tagend[*(ppat + 1)] = lastc - lin; /* non-closure */ else if (omatch (lin, &lastc, ppat) == NO) return (-1); /* else omatch succeeded */ return (lastc - lin); } /* omatch () --- try to match a single pattern at ppat */ static omatch (lin, adplin, ppat) char lin[], **adplin, *ppat; { register char *plin; register int bump, retval; plin = *adplin; retval = NO; if (*plin == EOS) return (retval); bump = -1; switch (*ppat) { case CHAR: if (*plin == *(ppat + 1)) bump = 1; break; case BOL: if (plin == lin) bump = 0; break; case ANY: if (*plin != NEWLINE) bump = 1; break; case EOL: if (*plin == NEWLINE) bump = 0; break; case CCL: if (locate (*plin, ppat + 1) == YES) bump = 1; break; case NCCL: if (*plin != NEWLINE && locate (*plin, ppat + 1) == NO) bump = 1; break; default: error ("in omatch: can't happen."); } if (bump >= 0) { *adplin += bump; retval = YES; } return (retval); } /* locate () --- look for c in char class at ppat */ static locate (c, ppat) register char c, *ppat; { register char *pclas; /* size of class is at ppat, characters follow */ for (pclas = ppat + *ppat; pclas > ppat; pclas--) if (c == *pclas) return (YES); return (NO); } /* patsiz () --- returns size of pattern entry at ppat */ static patsiz (ppat) register char *ppat; { switch (*ppat) { case CHAR: case START_TAG: case STOP_TAG: return (2); case BOL: case EOL: case ANY: return (1); case CCL: case NCCL: return (*(ppat + 1) + 2); case CLOSURE: return (CLOSIZE); default: error ("in patsiz: can't happen."); } } /* makpat () --- make pattern from arg[from], terminate at delim */ makpat (arg, from, delim, pat) char arg[], delim, pat[]; int from; { char ch, esc (); int argsub, junk, lastsub, ls, patsub, tag_nest, tag_num, tag_stack[9]; lastsub = patsub = 0; tag_num = -1; tag_nest = -1; for (argsub = from; arg[argsub] != delim && arg[argsub] != EOS; argsub++) { ls = patsub; if (arg[argsub] == ANY) junk = addset (ANY, pat, &patsub, MAXPAT); else if (arg[argsub] == BOL && argsub == from) junk = addset (BOL, pat, &patsub, MAXPAT); else if (arg[argsub] == EOL && arg[argsub + 1] == delim) junk = addset (EOL, pat, &patsub, MAXPAT); else if (arg[argsub] == CCL) { if (getccl (arg, &argsub, pat, &patsub) == ERR) return (ERR); } else if (arg[argsub] == CLOSURE && argsub > from) { ls = lastsub; if (pat[ls] == BOL || pat[ls] == EOL || pat[ls] == CLOSURE || pat[ls] == START_TAG || pat[ls] == STOP_TAG) break; stclos (pat, &patsub, &lastsub); } else if (start_tag(arg, &argsub)) { /* too many tagged sub-patterns */ if (tag_num >= 8) break; tag_num++; tag_nest++; tag_stack[tag_nest] = tag_num; junk = addset (START_TAG, pat, &patsub, MAXPAT); junk = addset (tag_num, pat, &patsub, MAXPAT); } else if (stop_tag(arg, &argsub) && tag_nest > -1) { junk = addset (STOP_TAG, pat, &patsub, MAXPAT); junk = addset (tag_stack[tag_nest], pat, &patsub, MAXPAT); tag_nest--; } else { junk = addset (CHAR, pat, &patsub, MAXPAT); /* don't allow match of newline other than via $ */ if ((ch = esc(arg, &argsub)) == NEWLINE) return (ERR); junk = addset (ch, pat, &patsub, MAXPAT); } lastsub = ls; } if (arg[argsub] != delim) /* terminated early */ return (ERR); else if (addset (EOS, pat, &patsub, MAXPAT) == NO) /* no room */ return (ERR); else if (tag_nest != -1) return (ERR); else return (argsub); } /* getccl () --- expand char class at arg[*pasub] into pat[*pindex] */ static getccl (arg, pasub, pat, pindex) char arg[], pat[]; int *pasub, *pindex; { int junk, start; (*pasub)++; /* skip over [ */ if (arg[*pasub] == NOTINCCL) { junk = addset (NCCL, pat, pindex, MAXPAT); (*pasub)++; } else junk = addset (CCL, pat, pindex, MAXPAT); start = *pindex; junk = addset (0, pat, pindex, MAXPAT); /* leave room for count */ filset (CCLEND, arg, pasub, pat, pindex, MAXPAT); pat[start] = *pindex - start - 1; if (arg[*pasub] == CCLEND) return (OK); else return (ERR); } /* stclos () --- insert closure entry at pat[*ppatsub] */ static stclos (pat, ppatsub, plastsub) char pat[]; int *ppatsub, *plastsub; { int i, j, junk; for (i = *ppatsub - 1; i >= *plastsub; i--) /* make a hole */ { j = i + CLOSIZE; junk = addset (pat[i], pat, &j, MAXPAT); } *ppatsub += CLOSIZE; /* put closure in it */ junk = addset (CLOSURE, pat, plastsub, MAXPAT); } /* maksub () --- make substitution string in sub */ maksub (arg, from, delim, sub) char arg[], delim, sub[]; int from; { char esc (); int argsub, index, junk; index = 0; for (argsub = from; arg[argsub] != delim && arg[argsub] != EOS; argsub++) if (arg[argsub] == AND) { junk = addset (DITTO, sub, &index, MAXPAT); junk = addset (0, sub, &index, MAXPAT); } else if (arg[argsub] == ESCAPE && isdigit (arg[argsub + 1])) { argsub++; junk = addset (DITTO, sub, &index, MAXPAT); junk = addset (arg[argsub] - '0', sub, &index, MAXPAT); } else junk = addset (esc (arg, &argsub), sub, &index, MAXPAT); if (arg[argsub] != delim) /* missing delimeter */ return (ERR); else if (addset (EOS, sub, &index, MAXPAT) == NO) /* no room */ return (ERR); else return (argsub); } /* catsub () --- add replacement text to end of new */ catsub (lin, from, to, sub, new, k, maxnew) register char lin[], new[], sub[]; int from[], *k, maxnew, to[]; { int junk, ri; register int i, j; for (i = 0; sub[i] != EOS; i++) if ((sub[i] & 0xff) == DITTO) { ri = sub[++i]; for (j = from[ri]; j < to[ri]; j++) junk = addset (lin[j], new, k, maxnew); } else junk = addset (sub[i], new, k, maxnew); } /* filset () --- expand set at array[*pasub] into set[*pindex], stop at delim */ filset (delim, array, pasub, set, pindex, maxset) char array[], delim, set[]; int maxset, *pasub, *pindex; { char esc (); int junk; static char digits[] = "0123456789"; static char lowalf[] = "abcdefghijklmnopqrstuvwxyz"; static char upalf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for ( ; array[*pasub] != delim && array[*pasub] != EOS; (*pasub)++) if (array[*pasub] == ESCAPE) junk = addset (esc (array, pasub), set, pindex, maxset); else if (array[*pasub] != DASH) junk = addset (array[*pasub], set, pindex, maxset); /* literal DASH */ else if (*pindex <= 0 || array[*pasub + 1] == EOS || array[*pasub + 1] == delim) junk = addset (DASH, set, pindex, maxset); /* else if (index (digits, set[*pindex - 1]) >= 0) */ else if (isdigit(set[*pindex - 1])) dodash (digits, array, pasub, set, pindex, maxset); /* else if(index (lowalf, set[*pindex - 1]) >= 0) */ else if (islower(set[*pindex - 1])) dodash (lowalf, array, pasub, set, pindex, maxset); /* else if (index (upalf, set[*pindex - 1]) >= 0) */ else if (isupper(set[*pindex - 1])) dodash (upalf, array, pasub, set, pindex, maxset); else junk = addset (DASH, set, pindex, maxset); } /* ** dodash () --- expand array[*pasub - 1]-array[*pasub + 1] into set[*pindex], ** from valid */ static dodash (valid, array, pasub, set, pindex, maxset) char array[], set[], valid[]; int maxset, *pasub, *pindex; { char esc (); int junk, k, limit; (*pasub)++; (*pindex)--; limit = index (valid, esc (array, pasub)); for (k = index (valid, set[*pindex]); k <= limit; k++) junk = addset (valid[k], set, pindex, maxset); } /* addset () --- put c in set[*pindex]; if it fits, increment *pindex */ addset (c, set, pindex, maxsiz) int maxsiz, *pindex; char c, set[]; { if (*pindex >= maxsiz) return (NO); else { set[(*pindex)++] = c; return (YES); } } /* esc () --- map array[*pindex] into escaped character if appropriate */ char esc (array, pindex) char array[]; int *pindex; { if (array[*pindex] != ESCAPE) return (array[*pindex]); else if (array[*pindex + 1] == EOS) /* ESCAPE not special at end */ return (ESCAPE); else { if (array[++(*pindex)] == 'n') return (NEWLINE); else if (array[*pindex] == 't') return (TAB); else return (array[*pindex]); } } /* start_tag --- determine if we've seen the start of a tagged pattern */ static int start_tag(arg, argsub) char *arg; int *argsub; { if (arg[*argsub] == ESCAPE && arg[*argsub + 1] == START_TAG) { (*argsub)++; return (YES); } else return (NO); } /* stop_tag --- determine if we've seen the end of a tagged pattern */ static int stop_tag(arg, argsub) char *arg; int *argsub; { if (arg[*argsub] == ESCAPE && arg[*argsub + 1] == STOP_TAG) { (*argsub)++; return (YES); } else return (NO); } SHAR_EOF fi # end of overwriting check echo shar: extracting "'makefile'" '(673 characters)' if test -f 'makefile' then echo shar: will not over-write existing file "'makefile'" else cat << \SHAR_EOF > 'makefile' # # $Header: makefile,v 1.2 86/07/11 15:25:14 osadr Exp $ # # $Log: makefile,v $ # Revision 1.2 86/07/11 15:25:14 osadr # Changed to ensure that the proper 'ar' program gets used. # # Revision 1.1 86/05/06 13:33:07 osadr # Initial revision # # # # makefile for pattern library for 'se' CFLAGS=-O PR=pr libpat.a: pat.o /bin/ar ruv libpat.a pat.o if test -r /usr/bin/ranlib; then /usr/bin/ranlib libpat.a; fi pat.o: pat.c install: libpat.a cp libpat.a /usr/lib print: $(PR) pat.c makefile | lpr -b 'pat lib' touch print2 print2: pat.c makefile $(PR) $? | lpr -b 'new pat lib' touch print2 clean: rm -f pat.o clobber: clean rm -f libpat.a print2 SHAR_EOF fi # end of overwriting check echo shar: extracting "'llib-lpat'" '(1270 characters)' if test -f 'llib-lpat' then echo shar: will not over-write existing file "'llib-lpat'" else cat << \SHAR_EOF > 'llib-lpat' /* llib-lpat --- lint library for pattern routines */ /*LINTLIBRARY*/ match (lin, pat) char lin[]; char pat[]; { return 0; } amatch(lin, from, pat, tagbeg, tagend) int from, tagbeg[], tagend[]; char lin[], pat[]; { return 0; } static omatch (lin, adplin, ppat) char lin[], **adplin, *ppat; { return 0; } static locate (c, ppat) char c, *ppat; { return 0; } static patsiz (ppat) char *ppat; { return 0; } makpat (arg, from, delim, pat) char arg[], delim, pat[]; int from; { return 0; } static getccl (arg, pasub, pat, pindex) char arg[], pat[]; int *pasub, *pindex; { return 0; } static stclos (pat, ppatsub, plastsub) char pat[]; int *ppatsub, *plastsub; { } maksub (arg, from, delim, sub) char arg[], delim, sub[]; int from; { return 0; } catsub (lin, from, to, sub, new, k, maxnew) char lin[], new[], sub[]; int from[], *k, maxnew, to[]; { } filset (delim, array, pasub, set, pindex, maxset) char array[], delim, set[]; int maxset, *pasub, *pindex; { } static dodash (valid, array, pasub, set, pindex, maxset) char array[], set[], valid[]; int maxset, *pasub, *pindex; { } addset (c, set, pindex, maxsiz) int maxsiz, *pindex; char c, set[]; { return 0; } char esc (array, pindex) char array[]; int *pindex; { return 0; } SHAR_EOF fi # end of overwriting check echo shar: done with directory "'pat'" cd .. # End of shell archive exit 0