xref: /freebsd/contrib/tcsh/ed.refresh.c (revision 45e5710bbb3676c9d945e9df78019b2c58930a59)
145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/ed.refresh.c,v 3.46 2006/08/23 15:03:14 christos Exp $ */
2c80476e4SDavid E. O'Brien /*
3c80476e4SDavid E. O'Brien  * ed.refresh.c: Lower level screen refreshing functions
4c80476e4SDavid E. O'Brien  */
5c80476e4SDavid E. O'Brien /*-
6c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
7c80476e4SDavid E. O'Brien  * All rights reserved.
8c80476e4SDavid E. O'Brien  *
9c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
10c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
11c80476e4SDavid E. O'Brien  * are met:
12c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
13c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
14c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
15c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
16c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1729301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
18c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
19c80476e4SDavid E. O'Brien  *    without specific prior written permission.
20c80476e4SDavid E. O'Brien  *
21c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
32c80476e4SDavid E. O'Brien  */
33c80476e4SDavid E. O'Brien #include "sh.h"
34c80476e4SDavid E. O'Brien 
3545e5710bSMark Peek RCSID("$tcsh: ed.refresh.c,v 3.46 2006/08/23 15:03:14 christos Exp $")
36c80476e4SDavid E. O'Brien 
37c80476e4SDavid E. O'Brien #include "ed.h"
38c80476e4SDavid E. O'Brien /* #define DEBUG_UPDATE */
39c80476e4SDavid E. O'Brien /* #define DEBUG_REFRESH */
40c80476e4SDavid E. O'Brien /* #define DEBUG_LITERAL */
41c80476e4SDavid E. O'Brien 
42c80476e4SDavid E. O'Brien /* refresh.c -- refresh the current set of lines on the screen */
43c80476e4SDavid E. O'Brien 
4423338178SMark Peek Char   *litptr;
45c80476e4SDavid E. O'Brien static int vcursor_h, vcursor_v;
46c80476e4SDavid E. O'Brien static int rprompt_h, rprompt_v;
47c80476e4SDavid E. O'Brien 
4845e5710bSMark Peek static	int	MakeLiteral		(Char *, int, Char);
4945e5710bSMark Peek static	int	Draw 			(Char *, int);
5045e5710bSMark Peek static	void	Vdraw 			(Char, int);
5145e5710bSMark Peek static	void	RefreshPromptpart	(Char *);
5245e5710bSMark Peek static	void	update_line 		(Char *, Char *, int);
5345e5710bSMark Peek static	void	str_insert		(Char *, int, int, Char *, int);
5445e5710bSMark Peek static	void	str_delete		(Char *, int, int, int);
5545e5710bSMark Peek static	void	str_cp			(Char *, Char *, int);
56b2d5d167SMark Peek #ifndef WINNT_NATIVE
57b2d5d167SMark Peek static
58b2d5d167SMark Peek #else
59b2d5d167SMark Peek extern
60b2d5d167SMark Peek #endif
6145e5710bSMark Peek 	void    PutPlusOne      (Char, int);
6245e5710bSMark Peek static	void	cpy_pad_spaces		(Char *, Char *, int);
63c80476e4SDavid E. O'Brien #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
6445e5710bSMark Peek static	void	dprintf			(char *, ...);
65c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
6645e5710bSMark Peek static	void	dprintstr		(char *, const Char *, const Char *);
67c80476e4SDavid E. O'Brien 
68c80476e4SDavid E. O'Brien static void
6945e5710bSMark Peek dprintstr(char *str, const Char *f, const Char *t)
70c80476e4SDavid E. O'Brien {
71c80476e4SDavid E. O'Brien     dprintf("%s:\"", str);
7223338178SMark Peek     while (f < t) {
7345e5710bSMark Peek 	if (ASC(*f) & ~ASCII)
7423338178SMark Peek 	  dprintf("[%x]", *f++);
7523338178SMark Peek 	else
7645e5710bSMark Peek 	  dprintf("%c", CTL_ESC(ASCII & ASC(*f++)));
7723338178SMark Peek     }
78c80476e4SDavid E. O'Brien     dprintf("\"\r\n");
79c80476e4SDavid E. O'Brien }
80c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
81c80476e4SDavid E. O'Brien 
82c80476e4SDavid E. O'Brien /* dprintf():
83c80476e4SDavid E. O'Brien  *	Print to $DEBUGTTY, so that we can test editing on one pty, and
84c80476e4SDavid E. O'Brien  *      print debugging stuff on another. Don't interrupt the shell while
85c80476e4SDavid E. O'Brien  *	debugging cause you'll mangle up the file descriptors!
86c80476e4SDavid E. O'Brien  */
87c80476e4SDavid E. O'Brien static void
88c80476e4SDavid E. O'Brien dprintf(char *fmt, ...)
89c80476e4SDavid E. O'Brien {
90c80476e4SDavid E. O'Brien     static int fd = -1;
91c80476e4SDavid E. O'Brien     char *dtty;
92c80476e4SDavid E. O'Brien 
93c80476e4SDavid E. O'Brien     if ((dtty = getenv("DEBUGTTY"))) {
94c80476e4SDavid E. O'Brien 	int o;
95c80476e4SDavid E. O'Brien 	va_list va;
96c80476e4SDavid E. O'Brien 	va_start(va, fmt);
97c80476e4SDavid E. O'Brien 
98c80476e4SDavid E. O'Brien 	if (fd == -1)
9945e5710bSMark Peek 	    fd = xopen(dtty, O_RDWR);
100c80476e4SDavid E. O'Brien 	o = SHOUT;
101c80476e4SDavid E. O'Brien 	flush();
102c80476e4SDavid E. O'Brien 	SHOUT = fd;
103c80476e4SDavid E. O'Brien 	xvprintf(fmt, va);
104c80476e4SDavid E. O'Brien 	va_end(va);
105c80476e4SDavid E. O'Brien 	flush();
106c80476e4SDavid E. O'Brien 	SHOUT = o;
107c80476e4SDavid E. O'Brien     }
108c80476e4SDavid E. O'Brien }
109c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
110c80476e4SDavid E. O'Brien 
11123338178SMark Peek static int litlen = 0, litalloc = 0;
11223338178SMark Peek 
11345e5710bSMark Peek static int MakeLiteral(Char *str, int len, Char addlit)
114c80476e4SDavid E. O'Brien {
11523338178SMark Peek     int i, addlitlen = 0;
11623338178SMark Peek     Char *addlitptr = 0;
11723338178SMark Peek     if (addlit) {
11823338178SMark Peek 	if ((addlit & LITERAL) != 0) {
11923338178SMark Peek 	    addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
12023338178SMark Peek 	    addlitlen = Strlen(addlitptr);
12123338178SMark Peek 	} else {
12223338178SMark Peek 	    addlitptr = &addlit;
12323338178SMark Peek 	    addlitlen = 1;
124c80476e4SDavid E. O'Brien 	}
12523338178SMark Peek 	for (i = 0; i < litlen; i += LIT_FACTOR)
12623338178SMark Peek 	    if (!Strncmp(addlitptr, litptr + i, addlitlen) && !Strncmp(str, litptr + i + addlitlen, len) && litptr[i + addlitlen + len] == 0)
12723338178SMark Peek 		return (i / LIT_FACTOR) | LITERAL;
12823338178SMark Peek     } else {
12923338178SMark Peek 	addlitlen = 0;
13023338178SMark Peek 	for (i = 0; i < litlen; i += LIT_FACTOR)
13123338178SMark Peek 	    if (!Strncmp(str, litptr + i, len) && litptr[i + len] == 0)
13223338178SMark Peek 		return (i / LIT_FACTOR) | LITERAL;
13323338178SMark Peek     }
13423338178SMark Peek     if (litlen + addlitlen + len + 1 + (LIT_FACTOR - 1) > litalloc) {
13523338178SMark Peek 	Char *newlitptr;
13623338178SMark Peek 	int add = 256;
13723338178SMark Peek 	while (len + addlitlen + 1 + (LIT_FACTOR - 1) > add)
13823338178SMark Peek 	    add *= 2;
13945e5710bSMark Peek 	newlitptr = xrealloc(litptr, (litalloc + add) * sizeof(Char));
14023338178SMark Peek 	if (!newlitptr)
14123338178SMark Peek 	    return '?';
14223338178SMark Peek 	litptr = newlitptr;
14323338178SMark Peek 	litalloc += add;
14423338178SMark Peek 	if (addlitptr && addlitptr != &addlit)
14523338178SMark Peek 	    addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
14623338178SMark Peek     }
14723338178SMark Peek     i = litlen / LIT_FACTOR;
14823338178SMark Peek     if (i >= LITERAL || i == CHAR_DBWIDTH)
14923338178SMark Peek 	return '?';
15023338178SMark Peek     if (addlitptr) {
15123338178SMark Peek 	Strncpy(litptr + litlen, addlitptr, addlitlen);
15223338178SMark Peek 	litlen += addlitlen;
15323338178SMark Peek     }
15423338178SMark Peek     Strncpy(litptr + litlen, str, len);
15523338178SMark Peek     litlen += len;
15623338178SMark Peek     do
15723338178SMark Peek 	litptr[litlen++] = 0;
15823338178SMark Peek     while (litlen % LIT_FACTOR);
15923338178SMark Peek     return i | LITERAL;
16023338178SMark Peek }
161c80476e4SDavid E. O'Brien 
16223338178SMark Peek static int
16345e5710bSMark Peek Draw(Char *cp, int nocomb)	/* draw char at cp, expand tabs, ctl chars */
16423338178SMark Peek {
16545e5710bSMark Peek     int w, i, lv, lh;
16645e5710bSMark Peek     Char c, attr;
16723338178SMark Peek 
16823338178SMark Peek     attr = *cp & ~CHAR;
16945e5710bSMark Peek     c = *cp & CHAR;
17023338178SMark Peek     w = NLSClassify(c, nocomb);
17123338178SMark Peek     switch (w) {
17223338178SMark Peek 	case NLSCLASS_NL:
17323338178SMark Peek 	    Vdraw('\0', 0);		/* assure end of line	 */
174c80476e4SDavid E. O'Brien 	    vcursor_h = 0;		/* reset cursor pos	 */
175c80476e4SDavid E. O'Brien 	    vcursor_v++;
17623338178SMark Peek 	    break;
17723338178SMark Peek 	case NLSCLASS_TAB:
17823338178SMark Peek 	    do {
17923338178SMark Peek 		Vdraw(' ', 1);
18023338178SMark Peek 	    } while ((vcursor_h & 07) != 0);
18123338178SMark Peek 	    break;
18223338178SMark Peek 	case NLSCLASS_CTRL:
18323338178SMark Peek 	    Vdraw('^' | attr, 1);
18423338178SMark Peek 	    if (c == CTL_ESC('\177')) {
18523338178SMark Peek 		Vdraw('?' | attr, 1);
18623338178SMark Peek 	    } else {
1873b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
188c80476e4SDavid E. O'Brien 		/* uncontrolify it; works only for iso8859-1 like sets */
18923338178SMark Peek 		Vdraw(c | 0100 | attr, 1);
1903b6eaa7bSAndrey A. Chernov #else
19123338178SMark Peek 		Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1);
19223338178SMark Peek #endif
193c80476e4SDavid E. O'Brien 	    }
19423338178SMark Peek 	    break;
19523338178SMark Peek 	case NLSCLASS_ILLEGAL:
19623338178SMark Peek 	    Vdraw('\\' | attr, 1);
19745e5710bSMark Peek 	    Vdraw((((c >> 6) & 7) + '0') | attr, 1);
19845e5710bSMark Peek 	    Vdraw((((c >> 3) & 7) + '0') | attr, 1);
19945e5710bSMark Peek 	    Vdraw(((c & 7) + '0') | attr, 1);
20023338178SMark Peek 	    break;
20123338178SMark Peek 	case NLSCLASS_ILLEGAL2:
20223338178SMark Peek 	case NLSCLASS_ILLEGAL3:
20323338178SMark Peek 	case NLSCLASS_ILLEGAL4:
20423338178SMark Peek 	    Vdraw('\\' | attr, 1);
20523338178SMark Peek 	    Vdraw('U' | attr, 1);
20623338178SMark Peek 	    Vdraw('+' | attr, 1);
20723338178SMark Peek 	    for (i = 8 * NLSCLASS_ILLEGAL_SIZE(w) - 4; i >= 0; i -= 4)
20823338178SMark Peek 		Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1);
20923338178SMark Peek 	    break;
21023338178SMark Peek 	case 0:
21123338178SMark Peek 	    lv = vcursor_v;
21223338178SMark Peek 	    lh = vcursor_h;
21323338178SMark Peek 	    for (;;) {
21423338178SMark Peek 		lh--;
21523338178SMark Peek 		if (lh < 0) {
21623338178SMark Peek 		    lv--;
21723338178SMark Peek 		    if (lv < 0)
21823338178SMark Peek 			break;
21923338178SMark Peek 		    lh = Strlen(Vdisplay[lv]) - 1;
220c80476e4SDavid E. O'Brien 		}
22123338178SMark Peek 		if (Vdisplay[lv][lh] != CHAR_DBWIDTH)
22223338178SMark Peek 		    break;
22323338178SMark Peek 	    }
22423338178SMark Peek 	    if (lv < 0) {
22523338178SMark Peek 		Vdraw('\\' | attr, 1);
22645e5710bSMark Peek 		Vdraw((((c >> 6) & 7) + '0') | attr, 1);
22745e5710bSMark Peek 		Vdraw((((c >> 3) & 7) + '0') | attr, 1);
22845e5710bSMark Peek 		Vdraw(((c & 7) + '0') | attr, 1);
22945e5710bSMark Peek 		break;
23023338178SMark Peek 	    }
23145e5710bSMark Peek 	    Vdisplay[lv][lh] = MakeLiteral(cp, 1, Vdisplay[lv][lh]);
23223338178SMark Peek 	    break;
23323338178SMark Peek 	default:
23423338178SMark Peek 	    Vdraw(*cp, w);
23523338178SMark Peek 	    break;
236c80476e4SDavid E. O'Brien     }
23745e5710bSMark Peek     return 1;
238c80476e4SDavid E. O'Brien }
239c80476e4SDavid E. O'Brien 
240c80476e4SDavid E. O'Brien static void
24145e5710bSMark Peek Vdraw(Char c, int width)	/* draw char c onto V lines */
242c80476e4SDavid E. O'Brien {
243c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
244c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS
24523338178SMark Peek     dprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width);
246c80476e4SDavid E. O'Brien # else
24723338178SMark Peek     dprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width);
248c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */
249c80476e4SDavid E. O'Brien #endif  /* DEBUG_REFRESH */
250c80476e4SDavid E. O'Brien 
25123338178SMark Peek     /* Hopefully this is what all the terminals do with multi-column characters
25223338178SMark Peek        that "span line breaks". */
25323338178SMark Peek     while (vcursor_h + width > TermH)
25423338178SMark Peek 	Vdraw(' ', 1);
25545e5710bSMark Peek     Vdisplay[vcursor_v][vcursor_h] = c;
25623338178SMark Peek     if (width)
257c80476e4SDavid E. O'Brien 	vcursor_h++;		/* advance to next place */
25823338178SMark Peek     while (--width > 0)
25923338178SMark Peek 	Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH;
260c80476e4SDavid E. O'Brien     if (vcursor_h >= TermH) {
261c80476e4SDavid E. O'Brien 	Vdisplay[vcursor_v][TermH] = '\0';	/* assure end of line */
262c80476e4SDavid E. O'Brien 	vcursor_h = 0;		/* reset it. */
263c80476e4SDavid E. O'Brien 	vcursor_v++;
264c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
265c80476e4SDavid E. O'Brien 	if (vcursor_v >= TermV) {	/* should NEVER happen. */
266c80476e4SDavid E. O'Brien 	    dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
267c80476e4SDavid E. O'Brien 		    vcursor_v, TermV);
268c80476e4SDavid E. O'Brien 	    abort();
269c80476e4SDavid E. O'Brien 	}
270c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
271c80476e4SDavid E. O'Brien     }
272c80476e4SDavid E. O'Brien }
273c80476e4SDavid E. O'Brien 
274c80476e4SDavid E. O'Brien /*
275c80476e4SDavid E. O'Brien  *  RefreshPromptpart()
276c80476e4SDavid E. O'Brien  *	draws a prompt element, expanding literals (we know it's ASCIZ)
277c80476e4SDavid E. O'Brien  */
278c80476e4SDavid E. O'Brien static void
27945e5710bSMark Peek RefreshPromptpart(Char *buf)
280c80476e4SDavid E. O'Brien {
28123338178SMark Peek     Char *cp;
28245e5710bSMark Peek     int w;
283c80476e4SDavid E. O'Brien 
28445e5710bSMark Peek     if (buf == NULL)
28545e5710bSMark Peek 	return;
28623338178SMark Peek     for (cp = buf; *cp; ) {
287c80476e4SDavid E. O'Brien 	if (*cp & LITERAL) {
28823338178SMark Peek 	    Char *litstart = cp;
289c80476e4SDavid E. O'Brien 	    while (*cp & LITERAL)
290c80476e4SDavid E. O'Brien 		cp++;
29123338178SMark Peek 	    if (*cp) {
29245e5710bSMark Peek 		w = NLSWidth(*cp & CHAR);
29345e5710bSMark Peek 		Vdraw(MakeLiteral(litstart, cp + 1 - litstart, 0), w);
29445e5710bSMark Peek 		cp++;
29523338178SMark Peek 	    }
296c80476e4SDavid E. O'Brien 	    else {
297c80476e4SDavid E. O'Brien 		/*
298c80476e4SDavid E. O'Brien 		 * XXX: This is a bug, we lose the last literal, if it is not
299c80476e4SDavid E. O'Brien 		 * followed by a normal character, but it is too hard to fix
300c80476e4SDavid E. O'Brien 		 */
301c80476e4SDavid E. O'Brien 		break;
302c80476e4SDavid E. O'Brien 	    }
303c80476e4SDavid E. O'Brien 	}
304c80476e4SDavid E. O'Brien 	else
30523338178SMark Peek 	    cp += Draw(cp, cp == buf);
306c80476e4SDavid E. O'Brien     }
307c80476e4SDavid E. O'Brien }
308c80476e4SDavid E. O'Brien 
309c80476e4SDavid E. O'Brien /*
310c80476e4SDavid E. O'Brien  *  Refresh()
311c80476e4SDavid E. O'Brien  *	draws the new virtual screen image from the current input
312c80476e4SDavid E. O'Brien  *  	line, then goes line-by-line changing the real image to the new
313c80476e4SDavid E. O'Brien  *	virtual image. The routine to re-draw a line can be replaced
314c80476e4SDavid E. O'Brien  *	easily in hopes of a smarter one being placed there.
315c80476e4SDavid E. O'Brien  */
316b2d5d167SMark Peek #ifndef WINNT_NATIVE
317b2d5d167SMark Peek static
318b2d5d167SMark Peek #endif
319b2d5d167SMark Peek int OldvcV = 0;
320b2d5d167SMark Peek 
321c80476e4SDavid E. O'Brien void
32245e5710bSMark Peek Refresh(void)
323c80476e4SDavid E. O'Brien {
32423338178SMark Peek     int cur_line;
32523338178SMark Peek     Char *cp;
326c80476e4SDavid E. O'Brien     int     cur_h, cur_v = 0, new_vcv;
327c80476e4SDavid E. O'Brien     int     rhdiff;
328c80476e4SDavid E. O'Brien     Char    oldgetting;
329c80476e4SDavid E. O'Brien 
330c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
33145e5710bSMark Peek     dprintf("Prompt = :%s:\r\n", short2str(Prompt));
332c80476e4SDavid E. O'Brien     dprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
333c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
334c80476e4SDavid E. O'Brien     oldgetting = GettingInput;
335c80476e4SDavid E. O'Brien     GettingInput = 0;		/* avoid re-entrance via SIGWINCH */
336c80476e4SDavid E. O'Brien 
337c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
338c80476e4SDavid E. O'Brien     vcursor_h = 0;
339c80476e4SDavid E. O'Brien     vcursor_v = 0;
34045e5710bSMark Peek     RefreshPromptpart(RPrompt);
341c80476e4SDavid E. O'Brien     rprompt_h = vcursor_h;
342c80476e4SDavid E. O'Brien     rprompt_v = vcursor_v;
343c80476e4SDavid E. O'Brien 
344c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, draw prompt */
345c80476e4SDavid E. O'Brien     vcursor_h = 0;
346c80476e4SDavid E. O'Brien     vcursor_v = 0;
34745e5710bSMark Peek     RefreshPromptpart(Prompt);
348c80476e4SDavid E. O'Brien     cur_h = -1;			/* set flag in case I'm not set */
349c80476e4SDavid E. O'Brien 
350c80476e4SDavid E. O'Brien     /* draw the current input buffer */
35123338178SMark Peek     for (cp = InputBuf; (cp < LastChar); ) {
35223338178SMark Peek 	if (cp >= Cursor && cur_h == -1) {
353c80476e4SDavid E. O'Brien 	    cur_h = vcursor_h;	/* save for later */
354c80476e4SDavid E. O'Brien 	    cur_v = vcursor_v;
35523338178SMark Peek 	    Cursor = cp;
356c80476e4SDavid E. O'Brien 	}
35723338178SMark Peek 	cp += Draw(cp, cp == InputBuf);
358c80476e4SDavid E. O'Brien     }
359c80476e4SDavid E. O'Brien 
360c80476e4SDavid E. O'Brien     if (cur_h == -1) {		/* if I haven't been set yet, I'm at the end */
361c80476e4SDavid E. O'Brien 	cur_h = vcursor_h;
362c80476e4SDavid E. O'Brien 	cur_v = vcursor_v;
363c80476e4SDavid E. O'Brien     }
364c80476e4SDavid E. O'Brien 
365c80476e4SDavid E. O'Brien     rhdiff = TermH - vcursor_h - rprompt_h;
366c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
367c80476e4SDavid E. O'Brien 			/*
368c80476e4SDavid E. O'Brien 			 * have a right-hand side prompt that will fit on
369c80476e4SDavid E. O'Brien 			 * the end of the first line with at least one
370c80476e4SDavid E. O'Brien 			 * character gap to the input buffer.
371c80476e4SDavid E. O'Brien 			 */
372c80476e4SDavid E. O'Brien 	while (--rhdiff > 0)		/* pad out with spaces */
37323338178SMark Peek 	    Vdraw(' ', 1);
37445e5710bSMark Peek 	RefreshPromptpart(RPrompt);
375c80476e4SDavid E. O'Brien     }
376c80476e4SDavid E. O'Brien     else {
377c80476e4SDavid E. O'Brien 	rprompt_h = 0;			/* flag "not using rprompt" */
378c80476e4SDavid E. O'Brien 	rprompt_v = 0;
379c80476e4SDavid E. O'Brien     }
380c80476e4SDavid E. O'Brien 
381c80476e4SDavid E. O'Brien     new_vcv = vcursor_v;	/* must be done BEFORE the NUL is written */
38223338178SMark Peek     Vdraw('\0', 1);		/* put NUL on end */
383c80476e4SDavid E. O'Brien 
38423338178SMark Peek #if defined (DEBUG_REFRESH)
385c80476e4SDavid E. O'Brien     dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
386c80476e4SDavid E. O'Brien 	    TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
387c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
388c80476e4SDavid E. O'Brien 
389c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
390c80476e4SDavid E. O'Brien     dprintf("updating %d lines.\r\n", new_vcv);
391c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
392c80476e4SDavid E. O'Brien     for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
393c80476e4SDavid E. O'Brien 	/* NOTE THAT update_line MAY CHANGE Display[cur_line] */
394c80476e4SDavid E. O'Brien 	update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
3953b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
396c80476e4SDavid E. O'Brien 	flush();
3973b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
398c80476e4SDavid E. O'Brien 
399c80476e4SDavid E. O'Brien 	/*
400c80476e4SDavid E. O'Brien 	 * Copy the new line to be the current one, and pad out with spaces
401c80476e4SDavid E. O'Brien 	 * to the full width of the terminal so that if we try moving the
402c80476e4SDavid E. O'Brien 	 * cursor by writing the character that is at the end of the
403c80476e4SDavid E. O'Brien 	 * screen line, it won't be a NUL or some old leftover stuff.
404c80476e4SDavid E. O'Brien 	 */
405c80476e4SDavid E. O'Brien 	cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
406c80476e4SDavid E. O'Brien     }
407c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
408c80476e4SDavid E. O'Brien     dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
409c80476e4SDavid E. O'Brien 	    vcursor_v, OldvcV, cur_line);
410c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
411c80476e4SDavid E. O'Brien     if (OldvcV > new_vcv) {
412c80476e4SDavid E. O'Brien 	for (; cur_line <= OldvcV; cur_line++) {
413c80476e4SDavid E. O'Brien 	    update_line(Display[cur_line], STRNULL, cur_line);
414c80476e4SDavid E. O'Brien 	    *Display[cur_line] = '\0';
415c80476e4SDavid E. O'Brien 	}
416c80476e4SDavid E. O'Brien     }
417c80476e4SDavid E. O'Brien     OldvcV = new_vcv;		/* set for next time */
418c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
419c80476e4SDavid E. O'Brien     dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
420c80476e4SDavid E. O'Brien 	    CursorH, CursorV, cur_h, cur_v);
421c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
4223b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
423c80476e4SDavid E. O'Brien     flush();
4243b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
425c80476e4SDavid E. O'Brien     MoveToLine(cur_v);		/* go to where the cursor is */
426c80476e4SDavid E. O'Brien     MoveToChar(cur_h);
427c80476e4SDavid E. O'Brien     SetAttributes(0);		/* Clear all attributes */
428c80476e4SDavid E. O'Brien     flush();			/* send the output... */
429c80476e4SDavid E. O'Brien     GettingInput = oldgetting;	/* reset to old value */
430c80476e4SDavid E. O'Brien }
431c80476e4SDavid E. O'Brien 
432c80476e4SDavid E. O'Brien #ifdef notdef
43345e5710bSMark Peek GotoBottom(void)
434c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
435c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
436c80476e4SDavid E. O'Brien }
437c80476e4SDavid E. O'Brien 
438c80476e4SDavid E. O'Brien #endif
439c80476e4SDavid E. O'Brien 
440c80476e4SDavid E. O'Brien void
44145e5710bSMark Peek PastBottom(void)
442c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
443c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
444c80476e4SDavid E. O'Brien     (void) putraw('\r');
445c80476e4SDavid E. O'Brien     (void) putraw('\n');
446c80476e4SDavid E. O'Brien     ClearDisp();
447c80476e4SDavid E. O'Brien     flush();
448c80476e4SDavid E. O'Brien }
449c80476e4SDavid E. O'Brien 
450c80476e4SDavid E. O'Brien 
451c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat,
452c80476e4SDavid E. O'Brien    maximum length of d is dlen */
453c80476e4SDavid E. O'Brien static void
45445e5710bSMark Peek str_insert(Char *d, int dat, int dlen, Char *s, int num)
455c80476e4SDavid E. O'Brien {
45623338178SMark Peek     Char *a, *b;
457c80476e4SDavid E. O'Brien 
458c80476e4SDavid E. O'Brien     if (num <= 0)
459c80476e4SDavid E. O'Brien 	return;
460c80476e4SDavid E. O'Brien     if (num > dlen - dat)
461c80476e4SDavid E. O'Brien 	num = dlen - dat;
462c80476e4SDavid E. O'Brien 
463c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
464c80476e4SDavid E. O'Brien     dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
465c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
466c80476e4SDavid E. O'Brien     dprintf("s == \"%s\"n", short2str(s));
467c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
468c80476e4SDavid E. O'Brien 
469c80476e4SDavid E. O'Brien     /* open up the space for num chars */
470c80476e4SDavid E. O'Brien     if (num > 0) {
471c80476e4SDavid E. O'Brien 	b = d + dlen - 1;
472c80476e4SDavid E. O'Brien 	a = b - num;
473c80476e4SDavid E. O'Brien 	while (a >= &d[dat])
474c80476e4SDavid E. O'Brien 	    *b-- = *a--;
475c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
476c80476e4SDavid E. O'Brien     }
477c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
478c80476e4SDavid E. O'Brien     dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
479c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
480c80476e4SDavid E. O'Brien     dprintf("s == \"%s\"n", short2str(s));
481c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
482c80476e4SDavid E. O'Brien 
483c80476e4SDavid E. O'Brien     /* copy the characters */
484c80476e4SDavid E. O'Brien     for (a = d + dat; (a < d + dlen) && (num > 0); num--)
485c80476e4SDavid E. O'Brien 	*a++ = *s++;
486c80476e4SDavid E. O'Brien 
487c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
488c80476e4SDavid E. O'Brien     dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
489c80476e4SDavid E. O'Brien 	    num, dat, dlen, d, short2str(s));
490c80476e4SDavid E. O'Brien     dprintf("s == \"%s\"n", short2str(s));
491c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
492c80476e4SDavid E. O'Brien }
493c80476e4SDavid E. O'Brien 
494c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */
495c80476e4SDavid E. O'Brien static void
49645e5710bSMark Peek str_delete(Char *d, int dat, int dlen, int num)
497c80476e4SDavid E. O'Brien {
49823338178SMark Peek     Char *a, *b;
499c80476e4SDavid E. O'Brien 
500c80476e4SDavid E. O'Brien     if (num <= 0)
501c80476e4SDavid E. O'Brien 	return;
502c80476e4SDavid E. O'Brien     if (dat + num >= dlen) {
503c80476e4SDavid E. O'Brien 	d[dat] = '\0';
504c80476e4SDavid E. O'Brien 	return;
505c80476e4SDavid E. O'Brien     }
506c80476e4SDavid E. O'Brien 
507c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
508c80476e4SDavid E. O'Brien     dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
509c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
510c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
511c80476e4SDavid E. O'Brien 
512c80476e4SDavid E. O'Brien     /* open up the space for num chars */
513c80476e4SDavid E. O'Brien     if (num > 0) {
514c80476e4SDavid E. O'Brien 	b = d + dat;
515c80476e4SDavid E. O'Brien 	a = b + num;
516c80476e4SDavid E. O'Brien 	while (a < &d[dlen])
517c80476e4SDavid E. O'Brien 	    *b++ = *a++;
518c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
519c80476e4SDavid E. O'Brien     }
520c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
521c80476e4SDavid E. O'Brien     dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
522c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
523c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
524c80476e4SDavid E. O'Brien }
525c80476e4SDavid E. O'Brien 
526c80476e4SDavid E. O'Brien static void
52745e5710bSMark Peek str_cp(Char *a, Char *b, int n)
528c80476e4SDavid E. O'Brien {
529c80476e4SDavid E. O'Brien     while (n-- && *b)
530c80476e4SDavid E. O'Brien 	*a++ = *b++;
531c80476e4SDavid E. O'Brien }
532c80476e4SDavid E. O'Brien 
533c80476e4SDavid E. O'Brien 
534c80476e4SDavid E. O'Brien /* ****************************************************************
535c80476e4SDavid E. O'Brien     update_line() is based on finding the middle difference of each line
536c80476e4SDavid E. O'Brien     on the screen; vis:
537c80476e4SDavid E. O'Brien 
538c80476e4SDavid E. O'Brien 			     /old first difference
539c80476e4SDavid E. O'Brien 	/beginning of line   |              /old last same       /old EOL
540c80476e4SDavid E. O'Brien 	v		     v              v                    v
541c80476e4SDavid E. O'Brien old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
542c80476e4SDavid E. O'Brien new:	eddie> Oh, my little buggy says to me, as lurgid as
543c80476e4SDavid E. O'Brien 	^		     ^        ^			   ^
544c80476e4SDavid E. O'Brien 	\beginning of line   |        \new last same	   \new end of line
545c80476e4SDavid E. O'Brien 			     \new first difference
546c80476e4SDavid E. O'Brien 
547c80476e4SDavid E. O'Brien     all are character pointers for the sake of speed.  Special cases for
548c80476e4SDavid E. O'Brien     no differences, as well as for end of line additions must be handled.
549c80476e4SDavid E. O'Brien **************************************************************** */
550c80476e4SDavid E. O'Brien 
551c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it".  This should be about
552c80476e4SDavid E. O'Brien  * half the "cost" of going into insert mode, inserting a character, and
553c80476e4SDavid E. O'Brien  * going back out.  This should really be calculated from the termcap
554c80476e4SDavid E. O'Brien  * data...  For the moment, a good number for ANSI terminals.
555c80476e4SDavid E. O'Brien  */
556c80476e4SDavid E. O'Brien #define MIN_END_KEEP	4
557c80476e4SDavid E. O'Brien 
558c80476e4SDavid E. O'Brien static void			/* could be changed to make it smarter */
55945e5710bSMark Peek update_line(Char *old, Char *new, int cur_line)
560c80476e4SDavid E. O'Brien {
56123338178SMark Peek     Char *o, *n, *p, c;
562c80476e4SDavid E. O'Brien     Char  *ofd, *ols, *oe, *nfd, *nls, *ne;
563c80476e4SDavid E. O'Brien     Char  *osb, *ose, *nsb, *nse;
564c80476e4SDavid E. O'Brien     int     fx, sx;
565c80476e4SDavid E. O'Brien 
566c80476e4SDavid E. O'Brien     /*
56723338178SMark Peek      * find first diff (won't be CHAR_DBWIDTH in either line)
568c80476e4SDavid E. O'Brien      */
569c80476e4SDavid E. O'Brien     for (o = old, n = new; *o && (*o == *n); o++, n++)
570c80476e4SDavid E. O'Brien 	continue;
571c80476e4SDavid E. O'Brien     ofd = o;
572c80476e4SDavid E. O'Brien     nfd = n;
573c80476e4SDavid E. O'Brien 
574c80476e4SDavid E. O'Brien     /*
575c80476e4SDavid E. O'Brien      * Find the end of both old and new
576c80476e4SDavid E. O'Brien      */
57745e5710bSMark Peek     o = Strend(o);
57845e5710bSMark Peek 
579c80476e4SDavid E. O'Brien     /*
580c80476e4SDavid E. O'Brien      * Remove any trailing blanks off of the end, being careful not to
581c80476e4SDavid E. O'Brien      * back up past the beginning.
582c80476e4SDavid E. O'Brien      */
58345e5710bSMark Peek     if (!(adrof(STRhighlight) && MarkIsSet)) {
584c80476e4SDavid E. O'Brien     while (ofd < o) {
585c80476e4SDavid E. O'Brien 	if (o[-1] != ' ')
586c80476e4SDavid E. O'Brien 	    break;
587c80476e4SDavid E. O'Brien 	o--;
588c80476e4SDavid E. O'Brien     }
58945e5710bSMark Peek     }
590c80476e4SDavid E. O'Brien     oe = o;
591c80476e4SDavid E. O'Brien     *oe = (Char) 0;
592c80476e4SDavid E. O'Brien 
59345e5710bSMark Peek     n = Strend(n);
594c80476e4SDavid E. O'Brien 
595c80476e4SDavid E. O'Brien     /* remove blanks from end of new */
59645e5710bSMark Peek     if (!(adrof(STRhighlight) && MarkIsSet)) {
597c80476e4SDavid E. O'Brien     while (nfd < n) {
598c80476e4SDavid E. O'Brien 	if (n[-1] != ' ')
599c80476e4SDavid E. O'Brien 	    break;
600c80476e4SDavid E. O'Brien 	n--;
601c80476e4SDavid E. O'Brien     }
60245e5710bSMark Peek     }
603c80476e4SDavid E. O'Brien     ne = n;
604c80476e4SDavid E. O'Brien     *ne = (Char) 0;
605c80476e4SDavid E. O'Brien 
606c80476e4SDavid E. O'Brien     /*
607c80476e4SDavid E. O'Brien      * if no diff, continue to next line of redraw
608c80476e4SDavid E. O'Brien      */
609c80476e4SDavid E. O'Brien     if (*ofd == '\0' && *nfd == '\0') {
610c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
611c80476e4SDavid E. O'Brien 	dprintf("no difference.\r\n");
612c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
613c80476e4SDavid E. O'Brien 	return;
614c80476e4SDavid E. O'Brien     }
615c80476e4SDavid E. O'Brien 
616c80476e4SDavid E. O'Brien     /*
617c80476e4SDavid E. O'Brien      * find last same pointer
618c80476e4SDavid E. O'Brien      */
619c80476e4SDavid E. O'Brien     while ((o > ofd) && (n > nfd) && (*--o == *--n))
620c80476e4SDavid E. O'Brien 	continue;
62123338178SMark Peek     if (*o != *n) {
62223338178SMark Peek 	o++;
62323338178SMark Peek 	n++;
62423338178SMark Peek     }
62523338178SMark Peek     while (*o == CHAR_DBWIDTH) {
62623338178SMark Peek 	o++;
62723338178SMark Peek 	n++;
62823338178SMark Peek     }
62923338178SMark Peek     ols = o;
63023338178SMark Peek     nls = n;
631c80476e4SDavid E. O'Brien 
632c80476e4SDavid E. O'Brien     /*
633c80476e4SDavid E. O'Brien      * find same begining and same end
634c80476e4SDavid E. O'Brien      */
635c80476e4SDavid E. O'Brien     osb = ols;
636c80476e4SDavid E. O'Brien     nsb = nls;
637c80476e4SDavid E. O'Brien     ose = ols;
638c80476e4SDavid E. O'Brien     nse = nls;
639c80476e4SDavid E. O'Brien 
640c80476e4SDavid E. O'Brien     /*
641c80476e4SDavid E. O'Brien      * case 1: insert: scan from nfd to nls looking for *ofd
642c80476e4SDavid E. O'Brien      */
643c80476e4SDavid E. O'Brien     if (*ofd) {
644c80476e4SDavid E. O'Brien 	for (c = *ofd, n = nfd; n < nls; n++) {
645c80476e4SDavid E. O'Brien 	    if (c == *n) {
646c80476e4SDavid E. O'Brien 		for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
647c80476e4SDavid E. O'Brien 		    continue;
648c80476e4SDavid E. O'Brien 		/*
649c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
650c80476e4SDavid E. O'Brien 		 * take it
651c80476e4SDavid E. O'Brien 		 */
652c80476e4SDavid E. O'Brien 		if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
653c80476e4SDavid E. O'Brien 		    nsb = n;
654c80476e4SDavid E. O'Brien 		    nse = p;
655c80476e4SDavid E. O'Brien 		    osb = ofd;
656c80476e4SDavid E. O'Brien 		    ose = o;
657c80476e4SDavid E. O'Brien 		}
658c80476e4SDavid E. O'Brien 	    }
659c80476e4SDavid E. O'Brien 	}
660c80476e4SDavid E. O'Brien     }
661c80476e4SDavid E. O'Brien 
662c80476e4SDavid E. O'Brien     /*
663c80476e4SDavid E. O'Brien      * case 2: delete: scan from ofd to ols looking for *nfd
664c80476e4SDavid E. O'Brien      */
665c80476e4SDavid E. O'Brien     if (*nfd) {
666c80476e4SDavid E. O'Brien 	for (c = *nfd, o = ofd; o < ols; o++) {
667c80476e4SDavid E. O'Brien 	    if (c == *o) {
668c80476e4SDavid E. O'Brien 		for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
669c80476e4SDavid E. O'Brien 		    continue;
670c80476e4SDavid E. O'Brien 		/*
671c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
672c80476e4SDavid E. O'Brien 		 * take it
673c80476e4SDavid E. O'Brien 		 */
674c80476e4SDavid E. O'Brien 		if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
675c80476e4SDavid E. O'Brien 		    nsb = nfd;
676c80476e4SDavid E. O'Brien 		    nse = n;
677c80476e4SDavid E. O'Brien 		    osb = o;
678c80476e4SDavid E. O'Brien 		    ose = p;
679c80476e4SDavid E. O'Brien 		}
680c80476e4SDavid E. O'Brien 	    }
681c80476e4SDavid E. O'Brien 	}
682c80476e4SDavid E. O'Brien     }
683c80476e4SDavid E. O'Brien #ifdef notdef
684c80476e4SDavid E. O'Brien     /*
685c80476e4SDavid E. O'Brien      * If `last same' is before `same end' re-adjust
686c80476e4SDavid E. O'Brien      */
687c80476e4SDavid E. O'Brien     if (ols < ose)
688c80476e4SDavid E. O'Brien 	ols = ose;
689c80476e4SDavid E. O'Brien     if (nls < nse)
690c80476e4SDavid E. O'Brien 	nls = nse;
691c80476e4SDavid E. O'Brien #endif
692c80476e4SDavid E. O'Brien 
693c80476e4SDavid E. O'Brien     /*
694c80476e4SDavid E. O'Brien      * Pragmatics I: If old trailing whitespace or not enough characters to
695c80476e4SDavid E. O'Brien      * save to be worth it, then don't save the last same info.
696c80476e4SDavid E. O'Brien      */
697c80476e4SDavid E. O'Brien     if ((oe - ols) < MIN_END_KEEP) {
698c80476e4SDavid E. O'Brien 	ols = oe;
699c80476e4SDavid E. O'Brien 	nls = ne;
700c80476e4SDavid E. O'Brien     }
701c80476e4SDavid E. O'Brien 
702c80476e4SDavid E. O'Brien     /*
703c80476e4SDavid E. O'Brien      * Pragmatics II: if the terminal isn't smart enough, make the data dumber
704c80476e4SDavid E. O'Brien      * so the smart update doesn't try anything fancy
705c80476e4SDavid E. O'Brien      */
706c80476e4SDavid E. O'Brien 
707c80476e4SDavid E. O'Brien     /*
708c80476e4SDavid E. O'Brien      * fx is the number of characters we need to insert/delete: in the
709c80476e4SDavid E. O'Brien      * beginning to bring the two same begins together
710c80476e4SDavid E. O'Brien      */
711c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
712c80476e4SDavid E. O'Brien     /*
713c80476e4SDavid E. O'Brien      * sx is the number of characters we need to insert/delete: in the end to
714c80476e4SDavid E. O'Brien      * bring the two same last parts together
715c80476e4SDavid E. O'Brien      */
716c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
717c80476e4SDavid E. O'Brien 
718c80476e4SDavid E. O'Brien     if (!T_CanIns) {
719c80476e4SDavid E. O'Brien 	if (fx > 0) {
720c80476e4SDavid E. O'Brien 	    osb = ols;
721c80476e4SDavid E. O'Brien 	    ose = ols;
722c80476e4SDavid E. O'Brien 	    nsb = nls;
723c80476e4SDavid E. O'Brien 	    nse = nls;
724c80476e4SDavid E. O'Brien 	}
725c80476e4SDavid E. O'Brien 	if (sx > 0) {
726c80476e4SDavid E. O'Brien 	    ols = oe;
727c80476e4SDavid E. O'Brien 	    nls = ne;
728c80476e4SDavid E. O'Brien 	}
729c80476e4SDavid E. O'Brien 	if ((ols - ofd) < (nls - nfd)) {
730c80476e4SDavid E. O'Brien 	    ols = oe;
731c80476e4SDavid E. O'Brien 	    nls = ne;
732c80476e4SDavid E. O'Brien 	}
733c80476e4SDavid E. O'Brien     }
734c80476e4SDavid E. O'Brien     if (!T_CanDel) {
735c80476e4SDavid E. O'Brien 	if (fx < 0) {
736c80476e4SDavid E. O'Brien 	    osb = ols;
737c80476e4SDavid E. O'Brien 	    ose = ols;
738c80476e4SDavid E. O'Brien 	    nsb = nls;
739c80476e4SDavid E. O'Brien 	    nse = nls;
740c80476e4SDavid E. O'Brien 	}
741c80476e4SDavid E. O'Brien 	if (sx < 0) {
742c80476e4SDavid E. O'Brien 	    ols = oe;
743c80476e4SDavid E. O'Brien 	    nls = ne;
744c80476e4SDavid E. O'Brien 	}
745c80476e4SDavid E. O'Brien 	if ((ols - ofd) > (nls - nfd)) {
746c80476e4SDavid E. O'Brien 	    ols = oe;
747c80476e4SDavid E. O'Brien 	    nls = ne;
748c80476e4SDavid E. O'Brien 	}
749c80476e4SDavid E. O'Brien     }
750c80476e4SDavid E. O'Brien 
751c80476e4SDavid E. O'Brien     /*
752c80476e4SDavid E. O'Brien      * Pragmatics III: make sure the middle shifted pointers are correct if
753c80476e4SDavid E. O'Brien      * they don't point to anything (we may have moved ols or nls).
754c80476e4SDavid E. O'Brien      */
755c80476e4SDavid E. O'Brien     /* if the change isn't worth it, don't bother */
756c80476e4SDavid E. O'Brien     /* was: if (osb == ose) */
757c80476e4SDavid E. O'Brien     if ((ose - osb) < MIN_END_KEEP) {
758c80476e4SDavid E. O'Brien 	osb = ols;
759c80476e4SDavid E. O'Brien 	ose = ols;
760c80476e4SDavid E. O'Brien 	nsb = nls;
761c80476e4SDavid E. O'Brien 	nse = nls;
762c80476e4SDavid E. O'Brien     }
763c80476e4SDavid E. O'Brien 
764c80476e4SDavid E. O'Brien     /*
765c80476e4SDavid E. O'Brien      * Now that we are done with pragmatics we recompute fx, sx
766c80476e4SDavid E. O'Brien      */
767c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
768c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
769c80476e4SDavid E. O'Brien 
770c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
771c80476e4SDavid E. O'Brien     dprintf("\n");
772c80476e4SDavid E. O'Brien     dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
773c80476e4SDavid E. O'Brien 	    ofd - old, osb - old, ose - old, ols - old, oe - old);
774c80476e4SDavid E. O'Brien     dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
775c80476e4SDavid E. O'Brien 	    nfd - new, nsb - new, nse - new, nls - new, ne - new);
776c80476e4SDavid E. O'Brien     dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
777c80476e4SDavid E. O'Brien     dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
778c80476e4SDavid E. O'Brien     dprintstr("old- oe", old, oe);
779c80476e4SDavid E. O'Brien     dprintstr("new- ne", new, ne);
780c80476e4SDavid E. O'Brien     dprintstr("old-ofd", old, ofd);
781c80476e4SDavid E. O'Brien     dprintstr("new-nfd", new, nfd);
782c80476e4SDavid E. O'Brien     dprintstr("ofd-osb", ofd, osb);
783c80476e4SDavid E. O'Brien     dprintstr("nfd-nsb", nfd, nsb);
784c80476e4SDavid E. O'Brien     dprintstr("osb-ose", osb, ose);
785c80476e4SDavid E. O'Brien     dprintstr("nsb-nse", nsb, nse);
786c80476e4SDavid E. O'Brien     dprintstr("ose-ols", ose, ols);
787c80476e4SDavid E. O'Brien     dprintstr("nse-nls", nse, nls);
788c80476e4SDavid E. O'Brien     dprintstr("ols- oe", ols, oe);
789c80476e4SDavid E. O'Brien     dprintstr("nls- ne", nls, ne);
790c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
791c80476e4SDavid E. O'Brien 
792c80476e4SDavid E. O'Brien     /*
793c80476e4SDavid E. O'Brien      * CursorV to this line cur_line MUST be in this routine so that if we
794c80476e4SDavid E. O'Brien      * don't have to change the line, we don't move to it. CursorH to first
795c80476e4SDavid E. O'Brien      * diff char
796c80476e4SDavid E. O'Brien      */
797c80476e4SDavid E. O'Brien     MoveToLine(cur_line);
798c80476e4SDavid E. O'Brien 
799c80476e4SDavid E. O'Brien     /*
800c80476e4SDavid E. O'Brien      * at this point we have something like this:
801c80476e4SDavid E. O'Brien      *
802c80476e4SDavid E. O'Brien      * /old                  /ofd    /osb               /ose    /ols     /oe
803c80476e4SDavid E. O'Brien      * v.....................v       v..................v       v........v
804c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
805c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
806c80476e4SDavid E. O'Brien      * ^.....................^     ^..................^       ^........^
807c80476e4SDavid E. O'Brien      * \new                  \nfd  \nsb               \nse     \nls    \ne
808c80476e4SDavid E. O'Brien      *
809c80476e4SDavid E. O'Brien      * fx is the difference in length between the the chars between nfd and
810c80476e4SDavid E. O'Brien      * nsb, and the chars between ofd and osb, and is thus the number of
811c80476e4SDavid E. O'Brien      * characters to delete if < 0 (new is shorter than old, as above),
812c80476e4SDavid E. O'Brien      * or insert (new is longer than short).
813c80476e4SDavid E. O'Brien      *
814c80476e4SDavid E. O'Brien      * sx is the same for the second differences.
815c80476e4SDavid E. O'Brien      */
816c80476e4SDavid E. O'Brien 
817c80476e4SDavid E. O'Brien     /*
818c80476e4SDavid E. O'Brien      * if we have a net insert on the first difference, AND inserting the net
819c80476e4SDavid E. O'Brien      * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
820c80476e4SDavid E. O'Brien      * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
821c80476e4SDavid E. O'Brien      * (TermH - 1) else we do the deletes first so that we keep everything we
822c80476e4SDavid E. O'Brien      * need to.
823c80476e4SDavid E. O'Brien      */
824c80476e4SDavid E. O'Brien 
825c80476e4SDavid E. O'Brien     /*
826c80476e4SDavid E. O'Brien      * if the last same is the same like the end, there is no last same part,
827c80476e4SDavid E. O'Brien      * otherwise we want to keep the last same part set p to the last useful
828c80476e4SDavid E. O'Brien      * old character
829c80476e4SDavid E. O'Brien      */
830c80476e4SDavid E. O'Brien     p = (ols != oe) ? oe : ose;
831c80476e4SDavid E. O'Brien 
832c80476e4SDavid E. O'Brien     /*
833c80476e4SDavid E. O'Brien      * if (There is a diffence in the beginning) && (we need to insert
834c80476e4SDavid E. O'Brien      * characters) && (the number of characters to insert is less than the term
835c80476e4SDavid E. O'Brien      * width) We need to do an insert! else if (we need to delete characters)
836c80476e4SDavid E. O'Brien      * We need to delete characters! else No insert or delete
837c80476e4SDavid E. O'Brien      */
838c80476e4SDavid E. O'Brien     if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
839c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
840c80476e4SDavid E. O'Brien 	dprintf("first diff insert at %d...\r\n", nfd - new);
841c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
842c80476e4SDavid E. O'Brien 	/*
843c80476e4SDavid E. O'Brien 	 * Move to the first char to insert, where the first diff is.
844c80476e4SDavid E. O'Brien 	 */
845c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
846c80476e4SDavid E. O'Brien 	/*
847c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at end
848c80476e4SDavid E. O'Brien 	 */
849c80476e4SDavid E. O'Brien 	if (nsb != ne) {
850c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
851c80476e4SDavid E. O'Brien 	    dprintf("with stuff to keep at end\r\n");
852c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
853c80476e4SDavid E. O'Brien 	    /*
854c80476e4SDavid E. O'Brien 	     * insert fx chars of new starting at nfd
855c80476e4SDavid E. O'Brien 	     */
856c80476e4SDavid E. O'Brien 	    if (fx > 0) {
857c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
858c80476e4SDavid E. O'Brien 		if (!T_CanIns)
859c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot insert in early first diff\n");
860c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
861c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
862c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
863c80476e4SDavid E. O'Brien 	    }
864c80476e4SDavid E. O'Brien 	    /*
865c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
866c80476e4SDavid E. O'Brien 	     */
867c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
868c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
869c80476e4SDavid E. O'Brien 	}
870c80476e4SDavid E. O'Brien 	else {
871c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
872c80476e4SDavid E. O'Brien 	    dprintf("without anything to save\r\n");
873c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
874c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
875c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
876c80476e4SDavid E. O'Brien 	    /*
877c80476e4SDavid E. O'Brien 	     * Done
878c80476e4SDavid E. O'Brien 	     */
879c80476e4SDavid E. O'Brien 	    return;
880c80476e4SDavid E. O'Brien 	}
881c80476e4SDavid E. O'Brien     }
882c80476e4SDavid E. O'Brien     else if (fx < 0) {
883c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
884c80476e4SDavid E. O'Brien 	dprintf("first diff delete at %d...\r\n", ofd - old);
885c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
886c80476e4SDavid E. O'Brien 	/*
887c80476e4SDavid E. O'Brien 	 * move to the first char to delete where the first diff is
888c80476e4SDavid E. O'Brien 	 */
889c80476e4SDavid E. O'Brien 	MoveToChar(ofd - old);
890c80476e4SDavid E. O'Brien 	/*
891c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
892c80476e4SDavid E. O'Brien 	 */
893c80476e4SDavid E. O'Brien 	if (osb != oe) {
894c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
895c80476e4SDavid E. O'Brien 	    dprintf("with stuff to save at end\r\n");
896c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
897c80476e4SDavid E. O'Brien 	    /*
898c80476e4SDavid E. O'Brien 	     * fx is less than zero *always* here but we check for code
899c80476e4SDavid E. O'Brien 	     * symmetry
900c80476e4SDavid E. O'Brien 	     */
901c80476e4SDavid E. O'Brien 	    if (fx < 0) {
902c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
903c80476e4SDavid E. O'Brien 		if (!T_CanDel)
904c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot delete in first diff\n");
905c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
906c80476e4SDavid E. O'Brien 		DeleteChars(-fx);
907c80476e4SDavid E. O'Brien 		str_delete(old, (int) (ofd - old), TermH, -fx);
908c80476e4SDavid E. O'Brien 	    }
909c80476e4SDavid E. O'Brien 	    /*
910c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
911c80476e4SDavid E. O'Brien 	     */
912c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
913c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
914c80476e4SDavid E. O'Brien 
915c80476e4SDavid E. O'Brien 	}
916c80476e4SDavid E. O'Brien 	else {
917c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
918c80476e4SDavid E. O'Brien 	    dprintf("but with nothing left to save\r\n");
919c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
920c80476e4SDavid E. O'Brien 	    /*
921c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
922c80476e4SDavid E. O'Brien 	     */
923c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
924c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
925c80476e4SDavid E. O'Brien 	    dprintf("cleareol %d\n", (oe - old) - (ne - new));
926c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
9273b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
928c80476e4SDavid E. O'Brien 	    ClearEOL((oe - old) - (ne - new));
929c80476e4SDavid E. O'Brien #else
930c80476e4SDavid E. O'Brien 	    /*
931c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
932c80476e4SDavid E. O'Brien 	     */
933c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
9343b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
935c80476e4SDavid E. O'Brien 	    /*
936c80476e4SDavid E. O'Brien 	     * Done
937c80476e4SDavid E. O'Brien 	     */
938c80476e4SDavid E. O'Brien 	    return;
939c80476e4SDavid E. O'Brien 	}
940c80476e4SDavid E. O'Brien     }
941c80476e4SDavid E. O'Brien     else
942c80476e4SDavid E. O'Brien 	fx = 0;
943c80476e4SDavid E. O'Brien 
944c80476e4SDavid E. O'Brien     if (sx < 0) {
945c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
946c80476e4SDavid E. O'Brien 	dprintf("second diff delete at %d...\r\n", (ose - old) + fx);
947c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
948c80476e4SDavid E. O'Brien 	/*
949c80476e4SDavid E. O'Brien 	 * Check if we have stuff to delete
950c80476e4SDavid E. O'Brien 	 */
951c80476e4SDavid E. O'Brien 	/*
952c80476e4SDavid E. O'Brien 	 * fx is the number of characters inserted (+) or deleted (-)
953c80476e4SDavid E. O'Brien 	 */
954c80476e4SDavid E. O'Brien 
955c80476e4SDavid E. O'Brien 	MoveToChar((ose - old) + fx);
956c80476e4SDavid E. O'Brien 	/*
957c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
958c80476e4SDavid E. O'Brien 	 */
959c80476e4SDavid E. O'Brien 	if (ols != oe) {
960c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
961c80476e4SDavid E. O'Brien 	    dprintf("with stuff to save at end\r\n");
962c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
963c80476e4SDavid E. O'Brien 	    /*
964c80476e4SDavid E. O'Brien 	     * Again a duplicate test.
965c80476e4SDavid E. O'Brien 	     */
966c80476e4SDavid E. O'Brien 	    if (sx < 0) {
967c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
968c80476e4SDavid E. O'Brien 		if (!T_CanDel)
969c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot delete in second diff\n");
970c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
971c80476e4SDavid E. O'Brien 		DeleteChars(-sx);
972c80476e4SDavid E. O'Brien 	    }
973c80476e4SDavid E. O'Brien 
974c80476e4SDavid E. O'Brien 	    /*
975c80476e4SDavid E. O'Brien 	     * write (nls-nse) chars of new starting at nse
976c80476e4SDavid E. O'Brien 	     */
977c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
978c80476e4SDavid E. O'Brien 	}
979c80476e4SDavid E. O'Brien 	else {
980c80476e4SDavid E. O'Brien 	    int olen = (int) (oe - old + fx);
981c80476e4SDavid E. O'Brien 	    if (olen > TermH)
982c80476e4SDavid E. O'Brien 		olen = TermH;
983c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
984c80476e4SDavid E. O'Brien 	    dprintf("but with nothing left to save\r\n");
985c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
986c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
987c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
988c80476e4SDavid E. O'Brien 	    dprintf("cleareol %d\n", olen - (ne - new));
989c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
9903b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
991c80476e4SDavid E. O'Brien 	    ClearEOL(olen - (ne - new));
992c80476e4SDavid E. O'Brien #else
993c80476e4SDavid E. O'Brien 	    /*
994c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
995c80476e4SDavid E. O'Brien 	     */
996c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
9973b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
998c80476e4SDavid E. O'Brien 	}
999c80476e4SDavid E. O'Brien     }
1000c80476e4SDavid E. O'Brien 
1001c80476e4SDavid E. O'Brien     /*
1002c80476e4SDavid E. O'Brien      * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
1003c80476e4SDavid E. O'Brien      */
1004c80476e4SDavid E. O'Brien     if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
1005c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1006c80476e4SDavid E. O'Brien 	dprintf("late first diff insert at %d...\r\n", nfd - new);
1007c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1008c80476e4SDavid E. O'Brien 
1009c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
1010c80476e4SDavid E. O'Brien 	/*
1011c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at the end
1012c80476e4SDavid E. O'Brien 	 */
1013c80476e4SDavid E. O'Brien 	if (nsb != ne) {
1014c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1015c80476e4SDavid E. O'Brien 	    dprintf("with stuff to keep at end\r\n");
1016c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1017c80476e4SDavid E. O'Brien 	    /*
1018c80476e4SDavid E. O'Brien 	     * We have to recalculate fx here because we set it
1019c80476e4SDavid E. O'Brien 	     * to zero above as a flag saying that we hadn't done
1020c80476e4SDavid E. O'Brien 	     * an early first insert.
1021c80476e4SDavid E. O'Brien 	     */
1022c80476e4SDavid E. O'Brien 	    fx = (int) ((nsb - nfd) - (osb - ofd));
1023c80476e4SDavid E. O'Brien 	    if (fx > 0) {
1024c80476e4SDavid E. O'Brien 		/*
1025c80476e4SDavid E. O'Brien 		 * insert fx chars of new starting at nfd
1026c80476e4SDavid E. O'Brien 		 */
1027c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1028c80476e4SDavid E. O'Brien 		if (!T_CanIns)
1029c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot insert in late first diff\n");
1030c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1031c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
1032c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1033c80476e4SDavid E. O'Brien 	    }
1034c80476e4SDavid E. O'Brien 
1035c80476e4SDavid E. O'Brien 	    /*
1036c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1037c80476e4SDavid E. O'Brien 	     */
1038c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
1039c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1040c80476e4SDavid E. O'Brien 	}
1041c80476e4SDavid E. O'Brien 	else {
1042c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1043c80476e4SDavid E. O'Brien 	    dprintf("without anything to save\r\n");
1044c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1045c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
1046c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
1047c80476e4SDavid E. O'Brien 	}
1048c80476e4SDavid E. O'Brien     }
1049c80476e4SDavid E. O'Brien 
1050c80476e4SDavid E. O'Brien     /*
1051c80476e4SDavid E. O'Brien      * line is now NEW up to nse
1052c80476e4SDavid E. O'Brien      */
1053c80476e4SDavid E. O'Brien     if (sx >= 0) {
1054c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1055c80476e4SDavid E. O'Brien 	dprintf("second diff insert at %d...\r\n", nse - new);
1056c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1057c80476e4SDavid E. O'Brien 	MoveToChar(nse - new);
1058c80476e4SDavid E. O'Brien 	if (ols != oe) {
1059c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1060c80476e4SDavid E. O'Brien 	    dprintf("with stuff to keep at end\r\n");
1061c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1062c80476e4SDavid E. O'Brien 	    if (sx > 0) {
1063c80476e4SDavid E. O'Brien 		/* insert sx chars of new starting at nse */
1064c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1065c80476e4SDavid E. O'Brien 		if (!T_CanIns)
1066c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot insert in second diff\n");
1067c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1068c80476e4SDavid E. O'Brien 		Insert_write(nse, sx);
1069c80476e4SDavid E. O'Brien 	    }
1070c80476e4SDavid E. O'Brien 
1071c80476e4SDavid E. O'Brien 	    /*
1072c80476e4SDavid E. O'Brien 	     * write (nls-nse) - sx chars of new starting at (nse + sx)
1073c80476e4SDavid E. O'Brien 	     */
1074c80476e4SDavid E. O'Brien 	    so_write(nse + sx, (nls - nse) - sx);
1075c80476e4SDavid E. O'Brien 	}
1076c80476e4SDavid E. O'Brien 	else {
1077c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1078c80476e4SDavid E. O'Brien 	    dprintf("without anything to save\r\n");
1079c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1080c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1081c80476e4SDavid E. O'Brien 
1082c80476e4SDavid E. O'Brien 	    /*
1083c80476e4SDavid E. O'Brien              * No need to do a clear-to-end here because we were doing
1084c80476e4SDavid E. O'Brien 	     * a second insert, so we will have over written all of the
1085c80476e4SDavid E. O'Brien 	     * old string.
1086c80476e4SDavid E. O'Brien 	     */
1087c80476e4SDavid E. O'Brien 	}
1088c80476e4SDavid E. O'Brien     }
1089c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1090c80476e4SDavid E. O'Brien     dprintf("done.\r\n");
1091c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1092c80476e4SDavid E. O'Brien }
1093c80476e4SDavid E. O'Brien 
1094c80476e4SDavid E. O'Brien 
1095c80476e4SDavid E. O'Brien static void
109645e5710bSMark Peek cpy_pad_spaces(Char *dst, Char *src, int width)
1097c80476e4SDavid E. O'Brien {
109823338178SMark Peek     int i;
1099c80476e4SDavid E. O'Brien 
1100c80476e4SDavid E. O'Brien     for (i = 0; i < width; i++) {
1101c80476e4SDavid E. O'Brien 	if (*src == (Char) 0)
1102c80476e4SDavid E. O'Brien 	    break;
1103c80476e4SDavid E. O'Brien 	*dst++ = *src++;
1104c80476e4SDavid E. O'Brien     }
1105c80476e4SDavid E. O'Brien 
1106c80476e4SDavid E. O'Brien     while (i < width) {
1107c80476e4SDavid E. O'Brien 	*dst++ = ' ';
1108c80476e4SDavid E. O'Brien 	i++;
1109c80476e4SDavid E. O'Brien     }
1110c80476e4SDavid E. O'Brien     *dst = (Char) 0;
1111c80476e4SDavid E. O'Brien }
1112c80476e4SDavid E. O'Brien 
1113c80476e4SDavid E. O'Brien void
111445e5710bSMark Peek RefCursor(void)
1115c80476e4SDavid E. O'Brien {				/* only move to new cursor pos */
111623338178SMark Peek     Char *cp;
111745e5710bSMark Peek     int w, h, th, v;
1118c80476e4SDavid E. O'Brien 
1119c80476e4SDavid E. O'Brien     /* first we must find where the cursor is... */
1120c80476e4SDavid E. O'Brien     h = 0;
1121c80476e4SDavid E. O'Brien     v = 0;
1122c80476e4SDavid E. O'Brien     th = TermH;			/* optimize for speed */
1123c80476e4SDavid E. O'Brien 
112445e5710bSMark Peek     for (cp = Prompt; cp != NULL && *cp; ) {	/* do prompt */
112523338178SMark Peek 	if (*cp & LITERAL) {
112623338178SMark Peek 	    cp++;
1127c80476e4SDavid E. O'Brien 	    continue;
112823338178SMark Peek 	}
112945e5710bSMark Peek 	w = NLSClassify(*cp & CHAR, cp == Prompt);
113045e5710bSMark Peek 	cp++;
113123338178SMark Peek 	switch(w) {
113223338178SMark Peek 	    case NLSCLASS_NL:
1133c80476e4SDavid E. O'Brien 		h = 0;
1134c80476e4SDavid E. O'Brien 		v++;
113523338178SMark Peek 		break;
113623338178SMark Peek 	    case NLSCLASS_TAB:
113723338178SMark Peek 		while (++h & 07)
113823338178SMark Peek 		    ;
113923338178SMark Peek 		break;
114023338178SMark Peek 	    case NLSCLASS_CTRL:
114123338178SMark Peek 		h += 2;
114223338178SMark Peek 		break;
114323338178SMark Peek 	    case NLSCLASS_ILLEGAL:
114423338178SMark Peek 		h += 4;
114523338178SMark Peek 		break;
114623338178SMark Peek 	    case NLSCLASS_ILLEGAL2:
114723338178SMark Peek 	    case NLSCLASS_ILLEGAL3:
114823338178SMark Peek 	    case NLSCLASS_ILLEGAL4:
114923338178SMark Peek 		h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
115023338178SMark Peek 		break;
115123338178SMark Peek 	    default:
115223338178SMark Peek 		h += w;
1153c80476e4SDavid E. O'Brien 	}
1154c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
115523338178SMark Peek 	    h -= th;
115623338178SMark Peek 	    v++;
115723338178SMark Peek 	}
115823338178SMark Peek     }
115923338178SMark Peek 
116023338178SMark Peek     for (cp = InputBuf; cp < Cursor;) {	/* do input buffer to Cursor */
116145e5710bSMark Peek 	w = NLSClassify(*cp & CHAR, cp == InputBuf);
116245e5710bSMark Peek 	cp++;
116323338178SMark Peek 	switch(w) {
116423338178SMark Peek 	    case NLSCLASS_NL:
1165c80476e4SDavid E. O'Brien 		h = 0;
1166c80476e4SDavid E. O'Brien 		v++;
116723338178SMark Peek 		break;
116823338178SMark Peek 	    case NLSCLASS_TAB:
116923338178SMark Peek 		while (++h & 07)
117023338178SMark Peek 		    ;
117123338178SMark Peek 		break;
117223338178SMark Peek 	    case NLSCLASS_CTRL:
117323338178SMark Peek 		h += 2;
117423338178SMark Peek 		break;
117523338178SMark Peek 	    case NLSCLASS_ILLEGAL:
117623338178SMark Peek 		h += 4;
117723338178SMark Peek 		break;
117823338178SMark Peek 	    case NLSCLASS_ILLEGAL2:
117923338178SMark Peek 	    case NLSCLASS_ILLEGAL3:
118023338178SMark Peek 	    case NLSCLASS_ILLEGAL4:
118123338178SMark Peek 		h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
118223338178SMark Peek 		break;
118323338178SMark Peek 	    default:
118423338178SMark Peek 		h += w;
1185c80476e4SDavid E. O'Brien 	}
1186c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
118723338178SMark Peek 	    h -= th;
1188c80476e4SDavid E. O'Brien 	    v++;
1189c80476e4SDavid E. O'Brien 	}
1190c80476e4SDavid E. O'Brien     }
1191c80476e4SDavid E. O'Brien 
1192c80476e4SDavid E. O'Brien     /* now go there */
1193c80476e4SDavid E. O'Brien     MoveToLine(v);
1194c80476e4SDavid E. O'Brien     MoveToChar(h);
119545e5710bSMark Peek     if (adrof(STRhighlight) && MarkIsSet) {
119645e5710bSMark Peek 	ClearLines();
119745e5710bSMark Peek 	ClearDisp();
119845e5710bSMark Peek 	Refresh();
119945e5710bSMark Peek     }
1200c80476e4SDavid E. O'Brien     flush();
1201c80476e4SDavid E. O'Brien }
1202c80476e4SDavid E. O'Brien 
1203b2d5d167SMark Peek #ifndef WINTT_NATIVE
1204c80476e4SDavid E. O'Brien static void
120545e5710bSMark Peek PutPlusOne(Char c, int width)
1206c80476e4SDavid E. O'Brien {
120723338178SMark Peek     while (width > 1 && CursorH + width > TermH)
120823338178SMark Peek 	PutPlusOne(' ', 1);
120923338178SMark Peek     if ((c & LITERAL) != 0) {
121023338178SMark Peek 	Char *d;
121123338178SMark Peek 	for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++)
121223338178SMark Peek 	    (void) putwraw(*d);
121323338178SMark Peek     } else {
121423338178SMark Peek 	(void) putwraw(c);
121523338178SMark Peek     }
1216c80476e4SDavid E. O'Brien     Display[CursorV][CursorH++] = (Char) c;
121723338178SMark Peek     while (--width > 0)
121823338178SMark Peek 	Display[CursorV][CursorH++] = CHAR_DBWIDTH;
1219c80476e4SDavid E. O'Brien     if (CursorH >= TermH) {	/* if we must overflow */
1220c80476e4SDavid E. O'Brien 	CursorH = 0;
1221c80476e4SDavid E. O'Brien 	CursorV++;
1222c80476e4SDavid E. O'Brien 	OldvcV++;
1223c80476e4SDavid E. O'Brien 	if (T_Margin & MARGIN_AUTO) {
1224c80476e4SDavid E. O'Brien 	    if (T_Margin & MARGIN_MAGIC) {
1225c80476e4SDavid E. O'Brien 		(void) putraw(' ');
1226c80476e4SDavid E. O'Brien 		(void) putraw('\b');
1227c80476e4SDavid E. O'Brien 	    }
1228c80476e4SDavid E. O'Brien 	}
1229c80476e4SDavid E. O'Brien 	else {
1230c80476e4SDavid E. O'Brien 	    (void) putraw('\r');
1231c80476e4SDavid E. O'Brien 	    (void) putraw('\n');
1232c80476e4SDavid E. O'Brien 	}
1233c80476e4SDavid E. O'Brien     }
1234c80476e4SDavid E. O'Brien }
1235b2d5d167SMark Peek #endif
1236c80476e4SDavid E. O'Brien 
1237c80476e4SDavid E. O'Brien void
123823338178SMark Peek RefPlusOne(int l)
1239c80476e4SDavid E. O'Brien {				/* we added just one char, handle it fast.
1240c80476e4SDavid E. O'Brien 				 * assumes that screen cursor == real cursor */
124145e5710bSMark Peek     Char *cp, c;
124223338178SMark Peek     int w;
1243c80476e4SDavid E. O'Brien 
124423338178SMark Peek     if (Cursor != LastChar) {
1245c80476e4SDavid E. O'Brien 	Refresh();		/* too hard to handle */
1246c80476e4SDavid E. O'Brien 	return;
1247c80476e4SDavid E. O'Brien     }
1248c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1249c80476e4SDavid E. O'Brien 	Refresh();		/* clear out rprompt if less than one char gap*/
1250c80476e4SDavid E. O'Brien 	return;
125123338178SMark Peek     }
125223338178SMark Peek     cp = Cursor - l;
125345e5710bSMark Peek     c = *cp & CHAR;
125423338178SMark Peek     w = NLSClassify(c, cp == InputBuf);
125523338178SMark Peek     switch(w) {
125623338178SMark Peek 	case NLSCLASS_CTRL:
125723338178SMark Peek 	    PutPlusOne('^', 1);
125823338178SMark Peek 	    if (c == CTL_ESC('\177')) {
125923338178SMark Peek 		PutPlusOne('?', 1);
126023338178SMark Peek 		break;
126123338178SMark Peek 	    }
12623b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
126323338178SMark Peek 	    /* uncontrolify it; works only for iso8859-1 like sets */
126423338178SMark Peek 	    PutPlusOne((c | 0100), 1);
12653b6eaa7bSAndrey A. Chernov #else
126623338178SMark Peek 	    PutPlusOne(_toebcdic[_toascii[c]|0100], 1);
126723338178SMark Peek #endif
126823338178SMark Peek 	    break;
126923338178SMark Peek 	case NLSCLASS_ILLEGAL:
127023338178SMark Peek 	    PutPlusOne('\\', 1);
127123338178SMark Peek 	    PutPlusOne(((c >> 6) & 7) + '0', 1);
127223338178SMark Peek 	    PutPlusOne(((c >> 3) & 7) + '0', 1);
127323338178SMark Peek 	    PutPlusOne((c & 7) + '0', 1);
127423338178SMark Peek 	    break;
127523338178SMark Peek 	case 1:
127645e5710bSMark Peek 	    if (adrof(STRhighlight) && MarkIsSet)
127745e5710bSMark Peek 		StartHighlight();
127823338178SMark Peek 	    if (l > 1)
127923338178SMark Peek 		PutPlusOne(MakeLiteral(cp, l, 0), 1);
1280c80476e4SDavid E. O'Brien 	    else
128123338178SMark Peek 		PutPlusOne(*cp, 1);
128245e5710bSMark Peek 	    if (adrof(STRhighlight) && MarkIsSet)
128345e5710bSMark Peek 		StopHighlight();
128423338178SMark Peek 	    break;
128523338178SMark Peek 	default:
128623338178SMark Peek 	    Refresh();		/* too hard to handle */
128723338178SMark Peek 	    return;
1288c80476e4SDavid E. O'Brien     }
1289c80476e4SDavid E. O'Brien     flush();
1290c80476e4SDavid E. O'Brien }
1291c80476e4SDavid E. O'Brien 
1292c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */
1293c80476e4SDavid E. O'Brien 
1294c80476e4SDavid E. O'Brien void
129545e5710bSMark Peek ClearDisp(void)
1296c80476e4SDavid E. O'Brien {
129723338178SMark Peek     int i;
1298c80476e4SDavid E. O'Brien 
1299c80476e4SDavid E. O'Brien     CursorV = 0;		/* clear the display buffer */
1300c80476e4SDavid E. O'Brien     CursorH = 0;
1301c80476e4SDavid E. O'Brien     for (i = 0; i < TermV; i++)
1302c80476e4SDavid E. O'Brien 	(void) memset(Display[i], 0, TermH * sizeof(Display[0][0]));
1303c80476e4SDavid E. O'Brien     OldvcV = 0;
130423338178SMark Peek     litlen = 0;
1305c80476e4SDavid E. O'Brien }
1306c80476e4SDavid E. O'Brien 
1307c80476e4SDavid E. O'Brien void
130845e5710bSMark Peek ClearLines(void)
1309c80476e4SDavid E. O'Brien {				/* Make sure all lines are *really* blank */
131023338178SMark Peek     int i;
1311c80476e4SDavid E. O'Brien 
1312c80476e4SDavid E. O'Brien     if (T_CanCEOL) {
1313c80476e4SDavid E. O'Brien 	/*
1314c80476e4SDavid E. O'Brien 	 * Clear the lines from the bottom up so that if we try moving
1315c80476e4SDavid E. O'Brien 	 * the cursor down by writing the character that is at the end
1316c80476e4SDavid E. O'Brien 	 * of the screen line, we won't rewrite a character that shouldn't
1317c80476e4SDavid E. O'Brien 	 * be there.
1318c80476e4SDavid E. O'Brien 	 */
1319c80476e4SDavid E. O'Brien 	for (i = OldvcV; i >= 0; i--) {	/* for each line on the screen */
1320c80476e4SDavid E. O'Brien 	    MoveToLine(i);
1321c80476e4SDavid E. O'Brien 	    MoveToChar(0);
1322c80476e4SDavid E. O'Brien 	    ClearEOL(TermH);
1323c80476e4SDavid E. O'Brien 	}
1324c80476e4SDavid E. O'Brien     }
1325c80476e4SDavid E. O'Brien     else {
1326c80476e4SDavid E. O'Brien 	MoveToLine(OldvcV);	/* go to last line */
1327c80476e4SDavid E. O'Brien 	(void) putraw('\r');	/* go to BOL */
1328c80476e4SDavid E. O'Brien 	(void) putraw('\n');	/* go to new line */
1329c80476e4SDavid E. O'Brien     }
1330c80476e4SDavid E. O'Brien }
1331