Path: utzoo!utgpu!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!think.com!cayman!pgf From: pgf@cayman.COM (Paul Fox) Newsgroups: alt.sources Subject: Vile 03/17 - vi feel-alike (multi-window) Message-ID: <4522@cayman.COM> Date: 7 Jun 91 22:09:16 GMT Organization: Cayman Systems Inc., Cambridge Ma Lines: 2455 Submitted-by: pgf@cayman.com Archive-name: Vile/part03 #!/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 #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 #include #include "estruct.h" #include "edef.h" #if UNIX #include #include #if ODT #include #include #include #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 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; j0 && 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; j0 && 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; rowv_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; rowv_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; rowv_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; rowv_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 #include #include #include 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 #include 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@cayman.com, (617)494-1999 Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139