home *** CD-ROM | disk | FTP | other *** search
- From: kirkenda@eecs.cs.pdx.edu (Steve Kirkendall)
- Newsgroups: alt.sources
- Subject: ELvis 1.4, part 6 of 8
- Message-ID: <830@pdxgate.UUCP>
- Date: 3 Dec 90 21:33:56 GMT
-
- # --------------------------- cut here ----------------------------
- # This is a shar archive. To unpack it, save it to a file, and delete
- # anything above the "cut here" line. Then run sh on the file.
- #
- # -rw-r--r-- 1 kirkenda 9893 Dec 2 17:57 modify.c
- # -rw-r--r-- 1 kirkenda 10230 Dec 2 17:57 move1.c
- # -rw-r--r-- 1 kirkenda 4445 Dec 2 17:57 move2.c
- # -rw-r--r-- 1 kirkenda 2697 Dec 2 17:57 move3.c
- # -rw-r--r-- 1 kirkenda 3699 Dec 2 17:57 move4.c
- # -rw-r--r-- 1 kirkenda 3940 Dec 2 17:57 move5.c
- # -rw-r--r-- 1 kirkenda 14362 Dec 2 17:57 opts.c
- # -rw-r--r-- 1 kirkenda 2306 Dec 2 17:57 recycle.c
- # -rw-r--r-- 1 kirkenda 19816 Dec 2 17:57 redraw.c
- #
-
- if test -f modify.c -a "$1" != -f
- then
- echo Will not overwrite modify.c
- else
- echo Extracting modify.c
- sed 's/^X//' >modify.c <<\eof
- X/* modify.c */
- X
- X/* This file contains the low-level file modification functions:
- X * delete(frommark, tomark) - removes line or portions of lines
- X * add(frommark, text) - inserts new text
- X * change(frommark, tomark, text) - delete, then add
- X */
- X
- X#include "config.h"
- X#include "vi.h"
- X
- X#ifdef DEBUG
- X# include <stdio.h>
- Xstatic FILE *dbg;
- X
- X/*VARARGS1*/
- Xdebout(msg, arg1, arg2, arg3, arg4, arg5)
- X char *msg, *arg1, *arg2, *arg3, *arg4, *arg5;
- X{
- X if (!dbg)
- X {
- X dbg = fopen("debug.out", "w");
- X setbuf(dbg, (FILE *)0);
- X }
- X fprintf(dbg, msg, arg1, arg2, arg3, arg4, arg5);
- X}
- X#endif /* DEBUG */
- X
- X/* delete a range of text from the file */
- Xvoid delete(frommark, tomark)
- X MARK frommark; /* first char to be deleted */
- X MARK tomark; /* AFTER last char to be deleted */
- X{
- X int i; /* used to move thru logical blocks */
- X REG char *scan; /* used to scan thru text of the blk */
- X REG char *cpy; /* used when copying chars */
- X BLK *blk; /* a text block */
- X long l; /* a line number */
- X MARK m; /* a traveling version of frommark */
- X
- X#ifdef DEBUG
- X debout("delete(%ld.%d, %ld.%d)\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark));
- X#endif
- X
- X /* if not deleting anything, quit now */
- X if (frommark == tomark)
- X {
- X return;
- X }
- X
- X /* This is a change */
- X changes++;
- X significant = TRUE;
- X
- X /* if this is a multi-line change, then we'll have to redraw */
- X if (markline(frommark) != markline(tomark))
- X {
- X mustredraw = TRUE;
- X redrawrange(markline(frommark), markline(tomark), markline(frommark));
- X }
- X
- X /* adjust marks 'a through 'z and '' as needed */
- X l = markline(tomark);
- X for (i = 0; i < NMARKS; i++)
- X {
- X if (mark[i] < frommark)
- X {
- X continue;
- X }
- X else if (mark[i] < tomark)
- X {
- X mark[i] = MARK_UNSET;
- X }
- X else if (markline(mark[i]) == l)
- X {
- X if (markline(frommark) == l)
- X {
- X mark[i] -= markidx(tomark) - markidx(frommark);
- X }
- X else
- X {
- X mark[i] -= markidx(tomark);
- X }
- X }
- X else
- X {
- X mark[i] -= MARK_AT_LINE(l - markline(frommark));
- X }
- X }
- X
- X /* Reporting... */
- X if (markidx(frommark) == 0 && markidx(tomark) == 0)
- X {
- X rptlines = markline(tomark) - markline(frommark);
- X rptlabel = "deleted";
- X }
- X
- X /* find the block containing frommark */
- X l = markline(frommark);
- X for (i = 1; lnum[i] < l; i++)
- X {
- X }
- X
- X /* process each affected block... */
- X for (m = frommark;
- X m < tomark && lnum[i] < INFINITY;
- X m = MARK_AT_LINE(lnum[i - 1] + 1))
- X {
- X /* fetch the block */
- X blk = blkget(i);
- X
- X /* find the mark in the block */
- X scan = blk->c;
- X for (l = markline(m) - lnum[i - 1] - 1; l > 0; l--)
- X {
- X while (*scan++ != '\n')
- X {
- X }
- X }
- X scan += markidx(m);
- X
- X /* figure out where the changes to this block end */
- X if (markline(tomark) > lnum[i])
- X {
- X cpy = blk->c + BLKSIZE;
- X }
- X else if (markline(tomark) == markline(m))
- X {
- X cpy = scan - markidx(m) + markidx(tomark);
- X }
- X else
- X {
- X cpy = scan;
- X for (l = markline(tomark) - markline(m);
- X l > 0;
- X l--)
- X {
- X while (*cpy++ != '\n')
- X {
- X }
- X }
- X cpy += markidx(tomark);
- X }
- X
- X /* delete the stuff by moving chars within this block */
- X while (cpy < blk->c + BLKSIZE)
- X {
- X *scan++ = *cpy++;
- X }
- X while (scan < blk->c + BLKSIZE)
- X {
- X *scan++ = '\0';
- X }
- X
- X /* adjust tomark to allow for lines deleted from this block */
- X tomark -= MARK_AT_LINE(lnum[i] + 1 - markline(m));
- X
- X /* if this block isn't empty now, then advance i */
- X if (*blk->c)
- X {
- X i++;
- X }
- X
- X /* the buffer has changed. Update hdr and lnum. */
- X blkdirty(blk);
- X }
- X
- X /* must have at least 1 line */
- X if (nlines == 0)
- X {
- X blk = blkadd(1);
- X blk->c[0] = '\n';
- X blkdirty(blk);
- X cursor = MARK_FIRST;
- X }
- X}
- X
- X
- X/* add some text at a specific place in the file */
- Xvoid add(atmark, newtext)
- X MARK atmark; /* where to insert the new text */
- X char *newtext; /* NUL-terminated string to insert */
- X{
- X REG char *scan; /* used to move through string */
- X REG char *build; /* used while copying chars */
- X int addlines; /* number of lines we're adding */
- X int lastpart; /* size of last partial line */
- X BLK *blk; /* the block to be modified */
- X int blkno; /* the logical block# of (*blk) */
- X REG char *newptr; /* where new text starts in blk */
- X BLK buf; /* holds chars from orig blk */
- X BLK linebuf; /* holds part of line that didn't fit */
- X BLK *following; /* the BLK following the last BLK */
- X int i;
- X long l;
- X
- X#ifdef DEBUG
- X debout("add(%ld.%d, \"%s\")\n", markline(atmark), markidx(atmark), newtext);
- X#endif
- X#ifdef lint
- X buf.c[0] = 0;
- X#endif
- X /* if not adding anything, return now */
- X if (!*newtext)
- X {
- X return;
- X }
- X
- X /* This is a change */
- X changes++;
- X significant = TRUE;
- X
- X /* count the number of lines in the new text */
- X for (scan = newtext, lastpart = addlines = 0; *scan; )
- X {
- X if (*scan++ == '\n')
- X {
- X addlines++;
- X lastpart = 0;
- X }
- X else
- X {
- X lastpart++;
- X }
- X }
- X
- X /* Reporting... */
- X if (lastpart == 0 && markidx(atmark) == 0)
- X {
- X rptlines = addlines;
- X rptlabel = "added";
- X }
- X
- X /* extract the line# from atmark */
- X l = markline(atmark);
- X
- X /* if more than 0 lines, then we'll have to redraw the screen */
- X if (addlines > 0)
- X {
- X mustredraw = TRUE;
- X if (markidx(atmark) == 0 && lastpart == 0)
- X {
- X redrawrange(l, l, l + addlines);
- X }
- X else
- X {
- X /* make sure the last line gets redrawn -- it was
- X * split, so its appearance has changed
- X */
- X redrawrange(l, l + 1L, l + addlines + 1L);
- X }
- X }
- X
- X /* adjust marks 'a through 'z and '' as needed */
- X for (i = 0; i < NMARKS; i++)
- X {
- X if (mark[i] < atmark)
- X {
- X /* earlier line, or earlier in same line: no change */
- X continue;
- X }
- X else if (markline(mark[i]) > l)
- X {
- X /* later line: move down a whole number of lines */
- X mark[i] += MARK_AT_LINE(addlines);
- X }
- X else
- X {
- X /* later in same line */
- X if (addlines > 0)
- X {
- X /* multi-line add, which split this line:
- X * move down, and possibly left or right,
- X * depending on where the split was and how
- X * much text was inserted after the last \n
- X */
- X mark[i] += MARK_AT_LINE(addlines) + lastpart - markidx(atmark);
- X }
- X else
- X {
- X /* totally within this line: move right */
- X mark[i] += lastpart;
- X }
- X }
- X }
- X
- X /* get the block to be modified */
- X for (blkno = 1; lnum[blkno] < l && lnum[blkno + 1] < INFINITY; blkno++)
- X {
- X }
- X blk = blkget(blkno);
- X buf = *blk;
- X
- X /* figure out where the new text starts */
- X for (newptr = buf.c, l = markline(atmark) - lnum[blkno - 1] - 1;
- X l > 0;
- X l--)
- X {
- X while (*newptr++ != '\n')
- X {
- X }
- X }
- X newptr += markidx(atmark);
- X
- X /* keep start of old block */
- X build = blk->c + (newptr - buf.c);
- X
- X /* fill this block (or blocks) from the newtext string */
- X while (*newtext)
- X {
- X while (*newtext && build < blk->c + BLKSIZE - 1)
- X {
- X *build++ = *newtext++;
- X }
- X if (*newtext)
- X {
- X /* save the excess */
- X for (scan = linebuf.c + BLKSIZE;
- X build > blk->c && build[-1] != '\n';
- X )
- X {
- X *--scan = *--build;
- X }
- X
- X /* write the block */
- X while (build < blk->c + BLKSIZE)
- X {
- X *build++ = '\0';
- X }
- X blkdirty(blk);
- X
- X /* add another block */
- X blkno++;
- X blk = blkadd(blkno);
- X
- X /* copy in the excess from last time */
- X for (build = blk->c; scan < linebuf.c + BLKSIZE; )
- X {
- X *build++ = *scan++;
- X }
- X }
- X }
- X
- X /* fill this block(s) from remainder of orig block */
- X while (newptr < buf.c + BLKSIZE && *newptr)
- X {
- X while (newptr < buf.c + BLKSIZE
- X && *newptr
- X && build < blk->c + BLKSIZE - 1)
- X {
- X *build++ = *newptr++;
- X }
- X if (newptr < buf.c + BLKSIZE && *newptr)
- X {
- X /* save the excess */
- X for (scan = linebuf.c + BLKSIZE;
- X build > blk->c && build[-1] != '\n';
- X )
- X {
- X *--scan = *--build;
- X }
- X
- X /* write the block */
- X while (build < blk->c + BLKSIZE)
- X {
- X *build++ = '\0';
- X }
- X blkdirty(blk);
- X
- X /* add another block */
- X blkno++;
- X blk = blkadd(blkno);
- X
- X /* copy in the excess from last time */
- X for (build = blk->c; scan < linebuf.c + BLKSIZE; )
- X {
- X *build++ = *scan++;
- X }
- X }
- X }
- X
- X /* see if we can combine our last block with the following block */
- X if (lnum[blkno] < nlines && lnum[blkno + 1] - lnum[blkno] < (BLKSIZE >> 6))
- X {
- X /* hey, we probably can! Get the following block & see... */
- X following = blkget(blkno + 1);
- X if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
- X {
- X /* we can! Copy text from following to blk */
- X for (scan = following->c; *scan; )
- X {
- X *build++ = *scan++;
- X }
- X while (build < blk->c + BLKSIZE)
- X {
- X *build++ = '\0';
- X }
- X blkdirty(blk);
- X
- X /* pretend the following was the last blk */
- X blk = following;
- X build = blk->c;
- X }
- X }
- X
- X /* that last block is dirty by now */
- X while (build < blk->c + BLKSIZE)
- X {
- X *build++ = '\0';
- X }
- X blkdirty(blk);
- X}
- X
- X
- X/* change the text of a file */
- Xvoid change(frommark, tomark, newtext)
- X MARK frommark, tomark;
- X char *newtext;
- X{
- X int i;
- X long l;
- X char *text;
- X BLK *blk;
- X
- X#ifdef DEBUG
- X debout("change(%ld.%d, %ld.%d, \"%s\")\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark), newtext);
- X#endif
- X
- X /* optimize for single-character replacement */
- X if (frommark + 1 == tomark && newtext[0] && !newtext[1] && newtext[0] != '\n')
- X {
- X /* find the block containing frommark */
- X l = markline(frommark);
- X for (i = 1; lnum[i] < l; i++)
- X {
- X }
- X
- X /* get the block */
- X blk = blkget(i);
- X
- X /* find the line within the block */
- X for (text = blk->c, i = l - lnum[i - 1] - 1; i > 0; text++)
- X {
- X if (*text == '\n')
- X {
- X i--;
- X }
- X }
- X
- X /* replace the char */
- X text += markidx(frommark);
- X if (*text == newtext[0])
- X {
- X /* no change was needed - same char */
- X return;
- X }
- X else if (*text != '\n')
- X {
- X /* This is a change */
- X changes++;
- X significant = TRUE;
- X ChangeText
- X {
- X *text = newtext[0];
- X blkdirty(blk);
- X }
- X return;
- X }
- X /* else it is a complex change involving newline... */
- X }
- X
- X /* couldn't optimize, so do delete & add */
- X ChangeText
- X {
- X delete(frommark, tomark);
- X add(frommark, newtext);
- X rptlabel = "changed";
- X }
- X}
- eof
- if test `wc -c <modify.c` -ne 9893
- then
- echo modify.c damaged!
- fi
- fi
-
- if test -f move1.c -a "$1" != -f
- then
- echo Will not overwrite move1.c
- else
- echo Extracting move1.c
- sed 's/^X//' >move1.c <<\eof
- X/* move1.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains most movement functions */
- X
- X#include "config.h"
- X#include <ctype.h>
- X#include "vi.h"
- X
- X#ifndef isascii
- X# define isascii(c) !((c) & ~0x7f)
- X#endif
- X
- XMARK m_updnto(m, cnt, cmd)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X DEFAULT(cmd == 'G' ? nlines : 1L);
- X
- X /* move up or down 'cnt' lines */
- X switch (cmd)
- X {
- X case ('P'&0x1f):
- X case '-':
- X case 'k':
- X m -= MARK_AT_LINE(cnt);
- X break;
- X
- X case 'G':
- X if (cnt < 1L || cnt > nlines)
- X {
- X msg("Only %ld lines", nlines);
- X return MARK_UNSET;
- X }
- X m = MARK_AT_LINE(cnt);
- X break;
- X
- X default:
- X m += MARK_AT_LINE(cnt);
- X }
- X
- X /* if that left us screwed up, then fail */
- X if (m < MARK_FIRST || markline(m) > nlines)
- X {
- X return MARK_UNSET;
- X }
- X
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_right(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X int idx; /* index of the new cursor position */
- X
- X DEFAULT(1);
- X
- X /* move to right, if that's OK */
- X pfetch(markline(m));
- X idx = markidx(m) + cnt;
- X if (idx < plen)
- X {
- X m += cnt;
- X }
- X else
- X {
- X return MARK_UNSET;
- X }
- X
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_left(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X DEFAULT(1);
- X
- X /* move to the left, if that's OK */
- X if (markidx(m) >= cnt)
- X {
- X m -= cnt;
- X }
- X else
- X {
- X return MARK_UNSET;
- X }
- X
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_tocol(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X char *text; /* text of the line */
- X int col; /* column number */
- X int idx; /* index into the line */
- X
- X DEFAULT(1);
- X
- X /* internally, columns are numbered 0..COLS-1, not 1..COLS */
- X cnt--;
- X
- X /* if 0, that's easy */
- X if (cnt == 0)
- X {
- X m &= ~(BLKSIZE - 1);
- X return m;
- X }
- X
- X /* find that column within the line */
- X pfetch(markline(m));
- X text = ptext;
- X for (col = idx = 0; col < cnt && *text; text++, idx++)
- X {
- X if (*text == '\t' && !*o_list)
- X {
- X col += *o_tabstop;
- X col -= col % *o_tabstop;
- X }
- X else if (UCHAR(*text) < ' ' || *text == '\177')
- X {
- X col += 2;
- X }
- X#ifndef NO_CHARATTR
- X else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
- X {
- X text += 2; /* plus one more as part of for loop */
- X }
- X#endif
- X else
- X {
- X col++;
- X }
- X }
- X if (!*text)
- X {
- X return MARK_UNSET;
- X }
- X else
- X {
- X m = (m & ~(BLKSIZE - 1)) + idx;
- X }
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_front(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument (ignored) */
- X{
- X char *scan;
- X
- X /* move to the first non-whitespace character */
- X pfetch(markline(m));
- X scan = ptext;
- X m &= ~(BLKSIZE - 1);
- X while (*scan == ' ' || *scan == '\t')
- X {
- X scan++;
- X m++;
- X }
- X
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_rear(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument (ignored) */
- X{
- X /* Try to move *EXTREMELY* far to the right. It is fervently hoped
- X * that other code will convert this to a more reasonable MARK before
- X * anything tries to actually use it. (See adjmove() in vi.c)
- X */
- X return m | (BLKSIZE - 1);
- X}
- X
- X#ifndef NO_SENTENCE
- X/*ARGSUSED*/
- XMARK m_fsentence(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X REG char *text;
- X REG long l;
- X
- X DEFAULT(1);
- X
- X /* get the current line */
- X l = markline(m);
- X pfetch(l);
- X text = ptext + markidx(m);
- X
- X /* for each requested sentence... */
- X while (cnt-- > 0)
- X {
- X /* search forward for one of [.?!] followed by spaces or EOL */
- X do
- X {
- X /* wrap at end of line */
- X if (!text[0])
- X {
- X if (l >= nlines)
- X {
- X return MARK_UNSET;
- X }
- X l++;
- X pfetch(l);
- X text = ptext;
- X }
- X else
- X {
- X text++;
- X }
- X } while (text[0] != '.' && text[0] != '?' && text[0] != '!'
- X || text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
- X }
- X
- X /* construct a mark for this location */
- X m = buildmark(text);
- X
- X /* move forward to the first word of the next sentence */
- X m = m_fword(m, 1L);
- X
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_bsentence(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X REG char *text; /* used to scan thru text */
- X REG long l; /* current line number */
- X int flag; /* have we passed at least one word? */
- X
- X DEFAULT(1);
- X
- X /* get the current line */
- X l = markline(m);
- X pfetch(l);
- X text = ptext + markidx(m);
- X
- X /* for each requested sentence... */
- X flag = TRUE;
- X while (cnt-- > 0)
- X {
- X /* search backward for one of [.?!] followed by spaces or EOL */
- X do
- X {
- X /* wrap at beginning of line */
- X if (text == ptext)
- X {
- X do
- X {
- X if (l <= 1)
- X {
- X return MARK_UNSET;
- X }
- X l--;
- X pfetch(l);
- X } while (!*ptext);
- X text = ptext + plen - 1;
- X }
- X else
- X {
- X text--;
- X }
- X
- X /* are we moving past a "word"? */
- X if (text[0] >= '0')
- X {
- X flag = FALSE;
- X }
- X } while (flag || text[0] != '.' && text[0] != '?' && text[0] != '!'
- X || text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
- X }
- X
- X /* construct a mark for this location */
- X m = buildmark(text);
- X
- X /* move to the front of the following sentence */
- X m = m_fword(m, 1L);
- X
- X return m;
- X}
- X#endif
- X
- X/*ARGSUSED*/
- XMARK m_fparagraph(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X char *text;
- X char *pscn; /* used to scan thru value of "paragraphs" option */
- X long l;
- X
- X DEFAULT(1);
- X
- X for (l = markline(m); cnt > 0 && l++ < nlines; )
- X {
- X text = fetchline(l);
- X if (!*text)
- X {
- X cnt--;
- X }
- X#ifndef NO_SENTENCE
- X else if (*text == '.')
- X {
- X for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
- X {
- X if (pscn[0] == text[1] && pscn[1] == text[2])
- X {
- X cnt--;
- X break;
- X }
- X }
- X }
- X#endif
- X }
- X if (l <= nlines)
- X {
- X m = MARK_AT_LINE(l);
- X }
- X else
- X {
- X m = MARK_LAST;
- X }
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_bparagraph(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X{
- X char *text;
- X char *pscn; /* used to scan thru value of "paragraph" option */
- X long l;
- X
- X DEFAULT(1);
- X
- X for (l = markline(m); cnt > 0 && l-- > 1; )
- X {
- X text = fetchline(l);
- X if (!*text)
- X {
- X cnt--;
- X }
- X#ifndef NO_SENTENCE
- X else if (*text == '.')
- X {
- X for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
- X {
- X if (pscn[0] == text[1] && pscn[1] == text[2])
- X {
- X cnt--;
- X break;
- X }
- X }
- X }
- X#endif
- X }
- X if (l >= 1)
- X {
- X m = MARK_AT_LINE(l);
- X }
- X else
- X {
- X m = MARK_FIRST;
- X }
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_fsection(m, cnt, key)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* (ignored) */
- X int key; /* second key stroke - must be ']' */
- X{
- X char *text;
- X char *sscn; /* used to scan thru value of "sections" option */
- X long l;
- X
- X /* make sure second key was ']' */
- X if (key != ']')
- X {
- X return MARK_UNSET;
- X }
- X
- X for (l = markline(m); l++ < nlines; )
- X {
- X text = fetchline(l);
- X if (*text == '{')
- X {
- X break;
- X }
- X#ifndef NO_SENTENCE
- X else if (*text == '.')
- X {
- X for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
- X {
- X if (sscn[0] == text[1] && sscn[1] == text[2])
- X {
- X goto BreakBreak;
- X }
- X }
- X }
- X#endif
- X }
- XBreakBreak:
- X if (l <= nlines)
- X {
- X m = MARK_AT_LINE(l);
- X }
- X else
- X {
- X m = MARK_LAST;
- X }
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_bsection(m, cnt, key)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* (ignored) */
- X int key; /* second key stroke - must be '[' */
- X{
- X char *text;
- X char *sscn; /* used to scan thru value of "sections" option */
- X long l;
- X
- X /* make sure second key was '[' */
- X if (key != '[')
- X {
- X return MARK_UNSET;
- X }
- X
- X for (l = markline(m); l-- > 1; )
- X {
- X text = fetchline(l);
- X if (*text == '{')
- X {
- X break;
- X }
- X#ifndef NO_SENTENCE
- X else if (*text == '.')
- X {
- X for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
- X {
- X if (sscn[0] == text[1] && sscn[1] == text[2])
- X {
- X goto BreakBreak;
- X }
- X }
- X }
- X#endif
- X }
- XBreakBreak:
- X if (l >= 1)
- X {
- X m = MARK_AT_LINE(l);
- X }
- X else
- X {
- X m = MARK_FIRST;
- X }
- X return m;
- X}
- X
- X
- X/*ARGSUSED*/
- XMARK m_match(m, cnt)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument (ignored) */
- X{
- X long l;
- X REG char *text;
- X REG char match;
- X REG char nest;
- X REG int count;
- X
- X /* get the current line */
- X l = markline(m);
- X pfetch(l);
- X text = ptext + markidx(m);
- X
- X /* search forward within line for one of "[](){}" */
- X for (match = '\0'; !match && *text; text++)
- X {
- X /* tricky way to recognize 'em in ASCII */
- X nest = *text;
- X if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
- X {
- X match = nest ^ ('[' ^ ']');
- X }
- X else if ((nest & 0xfe) == '(')
- X {
- X match = nest ^ ('(' ^ ')');
- X }
- X else
- X {
- X match = 0;
- X }
- X }
- X if (!match)
- X {
- X return MARK_UNSET;
- X }
- X text--;
- X
- X /* search forward or backward for match */
- X if (match == '(' || match == '[' || match == '{')
- X {
- X /* search backward */
- X for (count = 1; count > 0; )
- X {
- X /* wrap at beginning of line */
- X if (text == ptext)
- X {
- X do
- X {
- X if (l <= 1L)
- X {
- X return MARK_UNSET;
- X }
- X l--;
- X pfetch(l);
- X } while (!*ptext);
- X text = ptext + plen - 1;
- X }
- X else
- X {
- X text--;
- X }
- X
- X /* check the char */
- X if (*text == match)
- X count--;
- X else if (*text == nest)
- X count++;
- X }
- X }
- X else
- X {
- X /* search forward */
- X for (count = 1; count > 0; )
- X {
- X /* wrap at end of line */
- X if (!*text)
- X {
- X if (l >= nlines)
- X {
- X return MARK_UNSET;
- X }
- X l++;
- X pfetch(l);
- X text = ptext;
- X }
- X else
- X {
- X text++;
- X }
- X
- X /* check the char */
- X if (*text == match)
- X count--;
- X else if (*text == nest)
- X count++;
- X }
- X }
- X
- X /* construct a mark for this place */
- X m = buildmark(text);
- X return m;
- X}
- X
- X/*ARGSUSED*/
- XMARK m_tomark(m, cnt, key)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* (ignored) */
- X int key; /* keystroke - the mark to move to */
- X{
- X /* mark '' is a special case */
- X if (key == '\'' || key == '`')
- X {
- X if (mark[26] == MARK_UNSET)
- X {
- X return MARK_FIRST;
- X }
- X else
- X {
- X return mark[26];
- X }
- X }
- X
- X /* if not a valid mark number, don't move */
- X if (key < 'a' || key > 'z')
- X {
- X return MARK_UNSET;
- X }
- X
- X /* return the selected mark -- may be MARK_UNSET */
- X if (!mark[key - 'a'])
- X {
- X msg("mark '%c is unset", key);
- X }
- X return mark[key - 'a'];
- X}
- X
- eof
- if test `wc -c <move1.c` -ne 10230
- then
- echo move1.c damaged!
- fi
- fi
-
- if test -f move2.c -a "$1" != -f
- then
- echo Will not overwrite move2.c
- else
- echo Extracting move2.c
- sed 's/^X//' >move2.c <<\eof
- X/* move2.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This function contains the movement functions that perform RE searching */
- X
- X#include "config.h"
- X#include "vi.h"
- X#include "regexp.h"
- X
- Xextern long atol();
- X
- Xstatic regexp *re; /* compiled version of the pattern to search for */
- Xstatic prevsf; /* boolean: previous search direction was forward? */
- X
- XMARK m_nsrch(m)
- X MARK m; /* where to start searching */
- X{
- X if (prevsf)
- X {
- X m = m_fsrch(m, (char *)0);
- X prevsf = TRUE;
- X }
- X else
- X {
- X m = m_bsrch(m, (char *)0);
- X prevsf = FALSE;
- X }
- X return m;
- X}
- X
- XMARK m_Nsrch(m)
- X MARK m; /* where to start searching */
- X{
- X if (prevsf)
- X {
- X m = m_bsrch(m, (char *)0);
- X prevsf = TRUE;
- X }
- X else
- X {
- X m = m_fsrch(m, (char *)0);
- X prevsf = FALSE;
- X }
- X return m;
- X}
- X
- XMARK m_fsrch(m, ptrn)
- X MARK m; /* where to start searching */
- X char *ptrn; /* pattern to search for */
- X{
- X long l; /* line# of line to be searched */
- X char *line; /* text of line to be searched */
- X int wrapped;/* boolean: has our search wrapped yet? */
- X int pos; /* where we are in the line */
- X long delta; /* line offset, for things like "/foo/+1" */
- X
- X /* remember: "previous search was forward" */
- X prevsf = TRUE;
- X
- X delta = 0L;
- X if (ptrn && *ptrn)
- X {
- X /* locate the closing '/', if any */
- X line = parseptrn(ptrn);
- X if (*line)
- X {
- X delta = atol(line);
- X }
- X ptrn++;
- X
- X /* free the previous pattern */
- X if (re) free(re);
- X
- X /* compile the pattern */
- X re = regcomp(ptrn);
- X if (!re)
- X {
- X return MARK_UNSET;
- X }
- X }
- X else if (!re)
- X {
- X msg("No previous expression");
- X return MARK_UNSET;
- X }
- X
- X /* search forward for the pattern */
- X pos = markidx(m) + 1;
- X pfetch(markline(m));
- X if (pos >= plen)
- X {
- X pos = 0;
- X m = (m | (BLKSIZE - 1)) + 1;
- X }
- X wrapped = FALSE;
- X for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
- X {
- X /* wrap search */
- X if (l > nlines)
- X {
- X /* if we wrapped once already, then the search failed */
- X if (wrapped)
- X {
- X break;
- X }
- X
- X /* else maybe we should wrap now? */
- X if (*o_wrapscan)
- X {
- X l = 0;
- X wrapped = TRUE;
- X continue;
- X }
- X else
- X {
- X break;
- X }
- X }
- X
- X /* get this line */
- X line = fetchline(l);
- X
- X /* check this line */
- X if (regexec(re, &line[pos], (pos == 0)))
- X {
- X /* match! */
- X if (wrapped && *o_warn)
- X msg("(wrapped)");
- X if (delta != 0L)
- X {
- X l += delta;
- X if (l < 1 || l > nlines)
- X {
- X msg("search offset too big");
- X return MARK_UNSET;
- X }
- X return m_front(MARK_AT_LINE(l), 0L);
- X }
- X return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
- X }
- X pos = 0;
- X }
- X
- X /* not found */
- X msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
- X return MARK_UNSET;
- X}
- X
- XMARK m_bsrch(m, ptrn)
- X MARK m; /* where to start searching */
- X char *ptrn; /* pattern to search for */
- X{
- X long l; /* line# of line to be searched */
- X char *line; /* text of line to be searched */
- X int wrapped;/* boolean: has our search wrapped yet? */
- X int pos; /* last acceptable idx for a match on this line */
- X int last; /* remembered idx of the last acceptable match on this line */
- X int try; /* an idx at which we strat searching for another match */
- X
- X /* remember: "previous search was not forward" */
- X prevsf = FALSE;
- X
- X if (ptrn && *ptrn)
- X {
- X /* locate the closing '?', if any */
- X line = parseptrn(ptrn);
- X ptrn++;
- X
- X /* free the previous pattern, if any */
- X if (re) free(re);
- X
- X /* compile the pattern */
- X re = regcomp(ptrn);
- X if (!re)
- X {
- X return MARK_UNSET;
- X }
- X }
- X else if (!re)
- X {
- X msg("No previous expression");
- X return MARK_UNSET;
- X }
- X
- X /* search backward for the pattern */
- X pos = markidx(m);
- X wrapped = FALSE;
- X for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
- X {
- X /* wrap search */
- X if (l < 1)
- X {
- X if (*o_wrapscan)
- X {
- X l = nlines + 1;
- X wrapped = TRUE;
- X continue;
- X }
- X else
- X {
- X break;
- X }
- X }
- X
- X /* get this line */
- X line = fetchline(l);
- X
- X /* check this line */
- X if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
- X {
- X /* match! now find the last acceptable one in this line */
- X do
- X {
- X last = (int)(re->startp[0] - line);
- X try = (int)(re->endp[0] - line);
- X } while (try > 0
- X && regexec(re, &line[try], FALSE)
- X && (int)(re->startp[0] - line) < pos);
- X
- X if (wrapped && *o_warn)
- X msg("(wrapped)");
- X return MARK_AT_LINE(l) + last;
- X }
- X pos = BLKSIZE;
- X }
- X
- X /* not found */
- X msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
- X return MARK_UNSET;
- X}
- X
- eof
- if test `wc -c <move2.c` -ne 4445
- then
- echo move2.c damaged!
- fi
- fi
-
- if test -f move3.c -a "$1" != -f
- then
- echo Will not overwrite move3.c
- else
- echo Extracting move3.c
- sed 's/^X//' >move3.c <<\eof
- X/* move3.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains movement functions that perform character searches */
- X
- X#include "config.h"
- X#include "vi.h"
- X
- X#ifndef NO_CHARSEARCH
- Xstatic MARK (*prevfwdfn)(); /* function to search in same direction */
- Xstatic MARK (*prevrevfn)(); /* function to search in opposite direction */
- Xstatic char prev_key; /* sought cvhar from previous [fFtT] */
- X
- XMARK m__ch(m, cnt, cmd)
- X MARK m; /* current position */
- X long cnt;
- X char cmd; /* command: either ',' or ';' */
- X{
- X MARK (*tmp)();
- X
- X if (!prevfwdfn)
- X {
- X msg("No previous f, F, t, or T command");
- X return MARK_UNSET;
- X }
- X
- X if (cmd == ',')
- X {
- X m = (*prevrevfn)(m, cnt, prev_key);
- X
- X /* Oops! we didn't want to change the prev*fn vars! */
- X tmp = prevfwdfn;
- X prevfwdfn = prevrevfn;
- X prevrevfn = tmp;
- X
- X return m;
- X }
- X else
- X {
- X return (*prevfwdfn)(m, cnt, prev_key);
- X }
- X}
- X
- X/* move forward within this line to next occurrence of key */
- XMARK m_fch(m, cnt, key)
- X MARK m; /* where to search from */
- X long cnt;
- X char key; /* what to search for */
- X{
- X REG char *text;
- X
- X DEFAULT(1);
- X
- X prevfwdfn = m_fch;
- X prevrevfn = m_Fch;
- X prev_key = key;
- X
- X pfetch(markline(m));
- X text = ptext + markidx(m);
- X while (cnt-- > 0)
- X {
- X do
- X {
- X m++;
- X text++;
- X } while (*text && *text != key);
- X }
- X if (!*text)
- X {
- X return MARK_UNSET;
- X }
- X return m;
- X}
- X
- X/* move backward within this line to previous occurrence of key */
- XMARK m_Fch(m, cnt, key)
- X MARK m; /* where to search from */
- X long cnt;
- X char key; /* what to search for */
- X{
- X REG char *text;
- X
- X DEFAULT(1);
- X
- X prevfwdfn = m_Fch;
- X prevrevfn = m_fch;
- X prev_key = key;
- X
- X pfetch(markline(m));
- X text = ptext + markidx(m);
- X while (cnt-- > 0)
- X {
- X do
- X {
- X m--;
- X text--;
- X } while (text >= ptext && *text != key);
- X }
- X if (text < ptext)
- X {
- X return MARK_UNSET;
- X }
- X return m;
- X}
- X
- X/* move forward within this line almost to next occurrence of key */
- XMARK m_tch(m, cnt, key)
- X MARK m; /* where to search from */
- X long cnt;
- X char key; /* what to search for */
- X{
- X /* skip the adjacent char */
- X pfetch(markline(m));
- X if (plen <= markidx(m))
- X {
- X return MARK_UNSET;
- X }
- X m++;
- X
- X m = m_fch(m, cnt, key);
- X if (m == MARK_UNSET)
- X {
- X return MARK_UNSET;
- X }
- X
- X prevfwdfn = m_tch;
- X prevrevfn = m_Tch;
- X
- X return m - 1;
- X}
- X
- X/* move backward within this line almost to previous occurrence of key */
- XMARK m_Tch(m, cnt, key)
- X MARK m; /* where to search from */
- X long cnt;
- X char key; /* what to search for */
- X{
- X /* skip the adjacent char */
- X if (markidx(m) == 0)
- X {
- X return MARK_UNSET;
- X }
- X m--;
- X
- X m = m_Fch(m, cnt, key);
- X if (m == MARK_UNSET)
- X {
- X return MARK_UNSET;
- X }
- X
- X prevfwdfn = m_Tch;
- X prevrevfn = m_tch;
- X
- X return m + 1;
- X}
- X#endif
- eof
- if test `wc -c <move3.c` -ne 2697
- then
- echo move3.c damaged!
- fi
- fi
-
- if test -f move4.c -a "$1" != -f
- then
- echo Will not overwrite move4.c
- else
- echo Extracting move4.c
- sed 's/^X//' >move4.c <<\eof
- X/* move4.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains movement functions which are screen-relative */
- X
- X#include "config.h"
- X#include "vi.h"
- X
- X/* This moves the cursor to a particular row on the screen */
- X/*ARGSUSED*/
- XMARK m_row(m, cnt, key)
- X MARK m; /* the cursor position */
- X long cnt; /* the row we'll move to */
- X int key; /* the keystroke of this move - H/L/M */
- X{
- X DEFAULT(1);
- X
- X /* calculate destination line based on key */
- X cnt--;
- X switch (key)
- X {
- X case 'H':
- X cnt = topline + cnt;
- X break;
- X
- X case 'M':
- X cnt = topline + (LINES - 1) / 2;
- X break;
- X
- X case 'L':
- X cnt = botline - cnt;
- X break;
- X }
- X
- X /* return the mark of the destination line */
- X return MARK_AT_LINE(cnt);
- X}
- X
- X
- X/* This function repositions the current line to show on a given row */
- X/*ARGSUSED*/
- XMARK m_z(m, cnt, key)
- X MARK m; /* the cursor */
- X long cnt; /* the line number we're repositioning */
- X int key; /* key struck after the z */
- X{
- X long newtop;
- X
- X /* Which line are we talking about? */
- X if (cnt < 0 || cnt > nlines)
- X {
- X return MARK_UNSET;
- X }
- X if (cnt)
- X {
- X m = MARK_AT_LINE(cnt);
- X newtop = cnt;
- X }
- X else
- X {
- X newtop = markline(m);
- X }
- X
- X /* allow a "window size" number to be entered, but ignore it */
- X while (key >= '0' && key <= '9')
- X {
- X key = getkey(0);
- X }
- X
- X /* figure out which line will have to be at the top of the screen */
- X switch (key)
- X {
- X case '\n':
- X#if OSK
- X case '\l':
- X#else
- X case '\r':
- X#endif
- X case '+':
- X break;
- X
- X case '.':
- X case 'z':
- X newtop -= LINES / 2;
- X break;
- X
- X case '-':
- X newtop -= LINES - 1;
- X break;
- X
- X default:
- X return MARK_UNSET;
- X }
- X
- X /* make the new topline take effect */
- X if (newtop >= 1)
- X {
- X topline = newtop;
- X }
- X else
- X {
- X topline = 1L;
- X }
- X mustredraw = TRUE;
- X
- X /* The cursor doesn't move */
- X return m;
- X}
- X
- X
- X/* This function scrolls the screen. It does this by calling redraw() with
- X * an off-screen line as the argument. It will move the cursor if necessary
- X * so that the cursor is on the new screen.
- X */
- X/*ARGSUSED*/
- XMARK m_scroll(m, cnt, key)
- X MARK m; /* the cursor position */
- X long cnt; /* for some keys: the number of lines to scroll */
- X int key; /* keystroke that causes this movement */
- X{
- X MARK tmp; /* a temporary mark, used as arg to redraw() */
- X
- X /* adjust cnt, and maybe *o_scroll, depending of key */
- X switch (key)
- X {
- X case ctrl('F'):
- X case ctrl('B'):
- X DEFAULT(1);
- X mustredraw = TRUE;
- X cnt = cnt * (LINES - 1) - 1; /* keeps one old line on screen */
- X break;
- X
- X case ctrl('E'):
- X case ctrl('Y'):
- X DEFAULT(1);
- X break;
- X
- X case ctrl('U'):
- X case ctrl('D'):
- X if (cnt == 0) /* default */
- X {
- X cnt = *o_scroll;
- X }
- X else
- X {
- X if (cnt > LINES - 1)
- X {
- X cnt = LINES - 1;
- X }
- X *o_scroll = cnt;
- X }
- X break;
- X }
- X
- X /* scroll up or down, depending on key */
- X switch (key)
- X {
- X case ctrl('B'):
- X case ctrl('Y'):
- X case ctrl('U'):
- X cnt = topline - cnt;
- X if (cnt < 1L)
- X {
- X cnt = 1L;
- X m = MARK_FIRST;
- X }
- X tmp = MARK_AT_LINE(cnt) + markidx(m);
- X redraw(tmp, FALSE);
- X if (markline(m) > botline)
- X {
- X m = MARK_AT_LINE(botline);
- X }
- X break;
- X
- X case ctrl('F'):
- X case ctrl('E'):
- X case ctrl('D'):
- X cnt = botline + cnt;
- X if (cnt > nlines)
- X {
- X cnt = nlines;
- X m = MARK_LAST;
- X }
- X tmp = MARK_AT_LINE(cnt) + markidx(m);
- X redraw(tmp, FALSE);
- X if (markline(m) < topline)
- X {
- X m = MARK_AT_LINE(topline);
- X }
- X break;
- X }
- X
- X /* arrange for ctrl-B and ctrl-F to redraw the smart line */
- X if (key == ctrl('B') || key == ctrl('F'))
- X {
- X changes++;
- X
- X /* also, erase the statusline. This happens naturally for
- X * the scrolling commands, but the paging commands need to
- X * explicitly clear the statusline.
- X */
- X msg("");
- X }
- X
- X return m;
- X}
- eof
- if test `wc -c <move4.c` -ne 3699
- then
- echo move4.c damaged!
- fi
- fi
-
- if test -f move5.c -a "$1" != -f
- then
- echo Will not overwrite move5.c
- else
- echo Extracting move5.c
- sed 's/^X//' >move5.c <<\eof
- X/* move5.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains the word-oriented movement functions */
- X
- X#include <ctype.h>
- X#include "config.h"
- X#include "vi.h"
- X
- X#ifndef isascii
- X# define isascii(c) !((c) & ~0x7f)
- X#endif
- X
- X
- XMARK m_fword(m, cnt, cmd)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X int cmd; /* either 'w' or 'W' */
- X{
- X REG long l;
- X REG char *text;
- X REG int i;
- X
- X DEFAULT(1);
- X
- X l = markline(m);
- X pfetch(l);
- X text = ptext + markidx(m);
- X while (cnt-- > 0) /* yes, ASSIGNMENT! */
- X {
- X i = *text++;
- X
- X if (cmd == 'W')
- X {
- X /* include any non-whitespace */
- X while (i && (!isascii(i) || !isspace(i)))
- X {
- X i = *text++;
- X }
- X }
- X else if (!isascii(i) || isalnum(i) || i == '_')
- X {
- X /* include an alphanumeric word */
- X while (i && (!isascii(i) || isalnum(i) || i == '_'))
- X {
- X i = *text++;
- X }
- X }
- X else
- X {
- X /* include contiguous punctuation */
- X while (i && isascii(i) && !isalnum(i) && !isspace(i))
- X {
- X i = *text++;
- X }
- X }
- X
- X /* include trailing whitespace */
- X while (!i || isascii(i) && isspace(i))
- X {
- X /* did we hit the end of this line? */
- X if (!i)
- X {
- X /* move to next line, if there is one */
- X l++;
- X if (l > nlines)
- X {
- X return MARK_UNSET;
- X }
- X pfetch(l);
- X text = ptext;
- X }
- X
- X i = *text++;
- X }
- X text--;
- X }
- X
- X /* construct a MARK for this place */
- X m = buildmark(text);
- X return m;
- X}
- X
- X
- XMARK m_bword(m, cnt, cmd)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X int cmd; /* either 'b' or 'B' */
- X{
- X REG long l;
- X REG char *text;
- X
- X DEFAULT(1);
- X
- X l = markline(m);
- X pfetch(l);
- X text = ptext + markidx(m);
- X while (cnt-- > 0) /* yes, ASSIGNMENT! */
- X {
- X text--;
- X
- X /* include preceding whitespace */
- X while (text < ptext || isascii(*text) && isspace(*text))
- X {
- X /* did we hit the end of this line? */
- X if (text < ptext)
- X {
- X /* move to preceding line, if there is one */
- X l--;
- X if (l <= 0)
- X {
- X return MARK_UNSET;
- X }
- X pfetch(l);
- X text = ptext + plen - 1;
- X }
- X else
- X {
- X text--;
- X }
- X }
- X
- X if (cmd == 'B')
- X {
- X /* include any non-whitespace */
- X while (text >= ptext && (!isascii(*text) || !isspace(*text)))
- X {
- X text--;
- X }
- X }
- X else if (!isascii(*text) || isalnum(*text) || *text == '_')
- X {
- X /* include an alphanumeric word */
- X while (text >= ptext && (!isascii(*text) || isalnum(*text) || *text == '_'))
- X {
- X text--;
- X }
- X }
- X else
- X {
- X /* include contiguous punctuation */
- X while (text >= ptext && isascii(*text) && !isalnum(*text) && !isspace(*text))
- X {
- X text--;
- X }
- X }
- X text++;
- X }
- X
- X /* construct a MARK for this place */
- X m = buildmark(text);
- X return m;
- X}
- X
- XMARK m_eword(m, cnt, cmd)
- X MARK m; /* movement is relative to this mark */
- X long cnt; /* a numeric argument */
- X int cmd; /* either 'e' or 'E' */
- X{
- X REG long l;
- X REG char *text;
- X REG int i;
- X
- X DEFAULT(1);
- X
- X l = markline(m);
- X pfetch(l);
- X text = ptext + markidx(m);
- X while (cnt-- > 0) /* yes, ASSIGNMENT! */
- X {
- X text++;
- X i = *text++;
- X
- X /* include preceding whitespace */
- X while (!i || isascii(i) && isspace(i))
- X {
- X /* did we hit the end of this line? */
- X if (!i)
- X {
- X /* move to next line, if there is one */
- X l++;
- X if (l > nlines)
- X {
- X return MARK_UNSET;
- X }
- X pfetch(l);
- X text = ptext;
- X }
- X
- X i = *text++;
- X }
- X
- X if (cmd == 'E')
- X {
- X /* include any non-whitespace */
- X while (i && (!isascii(i) || !isspace(i)))
- X {
- X i = *text++;
- X }
- X }
- X else if (!isascii(i) || isalnum(i) || i == '_')
- X {
- X /* include an alphanumeric word */
- X while (i && (!isascii(i) || isalnum(i) || i == '_'))
- X {
- X i = *text++;
- X }
- X }
- X else
- X {
- X /* include contiguous punctuation */
- X while (i && isascii(i) && !isalnum(i) && !isspace(i))
- X {
- X i = *text++;
- X }
- X }
- X text -= 2;
- X }
- X
- X /* construct a MARK for this place */
- X m = buildmark(text);
- X return m;
- X}
- eof
- if test `wc -c <move5.c` -ne 3940
- then
- echo move5.c damaged!
- fi
- fi
-
- if test -f opts.c -a "$1" != -f
- then
- echo Will not overwrite opts.c
- else
- echo Extracting opts.c
- sed 's/^X//' >opts.c <<\eof
- X/* opts.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains the code that manages the run-time options -- The
- X * values that can be modified via the "set" command.
- X */
- X
- X#include "config.h"
- X#include "vi.h"
- X#ifndef NULL
- X#define NULL (char *)0
- X#endif
- Xextern char *getenv();
- X
- X/* maximum width to permit for strings, including ="" */
- X#define MAXWIDTH 20
- X
- X/* These are the default values of all options */
- Xchar o_autoindent[1] = {FALSE};
- Xchar o_autoprint[1] = {TRUE};
- Xchar o_autowrite[1] = {FALSE};
- X#ifndef NO_ERRLIST
- Xchar o_cc[30] = {CC_COMMAND};
- X#endif
- X#ifndef NO_CHARATTR
- Xchar o_charattr[1] = {FALSE};
- X#endif
- Xchar o_columns[3] = {80, 32, 255};
- X#ifndef NO_DIGRAPH
- Xchar o_digraph[1] = {FALSE};
- X#endif
- Xchar o_directory[30] = TMPDIR;
- Xchar o_edcompatible[1] = {FALSE};
- Xchar o_errorbells[1] = {TRUE};
- Xchar o_exrefresh[1] = {TRUE};
- X#ifndef NO_DIGRAPH
- Xchar o_flipcase[80]
- X# if CS_IBMPC
- X = {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
- X# endif
- X# if CS_LATIN1
- X /* initialized by initopts() */
- X# endif
- X ;
- X#endif
- X#ifndef NO_SENTENCE
- Xchar o_hideformat[1] = {FALSE};
- X#endif
- Xchar o_ignorecase[1] = {FALSE};
- X#ifndef NO_EXTENSIONS
- Xchar o_inputmode[1] = {FALSE};
- X#endif
- Xchar o_keytime[3] = {2, 0, 5};
- Xchar o_keywordprg[80] = {KEYWORDPRG};
- Xchar o_lines[3] = {25, 2, 50}; /* More lines? Enlarge kbuf */
- Xchar o_list[1] = {FALSE};
- X#ifndef NO_MAGIC
- Xchar o_magic[1] = {TRUE};
- X#endif
- X#ifndef NO_ERRLIST
- Xchar o_make[30] = {MAKE_COMMAND};
- X#endif
- X#ifndef NO_MODELINE
- Xchar o_modeline[1] = {FALSE};
- X#endif
- X#ifndef NO_SENTENCE
- Xchar o_paragraphs[30] = "PPppIPLPQP";
- X#endif
- X#if MSDOS
- Xchar o_pcbios[1] = {TRUE};
- X#endif
- Xchar o_readonly[1] = {FALSE};
- Xchar o_report[3] = {5, 1, 127};
- Xchar o_scroll[3] = {12, 1, 127};
- X#ifndef NO_SENTENCE
- Xchar o_sections[30] = "NHSHSSSEse";
- X#endif
- Xchar o_shell[60] = SHELL;
- Xchar o_shiftwidth[3] = {8, 1, 255};
- X#ifndef NO_SHOWMATCH
- Xchar o_showmatch[1] = {FALSE};
- X#endif
- X#ifndef NO_SHOWMODE
- Xchar o_smd[1] = {FALSE};
- X#endif
- Xchar o_sidescroll[3] = {8, 1, 40};
- Xchar o_sync[1] = {NEEDSYNC};
- Xchar o_tabstop[3] = {8, 1, 40};
- Xchar o_term[30] = "?";
- Xchar o_vbell[1] = {TRUE};
- Xchar o_warn[1] = {TRUE};
- Xchar o_wrapmargin[3] = {0, 0, 255};
- Xchar o_wrapscan[1] = {TRUE};
- X
- X
- X/* The following describes the names & types of all options */
- X#define BOOL 0
- X#define NUM 1
- X#define STR 2
- X#define SET 0x01 /* this option has had its value altered */
- X#define CANSET 0x02 /* this option can be set at any time */
- X#define RCSET 0x06 /* this option can be set in a .exrc file only */
- X#define MR 0x40 /* does this option affect the way text is displayed? */
- Xstruct
- X{
- X char *name; /* name of an option */
- X char *nm; /* short name of an option */
- X char type; /* type of an option */
- X char flags; /* boolean: has this option been set? */
- X char *value; /* value */
- X}
- X opts[] =
- X{
- X /* name type flags redraw value */
- X { "autoindent", "ai", BOOL, CANSET , o_autoindent },
- X { "autoprint", "ap", BOOL, CANSET , o_autoprint },
- X { "autowrite", "aw", BOOL, CANSET , o_autowrite },
- X#ifndef NO_ERRLIST
- X { "cc", "cc", STR, CANSET , o_cc },
- X#endif
- X#ifndef NO_CHARATTR
- X { "charattr", "ca", BOOL, CANSET | MR, o_charattr },
- X#endif
- X { "columns", "co", NUM, SET , o_columns },
- X#ifndef NO_DIGRAPH
- X { "digraph", "dig", BOOL, CANSET , o_digraph },
- X#endif
- X { "directory", "dir", STR, RCSET , o_directory },
- X { "edcompatible","ed", BOOL, CANSET , o_edcompatible },
- X { "errorbells", "eb", BOOL, CANSET , o_errorbells },
- X { "exrefresh", "er", BOOL, CANSET , o_exrefresh },
- X#ifndef NO_DIGRAPH
- X { "flipcase", "fc", STR, CANSET , o_flipcase },
- X#endif
- X#ifndef NO_SENTENCE
- X { "hideformat", "hf", BOOL, CANSET | MR, o_hideformat },
- X#endif
- X { "ignorecase", "ic", BOOL, CANSET , o_ignorecase },
- X#ifndef NO_EXTENSIONS
- X { "inputmode", "im", BOOL, CANSET , o_inputmode },
- X#endif
- X { "keytime", "kt", NUM, CANSET , o_keytime },
- X { "keywordprg", "kp", STR, CANSET , o_keywordprg },
- X { "lines", "ls", NUM, SET , o_lines },
- X { "list", "li", BOOL, CANSET | MR, o_list },
- X#ifndef NO_MAGIC
- X { "magic", "ma", BOOL, CANSET , o_magic },
- X#endif
- X#ifndef NO_ERRLIST
- X { "make", "mk", STR, CANSET , o_make },
- X#endif
- X#ifndef NO_MODELINE
- X { "modeline", "ml", BOOL, CANSET , o_modeline },
- X#endif
- X#ifndef NO_SENTENCE
- X { "paragraphs", "pa", STR, CANSET , o_paragraphs },
- X#endif
- X#if MSDOS
- X { "pcbios", "pc", BOOL, SET , o_pcbios },
- X#endif
- X { "readonly", "ro", BOOL, CANSET , o_readonly },
- X { "report", "re", NUM, CANSET , o_report },
- X { "scroll", "sc", NUM, CANSET , o_scroll },
- X#ifndef NO_SENTENCE
- X { "sections", "se", STR, CANSET , o_sections },
- X#endif
- X { "shell", "sh", STR, CANSET , o_shell },
- X#ifndef NO_SHOWMATCH
- X { "showmatch", "sm", BOOL, CANSET , o_showmatch },
- X#endif
- X#ifndef NO_SHOWMODE
- X { "showmode", "smd", BOOL, CANSET , o_smd },
- X#endif
- X { "shiftwidth", "sw", NUM, CANSET , o_shiftwidth },
- X { "sidescroll", "ss", NUM, CANSET , o_sidescroll },
- X { "sync", "sy", BOOL, CANSET , o_sync },
- X { "tabstop", "ts", NUM, CANSET | MR, o_tabstop },
- X { "term", "te", STR, SET , o_term },
- X { "vbell", "vb", BOOL, CANSET , o_vbell },
- X { "warn", "wa", BOOL, CANSET , o_warn },
- X { "wrapmargin", "wm", NUM, CANSET , o_wrapmargin },
- X { "wrapscan", "ws", BOOL, CANSET , o_wrapscan },
- X { NULL, NULL, 0, CANSET, NULL }
- X};
- X
- X
- X/* This function initializes certain options from environment variables, etc. */
- Xvoid initopts()
- X{
- X char *val;
- X int i;
- X
- X /* set some stuff from environment variables */
- X#if MSDOS
- X if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
- X#else
- X if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
- X#endif
- X {
- X strcpy(o_shell, val);
- X }
- X
- X#if ANY_UNIX
- X if (val = getenv("TERM")) /* yes, ASSIGNMENT! */
- X {
- X strcpy(o_term, val);
- X }
- X#endif
- X#if TOS
- X val = "vt52";
- X strcpy(o_term, val);
- X#endif
- X#if MSDOS
- X if ((val = getenv("TERM")) /* yes, ASSIGNMENT! */
- X && strcmp(val, "pcbios"))
- X {
- X strcpy(o_term, val);
- X o_pcbios[0] = 0;
- X }
- X else
- X {
- X strcpy(o_term, "pcbios");
- X o_pcbios[0] = 1;
- X }
- X#endif
- X#if MSDOS || TOS
- X if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
- X || (val = getenv("TEMP")))
- X strcpy(o_directory, val);
- X#endif
- X
- X *o_scroll = LINES / 2 - 1;
- X
- X /* disable the vbell option if we don't know how to do a vbell */
- X if (!has_VB)
- X {
- X for (i = 0; opts[i].value != o_vbell; i++)
- X {
- X }
- X opts[i].flags &= ~CANSET;
- X *o_vbell = FALSE;
- X }
- X
- X#ifndef NO_DIGRAPH
- X# ifdef CS_LATIN1
- X for (i = 0, val = o_flipcase; i < 32; i++)
- X {
- X /* leave out the multiply/divide symbols */
- X if (i == 23)
- X continue;
- X
- X /* add upper/lowercase pair */
- X *val++ = i + 0xc0;
- X *val++ = i + 0xe0;
- X }
- X *val = '\0';
- X# endif /* CS_LATIN1 */
- X#endif /* not NO_DIGRAPH */
- X}
- X
- X/* This function lists the current values of all options */
- Xvoid dumpopts(all)
- X int all; /* boolean: dump all options, or just set ones? */
- X{
- X#ifndef NO_OPTCOLS
- X int i, j, k;
- X char nbuf[4]; /* used for converting numbers to ASCII */
- X int widths[5]; /* width of each column, including gap */
- X int ncols; /* number of columns */
- X int nrows; /* number of options per column */
- X int nset; /* number of options to be output */
- X int width; /* width of a particular option */
- X int todump[50]; /* indicies of options to be dumped */
- X
- X /* step 1: count the number of set options */
- X for (nset = i = 0; opts[i].name; i++)
- X {
- X if (all || (opts[i].flags & SET))
- X {
- X todump[nset++] = i;
- X }
- X }
- X
- X /* step two: try to use as many columns as possible */
- X for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
- X {
- X /* how many would go in this column? */
- X nrows = (nset + ncols - 1) / ncols;
- X
- X /* figure out the width of each column */
- X for (i = 0; i < ncols; i++)
- X {
- X widths[i] = 0;
- X for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
- X {
- X /* figure out the width of a particular option */
- X switch (opts[todump[k]].type)
- X {
- X case BOOL:
- X if (!*opts[todump[k]].value)
- X width = 2;
- X else
- X width = 0;
- X break;
- X
- X case STR:
- X width = 3 + strlen(opts[todump[k]].value);
- X if (width > MAXWIDTH)
- X width = MAXWIDTH;
- X break;
- X
- X case NUM:
- X width = 4;
- X break;
- X }
- X width += strlen(opts[todump[k]].name);
- X
- X /* if this is the widest so far, widen col */
- X if (width > widths[i])
- X {
- X widths[i] = width;
- X }
- X }
- X
- X }
- X
- X /* if the total width is narrow enough, then use it */
- X for (width = -2, i = 0; i < ncols; i++)
- X {
- X width += widths[i] + 2;
- X }
- X if (width < COLS - 1)
- X {
- X break;
- X }
- X }
- X
- X /* step 3: output the columns */
- X nrows = (nset + ncols - 1) / ncols;
- X for (i = 0; i < nrows; i++)
- X {
- X for (j = 0; j < ncols; j++)
- X {
- X /* if we hit the end of the options, quit */
- X k = i + j * nrows;
- X if (k >= nset)
- X {
- X break;
- X }
- X
- X /* output this option's value */
- X width = 0;
- X switch (opts[todump[k]].type)
- X {
- X case BOOL:
- X if (!*opts[todump[k]].value)
- X {
- X qaddch('n');
- X qaddch('o');
- X width = 2;
- X }
- X qaddstr(opts[todump[k]].name);
- X width += strlen(opts[todump[k]].name);
- X break;
- X
- X case NUM:
- X sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
- X qaddstr(opts[todump[k]].name);
- X qaddch('=');
- X qaddstr(nbuf);
- X width = 4 + strlen(opts[todump[k]].name);
- X break;
- X
- X case STR:
- X qaddstr(opts[todump[k]].name);
- X qaddch('=');
- X qaddch('"');
- X strcpy(tmpblk.c, opts[todump[k]].value);
- X width = 3 + strlen(tmpblk.c);
- X if (width > MAXWIDTH)
- X {
- X width = MAXWIDTH;
- X strcpy(tmpblk.c + MAXWIDTH - 6, "...");
- X }
- X qaddstr(tmpblk.c);
- X qaddch('"');
- X width += strlen(opts[todump[k]].name);
- X break;
- X }
- X
- X /* pad the field to the correct size */
- X if (k + nrows <= nset)
- X {
- X while (width < widths[j] + 2)
- X {
- X qaddch(' ');
- X width++;
- X }
- X }
- X }
- X addch('\n');
- X exrefresh();
- X }
- X#else
- X int i;
- X int col;
- X char nbuf[4];
- X
- X for (i = col = 0; opts[i].name; i++)
- X {
- X /* if not set and not all, ignore this option */
- X if (!all && !(opts[i].flags & SET))
- X {
- X continue;
- X }
- X
- X /* align this option in one of the columns */
- X if (col > 52)
- X {
- X addch('\n');
- X col = 0;
- X }
- X else if (col > 26)
- X {
- X while (col < 52)
- X {
- X qaddch(' ');
- X col++;
- X }
- X }
- X else if (col > 0)
- X {
- X while (col < 26)
- X {
- X qaddch(' ');
- X col++;
- X }
- X }
- X
- X switch (opts[i].type)
- X {
- X case BOOL:
- X if (!*opts[i].value)
- X {
- X qaddch('n');
- X qaddch('o');
- X col += 2;
- X }
- X qaddstr(opts[i].name);
- X col += strlen(opts[i].name);
- X break;
- X
- X case NUM:
- X sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
- X qaddstr(opts[i].name);
- X qaddch('=');
- X qaddstr(nbuf);
- X col += 4 + strlen(opts[i].name);
- X break;
- X
- X case STR:
- X qaddstr(opts[i].name);
- X qaddch('=');
- X qaddch('"');
- X qaddstr(opts[i].value);
- X qaddch('"');
- X col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
- X break;
- X }
- X exrefresh();
- X }
- X if (col > 0)
- X {
- X addch('\n');
- X exrefresh();
- X }
- X#endif
- X}
- X
- X#ifndef NO_MKEXRC
- X/* This function saves the current configuarion of options to a file */
- Xvoid saveopts(fd)
- X int fd; /* file descriptor to write to */
- X{
- X int i;
- X char buf[256], *pos;
- X
- X /* write each set options */
- X for (i = 0; opts[i].name; i++)
- X {
- X /* if unset or unsettable, ignore this option */
- X if (!(opts[i].flags & SET) || !(opts[i].flags & CANSET))
- X {
- X continue;
- X }
- X
- X strcpy(buf, "set ");
- X pos = &buf[4];
- X switch (opts[i].type)
- X {
- X case BOOL:
- X if (!*opts[i].value)
- X {
- X *pos++='n';
- X *pos++='o';
- X }
- X strcpy(pos, opts[i].name);
- X strcat(pos, "\n");
- X break;
- X
- X case NUM:
- X sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
- X break;
- X
- X case STR:
- X sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
- X break;
- X }
- X twrite(fd, buf, strlen(buf));
- X }
- X}
- X#endif
- X
- X
- X/* This function changes the values of one or more options. */
- Xvoid setopts(assignments)
- X char *assignments; /* a string containing option assignments */
- X{
- X char *name; /* name of variable in assignments */
- X char *value; /* value of the variable */
- X char *scan; /* used for moving through strings */
- X int i, j;
- X
- X /* for each assignment... */
- X for (name = assignments; *name; )
- X {
- X /* skip whitespace */
- X if (*name == ' ' || *name == '\t')
- X {
- X name++;
- X continue;
- X }
- X
- X /* find the value, if any */
- X for (scan = name; *scan >= 'a' && *scan <= 'z'; scan++)
- X {
- X }
- X if (*scan == '=')
- X {
- X *scan++ = '\0';
- X if (*scan == '"')
- X {
- X value = ++scan;
- X while (*scan && *scan != '"')
- X {
- X scan++;
- X }
- X if (*scan)
- X {
- X *scan++ = '\0';
- X }
- X }
- X else
- X {
- X value = scan;
- X while (*scan && *scan != ' ' && *scan != '\t')
- X {
- X scan++;
- X }
- X if (*scan)
- X {
- X *scan++ = '\0';
- X }
- X }
- X }
- X else
- X {
- X if (*scan)
- X {
- X *scan++ = '\0';
- X }
- X value = NULL;
- X if (name[0] == 'n' && name[1] == 'o')
- X {
- X name += 2;
- X }
- X }
- X
- X /* find the variable */
- X for (i = 0;
- X opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
- X i++)
- X {
- X }
- X
- X /* change the variable */
- X if (!opts[i].name)
- X {
- X msg("invalid option name \"%s\"", name);
- X }
- X else if ((opts[i].flags & CANSET) != CANSET)
- X {
- X msg("option \"%s\" can't be altered", name);
- X }
- X else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
- X {
- X msg("option \"%s\" can only be set in a %s file", name, EXRC);
- X }
- X else if (value)
- X {
- X switch (opts[i].type)
- X {
- X case BOOL:
- X msg("option \"[no]%s\" is boolean", name);
- X break;
- X
- X case NUM:
- X j = atoi(value);
- X if (j == 0 && *value != '0')
- X {
- X msg("option \"%s\" must have a numeric value", name);
- X }
- X else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
- X {
- X msg("option \"%s\" must have a value between %d and %d",
- X name, opts[i].value[1], opts[i].value[2] & 0xff);
- X }
- X else
- X {
- X *opts[i].value = atoi(value);
- X opts[i].flags |= SET;
- X }
- X break;
- X
- X case STR:
- X strcpy(opts[i].value, value);
- X opts[i].flags |= SET;
- X break;
- X }
- X if (opts[i].flags & MR)
- X {
- X mustredraw = TRUE;
- X }
- X }
- X else /* valid option, no value */
- X {
- X if (opts[i].type == BOOL)
- X {
- X *opts[i].value = (name[-1] != 'o');
- X opts[i].flags |= SET;
- X if (opts[i].flags & MR)
- X {
- X mustredraw = TRUE;
- X }
- X }
- X else
- X {
- X msg("option \"%s\" must be given a value", name);
- X }
- X }
- X
- X /* move on to the next option */
- X name = scan;
- X }
- X
- X /* special processing ... */
- X
- X /* if "readonly" then set the READONLY flag for this file */
- X if (*o_readonly)
- X {
- X setflag(file, READONLY);
- X }
- X}
- eof
- if test `wc -c <opts.c` -ne 14362
- then
- echo opts.c damaged!
- fi
- fi
-
- if test -f recycle.c -a "$1" != -f
- then
- echo Will not overwrite recycle.c
- else
- echo Extracting recycle.c
- sed 's/^X//' >recycle.c <<\eof
- X/* recycle.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains the functions perform garbage collection and allocate
- X * reusable blocks.
- X */
- X
- X#include "config.h"
- X#include "vi.h"
- X
- X#ifndef NO_RECYCLE
- X/* this whole file would have be skipped if NO_RECYCLE is defined */
- X
- Xextern long lseek();
- X
- X#define BTST(bitno, byte) ((byte) & (1 << (bitno)))
- X#define BSET(bitno, byte) ((byte) |= (1 << (bitno)))
- X#define BCLR(bitno, byte) ((byte) &= ~(1 << (bitno)))
- X
- X#define TST(blkno) ((blkno) < MAXBIT ? BTST((blkno) & 7, bitmap[(blkno) >> 3]) : 1)
- X#define SET(blkno) if ((blkno) < MAXBIT) BSET((blkno) & 7, bitmap[(blkno) >> 3])
- X#define CLR(blkno) if ((blkno) < MAXBIT) BCLR((blkno) & 7, bitmap[(blkno) >> 3])
- X
- X/* bitmap of free blocks in first 4096k of tmp file */
- Xstatic unsigned char bitmap[512];
- X#define MAXBIT (sizeof bitmap << 3)
- X
- X/* this function locates all free blocks in the current tmp file */
- Xvoid garbage()
- X{
- X int i;
- X BLK oldhdr;
- X
- X /* start by assuming every block is free */
- X for (i = 0; i < sizeof bitmap; i++)
- X {
- X bitmap[i] = 255;
- X }
- X
- X /* header block isn't free */
- X#ifndef lint
- X CLR(0);
- X#endif
- X
- X /* blocks needed for current hdr aren't free */
- X for (i = 1; i < MAXBLKS; i++)
- X {
- X CLR(hdr.n[i]);
- X }
- X
- X /* blocks needed for undo version aren't free */
- X lseek(tmpfd, 0L, 0);
- X if (read(tmpfd, &oldhdr, (unsigned)sizeof oldhdr) != sizeof oldhdr)
- X {
- X msg("garbage() failed to read oldhdr??");
- X for (i = 0; i < sizeof bitmap; i++)
- X {
- X bitmap[i] = 0;
- X }
- X return;
- X }
- X for (i = 1; i < MAXBLKS; i++)
- X {
- X CLR(oldhdr.n[i]);
- X }
- X
- X /* blocks needed for cut buffers aren't free */
- X for (i = cutneeds(&oldhdr) - 1; i >= 0; i--)
- X {
- X CLR(oldhdr.n[i]);
- X }
- X}
- X
- X/* This function allocates the first available block in the tmp file */
- Xlong allocate()
- X{
- X int i;
- X long offset;
- X
- X /* search for the first byte with a free bit set */
- X for (i = 0; i < sizeof bitmap && bitmap[i] == 0; i++)
- X {
- X }
- X
- X /* if we hit the end of the bitmap, return the end of the file */
- X if (i == sizeof bitmap)
- X {
- X offset = lseek(tmpfd, 0L, 2);
- X }
- X else /* compute the offset for the free block */
- X {
- X for (i <<= 3; TST(i) == 0; i++)
- X {
- X }
- X offset = (long)i * (long)BLKSIZE;
- X
- X /* mark the block as "allocated" */
- X CLR(i);
- X }
- X
- X return offset;
- X}
- X
- X#endif
- eof
- if test `wc -c <recycle.c` -ne 2306
- then
- echo recycle.c damaged!
- fi
- fi
-
- if test -f redraw.c -a "$1" != -f
- then
- echo Will not overwrite redraw.c
- else
- echo Extracting redraw.c
- sed 's/^X//' >redraw.c <<\eof
- X/* redraw.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 14407 SW Teal Blvd. #C
- X * Beaverton, OR 97005
- X * kirkenda@cs.pdx.edu
- X */
- X
- X
- X/* This file contains functions that draw text on the screen. The major entry
- X * points are:
- X * redrawrange() - called from modify.c to give hints about what parts
- X * of the screen need to be redrawn.
- X * redraw() - redraws the screen (or part of it) and positions
- X * the cursor where it belongs.
- X * idx2col() - converts a markidx() value to a logical column number.
- X */
- X
- X#include "config.h"
- X#include "vi.h"
- X
- X/* This variable contains the line number that smartdrawtext() knows best */
- Xstatic long smartlno;
- X
- X/* This function remebers where changes were made, so that the screen can be
- X * redraw in a more efficient manner.
- X */
- Xstatic long redrawafter; /* line# of first line that must be redrawn */
- Xstatic long preredraw; /* line# of last line changed, before change */
- Xstatic long postredraw; /* line# of last line changed, after change */
- Xvoid redrawrange(after, pre, post)
- X long after; /* lower bound of redrawafter */
- X long pre; /* upper bound of preredraw */
- X long post; /* upper bound of postredraw */
- X{
- X if (after == redrawafter)
- X {
- X /* multiple insertions/deletions at the same place -- combine
- X * them
- X */
- X preredraw -= (post - pre);
- X if (postredraw < post)
- X {
- X preredraw += (post - postredraw);
- X postredraw = post;
- X }
- X if (redrawafter > preredraw)
- X {
- X redrawafter = preredraw;
- X }
- X if (redrawafter < 1L)
- X {
- X redrawafter = 0L;
- X preredraw = postredraw = INFINITY;
- X }
- X }
- X else if (postredraw > 0L)
- X {
- X /* multiple changes in different places -- redraw everything
- X * after "after".
- X */
- X postredraw = preredraw = INFINITY;
- X if (after < redrawafter)
- X redrawafter = after;
- X }
- X else
- X {
- X /* first change */
- X redrawafter = after;
- X preredraw = pre;
- X postredraw = post;
- X }
- X}
- X
- X
- X#ifndef NO_CHARATTR
- X/* see if a given line uses character attribute strings */
- Xstatic int hasattr(lno, text)
- X long lno; /* the line# of the cursor */
- X REG char *text; /* the text of the line, from fetchline */
- X{
- X static long plno; /* previous line number */
- X static long chgs; /* previous value of changes counter */
- X static int panswer;/* previous answer */
- X char *scan;
- X
- X /* if charattr is off, then the answer is "no, it doesn't" */
- X if (!*o_charattr)
- X {
- X chgs = 0; /* <- forces us to check if charattr is later set */
- X return FALSE;
- X }
- X
- X /* if we already know the answer, return it... */
- X if (lno == plno && chgs == changes)
- X {
- X return panswer;
- X }
- X
- X /* get the line & look for "\fX" */
- X if (!text[0] || !text[1] || !text[2])
- X {
- X panswer = FALSE;
- X }
- X else
- X {
- X for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
- X {
- X }
- X panswer = (scan[2] != '\0');
- X }
- X
- X /* save the results */
- X plno = lno;
- X chgs = changes;
- X
- X /* return the results */
- X return panswer;
- X}
- X#endif
- X
- X
- X
- X/* This function converts a MARK to a column number. It doesn't automatically
- X * adjust for leftcol; that must be done by the calling function
- X */
- Xint idx2col(curs, text, inputting)
- X MARK curs; /* the line# & index# of the cursor */
- X REG char *text; /* the text of the line, from fetchline */
- X int inputting; /* boolean: called from input() ? */
- X{
- X static MARK pcursor;/* previous cursor, for possible shortcut */
- X static MARK pcol; /* column number for pcol */
- X static long chgs; /* previous value of changes counter */
- X REG int col; /* used to count column numbers */
- X REG int idx; /* used to count down the index */
- X REG int i;
- X
- X /* for now, assume we have to start counting at the left edge */
- X col = 0;
- X idx = markidx(curs);
- X
- X /* if the file hasn't changed & line number is the same & it has no
- X * embedded character attribute strings, can we do shortcuts?
- X */
- X if (chgs == changes
- X && !((curs ^ pcursor) & ~(BLKSIZE - 1))
- X#ifndef NO_CHARATTR
- X && !hasattr(markline(curs), text)
- X#endif
- X )
- X {
- X /* no movement? */
- X if (curs == pcursor)
- X {
- X /* return the column of the char; for tabs, return its last column */
- X if (text[idx] == '\t' && !inputting && !*o_list)
- X {
- X return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
- X }
- X else
- X {
- X return pcol;
- X }
- X }
- X
- X /* movement to right? */
- X if (curs > pcursor)
- X {
- X /* start counting from previous place */
- X col = pcol;
- X idx = markidx(curs) - markidx(pcursor);
- X text += markidx(pcursor);
- X }
- X }
- X
- X /* count over to the char after the idx position */
- X while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
- X {
- X if (i == '\t' && !*o_list)
- X {
- X col += *o_tabstop;
- X col -= col % *o_tabstop;
- X }
- X else if (i >= '\0' && i < ' ' || i == '\177')
- X {
- X col += 2;
- X }
- X#ifndef NO_CHARATTR
- X else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
- X {
- X text += 2; /* plus one more at bottom of loop */
- X idx -= 2;
- X }
- X#endif
- X else
- X {
- X col++;
- X }
- X text++;
- X idx--;
- X }
- X
- X /* save stuff to speed next call */
- X pcursor = curs;
- X pcol = col;
- X chgs = changes;
- X
- X /* return the column of the char; for tabs, return its last column */
- X if (*text == '\t' && !inputting && !*o_list)
- X {
- X return col + *o_tabstop - (col % *o_tabstop) - 1;
- X }
- X else
- X {
- X return col;
- X }
- X}
- X
- X
- X/* This function is similar to idx2col except that it takes care of sideways
- X * scrolling - for the given line, at least.
- X */
- Xint mark2phys(m, text, inputting)
- X MARK m; /* a mark to convert */
- X char *text; /* the line that m refers to */
- X int inputting; /* boolean: caled from input() ? */
- X{
- X int i;
- X
- X i = idx2col(m, text, inputting);
- X while (i < leftcol)
- X {
- X leftcol -= *o_sidescroll;
- X mustredraw = TRUE;
- X redrawrange(1L, INFINITY, INFINITY);
- X qaddch('\r');
- X /* drawtext(text); */
- X }
- X while (i > rightcol)
- X {
- X leftcol += *o_sidescroll;
- X mustredraw = TRUE;
- X redrawrange(1L, INFINITY, INFINITY);
- X qaddch('\r');
- X /* drawtext(text); */
- X }
- X physcol = i - leftcol;
- X physrow = markline(m) - topline;
- X
- X return physcol;
- X}
- X
- X/* This function draws a single line of text on the screen. The screen's
- X * cursor is assumed to be located at the leftmost column of the appropriate
- X * row.
- X */
- Xstatic void drawtext(text, clr)
- X REG char *text; /* the text to draw */
- X int clr; /* boolean: do a clrtoeol? */
- X{
- X REG int col; /* column number */
- X REG int i;
- X REG int tabstop; /* *o_tabstop */
- X REG int limitcol; /* leftcol or leftcol + COLS */
- X int abnormal; /* boolean: charattr != A_NORMAL? */
- X
- X#ifndef NO_SENTENCE
- X /* if we're hiding format lines, and this is one of them, then hide it */
- X if (*o_hideformat && *text == '.')
- X {
- X clrtoeol();
- X#if OSK
- X qaddch('\l');
- X#else
- X qaddch('\n');
- X#endif
- X return;
- X }
- X#endif
- X
- X /* move some things into registers... */
- X limitcol = leftcol;
- X tabstop = *o_tabstop;
- X abnormal = FALSE;
- X
- X#ifndef CRUNCH
- X if (clr)
- X clrtoeol();
- X#endif
- X /* skip stuff that was scrolled off left edge */
- X for (col = 0;
- X (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
- X text++)
- X {
- X if (i == '\t' && !*o_list)
- X {
- X col = col + tabstop - (col % tabstop);
- X }
- X else if (i >= 0 && i < ' ' || i == '\177')
- X {
- X col += 2;
- X }
- X#ifndef NO_CHARATTR
- X else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
- X {
- X text += 2; /* plus one more as part of "for" loop */
- X
- X /* since this attribute might carry over, we need it */
- X switch (*text)
- X {
- X case 'R':
- X case 'P':
- X attrset(A_NORMAL);
- X abnormal = FALSE;
- X break;
- X
- X case 'B':
- X attrset(A_BOLD);
- X abnormal = TRUE;
- X break;
- X
- X case 'U':
- X attrset(A_UNDERLINE);
- X abnormal = TRUE;
- X break;
- X
- X case 'I':
- X attrset(A_ALTCHARSET);
- X abnormal = TRUE;
- X break;
- X }
- X }
- X#endif
- X else
- X {
- X col++;
- X }
- X }
- X
- X /* adjust for control char that was partially visible */
- X while (col > limitcol)
- X {
- X qaddch(' ');
- X limitcol++;
- X }
- X
- X /* now for the visible characters */
- X for (limitcol = leftcol + COLS;
- X (i = *text) && col < limitcol;
- X text++)
- X {
- X if (i == '\t' && !*o_list)
- X {
- X i = col + tabstop - (col % tabstop);
- X if (i < limitcol)
- X {
- X#ifdef CRUNCH
- X if (!clr && has_PT && !((i - leftcol) & 7))
- X#else
- X if (has_PT && !((i - leftcol) & 7))
- X#endif
- X {
- X do
- X {
- X qaddch('\t');
- X col += 8; /* not exact! */
- X } while (col < i);
- X col = i; /* NOW it is exact */
- X }
- X else
- X {
- X do
- X {
- X qaddch(' ');
- X col++;
- X } while (col < i);
- X }
- X }
- X else /* tab ending after screen? next line! */
- X {
- X col = limitcol;
- X if (has_AM)
- X {
- X addch('\n'); /* GB */
- X }
- X }
- X }
- X else if (i >= 0 && i < ' ' || i == '\177')
- X {
- X col += 2;
- X qaddch('^');
- X if (col <= limitcol)
- X {
- X qaddch(i ^ '@');
- X }
- X }
- X#ifndef NO_CHARATTR
- X else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
- X {
- X text += 2; /* plus one more as part of "for" loop */
- X switch (*text)
- X {
- X case 'R':
- X case 'P':
- X attrset(A_NORMAL);
- X abnormal = FALSE;
- X break;
- X
- X case 'B':
- X attrset(A_BOLD);
- X abnormal = TRUE;
- X break;
- X
- X case 'U':
- X attrset(A_UNDERLINE);
- X abnormal = TRUE;
- X break;
- X
- X case 'I':
- X attrset(A_ALTCHARSET);
- X abnormal = TRUE;
- X break;
- X }
- X }
- X#endif
- X else
- X {
- X col++;
- X qaddch(i);
- X }
- X }
- X
- X /* get ready for the next line */
- X#ifndef NO_CHARATTR
- X if (abnormal)
- X {
- X attrset(A_NORMAL);
- X }
- X#endif
- X if (*o_list && col < limitcol)
- X {
- X qaddch('$');
- X col++;
- X }
- X#ifdef CRUNCH
- X if (clr && col < limitcol)
- X {
- X clrtoeol();
- X }
- X#endif
- X if (!has_AM || col < limitcol)
- X {
- X addch('\n');
- X }
- X}
- X
- X
- X#ifndef CRUNCH
- Xstatic void nudgecursor(same, scan, new, lno)
- X int same; /* number of chars to be skipped over */
- X char *scan; /* where the same chars end */
- X char *new; /* where the visible part of the line starts */
- X long lno; /* line number of this line */
- X{
- X if (same > 0)
- X {
- X if (same < 5)
- X {
- X /* move the cursor by overwriting */
- X while (same > 0)
- X {
- X qaddch(scan[-same]);
- X same--;
- X }
- X }
- X else
- X {
- X /* move the cursor by calling move() */
- X move((int)(lno - topline), (int)(scan - new));
- X }
- X }
- X}
- X#endif /* not CRUNCH */
- X
- X/* This function draws a single line of text on the screen, possibly with
- X * some cursor optimization. The cursor is repositioned before drawing
- X * begins, so its position before doesn't really matter.
- X */
- Xstatic void smartdrawtext(text, lno)
- X REG char *text; /* the text to draw */
- X long lno; /* line number of the text */
- X{
- X#ifdef CRUNCH
- X move((int)(lno - topline), 0);
- X drawtext(text, TRUE);
- X#else /* not CRUNCH */
- X static char old[256]; /* how the line looked last time */
- X char new[256]; /* how it looks now */
- X char *build; /* used to put chars into new[] */
- X char *scan; /* used for moving thru new[] or old[] */
- X char *end; /* last non-blank changed char */
- X char *shift; /* used to insert/delete chars */
- X int same; /* length of a run of unchanged chars */
- X int limitcol;
- X int col;
- X int i;
- X
- X# ifndef NO_CHARATTR
- X /* if this line has attributes, do it the dumb way instead */
- X if (hasattr(lno, text))
- X {
- X move((int)(lno - topline), 0);
- X drawtext(text, TRUE);
- X return;
- X }
- X# endif
- X# ifndef NO_SENTENCE
- X /* if this line is a format line, & we're hiding format lines, then
- X * let the dumb drawtext() function handle it
- X */
- X if (*o_hideformat && *text == '.')
- X {
- X move((int)(lno - topline), 0);
- X drawtext(text, TRUE);
- X return;
- X }
- X# endif
- X
- X /* skip stuff that was scrolled off left edge */
- X limitcol = leftcol;
- X for (col = 0;
- X (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
- X text++)
- X {
- X if (i == '\t' && !*o_list)
- X {
- X col = col + *o_tabstop - (col % *o_tabstop);
- X }
- X else if (i >= 0 && i < ' ' || i == '\177')
- X {
- X col += 2;
- X }
- X else
- X {
- X col++;
- X }
- X }
- X
- X /* adjust for control char that was partially visible */
- X build = new;
- X while (col > limitcol)
- X {
- X *build++ = ' ';
- X limitcol++;
- X }
- X
- X /* now for the visible characters */
- X for (limitcol = leftcol + COLS;
- X (i = *text) && col < limitcol;
- X text++)
- X {
- X if (i == '\t' && !*o_list)
- X {
- X i = col + *o_tabstop - (col % *o_tabstop);
- X while (col < i && col < limitcol)
- X {
- X *build++ = ' ';
- X col++;
- X }
- X }
- X else if (i >= 0 && i < ' ' || i == '\177')
- X {
- X col += 2;
- X *build++ = '^';
- X if (col <= limitcol)
- X {
- X *build++ = (i ^ '@');
- X }
- X }
- X else
- X {
- X col++;
- X *build++ = i;
- X }
- X }
- X if (col < limitcol && *o_list)
- X {
- X *build++ = '$';
- X col++;
- X }
- X end = build;
- X while (col < limitcol)
- X {
- X *build++ = ' ';
- X col++;
- X }
- X
- X /* locate the last non-blank character */
- X while (end > new && end[-1] == ' ')
- X {
- X end--;
- X }
- X
- X /* can we optimize the displaying of this line? */
- X if (lno != smartlno)
- X {
- X /* nope, can't optimize - different line */
- X move((int)(lno - topline), 0);
- X for (scan = new, build = old; scan < end; )
- X {
- X qaddch(*scan);
- X *build++ = *scan++;
- X }
- X if (end < new + COLS)
- X {
- X clrtoeol();
- X while (build < old + COLS)
- X {
- X *build++ = ' ';
- X }
- X }
- X smartlno = lno;
- X return;
- X }
- X
- X /* skip any initial unchanged characters */
- X for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
- X {
- X }
- X move((int)(lno - topline), (int)(scan - new));
- X
- X /* The in-between characters must be changed */
- X same = 0;
- X while (scan < end)
- X {
- X /* is this character a match? */
- X if (scan[0] == build[0])
- X {
- X same++;
- X }
- X else /* do we want to insert? */
- X if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
- X {
- X nudgecursor(same, scan, new, lno);
- X same = 0;
- X
- X insch(*scan);
- X for (shift = old + COLS; --shift > build; )
- X {
- X shift[0] = shift[-1];
- X }
- X *build = *scan;
- X }
- X else /* do we want to delete? */
- X if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
- X {
- X nudgecursor(same, scan, new, lno);
- X same = 0;
- X
- X delch();
- X same++;
- X for (shift = build; shift < old + COLS - 1; shift++)
- X {
- X shift[0] = shift[1];
- X }
- X *shift = ' ';
- X }
- X else /* we must overwrite */
- X {
- X nudgecursor(same, scan, new, lno);
- X same = 0;
- X
- X addch(*scan);
- X *build = *scan;
- X }
- X
- X build++;
- X scan++;
- X }
- X
- X /* maybe clear to EOL */
- X while (build < old + COLS && *build == ' ')
- X {
- X build++;
- X }
- X if (build < old + COLS)
- X {
- X nudgecursor(same, scan, new, lno);
- X same = 0;
- X
- X clrtoeol();
- X while (build < old + COLS)
- X {
- X *build++ = ' ';
- X }
- X }
- X#endif /* not CRUNCH */
- X}
- X
- X
- X/* This function is used in visual mode for drawing the screen (or just parts
- X * of the screen, if that's all thats needed). It also takes care of
- X * scrolling.
- X */
- Xvoid redraw(curs, inputting)
- X MARK curs; /* where to leave the screen's cursor */
- X int inputting; /* boolean: being called from input() ? */
- X{
- X char *text; /* a line of text to display */
- X static long chgs; /* previous changes level */
- X long l;
- X int i;
- X
- X /* if curs == MARK_UNSET, then we should reset internal vars */
- X if (curs == MARK_UNSET)
- X {
- X if (topline < 1 || topline > nlines)
- X {
- X topline = 1L;
- X }
- X else
- X {
- X move(LINES - 1, 0);
- X clrtoeol();
- X }
- X leftcol = 0;
- X mustredraw = TRUE;
- X redrawafter = INFINITY;
- X preredraw = 0L;
- X postredraw = 0L;
- X chgs = 0;
- X smartlno = 0L;
- X return;
- X }
- X
- X /* figure out which column the cursor will be in */
- X l = markline(curs);
- X text = fetchline(l);
- X mark2phys(curs, text, inputting);
- X
- X /* adjust topline, if necessary, to get the cursor on the screen */
- X if (l >= topline && l <= botline)
- X {
- X /* it is on the screen already */
- X
- X /* if the file was changed but !mustredraw, then redraw line */
- X if (chgs != changes && !mustredraw)
- X {
- X smartdrawtext(text, l);
- X }
- X }
- X else if (l < topline && l > topline - LINES && (has_SR || has_AL))
- X {
- X /* near top - scroll down */
- X if (!mustredraw)
- X {
- X move(0,0);
- X while (l < topline)
- X {
- X topline--;
- X if (has_SR)
- X {
- X do_SR();
- X }
- X else
- X {
- X insertln();
- X }
- X text = fetchline(topline);
- X drawtext(text, FALSE);
- X do_UP();
- X }
- X
- X /* blank out the last line */
- X move(LINES - 1, 0);
- X clrtoeol();
- X }
- X else
- X {
- X topline = l;
- X redrawafter = INFINITY;
- X preredraw = 0L;
- X postredraw = 0L;
- X }
- X }
- X else if (l > topline && l < botline + LINES)
- X {
- X /* near bottom -- scroll up */
- X if (!mustredraw
- X#if 1
- X || redrawafter == preredraw && preredraw == botline && postredraw == l
- X#endif
- X )
- X {
- X move(LINES - 1,0);
- X clrtoeol();
- X while (l > botline)
- X {
- X topline++; /* <-- also adjusts botline */
- X text = fetchline(botline);
- X drawtext(text, FALSE);
- X }
- X mustredraw = FALSE;
- X }
- X else
- X {
- X topline = l - (LINES - 2);
- X redrawafter = INFINITY;
- X preredraw = 0L;
- X postredraw = 0L;
- X }
- X }
- X else
- X {
- X /* distant line - center it & force a redraw */
- X topline = l - (LINES / 2) - 1;
- X if (topline < 1)
- X {
- X topline = 1;
- X }
- X mustredraw = TRUE;
- X redrawafter = INFINITY;
- X preredraw = 0L;
- X postredraw = 0L;
- X }
- X
- X /* Now... do we really have to redraw? */
- X if (mustredraw)
- X {
- X /* If redrawfter (and friends) aren't set, assume we should
- X * redraw everything.
- X */
- X if (redrawafter == INFINITY)
- X {
- X redrawafter = 0L;
- X preredraw = postredraw = INFINITY;
- X }
- X
- X /* adjust smartlno to correspond with inserted/deleted lines */
- X if (smartlno >= redrawafter)
- X {
- X if (smartlno < preredraw)
- X {
- X smartlno = 0L;
- X }
- X else
- X {
- X smartlno += (postredraw - preredraw);
- X }
- X }
- X
- X /* should we insert some lines into the screen? */
- X if (preredraw < postredraw && preredraw <= botline)
- X {
- X /* lines were inserted into the file */
- X
- X /* decide where insertion should start */
- X if (preredraw < topline)
- X {
- X l = topline;
- X }
- X else
- X {
- X l = preredraw;
- X }
- X
- X /* insert the lines... maybe */
- X if (l + postredraw - preredraw > botline || !has_AL)
- X {
- X /* Whoa! a whole screen full - just redraw */
- X preredraw = postredraw = INFINITY;
- X }
- X else
- X {
- X /* really insert 'em */
- X move((int)(l - topline), 0);
- X for (i = postredraw - preredraw; i > 0; i--)
- X {
- X insertln();
- X }
- X
- X /* NOTE: the contents of those lines will be
- X * drawn as part of the regular redraw loop.
- X */
- X
- X /* clear the last line */
- X move(LINES - 1, 0);
- X clrtoeol();
- X }
- X }
- X
- X /* do we want to delete some lines from the screen? */
- X if (preredraw > postredraw && postredraw <= botline)
- X {
- X if (preredraw > botline || !has_DL)
- X {
- X postredraw = preredraw = INFINITY;
- X }
- X else /* we'd best delete some lines from the screen */
- X {
- X /* clear the last line, so it doesn't look
- X * ugly as it gets pulled up into the screen
- X */
- X move(LINES - 1, 0);
- X clrtoeol();
- X
- X /* delete the lines */
- X move((int)(postredraw - topline), 0);
- X for (l = postredraw;
- X l < preredraw && l <= botline;
- X l++)
- X {
- X deleteln();
- X }
- X
- X /* draw the lines that are now newly visible
- X * at the bottom of the screen
- X */
- X i = LINES - 1 + (postredraw - preredraw);
- X move(i, 0);
- X for (l = topline + i; l <= botline; l++)
- X {
- X /* clear this line */
- X clrtoeol();
- X
- X /* draw the line, or ~ for non-lines */
- X if (l <= nlines)
- X {
- X text = fetchline(l);
- X drawtext(text, FALSE);
- X }
- X else
- X {
- X addstr("~\n");
- X }
- X }
- X }
- X }
- X
- X /* redraw the current line */
- X l = markline(curs);
- X pfetch(l);
- X smartdrawtext(ptext, l);
- X
- X /* decide where we should start redrawing from */
- X if (redrawafter < topline)
- X {
- X l = topline;
- X }
- X else
- X {
- X l = redrawafter;
- X }
- X move((int)(l - topline), 0);
- X
- X /* draw the other lines */
- X for (; l <= botline && l < postredraw; l++)
- X {
- X /* we already drew the current line, so skip it now */
- X if (l == smartlno)
- X {
- X#if OSK
- X qaddch('\l');
- X#else
- X qaddch('\n');
- X#endif
- X continue;
- X }
- X
- X /* draw the line, or ~ for non-lines */
- X if (l <= nlines)
- X {
- X text = fetchline(l);
- X drawtext(text, TRUE);
- X }
- X else
- X {
- X qaddch('~');
- X clrtoeol();
- X addch('\n');
- X }
- X }
- X
- X mustredraw = FALSE;
- X }
- X
- X /* force total (non-partial) redraw next time if not set */
- X redrawafter = INFINITY;
- X preredraw = 0L;
- X postredraw = 0L;
- X
- X /* move the cursor to where it belongs */
- X move((int)(markline(curs) - topline), physcol);
- X wqrefresh(stdscr);
- X
- X chgs = changes;
- X}
- eof
- if test `wc -c <redraw.c` -ne 19816
- then
- echo redraw.c damaged!
- fi
- fi
-
- exit 0
- -------------------------------------------------------------------------------
- Steve Kirkendall kirkenda@cs.pdx.edu Grad student at Portland State U.
-