home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-03-14 | 59.5 KB | 2,587 lines |
-
- : This is a shar archive. Extract with sh, not csh.
- : The rest of this file will extract:
- : search.c sentence.c tagcmd.c term.c undo.c version.c tos.c
- echo extracting - search.c
- sed 's/^X//' > search.c << '!EOR!'
- X/* $Header: /nw/tony/src/stevie/src/RCS/search.c,v 1.16 89/08/06 09:50:51 tony Exp $
- 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
- 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 register 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 got_int = FALSE;
- X
- X if ((p = ssearch(dir,str)) == NULL) {
- X if (got_int)
- X msg("Interrupt");
- X else
- X msg("Pattern not found");
- X
- X got_int = FALSE;
- X return FALSE;
- X } else {
- X LPTR savep;
- X
- X cursupdate();
- X /*
- X * if we're backing up, we make sure the line we're on
- X * is on the screen.
- X */
- X setpcmark();
- X *Curschar = savep = *p;
- X set_want_col = TRUE;
- 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((char *)prog);
- X return (&infile);
- X }
- X i = 0;
- X
- X if (got_int)
- X goto fwdfail;
- X
- 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 goto fwdfail;
- 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((char *)prog);
- X return (&infile);
- X }
- X
- X if (p->linep == Curschar->linep)
- X break;
- X
- X if (got_int)
- X goto fwdfail;
- X }
- X
- Xfwdfail:
- X free((char *)prog);
- X return NULL;
- X}
- X
- Xstatic LPTR *
- Xbcksearch(str)
- Xchar *str;
- X{
- X static LPTR infile;
- X register LPTR *p = &infile;
- X register char *s;
- X register int i;
- X register char *match;
- X regexp *prog;
- 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 if (dec(p) == -1) { /* already at start of file? */
- X *p = *Fileend;
- X p->index = strlen(p->linep->s) - 1;
- X }
- 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((char *)prog);
- X return (&infile);
- X }
- X i = -1;
- X
- X if (got_int)
- X goto bckfail;
- 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 goto bckfail;
- 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((char *)prog);
- X return (&infile);
- X }
- X
- X if (p->linep == Curschar->linep)
- X break;
- X
- X if (got_int)
- X goto bckfail;
- X
- X } while ((p = prevline(p)) != NULL);
- X
- Xbckfail:
- X free((char *)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 == '\\') /* next char is quoted */
- X cmd += 2;
- X else if (*cmd == '/') { /* delimiter */
- X *cmd++ = NUL;
- X break;
- X } else
- X cmd++; /* regular character */
- 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 == '\\') /* next char is quoted */
- X cmd += 2;
- X else if (*cmd == '/') { /* delimiter */
- X do_all = (cmd[1] == 'g');
- X *cmd++ = NUL;
- X break;
- X } else
- X cmd++; /* regular character */
- 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 if (!sns) return;
- 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((char *)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 == '\\') /* next char is quoted */
- X cmd += 2;
- X else if (*cmd == '/') { /* delimiter */
- X cmdchar = cmd[1];
- X *cmd++ = NUL;
- X break;
- X } else
- X cmd++; /* regular character */
- 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 got_int = FALSE;
- X
- X for (cp = lp->linep; cp != NULL && !got_int ;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) || got_int)
- X smsg("%s%d fewer line%c",
- X got_int ? "Interrupt: " : "",
- X ndone,
- X (ndone > 1) ? 's' : ' ');
- X break;
- X
- X case 'p':
- X wait_return();
- X break;
- X }
- X } else {
- X if (got_int)
- X msg("Interrupt");
- X else
- X msg("No match");
- X }
- X
- X got_int = FALSE;
- X free((char *)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/*
- 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, in_change) - 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 * There's a strange special case here that the 'in_change' parameter
- X * helps us deal with. Vi effectively turns 'cw' into 'ce'. If we're on
- X * a word with only one character, we need to stick at the current
- X * position so we don't change two words.
- X *
- X * Returns the resulting position, or NULL if EOF was reached.
- X */
- XLPTR *
- Xend_word(p, type, in_change)
- XLPTR *p;
- Xint type;
- Xbool_t in_change;
- 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 of the next
- X * word, unless we're doing a change. In that case we stick
- X * at the end of the current word.
- X */
- X if (in_change)
- X return p;
- 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}
- !EOR!
- echo extracting - sentence.c
- sed 's/^X//' > sentence.c << '!EOR!'
- X/* Find the NEXT/PREVIOUS:
- X * - SENTENCE findsent (dir)
- X * - PARAGRAPH findpara (dir)
- X * - FUNCTION findfunc (dir)
- X *
- X * I've split these off from SEARCH.C, because they're alike and
- X * SEARCH.C is a big file already. findfunc() was already there.
- X * I added findsent() and findpara(). - Dave Tutelman
- X */
- X
- X#include "stevie.h"
- X#include "ops.h"
- X
- X/* We'll be doing some classification of input characters, into: */
- X#define BLANK 0 /* Whitespace */
- X#define DOT 1 /* Period, exclamation, q-mark */
- X#define EOL 2 /* End-of-line */
- X#define OTHER 3 /* Any other non-blank stuff */
- X
- Xextern int operator; /* From normal.c, is there an operator
- X * pending?
- X */
- X
- Xint
- Xinclass (c)
- X char c;
- X{
- X switch (c) {
- X case ' ':
- X case '\t':
- X return BLANK;
- X case '.':
- X case '!':
- X case '?':
- X return DOT;
- X case '\n':
- X case '\r':
- X case '\0':
- X return EOL;
- X default:
- X if (c<' ' || c>'~') return EOL;
- X else return OTHER;
- X }
- X}
- X
- X/* We'll also need to (1) tell if a line is just blanks, and
- X * (2) skip to the next OTHER character.
- X * Here are a couple of functions to do it.
- X */
- X
- Xbool_t
- Xblankline (line)
- X LPTR *line;
- X{
- X char *p;
- X int class;
- X
- X if (! line) return TRUE;
- X for (p = line->linep->s; (class=inclass(*p))!=EOL; p++)
- X if (class!=BLANK) return FALSE;
- X return TRUE;
- X}
- X
- X
- XLPTR *
- Xskiptotext (lp, dir)
- X LPTR *lp;
- X int dir;
- X{
- X LPTR *lpp;
- X
- X lpp = lp;
- X while (inclass( CHAR( lpp )) != OTHER) {
- X lpp = (dir==FORWARD) ? nextchar (lpp) : prevchar (lpp);
- X if (!lpp) return (lp); /* hit the end */
- X }
- X return (lpp);
- X}
- X
- X
- X/*
- X * findsent (dir) - Find the next sentence in direction 'dir'
- X *
- X * Return TRUE if a sentence was found.
- X *
- X * Algorithm: found end of a sentence if:
- X * FWD - current char is BLANK | EOL and last is DOT.
- X * BKWD- current char is DOT and last is BLANK | EOL.
- X * In either case, we then have to skip to text at beginning of next sentence.
- X *
- X */
- Xbool_t
- Xfindsent (dir)
- Xint dir;
- X{
- X LPTR *curr, *last; /* LPTR for current & last characters */
- X int ccurr, clast; /* class of curr and last characters */
- X int oldindex; /* need to keep in case search fails */
- X
- X curr = Curschar;
- X oldindex = curr->index;
- X /* Get INTO most recent sentence sentence. */
- X if (dir==BACKWARD)
- X curr = prevchar (curr);
- X curr = skiptotext (curr, BACKWARD);
- X ccurr = OTHER;
- X
- X
- X do {
- X /* Take a step */
- X last = curr; clast = ccurr;
- X
- X curr = (dir == FORWARD) ? nextchar(curr) : prevchar(curr);
- X ccurr = inclass (CHAR( curr ));
- X
- X /* Test halting condition */
- X if (dir==FORWARD &&
- X (ccurr==BLANK || ccurr==EOL) && clast==DOT) {
- X setpcmark();
- X last = skiptotext (last, FORWARD);
- X *Curschar = *last;
- X return TRUE;
- X }
- X else if (dir==BACKWARD &&
- X ccurr==DOT && (clast==BLANK || clast==EOL)) {
- X setpcmark();
- X last = skiptotext (last, FORWARD);
- X *Curschar = *last;
- X return TRUE;
- X }
- X } while (curr != NULL);
- X
- X Curschar->index = oldindex; /* restore if search failed */
- X return FALSE;
- X}
- X
- X
- X/*
- X * findpara(dir) - Find the next paragraph in direction 'dir'
- X *
- X * Return TRUE if a paragraph was found.
- X *
- X * Algorithm: found beginning of paragraph if:
- X * FWD - current line is non-blank and last is blank.
- X * BKWD- current line is blank and last is non-blank.
- X * Then we skip to the first non-blank, non-dot text.
- X *
- X */
- Xbool_t
- Xfindpara(dir)
- Xint dir;
- X{
- X LPTR *curr, *last; /* current & last lines */
- X LPTR *marker; /* end of current para */
- X bool_t bcurr, blast; /* "blankness" value for lines */
- X
- X curr = Curschar;
- X bcurr = (dir==FORWARD) ? FALSE : TRUE; /* keeps us from passing the
- X * text initially. */
- X
- X do {
- X /* Take a step */
- X last = curr; blast = bcurr;
- X curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);
- X bcurr = blankline (curr);
- X
- X /* Test halting condition */
- X if (dir==FORWARD && bcurr && !blast) {
- X setpcmark();
- X curr = skiptotext (curr, FORWARD);
- X *Curschar = *curr;
- X return TRUE;
- X }
- X else if (dir==BACKWARD && bcurr && !blast) {
- X setpcmark();
- X last = skiptotext (last, FORWARD);
- X *Curschar = *last;
- X return TRUE;
- X }
- X } while (curr != NULL);
- X
- X return FALSE;
- X}
- X
- X
- X/*
- X * findfunc(dir) - Find the next function in direction 'dir'
- X *
- X * Return TRUE if a function was found.
- X *
- X * Algorithm depends on a style of C coding in which the ONLY '{'
- X * in the first column occurs at the beginning of a function definition.
- X * This is a good and common style, but not syntactically required by C.
- 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
- !EOR!
- echo extracting - tagcmd.c
- sed 's/^X//' > tagcmd.c << '!EOR!'
- X/* #Header: /?????
- X *
- X * Routines to implement tags, and, especially, tag stacking.
- X * Added by Dave Tutelman - 12/89.
- X * The dotag() routine is a modification of the posted
- X * version by Tony Andrews.
- X * The untag() routine is new.
- X */
- X
- X#include "stevie.h"
- X
- X#define LSIZE 256 /* max. size of a line in the tags file */
- X
- X#ifdef TAGSTACK
- X/* We build a stack of file records, on which we push info about
- X * current file when dotag() is called.
- X */
- X#define TAGSTACKSIZE 12 /* how many tag calls can we stack? */
- Xstatic struct filerecord {
- X char *name; /* file name pointer */
- X int linenum; /* line number when we left */
- X} tagstack [TAGSTACKSIZE];
- Xstatic int stackindex = 0; /* here's how we keep track */
- X#endif
- X
- Xextern char **files;
- Xextern int curfile;
- Xstatic void pushtags(), poptags();
- X
- X
- X/*
- X * dotag(tag, force) - goto tag. If force=TRUE, dump pending changes.
- X */
- Xvoid
- Xdotag(tag, force)
- Xchar *tag;
- Xbool_t force;
- X{
- X FILE *tp, *fopen();
- X char lbuf[LSIZE]; /* line buffer */
- X char pbuf[LSIZE]; /* search pattern buffer */
- X register char *fname, *str;
- X register char *p;
- X
- X if ((tp = fopen("tags", "r")) == NULL) {
- X emsg("Can't open tags file");
- X return;
- X }
- X
- X while (fgets(lbuf, LSIZE, tp) != NULL) {
- X
- X if ((fname = strchr(lbuf, TAB)) == NULL) {
- X emsg("Format error in tags file");
- X return;
- X }
- X *fname++ = '\0';
- X if ((str = strchr(fname, TAB)) == NULL) {
- X emsg("Format error in tags file");
- X return;
- X }
- X *str++ = '\0';
- X
- X if (strcmp(lbuf, tag) == 0) {
- X
- X /*
- X * Scan through the search string. If we see a magic
- X * char, we have to quote it. This lets us use "real"
- X * implementations of ctags.
- X */
- X p = pbuf;
- X *p++ = *str++; /* copy the '/' or '?' */
- X *p++ = *str++; /* copy the '^' */
- X
- X for (; *str != NUL ;str++) {
- X if (*str == '\\') {
- X *p++ = *str++;
- X *p++ = *str;
- X } else if (strchr("/?", *str) != NULL) {
- X if (str[1] != '\n') {
- X *p++ = '\\';
- X *p++ = *str;
- X } else
- X *p++ = *str;
- X } else if (strchr("^()*.", *str) != NULL) {
- X *p++ = '\\';
- X *p++ = *str;
- X } else
- X *p++ = *str;
- X }
- X *p = NUL;
- X
- X#ifdef TAGSTACK
- X /* Push current position onto stack, unless this
- X * is a startup call using '-t' option. */
- X if (Filename!=NULL && *Filename!='\0')
- X pushtags ();
- X#endif
- X
- X /*
- X * This looks out of order, but by calling stuffin()
- X * before doecmd() we keep an extra screen update
- X * from occuring. This stuffins() have no effect
- X * until we get back to the main loop, anyway.
- X */
- X
- X stuffin(pbuf); /* str has \n at end */
- X stuffin("\007"); /* CTRL('g') */
- X
- X if (doecmd(fname, force)) {
- X fclose(tp);
- X return;
- X } else {
- X#ifdef TAGSTACK
- X poptags (); /* cancel stack entry */
- X#endif
- X stuffin(NULL); /* clear the input */
- X }
- X }
- X }
- X emsg("tag not found");
- X fclose(tp);
- X}
- X
- X/*
- X * dountag (spec) - undo the last ':ta' command, popping the tag stack.
- X * spec is the appended character, giving specifics:
- X * '!' dump pending changes.
- X * 'e' came from K_CCIRCM "shortcut". do :e# if stack empty.
- X * ' ' do normal untag.
- X * else bad command.
- X */
- X
- Xvoid
- Xdountag (spec)
- X char spec;
- X{
- X#ifndef TAGSTACK
- X badcmd(); /* complain & return */
- X}
- X#else
- X
- X char force=0, shortcut=0;
- X char *newfile;
- X char buf [LSIZE];
- X
- X switch (spec) {
- X case '!':
- X force++;
- X break;
- X case 'e':
- X shortcut++;
- X break;
- X case ' ':
- X case '\n':
- X case '\r':
- X case '\0':
- X break;
- X default:
- X badcmd();
- X return;
- X }
- X
- X /* Check the stack. If empty, don't pop */
- X if (!stackindex) {
- X if (shortcut) /* just edit altfile */
- X stuffin(":e #\n");
- X else
- X emsg("Tags stack empty");
- X return;
- X }
- X
- X /* Get the top of the stack, and do the implied edit.
- X * If it succeeds, switch; if not, back off */
- X newfile = tagstack [stackindex-1].name;
- X if (doecmd (newfile, force)) {
- X sprintf (buf, "%dG:f\n", tagstack [stackindex-1].linenum);
- X stuffin(buf);
- X poptags ();
- X return;
- X }
- X else
- X stuffin(NULL);
- X}
- X
- X/*
- X * pushtags () - push the current state onto the tagstack.
- X */
- X
- Xstatic void
- Xpushtags ()
- X{
- X int i;
- X
- X /* If stack full, throw away oldest and push the rest.
- X * This is clearly the best and most transparent way to behave,
- X * much preferable to either complaining or losing new entry.
- X */
- X if (stackindex >= TAGSTACKSIZE) {
- X for (i=0; i<TAGSTACKSIZE-1; i++) {
- X tagstack[i].name = tagstack[i+1].name;
- X tagstack[i].linenum = tagstack[i+1].linenum;
- X }
- X stackindex--;
- X }
- X
- X /* Get current state, and put it in stack.
- X * Right now, the state is file name & line number.
- X * This is less than perfect, in that line numbers may change if
- X * you edit elsewhere in the file. Eventually, I'd like to base
- X * it on "hidden" marks, if I can implement them. DMT
- X */
- X tagstack [stackindex].name = strsave (Filename);
- X tagstack [stackindex].linenum = cntllines (Filemem, Curschar);
- X stackindex++;
- X}
- X
- X/*
- X * poptags () - pop the tag stack.
- X */
- X
- Xstatic void
- Xpoptags ()
- X{
- X if (!stackindex) {
- X emsg("Tags stack empty");
- X return;
- X }
- X
- X stackindex--;
- X free (tagstack [stackindex].name);
- X}
- X
- X#endif
- X
- X
- !EOR!
- echo extracting - term.c
- sed 's/^X//' > term.c << '!EOR!'
- X/* $Header: /nw/tony/src/stevie/src/RCS/term.c,v 1.4 89/03/11 22:43:55 tony Exp $
- X *
- X * Termcap initialization (optional).
- X */
- X
- X#include <stdio.h>
- 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_ED = tgetstr("cl", &cp)) == NULL)
- X return 0;
- X
- X /*
- X * Optional capabilities.
- X */
- X if ((T_IL = tgetstr("al", &cp)) == NULL)
- X T_IL = "";
- X
- X if ((T_DL = tgetstr("dl", &cp)) == NULL)
- X T_DL = "";
- X
- X if ((T_SC = tgetstr("sc", &cp)) == NULL)
- X T_SC = "";
- X
- X if ((T_RC = tgetstr("rc", &cp)) == NULL)
- X T_RC = "";
- 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
- !EOR!
- echo extracting - undo.c
- sed 's/^X//' > undo.c << '!EOR!'
- X/* $Header: /nw/tony/src/stevie/src/RCS/undo.c,v 1.7 89/08/06 09:51:06 tony Exp $
- 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
- 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((char *)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((char *)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((char *)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));
- X strcpy(nl->s, l->s);
- X
- X return nl;
- X}
- !EOR!
- echo extracting - version.c
- sed 's/^X//' > version.c << '!EOR!'
- Xstatic char RCSid[] =
- X"$Header: /nw/tony/src/stevie/src/RCS/version.c,v 3.69 89/08/13 11:41:58 tony Exp $";
- X
- X/*
- X * Contains the declaration of the global version number variable.
- X *
- X * $Log: version.c,v $
- X *
- X * Revision 3.69a 90/02/04 dave
- X * A couple of minor bugfixes, and a whole load of enhancements:
- X * - Added tag-stacking.
- X * - Added searches for sentences and paragraphs.
- X * - Enhancements to "help" command:
- X * . Navigation of help screens, not just next-screen.
- X * . Index of help screens.
- X * . Screen for MSDOS-specific features.
- X * . Screen for :set commands.
- X * . A little context-sensitivity.
- X * - File mode is preserved (it wasn't in previous versions).
- X * - UNIX-like specifications of environments variables are expanded
- X * in file names. (E.g.- you can say :e $HOME/autoexec.bat)
- X * - PC keys for Insert & Delete now work.
- X * - Ported to Turbo C for the PC.
- X * - Integrated Larry Shurr's BIOS option for the PC.
- X * - Added color and multi-line options for the PC, and hooks for them
- X * in other systems.
- X * - Made "ctags" a little more general.
- X *
- X * Revision 3.69 89/08/13 11:41:58 tony
- X * Fixed a bug that caused messages from fileinfo() (in misccmds.c) to get
- X * screwed up. The routine smsg() which uses the kludge approach to varargs
- X * didn't have enough parameters for some of the calls made to it.
- X *
- X * Revision 3.68 89/08/06 09:51:20 tony
- X * Misc. minor changes to make lint happier before posting to USENET.
- X *
- X * Revision 3.67 89/08/03 13:08:52 tony
- X * There was some code in ops.c that was duplicating the function of the
- X * getcmdln() routine in cmdline.c. I modified getcmdln() to be slightly
- X * more general, and changed dofilter() in ops.c to use it.
- X *
- X * Revision 3.66 89/08/02 20:00:12 tony
- X * Fixed some problems with mode lines. There were still extra screen
- X * redraws that needed to be avoided. There was also a problem involving
- X * nested calls to docmdln() that can occur when mode lines are used.
- X *
- X * Revision 3.65 89/08/02 15:50:03 tony
- X * Finally got around to providing full support for the "change" operator.
- X * Multi-line changes (like "cL" or "3cc") now work correctly. Also fixed
- X * a small problem with multi-line character-oriented deletes leaving the
- X * cursor in the wrong location (off by one character). This is mainly
- X * useful for multi-line changes (such as "c%") so the insert starts in
- X * the right place.
- X *
- X * Revision 3.64 89/08/02 12:47:04 tony
- X * This message intentionally left blank.
- X *
- X * Revision 3.63 89/08/02 12:43:44 tony
- X * I just noticed that I had used the RCS cookie for log messages in one
- X * of my prior version messages. This caused these version update messages
- X * to be duplicated in this file. I just removed that string, and the
- X * extra message copies that had been generated.
- X *
- X * Revision 3.62 89/08/02 12:26:20 tony
- X * The ^G command now shows where you are in the file list, if more than one
- X * file is being edited. Also, the commands ":e#" and ":e!#" (note the lack
- X * of a space between the command and file name) will now work.
- X *
- X * Revision 3.61 89/08/02 11:03:16 tony
- X * Misc. cleanups regarding tags. Also added support for the "terse" option.
- X * This is ignored, but improves compatibility with vi, since we no longer
- X * complain about an unknown option if "terse" is used.
- X *
- X * Revision 3.60 89/08/02 09:26:39 tony
- X * Added code to avoid screen redraws when input is being read from the
- X * "stuffin" buffer. This avoids extra redraws when switching to the
- X * alternate file, or when invoking the editor with one of the "+" options,
- X * or when using tags.
- X *
- X * Revision 3.59 89/08/01 16:28:31 tony
- X * Added better support for counts on several cursor motion commands. These
- X * include ^F, ^B, f, F, t, T, as well as the repeated character search
- X * commands (command and semi-colon).
- X *
- X * Revision 3.58 89/07/19 08:08:23 tony
- X * Added the ability for '~' to be an operator. If enabled (by defined TILDEOP
- X * in env.h), the parameter "tildeop" (or "to") may be set to turn tilde into
- X * an operator.
- X *
- X * Revision 3.57 89/07/13 22:47:05 tony
- X * Made some generic speed improvements in screen.c and some TOS-specific
- X * improvements in tos.c. The TOS version is now much faster at screen
- X * updates than before.
- X *
- X * Revision 3.56 89/07/13 14:52:03 tony
- X * Minor cleanups in normal.c
- X *
- X * Revision 3.55 89/07/13 14:19:12 tony
- X * Cleaned up the logic in getcmdln() A LOT. The routine docmdln() needs a
- X * similar overhaul.
- X *
- X * Revision 3.54 89/07/12 21:40:01 tony
- X * Lots of misc. cleanup in normal.c and cmdline.c, but nothing much in the
- X * way of functional improvements. One change is that things like d/foo<CR>
- X * will now work since searches are less of a special case now.
- X *
- X * Revision 3.53 89/07/11 16:16:08 tony
- X * Added general support for interrupt-handling for those environments that
- X * can actually generate them. Basically, long-running operations are now
- X * able to terminate early if an error occurs. These operations are: string
- X * searches, the global command (":g/.../"), and file reads. File writes
- X * should probably be done as well, but this is more dangerous. In all cases,
- X * the user is given an indication on the status line that the operation
- X * terminated due to an interrupt.
- X *
- X * Revision 3.52 89/07/11 12:35:09 tony
- X * Improved the code in dosub() and doglob() that detects quoted characters
- X * and delimiters in search strings and replacement patterns. The current
- X * code didn't allow certain valid strings to be used. The delimiter is still
- X * required to be '/', but it can be quoted reliably now with backslash.
- X *
- X * Revision 3.51 89/07/10 14:01:58 tony
- X * Removed the function addtobuff() since it was rarely used and could be
- X * replaced by calls to other library functions. Also removed some other
- X * obsolete code that was already ifdef'd out anyway.
- X *
- X * Revision 3.50 89/07/10 13:10:32 tony
- X * Added a workaround in normal.c to avoid problems with broken versions of
- X * strncpy() that don't properly deal with a count of zero.
- X *
- X * Revision 3.49 89/07/07 16:28:37 tony
- X * Fixed a long-standing bug with 'cw' when the cursor is positioned on a
- X * word with only one character. Also fixed a problems with zero-length files
- X * and reverse searches.
- X *
- X * Revision 3.48 89/03/22 10:26:58 tony
- X * Fixed some outdated uses of the ":p" command (which has been changed to
- X * ":N" in os2.c and dos.c. Also added macros (F7 and F8) for dos and os/2
- X * to use the "cdecl" program to convert lines to and from a pseudo-english
- X * form. Use F7 to "explain" the declaration on the current line, and F8 to
- X * convert an english-style declaration to the C form. In both cases, the
- X * new form is placed on the next line, leaving the original line intact.
- X *
- X * Revision 3.47 89/03/11 22:44:14 tony
- X * General cleanup. Removed the static "rcsid" variables and the log
- X * strings (except in version.c). Fixed some coding style inconsistencies
- X * and added a few register declarations.
- X *
- X * Revision 3.46 89/02/14 09:52:07 tony
- X * Made a first pass at adding Robert Regn's changes, starting with the
- X * more portable ones. Added better support for '#' and '%' in colon
- X * commands, support for a configurable temp directory, and made the
- X * termcap code less picky about capabilities.
- X *
- 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.69a";
- !EOR!
- echo extracting - tos.c
- sed 's/^X//' > tos.c << '!EOR!'
- X/* $Header: /nw/tony/src/stevie/src/RCS/tos.c,v 1.5 89/07/13 22:45:31 tony Exp $
- X *
- X * System-dependent routines for the Atari ST.
- X */
- X
- X#include "stevie.h"
- X
- X#include <osbind.h>
- 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 register long c;
- X
- X for (;;) {
- X c = Bconin(2);
- 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_CCIRCM; /* control-circumflex */
- 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
- Xvoid
- Xoutchar(c)
- Xchar c;
- X{
- X if (c < ' ')
- X Bconout(2, c);
- X else
- X Bconout(5, c);
- X}
- X
- Xvoid
- Xoutstr(s)
- Xregister char *s;
- X{
- X while (*s)
- X Bconout(2, *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
- Xstatic char gobuf[5] = { '\033', 'Y', '\0', '\0', '\0' };
- X
- Xvoid
- Xwindgoto(r, c)
- Xint r, c;
- X{
- X gobuf[2] = r + 040;
- X gobuf[3] = c + 040;
- X outstr(gobuf);
- 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
- Xpause()
- 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 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}
- X
- X/*
- X * FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
- X *
- X * The next couple of functions do system-specific stuff.
- X * They currently do nothing; I'm not familiar enough with
- X * system-specific programming on this system.
- X * If you fill it in for your system, please post the results
- X * and share with the rest of us.
- X */
- X
- X
- Xsetcolor (c)
- X/*
- X * Set the color to c, using the local system convention for numbering
- X * colors or video attributes.
- X *
- X * If you implement this, remember to note the original color in
- X * windinit(), before you do any setcolor() commands, and
- X * do a setcolor() back to the original as part of windexit().
- X */
- X int c:
- X{
- X}
- X
- X
- Xsetrows (r)
- X/*
- X * Set the number of lines to r, if possible. Otherwise
- X * "do the right thing". Return the number of lines actually set.
- X *
- X * If you implement this, remember to note the original number of rows
- X * in windinit(), before you do any setrows() commands, and
- X * do a setrows() back to the original as part of windexit().
- X */
- X int r;
- X{
- X /* Since we do nothing, just return the current number of lines */
- X return ( P(P_LI) );
- X}
- X
- X
- Xvbeep ()
- X/*
- X * Do a "visual bell". This generally consists of flashing the screen
- X * once in inverse video.
- X */
- X{
- X int color, revco;
- X
- X color = P( P_CO ); /* get current color */
- X revco = reverse_color (color); /* system-specific */
- X setcolor (revco);
- X flushbuf ();
- X pause ();
- X setcolor (color);
- X windgoto (Cursrow, Curscol);
- X flushbuf ();
- X}
- X
- Xreverse_color (co)
- X/*
- X * Returns the inverse video attribute or color of co.
- X * The existing code below is VERY simple-minded.
- X * Replace it with proper code for your system.
- X */
- X int co;
- X{
- X if (co) return (0);
- X else return (1);
- X}
- X
- X
- X/********** End of do-it-yourself kit **********************/
- X
- !EOR!
-
-
-