Vile 03/17 - vi feel-alike (multi-window)
Paul Fox
pgf at cayman.COM
Sat Jun 8 08:09:16 AEST 1991
#!/bin/sh
# this is vileshar.03 (part 3 of Vile)
# do not concatenate these parts, unpack them in order with /bin/sh
# file crypt.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
echo 'x - continuing file crypt.c'
sed 's/^X//' << 'SHAR_EOF' >> 'crypt.c' &&
X * file from one computer should be able to be decrypted
X * on another computer.
X *
X * 3. The encryption had to be inexpensive, both in terms
X * of speed and space.
X *
X * 4. The system needed to be secure against all but the
X * most determined of attackers.
X *
X * For encryption of a block of data, one calls crypt passing
X * a pointer to the data block and its length. The data block is
X * encrypted in place, that is, the encrypted output overwrites
X * the input. Decryption is totally isomorphic, and is performed
X * in the same manner by the same routine.
X *
X * Before using this routine for encrypting data, you are expected
X * to specify an encryption key. This key is an arbitrary string,
X * to be supplied by the user. To set the key takes two calls to
X * crypt(). First, you call
X *
X * crypt(NULL, vector)
X *
X * This resets all internal control information. Typically (and
X * specifically in the case on MICRO-emacs) you would use a "vector"
X * of 0. Other values can be used to customize your editor to be
X * "incompatable" with the normally distributed version. For
X * this purpose, the best results will be obtained by avoiding
X * multiples of 95.
X *
X * Then, you "encrypt" your password by calling
X *
X * crypt(pass, strlen(pass))
X *
X * where "pass" is your password string. Crypt() will destroy
X * the original copy of the password (it becomes encrypted),
X * which is good. You do not want someone on a multiuser system
X * to peruse your memory space and bump into your password.
X * Still, it is a better idea to erase the password buffer to
X * defeat memory perusal by a more technical snooper.
X *
X * For the interest of cryptologists, at the heart of this
X * function is a Beaufort Cipher. The cipher alphabet is the
X * range of printable characters (' ' to '~'), all "control"
X * and "high-bit" characters are left unaltered.
X *
X * The key is a variant autokey, derived from a wieghted sum
X * of all the previous clear text and cipher text. A counter
X * is used as salt to obiterate any simple cyclic behavior
X * from the clear text, and key feedback is used to assure
X * that the entire message is based on the original key,
X * preventing attacks on the last part of the message as if
X * it were a pure autokey system.
X *
X * Overall security of encrypted data depends upon three
X * factors: the fundamental cryptographic system must be
X * difficult to compromise; exhaustive searching of the key
X * space must be computationally expensive; keys and plaintext
X * must remain out of sight. This system satisfies this set
X * of conditions to within the degree desired for MicroEMACS.
X *
X * Though direct methods of attack (against systems such as
X * this) do exist, they are not well known and will consume
X * considerable amounts of computing time. An exhaustive
X * search requires over a billion investigations, on average.
X *
X * The choice, entry, storage, manipulation, alteration,
X * protection and security of the keys themselves are the
X * responsiblity of the user.
X *
X **********/
X
crypt(bptr, len)
register char *bptr; /* buffer of characters to be encrypted */
register int len; /* number of characters in the buffer */
{
X register int cc; /* current character being considered */
X
X static long key = 0; /* 29 bit encipherment key */
X static int salt = 0; /* salt to spice up key with */
X
X if (!bptr) { /* is there anything here to encrypt? */
X key = len; /* set the new key */
X salt = len; /* set the new salt */
X return;
X }
X while (len--) { /* for every character in the buffer */
X
X cc = *bptr; /* get a character out of the buffer */
X
X /* only encipher printable characters */
X if ((cc >= ' ') && (cc <= '~')) {
X
/** If the upper bit (bit 29) is set, feed it back into the key. This
X assures us that the starting key affects the entire message. **/
X
X key &= 0x1FFFFFFFL; /* strip off overflow */
X if (key & 0x10000000L) {
X key ^= 0x0040A001L; /* feedback */
X }
X
/** Down-bias the character, perform a Beaufort encipherment, and
X up-bias the character again. We want key to be positive
X so that the left shift here will be more portable and the
X mod95() faster **/
X
X cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
X
/** the salt will spice up the key a little bit, helping to obscure
X any patterns in the clear text, particularly when all the
X characters (or long sequences of them) are the same. We do
X not want the salt to go negative, or it will affect the key
X too radically. It is always a good idea to chop off cyclics
X to prime values. **/
X
X if (++salt >= 20857) { /* prime modulus */
X salt = 0;
X }
X
/** our autokey (a special case of the running key) is being
X generated by a wieghted checksum of clear text, cipher
X text, and salt. **/
X
X key = key + key + cc + *bptr + salt;
X }
X *bptr++ = cc; /* put character back into buffer */
X }
X return;
}
X
static int mod95(val)
X
register int val;
X
{
X /* The mathematical MOD does not match the computer MOD */
X
X /* Yes, what I do here may look strange, but it gets the
X job done, and portably at that. */
X
X while (val >= 9500)
X val -= 9500;
X while (val >= 950)
X val -= 950;
X while (val >= 95)
X val -= 95;
X while (val < 0)
X val += 95;
X return (val);
}
#else
nocrypt()
{
}
#endif
SHAR_EOF
echo 'File crypt.c is complete' &&
chmod 0444 crypt.c ||
echo 'restore of crypt.c failed'
Wc_c="`wc -c < 'crypt.c'`"
test 6989 -eq "$Wc_c" ||
echo 'crypt.c: original size 6989, current size' "$Wc_c"
# ============= csrch.c ==============
echo 'x - extracting csrch.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'csrch.c' &&
X
#include "estruct.h"
#include "edef.h"
X
/* These functions perform vi's on-this-line character scanning functions.
X written for vile by Paul Fox, (c)1990
*/
static short lastscan;
static short lastchar;
#define BACK 0
#define FORW 1
#define DIREC 1
X
#define F 0
#define T 2
#define TYPE 2
X
X
fscan(f,n,c)
{
X int i = 0;
X int doto;
X
X if (n <= 0) n = 1;
X
X lastchar = c;
X lastscan = FORW;
X
X doto = curwp->w_doto;
X
X i = doto+1;
X while(i < llength(curwp->w_dotp)) {
X if ( c == lgetc(curwp->w_dotp,i)) {
X doto = i;
X n--;
X if (!n) break;
X }
X i++;
X }
X
X if ( i == llength(curwp->w_dotp)) {
X TTbeep();
X return(FALSE);
X }
X if (doingopcmd)
X doto++;
X
X curwp->w_doto = doto;
X curwp->w_flag |= WFMOVE;
X return(TRUE);
X
}
X
bscan(f,n,c)
{
X int i = 0;
X int doto;
X
X if (n <= 0) n = 1;
X
X lastchar = c;
X lastscan = BACK;
X
X doto = curwp->w_doto;
X
X i = doto-1;
X while(i >= 0) {
X if ( c == lgetc(curwp->w_dotp,i)) {
X doto = i;
X n--;
X if (!n) break;
X }
X i--;
X }
X
X if ( i < 0 ) {
X TTbeep();
X return(FALSE);
X }
X
X curwp->w_doto = doto;
X curwp->w_flag |= WFMOVE;
X return(TRUE);
X
}
X
/* f */
fcsrch(f,n)
{
X register int c;
X
X c = kbd_key();
X if (c == quotec)
X c = tgetc();
X else if (c == abortc)
X return FALSE;
X else
X c = kcod2key(c);
X
X return(fscan(f,n,c));
}
X
/* F */
bcsrch(f,n)
{
X register int c;
X
X c = kbd_key();
X if (c == quotec)
X c = tgetc();
X else if (c == abortc)
X return FALSE;
X else
X c = kcod2key(c);
X
X return(bscan(f,n,c));
}
X
/* t */
fcsrch_to(f,n)
{
X int s;
X s = fcsrch(f,n);
X if (s == TRUE)
X s = backchar(FALSE,1);
X lastscan |= T;
X return(s);
}
X
/* T */
bcsrch_to(f,n)
{
X int s;
X s = bcsrch(f,n);
X if (s == TRUE)
X s = forwchar(FALSE,1);
X lastscan |= T;
X return(s);
}
X
/* ; */
rep_csrch(f,n)
{
X int s;
X int ls = lastscan;
X
X if ((ls & DIREC) == FORW) {
X s = fscan(f,n,lastchar);
X if ((ls & TYPE) == T) {
X if (s == TRUE)
X s = backchar(FALSE,1);
X lastscan |= T;
X }
X return(s);
X } else {
X s = bscan(f,n,lastchar);
X if ((ls & TYPE) == T) {
X if (s == TRUE)
X s = forwchar(FALSE,1);
X lastscan |= T;
X }
X return(s);
X }
}
X
/* , */
rev_csrch(f,n)
{
X int s;
X
X lastscan ^= DIREC;
X s = rep_csrch(f,n);
X lastscan ^= DIREC;
X return(s);
}
SHAR_EOF
chmod 0444 csrch.c ||
echo 'restore of csrch.c failed'
Wc_c="`wc -c < 'csrch.c'`"
test 2171 -eq "$Wc_c" ||
echo 'csrch.c: original size 2171, current size' "$Wc_c"
# ============= dg10.c ==============
echo 'x - extracting dg10.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dg10.c' &&
/*
X * The routines in this file provide support for the Data General Model 10
X * Microcomputer.
X */
X
#define termdef 1 /* don't define "term" external */
X
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
X
#if DG10
X
#define NROW 24 /* Screen size. */
#define NCOL 80 /* Edit if you want to. */
#define NPAUSE 100 /* # times thru update to pause */
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define BEL 0x07 /* BEL character. */
#define ESC 30 /* DG10 ESC character. */
X
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int dg10kopen();
extern int dg10kclose();
extern int dg10move();
extern int dg10eeol();
extern int dg10eeop();
extern int dg10beep();
extern int dg10open();
extern int dg10rev();
extern int dg10close();
extern int dg10cres();
X
#if COLOR
extern int dg10fcol();
extern int dg10bcol();
X
int cfcolor = -1; /* current forground color */
int cbcolor = -1; /* current background color */
int ctrans[] = { /* emacs -> DG10 color translation table */
X 0, 4, 2, 6, 1, 5, 3, 7};
#endif
X
/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
TERM term = {
X NROW-1,
X NROW-1,
X NCOL,
X NCOL,
X MARGIN,
X SCRSIZ,
X NPAUSE,
X dg10open,
X dg10close,
X dg10kopen,
X dg10kclose,
X ttgetc,
X ttputc,
X ttflush,
X dg10move,
X dg10eeol,
X dg10eeop,
X dg10beep,
X dg10rev,
X dg10cres
#if COLOR
X , dg10fcol,
X dg10bcol
#endif
};
X
#if COLOR
dg10fcol(color) /* set the current output color */
X
int color; /* color to set */
X
{
X if (color == cfcolor)
X return;
X ttputc(ESC);
X ttputc(0101);
X ttputc(ctrans[color]);
X cfcolor = color;
}
X
dg10bcol(color) /* set the current background color */
X
int color; /* color to set */
X
{
X if (color == cbcolor)
X return;
X ttputc(ESC);
X ttputc(0102);
X ttputc(ctrans[color]);
X cbcolor = color;
}
#endif
X
dg10move(row, col)
{
X ttputc(16);
X ttputc(col);
X ttputc(row);
}
X
dg10eeol()
{
X ttputc(11);
}
X
dg10eeop()
{
#if COLOR
X dg10fcol(gfcolor);
X dg10bcol(gbcolor);
#endif
X ttputc(ESC);
X ttputc(0106);
X ttputc(0106);
}
X
dg10rev(state) /* change reverse video state */
X
int state; /* TRUE = reverse, FALSE = normal */
X
{
#if COLOR
X if (state == TRUE) {
X dg10fcol(0);
X dg10bcol(7);
X }
#else
X ttputc(ESC);
X ttputc(state ? 0104: 0105);
#endif
}
X
dg10cres() /* change screen resolution */
X
{
X return(TRUE);
}
X
spal() /* change palette string */
X
{
X /* Does nothing here */
}
X
dg10beep()
{
X ttputc(BEL);
X ttflush();
}
X
dg10open()
{
X strcpy(sres, "NORMAL");
X revexist = TRUE;
X ttopen();
}
X
dg10close()
X
{
#if COLOR
X dg10fcol(7);
X dg10bcol(0);
#endif
X ttclose();
}
X
dg10kopen()
X
{
}
X
dg10kclose()
X
{
}
X
#if FLABEL
fnclabel(f, n) /* label a function key */
X
int f,n; /* default flag, numeric argument [unused] */
X
{
X /* on machines with no function keys...don't bother */
X return(TRUE);
}
#endif
#else
dg10hello()
{
}
#endif
SHAR_EOF
chmod 0444 dg10.c ||
echo 'restore of dg10.c failed'
Wc_c="`wc -c < 'dg10.c'`"
test 3333 -eq "$Wc_c" ||
echo 'dg10.c: original size 3333, current size' "$Wc_c"
# ============= display.c ==============
echo 'x - extracting display.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'display.c' &&
/*
X * The functions in this file handle redisplay. There are two halves, the
X * ones that update the virtual display screen, and the ones that make the
X * physical display screen the same as the virtual display screen. These
X * functions use hints that are left in the windows by the commands.
X *
X */
X
X
#include <stdio.h>
#include <varargs.h>
#include "estruct.h"
#include "edef.h"
#if UNIX
#include <signal.h>
#include <termio.h>
#if ODT
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/ptem.h>
#endif
#endif
X
typedef struct VIDEO {
X int v_flag; /* Flags */
#if COLOR
X int v_fcolor; /* current forground color */
X int v_bcolor; /* current background color */
X int v_rfcolor; /* requested forground color */
X int v_rbcolor; /* requested background color */
#endif
X /* allocate 4 bytes here, and malloc 4 bytes less than we need,
X to keep malloc from rounding up. */
X char v_text[4]; /* Screen data. */
} VIDEO;
X
#define VFCHG 0x0001 /* Changed flag */
#define VFEXT 0x0002 /* extended (beyond column 80) */
#define VFREV 0x0004 /* reverse video status */
#define VFREQ 0x0008 /* reverse video request */
#define VFCOL 0x0010 /* color change requested */
X
VIDEO **vscreen; /* Virtual screen. */
#if ! MEMMAP
VIDEO **pscreen; /* Physical screen. */
#endif
X
X
int displaying = FALSE;
#ifdef SIGWINCH
/* for window size changes */
int chg_width, chg_height;
#endif
X
/*
X * Initialize the data structures used by the display code. The edge vectors
X * used to access the screens are set up. The operating system's terminal I/O
X * channel is set up. All the other things get initialized at compile time.
X * The original window has "WFCHG" set, so that it will get completely
X * redrawn on the first call to "update".
X */
vtinit()
{
X register int i;
X register VIDEO *vp;
X
X TTopen(); /* open the screen */
X TTkopen(); /* open the keyboard */
X TTrev(FALSE);
X vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
X
X if (vscreen == NULL)
X exit(1);
X
#if ! MEMMAP
X pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
X
X if (pscreen == NULL)
X exit(1);
#endif
X
X for (i = 0; i < term.t_mrow; ++i) {
X /* struct VIDEO already has 4 of the bytes */
X vp = (VIDEO *) malloc(sizeof(struct VIDEO) + term.t_mcol - 4);
X
X if (vp == NULL)
X exit(1);
X
X vp->v_flag = 0;
#if COLOR
X vp->v_rfcolor = 7;
X vp->v_rbcolor = 0;
#endif
X vscreen[i] = vp;
#if ! MEMMAP
X /* struct VIDEO already has 4 of the bytes */
X vp = (VIDEO *) malloc(sizeof(struct VIDEO) + term.t_mcol - 4);
X
X if (vp == NULL)
X exit(1);
X
X vp->v_flag = 0;
X pscreen[i] = vp;
#endif
X }
}
X
/*
X * Clean up the virtual terminal system, in anticipation for a return to the
X * operating system. Move down to the last line and advance, to make room
X * for the system prompt. Shut down the channel to the
X * terminal.
X */
vttidy(f)
{
X ttclean(f); /* does it all now */
}
X
/*
X * Set the virtual cursor to the specified row and column on the virtual
X * screen. There is no checking for nonsense values.
X */
vtmove(row, col)
{
X vtrow = row;
X vtcol = col;
}
X
/* Write a character to the virtual screen. The virtual row and
X column are updated. If we are not yet on left edge, don't print
X it yet. If the line is too long put a ">" in the last column.
X This routine only puts printing characters into the virtual
X terminal buffers. Only column overflow is checked.
*/
X
vtputc(c,list)
int c,list;
{
X register VIDEO *vp; /* ptr to line being updated */
X
X vp = vscreen[vtrow];
X
X if (c == '\t' && !list) {
X do {
X vtputc(' ',FALSE);
X } while (((vtcol + taboff)&TABMASK) != 0);
X } else if (c == '\n' && !list) {
X return;
X } else if (vtcol >= term.t_ncol) {
X ++vtcol;
X vp->v_text[term.t_ncol - 1] = '>';
X } else if (!isprint(c)) {
X vtputc('^',FALSE);
X vtputc(toalpha(c),FALSE);
X } else {
X if (vtcol >= 0)
X vp->v_text[vtcol] = c;
X ++vtcol;
X }
}
X
vtgetc(col)
{
X return vscreen[vtrow]->v_text[col];
}
X
vtputsn(s,n)
char *s;
{
X int c;
X while (n-- && (c = *s++) != 0)
X vtputc(c,FALSE);
}
X
/*
X * Erase from the end of the software cursor to the end of the line on which
X * the software cursor is located.
X */
vteeol()
{
X while (vtcol < term.t_ncol)
X vtputc(' ',FALSE);
}
X
/* upscreen: user routine to force a screen update
X always finishes complete update */
upscreen(f, n)
{
X update(TRUE);
X return(TRUE);
}
X
int scrflags;
/*
X * Make sure that the display is right. This is a three part process. First,
X * scan through all of the windows looking for dirty ones. Check the framing,
X * and refresh the screen. Second, make sure that "currow" and "curcol" are
X * correct for the current window. Third, make the virtual and physical
X * screens the same.
X */
update(force)
int force; /* force update past type ahead? */
{
X register WINDOW *wp;
X int screencol;
X
#if TYPEAH
X if (force == FALSE && typahead())
X return(SORTOFTRUE);
#endif
#if VISMAC == 0
X if (force == FALSE && (kbdmode == PLAY || dotcmdmode == PLAY))
X return(TRUE);
#endif
X
X displaying = TRUE;
X
X /* first, propagate mode line changes to all instances of
X a buffer displayed in more than one window */
X wp = wheadp;
X while (wp != NULL) {
X if (wp->w_flag & WFMODE) {
X if (wp->w_bufp->b_nwnd > 1) {
X /* make sure all previous windows have this */
X register WINDOW *owp;
X owp = wheadp;
X while (owp != NULL) {
X if (owp->w_bufp == wp->w_bufp)
X owp->w_flag |= WFMODE;
X owp = owp->w_wndp;
X }
X }
X }
X wp = wp->w_wndp;
X }
X
X /* update any windows that need refreshing */
X wp = wheadp;
X while (wp != NULL) {
X if (wp->w_flag) {
X /* if the window has changed, service it */
X reframe(wp); /* check the framing */
X if (wp->w_flag & (WFKILLS|WFINS)) {
X scrflags |= (wp->w_flag & (WFINS|WFKILLS));
X wp->w_flag &= ~(WFKILLS|WFINS);
X }
X if ((wp->w_flag & ~(/* WFMOVE| */WFMODE)) == WFEDIT)
X updone(wp); /* update EDITed line */
X else if (wp->w_flag & ~(WFMOVE))
X updall(wp); /* update all lines */
X if (scrflags || (wp->w_flag & WFMODE))
X modeline(wp); /* update modeline */
X wp->w_flag = 0;
X wp->w_force = 0;
X }
X /* on to the next window */
X wp = wp->w_wndp;
X }
X
X /* recalc the current hardware cursor location */
X screencol = updpos();
X
#if MEMMAP
X /* update the cursor and flush the buffers */
X movecursor(currow, screencol);
#endif
X
X /* check for lines to de-extend */
X upddex();
X
#if NeWS
X newsupd(force) ;
#else
X /* if screen is garbage, re-plot it */
X if (sgarbf)
X updgar();
X
X /* update the virtual screen to the physical screen */
X updupd(force);
#endif
X
X /* update the cursor and flush the buffers */
X movecursor(currow, screencol);
X TTflush();
X displaying = FALSE;
#if SIGWINCH
X while (chg_width || chg_height)
X newscreensize(chg_height,chg_width);
#endif
X return(TRUE);
}
X
/* reframe: check to see if the cursor is on in the window
X and re-frame it if needed or wanted */
reframe(wp)
WINDOW *wp;
{
X register LINE *lp;
X register int i;
X
X /* if not a requested reframe, check for a needed one */
X if ((wp->w_flag & WFFORCE) == 0) {
#if SCROLLCODE
X /* loop from one line above the window to one line after */
X lp = lback(wp->w_linep);
X for (i = -1; i <= wp->w_ntrows; i++)
#else
X /* loop through the window */
X lp = wp->w_linep;
X for (i = 0; i < wp->w_ntrows; i++)
#endif
X {
X
X /* if the line is in the window, no reframe */
X if (lp == wp->w_dotp) {
#if SCROLLCODE
X /* if not _quite_ in, we'll reframe gently */
X if ( i < 0 || i == wp->w_ntrows) {
X /* if the terminal can't help, then
X we're simply outside */
X if (term.t_scroll == NULL)
X i = wp->w_force;
X break;
X }
#endif
X return(TRUE);
X }
X
X /* if we are at the end of the file, reframe */
X if (i >= 0 && lp == wp->w_bufp->b_linep)
X break;
X
X /* on to the next line */
X lp = lforw(lp);
X }
X }
X
#if SCROLLCODE
X if (i == -1) { /* we're just above the window */
X i = 1; /* put dot at first line */
X scrflags |= WFINS;
X } else if (i == wp->w_ntrows) { /* we're just below the window */
X i = -1; /* put dot at last line */
X scrflags |= WFKILLS;
X } else /* put dot where requested */
#endif
X i = wp->w_force; /* (is 0, unless reposition() was called) */
X
X wp->w_flag |= WFMODE;
X
X /* w_force specifies which line of the window dot should end up on */
X /* positive --> lines from the top */
X /* negative --> lines from the bottom */
X /* zero --> middle of window */
X
X /* enforce some maximums */
X if (i > 0) {
X if (--i >= wp->w_ntrows)
X i = wp->w_ntrows - 1;
X } else if (i < 0) { /* negative update???? */
X i += wp->w_ntrows;
X if (i < 0)
X i = 0;
X } else
X i = wp->w_ntrows / 2;
X
X /* backup to new line at top of window */
X lp = wp->w_dotp;
X while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
X --i;
X lp = lback(lp);
X }
X
X if (lp == wp->w_bufp->b_linep)
X lp = lback(lp);
X
X /* and reset the current line-at-top-of-window */
X wp->w_linep = lp;
X wp->w_flag |= WFHARD;
X wp->w_flag &= ~WFFORCE;
X return(TRUE);
}
X
/* updone: update the current line to the virtual screen */
X
updone(wp)
WINDOW *wp; /* window to update current line in */
{
X register LINE *lp; /* line to update */
X register int sline; /* physical screen line to update */
X
X /* search down the line we want */
X lp = wp->w_linep;
X sline = wp->w_toprow;
X while (lp != wp->w_dotp) {
X ++sline;
X lp = lforw(lp);
X }
X
X l_to_vline(wp,lp,sline);
X vteeol();
}
X
/* updall: update all the lines in a window on the virtual screen */
X
updall(wp)
WINDOW *wp; /* window to update lines in */
{
X register LINE *lp; /* line to update */
X register int sline; /* physical screen line to update */
X
X /* search down the lines, updating them */
X lp = wp->w_linep;
X sline = wp->w_toprow;
X while (sline < wp->w_toprow + wp->w_ntrows) {
X l_to_vline(wp,lp,sline);
X vteeol();
X if (lp != wp->w_bufp->b_linep)
X lp = lforw(lp);
X ++sline;
X }
X
}
X
/* line to virtual screen line */
l_to_vline(wp,lp,sline)
WINDOW *wp; /* window to update lines in */
LINE *lp;
{
X int i,c;
X
X /* and update the virtual line */
X vscreen[sline]->v_flag |= VFCHG;
X vscreen[sline]->v_flag &= ~VFREQ;
X if (wp->w_sideways)
X taboff = wp->w_sideways;
X if (lp != wp->w_bufp->b_linep) {
X vtmove(sline, -wp->w_sideways);
X i = 0;
X while ( i < llength(lp) ) {
X vtputc(lgetc(lp, i), wp->w_bufp->b_mode & MDLIST);
X ++i;
X }
X vtputc('\n', wp->w_bufp->b_mode & MDLIST);
X if (wp->w_sideways) {
X vscreen[sline]->v_text[0] = '<';
X if (vtcol < 1) vtcol = 1;
X }
X } else {
X vtmove(sline, 0);
X vtputc('~',FALSE);
X }
X taboff = 0;
#if COLOR
X vscreen[sline]->v_rfcolor = wp->w_fcolor;
X vscreen[sline]->v_rbcolor = wp->w_bcolor;
#endif
}
X
/* updpos: update the position of the hardware cursor and handle extended
X lines. This is the only update for simple moves.
X returns the screen column for the cursor */
updpos()
{
X register LINE *lp;
X register int c;
X register int i;
X
X /* find the current row */
X lp = curwp->w_linep;
X currow = curwp->w_toprow;
X while (lp != curwp->w_dotp) {
X ++currow;
X lp = lforw(lp);
X if (lp == curwp->w_linep) {
X mlwrite("Bug: lost dot updpos(). setting at top");
X curwp->w_linep = curwp->w_dotp = lforw(curbp->b_linep);
X currow = curwp->w_toprow;
X }
X }
X
X /* find the current column */
X curcol = -curwp->w_sideways;
X i = 0;
X while (i < curwp->w_doto) {
X c = lgetc(lp, i++);
X if (((curwp->w_bufp->b_mode&MDLIST) == 0) && c == '\t') {
X do {
X curcol++;
X } while (((curcol + curwp->w_sideways)&TABMASK) != 0);
X } else {
X if (!isprint(c))
X ++curcol;
X ++curcol;
X }
X
X }
X
X /* if extended, flag so and update the virtual line image */
X if (curcol >= term.t_ncol - 1) {
X return updext_past();
X } else if (curwp->w_sideways && curcol < 1){
X return updext_before();
X } else {
X return curcol;
X }
}
X
/* upddex: de-extend any line that deserves it */
X
upddex()
{
X register WINDOW *wp;
X register LINE *lp;
X register int i,j;
X
X wp = wheadp;
X
X while (wp != NULL) {
X lp = wp->w_linep;
X i = wp->w_toprow;
X
X while (i < wp->w_toprow + wp->w_ntrows) {
X if (vscreen[i]->v_flag & VFEXT) {
X if ((wp != curwp) || (lp != wp->w_dotp) ||
X (curcol < term.t_ncol - 1)) {
X l_to_vline(wp,lp,i);
X vteeol();
X /* this line no longer is extended */
X vscreen[i]->v_flag &= ~VFEXT;
X }
X }
X lp = lforw(lp);
X ++i;
X }
X /* and onward to the next window */
X wp = wp->w_wndp;
X }
}
X
/* updgar: if the screen is garbage, clear the physical screen and
X the virtual screen and force a full update */
X
updgar()
{
X register char *txt;
X register int i,j;
X
X for (i = 0; i < term.t_nrow; ++i) {
X vscreen[i]->v_flag |= VFCHG;
#if REVSTA
X vscreen[i]->v_flag &= ~VFREV;
#endif
#if COLOR
X vscreen[i]->v_fcolor = gfcolor;
X vscreen[i]->v_bcolor = gbcolor;
#endif
#if ! MEMMAP
X txt = pscreen[i]->v_text;
X for (j = 0; j < term.t_ncol; ++j)
X txt[j] = ' ';
#endif
X }
X
X movecursor(0, 0); /* Erase the screen. */
X (*term.t_eeop)();
X sgarbf = FALSE; /* Erase-page clears */
X mpresf = FALSE; /* the message area. */
#if COLOR
X mlerase(); /* needs to be cleared if colored */
#endif
}
X
/* updupd: update the physical screen from the virtual screen */
X
updupd(force)
int force; /* forced update flag */
{
X register VIDEO *vp1;
X register int i;
#if SCROLLCODE
X if (scrflags & WFKILLS)
X scrolls(FALSE);
X if (scrflags & WFINS)
X scrolls(TRUE);
X scrflags = 0;
#endif
X
X for (i = 0; i < term.t_nrow; ++i) {
X vp1 = vscreen[i];
X
X /* for each line that needs to be updated*/
X if ((vp1->v_flag & VFCHG) != 0) {
#if TYPEAH
X if (force == FALSE && typahead())
X return(TRUE);
#endif
#if MEMMAP
X updateline(i, vp1);
#else
X updateline(i, vp1, pscreen[i]);
#endif
X }
X }
X return(TRUE);
}
X
#if SCROLLCODE
/* optimize out scrolls (line breaks, and newlines) */
/* arg. chooses between looking for inserts or deletes */
int
scrolls(inserts) /* returns true if it does something */
{
X struct VIDEO *vpv ; /* virtual screen image */
X struct VIDEO *vpp ; /* physical screen image */
X int i, j, k ;
X int rows, cols ;
X int first, match, count, ptarget, vtarget, end ;
X int longmatch, longcount;
X int from, to;
X
X if (!term.t_scroll) /* no way to scroll */
X return FALSE;
X
X rows = term.t_nrow ;
X cols = term.t_ncol ;
X
X first = -1 ;
X for (i = 0; i < rows; i++) { /* find first wrong line */
X if (!texttest(i,i)) {
X first = i;
X break;
X }
X }
X
X if (first < 0)
X return FALSE; /* no text changes */
X
X vpv = vscreen[first] ;
X vpp = pscreen[first] ;
X
X if (inserts) {
X /* determine types of potential scrolls */
X end = endofline(vpv->v_text,cols) ;
X if ( end == 0 )
X ptarget = first ; /* newlines */
X else if ( strncmp(vpp->v_text, vpv->v_text, end) == 0 )
X ptarget = first + 1 ; /* broken line newlines */
X else
X ptarget = first ;
X } else {
X vtarget = first + 1 ;
X }
X
X /* find the matching shifted area */
X match = -1 ;
X longmatch = -1;
X longcount = 0;
X from = inserts ? ptarget : vtarget;
X for (i = from+1; i < rows; i++) {
X if (inserts ? texttest(i,from) : texttest(from,i) ) {
X match = i ;
X count = 1 ;
X for (j=match+1, k=from+1; j<rows && k<rows; j++, k++) {
X if (inserts ? texttest(j,k) : texttest(k,j))
X count++ ;
X else
X break ;
X }
X if (longcount < count) {
X longcount = count;
X longmatch = match;
X }
X }
X }
X match = longmatch;
X count = longcount;
X
X if (!inserts) {
X /* full kill case? */
X if (match > 0 && texttest(first, match-1)) {
X vtarget-- ;
X match-- ;
X count++ ;
X }
X }
X
X /* do the scroll */
X if (match>0 && count>2) { /* got a scroll */
X /* move the count lines starting at ptarget to match */
X /* mlwrite("scrolls: move the %d lines starting at %d to %d",
X count,ptarget,match);
X */
X if (inserts) {
X from = ptarget;
X to = match;
X } else {
X from = match;
X to = vtarget;
X }
X scrscroll(from, to, count) ;
X for (i = 0; i < count; i++) {
X vpp = pscreen[to+i] ;
X vpv = vscreen[to+i];
X strncpy(vpp->v_text, vpv->v_text, cols) ;
X }
X if (inserts) {
X from = ptarget;
X to = match;
X } else {
X from = vtarget+count;
X to = match+count;
X }
X for (i = from; i < to; i++) {
X char *txt;
X txt = pscreen[i]->v_text;
X for (j = 0; j < term.t_ncol; ++j)
X txt[j] = ' ';
X vscreen[i]->v_flag |= VFCHG;
X }
X return(TRUE) ;
X }
X return(FALSE) ;
}
X
/* move the "count" lines starting at "from" to "to" */
scrscroll(from, to, count)
{
X ttrow = ttcol = -1;
X (*term.t_scroll)(from,to,count);
}
X
texttest(vrow,prow) /* return TRUE on text match */
int vrow, prow ; /* virtual, physical rows */
{
struct VIDEO *vpv = vscreen[vrow] ; /* virtual screen image */
struct VIDEO *vpp = pscreen[prow] ; /* physical screen image */
X
X return (!memcmp(vpv->v_text, vpp->v_text, term.t_ncol)) ;
}
X
/* return the index of the first blank of trailing whitespace */
int
endofline(s,n)
char *s ;
{
int i ;
X for (i = n - 1; i >= 0; i--)
X if (s[i] != ' ') return(i+1) ;
X return(0) ;
}
X
#endif /* SCROLLCODE */
X
X
/* updext_past: update the extended line which the cursor is currently
X on at a column greater than the terminal width. The line
X will be scrolled right or left to let the user see where
X the cursor is */
updext_past()
{
X register int lbound, rcursor;
X register LINE *lp; /* pointer to current line */
X register int j; /* index into line */
X
X /* calculate what column the real cursor will end up in */
X /* why is term.t_ncol in here? */
X rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
X lbound = curcol - rcursor;
X taboff = lbound + curwp->w_sideways;
X
X /* scan through the line outputing characters to the virtual screen */
X /* once we reach the left edge */
X vtmove(currow, -lbound-curwp->w_sideways); /* start scanning offscreen */
X lp = curwp->w_dotp; /* line to output */
X for (j = 0; j < llength(lp); ++j)
X vtputc(lgetc(lp, j), curwp->w_bufp->b_mode&MDLIST);
X vtputc('\n', curwp->w_bufp->b_mode&MDLIST);
X
X /* truncate the virtual line, restore tab offset */
X vteeol();
X taboff = 0;
X
X /* and put a '<' in column 1 */
X vscreen[currow]->v_text[0] = '<';
X vscreen[currow]->v_flag |= (VFEXT | VFCHG);
X return rcursor;
}
X
/* updext_before: update the extended line which the cursor is currently
X on at a column less than the terminal width. The line
X will be scrolled right or left to let the user see where
X the cursor is */
updext_before()
{
X register int lbound, rcursor;
X register LINE *lp; /* pointer to current line */
X register int j; /* index into line */
X
X /* calculate what column the real cursor will end up in */
X rcursor = (curcol % (term.t_ncol-term.t_margin));
X lbound = curcol - rcursor + 1;
X taboff = lbound;
X
X /* scan through the line outputing characters to the virtual screen */
X /* once we reach the left edge */
X vtmove(currow, -lbound); /* start scanning offscreen */
X lp = curwp->w_dotp; /* line to output */
X for (j = 0; j < llength(lp); ++j)
X vtputc(lgetc(lp, j), curwp->w_bufp->b_mode&MDLIST);
X vtputc('\n', curwp->w_bufp->b_mode&MDLIST);
X
X /* truncate the virtual line, restore tab offset */
X vteeol();
X taboff = 0;
X
X /* and put a '<' in column 1 */
X vscreen[currow]->v_text[0] = '<';
X vscreen[currow]->v_flag |= (VFEXT | VFCHG);
X return rcursor;
}
X
X
#if NeWS
newsupd(force) /* update the physical screen from the virtual screen */
int force; /* forced update flag */
{
register int i ;
struct VIDEO *vpv ; /* virtual screen image */
struct VIDEO *vpp ; /* physical screen image */
int bad, badcol, rows ;
X
X rows = term.t_nrow ;
X
X if (force == FALSE && typahead()) return ;
X if (sgarbf) {
X fastupdate() ;
X return ;
X }
X
X /* if enough lines are bad try to optimize scrolls/kills */
X for (bad = 0, i = 0; i < rows; ++i)
X if (!texttest(i,i)) {
X bad++ ;
X if (bad > 3) {
X if (!scrolls()) kills() ;
X break ;
X }
X }
X
X /* count bad lines, if enough need fixed redo whole screen */
X for (bad = 0, badcol = 0, i = 0; i < rows; ++i) {
X vpv = vscreen[i] ;
X vpv->v_flag &= ~(VFCHG|VFCOL) ; /* clear flag */
X if (!texttest(i,i)) {
X vpv->v_flag |= VFCHG ;
X bad++ ;
X }
X if (!colortest(i)) {
X vpv->v_flag |= VFCOL ;
X badcol++ ;
X }
X }
X if (bad == 0 && badcol > 0) { /* pure color update */
X colorupdate() ;
X return ;
X }
X if (bad > (3*rows)/4) { /* full update */
X fastupdate() ;
X return ;
X }
X
X /* Fix the bad lines one by one */
X for (i = 0; i < rows; ++i)
X if (vscreen[i]->v_flag & (VFCHG|VFCOL)) updateline(i) ;
}
X
X
/* optimize out scrolls (line breaks, and newlines) */
int scrolls() /* returns true if it does something */
{
struct VIDEO *vpv ; /* virtual screen image */
struct VIDEO *vpp ; /* physical screen image */
int i, j, k ;
int rows, cols ;
int first, match, count, ptarget, end ;
X
X rows = term.t_nrow ;
X cols = term.t_ncol ;
X
X first = -1 ;
X for (i = 0; i < rows; i++) /* find first wrong line */
X if (!texttest(i,i)) {first = i ; break ;}
X
X if (first < 0) return(FALSE) ; /* no text changes */
X
X vpv = vscreen[first] ;
X vpp = pscreen[first] ;
X
X /* determine types of potential scrolls */
X end = endofline(vpv->v_text,cols) ;
X if ( end == 0 )
X ptarget = first ; /* newlines */
X else if ( strncmp(vpp->v_text, vpv->v_text, end) == 0 )
X ptarget = first + 1 ; /* broken line newlines */
X else return(FALSE) ; /* no scrolls */
X
X /* find the matching shifted area */
X match = -1 ;
X for (i = ptarget+1; i < rows; i++) {
X if (texttest(i, ptarget)) {
X match = i ;
X count = 1 ;
X for (j=match+1, k=ptarget+1; j<rows && k<rows; j++, k++) {
X if (texttest(j,k))
X count++ ;
X else
X break ;
X }
X break ;
X }
X }
X
X /* do the scroll */
X if (match>0 && count>2) { /* got a scroll */
X newsscroll(ptarget, match, count) ;
X for (i = 0; i < count; i++) {
X vpv = vscreen[match+i] ; vpp = pscreen[match+i] ;
X strncpy(vpp->v_text, vpv->v_text, cols) ;
X }
X return(TRUE) ;
X }
X return(FALSE) ;
}
X
X
/* optimize out line kills (full and with a partial kill) */
int kills() /* returns true if it does something */
{
struct VIDEO *vpv ; /* virtual screen image */
struct VIDEO *vpp ; /* physical screen image */
int i, j, k ;
int rows, cols ;
int first, match, count, vtarget, end ;
X
X rows = term.t_nrow ;
X cols = term.t_ncol ;
X
X first = -1 ;
X for (i = 0; i < rows; i++) /* find first wrong line */
X if (!texttest(i,i)) {first = i ; break ;}
X
X if (first < 0) return(FALSE) ; /* no text changes */
X
X vpv = vscreen[first] ;
X vpp = pscreen[first] ;
X
X vtarget = first + 1 ;
X
X /* find the matching shifted area */
X match = -1 ;
X for (i = vtarget+1; i < rows; i++) {
X if (texttest(vtarget, i)) {
X match = i ;
X count = 1 ;
X for (j=match+1, k=vtarget+1; j<rows && k<rows; j++, k++) {
X if (texttest(k,j))
X count++ ;
X else
X break ;
X }
X break ;
X }
X }
X if (texttest(first, match-1)) { /* full kill case */
X vtarget-- ;
X match-- ;
X count++ ;
X }
X
X /* do the scroll */
X if (match>0 && count>2) { /* got a scroll */
X newsscroll(match, vtarget, count) ;
X for (i = 0; i < count; i++) {
X vpv = vscreen[vtarget+i] ; vpp = pscreen[vtarget+i] ;
X strncpy(vpp->v_text, vpv->v_text, cols) ;
X }
X return(TRUE) ;
X }
X return(FALSE) ;
}
X
X
texttest(vrow,prow) /* return TRUE on text match */
int vrow, prow ; /* virtual, physical rows */
{
struct VIDEO *vpv = vscreen[vrow] ; /* virtual screen image */
struct VIDEO *vpp = pscreen[prow] ; /* physical screen image */
X
X vpp->v_text[term.t_ncol] = 0 ;
X vpv->v_text[term.t_ncol] = 0 ;
X return (!strncmp(vpv->v_text, vpp->v_text, term.t_ncol)) ;
}
X
colortest(row) /* TRUE on color match */
int row ;
{
struct VIDEO *vpv = vscreen[row] ; /* virtual screen image */
X
X return (vpv->v_fcolor == vpv->v_rfcolor &&
X vpv->v_bcolor == vpv->v_rbcolor) ;
}
X
X
updateline(row)
int row ; /* row of screen to update */
{
struct VIDEO *vpv = vscreen[row] ; /* virtual screen image */
struct VIDEO *vpp = pscreen[row] ; /* physical screen image */
int end ;
X
X end = endofline(vpv->v_text, term.t_ncol) ;
X strncpy(vpp->v_text, vpv->v_text, term.t_ncol) ;
X vpv->v_text[end] = 0 ;
X newsputline(row, vpv->v_text, vpv->v_rfcolor, vpv->v_rbcolor) ;
X vpv->v_text[end] = ' ' ;
X vpv->v_fcolor = vpv->v_rfcolor;
X vpv->v_bcolor = vpv->v_rbcolor;
X vpv->v_flag &= ~(VFCHG|VFCOL); /* clear flag */
}
X
X
colorupdate()
{
struct VIDEO *vpv ; /* virtual screen image */
int row ;
X
X for (row=0; row<term.t_nrow; row++) { /* send the row colors */
X vpv = vscreen[row] ;
X if (vpv->v_flag & VFCOL) {
X newssetrowcolors(row, vpv->v_rfcolor, vpv->v_rbcolor) ;
X vpv->v_fcolor = vpv->v_rfcolor;
X vpv->v_bcolor = vpv->v_rbcolor;
X }
X vpv->v_flag &= ~VFCOL ;
X }
X
X newslocalupdate() ; /* ask for a screen refresh */
}
X
X
fastupdate() /* redo the entire screen fast */
{
int row ;
register char *cp, *first ;
struct VIDEO *vpv ; /* virtual screen image */
struct VIDEO *vpp ; /* physical screen image */
X
X /* send the row colors */
X for (row=0; row<term.t_nrow; row++) {
X vpv = vscreen[row] ;
X if (!colortest(row)) {
X newssetrowcolors(row, vpv->v_rfcolor, vpv->v_rbcolor) ;
X vpv->v_fcolor = vpv->v_rfcolor;
X vpv->v_bcolor = vpv->v_rbcolor;
X }
X vpv->v_flag &= ~VFCOL ;
X }
X
X /* virtual -> physical buffer */
X for (row=0; row<term.t_nrow; row++) {
X vpv = vscreen[row] ; vpp = pscreen[row] ;
X memcpy(vpp->v_text, vpv->v_text, term.t_ncol);
X vpp->v_text[term.t_ncol] = 0 ;
X vpv->v_text[term.t_ncol] = 0 ;
X vpv->v_flag &= ~VFCHG;
X }
X /* send the stuff */
X newscls() ;
X for (row=0; row<term.t_nrow; row++) {
X first = pscreen[row]->v_text ;
X /* don't send trailing blanks */
X cp = &first[endofline(first,term.t_ncol)] ;
X if (cp > first) {
X *cp = 0 ;
X newsfastputline(row, first) ;
X *cp = ' ' ;
X }
X }
X sgarbf = FALSE;
}
X
X
/* return the index of the first blank of trailing whitespace */
int endofline(s,n)
char *s ;
{
int i ;
X for (i = n - 1; i >= 0; i--)
X if (s[i] != ' ') return(i+1) ;
X return(0) ;
}
#else
X
/*
X * Update a single line. This does not know how to use insert or delete
X * character sequences; we are using VT52 functionality. Update the physical
X * row and column variables. It does try an exploit erase to end of line. The
X * RAINBOW version of this routine uses fast video.
X */
#if MEMMAP
/* UPDATELINE specific code for the IBM-PC and other compatables */
X
updateline(row, vp1)
X
int row; /* row of screen to update */
struct VIDEO *vp1; /* virtual screen image */
X
{
#if COLOR
X scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
X vp1->v_fcolor = vp1->v_rfcolor;
X vp1->v_bcolor = vp1->v_rbcolor;
#else
X if (vp1->v_flag & VFREQ)
X scwrite(row, vp1->v_text, 0, 7);
X else
X scwrite(row, vp1->v_text, 7, 0);
#endif
X vp1->v_flag &= ~(VFCHG | VFCOL); /* flag this line as changed */
X
}
X
#else
X
updateline(row, vp1, vp2)
X
int row; /* row of screen to update */
struct VIDEO *vp1; /* virtual screen image */
struct VIDEO *vp2; /* physical screen image */
X
{
#if RAINBOW
/* UPDATELINE specific code for the DEC rainbow 100 micro */
X
X register char *cp1;
X register char *cp2;
X register int nch;
X
X /* since we don't know how to make the rainbow do this, turn it off */
X flags &= (~VFREV & ~VFREQ);
X
X cp1 = &vp1->v_text[0]; /* Use fast video. */
X cp2 = &vp2->v_text[0];
X putline(row+1, 1, cp1);
X nch = term.t_ncol;
X
X do
X {
X *cp2 = *cp1;
X ++cp2;
X ++cp1;
X }
X while (--nch);
X *flags &= ~VFCHG;
#else
/* UPDATELINE code for all other versions */
X
X register char *cp1;
X register char *cp2;
X register char *cp3;
X register char *cp4;
X register char *cp5;
X register int nbflag; /* non-blanks to the right flag? */
X int rev; /* reverse video flag */
X int req; /* reverse video request flag */
X
X
X /* set up pointers to virtual and physical lines */
X cp1 = &vp1->v_text[0];
X cp2 = &vp2->v_text[0];
X
#if COLOR
X TTforg(vp1->v_rfcolor);
X TTbacg(vp1->v_rbcolor);
#endif
X
#if REVSTA | COLOR
X /* if we need to change the reverse video status of the
X current line, we need to re-write the entire line */
X rev = (vp1->v_flag & VFREV) == VFREV;
X req = (vp1->v_flag & VFREQ) == VFREQ;
X if ((rev != req)
#if COLOR
X || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
#endif
#if HP150
X /* the HP150 has some reverse video problems */
X || req || rev
#endif
X ) {
X movecursor(row, 0); /* Go to start of line. */
X /* set rev video if needed */
X if (rev != req)
X (*term.t_rev)(req);
X
X /* scan through the line and dump it to the screen and
X the virtual screen array */
X cp3 = &vp1->v_text[term.t_ncol];
X while (cp1 < cp3) {
X TTputc(*cp1);
X ++ttcol;
X *cp2++ = *cp1++;
X }
X /* turn rev video off */
X if (rev != req)
X (*term.t_rev)(FALSE);
X
X /* update the needed flags */
X vp1->v_flag &= ~VFCHG;
X if (req)
X vp1->v_flag |= VFREV;
X else
X vp1->v_flag &= ~VFREV;
#if COLOR
X vp1->v_fcolor = vp1->v_rfcolor;
X vp1->v_bcolor = vp1->v_rbcolor;
#endif
X return(TRUE);
X }
#endif
X
X /* advance past any common chars at the left */
X while (cp1 != &vp1->v_text[term.t_ncol] && *cp1 == *cp2) {
X ++cp1;
X ++cp2;
X }
X
/* This can still happen, even though we only call this routine on changed
X * lines. A hard update is always done when a line splits, a massive
X * change is done, or a buffer is displayed twice. This optimizes out most
X * of the excess updating. A lot of computes are used, but these tend to
X * be hard operations that do a lot of update, so I don't really care.
X */
X /* if both lines are the same, no update needs to be done */
X if (cp1 == &vp1->v_text[term.t_ncol]) {
X vp1->v_flag &= ~VFCHG; /* flag this line is changed */
X return(TRUE);
X }
X
X /* find out if there is a match on the right */
X nbflag = FALSE;
X cp3 = &vp1->v_text[term.t_ncol];
X cp4 = &vp2->v_text[term.t_ncol];
X
X while (cp3[-1] == cp4[-1]) {
X --cp3;
X --cp4;
X if (cp3[0] != ' ') /* Note if any nonblank */
X nbflag = TRUE; /* in right match. */
X }
X
X cp5 = cp3;
X
X /* Erase to EOL ? */
X if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
X while (cp5!=cp1 && cp5[-1]==' ')
X --cp5;
X
X if (cp3-cp5 <= 3) /* Use only if erase is */
X cp5 = cp3; /* fewer characters. */
X }
X
X movecursor(row, cp1 - &vp1->v_text[0]); /* Go to start of line. */
#if REVSTA
X TTrev(rev);
#endif
X
X while (cp1 != cp5) { /* Ordinary. */
X TTputc(*cp1);
X ++ttcol;
X *cp2++ = *cp1++;
X }
X
X if (cp5 != cp3) { /* Erase. */
X TTeeol();
X while (cp1 != cp3)
X *cp2++ = *cp1++;
X }
#if REVSTA
X TTrev(FALSE);
#endif
X vp1->v_flag &= ~VFCHG; /* flag this line as updated */
X return(TRUE);
#endif
}
#endif
X
#endif /* NeWS */
X
/*
X * Redisplay the mode line for the window pointed to by the "wp". This is the
X * only routine that has any idea of how the modeline is formatted. You can
X * change the modeline format by hacking at this routine. Called by "update"
X * any time there is a dirty window.
X */
modeline(wp)
WINDOW *wp;
{
X register int n;
X register BUFFER *bp;
X register lchar; /* character to draw line in buffer with */
X
X n = wp->w_toprow+wp->w_ntrows; /* Location. */
X vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
X
#if NeWS
X vscreen[n]->v_rfcolor = 0;
X vscreen[n]->v_rbcolor = 7;
X if (wp == curwp) { /* mark the current buffer */
X lchar = '^' ;
X } else {
X lchar = ' ' ;
X }
X vtmove(n, 0); /* Seek to right line. */
#else
X
#if COLOR
X vscreen[n]->v_rfcolor = 0; /* black on */
X vscreen[n]->v_rbcolor = 7; /* white.....*/
#endif
X vtmove(n, 0); /* Seek to right line. */
X if (wp == curwp) { /* mark the current buffer */
X lchar = '=';
X } else {
#if REVSTA
X if (revexist)
X lchar = ' ';
X else
#endif
X lchar = '-';
#endif
X }
X bp = wp->w_bufp;
X
X vtputc(lchar,FALSE);
X vtputc(' ',FALSE);
X vtputsn(bp->b_bname, NBUFN);
X if (bp->b_mode&MDVIEW)
X vtputsn(" [view only]", 20);
X if (bp->b_mode&MDDOS)
X vtputsn(" [dos-style]", 20);
X if (bp->b_flag&BFCHG)
X vtputsn(" [modified]", 20);
X /* don't print a filename if they're the same,
X or the filename is null */
X if (strcmp(bp->b_fname,bp->b_bname)) {
X if (bp->b_fname[0] != '\0') {
X if (isspace(bp->b_fname[0])) {
X /* some of the internally generated buffers
X put other info. in filename slot */
X vtputsn(bp->b_fname, NFILEN);
X } else {
X if (ispunct(bp->b_fname[0]))
X vtputsn(" is \"", 20);
X else
X vtputsn(" is file \"", 20);
X vtputsn(bp->b_fname, NFILEN);
X vtputsn("\"", 20);
X }
X }
X }
X vtputc(' ',FALSE);
X
X
X /* Pad to full width, then go back and overwrite right-end info */
X n = term.t_ncol;
X while (vtcol < n)
X vtputc(lchar,FALSE);
X
X { /* determine if top line, bottom line, or both are visible */
X LINE *lp = wp->w_linep;
X int rows = wp->w_ntrows;
X char *msg = NULL;
X
X vtcol = n - 7; /* strlen(" top ") plus a couple */
X while (rows--) {
X lp = lforw(lp);
X if (lp == wp->w_bufp->b_linep) {
X msg = " bot ";
X break;
X }
X }
X if (lback(wp->w_linep) == wp->w_bufp->b_linep) {
X if (msg) {
X if (wp->w_linep == wp->w_bufp->b_linep)
X msg = " emp ";
X else
X msg = " all ";
X } else {
X msg = " top ";
X }
X }
X if (!msg)
X msg = " mid ";
X vtputsn(msg,20);
X }
X
X if (vtgetc(80) == lchar) {
X vtcol = 80;
X vtputc('|',FALSE);
X }
}
X
upmode() /* update all the mode lines */
{
X register WINDOW *wp;
X
#if NeWS /* tell workstation the current modes */
X newsreportmodes() ;
#endif
X wp = wheadp;
X while (wp != NULL) {
X wp->w_flag |= WFMODE;
X wp = wp->w_wndp;
X }
}
X
/*
X * Send a command to the terminal to move the hardware cursor to row "row"
X * and column "col". The row and column arguments are origin 0. Optimize out
X * random calls. Update "ttrow" and "ttcol".
X */
movecursor(row, col)
{
#if ! NeWS /* "line buffered" */
X if (row!=ttrow || col!=ttcol)
#endif
X {
X ttrow = row;
X ttcol = col;
X TTmove(row, col);
X }
}
X
X
X
#if NeWS /* buffer the message line stuff, newsputc is slow */
#define NEWSBUFSIZ 256
#undef TTputc
#undef TTflush
#define TTputc(c) bufputc(c)
#define TTflush() bufputc((char)0)
X
bufputc(c)
char c ;
{
X static bufindex = 0 ;
X static char outbuf[NEWSBUFSIZ] ;
X
X if (c == NULL || bufindex >= NEWSBUFSIZ || bufindex >= term.t_ncol) {
X outbuf[bufindex] = NULL ;
X newsputline(term.t_nrow, outbuf, 7, 0) ;
X movecursor(term.t_nrow, strlen(outbuf)) ;
X newsflush() ;
X bufindex = 0 ;
X }
X else outbuf[bufindex++] = c ;
}
#endif
X
X
/*
X * Erase the message line. This is a special routine because the message line
X * is not considered to be part of the virtual screen. It always works
X * immediately; the terminal buffer is flushed via a call to the flusher.
X */
mlerase()
{
X int i;
X
X if (mpresf == FALSE)
X return;
X movecursor(term.t_nrow, 0);
X if (discmd == FALSE)
X return;
X
#if COLOR
X TTforg(7);
X TTbacg(0);
#endif
X if (eolexist == TRUE)
X TTeeol();
X else {
X for (i = 0; i < term.t_ncol - 1; i++)
X TTputc(' ');
X movecursor(term.t_nrow, 1); /* force the move! */
X movecursor(term.t_nrow, 0);
X }
X TTflush();
X mpresf = FALSE;
}
X
X
X
X
#ifndef va_dcl /* then try these out */
X
typedef char *va_list;
#define va_dcl int va_alist;
#define va_start(list) list = (char *) &va_alist
#define va_end(list)
#define va_arg(list, mode) ((mode *)(list += sizeof(mode)))[-1]
X
#endif
X
dbgwrite(s,x,y,z)
{
X mlwrite(s,x,y,z);
X tgetc();
}
X
/*
X * Write a message into the message line. Keep track of the physical cursor
X * position. A small class of printf like format items is handled.
X * Set the "message line" flag TRUE.
X */
X
/* VARARGS */
mlwrite(fmt, va_alist)
char *fmt; /* format string for output */
va_dcl
{
X register int c; /* current char in format string */
X register va_list ap; /* ptr to current data field */
X
X /* if we are not currently echoing on the command line, abort this */
X if (dotcmdmode == PLAY || discmd == FALSE) {
X movecursor(term.t_nrow, 0);
X return;
X }
X
#if COLOR
X /* set up the proper colors for the command line */
X TTforg(7);
X TTbacg(0);
#endif
X
X /* if we can not erase to end-of-line, do it manually */
X if (eolexist == FALSE) {
X mlerase();
X TTflush();
X }
X
X va_start(ap);
X
X movecursor(term.t_nrow, 0);
X while ((c = *fmt) != 0 && ttcol < term.t_ncol-1) {
X if (c != '%') {
X mlputc(c);
X } else {
X c = *++fmt;
X switch (c) {
X case '\0':
X break;
X case 'c':
X mlputc(va_arg(ap,int));
X break;
X
X case 'd':
X mlputi(va_arg(ap,int), 10);
X break;
X
X case 'o':
X mlputi(va_arg(ap,int), 8);
X break;
X
X case 'x':
X mlputi(va_arg(ap,int), 16);
X break;
X
X case 'D':
X mlputli(va_arg(ap,long), 10);
X break;
X
X case 's':
X mlputs(va_arg(ap,char *));
X break;
X
X case 'S': {
X int wid = va_arg(ap,int);
X mlputsn(va_arg(ap,char *),wid);
X break;
X }
X
X case 'f':
X mlputf(va_arg(ap,int));
X break;
X
X default:
X mlputc(c);
X }
X }
X fmt++;
X }
X
X va_end(ap);
X
X /* if we can, erase to the end of screen */
X if (eolexist == TRUE)
X TTeeol();
X TTflush();
X mpresf = TRUE;
}
X
/* Force a string out to the message line regardless of the
X current $discmd setting. This is needed when $debug is TRUE
X and for the write-message and clear-message-line commands
*/
X
mlforce(s)
char *s; /* string to force out */
{
X register oldcmd; /* original command display flag */
X
X oldcmd = discmd; /* save the discmd value */
X discmd = TRUE; /* and turn display on */
X mlwrite(s); /* write the string out */
X discmd = oldcmd; /* and restore the original setting */
}
X
/*
X * Write out a character. Update the physical cursor position. This assumes that
X * the character has width "1"; if this is not the case
X * things will get screwed up a little.
X */
mlputc(c)
char c;
{
X if (c == '\r') ttcol = 0;
X if (ttcol < term.t_ncol-1) {
X TTputc(c);
X ++ttcol;
X }
}
X
/*
X * Write out a string. Update the physical cursor position. This assumes that
X * the characters in the string all have width "1"; if this is not the case
X * things will get screwed up a little.
X */
mlputs(s)
char *s;
{
X register int c;
X
X while ((c = *s++) != 0) {
X mlputc(c);
X }
}
X
/* as above, but takes a count for s's length */
mlputsn(s,n)
char *s;
{
X register int c;
X while ((c = *s++) != 0 && n-- != 0) {
X mlputc(c);
X }
}
X
/*
X * Write out an integer, in the specified radix. Update the physical cursor
X * position.
X */
mlputi(i, r)
{
X register int q;
X static char hexdigits[] = "0123456789ABCDEF";
X
X if (i < 0) {
X i = -i;
X mlputc('-');
X }
X
X q = i/r;
X
X if (q != 0)
X mlputi(q, r);
X
X mlputc(hexdigits[i%r]);
}
X
/*
X * do the same except as a long integer.
X */
mlputli(l, r)
long l;
{
X register long q;
X
X if (l < 0) {
X l = -l;
X mlputc('-');
X }
X
X q = l/r;
X
X if (q != 0)
X mlputli(q, r);
X
X mlputc((int)(l%r)+'0');
}
X
/*
X * write out a scaled integer with two decimal places
X */
X
mlputf(s)
int s; /* scaled integer to output */
{
X register int i; /* integer portion of number */
X register int f; /* fractional portion of number */
X
X /* break it up */
X i = s / 100;
X f = s % 100;
X
X /* send out the integer portion */
X mlputi(i, 10);
X mlputc('.');
X mlputc((f / 10) + '0');
X mlputc((f % 10) + '0');
}
X
#if RAINBOW
X
putline(row, col, buf)
int row, col;
char buf[];
{
X int n;
X
X n = strlen(buf);
X if (col + n - 1 > term.t_ncol)
X n = term.t_ncol - col + 1;
X Put_Data(row, col, n, buf);
}
#endif
X
/* Get terminal size from system.
X Store number of lines into *heightp and width into *widthp.
X If zero or a negative number is stored, the value is not valid. */
X
getscreensize (widthp, heightp)
int *widthp, *heightp;
{
#ifdef TIOCGWINSZ
X struct winsize size;
X *widthp = 0;
X *heightp = 0;
X if (ioctl (0, TIOCGWINSZ, &size) < 0)
X return;
X *widthp = size.ws_col;
X *heightp = size.ws_row;
#else
X *widthp = 0;
X *heightp = 0;
#endif
}
X
#ifdef SIGWINCH
sizesignal ()
{
X int w, h;
X extern int errno;
X int old_errno = errno;
X
X getscreensize (&w, &h);
X
X if ((h && h-1 != term.t_nrow) || (w && w != term.t_ncol))
X newscreensize(h, w);
X
X signal (SIGWINCH, sizesignal);
X errno = old_errno;
}
X
newscreensize (h, w)
int h, w;
{
X /* do the change later */
X if (displaying) {
X chg_width = w;
X chg_height = h;
X return;
X }
X chg_width = chg_height = 0;
X if (h - 1 < term.t_mrow)
X newlength(TRUE,h);
X if (w < term.t_mcol)
X newwidth(TRUE,w);
X
X update(TRUE);
X return TRUE;
}
X
#endif
SHAR_EOF
chmod 0444 display.c ||
echo 'restore of display.c failed'
Wc_c="`wc -c < 'display.c'`"
test 40087 -eq "$Wc_c" ||
echo 'display.c: original size 40087, current size' "$Wc_c"
# ============= dolock.c ==============
echo 'x - extracting dolock.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dolock.c' &&
#if 0
/* dolock: MDBS specific Unix 4.2BSD file locking mechinism
X this is not to be distributed generally */
X
#include <mdbs.h>
#include <mdbsio.h>
#include <sys/types.h>
#include <sys/stat.h>
X
/* included by port.h: mdbs.h, mdbsio.h, sys/types.h, sys/stat.h */
X
X
#ifndef bsdunix
char *dolock(){return(NULL);}
char *undolock(){return(NULL);}
#else
X
#include <pwd.h>
#include <errno.h>
X
extern int errno;
X
#define LOCKDIR ".xlk"
X
#define LOCKMSG "LOCK ERROR -- "
#define LOCKMSZ sizeof(LOCKMSG)
#define LOCKERR(s) { strcat(lmsg,s); oldumask = umask(oldumask); return(lmsg); }
X
/**********************
X *
X * dolock -- lock the file fname
X *
X * if successful, returns NULL
X * if file locked, returns username of person locking the file
X * if other error, returns "LOCK ERROR: explanation"
X *
X * Jon Reid, 2/19/86
X *
X *********************/
X
BOOL parent = FALSE;
BOOL tellall = FALSE;
X
char *gtname(filespec) /* get name component of unix-style filespec */
char *filespec;
{
X char *rname, *rindex();
X
X rname = rindex(filespec,'/');
SHAR_EOF
true || echo 'restore of dolock.c failed'
echo 'End of Vile part 3'
echo 'File dolock.c is continued in part 4'
echo 4 > _shar_seq_.tmp
exit 0
--
paul fox, pgf at cayman.com, (617)494-1999
Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
More information about the Alt.sources
mailing list