Path: utzoo!attcan!uunet!mcvax!unido!fauern!faui44!immd3.informatik.uni-erlangen.de!rtregn From: rtregn@immd3.informatik.uni-erlangen.de (Robert Regn) Newsgroups: comp.os.minix Subject: Sources of new version of Stevie (vi clone) 5 of 5 Keywords: vi Message-ID: <771@faui10.informatik.uni-erlangen.de> Date: 14 Dec 88 16:27:42 GMT Organization: IMMD I, University of Erlangen, W-Erlangen Lines: 3022 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'search.c' <<'END_OF_FILE' Xstatic char RCSid[] = X"$Header: search.c,v 1.10 88/10/27 08:11:21 tony Exp $"; X X/* X * This file contains various searching-related routines. These fall into X * three groups: string searches (for /, ?, n, and N), character searches X * within a single line (for f, F, t, T, etc), and "other" kinds of searches X * like the '%' command, and 'word' searches. X * X * $Log: search.c,v $ X * Revision 1.10 88/10/27 08:11:21 tony X * Removed support for Megamax, and added code to print the search X * string on repeated searches. X * X * Revision 1.9 88/08/31 20:49:04 tony X * Made another fix in search.c related to repeated searches. X * X * Revision 1.8 88/08/25 15:12:06 tony X * Fixed a bug where the cursor didn't land on the right place after X * "beginning-of-word" searches if the word was preceded by the start X * of the line and a single character. X * X * Revision 1.7 88/08/23 12:52:08 tony X * Fixed a bug in ssearch() where repeated searches ('n' or 'N') resulted X * in dynamic memory being referenced after it was freed. X * X * Revision 1.6 88/06/26 14:48:51 tony X * Added a new routine, doglob(), to implement the ":g" command. X * X * Revision 1.5 88/05/02 21:34:34 tony X * Fixed a bug in my last modification that caused reverse repeated X * searches to save the wrong direction away for future use. X * X * Revision 1.4 88/04/29 14:46:06 tony X * Changed repsearch() and dosearch() to return a boolean indicating X * whether the search was successful. X * X * Revision 1.3 88/04/28 08:18:14 tony X * Added support for the "ignorecase" parameter. Also changed the search X * routines to use the modified regexec() interface. Changed dosub() to X * allow multiple substitutions per line. X * X * Revision 1.2 88/04/24 21:36:19 tony X * Added support for global substitution with the routine dosub(). The hard X * work is really done by regsub() in the regexp library. Only a single X * substitution per line is supported, for the moment. X * X * Revision 1.1 88/03/20 21:10:30 tony X * Initial revision X * X * X */ X X#include "stevie.h" X#include "regexp.h" /* Henry Spencer's (modified) reg. exp. routines */ X X/* X * String searches X * X * The actual searches are done using Henry Spencer's regular expression X * library. X */ X X#define BEGWORD "([^a-zA-Z0-9_]|^)" /* replaces "\<" in search strings */ X#define ENDWORD "([^a-zA-Z0-9_]|$)" /* likewise replaces "\>" */ X X#define BEGCHAR(c) (islower(c) || isupper(c) || isdigit(c) || ((c) == '_')) X Xbool_t begword; /* does the search include a 'begin word' match */ X X/* X * mapstring(s) - map special backslash sequences X */ Xstatic char * Xmapstring(s) Xregister char *s; X{ X static char ns[80]; X char *p; X X begword = FALSE; X X for (p = ns; *s ;s++) { X if (*s != '\\') { /* not an escape */ X *p++ = *s; X continue; X } X switch (*++s) { X case '/': X *p++ = '/'; X break; X X case '<': X strcpy(p, BEGWORD); X p += strlen(BEGWORD); X begword = TRUE; X break; X X case '>': X strcpy(p, ENDWORD); X p += strlen(ENDWORD); X break; X X default: X *p++ = '\\'; X *p++ = *s; X break; X } X } X *p++ = NUL; X X return ns; X} X Xstatic char *laststr = NULL; Xstatic int lastsdir; X Xstatic LPTR * Xssearch(dir,str) Xint dir; /* FORWARD or BACKWARD */ Xchar *str; X{ X LPTR *bcksearch(), *fwdsearch(); X LPTR *pos; X char *old_ls = laststr; X X reg_ic = P(P_IC); /* tell the regexp routines how to search */ X X laststr = strsave(str); X lastsdir = dir; X X if ( old_ls != NULL ) X free(old_ls); X X if ( dir == BACKWARD ) { X smsg("?%s", laststr); X pos = bcksearch(mapstring(laststr)); X } else { X smsg("/%s", laststr); X pos = fwdsearch(mapstring(laststr)); X } X X /* X * This is kind of a kludge, but its needed to make X * 'beginning of word' searches land on the right place. X */ X if (pos != NULL && begword) { X if (pos->index != 0 || !BEGCHAR(pos->linep->s[0])) X pos->index += 1; X } X return pos; X} X Xbool_t Xdosearch(dir,str) Xint dir; Xchar *str; X{ X LPTR *p; X X if (str == NULL) X str = laststr; X X if ((p = ssearch(dir,str)) == NULL) { X msg("Pattern not found"); X return FALSE; X } else { X LPTR savep; X X cursupdate(); X /* if we're backing up, we make sure the line we're on */ X /* is on the screen. */ X setpcmark(); X *Curschar = savep = *p; X cursupdate(); X X return TRUE; X } X} X X#define OTHERDIR(x) (((x) == FORWARD) ? BACKWARD : FORWARD) X Xbool_t Xrepsearch(flag) Xint flag; X{ X int dir = lastsdir; X bool_t found; X X if ( laststr == NULL ) { X beep(); X return FALSE; X } X X found = dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr); X X /* X * We have to save and restore 'lastsdir' because it gets munged X * by ssearch() and winds up saving the wrong direction from here X * if 'flag' is true. X */ X lastsdir = dir; X X return found; X} X X/* X * regerror - called by regexp routines when errors are detected. X */ Xvoid Xregerror(s) Xchar *s; X{ X emsg(s); X} X Xstatic LPTR * Xfwdsearch(str) Xregister char *str; X{ X static LPTR infile; X register LPTR *p; X regexp *prog; X X register char *s; X register int i; X X if ((prog = regcomp(str)) == NULL) { X emsg("Invalid search string"); X return NULL; X } X X p = Curschar; X i = Curschar->index + 1; X do { X s = p->linep->s + i; X X if (regexec(prog, s, i == 0)) { /* got a match */ X infile.linep = p->linep; X infile.index = (int) (prog->startp[0] - p->linep->s); X free(prog); X return (&infile); X } X i = 0; X } while ((p = nextline(p)) != NULL); X X /* X * If wrapscan isn't set, then don't scan from the beginning X * of the file. Just return failure here. X */ X if (!P(P_WS)) { X free(prog); X return NULL; X } X X /* search from the beginning of the file to Curschar */ X for (p = Filemem; p != NULL ;p = nextline(p)) { X s = p->linep->s; X X if (regexec(prog, s, TRUE)) { /* got a match */ X infile.linep = p->linep; X infile.index = (int) (prog->startp[0] - s); X free(prog); X return (&infile); X } X X if (p->linep == Curschar->linep) X break; X } X X free(prog); X return(NULL); X} X Xstatic LPTR * Xbcksearch(str) Xchar *str; X{ X static LPTR infile; X register LPTR *p; X regexp *prog; X register char *s; X register int i; X register char *match; X X /* make sure str isn't empty */ X if (str == NULL || *str == NUL) X return NULL; X X if ((prog = regcomp(str)) == NULL) { X emsg("Invalid search string"); X return NULL; X } X X p = Curschar; X dec(p); X X if (begword) /* so we don't get stuck on one match */ X dec(p); X X i = p->index; X X do { X s = p->linep->s; X X if (regexec(prog, s, TRUE)) { /* match somewhere on line */ X X /* X * Now, if there are multiple matches on this line, X * we have to get the last one. Or the last one X * before the cursor, if we're on that line. X */ X match = prog->startp[0]; X X while (regexec(prog, prog->endp[0], FALSE)) { X if ((i >= 0) && ((prog->startp[0] - s) > i)) X break; X match = prog->startp[0]; X } X X if ((i >= 0) && ((match - s) > i)) { X i = -1; X continue; X } X X infile.linep = p->linep; X infile.index = (int) (match - s); X free(prog); X return (&infile); X } X i = -1; X X } while ((p = prevline(p)) != NULL); X X /* X * If wrapscan isn't set, bag the search now X */ X if (!P(P_WS)) { X free(prog); X return NULL; X } X X /* search backward from the end of the file */ X p = prevline(Fileend); X do { X s = p->linep->s; X X if (regexec(prog, s, TRUE)) { /* match somewhere on line */ X X /* X * Now, if there are multiple matches on this line, X * we have to get the last one. X */ X match = prog->startp[0]; X X while (regexec(prog, prog->endp[0], FALSE)) X match = prog->startp[0]; X X infile.linep = p->linep; X infile.index = (int) (match - s); X free(prog); X return (&infile); X } X X if (p->linep == Curschar->linep) X break; X X } while ((p = prevline(p)) != NULL); X X free(prog); X return NULL; X} X X/* X * dosub(lp, up, cmd) X * X * Perform a substitution from line 'lp' to line 'up' using the X * command pointed to by 'cmd' which should be of the form: X * X * /pattern/substitution/g X * X * The trailing 'g' is optional and, if present, indicates that multiple X * substitutions should be performed on each line, if applicable. X * The usual escapes are supported as described in the regexp docs. X */ Xvoid Xdosub(lp, up, cmd) XLPTR *lp, *up; Xchar *cmd; X{ X LINE *cp; X char *pat, *sub; X regexp *prog; X int nsubs; X bool_t do_all; /* do multiple substitutions per line */ X X /* X * If no range was given, do the current line. If only one line X * was given, just do that one. X */ X if (lp->linep == NULL) X *up = *lp = *Curschar; X else { X if (up->linep == NULL) X *up = *lp; X } X X pat = ++cmd; /* skip the initial '/' */ X X while (*cmd) { X if (cmd[0] == '/' && cmd[-1] != '\\') { X *cmd++ = NUL; X break; X } X cmd++; X } X X if (*pat == NUL) { X emsg("NULL pattern specified"); X return; X } X X sub = cmd; X X do_all = FALSE; X X while (*cmd) { X if (cmd[0] == '/' && cmd[-1] != '\\') { X do_all = (cmd[1] == 'g'); X *cmd++ = NUL; X break; X } X cmd++; X } X X reg_ic = P(P_IC); /* set "ignore case" flag appropriately */ X X if ((prog = regcomp(pat)) == NULL) { X emsg("Invalid search string"); X return; X } X X nsubs = 0; X X for (cp = lp->linep; cp != NULL ;cp = cp->next) { X if (regexec(prog, cp->s, TRUE)) { /* a match on this line */ X char *ns, *sns, *p; X X /* X * Get some space for a temporary buffer X * to do the substitution into. X */ X sns = ns = alloc(2048); X *sns = NUL; X X p = cp->s; X X do { X for (ns = sns; *ns ;ns++) X ; X /* X * copy up to the part that matched X */ X while (p < prog->startp[0]) X *ns++ = *p++; X X regsub(prog, sub, ns); X X /* X * continue searching after the match X */ X p = prog->endp[0]; X X } while (regexec(prog, p, FALSE) && do_all); X X for (ns = sns; *ns ;ns++) X ; X X /* X * copy the rest of the line, that didn't match X */ X while (*p) X *ns++ = *p++; X X *ns = NUL; X X free(cp->s); /* free the original line */ X cp->s = strsave(sns); /* and save the modified str */ X cp->size = strlen(cp->s) + 1; X free(sns); /* free the temp buffer */ X nsubs++; X CHANGED; X } X if (cp == up->linep) X break; X } X X if (nsubs) { X updatescreen(); X if (nsubs >= P(P_RP)) X smsg("%d substitution%c", nsubs, (nsubs>1) ? 's' : ' '); X } else X msg("No match"); X X free(prog); X} X X/* X * doglob(cmd) X * X * Execute a global command of the form: X * X * g/pattern/X X * X * where 'x' is a command character, currently one of the following: X * X * d Delete all matching lines X * p Print all matching lines X * X * The command character (as well as the trailing slash) is optional, and X * is assumed to be 'p' if missing. X */ Xvoid Xdoglob(lp, up, cmd) XLPTR *lp, *up; Xchar *cmd; X{ X LINE *cp; X char *pat; X regexp *prog; X int ndone; X char cmdchar = NUL; /* what to do with matching lines */ X X /* X * If no range was given, do every line. If only one line X * was given, just do that one. X */ X if (lp->linep == NULL) { X *lp = *Filemem; X *up = *Fileend; X } else { X if (up->linep == NULL) X *up = *lp; X } X X pat = ++cmd; /* skip the initial '/' */ X X while (*cmd) { X if (cmd[0] == '/' && cmd[-1] != '\\') { X cmdchar = cmd[1]; X *cmd++ = NUL; X break; X } X cmd++; X } X if (cmdchar == NUL) X cmdchar = 'p'; X X reg_ic = P(P_IC); /* set "ignore case" flag appropriately */ X X if (cmdchar != 'd' && cmdchar != 'p') { X emsg("Invalid command character"); X return; X } X X if ((prog = regcomp(pat)) == NULL) { X emsg("Invalid search string"); X return; X } X X msg(""); X ndone = 0; X X for (cp = lp->linep; cp != NULL ;cp = cp->next) { X if (regexec(prog, cp->s, TRUE)) { /* a match on this line */ X switch (cmdchar) { X X case 'd': /* delete the line */ X if (Curschar->linep != cp) { X LPTR savep; X X savep = *Curschar; X Curschar->linep = cp; X Curschar->index = 0; X delline(1, FALSE); X *Curschar = savep; X } else X delline(1, FALSE); X break; X X case 'p': /* print the line */ X prt_line(cp->s); X outstr("\r\n"); X break; X } X ndone++; X } X if (cp == up->linep) X break; X } X X if (ndone) { X switch (cmdchar) { X X case 'd': X updatescreen(); X if (ndone >= P(P_RP)) X smsg("%d fewer line%c", ndone, X (ndone > 1) ? 's' : ' '); X break; X X case 'p': X wait_return(); X break; X } X } else X msg("No match"); X X free(prog); X} X X/* X * Character Searches X */ X Xstatic char lastc = NUL; /* last character searched for */ Xstatic int lastcdir; /* last direction of character search */ Xstatic int lastctype; /* last type of search ("find" or "to") */ X X/* X * searchc(c, dir, type) X * X * Search for character 'c', in direction 'dir'. If type is 0, move to X * the position of the character, otherwise move to just before the char. X */ Xbool_t Xsearchc(c, dir, type) Xchar c; Xint dir; Xint type; X{ X LPTR save; X X save = *Curschar; /* save position in case we fail */ X lastc = c; X lastcdir = dir; X lastctype = type; X X /* X * On 'to' searches, skip one to start with so we can repeat X * searches in the same direction and have it work right. X */ X if (type) X (dir == FORWARD) ? oneright() : oneleft(); X X while ( (dir == FORWARD) ? oneright() : oneleft() ) { X if (gchar(Curschar) == c) { X if (type) X (dir == FORWARD) ? oneleft() : oneright(); X return TRUE; X } X } X *Curschar = save; X return FALSE; X} X Xbool_t Xcrepsearch(flag) Xint flag; X{ X int dir = lastcdir; X int rval; X X if (lastc == NUL) X return FALSE; X X rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype); X X lastcdir = dir; /* restore dir., since it may have changed */ X X return rval; X} X X/* X * "Other" Searches X */ X X/* X * showmatch - move the cursor to the matching paren or brace X */ XLPTR * Xshowmatch() X{ X static LPTR pos; X int (*move)(), inc(), dec(); X char initc = gchar(Curschar); /* initial char */ X char findc; /* terminating char */ X char c; X int count = 0; X X pos = *Curschar; /* set starting point */ X X switch (initc) { X X case '(': X findc = ')'; X move = inc; X break; X case ')': X findc = '('; X move = dec; X break; X case '{': X findc = '}'; X move = inc; X break; X case '}': X findc = '{'; X move = dec; X break; X case '[': X findc = ']'; X move = inc; X break; X case ']': X findc = '['; X move = dec; X break; X default: X return (LPTR *) NULL; X } X X while ((*move)(&pos) != -1) { /* until end of file */ X c = gchar(&pos); X if (c == initc) X count++; X else if (c == findc) { X if (count == 0) X return &pos; X count--; X } X } X return (LPTR *) NULL; /* never found it */ X} X X/* X * findfunc(dir) - Find the next function in direction 'dir' X * X * Return TRUE if a function was found. X */ Xbool_t Xfindfunc(dir) Xint dir; X{ X LPTR *curr; X X curr = Curschar; X X do { X curr = (dir == FORWARD) ? nextline(curr) : prevline(curr); X X if (curr != NULL && curr->linep->s[0] == '{') { X setpcmark(); X *Curschar = *curr; X return TRUE; X } X } while (curr != NULL); X X return FALSE; X} X X/* X * The following routines do the word searches performed by the X * 'w', 'W', 'b', 'B', 'e', and 'E' commands. X */ X X/* X * To perform these searches, characters are placed into one of three X * classes, and transitions between classes determine word boundaries. X * X * The classes are: X * X * 0 - white space X * 1 - letters, digits, and underscore X * 2 - everything else X */ X Xstatic int stype; /* type of the word motion being performed */ X X#define C0(c) (((c) == ' ') || ((c) == '\t') || ((c) == NUL)) X#define C1(c) (isalpha(c) || isdigit(c) || ((c) == '_')) X X/* X * cls(c) - returns the class of character 'c' X * X * The 'type' of the current search modifies the classes of characters X * if a 'W', 'B', or 'E' motion is being done. In this case, chars. from X * class 2 are reported as class 1 since only white space boundaries are X * of interest. X */ Xstatic int Xcls(c) Xchar c; X{ X if (C0(c)) X return 0; X X if (C1(c)) X return 1; X X /* X * If stype is non-zero, report these as class 1. X */ X return (stype == 0) ? 2 : 1; X} X X X/* X * fwd_word(pos, type) - move forward one word X * X * Returns the resulting position, or NULL if EOF was reached. X */ XLPTR * Xfwd_word(p, type) XLPTR *p; Xint type; X{ X static LPTR pos; X int sclass = cls(gchar(p)); /* starting class */ X X pos = *p; X X stype = type; X X /* X * We always move at least one character. X */ X if (inc(&pos) == -1) X return NULL; X X if (sclass != 0) { X while (cls(gchar(&pos)) == sclass) { X if (inc(&pos) == -1) X return NULL; X } X /* X * If we went from 1 -> 2 or 2 -> 1, return here. X */ X if (cls(gchar(&pos)) != 0) X return &pos; X } X X /* We're in white space; go to next non-white */ X X while (cls(gchar(&pos)) == 0) { X /* X * We'll stop if we land on a blank line X */ X if (pos.index == 0 && pos.linep->s[0] == NUL) X break; X X if (inc(&pos) == -1) X return NULL; X } X X return &pos; X} X X/* X * bck_word(pos, type) - move backward one word X * X * Returns the resulting position, or NULL if EOF was reached. X */ XLPTR * Xbck_word(p, type) XLPTR *p; Xint type; X{ X static LPTR pos; X int sclass = cls(gchar(p)); /* starting class */ X X pos = *p; X X stype = type; X X if (dec(&pos) == -1) X return NULL; X X /* X * If we're in the middle of a word, we just have to X * back up to the start of it. X */ X if (cls(gchar(&pos)) == sclass && sclass != 0) { X /* X * Move backward to start of the current word X */ X while (cls(gchar(&pos)) == sclass) { X if (dec(&pos) == -1) X return NULL; X } X inc(&pos); /* overshot - forward one */ X return &pos; X } X X /* X * We were at the start of a word. Go back to the start X * of the prior word. X */ X X while (cls(gchar(&pos)) == 0) { /* skip any white space */ X /* X * We'll stop if we land on a blank line X */ X if (pos.index == 0 && pos.linep->s[0] == NUL) X return &pos; X X if (dec(&pos) == -1) X return NULL; X } X X sclass = cls(gchar(&pos)); X X /* X * Move backward to start of this word. X */ X while (cls(gchar(&pos)) == sclass) { X if (dec(&pos) == -1) X return NULL; X } X inc(&pos); /* overshot - forward one */ X X return &pos; X} X X/* X * end_word(pos, type) - move to the end of the word X * X * There is an apparent bug in the 'e' motion of the real vi. At least X * on the System V Release 3 version for the 80386. Unlike 'b' and 'w', X * the 'e' motion crosses blank lines. When the real vi crosses a blank X * line in an 'e' motion, the cursor is placed on the FIRST character X * of the next non-blank line. The 'E' command, however, works correctly. X * Since this appears to be a bug, I have not duplicated it here. X * X * Returns the resulting position, or NULL if EOF was reached. X */ XLPTR * Xend_word(p, type) XLPTR *p; Xint type; X{ X static LPTR pos; X int sclass = cls(gchar(p)); /* starting class */ X X pos = *p; X X stype = type; X X if (inc(&pos) == -1) X return NULL; X X /* X * If we're in the middle of a word, we just have to X * move to the end of it. X */ X if (cls(gchar(&pos)) == sclass && sclass != 0) { X /* X * Move forward to end of the current word X */ X while (cls(gchar(&pos)) == sclass) { X if (inc(&pos) == -1) X return NULL; X } X dec(&pos); /* overshot - forward one */ X return &pos; X } X X /* X * We were at the end of a word. Go to the end X * of the next word. X */ X X while (cls(gchar(&pos)) == 0) { /* skip any white space */ X if (inc(&pos) == -1) X return NULL; X } X X sclass = cls(gchar(&pos)); X X /* X * Move forward to end of this word. X */ X while (cls(gchar(&pos)) == sclass) { X if (inc(&pos) == -1) X return NULL; X } X dec(&pos); /* overshot - forward one */ X X return &pos; X} END_OF_FILE if test 19131 -ne `wc -c <'search.c'`; then echo shar: \"'search.c'\" unpacked with wrong size! fi # end of 'search.c' fi if test -f 'stevie.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'stevie.h'\" else echo shar: Extracting \"'stevie.h'\" \(5840 characters\) sed "s/^X//" >'stevie.h' <<'END_OF_FILE' X/* X * $Header: stevie.h,v 1.15 88/11/10 08:59:10 tony Exp $ X * X * Main header file included by all source files. X * X * $Log: stevie.h,v $ X * Revision 1.15 88/11/10 08:59:10 tony X * Added a declaration for the routine do_mlines() in main.c that checks X * for mode lines in a file. X * X * Revision 1.14 88/10/28 13:59:36 tony X * Added missing endif. X * X * Revision 1.13 88/10/27 08:23:47 tony X * Also added declarations for the new system- X * dependent routines flushbuf() and doshell(). X * X * Revision 1.12 88/10/06 10:13:08 tony X * Added a declaration for fixname(). X * X * Revision 1.11 88/08/30 20:37:10 tony X * After much prodding from Mark, I finally added support for replace mode. X * X * Revision 1.10 88/08/26 08:45:51 tony X * Misc. changes to make lint happy. X * X * Revision 1.9 88/07/09 20:38:47 tony X * Added declarations for new routines in undo.c supporting the 'U' command. X * X * Revision 1.8 88/06/26 14:52:33 tony X * Added missing declaration for prt_line() in screen.c X * X * Revision 1.7 88/06/26 14:49:21 tony X * Added a declaration for the new routine, doglog(), in search.c. X * X * Revision 1.6 88/06/20 14:52:13 tony X * Merged in changes for BSD Unix sent in by Michael Lichter. X * X * Revision 1.5 88/05/03 14:39:15 tony X * Minor change for DOS support. X * X * Revision 1.4 88/04/29 14:46:39 tony X * Changed the declarations of repsearch() and dosearch() from void to bool_t. X * X * Revision 1.3 88/04/24 21:35:56 tony X * Added a declaration for the new routine dosub() in search.c. X * X * Revision 1.2 88/03/21 16:46:57 tony X * Moved the environmental defines out to a file named "env.h" which is X * not maintained with RCS. X * X * Revision 1.1 88/03/20 21:05:17 tony X * Initial revision X * X * X */ X X#include "env.h" /* defines to establish the compile-time environment */ X X#include X#include X X#ifdef BSD X X#include X#define strchr index X X#else X X#ifdef MINIX X Xextern char *strchr(); Xextern char *strrchr(); Xextern char *strcpy(); Xextern char *strcat(); Xextern int strlen(); X X#else X#include X#endif X X#endif X X#include "ascii.h" X#include "keymap.h" X#include "param.h" X#include "term.h" X Xextern char *strchr(); X X#define NORMAL 0 X#define CMDLINE 1 X#define INSERT 2 X#define REPLACE 3 X#define FORWARD 4 X#define BACKWARD 5 X X/* X * Boolean type definition and constants X */ Xtypedef short bool_t; X X#ifndef TRUE X#define FALSE (0) X#define TRUE (1) X#endif X X/* X * SLOP is the amount of extra space we get for text on a line during X * editing operations that need more space. This keeps us from calling X * malloc every time we get a character during insert mode. No extra X * space is allocated when the file is initially read. X */ X#define SLOP 10 X X/* X * LINEINC is the gap we leave between the artificial line numbers. This X * helps to avoid renumbering all the lines every time a new line is X * inserted. X */ X#define LINEINC 10 X X#define CHANGED Changed=TRUE X#define UNCHANGED Changed=FALSE X Xstruct line { X struct line *prev, *next; /* previous and next lines */ X char *s; /* text for this line */ X int size; /* actual size of space at 's' */ X unsigned long num; /* line "number" */ X}; X X#define LINEOF(x) ((x)->linep->num) X Xstruct lptr { X struct line *linep; /* line we're referencing */ X int index; /* position within that line */ X}; X Xtypedef struct line LINE; Xtypedef struct lptr LPTR; X Xstruct charinfo { X char ch_size; X char *ch_str; X}; X Xextern struct charinfo chars[]; X Xextern int State; Xextern int Rows; Xextern int Columns; Xextern char *Realscreen; Xextern char *Nextscreen; Xextern char *Filename; Xextern LPTR *Filemem; Xextern LPTR *Filetop; Xextern LPTR *Fileend; Xextern LPTR *Topchar; Xextern LPTR *Botchar; Xextern LPTR *Curschar; Xextern LPTR *Insstart; Xextern int Cursrow, Curscol, Cursvcol, Curswant; Xextern bool_t set_want_col; Xextern int Prenum; Xextern bool_t Changed; Xextern char Redobuff[], Insbuff[]; Xextern char *Insptr; Xextern int Ninsert; X Xextern char *malloc(), *strcpy(); X X/* X * alloc.c X */ Xchar *alloc(), *strsave(); Xvoid screenalloc(), filealloc(), freeall(); XLINE *newline(); Xbool_t bufempty(), buf1line(), lineempty(), endofline(), canincrease(); X X/* X * cmdline.c X */ Xvoid readcmdline(), dotag(), msg(), emsg(), smsg(), gotocmd(), wait_return(); X X/* X * edit.c X */ Xvoid edit(), insertchar(), getout(), scrollup(), scrolldown(), beginline(); Xbool_t oneright(), oneleft(), oneup(), onedown(); X X/* X * fileio.c X */ Xvoid filemess(), renum(); Xbool_t readfile(), writeit(); X X/* X * help.c X */ Xbool_t help(); X X/* X * linefunc.c X */ XLPTR *nextline(), *prevline(), *coladvance(); X X/* X * main.c X */ Xvoid stuffin(), stuffnum(), addtobuff(); Xvoid do_mlines(); Xint vgetc(); Xbool_t anyinput(); X X/* X * mark.c X */ Xvoid setpcmark(), clrall(), clrmark(); Xbool_t setmark(); XLPTR *getmark(); X X/* X * misccmds.c X */ Xvoid opencmd(), fileinfo(), inschar(), delline(); Xbool_t delchar(); Xint cntllines(), plines(); XLPTR *gotoline(); X X/* X * normal.c X */ Xvoid normal(); Xchar *mkstr(); X X/* X * param.c X */ Xvoid doset(); X X/* X * ptrfunc.c X */ Xint inc(), dec(); Xint gchar(); Xvoid pchar(), pswap(); Xbool_t lt(), equal(), ltoreq(); X#if 0 X/* not currently used */ Xbool_t gtoreq(), gt(); X#endif X X/* X * screen.c X */ Xvoid updatescreen(), updateline(); Xvoid screenclear(), cursupdate(); Xvoid s_ins(), s_del(); Xvoid prt_line(); X X/* X * search.c X */ Xvoid dosub(), doglob(); Xbool_t searchc(), crepsearch(), findfunc(), dosearch(), repsearch(); XLPTR *showmatch(); XLPTR *fwd_word(), *bck_word(), *end_word(); X X/* X * undo.c X */ Xvoid u_save(), u_saveline(), u_clear(); Xvoid u_lcheck(), u_lundo(); Xvoid u_undo(); X X/* X * Machine-dependent routines. X */ Xint inchar(); Xvoid flushbuf(); Xvoid outchar(), outstr(), beep(); Xchar *fixname(); X#ifndef OS2 X#ifndef DOS Xvoid remove(), rename(); X#endif X#endif Xvoid windinit(), windexit(), windgoto(); Xvoid delay(); Xvoid doshell(); END_OF_FILE if test 5840 -ne `wc -c <'stevie.h'`; then echo shar: \"'stevie.h'\" unpacked with wrong size! fi # end of 'stevie.h' fi if test -f 'tags' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tags'\" else echo shar: Extracting \"'tags'\" \(7248 characters\) sed "s/^X//" >'tags' <<'END_OF_FILE' XBEGCHAR search.c /^#define BEGCHAR(c) (islower(c) || isupper(c) || is/ XBEGID ctags.c /^#define BEGID(c) (isalpha(c) || (c) == '_')$/ XC0 search.c /^#define C0(c) (((c) == ' ') || ((c) == '\\t') || ((/ XC1 search.c /^#define C1(c) (isalpha(c) || isdigit(c) || ((c) ==/ XDEFAULT1 normal.c /^#define DEFAULT1(x) (((x) == 0) ? 1 : (x))$/ XFAIL regexp.c /^#define FAIL(m) { regerror(m); return(NULL); }$/ XIDCHAR normal.c /^#define IDCHAR(c) (isalpha(c) || isdigit(c) || (c)/ XISMULT regexp.c /^#define ISMULT(c) ((c) == '*' || (c) == '+' || (c)/ XISSPECIAL edit.c /^#define ISSPECIAL(c) ((c) == NL || (c) == CR || (c/ XMIDID ctags.c /^#define MIDID(c) (isalpha(c) || isdigit(c) || (c) / XMctags ctags.c /^main(argc, argv)$/ XMmain main.c /^main(argc,argv)$/ XNEXT regexp.c /^#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&/ XOP regexp.c /^#define OP(p) (*(p))$/ XOPERAND regexp.c /^#define OPERAND(p) ((p) + 3)$/ XOTHERDIR search.c /^#define OTHERDIR(x) (((x) == FORWARD) ? BACKWARD :/ XUCHARAT regexp.c /^#define UCHARAT(p) ((int)*(unsigned char *)(p))$/ Xaddtobuff main.c /^addtobuff(s,c1,c2,c3,c4,c5,c6)$/ Xalloc alloc.c /^alloc(size)$/ Xanyinput main.c /^anyinput()$/ Xbadcmd cmdline.c /^badcmd()$/ Xbck_word search.c /^bck_word(p, type)$/ Xbcksearch search.c /^bcksearch(str)$/ Xbeep dos.c /^beep()$/ Xbeginline edit.c /^beginline(flag)$/ Xbuf1line alloc.c /^buf1line()$/ Xbufempty alloc.c /^bufempty()$/ Xcanincrease alloc.c /^canincrease(n)$/ Xchk_mline main.c /^chk_mline(s)$/ Xclrall mark.c /^clrall()$/ Xclrmark mark.c /^clrmark(line)$/ Xcls search.c /^cls(c)$/ Xcntllines misccmds.c /^cntllines(pbegin,pend)$/ Xcoladvance linefunc.c /^coladvance(p, col)$/ Xcopyline undo.c /^copyline(l)$/ Xcrepsearch search.c /^crepsearch(flag)$/ Xcstrchr regexp.c /^cstrchr(s, c)$/ Xcstrncmp regexp.c /^cstrncmp(s1, s2, n)$/ Xcursupdate screen.c /^cursupdate()$/ Xdec ptrfunc.c /^dec(lp)$/ Xdelay dos.c /^delay()$/ Xdelchar misccmds.c /^delchar(fixpos)$/ Xdelline misccmds.c /^delline(nlines, can_update)$/ Xdo_mlines main.c /^do_mlines()$/ Xdochange normal.c /^dochange(c1, c2, num)$/ Xdodelete normal.c /^dodelete(c1, c2, num)$/ Xdoecmd cmdline.c /^doecmd(arg, force)$/ Xdofile ctags.c /^dofile(fn, tp)$/ Xdofilter normal.c /^dofilter(c1, c2, num)$/ Xdoglob search.c /^doglob(lp, up, cmd)$/ Xdojoin normal.c /^dojoin()$/ Xdoput normal.c /^doput(dir)$/ Xdosearch search.c /^dosearch(dir,str)$/ Xdoset param.c /^doset(arg, inter)$/ Xdoshell dos.c /^doshell(cmd)$/ Xdoshift normal.c /^doshift(op, c1, c2, num)$/ Xdosub search.c /^dosub(lp, up, cmd)$/ Xdotag cmdline.c /^dotag(tag, force)$/ Xdoyank normal.c /^doyank()$/ Xedit edit.c /^edit()$/ Xemsg cmdline.c /^emsg(s)$/ Xend_word search.c /^end_word(p, type)$/ Xendofline alloc.c /^endofline(p)$/ Xequal ptrfunc.c /^equal(a, b)$/ Xfilealloc alloc.c /^filealloc()$/ Xfileinfo misccmds.c /^fileinfo()$/ Xfilemess fileio.c /^filemess(s)$/ Xfiletonext screen.c /^filetonext()$/ Xfindfunc search.c /^findfunc(dir)$/ Xfixname dos.c /^fixname(s)$/ Xflushbuf dos.c /^flushbuf()$/ Xfopenb dos.c /^fopenb(fname, mode)$/ Xfreeall alloc.c /^freeall()$/ Xfwd_word search.c /^fwd_word(p, type)$/ Xfwdsearch search.c /^fwdsearch(str)$/ Xgchar ptrfunc.c /^gchar(lp)$/ Xget_line cmdline.c /^get_line(cp)$/ Xget_range cmdline.c /^get_range(cp)$/ Xgetmark mark.c /^getmark(c)$/ Xgetout edit.c /^getout()$/ Xgetswitch dos.c /^getswitch()$/ Xgotocmd cmdline.c /^gotocmd(clr, firstc)$/ Xgotoline misccmds.c /^gotoline(n)$/ Xgt ptrfunc.c /^gt(a, b)$/ Xgtoreq ptrfunc.c /^gtoreq(a, b)$/ Xhelp help.c /^help()$/ Xinc ptrfunc.c /^inc(lp)$/ Xinchar dos.c /^inchar()$/ Xinschar misccmds.c /^inschar(c)$/ Xinsertchar edit.c /^insertchar(c)$/ Xinslines normal.c /^inslines(lp, dir, buf)$/ Xinsstr misccmds.c /^insstr(s)$/ Xlfiletonext screen.c /^lfiletonext()$/ Xlineempty alloc.c /^lineempty()$/ Xlnexttoscreen screen.c /^lnexttoscreen()$/ Xlongline help.c /^longline(p)$/ Xlt ptrfunc.c /^lt(a, b)$/ Xltoreq ptrfunc.c /^ltoreq(a, b)$/ Xmapstring search.c /^mapstring(s)$/ Xmkline screen.c /^mkline(n)$/ Xmkstr normal.c /^mkstr(c)$/ Xmkup regexp.c /^#define mkup(c) ((islower(c) && reg_ic) ? toupper/ Xmsg cmdline.c /^msg(s)$/ Xnewline alloc.c /^newline(nchars)$/ Xnextfile ctags.c /^nextfile() \/* returns ptr to next file to be searc/ Xnextline linefunc.c /^nextline(curr)$/ Xnexttoscreen screen.c /^nexttoscreen()$/ Xnormal normal.c /^normal(c)$/ Xonedown edit.c /^onedown(n)$/ Xoneleft edit.c /^oneleft()$/ Xoneright edit.c /^oneright()$/ Xoneup edit.c /^oneup(n)$/ Xopenbwd misccmds.c /^openbwd(can_ai)$/ Xopencmd misccmds.c /^opencmd(dir, can_ai)$/ Xopenfwd misccmds.c /^openfwd(can_ai)$/ Xoutchar dos.c /^outchar(c)$/ Xoutone dos.c /^#define outone(c) outbuf[bpos++] = c; if (bpos >= / Xoutstr dos.c /^outstr(s)$/ Xpchar ptrfunc.c /^pchar(lp, c)$/ Xplines misccmds.c /^plines(p)$/ Xprevline linefunc.c /^prevline(curr)$/ Xprt_line screen.c /^prt_line(s)$/ Xpswap ptrfunc.c /^pswap(a, b)$/ Xreadcmdline cmdline.c /^readcmdline(firstc, cmdline)$/ Xreadfile fileio.c /^readfile(fname,fromp,nochangename)$/ Xreg regexp.c /^reg(paren, flagp)$/ Xregatom regexp.c /^regatom(flagp)$/ Xregbranch regexp.c /^regbranch(flagp)$/ Xregc regexp.c /^regc(b)$/ Xregcomp regexp.c /^regcomp(exp)$/ Xregdump regexp.c /^regdump(r)$/ Xregerror search.c /^regerror(s)$/ Xregexec regexp.c /^regexec(prog, string, at_bol)$/ Xreginsert regexp.c /^reginsert(op, opnd)$/ Xregmatch regexp.c /^regmatch(prog)$/ Xregnext regexp.c /^regnext(p)$/ Xregnode regexp.c /^regnode(op)$/ Xregoptail regexp.c /^regoptail(p, val)$/ Xregpiece regexp.c /^regpiece(flagp)$/ Xregprop regexp.c /^regprop(op)$/ Xregrepeat regexp.c /^regrepeat(p)$/ Xregsub regsub.c /^regsub(prog, source, dest)$/ Xregtail regexp.c /^regtail(p, val)$/ Xregtry regexp.c /^regtry(prog, string)$/ Xremove minix.c /^remove(file)$/ Xrename minix.c /^rename(of, nf)$/ Xrenum fileio.c /^renum()$/ Xrepsearch search.c /^repsearch(flag)$/ Xreset_tty minix.c /^reset_tty()$/ Xs_del screen.c /^s_del(row, nlines)$/ Xs_ins screen.c /^s_ins(row, nlines)$/ Xscreenalloc alloc.c /^screenalloc()$/ Xscreenclear screen.c /^screenclear()$/ Xscrolldown edit.c /^scrolldown(nlines)$/ Xscrollup edit.c /^scrollup(nlines)$/ Xsearchc search.c /^searchc(c, dir, type)$/ Xset_tty minix.c /^set_tty()$/ Xsetmark mark.c /^setmark(c)$/ Xsetpcmark mark.c /^setpcmark()$/ Xsetswitch dos.c /^setswitch(c)$/ Xshowmatch search.c /^showmatch()$/ Xshowparms param.c /^showparms(all)$/ Xsleep dos.c /^sleep(n)$/ Xsmsg cmdline.c /^smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)$/ Xssearch search.c /^ssearch(dir,str)$/ Xstartinsert normal.c /^startinsert(initstr, startln)$/ Xstrchr minix.c /^strchr(s, c)$/ Xstrcspn regexp.c /^strcspn(s1, s2)$/ Xstrsave alloc.c /^strsave(string)$/ Xstuffin main.c /^stuffin(s)$/ Xstuffnum main.c /^stuffnum(n)$/ Xt_init term.c /^t_init()$/ Xtabinout normal.c /^tabinout(inout, num)$/ Xu_clear undo.c /^u_clear()$/ Xu_lcheck undo.c /^u_lcheck()$/ Xu_lfree undo.c /^u_lfree()$/ Xu_lsave undo.c /^u_lsave(l, u)$/ Xu_lundo undo.c /^u_lundo()$/ Xu_save undo.c /^u_save(l, u)$/ Xu_saveline undo.c /^u_saveline()$/ Xu_undo undo.c /^u_undo()$/ Xupdateline screen.c /^updateline()$/ Xupdatescreen screen.c /^updatescreen()$/ Xusage main.c /^usage()$/ Xvgetc main.c /^vgetc()$/ Xvpeekc main.c /^vpeekc()$/ Xwait_return cmdline.c /^wait_return()$/ Xwindexit dos.c /^windexit(r)$/ Xwindgoto dos.c /^windgoto(r, c)$/ Xwindinit dos.c /^windinit()$/ Xwriteit fileio.c /^writeit(fname, start, end)$/ END_OF_FILE if test 7248 -ne `wc -c <'tags'`; then echo shar: \"'tags'\" unpacked with wrong size! fi # end of 'tags' fi if test -f 'term.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'term.c'\" else echo shar: Extracting \"'term.c'\" \(1878 characters\) sed "s/^X//" >'term.c' <<'END_OF_FILE' Xstatic char RCSid[] = X"$Header: term.c,v 1.2 88/10/31 13:10:32 tony Exp $"; X X/* X * Termcap initialization (optional). X * X * $Log: term.c,v $ X * Revision 1.2 88/10/31 13:10:32 tony X * Removed text after "#endif" that some compilers complain about. X * X * Revision 1.1 88/10/29 14:05:27 tony X * Initial revision X * X */ X X#include X#include "stevie.h" X X#ifdef TERMCAP X Xstatic char buf[1024]; /* termcap entry read here */ Xstatic char cap[256]; /* capability strings go in here */ X Xchar *T_EL; /* erase the entire current line */ Xchar *T_IL; /* insert one line */ Xchar *T_DL; /* delete one line */ Xchar *T_SC; /* save the cursor position */ Xchar *T_ED; /* erase display (may optionally home cursor) */ Xchar *T_RC; /* restore the cursor position */ Xchar *T_CI; /* invisible cursor (very optional) */ Xchar *T_CV; /* visible cursor (very optional) */ X Xchar *T_CM; /* cursor motion string */ X Xextern int tgetent(), tgetnum(); Xextern char *tgetstr(); Xextern char *getenv(); X Xint Xt_init() X{ X char *term; X int n; X char *cp = cap; X X if ((term = getenv("TERM")) == NULL) X return 0; X X if (tgetent(buf, term) != 1) X return 0; X X if ((n = tgetnum("li")) == -1) X return 0; X else X P(P_LI) = Rows = n; X X if ((n = tgetnum("co")) == -1) X return 0; X else X Columns = n; X X /* X * Get mandatory capability strings. X */ X if ((T_CM = tgetstr("cm", &cp)) == NULL) X return 0; X X if ((T_EL = tgetstr("ce", &cp)) == NULL) X return 0; X X if ((T_IL = tgetstr("al", &cp)) == NULL) X return 0; X X if ((T_DL = tgetstr("dl", &cp)) == NULL) X return 0; X X if ((T_ED = tgetstr("cl", &cp)) == NULL) X return 0; X X if ((T_SC = tgetstr("sc", &cp)) == NULL) X return 0; X X if ((T_RC = tgetstr("rc", &cp)) == NULL) X return 0; X X /* X * Optional capabilities. X */ X if ((T_CI = tgetstr("vi", &cp)) == NULL) X T_CI = ""; X X if ((T_CV = tgetstr("ve", &cp)) == NULL) X T_CV = ""; X X return 1; X} X X#endif END_OF_FILE if test 1878 -ne `wc -c <'term.c'`; then echo shar: \"'term.c'\" unpacked with wrong size! fi # end of 'term.c' fi if test -f 'term.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'term.h'\" else echo shar: Extracting \"'term.h'\" \(5757 characters\) sed "s/^X//" >'term.h' <<'END_OF_FILE' X/* X * $Header: term.h,v 1.5 88/10/31 13:10:56 tony Exp $ X * X * System-dependent escape sequence definitions. X * X * $Log: term.h,v $ X * Revision 1.5 88/10/31 13:10:56 tony X * Removed text after "#endif" that some compilers complain about. X * X * Revision 1.4 88/10/29 14:06:41 tony X * Added support for termcap, if TERMCAP is defined. If not defined, the X * escape sequences are still hard-coded here. X * X * Revision 1.3 88/10/27 07:54:01 tony X * Added escape sequences for Minix-ST. X * X * Revision 1.2 88/05/03 14:39:27 tony X * Added escape sequences for DOS. X * X * Revision 1.1 88/03/21 12:04:50 tony X * Initial revision X * X * X */ X X#ifdef TERMCAP X Xextern char *T_EL; /* erase the entire current line */ Xextern char *T_IL; /* insert one line */ Xextern char *T_DL; /* delete one line */ Xextern char *T_SC; /* save the cursor position */ Xextern char *T_ED; /* erase display (may optionally home cursor) */ Xextern char *T_RC; /* restore the cursor position */ Xextern char *T_CI; /* invisible cursor (very optional) */ Xextern char *T_CV; /* visible cursor (very optional) */ X Xextern char *T_CM; /* cursor motion string */ X X#else X X/* X * This file contains the machine dependent escape sequences that X * the editor needs to perform various operations. Some of the sequences X * here are optional. Anything not available should be indicated by X * a null string. In the case of insert/delete line sequences, the X * editor checks the capability and works around the deficiency, if X * necessary. X * X * Currently, insert/delete line sequences are used for screen scrolling. X * There are lots of terminals that have 'index' and 'reverse index' X * capabilities, but no line insert/delete. For this reason, the editor X * routines s_ins() and s_del() should be modified to use 'index' X * sequences when the line to be inserted or deleted line zero. X */ X X/* X * The macro names here correspond (more or less) to the actual ANSI names X */ X X#ifdef MINIX X X#define T_EL "\033[K" /* erase the entire current line */ X#define T_IL "\033[L" /* insert one line */ X#define T_DL "\033[M" /* delete one line */ X#define T_SC "\0337" /* save the cursor position */ X#define T_ED "\033[H\033[J" /* erase display (may optionally home cursor) */ X#define T_RC "\0338" /* restore the cursor position */ X#define T_CI "" /* invisible cursor (very optional) */ X#define T_CV "" /* visible cursor (very optional) */ X X#endif X X#ifdef ATARI X#ifdef MINIX X X#define T_EL "\033[2K" /* erase the entire current line */ X#define T_IL "\033[L" /* insert one line */ X#define T_DL "\033[M" /* delete one line */ X#define T_SC "\0337" /* save the cursor position */ X#define T_ED "\033[2J" /* erase display (may optionally home cursor) */ X#define T_RC "\0338" /* restore the cursor position */ X#define T_CI "" /* invisible cursor (very optional) */ X#define T_CV "" /* visible cursor (very optional) */ X X#else X X X#define T_EL "\033l" /* erase the entire current line */ X#define T_IL "\033L" /* insert one line */ X#define T_DL "\033M" /* delete one line */ X#define T_SC "\033j" /* save the cursor position */ X#define T_ED "\033E" /* erase display (may optionally home cursor) */ X#define T_RC "\033k" /* restore the cursor position */ X#define T_CI "\033f" /* invisible cursor (very optional) */ X#define T_CV "\033e" /* visible cursor (very optional) */ X X#endif X#endif X X#ifdef UNIX X/* X * The UNIX sequences are hard-wired for ansi-like terminals. I should X * really use termcap/terminfo, but the UNIX port was done for profiling, X * not for actual use, so it wasn't worth the effort. X */ X#define T_EL "\033[2K" /* erase the entire current line */ X#define T_IL "\033[L" /* insert one line */ X#define T_DL "\033[M" /* delete one line */ X#define T_ED "\033[2J" /* erase display (may optionally home cursor) */ X#define T_SC "\0337" /* save the cursor position */ X#define T_RC "\0338" /* restore the cursor position */ X#define T_CI "" /* invisible cursor (very optional) */ X#define T_CV "" /* visible cursor (very optional) */ X#endif X X#ifdef OS2 X/* X * The OS/2 ansi console driver is pretty deficient. No insert or delete line X * sequences. The erase line sequence only erases from the cursor to the end X * of the line. For our purposes that works out okay, since the only time X * T_EL is used is when the cursor is in column 0. X * X * The insert/delete line sequences marked here are actually implemented in X * the file os2.c using direct OS/2 system calls. This makes the capability X * available for the rest of the editor via appropriate escape sequences X * passed to outstr(). X */ X#define T_EL "\033[K" /* erase the entire current line */ X#define T_IL "\033[L" /* insert one line - fake (see os2.c) */ X#define T_DL "\033[M" /* delete one line - fake (see os2.c) */ X#define T_ED "\033[2J" /* erase display (may optionally home cursor) */ X#define T_SC "\033[s" /* save the cursor position */ X#define T_RC "\033[u" /* restore the cursor position */ X#define T_CI "" /* invisible cursor (very optional) */ X#define T_CV "" /* visible cursor (very optional) */ X#endif X X#ifdef DOS X/* X * DOS sequences X * X * Some of the following sequences require the use of the "nansi.sys" X * console driver. The standard "ansi.sys" driver doesn't support X * sequences for insert/delete line. X */ X#define T_EL "\033[K" /* erase the entire current line */ X#define T_IL "\033[L" /* insert line (requires nansi.sys driver) */ X#define T_DL "\033[M" /* delete line (requires nansi.sys driver) */ X#define T_ED "\033[2J" /* erase display (may optionally home cursor) */ X#define T_SC "\033[s" /* save the cursor position */ X#define T_RC "\033[u" /* restore the cursor position */ X#define T_CI "" /* invisible cursor (very optional) */ X#define T_CV "" /* visible cursor (very optional) */ X#endif X X#endif END_OF_FILE if test 5757 -ne `wc -c <'term.h'`; then echo shar: \"'term.h'\" unpacked with wrong size! fi # end of 'term.h' fi if test -f 'undo.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'undo.c'\" else echo shar: Extracting \"'undo.c'\" \(7253 characters\) sed "s/^X//" >'undo.c' <<'END_OF_FILE' Xstatic char RCSid[] = X"$Header: undo.c,v 1.4 88/08/26 08:45:56 tony Exp $"; X X/* X * Undo facility X * X * The routines in this file comprise a general undo facility for use X * throughout the rest of the editor. The routine u_save() is called X * before each edit operation to save the current contents of the lines X * to be editted. Later, u_undo() can be called to return those lines X * to their original state. The routine u_clear() should be called X * whenever a new file is going to be editted to clear the undo buffer. X * X * $Log: undo.c,v $ X * Revision 1.4 88/08/26 08:45:56 tony X * Misc. changes to make lint happy. X * X * Revision 1.3 88/08/17 07:38:14 tony X * Made u_save() more robust by checking for null parameters. It's up to X * the caller to notice the problem before it causes trouble elsewhere. X * X * Revision 1.2 88/07/09 20:39:11 tony X * Added routines to implement the 'U' command. X * X * Revision 1.1 88/03/20 21:10:53 tony X * Initial revision X * X */ X X#include "stevie.h" X X/* X * The next two variables mark the boundaries of the changed section X * of the file. Lines BETWEEN the lower and upper bounds are changed X * and originally contained the lines pointed to by u_lines. To undo X * the last change, insert the lines in u_lines between the lower and X * upper bounds. X */ Xstatic LINE *u_lbound = NULL; /* line just prior to first changed line */ Xstatic LINE *u_ubound = NULL; /* line just after the last changed line */ X Xstatic LINE *u_lline = NULL; /* bounds of the saved lines */ Xstatic LINE *u_uline = NULL; X Xstatic int u_col; Xstatic bool_t u_valid = FALSE; /* is the undo buffer valid */ X X/* X * Local forward declarations X */ Xstatic LINE *copyline(); Xstatic void u_lsave(); Xstatic void u_lfree(); X X/* X * u_save(l, u) - save the current contents of part of the file X * X * The lines between 'l' and 'u' are about to be changed. This routine X * saves their current contents into the undo buffer. The range l to u X * is not inclusive because when we do an open, for example, there aren't X * any lines in between. If no lines are to be saved, then l->next == u. X */ Xvoid Xu_save(l, u) XLINE *l, *u; X{ X LINE *nl; /* copy of the current line */ X X /* X * If l or u is null, there's an error. We don't return an X * indication to the caller. They should find the problem X * while trying to perform whatever edit is being requested X * (e.g. a join on the last line). X */ X if (l == NULL || u == NULL) X return; X X u_clear(); /* clear the buffer, first */ X X u_lsave(l, u); /* save to the "line undo" buffer, if needed */ X X u_lbound = l; X u_ubound = u; X X if (l->next != u) { /* there are lines in the middle */ X l = l->next; X u = u->prev; X X u_lline = nl = copyline(l); /* copy the first line */ X while (l != u) { X nl->next = copyline(l->next); X nl->next->prev = nl; X l = l->next; X nl = nl->next; X } X u_uline = nl; X } else X u_lline = u_uline = NULL; X X u_valid = TRUE; X u_col = Cursvcol; X} X X/* X * u_saveline() - save the current line in the undo buffer X */ Xvoid Xu_saveline() X{ X u_save(Curschar->linep->prev, Curschar->linep->next); X} X X/* X * u_undo() - effect an 'undo' operation X * X * The last edit is undone by restoring the modified section of the file X * to its original state. The lines we're going to trash are copied to X * the undo buffer so that even an 'undo' can be undone. Rings the bell X * if the undo buffer is empty. X */ Xvoid Xu_undo() X{ X LINE *tl, *tu; X X if (!u_valid) { X beep(); X return; X } X X /* X * Get the first line of the thing we're undoing on the screen. X */ X Curschar->linep = u_lbound->next; X Curschar->index = 0; /* for now */ X if (Curschar->linep == Fileend->linep) X Curschar->linep = Curschar->linep->prev; X cursupdate(); X X /* X * Save pointers to what's in the file now. X */ X if (u_lbound->next != u_ubound) { /* there are lines to get */ X tl = u_lbound->next; X tu = u_ubound->prev; X tl->prev = NULL; X tu->next = NULL; X } else X tl = tu = NULL; /* no lines between bounds */ X X /* X * Link the undo buffer into the right place in the file. X */ X if (u_lline != NULL) { /* there are lines in the undo buf */ X X /* X * If the top line of the screen is being undone, we need to X * fix up Topchar to point to the new line that will be there. X */ X if (u_lbound->next == Topchar->linep) X Topchar->linep = u_lline; X X u_lbound->next = u_lline; X u_lline->prev = u_lbound; X u_ubound->prev = u_uline; X u_uline->next = u_ubound; X } else { /* no lines... link the bounds */ X if (u_lbound->next == Topchar->linep) X Topchar->linep = u_ubound; X if (u_lbound == Filetop->linep) X Topchar->linep = u_ubound; X X u_lbound->next = u_ubound; X u_ubound->prev = u_lbound; X } X X /* X * If we swapped the top line, patch up Filemem appropriately. X */ X if (u_lbound == Filetop->linep) X Filemem->linep = Filetop->linep->next; X X /* X * Now save the old stuff in the undo buffer. X */ X u_lline = tl; X u_uline = tu; X X renum(); /* have to renumber everything */ X X /* X * Put the cursor on the first line of the 'undo' region. X */ X Curschar->linep = u_lbound->next; X Curschar->index = 0; X if (Curschar->linep == Fileend->linep) X Curschar->linep = Curschar->linep->prev; X *Curschar = *coladvance(Curschar, u_col); X cursupdate(); X updatescreen(); /* now show the change */ X X u_lfree(); /* clear the "line undo" buffer */ X} X X/* X * u_clear() - clear the undo buffer X * X * This routine is called to clear the undo buffer at times when the X * pointers are about to become invalid, such as when a new file is X * about to be editted. X */ Xvoid Xu_clear() X{ X LINE *l, *nextl; X X if (!u_valid) /* nothing to do */ X return; X X for (l = u_lline; l != NULL ;l = nextl) { X nextl = l->next; X free(l->s); X free(l); X } X X u_lbound = u_ubound = u_lline = u_uline = NULL; X u_valid = FALSE; X} X X/* X * The following functions and data implement the "line undo" feature X * performed by the 'U' command. X */ X Xstatic LINE *u_line; /* pointer to the line we last saved */ Xstatic LINE *u_lcopy = NULL; /* local copy of the original line */ X X/* X * u_lfree() - free the line save buffer X */ Xstatic void Xu_lfree() X{ X if (u_lcopy != NULL) { X free(u_lcopy->s); X free(u_lcopy); X u_lcopy = NULL; X } X u_line = NULL; X} X X/* X * u_lsave() - save the current line if necessary X */ Xstatic void Xu_lsave(l, u) XLINE *l, *u; X{ X X if (l->next != u->prev) { /* not changing exactly one line */ X u_lfree(); X return; X } X X if (l->next == u_line) /* more edits on the same line */ X return; X X u_lfree(); X u_line = l->next; X u_lcopy = copyline(l->next); X} X X/* X * u_lundo() - undo the current line (the 'U' command) X */ Xvoid Xu_lundo() X{ X if (u_lcopy != NULL) { X free(Curschar->linep->s); X Curschar->linep->s = u_lcopy->s; X Curschar->linep->size = u_lcopy->size; X free(u_lcopy); X } else X beep(); X Curschar->index = 0; X X cursupdate(); X updatescreen(); /* now show the change */ X X u_lcopy = NULL; /* can't undo this kind of undo */ X u_line = NULL; X} X X/* X * u_lcheck() - clear the "line undo" buffer if we've moved to a new line X */ Xvoid Xu_lcheck() X{ X if (Curschar->linep != u_line) X u_lfree(); X} X X/* X * copyline(l) - copy the given line, and return a pointer to the copy X */ Xstatic LINE * Xcopyline(l) XLINE *l; X{ X LINE *nl; /* the new line */ X X nl = newline(strlen(l->s) + 1); X strcpy(nl->s, l->s); X X return nl; X} END_OF_FILE if test 7253 -ne `wc -c <'undo.c'`; then echo shar: \"'undo.c'\" unpacked with wrong size! fi # end of 'undo.c' fi if test -f 'unix.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'unix.c'\" else echo shar: Extracting \"'unix.c'\" \(3697 characters\) sed "s/^X//" >'unix.c' <<'END_OF_FILE' Xstatic char RCSid[] = X"$Header: unix.c,v 1.5 88/10/31 13:11:03 tony Exp $"; X X/* X * System-dependent routines for UNIX System V or Berkeley. X * X * $Log: unix.c,v $ X * Revision 1.5 88/10/31 13:11:03 tony X * Added code (optional) to support the use of termcap. X * X * Revision 1.4 88/10/27 08:16:52 tony X * Added doshell() to support ":sh" and ":!". X * X * Revision 1.3 88/10/06 10:14:36 tony X * Added fixname() routine, which does nothing under UNIX. X * X * Revision 1.2 88/06/20 14:51:36 tony X * Merged in changes for BSD Unix sent in by Michael Lichter. X * X * Revision 1.1 88/03/20 21:11:02 tony X * Initial revision X * X * X */ X X#include "stevie.h" X#ifdef BSD X#include X#else X#include X#endif X X/* X * inchar() - get a character from the keyboard X */ Xint Xinchar() X{ X char c; X X flushbuf(); /* flush any pending output */ X X do { X while (read(0, &c, 1) != 1) X ; X } while (c == NUL); X X return c; X} X X#define BSIZE 2048 Xstatic char outbuf[BSIZE]; Xstatic int bpos = 0; X Xvoid Xflushbuf() X{ X if (bpos != 0) X write(1, outbuf, bpos); X bpos = 0; X} X X/* X * Macro to output a character. Used within this file for speed. X */ X#define outone(c) outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf() X X/* X * Function version for use outside this file. X */ Xvoid Xoutchar(c) Xregister char c; X{ X outbuf[bpos++] = c; X if (bpos >= BSIZE) X flushbuf(); X} X Xvoid Xoutstr(s) Xregister char *s; X{ X while (*s) { X outone(*s++); X } X} X Xvoid Xbeep() X{ X outone('\007'); X} X X/* X * remove(file) - remove a file X */ Xvoid Xremove(file) Xchar *file; X{ X unlink(file); X} X X/* X * rename(of, nf) - rename existing file 'of' to 'nf' X */ Xvoid Xrename(of, nf) Xchar *of, *nf; X{ X unlink(nf); X link(of, nf); X unlink(of); X} X Xvoid Xdelay() X{ X /* not implemented */ X} X X#ifdef BSD Xstatic struct sgttyb ostate; X#else Xstatic struct termio ostate; X#endif X X/* X * Go into cbreak mode X */ Xvoid Xset_tty() X{ X#ifdef BSD X struct sgttyb nstate; X X ioctl(0, TIOCGETP, &ostate); X nstate = ostate; X nstate.sg_flags &= ~(XTABS|CRMOD|ECHO); X nstate.sg_flags |= CBREAK; X ioctl(0, TIOCSETN, &nstate); X#else X struct termio nstate; X X ioctl(0, TCGETA, &ostate); X nstate = ostate; X nstate.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL); X nstate.c_cc[VMIN] = 1; X nstate.c_cc[VTIME] = 0; X ioctl(0, TCSETAW, &nstate); X#endif X} X X/* X * Restore original terminal modes X */ Xvoid Xreset_tty() X{ X#ifdef BSD X ioctl(0, TIOCSETP, &ostate); X#else X ioctl(0, TCSETAW, &ostate); X#endif X} X Xvoid Xwindinit() X{ X#ifdef TERMCAP X if (t_init() != 1) { X fprintf(stderr, "unknown terminal type\n"); X exit(1); X } X#else X Columns = 80; X P(P_LI) = Rows = 24; X#endif X X set_tty(); X} X Xvoid Xwindexit(r) Xint r; X{ X reset_tty(); X exit(r); X} X X#define outone(c) outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf() X Xvoid Xwindgoto(r, c) Xregister int r, c; X{ X#ifdef TERMCAP X char *tgoto(); X#else X r += 1; X c += 1; X#endif X X /* X * Check for overflow once, to save time. X */ X if (bpos + 8 >= BSIZE) X flushbuf(); X X#ifdef TERMCAP X outstr(tgoto(T_CM, c, r)); X#else X outbuf[bpos++] = '\033'; X outbuf[bpos++] = '['; X if (r >= 10) X outbuf[bpos++] = r/10 + '0'; X outbuf[bpos++] = r%10 + '0'; X outbuf[bpos++] = ';'; X if (c >= 10) X outbuf[bpos++] = c/10 + '0'; X outbuf[bpos++] = c%10 + '0'; X outbuf[bpos++] = 'H'; X#endif X} X XFILE * Xfopenb(fname, mode) Xchar *fname; Xchar *mode; X{ X return fopen(fname, mode); X} X Xchar * Xfixname(s) Xchar *s; X{ X return s; X} X X/* X * doshell() - run a command or an interactive shell X */ Xvoid Xdoshell(cmd) Xchar *cmd; X{ X char *cp, *getenv(); X char cline[128]; X X outstr("\r\n"); X flushbuf(); X X if (cmd == NULL) { X if ((cmd = getenv("SHELL")) == NULL) X cmd = "/bin/sh"; X sprintf(cline, "%s -i", cmd); X cmd = cline; X } X X reset_tty(); X system(cmd); X set_tty(); X X wait_return(); X} END_OF_FILE if test 3697 -ne `wc -c <'unix.c'`; then echo shar: \"'unix.c'\" unpacked with wrong size! fi # end of 'unix.c' fi if test -f 'version.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'version.c'\" else echo shar: Extracting \"'version.c'\" \(7218 characters\) sed "s/^X//" >'version.c' <<'END_OF_FILE' Xstatic char RCSid[] = X"$Header: version.c,v 3.45 88/11/10 09:00:06 tony Exp $"; X X/* X * Contains the declaration of the global version number variable. X * X * changes by Robert Regn: X * Tue Nov 29 12:12:10 MET 1988 X * Better handling of Read/only files X * preserving link structure and modes X * recognizes % in cmdline - better algorithm for # also X * edit an empty file is now possible X * restore tty if the file to edit is too big X * if writeit in :w fails, :q is not further possible X * X * $Log: version.c,v $ X * Revision 3.45 88/11/10 09:00:06 tony X * Added support for mode lines. Strings like "vi:stuff:" or "ex:stuff:" X * occurring in the first or last 5 lines of a file cause the editor to X * pretend that "stuff" was types as a colon command. This examination X * is done only if the parameter "modelines" (or "ml") is set. This is X * not enabled, by default, because of the security implications involved. X * X * Revision 3.44 88/11/01 21:34:11 tony X * Fixed a couple of minor points for Minix, and improved the speed of X * the 'put' command dramatically. X * X * Revision 3.43 88/10/31 13:11:33 tony X * Added optional support for termcap. Initialization is done in term.c X * and also affects the system-dependent files. To enable termcap in those X * environments that support it, define the symbol "TERMCAP" in env.h X * X * Revision 3.42 88/10/27 18:30:19 tony X * Removed support for Megamax. Added '%' as an alias for '1,$'. Made the X * 'r' command more robust. Now prints the string on repeated searches. X * The ':=" command now works. Some pointer operations are now safer. X * The ":!" and ":sh" now work correctly. Re-organized the help screens X * a little. X * X * Revision 3.41 88/10/06 10:15:00 tony X * Fixed a bug involving ^Y that occurs when the cursor is on the last X * line, and the line above the screen is long. Also hacked up fileio.c X * to pass pathnames off to fixname() for system-dependent processing. X * Used under DOS & OS/2 to trim parts of the name appropriately. X * X * Revision 3.40 88/09/16 08:37:36 tony X * No longer beeps when repeated searches fail. X * X * Revision 3.39 88/09/06 06:51:07 tony X * Fixed a bug with shifts that was introduced when replace mode was added. X * X * Revision 3.38 88/08/31 20:48:28 tony X * Made another fix in search.c related to repeated searches. X * X * Revision 3.37 88/08/30 20:37:16 tony X * After much prodding from Mark, I finally added support for replace mode. X * X * Revision 3.36 88/08/26 13:46:34 tony X * Added support for the '!' (filter) operator. X * X * Revision 3.35 88/08/26 08:46:01 tony X * Misc. changes to make lint happy. X * X * Revision 3.34 88/08/25 15:13:36 tony X * Fixed a bug where the cursor didn't land on the right place after X * "beginning-of-word" searches if the word was preceded by the start X * of the line and a single character. X * X * Revision 3.33 88/08/23 12:53:08 tony X * Fixed a bug in ssearch() where repeated searches ('n' or 'N') resulted X * in dynamic memory being referenced after it was freed. X * X * Revision 3.32 88/08/17 07:37:07 tony X * Fixed a general problem in u_save() by checking both parameters for X * null values. The specific symptom was that a join on the last line of X * the file would crash the editor. X * X * Revision 3.31 88/07/09 20:39:38 tony X * Implemented the "line undo" command (i.e. 'U'). X * X * Revision 3.30 88/06/28 07:54:22 tony X * Fixed a bug involving redo's of the '~' command. The redo would just X * repeat the replacement last performed instead of switching the case of X * the current character. X * X * Revision 3.29 88/06/26 14:53:19 tony X * Added support for a simple form of the "global" command. It supports X * commands of the form "g/pat/d" or "g/pat/p", to delete or print lines X * that match the given pattern. A range spec may be used to limit the X * lines to be searched. X * X * Revision 3.28 88/06/25 21:44:22 tony X * Fixed a problem in the processing of colon commands that caused X * substitutions of patterns containing white space to fail. X * X * Revision 3.27 88/06/20 14:52:21 tony X * Merged in changes for BSD Unix sent in by Michael Lichter. X * X * Revision 3.26 88/06/10 13:44:06 tony X * Fixed a bug involving writing out files with long pathnames. A small X * fixed size buffer was being used. The space for the backup file name X * is now allocated dynamically. X * X * Revision 3.25 88/05/04 08:29:02 tony X * Fixed a minor incompatibility with vi involving the 'G' command. Also X * changed the RCS version number of version.c to match the actual version X * of the editor. X * X * Revision 1.12 88/05/03 14:39:52 tony X * Changed the screen representation of the ascii character DELETE to be X * compatible with vi. Also merged in support for DOS. X * X * Revision 1.11 88/05/02 21:38:21 tony X * The code that reads files now handles boundary/error conditions much X * better, and generates status/error messages that are compatible with X * the real vi. Also fixed a bug in repeated reverse searches that got X * inserted in the recent changes to search.c. X * X * Revision 1.10 88/05/02 07:35:41 tony X * Fixed a bug in the routine plines() that was introduced during changes X * made for the last version. X * X * Revision 1.9 88/05/01 20:10:19 tony X * Fixed some problems with auto-indent, and added support for the "number" X * parameter. X * X * Revision 1.8 88/04/30 20:00:49 tony X * Added support for the auto-indent feature. X * X * Revision 1.7 88/04/29 14:50:11 tony X * Fixed a class of bugs involving commands like "ct)" where the cursor X * motion part of the operator can fail. If the motion failed, the operator X * was continued, with the cursor position unchanged. Cases like this were X * modified to abort the operation if the motion fails. X * X * Revision 1.6 88/04/28 08:19:35 tony X * Modified Henry Spencer's regular expression library to support new X * features that couldn't be done easily with the existing interface. X * This code is now a direct part of the editor source code. The editor X * now supports the "ignorecase" parameter, and multiple substitutions X * per line, as in "1,$s/foo/bar/g". X * X * Revision 1.5 88/04/24 21:38:00 tony X * Added preliminary support for the substitute command. Full range specs. X * are supported, but only a single substitution is allowed on each line. X * X * Revision 1.4 88/04/23 20:41:01 tony X * Worked around a problem with adding lines to the end of the buffer when X * the cursor is at the bottom of the screen (in misccmds.c). Also fixed a X * bug that caused reverse searches from the start of the file to bomb. X * X * Revision 1.3 88/03/24 08:57:00 tony X * Fixed a bug in cmdline() that had to do with backspacing out of colon X * commands or searches. Searches were okay, but colon commands backed out X * one backspace too early. X * X * Revision 1.2 88/03/21 16:47:55 tony X * Fixed a bug in renum() causing problems with large files (>6400 lines). X * Also moved system-specific defines out of stevie.h and into a new file X * named env.h. This keeps volatile information outside the scope of RCS. X * X * Revision 1.1 88/03/20 21:00:39 tony X * Initial revision X * X */ X Xchar *Version = "STEVIE - Version 3.45"; END_OF_FILE if test 7218 -ne `wc -c <'version.c'`; then echo shar: \"'version.c'\" unpacked with wrong size! fi # end of 'version.c' fi if test -f 'tos_c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tos_c'\" else echo shar: Extracting \"'tos_c'\" \(7273 characters\) sed "s/^X//" >'tos_c' <<'END_OF_FILE' Xstatic char RCSid[] = X"$Header: tos.c,v 1.3 88/10/27 08:18:07 tony Exp $"; X X/* X * System-dependent routines for the Atari ST. X * X * $Log: tos.c,v $ X * Revision 1.3 88/10/27 08:18:07 tony X * Added a null flushbuf() for compatibility with versions that buffer X * output. Added fixname() to do appropriate name truncation. Added X * a quick doshell() that supports commands, but not interactive shells. X * Removed support for Megamax. X * X * Revision 1.2 88/09/23 19:35:44 tony X * Added mktemp() for use with the '!' operator. Also added support for X * the Sozobon C compiler. X * X * Revision 1.1 88/03/20 21:10:42 tony X * Initial revision X * X * X */ X X#include "stevie.h" X X#include X X/* X * The following buffer is used to work around a bug in TOS. It appears that X * unread console input can cause a crash, but only if console output is X * going on. The solution is to always grab any unread input before putting X * out a character. The following buffer holds any characters read in this X * fashion. The problem can be easily produced because STEVIE can't yet keep X * up with the normal auto-repeat rate in insert mode. X */ X#define IBUFSZ 128 X Xstatic long inbuf[IBUFSZ]; /* buffer for unread input */ Xstatic long *inptr = inbuf; /* where to put next character */ X X/* X * inchar() - get a character from the keyboard X * X * Certain special keys are mapped to values above 0x80. These X * mappings are defined in keymap.h. If the key has a non-zero X * ascii value, it is simply returned. Otherwise it may be a X * special key we want to map. X * X * The ST has a bug involving keyboard input that seems to occur X * when typing quickly, especially typing capital letters. Sometimes X * a value of 0x02540000 is read. This doesn't correspond to anything X * on the keyboard, according to my documentation. My solution is to X * loop when any unknown key is seen. Normally, the bell is rung to X * indicate the error. If the "bug" value is seen, we ignore it completely. X */ Xint Xinchar() X{ X for (;;) { X long c, *p; X X /* X * Get the next input character, either from the input X * buffer or directly from TOS. X */ X if (inptr != inbuf) { /* input in the buffer, use it */ X c = inbuf[0]; X /* X * Shift everything else in the buffer down. This X * would be cleaner if we used a circular buffer, X * but it really isn't worth it. X */ X inptr--; X for (p = inbuf; p < inptr ;p++) X *p = *(p+1); X } else X c = Crawcin(); X X if ((c & 0xff) != 0) X return ((int) c); X X switch ((int) (c >> 16) & 0xff) { X X case 0x62: return K_HELP; X case 0x61: return K_UNDO; X case 0x52: return K_INSERT; X case 0x47: return K_HOME; X case 0x48: return K_UARROW; X case 0x50: return K_DARROW; X case 0x4b: return K_LARROW; X case 0x4d: return K_RARROW; X case 0x29: return K_CGRAVE; /* control grave accent */ X X /* X * Occurs due to a bug in TOS. X */ X case 0x54: X break; X /* X * Add the function keys here later if we put in support X * for macros. X */ X X default: X beep(); X break; X X } X } X} X X/* X * get_inchars - snarf away any pending console input X * X * If the buffer overflows, we discard what's left and ring the bell. X */ Xstatic void Xget_inchars() X{ X while (Cconis()) { X if (inptr >= &inbuf[IBUFSZ]) { /* no room in buffer? */ X Crawcin(); /* discard the input */ X beep(); /* and sound the alarm */ X } else X *inptr++ = Crawcin(); X } X} X Xvoid Xoutchar(c) Xchar c; X{ X get_inchars(); X Cconout(c); X} X Xvoid Xoutstr(s) Xregister char *s; X{ X get_inchars(); X Cconws(s); X} X X/* X * flushbuf() - a no-op for TOS X */ Xvoid Xflushbuf() X{ X} X X#define BGND 0 X#define TEXT 3 X X/* X * vbeep() - visual bell X */ Xstatic void Xvbeep() X{ X int text, bgnd; /* text and background colors */ X long l; X X text = Setcolor(TEXT, -1); X bgnd = Setcolor(BGND, -1); X X Setcolor(TEXT, bgnd); /* swap colors */ X Setcolor(BGND, text); X X for (l=0; l < 5000 ;l++) /* short pause */ X ; X X Setcolor(TEXT, text); /* restore colors */ X Setcolor(BGND, bgnd); X} X Xvoid Xbeep() X{ X if (P(P_VB)) X vbeep(); X else X outchar('\007'); X} X X/* X * remove(file) - remove a file X */ Xvoid Xremove(file) Xchar *file; X{ X Fdelete(file); X} X X/* X * rename(of, nf) - rename existing file 'of' to 'nf' X */ Xvoid Xrename(of, nf) Xchar *of, *nf; X{ X Fdelete(nf); /* if 'nf' exists, remove it */ X Frename(0, of, nf); X} X Xvoid Xwindinit() X{ X if (Getrez() == 0) X Columns = 40; /* low resolution */ X else X Columns = 80; /* medium or high */ X X P(P_LI) = Rows = 25; X X Cursconf(1,NULL); X} X Xvoid Xwindexit(r) Xint r; X{ X exit(r); X} X Xvoid Xwindgoto(r, c) Xint r, c; X{ X outstr("\033Y"); X outchar(r + 040); X outchar(c + 040); X} X X/* X * System calls or library routines missing in TOS. X */ X Xvoid Xsleep(n) Xint n; X{ X int k; X X k = Tgettime(); X while ( Tgettime() <= k+n ) X ; X} X Xvoid Xdelay() X{ X long n; X X for (n = 0; n < 8000 ;n++) X ; X} X Xint Xsystem(cmd) Xchar *cmd; X{ X char arg[1]; X X arg[0] = (char) 0; /* no arguments passed to the shell */ X X if (Pexec(0, cmd, arg, 0L) < 0) X return -1; X else X return 0; X} X X#ifdef SOZOBON X XFILE * Xfopenb(fname, mode) Xchar *fname; Xchar *mode; X{ X char modestr[10]; X X sprintf(modestr, "%sb", mode); X X return fopen(fname, modestr); X} X X#endif X X#ifndef SOZOBON X/* X * getenv() - get a string from the environment X * X * Both Alcyon and Megamax are missing getenv(). This routine works for X * both compilers and with the Beckemeyer and Gulam shells. With gulam, X * the env_style variable should be set to either "mw" or "gu". X */ Xchar * Xgetenv(name) Xchar *name; X{ X extern long _base; X char *envp, *p; X X envp = *((char **) (_base + 0x2c)); X X for (; *envp ;envp += strlen(envp)+1) { X if (strncmp(envp, name, strlen(name)) == 0) { X p = envp + strlen(name); X if (*p++ == '=') X return p; X } X } X return (char *) 0; X} X#endif X X/* X * mktemp() - quick hack since there isn't one here X */ Xchar * Xmktemp(name) Xchar *name; X{ X int num; /* pasted into the string to make it unique */ X char cbuf[7]; X char *s; /* where the X's start in name */ X int fd; X X if ((s = strchr(name, 'X')) == NULL) /* needs to be an X */ X return (char *) NULL; X X if (strlen(s) != 6) /* should be 6 X's */ X return (char *) NULL; X X for (num = 0; num < 1000 ;num++) { X sprintf(cbuf, "%06d", num); X strcpy(s, cbuf); X if ((fd = open(name, 0)) < 0) X return name; X close(fd); X } X return (char *) NULL; X} X Xvoid Xdoshell(cmd) Xchar *cmd; X{ X if (cmd == NULL) { X emsg("Sorry, no interactive shell"); X return; X } X system(cmd); X wait_return(); X} X X#define PSIZE 128 X X/* X * fixname(s) - fix up a dos name X * X * Takes a name like: X * X * \x\y\z\base.ext X * X * and trims 'base' to 8 characters, and 'ext' to 3. X */ Xchar * Xfixname(s) Xchar *s; X{ X char *strchr(), *strrchr(); X static char f[PSIZE]; X char base[32]; X char ext[32]; X char *p; X int i; X X strcpy(f, s); X X for (i=0; i < PSIZE ;i++) X if (f[i] == '/') X f[i] = '\\'; X X /* X * Split the name into directory, base, extension. X */ X if ((p = strrchr(f, '\\')) != NULL) { X strcpy(base, p+1); X p[1] = '\0'; X } else { X strcpy(base, f); X f[0] = '\0'; X } X X if ((p = strchr(base, '.')) != NULL) { X strcpy(ext, p+1); X *p = '\0'; X } else X ext[0] = '\0'; X X /* X * Trim the base name if necessary. X */ X if (strlen(base) > 8) X base[8] = '\0'; X X if (strlen(ext) > 3) X ext[3] = '\0'; X X /* X * Paste it all back together X */ X strcat(f, base); X strcat(f, "."); X strcat(f, ext); X X return f; X} END_OF_FILE if test 7273 -ne `wc -c <'tos_c'`; then echo shar: \"'tos_c'\" unpacked with wrong size! fi # end of 'tos_c' fi echo shar: End of shell archive. exit 0