home *** CD-ROM | disk | FTP | other *** search
- From: kirkenda@eecs.cs.pdx.edu (Steve Kirkendall)
- Newsgroups: alt.sources
- Subject: Elvis 1.3 fixes
- Message-ID: <12@pdxgate.UUCP>
- Date: 30 Aug 90 21:15:51 GMT
-
- Here are new versions of the ELvis.lnk and Elvis.prj, to fix the problem
- with the "termcap" functions; and a new version of cut.c to avoid the MS-DOS
- bug that causes "lost clusters" when the temporary file is renamed.
-
- Thanks for the bug reports, everybody! I think I have enough now!
- (Well, almost.)
- -------------------------------------------------------------------------------
- Steve Kirkendall kirkenda@cs.pdx.edu uunet!tektronix!psueea!eecs!kirkenda
-
-
- # --------------------------- 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 steve group 343 Aug 30 13:37 Elvis.lnk
- # -rw-r--r-- 1 steve group 162 Aug 30 13:37 Elvis.prj
- # -rw-r--r-- 1 steve group 10357 Aug 30 13:35 cut.c
- #
-
- if test -f Elvis.lnk -a "$1" != -f
- then
- echo Will not overwrite Elvis.lnk
- else
- echo Extracting Elvis.lnk
- sed 's/^X//' >Elvis.lnk <<\eof
- Xblk.obj cmd1.obj cmd2.obj curses.obj cut.obj +
- Xex.obj input.obj main.obj misc.obj modify.obj +
- Xmove1.obj move2.obj move3.obj move4.obj move5.obj +
- Xopts.obj recycle.obj redraw.obj regexp.obj +
- Xregsub.obj system.obj tio.obj tmp.obj vars.obj +
- Xvcmd.obj vi.obj pc.obj sysdos.obj tinytcap.obj +
- X/co /noi /map +
- X/pac /far /stack:0x2000
- Xelvis.exe;
- eof
- if test `wc -c <Elvis.lnk` -ne 343
- then
- echo Elvis.lnk damaged!
- fi
- fi
-
- if test -f Elvis.prj -a "$1" != -f
- then
- echo Will not overwrite Elvis.prj
- else
- echo Extracting Elvis.prj
- sed 's/^X//' >Elvis.prj <<\eof
- Xblk
- Xcmd1
- Xcmd2
- Xcurses
- Xcut
- Xex
- Xinput
- Xmain
- Xmisc
- Xmodify
- Xmove1
- Xmove2
- Xmove3
- Xmove4
- Xmove5
- Xopts
- Xpc
- Xrecycle
- Xredraw
- Xregexp
- Xregsub
- Xsysdos
- Xsystem
- Xtio
- Xtmp
- Xvars
- Xvcmd
- Xvi
- Xtinytcap
- eof
- if test `wc -c <Elvis.prj` -ne 162
- then
- echo Elvis.prj damaged!
- fi
- fi
-
- if test -f cut.c -a "$1" != -f
- then
- echo Will not overwrite cut.c
- else
- echo Extracting cut.c
- sed 's/^X//' >cut.c <<\eof
- X/* cut.c */
- X
- X/* Author:
- X * Steve Kirkendall
- X * 16820 SW Tallac Way
- X * Beaverton, OR 97006
- X * kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
- X */
- X
- X
- X/* This file contains function which manipulate the cut buffers. */
- X
- X#include "config.h"
- X#include "vi.h"
- X#if TURBOC
- X#include <process.h> /* needed for getpid */
- X#endif
- X#if TOS
- X#include <osbind.h>
- X#define rename(a,b) Frename(0,a,b)
- X#endif
- X
- X# define NANNONS 9 /* number of annonymous buffers */
- X
- Xstatic struct cutbuf
- X{
- X short *phys; /* pointer to an array of #s of BLKs containing text */
- X int nblks; /* number of blocks in phys[] array */
- X int start; /* offset into first block of start of cut */
- X int end; /* offset into last block of end of cut */
- X int fd; /* fd of tmp file, or -1 to use tmpfd */
- X char lnmode; /* boolean: line-mode cut? (as opposed to char-mode) */
- X}
- X named[27], /* cut buffers "a through "z and ". */
- X annon[NANNONS]; /* annonymous cut buffers */
- X
- Xstatic char cbname; /* name chosen for next cut/paste operation */
- X
- X
- X#ifndef NO_RECYCLE
- X/* This function builds a list of all blocks needed in the current tmp file
- X * for the contents of cut buffers.
- X * !!! WARNING: if you have more than ~450000 bytes of text in all of the
- X * cut buffers, then this will fail disastrously, because buffer overflow
- X * is *not* allowed for.
- X */
- Xint cutneeds(need)
- X BLK *need; /* this is where we deposit the list */
- X{
- X struct cutbuf *cb; /* used to count through cut buffers */
- X int i; /* used to count through blocks of a cut buffer */
- X int n; /* total number of blocks in list */
- X
- X n = 0;
- X
- X /* first the named buffers... */
- X for (cb = named; cb < &named[27]; cb++)
- X {
- X if (cb->fd > 0)
- X continue;
- X
- X for (i = cb->nblks; i-- > 0; )
- X {
- X need->n[n++] = cb->phys[i];
- X }
- X }
- X
- X /* then the anonymous buffers */
- X for (cb = annon; cb < &annon[NANNONS]; cb++)
- X {
- X if (cb->fd > 0)
- X continue;
- X
- X for (i = cb->nblks; i-- > 0; )
- X {
- X need->n[n++] = cb->phys[i];
- X }
- X }
- X
- X return n;
- X}
- X#endif
- X
- X/* This function is called when we are about to abort a tmp file. If any
- X * cut buffers still need the file, then a copy of the file should be
- X * created for use by the cut buffers.
- X *
- X * To minimize the number of extra files lying around, only named cut buffers
- X * are preserved in a file switch; the annonymous buffers just go away.
- X */
- Xcutswitch(tmpname)
- X char *tmpname; /* name of the tmp file */
- X{
- X char cutname[50]; /* used to build a new name for the tmp file */
- X int fd; /* a new fd for the current tmp file */
- X int i, j;
- X
- X /* discard all annonymous cut buffers */
- X for (i = 0; i < NANNONS; i++)
- X {
- X cutfree(&annon[i]);
- X }
- X
- X /* find the first named buffer that uses this tmp file */
- X for (i = 0; i < 27; i++)
- X {
- X if (named[i].nblks > 0 && named[i].fd < 0)
- X {
- X break;
- X }
- X }
- X
- X /* if none of them use this tmp file, then we're done */
- X if (i == 27)
- X {
- X return;
- X }
- X
- X /* else we'll need this file and an fd a little longer */
- X /* !!! we could use some error checking here */
- X#if MSDOS || TOS
- X strcpy(cutname, o_directory);
- X if ((j = strlen(cutname)) && !strchr(":/\\", cutname[j-1]))
- X cutname[j++]=SLASH;
- X close(tmpfd);
- X fd = open(tmpname, O_RDONLY|O_BINARY);
- X close(fd);
- X sprintf(cutname+j, CUTNAME+3, getpid(), fd);
- X rename(tmpname, cutname);
- X fd = open(cutname, O_RDONLY|O_BINARY);
- X tmpfd = -1; /* we'll try to close this in tmp.c, but who cares? */
- X#else
- X fd = dup(tmpfd);
- X sprintf(cutname, CUTNAME, o_directory, getpid(), fd);
- X link(tmpname, cutname) || unlink(tmpname);
- X#endif
- X
- X /* have all cut buffers use the new fd instead */
- X for (; i < 27; i++)
- X {
- X if (named[i].nblks > 0 && named[i].fd < 0)
- X {
- X named[i].fd = fd;
- X }
- X }
- X}
- X
- X
- X/* This function frees a cut buffer */
- Xstatic cutfree(buf)
- X struct cutbuf *buf;
- X{
- X char cutname[50];
- X int i;
- X
- X /* return immediately if the buffer is already empty */
- X if (buf->nblks <= 0)
- X {
- X return;
- X }
- X
- X /* else free up stuff */
- X buf->nblks = 0;
- X free(buf->phys);
- X
- X /* see if anybody else needs this tmp file */
- X if (buf->fd >= 0)
- X {
- X for (i = 0; i < 27; i++)
- X {
- X#if 0
- X if (named[i].nblks > 0 && named[i].fd >= 0)
- X#else
- X if (named[i].nblks > 0 && named[i].fd == buf->fd)
- X#endif
- X {
- X break;
- X }
- X }
- X }
- X
- X /* if nobody else needs it, then discard the tmp file */
- X if (buf->fd >= 0 && i == 27)
- X {
- X close(buf->fd);
- X#if MSDOS || TOS
- X strcpy(cutname, o_directory);
- X if ((i = strlen(cutname)) && !strchr(":/\\", cutname[i-1]))
- X cutname[i++]=SLASH;
- X sprintf(cutname+i, CUTNAME+3, getpid(), buf->fd);
- X#else
- X sprintf(cutname, CUTNAME, o_directory, getpid(), buf->fd);
- X#endif
- X unlink(cutname);
- X }
- X}
- X
- X/* This function should be called just before termination of vi */
- Xcutend()
- X{
- X int i;
- X
- X /* free all named cut buffers, since they might be forcing an older
- X * tmp file to be retained.
- X */
- X for (i = 0; i < 27; i++)
- X {
- X cutfree(&named[i]);
- X }
- X}
- X
- X
- X/* This function is used to select the cut buffer to be used next */
- Xcutname(name)
- X int name; /* a single character */
- X{
- X cbname = name;
- X}
- X
- X
- X
- X
- X/* This function copies a selected segment of text to a cut buffer */
- Xcut(from, to)
- X MARK from; /* start of text to cut */
- X MARK to; /* end of text to cut */
- X{
- X int first; /* logical number of first block in cut */
- X int last; /* logical number of last block used in cut */
- X long line; /* a line number */
- X register struct cutbuf *cb;
- X register long l;
- X register int i;
- X register char *scan;
- X char *blkc;
- X
- X /* decide which cut buffer to use */
- X if (!cbname)
- X {
- X /* free up the last annonymous cut buffer */
- X cutfree(&annon[NANNONS - 1]);
- X
- X /* shift the annonymous cut buffers */
- X for (i = NANNONS - 1; i > 0; i--)
- X {
- X annon[i] = annon[i - 1];
- X }
- X
- X /* use the first annonymous cut buffer */
- X cb = annon;
- X cb->nblks = 0;
- X }
- X else if (cbname >= 'a' && cbname <= 'z')
- X {
- X cb = &named[cbname - 'a'];
- X cutfree(cb);
- X }
- X else if (cbname == '.')
- X {
- X cb = &named[26];
- X cutfree(cb);
- X }
- X else
- X {
- X msg("Invalid cut buffer name: \"%c", cbname);
- X cbname = '\0';
- X return;
- X }
- X cbname = '\0';
- X cb->fd = -1;
- X
- X /* detect whether we're doing a line mode cut */
- X cb->lnmode = (markidx(from) == 0 && markidx(to) == 0);
- X
- X /* ---------- */
- X
- X /* Reporting... */
- X if (markidx(from) == 0 && markidx(to) == 0)
- X {
- X rptlines = markline(to) - markline(from);
- X rptlabel = "yanked";
- X }
- X
- X /* ---------- */
- Xblksync();
- X /* find the first block in the cut */
- X line = markline(from);
- X for (first = 1; line > lnum[first]; first++)
- X {
- X }
- X
- X /* fetch text of the block containing that line */
- X blkc = scan = blkget(first)->c;
- X
- X /* find the mark in the block */
- X for (l = lnum[first - 1]; ++l < line; )
- X {
- X while (*scan++ != '\n')
- X {
- X }
- X }
- X scan += markidx(from);
- X
- X /* remember the offset of the start */
- X cb->start = scan - blkc;
- X
- X /* ---------- */
- X
- X /* find the last block in the cut */
- X line = markline(to);
- X for (last = first; line > lnum[last]; last++)
- X {
- X }
- X
- X /* fetch text of the block containing that line */
- X if (last != first)
- X {
- X blkc = scan = blkget(last)->c;
- X }
- X else
- X {
- X scan = blkc;
- X }
- X
- X /* find the mark in the block */
- X for (l = lnum[last - 1]; ++l < line; )
- X {
- X while (*scan++ != '\n')
- X {
- X }
- X }
- X if (markline(to) <= nlines)
- X {
- X scan += markidx(to);
- X }
- X
- X /* remember the offset of the end */
- X cb->end = scan - blkc;
- X
- X /* ------- */
- X
- X /* remember the physical block numbers of all included blocks */
- X cb->nblks = last - first;
- X if (cb->end > 0)
- X {
- X cb->nblks++;
- X }
- X cb->phys = (short *)malloc((unsigned)(cb->nblks * sizeof(short)));
- X for (i = 0; i < cb->nblks; i++)
- X {
- X cb->phys[i] = hdr.n[first++];
- X }
- X}
- X
- X
- Xstatic readcutblk(cb, blkno)
- X struct cutbuf *cb;
- X int blkno;
- X{
- X int fd; /* either tmpfd or cb->fd */
- X
- X /* decide which fd to use */
- X if (cb->fd >= 0)
- X {
- X fd = cb->fd;
- X }
- X else
- X {
- X fd = tmpfd;
- X }
- X
- X /* get the block */
- X lseek(fd, (long)cb->phys[blkno] * (long)BLKSIZE, 0);
- X if (read(fd, tmpblk.c, BLKSIZE) != BLKSIZE)
- X {
- X msg("Error reading back from tmp file for pasting!");
- X }
- X}
- X
- X
- X/* This function inserts text from a cut buffer, and returns the MARK where
- X * insertion ended. Return MARK_UNSET on errors.
- X */
- XMARK paste(at, after, retend)
- X MARK at; /* where to insert the text */
- X int after; /* boolean: insert after mark? (rather than before) */
- X int retend; /* boolean: return end marker (rather than start) */
- X{
- X register struct cutbuf *cb;
- X register int i;
- X
- X /* decide which cut buffer to use */
- X if (cbname >= 'a' && cbname <= 'z')
- X {
- X cb = &named[cbname - 'a'];
- X }
- X else if (cbname >= '1' && cbname <= '9')
- X {
- X cb = &annon[cbname - '1'];
- X }
- X else if (cbname == '.')
- X {
- X cb = &named[26];
- X }
- X else if (!cbname)
- X {
- X cb = annon;
- X }
- X else
- X {
- X msg("Invalid cut buffer name: \"%c", cbname);
- X return MARK_UNSET;
- X }
- X
- X /* make sure it isn't empty */
- X if (cb->nblks == 0)
- X {
- X if (cbname)
- X msg("Cut buffer \"%c is empty", cbname);
- X else
- X msg("Cut buffer is empty");
- X cbname = '\0';
- X return MARK_UNSET;
- X }
- X cbname = '\0';
- X
- X /* adjust the insertion MARK for "after" and line-mode cuts */
- X if (cb->lnmode)
- X {
- X at &= ~(BLKSIZE - 1);
- X if (after)
- X {
- X at += BLKSIZE;
- X }
- X }
- X else if (after)
- X {
- X /* careful! if markidx(at) == 0 we might be pasting into an
- X * empty line -- so we can't blindly increment "at".
- X */
- X if (markidx(at) == 0)
- X {
- X pfetch(markline(at));
- X if (plen != 0)
- X {
- X at++;
- X }
- X }
- X else
- X {
- X at++;
- X }
- X }
- X
- X /* put a copy of the "at" mark in the mark[] array, so it stays in
- X * sync with changes made via add().
- X */
- X mark[27] = at;
- X
- X /* simple one-block paste? */
- X if (cb->nblks == 1)
- X {
- X /* get the block */
- X readcutblk(cb, 0);
- X
- X /* isolate the text we need within it */
- X if (cb->end)
- X {
- X tmpblk.c[cb->end] = '\0';
- X }
- X
- X /* insert it */
- X ChangeText
- X {
- X add(at, &tmpblk.c[cb->start]);
- X }
- X }
- X else
- X {
- X /* multi-block paste */
- X
- X ChangeText
- X {
- X i = cb->nblks - 1;
- X
- X /* add text from the last block first */
- X if (cb->end > 0)
- X {
- X readcutblk(cb, i);
- X tmpblk.c[cb->end] = '\0';
- X add(at, tmpblk.c);
- X i--;
- X }
- X
- X /* add intervening blocks */
- X while (i > 0)
- X {
- X readcutblk(cb, i);
- X add(at, tmpblk.c);
- X i--;
- X }
- X
- X /* add text from the first cut block */
- X readcutblk(cb, 0);
- X add(at, &tmpblk.c[cb->start]);
- X }
- X }
- X
- X /* Reporting... */
- X rptlines = markline(mark[27]) - markline(at);
- X rptlabel = "pasted";
- X
- X /* correct the redraw range */
- X redrawafter = preredraw = markline(at);
- X postredraw = markline(mark[27]);
- X
- X /* return the mark at the beginning of inserted text */
- X if (retend)
- X {
- X return mark[27] - 1L;
- X }
- X return at;
- X}
- eof
- if test `wc -c <cut.c` -ne 10357
- then
- echo cut.c damaged!
- fi
- fi
-
- exit 0
- -------------------------------------------------------------------------------
- Steve Kirkendall kirkenda@cs.pdx.edu uunet!tektronix!psueea!eecs!kirkenda
-