xref: /freebsd/contrib/tcsh/ed.refresh.c (revision 19d2e3de755b7c9ca2f5c90b5902fc8f214b2490)
1*19d2e3deSDmitry Chagin /* $Header: /p/tcsh/cvsroot/tcsh/ed.refresh.c,v 3.51 2015/06/06 21:19:07 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 
35*19d2e3deSDmitry Chagin RCSID("$tcsh: ed.refresh.c,v 3.51 2015/06/06 21:19:07 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);
49*19d2e3deSDmitry Chagin static	int	Draw 			(Char *, int, 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)
649ccc37e3SMark Peek static	void	reprintf			(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 {
719ccc37e3SMark Peek     reprintf("%s:\"", str);
7223338178SMark Peek     while (f < t) {
7345e5710bSMark Peek 	if (ASC(*f) & ~ASCII)
749ccc37e3SMark Peek 	  reprintf("[%x]", *f++);
7523338178SMark Peek 	else
769ccc37e3SMark Peek 	  reprintf("%c", CTL_ESC(ASCII & ASC(*f++)));
7723338178SMark Peek     }
789ccc37e3SMark Peek     reprintf("\"\r\n");
79c80476e4SDavid E. O'Brien }
80c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
81c80476e4SDavid E. O'Brien 
829ccc37e3SMark Peek /* reprintf():
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
889ccc37e3SMark Peek reprintf(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 
162*19d2e3deSDmitry Chagin /* draw char at cp, expand tabs, ctl chars */
16323338178SMark Peek static int
164*19d2e3deSDmitry Chagin Draw(Char *cp, int nocomb, int drawPrompt)
16523338178SMark Peek {
16645e5710bSMark Peek     int w, i, lv, lh;
16745e5710bSMark Peek     Char c, attr;
16823338178SMark Peek 
169*19d2e3deSDmitry Chagin #ifdef WIDE_STRINGS
170*19d2e3deSDmitry Chagin     if (!drawPrompt) {			/* draw command-line */
171*19d2e3deSDmitry Chagin 	attr = 0;
172*19d2e3deSDmitry Chagin 	c = *cp;
173*19d2e3deSDmitry Chagin     } else {				/* draw prompt */
174*19d2e3deSDmitry Chagin 	/* prompt with attributes(UNDER,BOLD,STANDOUT) */
175*19d2e3deSDmitry Chagin 	if (*cp & (UNDER | BOLD | STANDOUT)) {		/* *cp >= STANDOUT */
176*19d2e3deSDmitry Chagin 
177*19d2e3deSDmitry Chagin 	    /* example)
178*19d2e3deSDmitry Chagin 	     * We can't distinguish whether (*cp=)0x02ffffff is
179*19d2e3deSDmitry Chagin 	     * U+02FFFFFF or U+00FFFFFF|STANDOUT.
180*19d2e3deSDmitry Chagin 	     * We handle as U+00FFFFFF|STANDOUT, only when drawing prompt. */
181*19d2e3deSDmitry Chagin 	    attr = (*cp & ATTRIBUTES);
182*19d2e3deSDmitry Chagin 	    /* ~(UNDER | BOLD | STANDOUT) = 0xf1ffffff */
183*19d2e3deSDmitry Chagin 	    c = *cp & ~(UNDER | BOLD | STANDOUT);
184*19d2e3deSDmitry Chagin 
185*19d2e3deSDmitry Chagin 	    /* if c is ctrl code, we handle *cp as havnig no attributes */
186*19d2e3deSDmitry Chagin 	    if ((c < 0x20 && c >= 0) || c == 0x7f) {
187*19d2e3deSDmitry Chagin 		attr = 0;
188*19d2e3deSDmitry Chagin 		c = *cp;
189*19d2e3deSDmitry Chagin 	    }
190*19d2e3deSDmitry Chagin 	} else {			/* prompt without attributes */
191*19d2e3deSDmitry Chagin 	    attr = 0;
192*19d2e3deSDmitry Chagin 	    c = *cp;
193*19d2e3deSDmitry Chagin 	}
194*19d2e3deSDmitry Chagin     }
195*19d2e3deSDmitry Chagin #else
19623338178SMark Peek     attr = *cp & ~CHAR;
19745e5710bSMark Peek     c = *cp & CHAR;
198*19d2e3deSDmitry Chagin #endif
199*19d2e3deSDmitry Chagin     w = NLSClassify(c, nocomb, drawPrompt);
20023338178SMark Peek     switch (w) {
20123338178SMark Peek 	case NLSCLASS_NL:
20223338178SMark Peek 	    Vdraw('\0', 0);		/* assure end of line	 */
203c80476e4SDavid E. O'Brien 	    vcursor_h = 0;		/* reset cursor pos	 */
204c80476e4SDavid E. O'Brien 	    vcursor_v++;
20523338178SMark Peek 	    break;
20623338178SMark Peek 	case NLSCLASS_TAB:
20723338178SMark Peek 	    do {
20823338178SMark Peek 		Vdraw(' ', 1);
20923338178SMark Peek 	    } while ((vcursor_h & 07) != 0);
21023338178SMark Peek 	    break;
21123338178SMark Peek 	case NLSCLASS_CTRL:
21223338178SMark Peek 	    Vdraw('^' | attr, 1);
21323338178SMark Peek 	    if (c == CTL_ESC('\177')) {
21423338178SMark Peek 		Vdraw('?' | attr, 1);
21523338178SMark Peek 	    } else {
2163b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
217c80476e4SDavid E. O'Brien 		/* uncontrolify it; works only for iso8859-1 like sets */
21823338178SMark Peek 		Vdraw(c | 0100 | attr, 1);
2193b6eaa7bSAndrey A. Chernov #else
22023338178SMark Peek 		Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1);
22123338178SMark Peek #endif
222c80476e4SDavid E. O'Brien 	    }
22323338178SMark Peek 	    break;
22423338178SMark Peek 	case NLSCLASS_ILLEGAL:
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);
22923338178SMark Peek 	    break;
23023338178SMark Peek 	case NLSCLASS_ILLEGAL2:
23123338178SMark Peek 	case NLSCLASS_ILLEGAL3:
23223338178SMark Peek 	case NLSCLASS_ILLEGAL4:
233*19d2e3deSDmitry Chagin 	case NLSCLASS_ILLEGAL5:
234*19d2e3deSDmitry Chagin 	    Vdraw('\\', 1);
235*19d2e3deSDmitry Chagin 	    Vdraw('U', 1);
236*19d2e3deSDmitry Chagin 	    Vdraw('+', 1);
237*19d2e3deSDmitry Chagin 	    for (i = 16 + 4 * (-w-5); i >= 0; i -= 4)
23823338178SMark Peek 		Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1);
23923338178SMark Peek 	    break;
24023338178SMark Peek 	case 0:
24123338178SMark Peek 	    lv = vcursor_v;
24223338178SMark Peek 	    lh = vcursor_h;
24323338178SMark Peek 	    for (;;) {
24423338178SMark Peek 		lh--;
24523338178SMark Peek 		if (lh < 0) {
24623338178SMark Peek 		    lv--;
24723338178SMark Peek 		    if (lv < 0)
24823338178SMark Peek 			break;
24923338178SMark Peek 		    lh = Strlen(Vdisplay[lv]) - 1;
250c80476e4SDavid E. O'Brien 		}
25123338178SMark Peek 		if (Vdisplay[lv][lh] != CHAR_DBWIDTH)
25223338178SMark Peek 		    break;
25323338178SMark Peek 	    }
25423338178SMark Peek 	    if (lv < 0) {
25523338178SMark Peek 		Vdraw('\\' | attr, 1);
25645e5710bSMark Peek 		Vdraw((((c >> 6) & 7) + '0') | attr, 1);
25745e5710bSMark Peek 		Vdraw((((c >> 3) & 7) + '0') | attr, 1);
25845e5710bSMark Peek 		Vdraw(((c & 7) + '0') | attr, 1);
25945e5710bSMark Peek 		break;
26023338178SMark Peek 	    }
26145e5710bSMark Peek 	    Vdisplay[lv][lh] = MakeLiteral(cp, 1, Vdisplay[lv][lh]);
26223338178SMark Peek 	    break;
26323338178SMark Peek 	default:
26423338178SMark Peek 	    Vdraw(*cp, w);
26523338178SMark Peek 	    break;
266c80476e4SDavid E. O'Brien     }
26745e5710bSMark Peek     return 1;
268c80476e4SDavid E. O'Brien }
269c80476e4SDavid E. O'Brien 
270c80476e4SDavid E. O'Brien static void
27145e5710bSMark Peek Vdraw(Char c, int width)	/* draw char c onto V lines */
272c80476e4SDavid E. O'Brien {
273c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
274c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS
2759ccc37e3SMark Peek     reprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width);
276c80476e4SDavid E. O'Brien # else
2779ccc37e3SMark Peek     reprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width);
278c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */
279c80476e4SDavid E. O'Brien #endif  /* DEBUG_REFRESH */
280c80476e4SDavid E. O'Brien 
28123338178SMark Peek     /* Hopefully this is what all the terminals do with multi-column characters
28223338178SMark Peek        that "span line breaks". */
28323338178SMark Peek     while (vcursor_h + width > TermH)
28423338178SMark Peek 	Vdraw(' ', 1);
28545e5710bSMark Peek     Vdisplay[vcursor_v][vcursor_h] = c;
28623338178SMark Peek     if (width)
287c80476e4SDavid E. O'Brien 	vcursor_h++;		/* advance to next place */
28823338178SMark Peek     while (--width > 0)
28923338178SMark Peek 	Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH;
290c80476e4SDavid E. O'Brien     if (vcursor_h >= TermH) {
291c80476e4SDavid E. O'Brien 	Vdisplay[vcursor_v][TermH] = '\0';	/* assure end of line */
292c80476e4SDavid E. O'Brien 	vcursor_h = 0;		/* reset it. */
293c80476e4SDavid E. O'Brien 	vcursor_v++;
294c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
295c80476e4SDavid E. O'Brien 	if (vcursor_v >= TermV) {	/* should NEVER happen. */
2969ccc37e3SMark Peek 	    reprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
297c80476e4SDavid E. O'Brien 		    vcursor_v, TermV);
298c80476e4SDavid E. O'Brien 	    abort();
299c80476e4SDavid E. O'Brien 	}
300c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
301c80476e4SDavid E. O'Brien     }
302c80476e4SDavid E. O'Brien }
303c80476e4SDavid E. O'Brien 
304c80476e4SDavid E. O'Brien /*
305c80476e4SDavid E. O'Brien  *  RefreshPromptpart()
306c80476e4SDavid E. O'Brien  *	draws a prompt element, expanding literals (we know it's ASCIZ)
307c80476e4SDavid E. O'Brien  */
308c80476e4SDavid E. O'Brien static void
30945e5710bSMark Peek RefreshPromptpart(Char *buf)
310c80476e4SDavid E. O'Brien {
31123338178SMark Peek     Char *cp;
31245e5710bSMark Peek     int w;
313c80476e4SDavid E. O'Brien 
31445e5710bSMark Peek     if (buf == NULL)
31545e5710bSMark Peek 	return;
31623338178SMark Peek     for (cp = buf; *cp; ) {
317c80476e4SDavid E. O'Brien 	if (*cp & LITERAL) {
31823338178SMark Peek 	    Char *litstart = cp;
319c80476e4SDavid E. O'Brien 	    while (*cp & LITERAL)
320c80476e4SDavid E. O'Brien 		cp++;
32123338178SMark Peek 	    if (*cp) {
32245e5710bSMark Peek 		w = NLSWidth(*cp & CHAR);
32345e5710bSMark Peek 		Vdraw(MakeLiteral(litstart, cp + 1 - litstart, 0), w);
32445e5710bSMark Peek 		cp++;
32523338178SMark Peek 	    }
326c80476e4SDavid E. O'Brien 	    else {
327c80476e4SDavid E. O'Brien 		/*
328c80476e4SDavid E. O'Brien 		 * XXX: This is a bug, we lose the last literal, if it is not
329c80476e4SDavid E. O'Brien 		 * followed by a normal character, but it is too hard to fix
330c80476e4SDavid E. O'Brien 		 */
331c80476e4SDavid E. O'Brien 		break;
332c80476e4SDavid E. O'Brien 	    }
333c80476e4SDavid E. O'Brien 	}
334c80476e4SDavid E. O'Brien 	else
335*19d2e3deSDmitry Chagin 	    cp += Draw(cp, cp == buf, 1);
336c80476e4SDavid E. O'Brien     }
337c80476e4SDavid E. O'Brien }
338c80476e4SDavid E. O'Brien 
339c80476e4SDavid E. O'Brien /*
340c80476e4SDavid E. O'Brien  *  Refresh()
341c80476e4SDavid E. O'Brien  *	draws the new virtual screen image from the current input
342c80476e4SDavid E. O'Brien  *  	line, then goes line-by-line changing the real image to the new
343c80476e4SDavid E. O'Brien  *	virtual image. The routine to re-draw a line can be replaced
344c80476e4SDavid E. O'Brien  *	easily in hopes of a smarter one being placed there.
345c80476e4SDavid E. O'Brien  */
346b2d5d167SMark Peek #ifndef WINNT_NATIVE
347b2d5d167SMark Peek static
348b2d5d167SMark Peek #endif
349b2d5d167SMark Peek int OldvcV = 0;
350b2d5d167SMark Peek 
351c80476e4SDavid E. O'Brien void
35245e5710bSMark Peek Refresh(void)
353c80476e4SDavid E. O'Brien {
35423338178SMark Peek     int cur_line;
35523338178SMark Peek     Char *cp;
356c80476e4SDavid E. O'Brien     int     cur_h, cur_v = 0, new_vcv;
357c80476e4SDavid E. O'Brien     int     rhdiff;
358c80476e4SDavid E. O'Brien     Char    oldgetting;
359c80476e4SDavid E. O'Brien 
360c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
3619ccc37e3SMark Peek     reprintf("Prompt = :%s:\r\n", short2str(Prompt));
3629ccc37e3SMark Peek     reprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
363c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
364c80476e4SDavid E. O'Brien     oldgetting = GettingInput;
365c80476e4SDavid E. O'Brien     GettingInput = 0;		/* avoid re-entrance via SIGWINCH */
366c80476e4SDavid E. O'Brien 
367c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
368c80476e4SDavid E. O'Brien     vcursor_h = 0;
369c80476e4SDavid E. O'Brien     vcursor_v = 0;
37045e5710bSMark Peek     RefreshPromptpart(RPrompt);
371c80476e4SDavid E. O'Brien     rprompt_h = vcursor_h;
372c80476e4SDavid E. O'Brien     rprompt_v = vcursor_v;
373c80476e4SDavid E. O'Brien 
374c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, draw prompt */
375c80476e4SDavid E. O'Brien     vcursor_h = 0;
376c80476e4SDavid E. O'Brien     vcursor_v = 0;
37745e5710bSMark Peek     RefreshPromptpart(Prompt);
378c80476e4SDavid E. O'Brien     cur_h = -1;			/* set flag in case I'm not set */
379c80476e4SDavid E. O'Brien 
380c80476e4SDavid E. O'Brien     /* draw the current input buffer */
38123338178SMark Peek     for (cp = InputBuf; (cp < LastChar); ) {
38223338178SMark Peek 	if (cp >= Cursor && cur_h == -1) {
383c80476e4SDavid E. O'Brien 	    cur_h = vcursor_h;	/* save for later */
384c80476e4SDavid E. O'Brien 	    cur_v = vcursor_v;
38523338178SMark Peek 	    Cursor = cp;
386c80476e4SDavid E. O'Brien 	}
387*19d2e3deSDmitry Chagin 	cp += Draw(cp, cp == InputBuf, 0);
388c80476e4SDavid E. O'Brien     }
389c80476e4SDavid E. O'Brien 
390c80476e4SDavid E. O'Brien     if (cur_h == -1) {		/* if I haven't been set yet, I'm at the end */
391c80476e4SDavid E. O'Brien 	cur_h = vcursor_h;
392c80476e4SDavid E. O'Brien 	cur_v = vcursor_v;
393c80476e4SDavid E. O'Brien     }
394c80476e4SDavid E. O'Brien 
395c80476e4SDavid E. O'Brien     rhdiff = TermH - vcursor_h - rprompt_h;
396c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
397c80476e4SDavid E. O'Brien 			/*
398c80476e4SDavid E. O'Brien 			 * have a right-hand side prompt that will fit on
399c80476e4SDavid E. O'Brien 			 * the end of the first line with at least one
400c80476e4SDavid E. O'Brien 			 * character gap to the input buffer.
401c80476e4SDavid E. O'Brien 			 */
402c80476e4SDavid E. O'Brien 	while (--rhdiff > 0)		/* pad out with spaces */
40323338178SMark Peek 	    Vdraw(' ', 1);
40445e5710bSMark Peek 	RefreshPromptpart(RPrompt);
405c80476e4SDavid E. O'Brien     }
406c80476e4SDavid E. O'Brien     else {
407c80476e4SDavid E. O'Brien 	rprompt_h = 0;			/* flag "not using rprompt" */
408c80476e4SDavid E. O'Brien 	rprompt_v = 0;
409c80476e4SDavid E. O'Brien     }
410c80476e4SDavid E. O'Brien 
411c80476e4SDavid E. O'Brien     new_vcv = vcursor_v;	/* must be done BEFORE the NUL is written */
41223338178SMark Peek     Vdraw('\0', 1);		/* put NUL on end */
413c80476e4SDavid E. O'Brien 
41423338178SMark Peek #if defined (DEBUG_REFRESH)
4159ccc37e3SMark Peek     reprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
416c80476e4SDavid E. O'Brien 	    TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
417c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
418c80476e4SDavid E. O'Brien 
419c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
4209ccc37e3SMark Peek     reprintf("updating %d lines.\r\n", new_vcv);
421c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
422c80476e4SDavid E. O'Brien     for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
423c80476e4SDavid E. O'Brien 	/* NOTE THAT update_line MAY CHANGE Display[cur_line] */
424c80476e4SDavid E. O'Brien 	update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
4253b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
426c80476e4SDavid E. O'Brien 	flush();
4273b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
428c80476e4SDavid E. O'Brien 
429c80476e4SDavid E. O'Brien 	/*
430c80476e4SDavid E. O'Brien 	 * Copy the new line to be the current one, and pad out with spaces
431c80476e4SDavid E. O'Brien 	 * to the full width of the terminal so that if we try moving the
432c80476e4SDavid E. O'Brien 	 * cursor by writing the character that is at the end of the
433c80476e4SDavid E. O'Brien 	 * screen line, it won't be a NUL or some old leftover stuff.
434c80476e4SDavid E. O'Brien 	 */
435c80476e4SDavid E. O'Brien 	cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
436c80476e4SDavid E. O'Brien     }
437c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4389ccc37e3SMark Peek     reprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
439c80476e4SDavid E. O'Brien 	    vcursor_v, OldvcV, cur_line);
440c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
441c80476e4SDavid E. O'Brien     if (OldvcV > new_vcv) {
442c80476e4SDavid E. O'Brien 	for (; cur_line <= OldvcV; cur_line++) {
443c80476e4SDavid E. O'Brien 	    update_line(Display[cur_line], STRNULL, cur_line);
444c80476e4SDavid E. O'Brien 	    *Display[cur_line] = '\0';
445c80476e4SDavid E. O'Brien 	}
446c80476e4SDavid E. O'Brien     }
447c80476e4SDavid E. O'Brien     OldvcV = new_vcv;		/* set for next time */
448c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4499ccc37e3SMark Peek     reprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
450c80476e4SDavid E. O'Brien 	    CursorH, CursorV, cur_h, cur_v);
451c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
4523b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
453c80476e4SDavid E. O'Brien     flush();
4543b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
455c80476e4SDavid E. O'Brien     MoveToLine(cur_v);		/* go to where the cursor is */
456c80476e4SDavid E. O'Brien     MoveToChar(cur_h);
457c80476e4SDavid E. O'Brien     SetAttributes(0);		/* Clear all attributes */
458c80476e4SDavid E. O'Brien     flush();			/* send the output... */
459c80476e4SDavid E. O'Brien     GettingInput = oldgetting;	/* reset to old value */
460c80476e4SDavid E. O'Brien }
461c80476e4SDavid E. O'Brien 
462c80476e4SDavid E. O'Brien #ifdef notdef
46345e5710bSMark Peek GotoBottom(void)
464c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
465c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
466c80476e4SDavid E. O'Brien }
467c80476e4SDavid E. O'Brien 
468c80476e4SDavid E. O'Brien #endif
469c80476e4SDavid E. O'Brien 
470c80476e4SDavid E. O'Brien void
47145e5710bSMark Peek PastBottom(void)
472c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
473c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
474c80476e4SDavid E. O'Brien     (void) putraw('\r');
475c80476e4SDavid E. O'Brien     (void) putraw('\n');
476c80476e4SDavid E. O'Brien     ClearDisp();
477c80476e4SDavid E. O'Brien     flush();
478c80476e4SDavid E. O'Brien }
479c80476e4SDavid E. O'Brien 
480c80476e4SDavid E. O'Brien 
481c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat,
482c80476e4SDavid E. O'Brien    maximum length of d is dlen */
483c80476e4SDavid E. O'Brien static void
48445e5710bSMark Peek str_insert(Char *d, int dat, int dlen, Char *s, int num)
485c80476e4SDavid E. O'Brien {
48623338178SMark Peek     Char *a, *b;
487c80476e4SDavid E. O'Brien 
488c80476e4SDavid E. O'Brien     if (num <= 0)
489c80476e4SDavid E. O'Brien 	return;
490c80476e4SDavid E. O'Brien     if (num > dlen - dat)
491c80476e4SDavid E. O'Brien 	num = dlen - dat;
492c80476e4SDavid E. O'Brien 
493c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4949ccc37e3SMark Peek     reprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
495c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
4969ccc37e3SMark Peek     reprintf("s == \"%s\"n", short2str(s));
497c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
498c80476e4SDavid E. O'Brien 
499c80476e4SDavid E. O'Brien     /* open up the space for num chars */
500c80476e4SDavid E. O'Brien     if (num > 0) {
501c80476e4SDavid E. O'Brien 	b = d + dlen - 1;
502c80476e4SDavid E. O'Brien 	a = b - num;
503c80476e4SDavid E. O'Brien 	while (a >= &d[dat])
504c80476e4SDavid E. O'Brien 	    *b-- = *a--;
505c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
506c80476e4SDavid E. O'Brien     }
507c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5089ccc37e3SMark Peek     reprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
509c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
5109ccc37e3SMark Peek     reprintf("s == \"%s\"n", short2str(s));
511c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
512c80476e4SDavid E. O'Brien 
513c80476e4SDavid E. O'Brien     /* copy the characters */
514c80476e4SDavid E. O'Brien     for (a = d + dat; (a < d + dlen) && (num > 0); num--)
515c80476e4SDavid E. O'Brien 	*a++ = *s++;
516c80476e4SDavid E. O'Brien 
517c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5189ccc37e3SMark Peek     reprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
519c80476e4SDavid E. O'Brien 	    num, dat, dlen, d, short2str(s));
5209ccc37e3SMark Peek     reprintf("s == \"%s\"n", short2str(s));
521c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
522c80476e4SDavid E. O'Brien }
523c80476e4SDavid E. O'Brien 
524c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */
525c80476e4SDavid E. O'Brien static void
52645e5710bSMark Peek str_delete(Char *d, int dat, int dlen, int num)
527c80476e4SDavid E. O'Brien {
52823338178SMark Peek     Char *a, *b;
529c80476e4SDavid E. O'Brien 
530c80476e4SDavid E. O'Brien     if (num <= 0)
531c80476e4SDavid E. O'Brien 	return;
532c80476e4SDavid E. O'Brien     if (dat + num >= dlen) {
533c80476e4SDavid E. O'Brien 	d[dat] = '\0';
534c80476e4SDavid E. O'Brien 	return;
535c80476e4SDavid E. O'Brien     }
536c80476e4SDavid E. O'Brien 
537c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5389ccc37e3SMark Peek     reprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
539c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
540c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
541c80476e4SDavid E. O'Brien 
542c80476e4SDavid E. O'Brien     /* open up the space for num chars */
543c80476e4SDavid E. O'Brien     if (num > 0) {
544c80476e4SDavid E. O'Brien 	b = d + dat;
545c80476e4SDavid E. O'Brien 	a = b + num;
546c80476e4SDavid E. O'Brien 	while (a < &d[dlen])
547c80476e4SDavid E. O'Brien 	    *b++ = *a++;
548c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
549c80476e4SDavid E. O'Brien     }
550c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5519ccc37e3SMark Peek     reprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
552c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
553c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
554c80476e4SDavid E. O'Brien }
555c80476e4SDavid E. O'Brien 
556c80476e4SDavid E. O'Brien static void
55745e5710bSMark Peek str_cp(Char *a, Char *b, int n)
558c80476e4SDavid E. O'Brien {
559c80476e4SDavid E. O'Brien     while (n-- && *b)
560c80476e4SDavid E. O'Brien 	*a++ = *b++;
561c80476e4SDavid E. O'Brien }
562c80476e4SDavid E. O'Brien 
563c80476e4SDavid E. O'Brien 
564c80476e4SDavid E. O'Brien /* ****************************************************************
565c80476e4SDavid E. O'Brien     update_line() is based on finding the middle difference of each line
566c80476e4SDavid E. O'Brien     on the screen; vis:
567c80476e4SDavid E. O'Brien 
568c80476e4SDavid E. O'Brien 			     /old first difference
569c80476e4SDavid E. O'Brien 	/beginning of line   |              /old last same       /old EOL
570c80476e4SDavid E. O'Brien 	v		     v              v                    v
571c80476e4SDavid E. O'Brien old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
572c80476e4SDavid E. O'Brien new:	eddie> Oh, my little buggy says to me, as lurgid as
573c80476e4SDavid E. O'Brien 	^		     ^        ^			   ^
574c80476e4SDavid E. O'Brien 	\beginning of line   |        \new last same	   \new end of line
575c80476e4SDavid E. O'Brien 			     \new first difference
576c80476e4SDavid E. O'Brien 
577c80476e4SDavid E. O'Brien     all are character pointers for the sake of speed.  Special cases for
578c80476e4SDavid E. O'Brien     no differences, as well as for end of line additions must be handled.
579c80476e4SDavid E. O'Brien **************************************************************** */
580c80476e4SDavid E. O'Brien 
581c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it".  This should be about
582c80476e4SDavid E. O'Brien  * half the "cost" of going into insert mode, inserting a character, and
583c80476e4SDavid E. O'Brien  * going back out.  This should really be calculated from the termcap
584c80476e4SDavid E. O'Brien  * data...  For the moment, a good number for ANSI terminals.
585c80476e4SDavid E. O'Brien  */
586c80476e4SDavid E. O'Brien #define MIN_END_KEEP	4
587c80476e4SDavid E. O'Brien 
588c80476e4SDavid E. O'Brien static void			/* could be changed to make it smarter */
58945e5710bSMark Peek update_line(Char *old, Char *new, int cur_line)
590c80476e4SDavid E. O'Brien {
59123338178SMark Peek     Char *o, *n, *p, c;
592c80476e4SDavid E. O'Brien     Char  *ofd, *ols, *oe, *nfd, *nls, *ne;
593c80476e4SDavid E. O'Brien     Char  *osb, *ose, *nsb, *nse;
594c80476e4SDavid E. O'Brien     int     fx, sx;
595c80476e4SDavid E. O'Brien 
596c80476e4SDavid E. O'Brien     /*
59723338178SMark Peek      * find first diff (won't be CHAR_DBWIDTH in either line)
598c80476e4SDavid E. O'Brien      */
599c80476e4SDavid E. O'Brien     for (o = old, n = new; *o && (*o == *n); o++, n++)
600c80476e4SDavid E. O'Brien 	continue;
601c80476e4SDavid E. O'Brien     ofd = o;
602c80476e4SDavid E. O'Brien     nfd = n;
603c80476e4SDavid E. O'Brien 
604c80476e4SDavid E. O'Brien     /*
605c80476e4SDavid E. O'Brien      * Find the end of both old and new
606c80476e4SDavid E. O'Brien      */
60745e5710bSMark Peek     o = Strend(o);
60845e5710bSMark Peek 
609c80476e4SDavid E. O'Brien     /*
610c80476e4SDavid E. O'Brien      * Remove any trailing blanks off of the end, being careful not to
611c80476e4SDavid E. O'Brien      * back up past the beginning.
612c80476e4SDavid E. O'Brien      */
61345e5710bSMark Peek     if (!(adrof(STRhighlight) && MarkIsSet)) {
614c80476e4SDavid E. O'Brien     while (ofd < o) {
615c80476e4SDavid E. O'Brien 	if (o[-1] != ' ')
616c80476e4SDavid E. O'Brien 	    break;
617c80476e4SDavid E. O'Brien 	o--;
618c80476e4SDavid E. O'Brien     }
61945e5710bSMark Peek     }
620c80476e4SDavid E. O'Brien     oe = o;
621c80476e4SDavid E. O'Brien     *oe = (Char) 0;
622c80476e4SDavid E. O'Brien 
62345e5710bSMark Peek     n = Strend(n);
624c80476e4SDavid E. O'Brien 
625c80476e4SDavid E. O'Brien     /* remove blanks from end of new */
62645e5710bSMark Peek     if (!(adrof(STRhighlight) && MarkIsSet)) {
627c80476e4SDavid E. O'Brien     while (nfd < n) {
628c80476e4SDavid E. O'Brien 	if (n[-1] != ' ')
629c80476e4SDavid E. O'Brien 	    break;
630c80476e4SDavid E. O'Brien 	n--;
631c80476e4SDavid E. O'Brien     }
63245e5710bSMark Peek     }
633c80476e4SDavid E. O'Brien     ne = n;
634c80476e4SDavid E. O'Brien     *ne = (Char) 0;
635c80476e4SDavid E. O'Brien 
636c80476e4SDavid E. O'Brien     /*
637c80476e4SDavid E. O'Brien      * if no diff, continue to next line of redraw
638c80476e4SDavid E. O'Brien      */
639c80476e4SDavid E. O'Brien     if (*ofd == '\0' && *nfd == '\0') {
640c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
6419ccc37e3SMark Peek 	reprintf("no difference.\r\n");
642c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
643c80476e4SDavid E. O'Brien 	return;
644c80476e4SDavid E. O'Brien     }
645c80476e4SDavid E. O'Brien 
646c80476e4SDavid E. O'Brien     /*
647c80476e4SDavid E. O'Brien      * find last same pointer
648c80476e4SDavid E. O'Brien      */
649c80476e4SDavid E. O'Brien     while ((o > ofd) && (n > nfd) && (*--o == *--n))
650c80476e4SDavid E. O'Brien 	continue;
65123338178SMark Peek     if (*o != *n) {
65223338178SMark Peek 	o++;
65323338178SMark Peek 	n++;
65423338178SMark Peek     }
65523338178SMark Peek     while (*o == CHAR_DBWIDTH) {
65623338178SMark Peek 	o++;
65723338178SMark Peek 	n++;
65823338178SMark Peek     }
65923338178SMark Peek     ols = o;
66023338178SMark Peek     nls = n;
661c80476e4SDavid E. O'Brien 
662c80476e4SDavid E. O'Brien     /*
663c80476e4SDavid E. O'Brien      * find same begining and same end
664c80476e4SDavid E. O'Brien      */
665c80476e4SDavid E. O'Brien     osb = ols;
666c80476e4SDavid E. O'Brien     nsb = nls;
667c80476e4SDavid E. O'Brien     ose = ols;
668c80476e4SDavid E. O'Brien     nse = nls;
669c80476e4SDavid E. O'Brien 
670c80476e4SDavid E. O'Brien     /*
671c80476e4SDavid E. O'Brien      * case 1: insert: scan from nfd to nls looking for *ofd
672c80476e4SDavid E. O'Brien      */
673c80476e4SDavid E. O'Brien     if (*ofd) {
674c80476e4SDavid E. O'Brien 	for (c = *ofd, n = nfd; n < nls; n++) {
675c80476e4SDavid E. O'Brien 	    if (c == *n) {
676c80476e4SDavid E. O'Brien 		for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
677c80476e4SDavid E. O'Brien 		    continue;
678c80476e4SDavid E. O'Brien 		/*
679c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
680c80476e4SDavid E. O'Brien 		 * take it
681c80476e4SDavid E. O'Brien 		 */
682c80476e4SDavid E. O'Brien 		if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
683c80476e4SDavid E. O'Brien 		    nsb = n;
684c80476e4SDavid E. O'Brien 		    nse = p;
685c80476e4SDavid E. O'Brien 		    osb = ofd;
686c80476e4SDavid E. O'Brien 		    ose = o;
687c80476e4SDavid E. O'Brien 		}
688c80476e4SDavid E. O'Brien 	    }
689c80476e4SDavid E. O'Brien 	}
690c80476e4SDavid E. O'Brien     }
691c80476e4SDavid E. O'Brien 
692c80476e4SDavid E. O'Brien     /*
693c80476e4SDavid E. O'Brien      * case 2: delete: scan from ofd to ols looking for *nfd
694c80476e4SDavid E. O'Brien      */
695c80476e4SDavid E. O'Brien     if (*nfd) {
696c80476e4SDavid E. O'Brien 	for (c = *nfd, o = ofd; o < ols; o++) {
697c80476e4SDavid E. O'Brien 	    if (c == *o) {
698c80476e4SDavid E. O'Brien 		for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
699c80476e4SDavid E. O'Brien 		    continue;
700c80476e4SDavid E. O'Brien 		/*
701c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
702c80476e4SDavid E. O'Brien 		 * take it
703c80476e4SDavid E. O'Brien 		 */
704c80476e4SDavid E. O'Brien 		if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
705c80476e4SDavid E. O'Brien 		    nsb = nfd;
706c80476e4SDavid E. O'Brien 		    nse = n;
707c80476e4SDavid E. O'Brien 		    osb = o;
708c80476e4SDavid E. O'Brien 		    ose = p;
709c80476e4SDavid E. O'Brien 		}
710c80476e4SDavid E. O'Brien 	    }
711c80476e4SDavid E. O'Brien 	}
712c80476e4SDavid E. O'Brien     }
713c80476e4SDavid E. O'Brien #ifdef notdef
714c80476e4SDavid E. O'Brien     /*
715c80476e4SDavid E. O'Brien      * If `last same' is before `same end' re-adjust
716c80476e4SDavid E. O'Brien      */
717c80476e4SDavid E. O'Brien     if (ols < ose)
718c80476e4SDavid E. O'Brien 	ols = ose;
719c80476e4SDavid E. O'Brien     if (nls < nse)
720c80476e4SDavid E. O'Brien 	nls = nse;
721c80476e4SDavid E. O'Brien #endif
722c80476e4SDavid E. O'Brien 
723c80476e4SDavid E. O'Brien     /*
724c80476e4SDavid E. O'Brien      * Pragmatics I: If old trailing whitespace or not enough characters to
725c80476e4SDavid E. O'Brien      * save to be worth it, then don't save the last same info.
726c80476e4SDavid E. O'Brien      */
727c80476e4SDavid E. O'Brien     if ((oe - ols) < MIN_END_KEEP) {
728c80476e4SDavid E. O'Brien 	ols = oe;
729c80476e4SDavid E. O'Brien 	nls = ne;
730c80476e4SDavid E. O'Brien     }
731c80476e4SDavid E. O'Brien 
732c80476e4SDavid E. O'Brien     /*
733c80476e4SDavid E. O'Brien      * Pragmatics II: if the terminal isn't smart enough, make the data dumber
734c80476e4SDavid E. O'Brien      * so the smart update doesn't try anything fancy
735c80476e4SDavid E. O'Brien      */
736c80476e4SDavid E. O'Brien 
737c80476e4SDavid E. O'Brien     /*
738c80476e4SDavid E. O'Brien      * fx is the number of characters we need to insert/delete: in the
739c80476e4SDavid E. O'Brien      * beginning to bring the two same begins together
740c80476e4SDavid E. O'Brien      */
741c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
742c80476e4SDavid E. O'Brien     /*
743c80476e4SDavid E. O'Brien      * sx is the number of characters we need to insert/delete: in the end to
744c80476e4SDavid E. O'Brien      * bring the two same last parts together
745c80476e4SDavid E. O'Brien      */
746c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
747c80476e4SDavid E. O'Brien 
748c80476e4SDavid E. O'Brien     if (!T_CanIns) {
749c80476e4SDavid E. O'Brien 	if (fx > 0) {
750c80476e4SDavid E. O'Brien 	    osb = ols;
751c80476e4SDavid E. O'Brien 	    ose = ols;
752c80476e4SDavid E. O'Brien 	    nsb = nls;
753c80476e4SDavid E. O'Brien 	    nse = nls;
754c80476e4SDavid E. O'Brien 	}
755c80476e4SDavid E. O'Brien 	if (sx > 0) {
756c80476e4SDavid E. O'Brien 	    ols = oe;
757c80476e4SDavid E. O'Brien 	    nls = ne;
758c80476e4SDavid E. O'Brien 	}
759c80476e4SDavid E. O'Brien 	if ((ols - ofd) < (nls - nfd)) {
760c80476e4SDavid E. O'Brien 	    ols = oe;
761c80476e4SDavid E. O'Brien 	    nls = ne;
762c80476e4SDavid E. O'Brien 	}
763c80476e4SDavid E. O'Brien     }
764c80476e4SDavid E. O'Brien     if (!T_CanDel) {
765c80476e4SDavid E. O'Brien 	if (fx < 0) {
766c80476e4SDavid E. O'Brien 	    osb = ols;
767c80476e4SDavid E. O'Brien 	    ose = ols;
768c80476e4SDavid E. O'Brien 	    nsb = nls;
769c80476e4SDavid E. O'Brien 	    nse = nls;
770c80476e4SDavid E. O'Brien 	}
771c80476e4SDavid E. O'Brien 	if (sx < 0) {
772c80476e4SDavid E. O'Brien 	    ols = oe;
773c80476e4SDavid E. O'Brien 	    nls = ne;
774c80476e4SDavid E. O'Brien 	}
775c80476e4SDavid E. O'Brien 	if ((ols - ofd) > (nls - nfd)) {
776c80476e4SDavid E. O'Brien 	    ols = oe;
777c80476e4SDavid E. O'Brien 	    nls = ne;
778c80476e4SDavid E. O'Brien 	}
779c80476e4SDavid E. O'Brien     }
780c80476e4SDavid E. O'Brien 
781c80476e4SDavid E. O'Brien     /*
782c80476e4SDavid E. O'Brien      * Pragmatics III: make sure the middle shifted pointers are correct if
783c80476e4SDavid E. O'Brien      * they don't point to anything (we may have moved ols or nls).
784c80476e4SDavid E. O'Brien      */
785c80476e4SDavid E. O'Brien     /* if the change isn't worth it, don't bother */
786c80476e4SDavid E. O'Brien     /* was: if (osb == ose) */
787c80476e4SDavid E. O'Brien     if ((ose - osb) < MIN_END_KEEP) {
788c80476e4SDavid E. O'Brien 	osb = ols;
789c80476e4SDavid E. O'Brien 	ose = ols;
790c80476e4SDavid E. O'Brien 	nsb = nls;
791c80476e4SDavid E. O'Brien 	nse = nls;
792c80476e4SDavid E. O'Brien     }
793c80476e4SDavid E. O'Brien 
794c80476e4SDavid E. O'Brien     /*
795c80476e4SDavid E. O'Brien      * Now that we are done with pragmatics we recompute fx, sx
796c80476e4SDavid E. O'Brien      */
797c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
798c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
799c80476e4SDavid E. O'Brien 
800c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8019ccc37e3SMark Peek     reprintf("\n");
8029ccc37e3SMark Peek     reprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
803c80476e4SDavid E. O'Brien 	    ofd - old, osb - old, ose - old, ols - old, oe - old);
8049ccc37e3SMark Peek     reprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
805c80476e4SDavid E. O'Brien 	    nfd - new, nsb - new, nse - new, nls - new, ne - new);
8069ccc37e3SMark Peek     reprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
8079ccc37e3SMark Peek     reprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
808c80476e4SDavid E. O'Brien     dprintstr("old- oe", old, oe);
809c80476e4SDavid E. O'Brien     dprintstr("new- ne", new, ne);
810c80476e4SDavid E. O'Brien     dprintstr("old-ofd", old, ofd);
811c80476e4SDavid E. O'Brien     dprintstr("new-nfd", new, nfd);
812c80476e4SDavid E. O'Brien     dprintstr("ofd-osb", ofd, osb);
813c80476e4SDavid E. O'Brien     dprintstr("nfd-nsb", nfd, nsb);
814c80476e4SDavid E. O'Brien     dprintstr("osb-ose", osb, ose);
815c80476e4SDavid E. O'Brien     dprintstr("nsb-nse", nsb, nse);
816c80476e4SDavid E. O'Brien     dprintstr("ose-ols", ose, ols);
817c80476e4SDavid E. O'Brien     dprintstr("nse-nls", nse, nls);
818c80476e4SDavid E. O'Brien     dprintstr("ols- oe", ols, oe);
819c80476e4SDavid E. O'Brien     dprintstr("nls- ne", nls, ne);
820c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
821c80476e4SDavid E. O'Brien 
822c80476e4SDavid E. O'Brien     /*
823c80476e4SDavid E. O'Brien      * CursorV to this line cur_line MUST be in this routine so that if we
824c80476e4SDavid E. O'Brien      * don't have to change the line, we don't move to it. CursorH to first
825c80476e4SDavid E. O'Brien      * diff char
826c80476e4SDavid E. O'Brien      */
827c80476e4SDavid E. O'Brien     MoveToLine(cur_line);
828c80476e4SDavid E. O'Brien 
829c80476e4SDavid E. O'Brien     /*
830c80476e4SDavid E. O'Brien      * at this point we have something like this:
831c80476e4SDavid E. O'Brien      *
832c80476e4SDavid E. O'Brien      * /old                  /ofd    /osb               /ose    /ols     /oe
833c80476e4SDavid E. O'Brien      * v.....................v       v..................v       v........v
834c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
835c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
836c80476e4SDavid E. O'Brien      * ^.....................^     ^..................^       ^........^
837c80476e4SDavid E. O'Brien      * \new                  \nfd  \nsb               \nse     \nls    \ne
838c80476e4SDavid E. O'Brien      *
839c80476e4SDavid E. O'Brien      * fx is the difference in length between the the chars between nfd and
840c80476e4SDavid E. O'Brien      * nsb, and the chars between ofd and osb, and is thus the number of
841c80476e4SDavid E. O'Brien      * characters to delete if < 0 (new is shorter than old, as above),
842c80476e4SDavid E. O'Brien      * or insert (new is longer than short).
843c80476e4SDavid E. O'Brien      *
844c80476e4SDavid E. O'Brien      * sx is the same for the second differences.
845c80476e4SDavid E. O'Brien      */
846c80476e4SDavid E. O'Brien 
847c80476e4SDavid E. O'Brien     /*
848c80476e4SDavid E. O'Brien      * if we have a net insert on the first difference, AND inserting the net
849c80476e4SDavid E. O'Brien      * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
850c80476e4SDavid E. O'Brien      * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
851c80476e4SDavid E. O'Brien      * (TermH - 1) else we do the deletes first so that we keep everything we
852c80476e4SDavid E. O'Brien      * need to.
853c80476e4SDavid E. O'Brien      */
854c80476e4SDavid E. O'Brien 
855c80476e4SDavid E. O'Brien     /*
856c80476e4SDavid E. O'Brien      * if the last same is the same like the end, there is no last same part,
857c80476e4SDavid E. O'Brien      * otherwise we want to keep the last same part set p to the last useful
858c80476e4SDavid E. O'Brien      * old character
859c80476e4SDavid E. O'Brien      */
860c80476e4SDavid E. O'Brien     p = (ols != oe) ? oe : ose;
861c80476e4SDavid E. O'Brien 
862c80476e4SDavid E. O'Brien     /*
863c80476e4SDavid E. O'Brien      * if (There is a diffence in the beginning) && (we need to insert
864c80476e4SDavid E. O'Brien      * characters) && (the number of characters to insert is less than the term
865c80476e4SDavid E. O'Brien      * width) We need to do an insert! else if (we need to delete characters)
866c80476e4SDavid E. O'Brien      * We need to delete characters! else No insert or delete
867c80476e4SDavid E. O'Brien      */
868c80476e4SDavid E. O'Brien     if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
869c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8709ccc37e3SMark Peek 	reprintf("first diff insert at %d...\r\n", nfd - new);
871c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
872c80476e4SDavid E. O'Brien 	/*
873c80476e4SDavid E. O'Brien 	 * Move to the first char to insert, where the first diff is.
874c80476e4SDavid E. O'Brien 	 */
875c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
876c80476e4SDavid E. O'Brien 	/*
877c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at end
878c80476e4SDavid E. O'Brien 	 */
879c80476e4SDavid E. O'Brien 	if (nsb != ne) {
880c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8819ccc37e3SMark Peek 	    reprintf("with stuff to keep at end\r\n");
882c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
883c80476e4SDavid E. O'Brien 	    /*
884c80476e4SDavid E. O'Brien 	     * insert fx chars of new starting at nfd
885c80476e4SDavid E. O'Brien 	     */
886c80476e4SDavid E. O'Brien 	    if (fx > 0) {
887c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
888c80476e4SDavid E. O'Brien 		if (!T_CanIns)
8899ccc37e3SMark Peek 		    reprintf("   ERROR: cannot insert in early first diff\n");
890c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
891c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
892c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
893c80476e4SDavid E. O'Brien 	    }
894c80476e4SDavid E. O'Brien 	    /*
895c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
896c80476e4SDavid E. O'Brien 	     */
897c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
898c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
899c80476e4SDavid E. O'Brien 	}
900c80476e4SDavid E. O'Brien 	else {
901c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9029ccc37e3SMark Peek 	    reprintf("without anything to save\r\n");
903c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
904c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
905c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
906c80476e4SDavid E. O'Brien 	    /*
907c80476e4SDavid E. O'Brien 	     * Done
908c80476e4SDavid E. O'Brien 	     */
909c80476e4SDavid E. O'Brien 	    return;
910c80476e4SDavid E. O'Brien 	}
911c80476e4SDavid E. O'Brien     }
912c80476e4SDavid E. O'Brien     else if (fx < 0) {
913c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9149ccc37e3SMark Peek 	reprintf("first diff delete at %d...\r\n", ofd - old);
915c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
916c80476e4SDavid E. O'Brien 	/*
917c80476e4SDavid E. O'Brien 	 * move to the first char to delete where the first diff is
918c80476e4SDavid E. O'Brien 	 */
919c80476e4SDavid E. O'Brien 	MoveToChar(ofd - old);
920c80476e4SDavid E. O'Brien 	/*
921c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
922c80476e4SDavid E. O'Brien 	 */
923c80476e4SDavid E. O'Brien 	if (osb != oe) {
924c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9259ccc37e3SMark Peek 	    reprintf("with stuff to save at end\r\n");
926c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
927c80476e4SDavid E. O'Brien 	    /*
928c80476e4SDavid E. O'Brien 	     * fx is less than zero *always* here but we check for code
929c80476e4SDavid E. O'Brien 	     * symmetry
930c80476e4SDavid E. O'Brien 	     */
931c80476e4SDavid E. O'Brien 	    if (fx < 0) {
932c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
933c80476e4SDavid E. O'Brien 		if (!T_CanDel)
9349ccc37e3SMark Peek 		    reprintf("   ERROR: cannot delete in first diff\n");
935c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
936c80476e4SDavid E. O'Brien 		DeleteChars(-fx);
937c80476e4SDavid E. O'Brien 		str_delete(old, (int) (ofd - old), TermH, -fx);
938c80476e4SDavid E. O'Brien 	    }
939c80476e4SDavid E. O'Brien 	    /*
940c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
941c80476e4SDavid E. O'Brien 	     */
942c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
943c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
944c80476e4SDavid E. O'Brien 
945c80476e4SDavid E. O'Brien 	}
946c80476e4SDavid E. O'Brien 	else {
947c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9489ccc37e3SMark Peek 	    reprintf("but with nothing left to save\r\n");
949c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
950c80476e4SDavid E. O'Brien 	    /*
951c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
952c80476e4SDavid E. O'Brien 	     */
953c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
954c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
9559ccc37e3SMark Peek 	    reprintf("cleareol %d\n", (oe - old) - (ne - new));
956c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
9573b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
958c80476e4SDavid E. O'Brien 	    ClearEOL((oe - old) - (ne - new));
959c80476e4SDavid E. O'Brien #else
960c80476e4SDavid E. O'Brien 	    /*
961c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
962c80476e4SDavid E. O'Brien 	     */
963c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
9643b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
965c80476e4SDavid E. O'Brien 	    /*
966c80476e4SDavid E. O'Brien 	     * Done
967c80476e4SDavid E. O'Brien 	     */
968c80476e4SDavid E. O'Brien 	    return;
969c80476e4SDavid E. O'Brien 	}
970c80476e4SDavid E. O'Brien     }
971c80476e4SDavid E. O'Brien     else
972c80476e4SDavid E. O'Brien 	fx = 0;
973c80476e4SDavid E. O'Brien 
974c80476e4SDavid E. O'Brien     if (sx < 0) {
975c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9769ccc37e3SMark Peek 	reprintf("second diff delete at %d...\r\n", (ose - old) + fx);
977c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
978c80476e4SDavid E. O'Brien 	/*
979c80476e4SDavid E. O'Brien 	 * Check if we have stuff to delete
980c80476e4SDavid E. O'Brien 	 */
981c80476e4SDavid E. O'Brien 	/*
982c80476e4SDavid E. O'Brien 	 * fx is the number of characters inserted (+) or deleted (-)
983c80476e4SDavid E. O'Brien 	 */
984c80476e4SDavid E. O'Brien 
985c80476e4SDavid E. O'Brien 	MoveToChar((ose - old) + fx);
986c80476e4SDavid E. O'Brien 	/*
987c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
988c80476e4SDavid E. O'Brien 	 */
989c80476e4SDavid E. O'Brien 	if (ols != oe) {
990c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9919ccc37e3SMark Peek 	    reprintf("with stuff to save at end\r\n");
992c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
993c80476e4SDavid E. O'Brien 	    /*
994c80476e4SDavid E. O'Brien 	     * Again a duplicate test.
995c80476e4SDavid E. O'Brien 	     */
996c80476e4SDavid E. O'Brien 	    if (sx < 0) {
997c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
998c80476e4SDavid E. O'Brien 		if (!T_CanDel)
9999ccc37e3SMark Peek 		    reprintf("   ERROR: cannot delete in second diff\n");
1000c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
1001c80476e4SDavid E. O'Brien 		DeleteChars(-sx);
1002c80476e4SDavid E. O'Brien 	    }
1003c80476e4SDavid E. O'Brien 
1004c80476e4SDavid E. O'Brien 	    /*
1005c80476e4SDavid E. O'Brien 	     * write (nls-nse) chars of new starting at nse
1006c80476e4SDavid E. O'Brien 	     */
1007c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1008c80476e4SDavid E. O'Brien 	}
1009c80476e4SDavid E. O'Brien 	else {
1010c80476e4SDavid E. O'Brien 	    int olen = (int) (oe - old + fx);
1011c80476e4SDavid E. O'Brien 	    if (olen > TermH)
1012c80476e4SDavid E. O'Brien 		olen = TermH;
1013c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10149ccc37e3SMark Peek 	    reprintf("but with nothing left to save\r\n");
1015c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1016c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1017c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
10189ccc37e3SMark Peek 	    reprintf("cleareol %d\n", olen - (ne - new));
1019c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
10203b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
1021c80476e4SDavid E. O'Brien 	    ClearEOL(olen - (ne - new));
1022c80476e4SDavid E. O'Brien #else
1023c80476e4SDavid E. O'Brien 	    /*
1024c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
1025c80476e4SDavid E. O'Brien 	     */
1026c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
10273b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
1028c80476e4SDavid E. O'Brien 	}
1029c80476e4SDavid E. O'Brien     }
1030c80476e4SDavid E. O'Brien 
1031c80476e4SDavid E. O'Brien     /*
1032c80476e4SDavid E. O'Brien      * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
1033c80476e4SDavid E. O'Brien      */
1034c80476e4SDavid E. O'Brien     if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
1035c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10369ccc37e3SMark Peek 	reprintf("late first diff insert at %d...\r\n", nfd - new);
1037c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1038c80476e4SDavid E. O'Brien 
1039c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
1040c80476e4SDavid E. O'Brien 	/*
1041c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at the end
1042c80476e4SDavid E. O'Brien 	 */
1043c80476e4SDavid E. O'Brien 	if (nsb != ne) {
1044c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10459ccc37e3SMark Peek 	    reprintf("with stuff to keep at end\r\n");
1046c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1047c80476e4SDavid E. O'Brien 	    /*
1048c80476e4SDavid E. O'Brien 	     * We have to recalculate fx here because we set it
1049c80476e4SDavid E. O'Brien 	     * to zero above as a flag saying that we hadn't done
1050c80476e4SDavid E. O'Brien 	     * an early first insert.
1051c80476e4SDavid E. O'Brien 	     */
1052c80476e4SDavid E. O'Brien 	    fx = (int) ((nsb - nfd) - (osb - ofd));
1053c80476e4SDavid E. O'Brien 	    if (fx > 0) {
1054c80476e4SDavid E. O'Brien 		/*
1055c80476e4SDavid E. O'Brien 		 * insert fx chars of new starting at nfd
1056c80476e4SDavid E. O'Brien 		 */
1057c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1058c80476e4SDavid E. O'Brien 		if (!T_CanIns)
10599ccc37e3SMark Peek 		    reprintf("   ERROR: cannot insert in late first diff\n");
1060c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1061c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
1062c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1063c80476e4SDavid E. O'Brien 	    }
1064c80476e4SDavid E. O'Brien 
1065c80476e4SDavid E. O'Brien 	    /*
1066c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1067c80476e4SDavid E. O'Brien 	     */
1068c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
1069c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1070c80476e4SDavid E. O'Brien 	}
1071c80476e4SDavid E. O'Brien 	else {
1072c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10739ccc37e3SMark Peek 	    reprintf("without anything to save\r\n");
1074c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1075c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
1076c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
1077c80476e4SDavid E. O'Brien 	}
1078c80476e4SDavid E. O'Brien     }
1079c80476e4SDavid E. O'Brien 
1080c80476e4SDavid E. O'Brien     /*
1081c80476e4SDavid E. O'Brien      * line is now NEW up to nse
1082c80476e4SDavid E. O'Brien      */
1083c80476e4SDavid E. O'Brien     if (sx >= 0) {
1084c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10859ccc37e3SMark Peek 	reprintf("second diff insert at %d...\r\n", nse - new);
1086c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1087c80476e4SDavid E. O'Brien 	MoveToChar(nse - new);
1088c80476e4SDavid E. O'Brien 	if (ols != oe) {
1089c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10909ccc37e3SMark Peek 	    reprintf("with stuff to keep at end\r\n");
1091c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1092c80476e4SDavid E. O'Brien 	    if (sx > 0) {
1093c80476e4SDavid E. O'Brien 		/* insert sx chars of new starting at nse */
1094c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1095c80476e4SDavid E. O'Brien 		if (!T_CanIns)
10969ccc37e3SMark Peek 		    reprintf("   ERROR: cannot insert in second diff\n");
1097c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1098c80476e4SDavid E. O'Brien 		Insert_write(nse, sx);
1099c80476e4SDavid E. O'Brien 	    }
1100c80476e4SDavid E. O'Brien 
1101c80476e4SDavid E. O'Brien 	    /*
1102c80476e4SDavid E. O'Brien 	     * write (nls-nse) - sx chars of new starting at (nse + sx)
1103c80476e4SDavid E. O'Brien 	     */
1104c80476e4SDavid E. O'Brien 	    so_write(nse + sx, (nls - nse) - sx);
1105c80476e4SDavid E. O'Brien 	}
1106c80476e4SDavid E. O'Brien 	else {
1107c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
11089ccc37e3SMark Peek 	    reprintf("without anything to save\r\n");
1109c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1110c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1111c80476e4SDavid E. O'Brien 
1112c80476e4SDavid E. O'Brien 	    /*
1113c80476e4SDavid E. O'Brien              * No need to do a clear-to-end here because we were doing
1114c80476e4SDavid E. O'Brien 	     * a second insert, so we will have over written all of the
1115c80476e4SDavid E. O'Brien 	     * old string.
1116c80476e4SDavid E. O'Brien 	     */
1117c80476e4SDavid E. O'Brien 	}
1118c80476e4SDavid E. O'Brien     }
1119c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
11209ccc37e3SMark Peek     reprintf("done.\r\n");
1121c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1122c80476e4SDavid E. O'Brien }
1123c80476e4SDavid E. O'Brien 
1124c80476e4SDavid E. O'Brien 
1125c80476e4SDavid E. O'Brien static void
112645e5710bSMark Peek cpy_pad_spaces(Char *dst, Char *src, int width)
1127c80476e4SDavid E. O'Brien {
112823338178SMark Peek     int i;
1129c80476e4SDavid E. O'Brien 
1130c80476e4SDavid E. O'Brien     for (i = 0; i < width; i++) {
1131c80476e4SDavid E. O'Brien 	if (*src == (Char) 0)
1132c80476e4SDavid E. O'Brien 	    break;
1133c80476e4SDavid E. O'Brien 	*dst++ = *src++;
1134c80476e4SDavid E. O'Brien     }
1135c80476e4SDavid E. O'Brien 
1136c80476e4SDavid E. O'Brien     while (i < width) {
1137c80476e4SDavid E. O'Brien 	*dst++ = ' ';
1138c80476e4SDavid E. O'Brien 	i++;
1139c80476e4SDavid E. O'Brien     }
1140c80476e4SDavid E. O'Brien     *dst = (Char) 0;
1141c80476e4SDavid E. O'Brien }
1142c80476e4SDavid E. O'Brien 
1143c80476e4SDavid E. O'Brien void
114445e5710bSMark Peek RefCursor(void)
1145c80476e4SDavid E. O'Brien {				/* only move to new cursor pos */
114623338178SMark Peek     Char *cp;
114745e5710bSMark Peek     int w, h, th, v;
1148c80476e4SDavid E. O'Brien 
1149c80476e4SDavid E. O'Brien     /* first we must find where the cursor is... */
1150c80476e4SDavid E. O'Brien     h = 0;
1151c80476e4SDavid E. O'Brien     v = 0;
1152c80476e4SDavid E. O'Brien     th = TermH;			/* optimize for speed */
1153c80476e4SDavid E. O'Brien 
115445e5710bSMark Peek     for (cp = Prompt; cp != NULL && *cp; ) {	/* do prompt */
115523338178SMark Peek 	if (*cp & LITERAL) {
115623338178SMark Peek 	    cp++;
1157c80476e4SDavid E. O'Brien 	    continue;
115823338178SMark Peek 	}
1159*19d2e3deSDmitry Chagin 	w = NLSClassify(*cp & CHAR, cp == Prompt, 0);
116045e5710bSMark Peek 	cp++;
116123338178SMark Peek 	switch(w) {
116223338178SMark Peek 	    case NLSCLASS_NL:
1163c80476e4SDavid E. O'Brien 		h = 0;
1164c80476e4SDavid E. O'Brien 		v++;
116523338178SMark Peek 		break;
116623338178SMark Peek 	    case NLSCLASS_TAB:
116723338178SMark Peek 		while (++h & 07)
116823338178SMark Peek 		    ;
116923338178SMark Peek 		break;
117023338178SMark Peek 	    case NLSCLASS_CTRL:
117123338178SMark Peek 		h += 2;
117223338178SMark Peek 		break;
117323338178SMark Peek 	    case NLSCLASS_ILLEGAL:
117423338178SMark Peek 		h += 4;
117523338178SMark Peek 		break;
117623338178SMark Peek 	    case NLSCLASS_ILLEGAL2:
117723338178SMark Peek 	    case NLSCLASS_ILLEGAL3:
117823338178SMark Peek 	    case NLSCLASS_ILLEGAL4:
117923338178SMark Peek 		h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
118023338178SMark Peek 		break;
118123338178SMark Peek 	    default:
118223338178SMark Peek 		h += w;
1183c80476e4SDavid E. O'Brien 	}
1184c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
118523338178SMark Peek 	    h -= th;
118623338178SMark Peek 	    v++;
118723338178SMark Peek 	}
118823338178SMark Peek     }
118923338178SMark Peek 
119023338178SMark Peek     for (cp = InputBuf; cp < Cursor;) {	/* do input buffer to Cursor */
1191*19d2e3deSDmitry Chagin 	w = NLSClassify(*cp & CHAR, cp == InputBuf, 0);
119245e5710bSMark Peek 	cp++;
119323338178SMark Peek 	switch(w) {
119423338178SMark Peek 	    case NLSCLASS_NL:
1195c80476e4SDavid E. O'Brien 		h = 0;
1196c80476e4SDavid E. O'Brien 		v++;
119723338178SMark Peek 		break;
119823338178SMark Peek 	    case NLSCLASS_TAB:
119923338178SMark Peek 		while (++h & 07)
120023338178SMark Peek 		    ;
120123338178SMark Peek 		break;
120223338178SMark Peek 	    case NLSCLASS_CTRL:
120323338178SMark Peek 		h += 2;
120423338178SMark Peek 		break;
120523338178SMark Peek 	    case NLSCLASS_ILLEGAL:
120623338178SMark Peek 		h += 4;
120723338178SMark Peek 		break;
120823338178SMark Peek 	    case NLSCLASS_ILLEGAL2:
120923338178SMark Peek 	    case NLSCLASS_ILLEGAL3:
121023338178SMark Peek 	    case NLSCLASS_ILLEGAL4:
121123338178SMark Peek 		h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
121223338178SMark Peek 		break;
121323338178SMark Peek 	    default:
121423338178SMark Peek 		h += w;
1215c80476e4SDavid E. O'Brien 	}
1216c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
121723338178SMark Peek 	    h -= th;
1218c80476e4SDavid E. O'Brien 	    v++;
1219c80476e4SDavid E. O'Brien 	}
1220c80476e4SDavid E. O'Brien     }
1221c80476e4SDavid E. O'Brien 
1222c80476e4SDavid E. O'Brien     /* now go there */
1223c80476e4SDavid E. O'Brien     MoveToLine(v);
1224c80476e4SDavid E. O'Brien     MoveToChar(h);
122545e5710bSMark Peek     if (adrof(STRhighlight) && MarkIsSet) {
122645e5710bSMark Peek 	ClearLines();
122745e5710bSMark Peek 	ClearDisp();
122845e5710bSMark Peek 	Refresh();
122945e5710bSMark Peek     }
1230c80476e4SDavid E. O'Brien     flush();
1231c80476e4SDavid E. O'Brien }
1232c80476e4SDavid E. O'Brien 
1233b2d5d167SMark Peek #ifndef WINTT_NATIVE
1234c80476e4SDavid E. O'Brien static void
123545e5710bSMark Peek PutPlusOne(Char c, int width)
1236c80476e4SDavid E. O'Brien {
123723338178SMark Peek     while (width > 1 && CursorH + width > TermH)
123823338178SMark Peek 	PutPlusOne(' ', 1);
123923338178SMark Peek     if ((c & LITERAL) != 0) {
124023338178SMark Peek 	Char *d;
124123338178SMark Peek 	for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++)
124223338178SMark Peek 	    (void) putwraw(*d);
124323338178SMark Peek     } else {
124423338178SMark Peek 	(void) putwraw(c);
124523338178SMark Peek     }
1246c80476e4SDavid E. O'Brien     Display[CursorV][CursorH++] = (Char) c;
124723338178SMark Peek     while (--width > 0)
124823338178SMark Peek 	Display[CursorV][CursorH++] = CHAR_DBWIDTH;
1249c80476e4SDavid E. O'Brien     if (CursorH >= TermH) {	/* if we must overflow */
1250c80476e4SDavid E. O'Brien 	CursorH = 0;
1251c80476e4SDavid E. O'Brien 	CursorV++;
1252c80476e4SDavid E. O'Brien 	OldvcV++;
1253c80476e4SDavid E. O'Brien 	if (T_Margin & MARGIN_AUTO) {
1254c80476e4SDavid E. O'Brien 	    if (T_Margin & MARGIN_MAGIC) {
1255c80476e4SDavid E. O'Brien 		(void) putraw(' ');
1256c80476e4SDavid E. O'Brien 		(void) putraw('\b');
1257c80476e4SDavid E. O'Brien 	    }
1258c80476e4SDavid E. O'Brien 	}
1259c80476e4SDavid E. O'Brien 	else {
1260c80476e4SDavid E. O'Brien 	    (void) putraw('\r');
1261c80476e4SDavid E. O'Brien 	    (void) putraw('\n');
1262c80476e4SDavid E. O'Brien 	}
1263c80476e4SDavid E. O'Brien     }
1264c80476e4SDavid E. O'Brien }
1265b2d5d167SMark Peek #endif
1266c80476e4SDavid E. O'Brien 
1267c80476e4SDavid E. O'Brien void
126823338178SMark Peek RefPlusOne(int l)
1269c80476e4SDavid E. O'Brien {				/* we added just one char, handle it fast.
1270c80476e4SDavid E. O'Brien 				 * assumes that screen cursor == real cursor */
127145e5710bSMark Peek     Char *cp, c;
127223338178SMark Peek     int w;
1273c80476e4SDavid E. O'Brien 
127423338178SMark Peek     if (Cursor != LastChar) {
1275c80476e4SDavid E. O'Brien 	Refresh();		/* too hard to handle */
1276c80476e4SDavid E. O'Brien 	return;
1277c80476e4SDavid E. O'Brien     }
1278c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1279c80476e4SDavid E. O'Brien 	Refresh();		/* clear out rprompt if less than one char gap*/
1280c80476e4SDavid E. O'Brien 	return;
128123338178SMark Peek     }
128223338178SMark Peek     cp = Cursor - l;
128345e5710bSMark Peek     c = *cp & CHAR;
1284*19d2e3deSDmitry Chagin     w = NLSClassify(c, cp == InputBuf, 0);
128523338178SMark Peek     switch(w) {
128623338178SMark Peek 	case NLSCLASS_CTRL:
128723338178SMark Peek 	    PutPlusOne('^', 1);
128823338178SMark Peek 	    if (c == CTL_ESC('\177')) {
128923338178SMark Peek 		PutPlusOne('?', 1);
129023338178SMark Peek 		break;
129123338178SMark Peek 	    }
12923b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
129323338178SMark Peek 	    /* uncontrolify it; works only for iso8859-1 like sets */
129423338178SMark Peek 	    PutPlusOne((c | 0100), 1);
12953b6eaa7bSAndrey A. Chernov #else
129623338178SMark Peek 	    PutPlusOne(_toebcdic[_toascii[c]|0100], 1);
129723338178SMark Peek #endif
129823338178SMark Peek 	    break;
129923338178SMark Peek 	case NLSCLASS_ILLEGAL:
130023338178SMark Peek 	    PutPlusOne('\\', 1);
130123338178SMark Peek 	    PutPlusOne(((c >> 6) & 7) + '0', 1);
130223338178SMark Peek 	    PutPlusOne(((c >> 3) & 7) + '0', 1);
130323338178SMark Peek 	    PutPlusOne((c & 7) + '0', 1);
130423338178SMark Peek 	    break;
130523338178SMark Peek 	case 1:
130645e5710bSMark Peek 	    if (adrof(STRhighlight) && MarkIsSet)
130745e5710bSMark Peek 		StartHighlight();
130823338178SMark Peek 	    if (l > 1)
130923338178SMark Peek 		PutPlusOne(MakeLiteral(cp, l, 0), 1);
1310c80476e4SDavid E. O'Brien 	    else
131123338178SMark Peek 		PutPlusOne(*cp, 1);
131245e5710bSMark Peek 	    if (adrof(STRhighlight) && MarkIsSet)
131345e5710bSMark Peek 		StopHighlight();
131423338178SMark Peek 	    break;
131523338178SMark Peek 	default:
131623338178SMark Peek 	    Refresh();		/* too hard to handle */
131723338178SMark Peek 	    return;
1318c80476e4SDavid E. O'Brien     }
1319c80476e4SDavid E. O'Brien     flush();
1320c80476e4SDavid E. O'Brien }
1321c80476e4SDavid E. O'Brien 
1322c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */
1323c80476e4SDavid E. O'Brien 
1324c80476e4SDavid E. O'Brien void
132545e5710bSMark Peek ClearDisp(void)
1326c80476e4SDavid E. O'Brien {
132723338178SMark Peek     int i;
1328c80476e4SDavid E. O'Brien 
1329c80476e4SDavid E. O'Brien     CursorV = 0;		/* clear the display buffer */
1330c80476e4SDavid E. O'Brien     CursorH = 0;
1331c80476e4SDavid E. O'Brien     for (i = 0; i < TermV; i++)
1332*19d2e3deSDmitry Chagin 	(void) memset(Display[i], 0, (TermH + 1) * sizeof(Display[0][0]));
1333c80476e4SDavid E. O'Brien     OldvcV = 0;
133423338178SMark Peek     litlen = 0;
1335c80476e4SDavid E. O'Brien }
1336c80476e4SDavid E. O'Brien 
1337c80476e4SDavid E. O'Brien void
133845e5710bSMark Peek ClearLines(void)
1339c80476e4SDavid E. O'Brien {				/* Make sure all lines are *really* blank */
134023338178SMark Peek     int i;
1341c80476e4SDavid E. O'Brien 
1342c80476e4SDavid E. O'Brien     if (T_CanCEOL) {
1343c80476e4SDavid E. O'Brien 	/*
1344c80476e4SDavid E. O'Brien 	 * Clear the lines from the bottom up so that if we try moving
1345c80476e4SDavid E. O'Brien 	 * the cursor down by writing the character that is at the end
1346c80476e4SDavid E. O'Brien 	 * of the screen line, we won't rewrite a character that shouldn't
1347c80476e4SDavid E. O'Brien 	 * be there.
1348c80476e4SDavid E. O'Brien 	 */
1349c80476e4SDavid E. O'Brien 	for (i = OldvcV; i >= 0; i--) {	/* for each line on the screen */
1350c80476e4SDavid E. O'Brien 	    MoveToLine(i);
1351c80476e4SDavid E. O'Brien 	    MoveToChar(0);
1352c80476e4SDavid E. O'Brien 	    ClearEOL(TermH);
1353c80476e4SDavid E. O'Brien 	}
1354c80476e4SDavid E. O'Brien     }
1355c80476e4SDavid E. O'Brien     else {
1356c80476e4SDavid E. O'Brien 	MoveToLine(OldvcV);	/* go to last line */
1357c80476e4SDavid E. O'Brien 	(void) putraw('\r');	/* go to BOL */
1358c80476e4SDavid E. O'Brien 	(void) putraw('\n');	/* go to new line */
1359c80476e4SDavid E. O'Brien     }
1360c80476e4SDavid E. O'Brien }
1361