xref: /freebsd/contrib/tcsh/ed.refresh.c (revision 6560ac57ce879857203bc456cdc3849808dc0700)
1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien  * ed.refresh.c: Lower level screen refreshing functions
3c80476e4SDavid E. O'Brien  */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien  * All rights reserved.
7c80476e4SDavid E. O'Brien  *
8c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien  * are met:
11c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1629301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien  *    without specific prior written permission.
19c80476e4SDavid E. O'Brien  *
20c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien  */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "ed.h"
34c80476e4SDavid E. O'Brien /* #define DEBUG_UPDATE */
35c80476e4SDavid E. O'Brien /* #define DEBUG_REFRESH */
36c80476e4SDavid E. O'Brien /* #define DEBUG_LITERAL */
37c80476e4SDavid E. O'Brien 
38c80476e4SDavid E. O'Brien /* refresh.c -- refresh the current set of lines on the screen */
39c80476e4SDavid E. O'Brien 
4023338178SMark Peek Char   *litptr;
41c80476e4SDavid E. O'Brien static int vcursor_h, vcursor_v;
42c80476e4SDavid E. O'Brien static int rprompt_h, rprompt_v;
43c80476e4SDavid E. O'Brien 
4445e5710bSMark Peek static	int	MakeLiteral		(Char *, int, Char);
45*19d2e3deSDmitry Chagin static	int	Draw 			(Char *, int, int);
4645e5710bSMark Peek static	void	Vdraw 			(Char, int);
4745e5710bSMark Peek static	void	RefreshPromptpart	(Char *);
4845e5710bSMark Peek static	void	update_line 		(Char *, Char *, int);
4945e5710bSMark Peek static	void	str_insert		(Char *, int, int, Char *, int);
5045e5710bSMark Peek static	void	str_delete		(Char *, int, int, int);
5145e5710bSMark Peek static	void	str_cp			(Char *, Char *, int);
52b2d5d167SMark Peek #ifndef WINNT_NATIVE
53b2d5d167SMark Peek static
54b2d5d167SMark Peek #else
55b2d5d167SMark Peek extern
56b2d5d167SMark Peek #endif
5745e5710bSMark Peek 	void    PutPlusOne      (Char, int);
5845e5710bSMark Peek static	void	cpy_pad_spaces		(Char *, Char *, int);
59c80476e4SDavid E. O'Brien #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
609ccc37e3SMark Peek static	void	reprintf			(char *, ...);
61c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
6245e5710bSMark Peek static	void	dprintstr		(char *, const Char *, const Char *);
63c80476e4SDavid E. O'Brien 
64c80476e4SDavid E. O'Brien static void
dprintstr(char * str,const Char * f,const Char * t)6545e5710bSMark Peek dprintstr(char *str, const Char *f, const Char *t)
66c80476e4SDavid E. O'Brien {
679ccc37e3SMark Peek     reprintf("%s:\"", str);
6823338178SMark Peek     while (f < t) {
6945e5710bSMark Peek 	if (ASC(*f) & ~ASCII)
709ccc37e3SMark Peek 	  reprintf("[%x]", *f++);
7123338178SMark Peek 	else
729ccc37e3SMark Peek 	  reprintf("%c", CTL_ESC(ASCII & ASC(*f++)));
7323338178SMark Peek     }
749ccc37e3SMark Peek     reprintf("\"\r\n");
75c80476e4SDavid E. O'Brien }
76c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
77c80476e4SDavid E. O'Brien 
789ccc37e3SMark Peek /* reprintf():
79c80476e4SDavid E. O'Brien  *	Print to $DEBUGTTY, so that we can test editing on one pty, and
80c80476e4SDavid E. O'Brien  *      print debugging stuff on another. Don't interrupt the shell while
81c80476e4SDavid E. O'Brien  *	debugging cause you'll mangle up the file descriptors!
82c80476e4SDavid E. O'Brien  */
83c80476e4SDavid E. O'Brien static void
reprintf(char * fmt,...)849ccc37e3SMark Peek reprintf(char *fmt, ...)
85c80476e4SDavid E. O'Brien {
86c80476e4SDavid E. O'Brien     static int fd = -1;
87c80476e4SDavid E. O'Brien     char *dtty;
88c80476e4SDavid E. O'Brien 
89c80476e4SDavid E. O'Brien     if ((dtty = getenv("DEBUGTTY"))) {
90c80476e4SDavid E. O'Brien 	int o;
91c80476e4SDavid E. O'Brien 	va_list va;
92c80476e4SDavid E. O'Brien 	va_start(va, fmt);
93c80476e4SDavid E. O'Brien 
94c80476e4SDavid E. O'Brien 	if (fd == -1)
9545e5710bSMark Peek 	    fd = xopen(dtty, O_RDWR);
96c80476e4SDavid E. O'Brien 	o = SHOUT;
97c80476e4SDavid E. O'Brien 	flush();
98c80476e4SDavid E. O'Brien 	SHOUT = fd;
99c80476e4SDavid E. O'Brien 	xvprintf(fmt, va);
100c80476e4SDavid E. O'Brien 	va_end(va);
101c80476e4SDavid E. O'Brien 	flush();
102c80476e4SDavid E. O'Brien 	SHOUT = o;
103c80476e4SDavid E. O'Brien     }
104c80476e4SDavid E. O'Brien }
105c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
106c80476e4SDavid E. O'Brien 
10723338178SMark Peek static int litlen = 0, litalloc = 0;
10823338178SMark Peek 
MakeLiteral(Char * str,int len,Char addlit)10945e5710bSMark Peek static int MakeLiteral(Char *str, int len, Char addlit)
110c80476e4SDavid E. O'Brien {
11123338178SMark Peek     int i, addlitlen = 0;
11223338178SMark Peek     Char *addlitptr = 0;
11323338178SMark Peek     if (addlit) {
11423338178SMark Peek 	if ((addlit & LITERAL) != 0) {
11523338178SMark Peek 	    addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
11623338178SMark Peek 	    addlitlen = Strlen(addlitptr);
11723338178SMark Peek 	} else {
11823338178SMark Peek 	    addlitptr = &addlit;
11923338178SMark Peek 	    addlitlen = 1;
120c80476e4SDavid E. O'Brien 	}
12123338178SMark Peek 	for (i = 0; i < litlen; i += LIT_FACTOR)
12223338178SMark Peek 	    if (!Strncmp(addlitptr, litptr + i, addlitlen) && !Strncmp(str, litptr + i + addlitlen, len) && litptr[i + addlitlen + len] == 0)
12323338178SMark Peek 		return (i / LIT_FACTOR) | LITERAL;
12423338178SMark Peek     } else {
12523338178SMark Peek 	addlitlen = 0;
12623338178SMark Peek 	for (i = 0; i < litlen; i += LIT_FACTOR)
12723338178SMark Peek 	    if (!Strncmp(str, litptr + i, len) && litptr[i + len] == 0)
12823338178SMark Peek 		return (i / LIT_FACTOR) | LITERAL;
12923338178SMark Peek     }
13023338178SMark Peek     if (litlen + addlitlen + len + 1 + (LIT_FACTOR - 1) > litalloc) {
13123338178SMark Peek 	Char *newlitptr;
13223338178SMark Peek 	int add = 256;
13323338178SMark Peek 	while (len + addlitlen + 1 + (LIT_FACTOR - 1) > add)
13423338178SMark Peek 	    add *= 2;
13545e5710bSMark Peek 	newlitptr = xrealloc(litptr, (litalloc + add) * sizeof(Char));
13623338178SMark Peek 	if (!newlitptr)
13723338178SMark Peek 	    return '?';
13823338178SMark Peek 	litptr = newlitptr;
13923338178SMark Peek 	litalloc += add;
14023338178SMark Peek 	if (addlitptr && addlitptr != &addlit)
14123338178SMark Peek 	    addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
14223338178SMark Peek     }
14323338178SMark Peek     i = litlen / LIT_FACTOR;
14423338178SMark Peek     if (i >= LITERAL || i == CHAR_DBWIDTH)
14523338178SMark Peek 	return '?';
14623338178SMark Peek     if (addlitptr) {
14723338178SMark Peek 	Strncpy(litptr + litlen, addlitptr, addlitlen);
14823338178SMark Peek 	litlen += addlitlen;
14923338178SMark Peek     }
15023338178SMark Peek     Strncpy(litptr + litlen, str, len);
15123338178SMark Peek     litlen += len;
15223338178SMark Peek     do
15323338178SMark Peek 	litptr[litlen++] = 0;
15423338178SMark Peek     while (litlen % LIT_FACTOR);
15523338178SMark Peek     return i | LITERAL;
15623338178SMark Peek }
157c80476e4SDavid E. O'Brien 
158*19d2e3deSDmitry Chagin /* draw char at cp, expand tabs, ctl chars */
15923338178SMark Peek static int
Draw(Char * cp,int nocomb,int drawPrompt)160*19d2e3deSDmitry Chagin Draw(Char *cp, int nocomb, int drawPrompt)
16123338178SMark Peek {
16245e5710bSMark Peek     int w, i, lv, lh;
16345e5710bSMark Peek     Char c, attr;
16423338178SMark Peek 
165*19d2e3deSDmitry Chagin #ifdef WIDE_STRINGS
166*19d2e3deSDmitry Chagin     if (!drawPrompt) {			/* draw command-line */
167*19d2e3deSDmitry Chagin 	attr = 0;
168*19d2e3deSDmitry Chagin 	c = *cp;
169*19d2e3deSDmitry Chagin     } else {				/* draw prompt */
170*19d2e3deSDmitry Chagin 	/* prompt with attributes(UNDER,BOLD,STANDOUT) */
171*19d2e3deSDmitry Chagin 	if (*cp & (UNDER | BOLD | STANDOUT)) {		/* *cp >= STANDOUT */
172*19d2e3deSDmitry Chagin 
173*19d2e3deSDmitry Chagin 	    /* example)
174*19d2e3deSDmitry Chagin 	     * We can't distinguish whether (*cp=)0x02ffffff is
175*19d2e3deSDmitry Chagin 	     * U+02FFFFFF or U+00FFFFFF|STANDOUT.
176*19d2e3deSDmitry Chagin 	     * We handle as U+00FFFFFF|STANDOUT, only when drawing prompt. */
177*19d2e3deSDmitry Chagin 	    attr = (*cp & ATTRIBUTES);
178*19d2e3deSDmitry Chagin 	    /* ~(UNDER | BOLD | STANDOUT) = 0xf1ffffff */
179*19d2e3deSDmitry Chagin 	    c = *cp & ~(UNDER | BOLD | STANDOUT);
180*19d2e3deSDmitry Chagin 
181*19d2e3deSDmitry Chagin 	    /* if c is ctrl code, we handle *cp as havnig no attributes */
182*19d2e3deSDmitry Chagin 	    if ((c < 0x20 && c >= 0) || c == 0x7f) {
183*19d2e3deSDmitry Chagin 		attr = 0;
184*19d2e3deSDmitry Chagin 		c = *cp;
185*19d2e3deSDmitry Chagin 	    }
186*19d2e3deSDmitry Chagin 	} else {			/* prompt without attributes */
187*19d2e3deSDmitry Chagin 	    attr = 0;
188*19d2e3deSDmitry Chagin 	    c = *cp;
189*19d2e3deSDmitry Chagin 	}
190*19d2e3deSDmitry Chagin     }
191*19d2e3deSDmitry Chagin #else
19223338178SMark Peek     attr = *cp & ~CHAR;
19345e5710bSMark Peek     c = *cp & CHAR;
194*19d2e3deSDmitry Chagin #endif
195*19d2e3deSDmitry Chagin     w = NLSClassify(c, nocomb, drawPrompt);
19623338178SMark Peek     switch (w) {
19723338178SMark Peek 	case NLSCLASS_NL:
19823338178SMark Peek 	    Vdraw('\0', 0);		/* assure end of line	 */
199c80476e4SDavid E. O'Brien 	    vcursor_h = 0;		/* reset cursor pos	 */
200c80476e4SDavid E. O'Brien 	    vcursor_v++;
20123338178SMark Peek 	    break;
20223338178SMark Peek 	case NLSCLASS_TAB:
20323338178SMark Peek 	    do {
20423338178SMark Peek 		Vdraw(' ', 1);
20523338178SMark Peek 	    } while ((vcursor_h & 07) != 0);
20623338178SMark Peek 	    break;
20723338178SMark Peek 	case NLSCLASS_CTRL:
20823338178SMark Peek 	    Vdraw('^' | attr, 1);
20923338178SMark Peek 	    if (c == CTL_ESC('\177')) {
21023338178SMark Peek 		Vdraw('?' | attr, 1);
21123338178SMark Peek 	    } else {
2123b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
213c80476e4SDavid E. O'Brien 		/* uncontrolify it; works only for iso8859-1 like sets */
21423338178SMark Peek 		Vdraw(c | 0100 | attr, 1);
2153b6eaa7bSAndrey A. Chernov #else
21623338178SMark Peek 		Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1);
21723338178SMark Peek #endif
218c80476e4SDavid E. O'Brien 	    }
21923338178SMark Peek 	    break;
22023338178SMark Peek 	case NLSCLASS_ILLEGAL:
22123338178SMark Peek 	    Vdraw('\\' | attr, 1);
22245e5710bSMark Peek 	    Vdraw((((c >> 6) & 7) + '0') | attr, 1);
22345e5710bSMark Peek 	    Vdraw((((c >> 3) & 7) + '0') | attr, 1);
22445e5710bSMark Peek 	    Vdraw(((c & 7) + '0') | attr, 1);
22523338178SMark Peek 	    break;
22623338178SMark Peek 	case NLSCLASS_ILLEGAL2:
22723338178SMark Peek 	case NLSCLASS_ILLEGAL3:
22823338178SMark Peek 	case NLSCLASS_ILLEGAL4:
229*19d2e3deSDmitry Chagin 	case NLSCLASS_ILLEGAL5:
230*19d2e3deSDmitry Chagin 	    Vdraw('\\', 1);
231*19d2e3deSDmitry Chagin 	    Vdraw('U', 1);
232*19d2e3deSDmitry Chagin 	    Vdraw('+', 1);
233*19d2e3deSDmitry Chagin 	    for (i = 16 + 4 * (-w-5); i >= 0; i -= 4)
23423338178SMark Peek 		Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1);
23523338178SMark Peek 	    break;
23623338178SMark Peek 	case 0:
23723338178SMark Peek 	    lv = vcursor_v;
23823338178SMark Peek 	    lh = vcursor_h;
23923338178SMark Peek 	    for (;;) {
24023338178SMark Peek 		lh--;
24123338178SMark Peek 		if (lh < 0) {
24223338178SMark Peek 		    lv--;
24323338178SMark Peek 		    if (lv < 0)
24423338178SMark Peek 			break;
24523338178SMark Peek 		    lh = Strlen(Vdisplay[lv]) - 1;
246c80476e4SDavid E. O'Brien 		}
24723338178SMark Peek 		if (Vdisplay[lv][lh] != CHAR_DBWIDTH)
24823338178SMark Peek 		    break;
24923338178SMark Peek 	    }
25023338178SMark Peek 	    if (lv < 0) {
25123338178SMark Peek 		Vdraw('\\' | attr, 1);
25245e5710bSMark Peek 		Vdraw((((c >> 6) & 7) + '0') | attr, 1);
25345e5710bSMark Peek 		Vdraw((((c >> 3) & 7) + '0') | attr, 1);
25445e5710bSMark Peek 		Vdraw(((c & 7) + '0') | attr, 1);
25545e5710bSMark Peek 		break;
25623338178SMark Peek 	    }
25745e5710bSMark Peek 	    Vdisplay[lv][lh] = MakeLiteral(cp, 1, Vdisplay[lv][lh]);
25823338178SMark Peek 	    break;
25923338178SMark Peek 	default:
26023338178SMark Peek 	    Vdraw(*cp, w);
26123338178SMark Peek 	    break;
262c80476e4SDavid E. O'Brien     }
26345e5710bSMark Peek     return 1;
264c80476e4SDavid E. O'Brien }
265c80476e4SDavid E. O'Brien 
266c80476e4SDavid E. O'Brien static void
Vdraw(Char c,int width)26745e5710bSMark Peek Vdraw(Char c, int width)	/* draw char c onto V lines */
268c80476e4SDavid E. O'Brien {
269c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
270c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS
2719ccc37e3SMark Peek     reprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width);
272c80476e4SDavid E. O'Brien # else
2739ccc37e3SMark Peek     reprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width);
274c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */
275c80476e4SDavid E. O'Brien #endif  /* DEBUG_REFRESH */
276c80476e4SDavid E. O'Brien 
27723338178SMark Peek     /* Hopefully this is what all the terminals do with multi-column characters
27823338178SMark Peek        that "span line breaks". */
27923338178SMark Peek     while (vcursor_h + width > TermH)
28023338178SMark Peek 	Vdraw(' ', 1);
28145e5710bSMark Peek     Vdisplay[vcursor_v][vcursor_h] = c;
28223338178SMark Peek     if (width)
283c80476e4SDavid E. O'Brien 	vcursor_h++;		/* advance to next place */
28423338178SMark Peek     while (--width > 0)
28523338178SMark Peek 	Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH;
286c80476e4SDavid E. O'Brien     if (vcursor_h >= TermH) {
287c80476e4SDavid E. O'Brien 	Vdisplay[vcursor_v][TermH] = '\0';	/* assure end of line */
288c80476e4SDavid E. O'Brien 	vcursor_h = 0;		/* reset it. */
289c80476e4SDavid E. O'Brien 	vcursor_v++;
290c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
291c80476e4SDavid E. O'Brien 	if (vcursor_v >= TermV) {	/* should NEVER happen. */
2929ccc37e3SMark Peek 	    reprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
293c80476e4SDavid E. O'Brien 		    vcursor_v, TermV);
294c80476e4SDavid E. O'Brien 	    abort();
295c80476e4SDavid E. O'Brien 	}
296c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
297c80476e4SDavid E. O'Brien     }
298c80476e4SDavid E. O'Brien }
299c80476e4SDavid E. O'Brien 
300c80476e4SDavid E. O'Brien /*
301c80476e4SDavid E. O'Brien  *  RefreshPromptpart()
302c80476e4SDavid E. O'Brien  *	draws a prompt element, expanding literals (we know it's ASCIZ)
303c80476e4SDavid E. O'Brien  */
304c80476e4SDavid E. O'Brien static void
RefreshPromptpart(Char * buf)30545e5710bSMark Peek RefreshPromptpart(Char *buf)
306c80476e4SDavid E. O'Brien {
30723338178SMark Peek     Char *cp;
30845e5710bSMark Peek     int w;
309c80476e4SDavid E. O'Brien 
31045e5710bSMark Peek     if (buf == NULL)
31145e5710bSMark Peek 	return;
31223338178SMark Peek     for (cp = buf; *cp; ) {
313c80476e4SDavid E. O'Brien 	if (*cp & LITERAL) {
31423338178SMark Peek 	    Char *litstart = cp;
315c80476e4SDavid E. O'Brien 	    while (*cp & LITERAL)
316c80476e4SDavid E. O'Brien 		cp++;
31723338178SMark Peek 	    if (*cp) {
31845e5710bSMark Peek 		w = NLSWidth(*cp & CHAR);
31945e5710bSMark Peek 		Vdraw(MakeLiteral(litstart, cp + 1 - litstart, 0), w);
32045e5710bSMark Peek 		cp++;
32123338178SMark Peek 	    }
322c80476e4SDavid E. O'Brien 	    else {
323c80476e4SDavid E. O'Brien 		/*
324c80476e4SDavid E. O'Brien 		 * XXX: This is a bug, we lose the last literal, if it is not
325c80476e4SDavid E. O'Brien 		 * followed by a normal character, but it is too hard to fix
326c80476e4SDavid E. O'Brien 		 */
327c80476e4SDavid E. O'Brien 		break;
328c80476e4SDavid E. O'Brien 	    }
329c80476e4SDavid E. O'Brien 	}
330c80476e4SDavid E. O'Brien 	else
331*19d2e3deSDmitry Chagin 	    cp += Draw(cp, cp == buf, 1);
332c80476e4SDavid E. O'Brien     }
333c80476e4SDavid E. O'Brien }
334c80476e4SDavid E. O'Brien 
335c80476e4SDavid E. O'Brien /*
336c80476e4SDavid E. O'Brien  *  Refresh()
337c80476e4SDavid E. O'Brien  *	draws the new virtual screen image from the current input
338c80476e4SDavid E. O'Brien  *  	line, then goes line-by-line changing the real image to the new
339c80476e4SDavid E. O'Brien  *	virtual image. The routine to re-draw a line can be replaced
340c80476e4SDavid E. O'Brien  *	easily in hopes of a smarter one being placed there.
341c80476e4SDavid E. O'Brien  */
342b2d5d167SMark Peek #ifndef WINNT_NATIVE
343b2d5d167SMark Peek static
344b2d5d167SMark Peek #endif
345b2d5d167SMark Peek int OldvcV = 0;
346b2d5d167SMark Peek 
347c80476e4SDavid E. O'Brien void
Refresh(void)34845e5710bSMark Peek Refresh(void)
349c80476e4SDavid E. O'Brien {
35023338178SMark Peek     int cur_line;
35123338178SMark Peek     Char *cp;
352c80476e4SDavid E. O'Brien     int     cur_h, cur_v = 0, new_vcv;
353c80476e4SDavid E. O'Brien     int     rhdiff;
354c80476e4SDavid E. O'Brien     Char    oldgetting;
355c80476e4SDavid E. O'Brien 
356c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
3579ccc37e3SMark Peek     reprintf("Prompt = :%s:\r\n", short2str(Prompt));
3589ccc37e3SMark Peek     reprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
359c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
360c80476e4SDavid E. O'Brien     oldgetting = GettingInput;
361c80476e4SDavid E. O'Brien     GettingInput = 0;		/* avoid re-entrance via SIGWINCH */
362c80476e4SDavid E. O'Brien 
363c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
364c80476e4SDavid E. O'Brien     vcursor_h = 0;
365c80476e4SDavid E. O'Brien     vcursor_v = 0;
36645e5710bSMark Peek     RefreshPromptpart(RPrompt);
367c80476e4SDavid E. O'Brien     rprompt_h = vcursor_h;
368c80476e4SDavid E. O'Brien     rprompt_v = vcursor_v;
369c80476e4SDavid E. O'Brien 
370c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, draw prompt */
371c80476e4SDavid E. O'Brien     vcursor_h = 0;
372c80476e4SDavid E. O'Brien     vcursor_v = 0;
37345e5710bSMark Peek     RefreshPromptpart(Prompt);
374c80476e4SDavid E. O'Brien     cur_h = -1;			/* set flag in case I'm not set */
375c80476e4SDavid E. O'Brien 
376c80476e4SDavid E. O'Brien     /* draw the current input buffer */
37723338178SMark Peek     for (cp = InputBuf; (cp < LastChar); ) {
37823338178SMark Peek 	if (cp >= Cursor && cur_h == -1) {
379c80476e4SDavid E. O'Brien 	    cur_h = vcursor_h;	/* save for later */
380c80476e4SDavid E. O'Brien 	    cur_v = vcursor_v;
38123338178SMark Peek 	    Cursor = cp;
382c80476e4SDavid E. O'Brien 	}
383*19d2e3deSDmitry Chagin 	cp += Draw(cp, cp == InputBuf, 0);
384c80476e4SDavid E. O'Brien     }
385c80476e4SDavid E. O'Brien 
386c80476e4SDavid E. O'Brien     if (cur_h == -1) {		/* if I haven't been set yet, I'm at the end */
387c80476e4SDavid E. O'Brien 	cur_h = vcursor_h;
388c80476e4SDavid E. O'Brien 	cur_v = vcursor_v;
389c80476e4SDavid E. O'Brien     }
390c80476e4SDavid E. O'Brien 
391c80476e4SDavid E. O'Brien     rhdiff = TermH - vcursor_h - rprompt_h;
392c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
393c80476e4SDavid E. O'Brien 			/*
394c80476e4SDavid E. O'Brien 			 * have a right-hand side prompt that will fit on
395c80476e4SDavid E. O'Brien 			 * the end of the first line with at least one
396c80476e4SDavid E. O'Brien 			 * character gap to the input buffer.
397c80476e4SDavid E. O'Brien 			 */
398c80476e4SDavid E. O'Brien 	while (--rhdiff > 0)		/* pad out with spaces */
39923338178SMark Peek 	    Vdraw(' ', 1);
40045e5710bSMark Peek 	RefreshPromptpart(RPrompt);
401c80476e4SDavid E. O'Brien     }
402c80476e4SDavid E. O'Brien     else {
403c80476e4SDavid E. O'Brien 	rprompt_h = 0;			/* flag "not using rprompt" */
404c80476e4SDavid E. O'Brien 	rprompt_v = 0;
405c80476e4SDavid E. O'Brien     }
406c80476e4SDavid E. O'Brien 
407c80476e4SDavid E. O'Brien     new_vcv = vcursor_v;	/* must be done BEFORE the NUL is written */
40823338178SMark Peek     Vdraw('\0', 1);		/* put NUL on end */
409c80476e4SDavid E. O'Brien 
41023338178SMark Peek #if defined (DEBUG_REFRESH)
4119ccc37e3SMark Peek     reprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
412c80476e4SDavid E. O'Brien 	    TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
413c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
414c80476e4SDavid E. O'Brien 
415c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
4169ccc37e3SMark Peek     reprintf("updating %d lines.\r\n", new_vcv);
417c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
418c80476e4SDavid E. O'Brien     for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
419c80476e4SDavid E. O'Brien 	/* NOTE THAT update_line MAY CHANGE Display[cur_line] */
420c80476e4SDavid E. O'Brien 	update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
4213b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
422c80476e4SDavid E. O'Brien 	flush();
4233b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
424c80476e4SDavid E. O'Brien 
425c80476e4SDavid E. O'Brien 	/*
426c80476e4SDavid E. O'Brien 	 * Copy the new line to be the current one, and pad out with spaces
427c80476e4SDavid E. O'Brien 	 * to the full width of the terminal so that if we try moving the
428c80476e4SDavid E. O'Brien 	 * cursor by writing the character that is at the end of the
429c80476e4SDavid E. O'Brien 	 * screen line, it won't be a NUL or some old leftover stuff.
430c80476e4SDavid E. O'Brien 	 */
431c80476e4SDavid E. O'Brien 	cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
432c80476e4SDavid E. O'Brien     }
433c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4349ccc37e3SMark Peek     reprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
435c80476e4SDavid E. O'Brien 	    vcursor_v, OldvcV, cur_line);
436c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
437c80476e4SDavid E. O'Brien     if (OldvcV > new_vcv) {
438c80476e4SDavid E. O'Brien 	for (; cur_line <= OldvcV; cur_line++) {
439c80476e4SDavid E. O'Brien 	    update_line(Display[cur_line], STRNULL, cur_line);
440c80476e4SDavid E. O'Brien 	    *Display[cur_line] = '\0';
441c80476e4SDavid E. O'Brien 	}
442c80476e4SDavid E. O'Brien     }
443c80476e4SDavid E. O'Brien     OldvcV = new_vcv;		/* set for next time */
444c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4459ccc37e3SMark Peek     reprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
446c80476e4SDavid E. O'Brien 	    CursorH, CursorV, cur_h, cur_v);
447c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
4483b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
449c80476e4SDavid E. O'Brien     flush();
4503b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
451c80476e4SDavid E. O'Brien     MoveToLine(cur_v);		/* go to where the cursor is */
452c80476e4SDavid E. O'Brien     MoveToChar(cur_h);
453c80476e4SDavid E. O'Brien     SetAttributes(0);		/* Clear all attributes */
454c80476e4SDavid E. O'Brien     flush();			/* send the output... */
455c80476e4SDavid E. O'Brien     GettingInput = oldgetting;	/* reset to old value */
456c80476e4SDavid E. O'Brien }
457c80476e4SDavid E. O'Brien 
458c80476e4SDavid E. O'Brien #ifdef notdef
GotoBottom(void)45945e5710bSMark Peek GotoBottom(void)
460c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
461c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
462c80476e4SDavid E. O'Brien }
463c80476e4SDavid E. O'Brien 
464c80476e4SDavid E. O'Brien #endif
465c80476e4SDavid E. O'Brien 
466c80476e4SDavid E. O'Brien void
PastBottom(void)46745e5710bSMark Peek PastBottom(void)
468c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
469c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
470c80476e4SDavid E. O'Brien     (void) putraw('\r');
471c80476e4SDavid E. O'Brien     (void) putraw('\n');
472c80476e4SDavid E. O'Brien     ClearDisp();
473c80476e4SDavid E. O'Brien     flush();
474c80476e4SDavid E. O'Brien }
475c80476e4SDavid E. O'Brien 
476c80476e4SDavid E. O'Brien 
477c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat,
478c80476e4SDavid E. O'Brien    maximum length of d is dlen */
479c80476e4SDavid E. O'Brien static void
str_insert(Char * d,int dat,int dlen,Char * s,int num)48045e5710bSMark Peek str_insert(Char *d, int dat, int dlen, Char *s, int num)
481c80476e4SDavid E. O'Brien {
48223338178SMark Peek     Char *a, *b;
483c80476e4SDavid E. O'Brien 
484c80476e4SDavid E. O'Brien     if (num <= 0)
485c80476e4SDavid E. O'Brien 	return;
486c80476e4SDavid E. O'Brien     if (num > dlen - dat)
487c80476e4SDavid E. O'Brien 	num = dlen - dat;
488c80476e4SDavid E. O'Brien 
489c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4909ccc37e3SMark Peek     reprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
491c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
4929ccc37e3SMark Peek     reprintf("s == \"%s\"n", short2str(s));
493c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
494c80476e4SDavid E. O'Brien 
495c80476e4SDavid E. O'Brien     /* open up the space for num chars */
496c80476e4SDavid E. O'Brien     if (num > 0) {
497c80476e4SDavid E. O'Brien 	b = d + dlen - 1;
498c80476e4SDavid E. O'Brien 	a = b - num;
499c80476e4SDavid E. O'Brien 	while (a >= &d[dat])
500c80476e4SDavid E. O'Brien 	    *b-- = *a--;
501c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
502c80476e4SDavid E. O'Brien     }
503c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5049ccc37e3SMark Peek     reprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
505c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
5069ccc37e3SMark Peek     reprintf("s == \"%s\"n", short2str(s));
507c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
508c80476e4SDavid E. O'Brien 
509c80476e4SDavid E. O'Brien     /* copy the characters */
510c80476e4SDavid E. O'Brien     for (a = d + dat; (a < d + dlen) && (num > 0); num--)
511c80476e4SDavid E. O'Brien 	*a++ = *s++;
512c80476e4SDavid E. O'Brien 
513c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5149ccc37e3SMark Peek     reprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
515c80476e4SDavid E. O'Brien 	    num, dat, dlen, d, short2str(s));
5169ccc37e3SMark Peek     reprintf("s == \"%s\"n", short2str(s));
517c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
518c80476e4SDavid E. O'Brien }
519c80476e4SDavid E. O'Brien 
520c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */
521c80476e4SDavid E. O'Brien static void
str_delete(Char * d,int dat,int dlen,int num)52245e5710bSMark Peek str_delete(Char *d, int dat, int dlen, int num)
523c80476e4SDavid E. O'Brien {
52423338178SMark Peek     Char *a, *b;
525c80476e4SDavid E. O'Brien 
526c80476e4SDavid E. O'Brien     if (num <= 0)
527c80476e4SDavid E. O'Brien 	return;
528c80476e4SDavid E. O'Brien     if (dat + num >= dlen) {
529c80476e4SDavid E. O'Brien 	d[dat] = '\0';
530c80476e4SDavid E. O'Brien 	return;
531c80476e4SDavid E. O'Brien     }
532c80476e4SDavid E. O'Brien 
533c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5349ccc37e3SMark Peek     reprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
535c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
536c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
537c80476e4SDavid E. O'Brien 
538c80476e4SDavid E. O'Brien     /* open up the space for num chars */
539c80476e4SDavid E. O'Brien     if (num > 0) {
540c80476e4SDavid E. O'Brien 	b = d + dat;
541c80476e4SDavid E. O'Brien 	a = b + num;
542c80476e4SDavid E. O'Brien 	while (a < &d[dlen])
543c80476e4SDavid E. O'Brien 	    *b++ = *a++;
544c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
545c80476e4SDavid E. O'Brien     }
546c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5479ccc37e3SMark Peek     reprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
548c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
549c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
550c80476e4SDavid E. O'Brien }
551c80476e4SDavid E. O'Brien 
552c80476e4SDavid E. O'Brien static void
str_cp(Char * a,Char * b,int n)55345e5710bSMark Peek str_cp(Char *a, Char *b, int n)
554c80476e4SDavid E. O'Brien {
555c80476e4SDavid E. O'Brien     while (n-- && *b)
556c80476e4SDavid E. O'Brien 	*a++ = *b++;
557c80476e4SDavid E. O'Brien }
558c80476e4SDavid E. O'Brien 
559c80476e4SDavid E. O'Brien 
560c80476e4SDavid E. O'Brien /* ****************************************************************
561c80476e4SDavid E. O'Brien     update_line() is based on finding the middle difference of each line
562c80476e4SDavid E. O'Brien     on the screen; vis:
563c80476e4SDavid E. O'Brien 
564c80476e4SDavid E. O'Brien 			     /old first difference
565c80476e4SDavid E. O'Brien 	/beginning of line   |              /old last same       /old EOL
566c80476e4SDavid E. O'Brien 	v		     v              v                    v
567c80476e4SDavid E. O'Brien old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
568c80476e4SDavid E. O'Brien new:	eddie> Oh, my little buggy says to me, as lurgid as
569c80476e4SDavid E. O'Brien 	^		     ^        ^			   ^
570c80476e4SDavid E. O'Brien 	\beginning of line   |        \new last same	   \new end of line
571c80476e4SDavid E. O'Brien 			     \new first difference
572c80476e4SDavid E. O'Brien 
573c80476e4SDavid E. O'Brien     all are character pointers for the sake of speed.  Special cases for
574c80476e4SDavid E. O'Brien     no differences, as well as for end of line additions must be handled.
575c80476e4SDavid E. O'Brien **************************************************************** */
576c80476e4SDavid E. O'Brien 
577c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it".  This should be about
578c80476e4SDavid E. O'Brien  * half the "cost" of going into insert mode, inserting a character, and
579c80476e4SDavid E. O'Brien  * going back out.  This should really be calculated from the termcap
580c80476e4SDavid E. O'Brien  * data...  For the moment, a good number for ANSI terminals.
581c80476e4SDavid E. O'Brien  */
582c80476e4SDavid E. O'Brien #define MIN_END_KEEP	4
583c80476e4SDavid E. O'Brien 
584c80476e4SDavid E. O'Brien static void			/* could be changed to make it smarter */
update_line(Char * old,Char * new,int cur_line)58545e5710bSMark Peek update_line(Char *old, Char *new, int cur_line)
586c80476e4SDavid E. O'Brien {
58723338178SMark Peek     Char *o, *n, *p, c;
588c80476e4SDavid E. O'Brien     Char  *ofd, *ols, *oe, *nfd, *nls, *ne;
589c80476e4SDavid E. O'Brien     Char  *osb, *ose, *nsb, *nse;
590c80476e4SDavid E. O'Brien     int     fx, sx;
591c80476e4SDavid E. O'Brien 
592c80476e4SDavid E. O'Brien     /*
59323338178SMark Peek      * find first diff (won't be CHAR_DBWIDTH in either line)
594c80476e4SDavid E. O'Brien      */
595c80476e4SDavid E. O'Brien     for (o = old, n = new; *o && (*o == *n); o++, n++)
596c80476e4SDavid E. O'Brien 	continue;
597c80476e4SDavid E. O'Brien     ofd = o;
598c80476e4SDavid E. O'Brien     nfd = n;
599c80476e4SDavid E. O'Brien 
600c80476e4SDavid E. O'Brien     /*
601c80476e4SDavid E. O'Brien      * Find the end of both old and new
602c80476e4SDavid E. O'Brien      */
60345e5710bSMark Peek     o = Strend(o);
60445e5710bSMark Peek 
605c80476e4SDavid E. O'Brien     /*
606c80476e4SDavid E. O'Brien      * Remove any trailing blanks off of the end, being careful not to
607c80476e4SDavid E. O'Brien      * back up past the beginning.
608c80476e4SDavid E. O'Brien      */
60945e5710bSMark Peek     if (!(adrof(STRhighlight) && MarkIsSet)) {
610c80476e4SDavid E. O'Brien     while (ofd < o) {
611c80476e4SDavid E. O'Brien 	if (o[-1] != ' ')
612c80476e4SDavid E. O'Brien 	    break;
613c80476e4SDavid E. O'Brien 	o--;
614c80476e4SDavid E. O'Brien     }
61545e5710bSMark Peek     }
616c80476e4SDavid E. O'Brien     oe = o;
617c80476e4SDavid E. O'Brien     *oe = (Char) 0;
618c80476e4SDavid E. O'Brien 
61945e5710bSMark Peek     n = Strend(n);
620c80476e4SDavid E. O'Brien 
621c80476e4SDavid E. O'Brien     /* remove blanks from end of new */
62245e5710bSMark Peek     if (!(adrof(STRhighlight) && MarkIsSet)) {
623c80476e4SDavid E. O'Brien     while (nfd < n) {
624c80476e4SDavid E. O'Brien 	if (n[-1] != ' ')
625c80476e4SDavid E. O'Brien 	    break;
626c80476e4SDavid E. O'Brien 	n--;
627c80476e4SDavid E. O'Brien     }
62845e5710bSMark Peek     }
629c80476e4SDavid E. O'Brien     ne = n;
630c80476e4SDavid E. O'Brien     *ne = (Char) 0;
631c80476e4SDavid E. O'Brien 
632c80476e4SDavid E. O'Brien     /*
633c80476e4SDavid E. O'Brien      * if no diff, continue to next line of redraw
634c80476e4SDavid E. O'Brien      */
635c80476e4SDavid E. O'Brien     if (*ofd == '\0' && *nfd == '\0') {
636c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
6379ccc37e3SMark Peek 	reprintf("no difference.\r\n");
638c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
639c80476e4SDavid E. O'Brien 	return;
640c80476e4SDavid E. O'Brien     }
641c80476e4SDavid E. O'Brien 
642c80476e4SDavid E. O'Brien     /*
643c80476e4SDavid E. O'Brien      * find last same pointer
644c80476e4SDavid E. O'Brien      */
645c80476e4SDavid E. O'Brien     while ((o > ofd) && (n > nfd) && (*--o == *--n))
646c80476e4SDavid E. O'Brien 	continue;
64723338178SMark Peek     if (*o != *n) {
64823338178SMark Peek 	o++;
64923338178SMark Peek 	n++;
65023338178SMark Peek     }
65123338178SMark Peek     while (*o == CHAR_DBWIDTH) {
65223338178SMark Peek 	o++;
65323338178SMark Peek 	n++;
65423338178SMark Peek     }
65523338178SMark Peek     ols = o;
65623338178SMark Peek     nls = n;
657c80476e4SDavid E. O'Brien 
658c80476e4SDavid E. O'Brien     /*
659c80476e4SDavid E. O'Brien      * find same begining and same end
660c80476e4SDavid E. O'Brien      */
661c80476e4SDavid E. O'Brien     osb = ols;
662c80476e4SDavid E. O'Brien     nsb = nls;
663c80476e4SDavid E. O'Brien     ose = ols;
664c80476e4SDavid E. O'Brien     nse = nls;
665c80476e4SDavid E. O'Brien 
666c80476e4SDavid E. O'Brien     /*
667c80476e4SDavid E. O'Brien      * case 1: insert: scan from nfd to nls looking for *ofd
668c80476e4SDavid E. O'Brien      */
669c80476e4SDavid E. O'Brien     if (*ofd) {
670c80476e4SDavid E. O'Brien 	for (c = *ofd, n = nfd; n < nls; n++) {
671c80476e4SDavid E. O'Brien 	    if (c == *n) {
672c80476e4SDavid E. O'Brien 		for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
673c80476e4SDavid E. O'Brien 		    continue;
674c80476e4SDavid E. O'Brien 		/*
675c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
676c80476e4SDavid E. O'Brien 		 * take it
677c80476e4SDavid E. O'Brien 		 */
678c80476e4SDavid E. O'Brien 		if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
679c80476e4SDavid E. O'Brien 		    nsb = n;
680c80476e4SDavid E. O'Brien 		    nse = p;
681c80476e4SDavid E. O'Brien 		    osb = ofd;
682c80476e4SDavid E. O'Brien 		    ose = o;
683c80476e4SDavid E. O'Brien 		}
684c80476e4SDavid E. O'Brien 	    }
685c80476e4SDavid E. O'Brien 	}
686c80476e4SDavid E. O'Brien     }
687c80476e4SDavid E. O'Brien 
688c80476e4SDavid E. O'Brien     /*
689c80476e4SDavid E. O'Brien      * case 2: delete: scan from ofd to ols looking for *nfd
690c80476e4SDavid E. O'Brien      */
691c80476e4SDavid E. O'Brien     if (*nfd) {
692c80476e4SDavid E. O'Brien 	for (c = *nfd, o = ofd; o < ols; o++) {
693c80476e4SDavid E. O'Brien 	    if (c == *o) {
694c80476e4SDavid E. O'Brien 		for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
695c80476e4SDavid E. O'Brien 		    continue;
696c80476e4SDavid E. O'Brien 		/*
697c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
698c80476e4SDavid E. O'Brien 		 * take it
699c80476e4SDavid E. O'Brien 		 */
700c80476e4SDavid E. O'Brien 		if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
701c80476e4SDavid E. O'Brien 		    nsb = nfd;
702c80476e4SDavid E. O'Brien 		    nse = n;
703c80476e4SDavid E. O'Brien 		    osb = o;
704c80476e4SDavid E. O'Brien 		    ose = p;
705c80476e4SDavid E. O'Brien 		}
706c80476e4SDavid E. O'Brien 	    }
707c80476e4SDavid E. O'Brien 	}
708c80476e4SDavid E. O'Brien     }
709c80476e4SDavid E. O'Brien #ifdef notdef
710c80476e4SDavid E. O'Brien     /*
711c80476e4SDavid E. O'Brien      * If `last same' is before `same end' re-adjust
712c80476e4SDavid E. O'Brien      */
713c80476e4SDavid E. O'Brien     if (ols < ose)
714c80476e4SDavid E. O'Brien 	ols = ose;
715c80476e4SDavid E. O'Brien     if (nls < nse)
716c80476e4SDavid E. O'Brien 	nls = nse;
717c80476e4SDavid E. O'Brien #endif
718c80476e4SDavid E. O'Brien 
719c80476e4SDavid E. O'Brien     /*
720c80476e4SDavid E. O'Brien      * Pragmatics I: If old trailing whitespace or not enough characters to
721c80476e4SDavid E. O'Brien      * save to be worth it, then don't save the last same info.
722c80476e4SDavid E. O'Brien      */
723c80476e4SDavid E. O'Brien     if ((oe - ols) < MIN_END_KEEP) {
724c80476e4SDavid E. O'Brien 	ols = oe;
725c80476e4SDavid E. O'Brien 	nls = ne;
726c80476e4SDavid E. O'Brien     }
727c80476e4SDavid E. O'Brien 
728c80476e4SDavid E. O'Brien     /*
729c80476e4SDavid E. O'Brien      * Pragmatics II: if the terminal isn't smart enough, make the data dumber
730c80476e4SDavid E. O'Brien      * so the smart update doesn't try anything fancy
731c80476e4SDavid E. O'Brien      */
732c80476e4SDavid E. O'Brien 
733c80476e4SDavid E. O'Brien     /*
734c80476e4SDavid E. O'Brien      * fx is the number of characters we need to insert/delete: in the
735c80476e4SDavid E. O'Brien      * beginning to bring the two same begins together
736c80476e4SDavid E. O'Brien      */
737c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
738c80476e4SDavid E. O'Brien     /*
739c80476e4SDavid E. O'Brien      * sx is the number of characters we need to insert/delete: in the end to
740c80476e4SDavid E. O'Brien      * bring the two same last parts together
741c80476e4SDavid E. O'Brien      */
742c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
743c80476e4SDavid E. O'Brien 
744c80476e4SDavid E. O'Brien     if (!T_CanIns) {
745c80476e4SDavid E. O'Brien 	if (fx > 0) {
746c80476e4SDavid E. O'Brien 	    osb = ols;
747c80476e4SDavid E. O'Brien 	    ose = ols;
748c80476e4SDavid E. O'Brien 	    nsb = nls;
749c80476e4SDavid E. O'Brien 	    nse = nls;
750c80476e4SDavid E. O'Brien 	}
751c80476e4SDavid E. O'Brien 	if (sx > 0) {
752c80476e4SDavid E. O'Brien 	    ols = oe;
753c80476e4SDavid E. O'Brien 	    nls = ne;
754c80476e4SDavid E. O'Brien 	}
755c80476e4SDavid E. O'Brien 	if ((ols - ofd) < (nls - nfd)) {
756c80476e4SDavid E. O'Brien 	    ols = oe;
757c80476e4SDavid E. O'Brien 	    nls = ne;
758c80476e4SDavid E. O'Brien 	}
759c80476e4SDavid E. O'Brien     }
760c80476e4SDavid E. O'Brien     if (!T_CanDel) {
761c80476e4SDavid E. O'Brien 	if (fx < 0) {
762c80476e4SDavid E. O'Brien 	    osb = ols;
763c80476e4SDavid E. O'Brien 	    ose = ols;
764c80476e4SDavid E. O'Brien 	    nsb = nls;
765c80476e4SDavid E. O'Brien 	    nse = nls;
766c80476e4SDavid E. O'Brien 	}
767c80476e4SDavid E. O'Brien 	if (sx < 0) {
768c80476e4SDavid E. O'Brien 	    ols = oe;
769c80476e4SDavid E. O'Brien 	    nls = ne;
770c80476e4SDavid E. O'Brien 	}
771c80476e4SDavid E. O'Brien 	if ((ols - ofd) > (nls - nfd)) {
772c80476e4SDavid E. O'Brien 	    ols = oe;
773c80476e4SDavid E. O'Brien 	    nls = ne;
774c80476e4SDavid E. O'Brien 	}
775c80476e4SDavid E. O'Brien     }
776c80476e4SDavid E. O'Brien 
777c80476e4SDavid E. O'Brien     /*
778c80476e4SDavid E. O'Brien      * Pragmatics III: make sure the middle shifted pointers are correct if
779c80476e4SDavid E. O'Brien      * they don't point to anything (we may have moved ols or nls).
780c80476e4SDavid E. O'Brien      */
781c80476e4SDavid E. O'Brien     /* if the change isn't worth it, don't bother */
782c80476e4SDavid E. O'Brien     /* was: if (osb == ose) */
783c80476e4SDavid E. O'Brien     if ((ose - osb) < MIN_END_KEEP) {
784c80476e4SDavid E. O'Brien 	osb = ols;
785c80476e4SDavid E. O'Brien 	ose = ols;
786c80476e4SDavid E. O'Brien 	nsb = nls;
787c80476e4SDavid E. O'Brien 	nse = nls;
788c80476e4SDavid E. O'Brien     }
789c80476e4SDavid E. O'Brien 
790c80476e4SDavid E. O'Brien     /*
791c80476e4SDavid E. O'Brien      * Now that we are done with pragmatics we recompute fx, sx
792c80476e4SDavid E. O'Brien      */
793c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
794c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
795c80476e4SDavid E. O'Brien 
796c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
7979ccc37e3SMark Peek     reprintf("\n");
7989ccc37e3SMark Peek     reprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
799c80476e4SDavid E. O'Brien 	    ofd - old, osb - old, ose - old, ols - old, oe - old);
8009ccc37e3SMark Peek     reprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
801c80476e4SDavid E. O'Brien 	    nfd - new, nsb - new, nse - new, nls - new, ne - new);
8029ccc37e3SMark Peek     reprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
8039ccc37e3SMark Peek     reprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
804c80476e4SDavid E. O'Brien     dprintstr("old- oe", old, oe);
805c80476e4SDavid E. O'Brien     dprintstr("new- ne", new, ne);
806c80476e4SDavid E. O'Brien     dprintstr("old-ofd", old, ofd);
807c80476e4SDavid E. O'Brien     dprintstr("new-nfd", new, nfd);
808c80476e4SDavid E. O'Brien     dprintstr("ofd-osb", ofd, osb);
809c80476e4SDavid E. O'Brien     dprintstr("nfd-nsb", nfd, nsb);
810c80476e4SDavid E. O'Brien     dprintstr("osb-ose", osb, ose);
811c80476e4SDavid E. O'Brien     dprintstr("nsb-nse", nsb, nse);
812c80476e4SDavid E. O'Brien     dprintstr("ose-ols", ose, ols);
813c80476e4SDavid E. O'Brien     dprintstr("nse-nls", nse, nls);
814c80476e4SDavid E. O'Brien     dprintstr("ols- oe", ols, oe);
815c80476e4SDavid E. O'Brien     dprintstr("nls- ne", nls, ne);
816c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
817c80476e4SDavid E. O'Brien 
818c80476e4SDavid E. O'Brien     /*
819c80476e4SDavid E. O'Brien      * CursorV to this line cur_line MUST be in this routine so that if we
820c80476e4SDavid E. O'Brien      * don't have to change the line, we don't move to it. CursorH to first
821c80476e4SDavid E. O'Brien      * diff char
822c80476e4SDavid E. O'Brien      */
823c80476e4SDavid E. O'Brien     MoveToLine(cur_line);
824c80476e4SDavid E. O'Brien 
825c80476e4SDavid E. O'Brien     /*
826c80476e4SDavid E. O'Brien      * at this point we have something like this:
827c80476e4SDavid E. O'Brien      *
828c80476e4SDavid E. O'Brien      * /old                  /ofd    /osb               /ose    /ols     /oe
829c80476e4SDavid E. O'Brien      * v.....................v       v..................v       v........v
830c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
831c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
832c80476e4SDavid E. O'Brien      * ^.....................^     ^..................^       ^........^
833c80476e4SDavid E. O'Brien      * \new                  \nfd  \nsb               \nse     \nls    \ne
834c80476e4SDavid E. O'Brien      *
835c80476e4SDavid E. O'Brien      * fx is the difference in length between the the chars between nfd and
836c80476e4SDavid E. O'Brien      * nsb, and the chars between ofd and osb, and is thus the number of
837c80476e4SDavid E. O'Brien      * characters to delete if < 0 (new is shorter than old, as above),
838c80476e4SDavid E. O'Brien      * or insert (new is longer than short).
839c80476e4SDavid E. O'Brien      *
840c80476e4SDavid E. O'Brien      * sx is the same for the second differences.
841c80476e4SDavid E. O'Brien      */
842c80476e4SDavid E. O'Brien 
843c80476e4SDavid E. O'Brien     /*
844c80476e4SDavid E. O'Brien      * if we have a net insert on the first difference, AND inserting the net
845c80476e4SDavid E. O'Brien      * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
846c80476e4SDavid E. O'Brien      * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
847c80476e4SDavid E. O'Brien      * (TermH - 1) else we do the deletes first so that we keep everything we
848c80476e4SDavid E. O'Brien      * need to.
849c80476e4SDavid E. O'Brien      */
850c80476e4SDavid E. O'Brien 
851c80476e4SDavid E. O'Brien     /*
852c80476e4SDavid E. O'Brien      * if the last same is the same like the end, there is no last same part,
853c80476e4SDavid E. O'Brien      * otherwise we want to keep the last same part set p to the last useful
854c80476e4SDavid E. O'Brien      * old character
855c80476e4SDavid E. O'Brien      */
856c80476e4SDavid E. O'Brien     p = (ols != oe) ? oe : ose;
857c80476e4SDavid E. O'Brien 
858c80476e4SDavid E. O'Brien     /*
859c80476e4SDavid E. O'Brien      * if (There is a diffence in the beginning) && (we need to insert
860c80476e4SDavid E. O'Brien      * characters) && (the number of characters to insert is less than the term
861c80476e4SDavid E. O'Brien      * width) We need to do an insert! else if (we need to delete characters)
862c80476e4SDavid E. O'Brien      * We need to delete characters! else No insert or delete
863c80476e4SDavid E. O'Brien      */
864c80476e4SDavid E. O'Brien     if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
865c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8669ccc37e3SMark Peek 	reprintf("first diff insert at %d...\r\n", nfd - new);
867c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
868c80476e4SDavid E. O'Brien 	/*
869c80476e4SDavid E. O'Brien 	 * Move to the first char to insert, where the first diff is.
870c80476e4SDavid E. O'Brien 	 */
871c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
872c80476e4SDavid E. O'Brien 	/*
873c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at end
874c80476e4SDavid E. O'Brien 	 */
875c80476e4SDavid E. O'Brien 	if (nsb != ne) {
876c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8779ccc37e3SMark Peek 	    reprintf("with stuff to keep at end\r\n");
878c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
879c80476e4SDavid E. O'Brien 	    /*
880c80476e4SDavid E. O'Brien 	     * insert fx chars of new starting at nfd
881c80476e4SDavid E. O'Brien 	     */
882c80476e4SDavid E. O'Brien 	    if (fx > 0) {
883c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
884c80476e4SDavid E. O'Brien 		if (!T_CanIns)
8859ccc37e3SMark Peek 		    reprintf("   ERROR: cannot insert in early first diff\n");
886c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
887c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
888c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
889c80476e4SDavid E. O'Brien 	    }
890c80476e4SDavid E. O'Brien 	    /*
891c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
892c80476e4SDavid E. O'Brien 	     */
893c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
894c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
895c80476e4SDavid E. O'Brien 	}
896c80476e4SDavid E. O'Brien 	else {
897c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8989ccc37e3SMark Peek 	    reprintf("without anything to save\r\n");
899c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
900c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
901c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
902c80476e4SDavid E. O'Brien 	    /*
903c80476e4SDavid E. O'Brien 	     * Done
904c80476e4SDavid E. O'Brien 	     */
905c80476e4SDavid E. O'Brien 	    return;
906c80476e4SDavid E. O'Brien 	}
907c80476e4SDavid E. O'Brien     }
908c80476e4SDavid E. O'Brien     else if (fx < 0) {
909c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9109ccc37e3SMark Peek 	reprintf("first diff delete at %d...\r\n", ofd - old);
911c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
912c80476e4SDavid E. O'Brien 	/*
913c80476e4SDavid E. O'Brien 	 * move to the first char to delete where the first diff is
914c80476e4SDavid E. O'Brien 	 */
915c80476e4SDavid E. O'Brien 	MoveToChar(ofd - old);
916c80476e4SDavid E. O'Brien 	/*
917c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
918c80476e4SDavid E. O'Brien 	 */
919c80476e4SDavid E. O'Brien 	if (osb != oe) {
920c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9219ccc37e3SMark Peek 	    reprintf("with stuff to save at end\r\n");
922c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
923c80476e4SDavid E. O'Brien 	    /*
924c80476e4SDavid E. O'Brien 	     * fx is less than zero *always* here but we check for code
925c80476e4SDavid E. O'Brien 	     * symmetry
926c80476e4SDavid E. O'Brien 	     */
927c80476e4SDavid E. O'Brien 	    if (fx < 0) {
928c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
929c80476e4SDavid E. O'Brien 		if (!T_CanDel)
9309ccc37e3SMark Peek 		    reprintf("   ERROR: cannot delete in first diff\n");
931c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
932c80476e4SDavid E. O'Brien 		DeleteChars(-fx);
933c80476e4SDavid E. O'Brien 		str_delete(old, (int) (ofd - old), TermH, -fx);
934c80476e4SDavid E. O'Brien 	    }
935c80476e4SDavid E. O'Brien 	    /*
936c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
937c80476e4SDavid E. O'Brien 	     */
938c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
939c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
940c80476e4SDavid E. O'Brien 
941c80476e4SDavid E. O'Brien 	}
942c80476e4SDavid E. O'Brien 	else {
943c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9449ccc37e3SMark Peek 	    reprintf("but with nothing left to save\r\n");
945c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
946c80476e4SDavid E. O'Brien 	    /*
947c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
948c80476e4SDavid E. O'Brien 	     */
949c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
950c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
9519ccc37e3SMark Peek 	    reprintf("cleareol %d\n", (oe - old) - (ne - new));
952c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
9533b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
954c80476e4SDavid E. O'Brien 	    ClearEOL((oe - old) - (ne - new));
955c80476e4SDavid E. O'Brien #else
956c80476e4SDavid E. O'Brien 	    /*
957c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
958c80476e4SDavid E. O'Brien 	     */
959c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
9603b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
961c80476e4SDavid E. O'Brien 	    /*
962c80476e4SDavid E. O'Brien 	     * Done
963c80476e4SDavid E. O'Brien 	     */
964c80476e4SDavid E. O'Brien 	    return;
965c80476e4SDavid E. O'Brien 	}
966c80476e4SDavid E. O'Brien     }
967c80476e4SDavid E. O'Brien     else
968c80476e4SDavid E. O'Brien 	fx = 0;
969c80476e4SDavid E. O'Brien 
970c80476e4SDavid E. O'Brien     if (sx < 0) {
971c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9729ccc37e3SMark Peek 	reprintf("second diff delete at %d...\r\n", (ose - old) + fx);
973c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
974c80476e4SDavid E. O'Brien 	/*
975c80476e4SDavid E. O'Brien 	 * Check if we have stuff to delete
976c80476e4SDavid E. O'Brien 	 */
977c80476e4SDavid E. O'Brien 	/*
978c80476e4SDavid E. O'Brien 	 * fx is the number of characters inserted (+) or deleted (-)
979c80476e4SDavid E. O'Brien 	 */
980c80476e4SDavid E. O'Brien 
981c80476e4SDavid E. O'Brien 	MoveToChar((ose - old) + fx);
982c80476e4SDavid E. O'Brien 	/*
983c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
984c80476e4SDavid E. O'Brien 	 */
985c80476e4SDavid E. O'Brien 	if (ols != oe) {
986c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9879ccc37e3SMark Peek 	    reprintf("with stuff to save at end\r\n");
988c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
989c80476e4SDavid E. O'Brien 	    /*
990c80476e4SDavid E. O'Brien 	     * Again a duplicate test.
991c80476e4SDavid E. O'Brien 	     */
992c80476e4SDavid E. O'Brien 	    if (sx < 0) {
993c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
994c80476e4SDavid E. O'Brien 		if (!T_CanDel)
9959ccc37e3SMark Peek 		    reprintf("   ERROR: cannot delete in second diff\n");
996c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
997c80476e4SDavid E. O'Brien 		DeleteChars(-sx);
998c80476e4SDavid E. O'Brien 	    }
999c80476e4SDavid E. O'Brien 
1000c80476e4SDavid E. O'Brien 	    /*
1001c80476e4SDavid E. O'Brien 	     * write (nls-nse) chars of new starting at nse
1002c80476e4SDavid E. O'Brien 	     */
1003c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1004c80476e4SDavid E. O'Brien 	}
1005c80476e4SDavid E. O'Brien 	else {
1006c80476e4SDavid E. O'Brien 	    int olen = (int) (oe - old + fx);
1007c80476e4SDavid E. O'Brien 	    if (olen > TermH)
1008c80476e4SDavid E. O'Brien 		olen = TermH;
1009c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10109ccc37e3SMark Peek 	    reprintf("but with nothing left to save\r\n");
1011c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1012c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1013c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
10149ccc37e3SMark Peek 	    reprintf("cleareol %d\n", olen - (ne - new));
1015c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
10163b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
1017c80476e4SDavid E. O'Brien 	    ClearEOL(olen - (ne - new));
1018c80476e4SDavid E. O'Brien #else
1019c80476e4SDavid E. O'Brien 	    /*
1020c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
1021c80476e4SDavid E. O'Brien 	     */
1022c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
10233b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
1024c80476e4SDavid E. O'Brien 	}
1025c80476e4SDavid E. O'Brien     }
1026c80476e4SDavid E. O'Brien 
1027c80476e4SDavid E. O'Brien     /*
1028c80476e4SDavid E. O'Brien      * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
1029c80476e4SDavid E. O'Brien      */
1030c80476e4SDavid E. O'Brien     if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
1031c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10329ccc37e3SMark Peek 	reprintf("late first diff insert at %d...\r\n", nfd - new);
1033c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1034c80476e4SDavid E. O'Brien 
1035c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
1036c80476e4SDavid E. O'Brien 	/*
1037c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at the end
1038c80476e4SDavid E. O'Brien 	 */
1039c80476e4SDavid E. O'Brien 	if (nsb != ne) {
1040c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10419ccc37e3SMark Peek 	    reprintf("with stuff to keep at end\r\n");
1042c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1043c80476e4SDavid E. O'Brien 	    /*
1044c80476e4SDavid E. O'Brien 	     * We have to recalculate fx here because we set it
1045c80476e4SDavid E. O'Brien 	     * to zero above as a flag saying that we hadn't done
1046c80476e4SDavid E. O'Brien 	     * an early first insert.
1047c80476e4SDavid E. O'Brien 	     */
1048c80476e4SDavid E. O'Brien 	    fx = (int) ((nsb - nfd) - (osb - ofd));
1049c80476e4SDavid E. O'Brien 	    if (fx > 0) {
1050c80476e4SDavid E. O'Brien 		/*
1051c80476e4SDavid E. O'Brien 		 * insert fx chars of new starting at nfd
1052c80476e4SDavid E. O'Brien 		 */
1053c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1054c80476e4SDavid E. O'Brien 		if (!T_CanIns)
10559ccc37e3SMark Peek 		    reprintf("   ERROR: cannot insert in late first diff\n");
1056c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1057c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
1058c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1059c80476e4SDavid E. O'Brien 	    }
1060c80476e4SDavid E. O'Brien 
1061c80476e4SDavid E. O'Brien 	    /*
1062c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1063c80476e4SDavid E. O'Brien 	     */
1064c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
1065c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1066c80476e4SDavid E. O'Brien 	}
1067c80476e4SDavid E. O'Brien 	else {
1068c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10699ccc37e3SMark Peek 	    reprintf("without anything to save\r\n");
1070c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1071c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
1072c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
1073c80476e4SDavid E. O'Brien 	}
1074c80476e4SDavid E. O'Brien     }
1075c80476e4SDavid E. O'Brien 
1076c80476e4SDavid E. O'Brien     /*
1077c80476e4SDavid E. O'Brien      * line is now NEW up to nse
1078c80476e4SDavid E. O'Brien      */
1079c80476e4SDavid E. O'Brien     if (sx >= 0) {
1080c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10819ccc37e3SMark Peek 	reprintf("second diff insert at %d...\r\n", nse - new);
1082c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1083c80476e4SDavid E. O'Brien 	MoveToChar(nse - new);
1084c80476e4SDavid E. O'Brien 	if (ols != oe) {
1085c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10869ccc37e3SMark Peek 	    reprintf("with stuff to keep at end\r\n");
1087c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1088c80476e4SDavid E. O'Brien 	    if (sx > 0) {
1089c80476e4SDavid E. O'Brien 		/* insert sx chars of new starting at nse */
1090c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1091c80476e4SDavid E. O'Brien 		if (!T_CanIns)
10929ccc37e3SMark Peek 		    reprintf("   ERROR: cannot insert in second diff\n");
1093c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1094c80476e4SDavid E. O'Brien 		Insert_write(nse, sx);
1095c80476e4SDavid E. O'Brien 	    }
1096c80476e4SDavid E. O'Brien 
1097c80476e4SDavid E. O'Brien 	    /*
1098c80476e4SDavid E. O'Brien 	     * write (nls-nse) - sx chars of new starting at (nse + sx)
1099c80476e4SDavid E. O'Brien 	     */
1100c80476e4SDavid E. O'Brien 	    so_write(nse + sx, (nls - nse) - sx);
1101c80476e4SDavid E. O'Brien 	}
1102c80476e4SDavid E. O'Brien 	else {
1103c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
11049ccc37e3SMark Peek 	    reprintf("without anything to save\r\n");
1105c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1106c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1107c80476e4SDavid E. O'Brien 
1108c80476e4SDavid E. O'Brien 	    /*
1109c80476e4SDavid E. O'Brien              * No need to do a clear-to-end here because we were doing
1110c80476e4SDavid E. O'Brien 	     * a second insert, so we will have over written all of the
1111c80476e4SDavid E. O'Brien 	     * old string.
1112c80476e4SDavid E. O'Brien 	     */
1113c80476e4SDavid E. O'Brien 	}
1114c80476e4SDavid E. O'Brien     }
1115c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
11169ccc37e3SMark Peek     reprintf("done.\r\n");
1117c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1118c80476e4SDavid E. O'Brien }
1119c80476e4SDavid E. O'Brien 
1120c80476e4SDavid E. O'Brien 
1121c80476e4SDavid E. O'Brien static void
cpy_pad_spaces(Char * dst,Char * src,int width)112245e5710bSMark Peek cpy_pad_spaces(Char *dst, Char *src, int width)
1123c80476e4SDavid E. O'Brien {
112423338178SMark Peek     int i;
1125c80476e4SDavid E. O'Brien 
1126c80476e4SDavid E. O'Brien     for (i = 0; i < width; i++) {
1127c80476e4SDavid E. O'Brien 	if (*src == (Char) 0)
1128c80476e4SDavid E. O'Brien 	    break;
1129c80476e4SDavid E. O'Brien 	*dst++ = *src++;
1130c80476e4SDavid E. O'Brien     }
1131c80476e4SDavid E. O'Brien 
1132c80476e4SDavid E. O'Brien     while (i < width) {
1133c80476e4SDavid E. O'Brien 	*dst++ = ' ';
1134c80476e4SDavid E. O'Brien 	i++;
1135c80476e4SDavid E. O'Brien     }
1136c80476e4SDavid E. O'Brien     *dst = (Char) 0;
1137c80476e4SDavid E. O'Brien }
1138c80476e4SDavid E. O'Brien 
1139c80476e4SDavid E. O'Brien void
RefCursor(void)114045e5710bSMark Peek RefCursor(void)
1141c80476e4SDavid E. O'Brien {				/* only move to new cursor pos */
114223338178SMark Peek     Char *cp;
114345e5710bSMark Peek     int w, h, th, v;
1144c80476e4SDavid E. O'Brien 
1145c80476e4SDavid E. O'Brien     /* first we must find where the cursor is... */
1146c80476e4SDavid E. O'Brien     h = 0;
1147c80476e4SDavid E. O'Brien     v = 0;
1148c80476e4SDavid E. O'Brien     th = TermH;			/* optimize for speed */
1149c80476e4SDavid E. O'Brien 
115045e5710bSMark Peek     for (cp = Prompt; cp != NULL && *cp; ) {	/* do prompt */
115123338178SMark Peek 	if (*cp & LITERAL) {
115223338178SMark Peek 	    cp++;
1153c80476e4SDavid E. O'Brien 	    continue;
115423338178SMark Peek 	}
1155*19d2e3deSDmitry Chagin 	w = NLSClassify(*cp & CHAR, cp == Prompt, 0);
115645e5710bSMark Peek 	cp++;
115723338178SMark Peek 	switch(w) {
115823338178SMark Peek 	    case NLSCLASS_NL:
1159c80476e4SDavid E. O'Brien 		h = 0;
1160c80476e4SDavid E. O'Brien 		v++;
116123338178SMark Peek 		break;
116223338178SMark Peek 	    case NLSCLASS_TAB:
116323338178SMark Peek 		while (++h & 07)
116423338178SMark Peek 		    ;
116523338178SMark Peek 		break;
116623338178SMark Peek 	    case NLSCLASS_CTRL:
116723338178SMark Peek 		h += 2;
116823338178SMark Peek 		break;
116923338178SMark Peek 	    case NLSCLASS_ILLEGAL:
117023338178SMark Peek 		h += 4;
117123338178SMark Peek 		break;
117223338178SMark Peek 	    case NLSCLASS_ILLEGAL2:
117323338178SMark Peek 	    case NLSCLASS_ILLEGAL3:
117423338178SMark Peek 	    case NLSCLASS_ILLEGAL4:
117523338178SMark Peek 		h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
117623338178SMark Peek 		break;
117723338178SMark Peek 	    default:
117823338178SMark Peek 		h += w;
1179c80476e4SDavid E. O'Brien 	}
1180c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
118123338178SMark Peek 	    h -= th;
118223338178SMark Peek 	    v++;
118323338178SMark Peek 	}
118423338178SMark Peek     }
118523338178SMark Peek 
118623338178SMark Peek     for (cp = InputBuf; cp < Cursor;) {	/* do input buffer to Cursor */
1187*19d2e3deSDmitry Chagin 	w = NLSClassify(*cp & CHAR, cp == InputBuf, 0);
118845e5710bSMark Peek 	cp++;
118923338178SMark Peek 	switch(w) {
119023338178SMark Peek 	    case NLSCLASS_NL:
1191c80476e4SDavid E. O'Brien 		h = 0;
1192c80476e4SDavid E. O'Brien 		v++;
119323338178SMark Peek 		break;
119423338178SMark Peek 	    case NLSCLASS_TAB:
119523338178SMark Peek 		while (++h & 07)
119623338178SMark Peek 		    ;
119723338178SMark Peek 		break;
119823338178SMark Peek 	    case NLSCLASS_CTRL:
119923338178SMark Peek 		h += 2;
120023338178SMark Peek 		break;
120123338178SMark Peek 	    case NLSCLASS_ILLEGAL:
120223338178SMark Peek 		h += 4;
120323338178SMark Peek 		break;
120423338178SMark Peek 	    case NLSCLASS_ILLEGAL2:
120523338178SMark Peek 	    case NLSCLASS_ILLEGAL3:
120623338178SMark Peek 	    case NLSCLASS_ILLEGAL4:
120723338178SMark Peek 		h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
120823338178SMark Peek 		break;
120923338178SMark Peek 	    default:
121023338178SMark Peek 		h += w;
1211c80476e4SDavid E. O'Brien 	}
1212c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
121323338178SMark Peek 	    h -= th;
1214c80476e4SDavid E. O'Brien 	    v++;
1215c80476e4SDavid E. O'Brien 	}
1216c80476e4SDavid E. O'Brien     }
1217c80476e4SDavid E. O'Brien 
1218c80476e4SDavid E. O'Brien     /* now go there */
1219c80476e4SDavid E. O'Brien     MoveToLine(v);
1220c80476e4SDavid E. O'Brien     MoveToChar(h);
122145e5710bSMark Peek     if (adrof(STRhighlight) && MarkIsSet) {
122245e5710bSMark Peek 	ClearLines();
122345e5710bSMark Peek 	ClearDisp();
122445e5710bSMark Peek 	Refresh();
122545e5710bSMark Peek     }
1226c80476e4SDavid E. O'Brien     flush();
1227c80476e4SDavid E. O'Brien }
1228c80476e4SDavid E. O'Brien 
1229b2d5d167SMark Peek #ifndef WINTT_NATIVE
1230c80476e4SDavid E. O'Brien static void
PutPlusOne(Char c,int width)123145e5710bSMark Peek PutPlusOne(Char c, int width)
1232c80476e4SDavid E. O'Brien {
123323338178SMark Peek     while (width > 1 && CursorH + width > TermH)
123423338178SMark Peek 	PutPlusOne(' ', 1);
123523338178SMark Peek     if ((c & LITERAL) != 0) {
123623338178SMark Peek 	Char *d;
123723338178SMark Peek 	for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++)
123823338178SMark Peek 	    (void) putwraw(*d);
123923338178SMark Peek     } else {
124023338178SMark Peek 	(void) putwraw(c);
124123338178SMark Peek     }
1242c80476e4SDavid E. O'Brien     Display[CursorV][CursorH++] = (Char) c;
124323338178SMark Peek     while (--width > 0)
124423338178SMark Peek 	Display[CursorV][CursorH++] = CHAR_DBWIDTH;
1245c80476e4SDavid E. O'Brien     if (CursorH >= TermH) {	/* if we must overflow */
1246c80476e4SDavid E. O'Brien 	CursorH = 0;
1247c80476e4SDavid E. O'Brien 	CursorV++;
1248c80476e4SDavid E. O'Brien 	OldvcV++;
1249c80476e4SDavid E. O'Brien 	if (T_Margin & MARGIN_AUTO) {
1250c80476e4SDavid E. O'Brien 	    if (T_Margin & MARGIN_MAGIC) {
1251c80476e4SDavid E. O'Brien 		(void) putraw(' ');
1252c80476e4SDavid E. O'Brien 		(void) putraw('\b');
1253c80476e4SDavid E. O'Brien 	    }
1254c80476e4SDavid E. O'Brien 	}
1255c80476e4SDavid E. O'Brien 	else {
1256c80476e4SDavid E. O'Brien 	    (void) putraw('\r');
1257c80476e4SDavid E. O'Brien 	    (void) putraw('\n');
1258c80476e4SDavid E. O'Brien 	}
1259c80476e4SDavid E. O'Brien     }
1260c80476e4SDavid E. O'Brien }
1261b2d5d167SMark Peek #endif
1262c80476e4SDavid E. O'Brien 
1263c80476e4SDavid E. O'Brien void
RefPlusOne(int l)126423338178SMark Peek RefPlusOne(int l)
1265c80476e4SDavid E. O'Brien {				/* we added just one char, handle it fast.
1266c80476e4SDavid E. O'Brien 				 * assumes that screen cursor == real cursor */
126745e5710bSMark Peek     Char *cp, c;
126823338178SMark Peek     int w;
1269c80476e4SDavid E. O'Brien 
127023338178SMark Peek     if (Cursor != LastChar) {
1271c80476e4SDavid E. O'Brien 	Refresh();		/* too hard to handle */
1272c80476e4SDavid E. O'Brien 	return;
1273c80476e4SDavid E. O'Brien     }
1274c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1275c80476e4SDavid E. O'Brien 	Refresh();		/* clear out rprompt if less than one char gap*/
1276c80476e4SDavid E. O'Brien 	return;
127723338178SMark Peek     }
127823338178SMark Peek     cp = Cursor - l;
127945e5710bSMark Peek     c = *cp & CHAR;
1280*19d2e3deSDmitry Chagin     w = NLSClassify(c, cp == InputBuf, 0);
128123338178SMark Peek     switch(w) {
128223338178SMark Peek 	case NLSCLASS_CTRL:
128323338178SMark Peek 	    PutPlusOne('^', 1);
128423338178SMark Peek 	    if (c == CTL_ESC('\177')) {
128523338178SMark Peek 		PutPlusOne('?', 1);
128623338178SMark Peek 		break;
128723338178SMark Peek 	    }
12883b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
128923338178SMark Peek 	    /* uncontrolify it; works only for iso8859-1 like sets */
129023338178SMark Peek 	    PutPlusOne((c | 0100), 1);
12913b6eaa7bSAndrey A. Chernov #else
129223338178SMark Peek 	    PutPlusOne(_toebcdic[_toascii[c]|0100], 1);
129323338178SMark Peek #endif
129423338178SMark Peek 	    break;
129523338178SMark Peek 	case NLSCLASS_ILLEGAL:
129623338178SMark Peek 	    PutPlusOne('\\', 1);
129723338178SMark Peek 	    PutPlusOne(((c >> 6) & 7) + '0', 1);
129823338178SMark Peek 	    PutPlusOne(((c >> 3) & 7) + '0', 1);
129923338178SMark Peek 	    PutPlusOne((c & 7) + '0', 1);
130023338178SMark Peek 	    break;
130123338178SMark Peek 	case 1:
130245e5710bSMark Peek 	    if (adrof(STRhighlight) && MarkIsSet)
130345e5710bSMark Peek 		StartHighlight();
130423338178SMark Peek 	    if (l > 1)
130523338178SMark Peek 		PutPlusOne(MakeLiteral(cp, l, 0), 1);
1306c80476e4SDavid E. O'Brien 	    else
130723338178SMark Peek 		PutPlusOne(*cp, 1);
130845e5710bSMark Peek 	    if (adrof(STRhighlight) && MarkIsSet)
130945e5710bSMark Peek 		StopHighlight();
131023338178SMark Peek 	    break;
131123338178SMark Peek 	default:
131223338178SMark Peek 	    Refresh();		/* too hard to handle */
131323338178SMark Peek 	    return;
1314c80476e4SDavid E. O'Brien     }
1315c80476e4SDavid E. O'Brien     flush();
1316c80476e4SDavid E. O'Brien }
1317c80476e4SDavid E. O'Brien 
1318c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */
1319c80476e4SDavid E. O'Brien 
1320c80476e4SDavid E. O'Brien void
ClearDisp(void)132145e5710bSMark Peek ClearDisp(void)
1322c80476e4SDavid E. O'Brien {
132323338178SMark Peek     int i;
1324c80476e4SDavid E. O'Brien 
1325c80476e4SDavid E. O'Brien     CursorV = 0;		/* clear the display buffer */
1326c80476e4SDavid E. O'Brien     CursorH = 0;
1327c80476e4SDavid E. O'Brien     for (i = 0; i < TermV; i++)
1328*19d2e3deSDmitry Chagin 	(void) memset(Display[i], 0, (TermH + 1) * sizeof(Display[0][0]));
1329c80476e4SDavid E. O'Brien     OldvcV = 0;
133023338178SMark Peek     litlen = 0;
1331c80476e4SDavid E. O'Brien }
1332c80476e4SDavid E. O'Brien 
1333c80476e4SDavid E. O'Brien void
ClearLines(void)133445e5710bSMark Peek ClearLines(void)
1335c80476e4SDavid E. O'Brien {				/* Make sure all lines are *really* blank */
133623338178SMark Peek     int i;
1337c80476e4SDavid E. O'Brien 
1338c80476e4SDavid E. O'Brien     if (T_CanCEOL) {
1339c80476e4SDavid E. O'Brien 	/*
1340c80476e4SDavid E. O'Brien 	 * Clear the lines from the bottom up so that if we try moving
1341c80476e4SDavid E. O'Brien 	 * the cursor down by writing the character that is at the end
1342c80476e4SDavid E. O'Brien 	 * of the screen line, we won't rewrite a character that shouldn't
1343c80476e4SDavid E. O'Brien 	 * be there.
1344c80476e4SDavid E. O'Brien 	 */
1345c80476e4SDavid E. O'Brien 	for (i = OldvcV; i >= 0; i--) {	/* for each line on the screen */
1346c80476e4SDavid E. O'Brien 	    MoveToLine(i);
1347c80476e4SDavid E. O'Brien 	    MoveToChar(0);
1348c80476e4SDavid E. O'Brien 	    ClearEOL(TermH);
1349c80476e4SDavid E. O'Brien 	}
1350c80476e4SDavid E. O'Brien     }
1351c80476e4SDavid E. O'Brien     else {
1352c80476e4SDavid E. O'Brien 	MoveToLine(OldvcV);	/* go to last line */
1353c80476e4SDavid E. O'Brien 	(void) putraw('\r');	/* go to BOL */
1354c80476e4SDavid E. O'Brien 	(void) putraw('\n');	/* go to new line */
1355c80476e4SDavid E. O'Brien     }
1356c80476e4SDavid E. O'Brien }
1357