xref: /freebsd/contrib/tcsh/ed.refresh.c (revision c80476e4c3e6730697b9424f88dfa74d1907cabd)
1c80476e4SDavid E. O'Brien /* $Header: /src/pub/tcsh/ed.refresh.c,v 3.25 1998/11/24 18:17:22 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.
17c80476e4SDavid E. O'Brien  * 3. All advertising materials mentioning features or use of this software
18c80476e4SDavid E. O'Brien  *    must display the following acknowledgement:
19c80476e4SDavid E. O'Brien  *	This product includes software developed by the University of
20c80476e4SDavid E. O'Brien  *	California, Berkeley and its contributors.
21c80476e4SDavid E. O'Brien  * 4. Neither the name of the University nor the names of its contributors
22c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
23c80476e4SDavid E. O'Brien  *    without specific prior written permission.
24c80476e4SDavid E. O'Brien  *
25c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
36c80476e4SDavid E. O'Brien  */
37c80476e4SDavid E. O'Brien #include "sh.h"
38c80476e4SDavid E. O'Brien 
39c80476e4SDavid E. O'Brien RCSID("$Id: ed.refresh.c,v 3.25 1998/11/24 18:17:22 christos Exp $")
40c80476e4SDavid E. O'Brien 
41c80476e4SDavid E. O'Brien #include "ed.h"
42c80476e4SDavid E. O'Brien /* #define DEBUG_UPDATE */
43c80476e4SDavid E. O'Brien /* #define DEBUG_REFRESH */
44c80476e4SDavid E. O'Brien /* #define DEBUG_LITERAL */
45c80476e4SDavid E. O'Brien 
46c80476e4SDavid E. O'Brien /* refresh.c -- refresh the current set of lines on the screen */
47c80476e4SDavid E. O'Brien 
48c80476e4SDavid E. O'Brien Char   *litptr[256];
49c80476e4SDavid E. O'Brien static int vcursor_h, vcursor_v;
50c80476e4SDavid E. O'Brien static int rprompt_h, rprompt_v;
51c80476e4SDavid E. O'Brien 
52c80476e4SDavid E. O'Brien static	void	Draw 			__P((int));
53c80476e4SDavid E. O'Brien static	void	Vdraw 			__P((int));
54c80476e4SDavid E. O'Brien static	void	RefreshPromptpart	__P((Char *));
55c80476e4SDavid E. O'Brien static	void	update_line 		__P((Char *, Char *, int));
56c80476e4SDavid E. O'Brien static	void	str_insert		__P((Char *, int, int, Char *, int));
57c80476e4SDavid E. O'Brien static	void	str_delete		__P((Char *, int, int, int));
58c80476e4SDavid E. O'Brien static	void	str_cp			__P((Char *, Char *, int));
59c80476e4SDavid E. O'Brien static	void	PutPlusOne		__P((int));
60c80476e4SDavid E. O'Brien static	void	cpy_pad_spaces		__P((Char *, Char *, int));
61c80476e4SDavid E. O'Brien #if defined(DSPMBYTE)
62c80476e4SDavid E. O'Brien static	Char 	*update_line_fix_mbyte_point __P((Char *, Char *, int));
63c80476e4SDavid E. O'Brien #endif
64c80476e4SDavid E. O'Brien #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
65c80476e4SDavid E. O'Brien static	void	dprintf			__P((char *, ...));
66c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
67c80476e4SDavid E. O'Brien static	void	dprintstr		__P((char *, Char *, Char *));
68c80476e4SDavid E. O'Brien 
69c80476e4SDavid E. O'Brien static void
70c80476e4SDavid E. O'Brien dprintstr(str, f, t)
71c80476e4SDavid E. O'Brien char *str;
72c80476e4SDavid E. O'Brien Char *f, *t;
73c80476e4SDavid E. O'Brien {
74c80476e4SDavid E. O'Brien     dprintf("%s:\"", str);
75c80476e4SDavid E. O'Brien     while (f < t)
76c80476e4SDavid E. O'Brien 	dprintf("%c", *f++ & ASCII);
77c80476e4SDavid E. O'Brien     dprintf("\"\r\n");
78c80476e4SDavid E. O'Brien }
79c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
80c80476e4SDavid E. O'Brien 
81c80476e4SDavid E. O'Brien /* dprintf():
82c80476e4SDavid E. O'Brien  *	Print to $DEBUGTTY, so that we can test editing on one pty, and
83c80476e4SDavid E. O'Brien  *      print debugging stuff on another. Don't interrupt the shell while
84c80476e4SDavid E. O'Brien  *	debugging cause you'll mangle up the file descriptors!
85c80476e4SDavid E. O'Brien  */
86c80476e4SDavid E. O'Brien static void
87c80476e4SDavid E. O'Brien #ifdef FUNCPROTO
88c80476e4SDavid E. O'Brien dprintf(char *fmt, ...)
89c80476e4SDavid E. O'Brien #else
90c80476e4SDavid E. O'Brien dprintf(va_list)
91c80476e4SDavid E. O'Brien     va_dcl
92c80476e4SDavid E. O'Brien #endif /* __STDC__ */
93c80476e4SDavid E. O'Brien {
94c80476e4SDavid E. O'Brien     static int fd = -1;
95c80476e4SDavid E. O'Brien     char *dtty;
96c80476e4SDavid E. O'Brien 
97c80476e4SDavid E. O'Brien     if ((dtty = getenv("DEBUGTTY"))) {
98c80476e4SDavid E. O'Brien 	int o;
99c80476e4SDavid E. O'Brien 	va_list va;
100c80476e4SDavid E. O'Brien #ifdef FUNCPROTO
101c80476e4SDavid E. O'Brien 	va_start(va, fmt);
102c80476e4SDavid E. O'Brien #else
103c80476e4SDavid E. O'Brien 	char *fmt;
104c80476e4SDavid E. O'Brien 	va_start(va);
105c80476e4SDavid E. O'Brien 	fmt = va_arg(va, char *);
106c80476e4SDavid E. O'Brien #endif /* __STDC__ */
107c80476e4SDavid E. O'Brien 
108c80476e4SDavid E. O'Brien 	if (fd == -1)
109c80476e4SDavid E. O'Brien 	    fd = open(dtty, O_RDWR);
110c80476e4SDavid E. O'Brien 	o = SHOUT;
111c80476e4SDavid E. O'Brien 	flush();
112c80476e4SDavid E. O'Brien 	SHOUT = fd;
113c80476e4SDavid E. O'Brien 	xvprintf(fmt, va);
114c80476e4SDavid E. O'Brien 	va_end(va);
115c80476e4SDavid E. O'Brien 	flush();
116c80476e4SDavid E. O'Brien 	SHOUT = o;
117c80476e4SDavid E. O'Brien     }
118c80476e4SDavid E. O'Brien }
119c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
120c80476e4SDavid E. O'Brien 
121c80476e4SDavid E. O'Brien static void
122c80476e4SDavid E. O'Brien Draw(c)				/* draw c, expand tabs, ctl chars */
123c80476e4SDavid E. O'Brien     register int c;
124c80476e4SDavid E. O'Brien {
125c80476e4SDavid E. O'Brien     register Char ch = c & CHAR;
126c80476e4SDavid E. O'Brien 
127c80476e4SDavid E. O'Brien     if (Isprint(ch)) {
128c80476e4SDavid E. O'Brien 	Vdraw(c);
129c80476e4SDavid E. O'Brien 	return;
130c80476e4SDavid E. O'Brien     }
131c80476e4SDavid E. O'Brien     /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
132c80476e4SDavid E. O'Brien     if (ch == '\n') {		/* expand the newline	 */
133c80476e4SDavid E. O'Brien 	/*
134c80476e4SDavid E. O'Brien 	 * Don't force a newline if Vdraw does it (i.e. we're at end of line)
135c80476e4SDavid E. O'Brien 	 * - or we will get two newlines and possibly garbage in between
136c80476e4SDavid E. O'Brien 	 */
137c80476e4SDavid E. O'Brien 	int oldv = vcursor_v;
138c80476e4SDavid E. O'Brien 
139c80476e4SDavid E. O'Brien 	Vdraw('\0');		/* assure end of line	 */
140c80476e4SDavid E. O'Brien 	if (oldv == vcursor_v) {
141c80476e4SDavid E. O'Brien 	    vcursor_h = 0;	/* reset cursor pos	 */
142c80476e4SDavid E. O'Brien 	    vcursor_v++;
143c80476e4SDavid E. O'Brien 	}
144c80476e4SDavid E. O'Brien 	return;
145c80476e4SDavid E. O'Brien     }
146c80476e4SDavid E. O'Brien     if (ch == '\t') {		/* expand the tab 	 */
147c80476e4SDavid E. O'Brien 	for (;;) {
148c80476e4SDavid E. O'Brien 	    Vdraw(' ');
149c80476e4SDavid E. O'Brien 	    if ((vcursor_h & 07) == 0)
150c80476e4SDavid E. O'Brien 		break;		/* go until tab stop	 */
151c80476e4SDavid E. O'Brien 	}
152c80476e4SDavid E. O'Brien     }
153c80476e4SDavid E. O'Brien     else if (Iscntrl(ch)) {
154c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX
155c80476e4SDavid E. O'Brien 	Vdraw('^');
156c80476e4SDavid E. O'Brien 	if (ch == CTL_ESC('\177')) {
157c80476e4SDavid E. O'Brien 	    Vdraw('?');
158c80476e4SDavid E. O'Brien 	}
159c80476e4SDavid E. O'Brien 	else {
160c80476e4SDavid E. O'Brien 	    /* uncontrolify it; works only for iso8859-1 like sets */
161c80476e4SDavid E. O'Brien 	    Vdraw((c | 0100));
162c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/
163c80476e4SDavid E. O'Brien 	if (ch == CTL_ESC('\177')) {
164c80476e4SDavid E. O'Brien 	    Vdraw('^');
165c80476e4SDavid E. O'Brien 	    Vdraw('?');
166c80476e4SDavid E. O'Brien 	}
167c80476e4SDavid E. O'Brien 	else {
168c80476e4SDavid E. O'Brien 	    if (Isupper(_toebcdic[_toascii[c]|0100])
169c80476e4SDavid E. O'Brien 		|| strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
170c80476e4SDavid E. O'Brien 	    {
171c80476e4SDavid E. O'Brien 		Vdraw('^');
172c80476e4SDavid E. O'Brien 		Vdraw(_toebcdic[_toascii[c]|0100]);
173c80476e4SDavid E. O'Brien 	    }
174c80476e4SDavid E. O'Brien 	    else
175c80476e4SDavid E. O'Brien 	    {
176c80476e4SDavid E. O'Brien 		Vdraw('\\');
177c80476e4SDavid E. O'Brien 		Vdraw(((c >> 6) & 7) + '0');
178c80476e4SDavid E. O'Brien 		Vdraw(((c >> 3) & 7) + '0');
179c80476e4SDavid E. O'Brien 		Vdraw((c & 7) + '0');
180c80476e4SDavid E. O'Brien 	    }
181c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/
182c80476e4SDavid E. O'Brien 	}
183c80476e4SDavid E. O'Brien     }
184c80476e4SDavid E. O'Brien #ifdef KANJI
185c80476e4SDavid E. O'Brien     else if (!adrof(STRnokanji)) {
186c80476e4SDavid E. O'Brien 	Vdraw(c);
187c80476e4SDavid E. O'Brien 	return;
188c80476e4SDavid E. O'Brien     }
189c80476e4SDavid E. O'Brien #endif
190c80476e4SDavid E. O'Brien     else {
191c80476e4SDavid E. O'Brien 	Vdraw('\\');
192c80476e4SDavid E. O'Brien 	Vdraw(((c >> 6) & 7) + '0');
193c80476e4SDavid E. O'Brien 	Vdraw(((c >> 3) & 7) + '0');
194c80476e4SDavid E. O'Brien 	Vdraw((c & 7) + '0');
195c80476e4SDavid E. O'Brien     }
196c80476e4SDavid E. O'Brien }
197c80476e4SDavid E. O'Brien 
198c80476e4SDavid E. O'Brien static void
199c80476e4SDavid E. O'Brien Vdraw(c)			/* draw char c onto V lines */
200c80476e4SDavid E. O'Brien     register int c;
201c80476e4SDavid E. O'Brien {
202c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
203c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS
204c80476e4SDavid E. O'Brien     dprintf("Vdrawing %6.6o '%c'\r\n", c, c & ASCII);
205c80476e4SDavid E. O'Brien # else
206c80476e4SDavid E. O'Brien     dprintf("Vdrawing %3.3o '%c'\r\n", c, c);
207c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */
208c80476e4SDavid E. O'Brien #endif  /* DEBUG_REFRESH */
209c80476e4SDavid E. O'Brien 
210c80476e4SDavid E. O'Brien     Vdisplay[vcursor_v][vcursor_h] = (Char) c;
211c80476e4SDavid E. O'Brien     vcursor_h++;		/* advance to next place */
212c80476e4SDavid E. O'Brien     if (vcursor_h >= TermH) {
213c80476e4SDavid E. O'Brien 	Vdisplay[vcursor_v][TermH] = '\0';	/* assure end of line */
214c80476e4SDavid E. O'Brien 	vcursor_h = 0;		/* reset it. */
215c80476e4SDavid E. O'Brien 	vcursor_v++;
216c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
217c80476e4SDavid E. O'Brien 	if (vcursor_v >= TermV) {	/* should NEVER happen. */
218c80476e4SDavid E. O'Brien 	    dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
219c80476e4SDavid E. O'Brien 		    vcursor_v, TermV);
220c80476e4SDavid E. O'Brien 	    abort();
221c80476e4SDavid E. O'Brien 	}
222c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
223c80476e4SDavid E. O'Brien     }
224c80476e4SDavid E. O'Brien }
225c80476e4SDavid E. O'Brien 
226c80476e4SDavid E. O'Brien /*
227c80476e4SDavid E. O'Brien  *  RefreshPromptpart()
228c80476e4SDavid E. O'Brien  *	draws a prompt element, expanding literals (we know it's ASCIZ)
229c80476e4SDavid E. O'Brien  */
230c80476e4SDavid E. O'Brien static void
231c80476e4SDavid E. O'Brien RefreshPromptpart(buf)
232c80476e4SDavid E. O'Brien     Char *buf;
233c80476e4SDavid E. O'Brien {
234c80476e4SDavid E. O'Brien     register Char *cp;
235c80476e4SDavid E. O'Brien     static unsigned int litnum = 0;
236c80476e4SDavid E. O'Brien     if (buf == NULL)
237c80476e4SDavid E. O'Brien     {
238c80476e4SDavid E. O'Brien       litnum = 0;
239c80476e4SDavid E. O'Brien       return;
240c80476e4SDavid E. O'Brien     }
241c80476e4SDavid E. O'Brien 
242c80476e4SDavid E. O'Brien     for (cp = buf; *cp; cp++) {
243c80476e4SDavid E. O'Brien 	if (*cp & LITERAL) {
244c80476e4SDavid E. O'Brien 	    if (litnum < (sizeof(litptr) / sizeof(litptr[0]))) {
245c80476e4SDavid E. O'Brien 		litptr[litnum] = cp;
246c80476e4SDavid E. O'Brien #ifdef DEBUG_LITERAL
247c80476e4SDavid E. O'Brien 		dprintf("litnum = %d, litptr = %x:\r\n",
248c80476e4SDavid E. O'Brien 			litnum, litptr[litnum]);
249c80476e4SDavid E. O'Brien #endif /* DEBUG_LITERAL */
250c80476e4SDavid E. O'Brien 	    }
251c80476e4SDavid E. O'Brien 	    while (*cp & LITERAL)
252c80476e4SDavid E. O'Brien 		cp++;
253c80476e4SDavid E. O'Brien 	    if (*cp)
254c80476e4SDavid E. O'Brien 		Vdraw((int) (litnum++ | LITERAL));
255c80476e4SDavid E. O'Brien 	    else {
256c80476e4SDavid E. O'Brien 		/*
257c80476e4SDavid E. O'Brien 		 * XXX: This is a bug, we lose the last literal, if it is not
258c80476e4SDavid E. O'Brien 		 * followed by a normal character, but it is too hard to fix
259c80476e4SDavid E. O'Brien 		 */
260c80476e4SDavid E. O'Brien 		break;
261c80476e4SDavid E. O'Brien 	    }
262c80476e4SDavid E. O'Brien 	}
263c80476e4SDavid E. O'Brien 	else
264c80476e4SDavid E. O'Brien 	    Draw(*cp);
265c80476e4SDavid E. O'Brien     }
266c80476e4SDavid E. O'Brien }
267c80476e4SDavid E. O'Brien 
268c80476e4SDavid E. O'Brien /*
269c80476e4SDavid E. O'Brien  *  Refresh()
270c80476e4SDavid E. O'Brien  *	draws the new virtual screen image from the current input
271c80476e4SDavid E. O'Brien  *  	line, then goes line-by-line changing the real image to the new
272c80476e4SDavid E. O'Brien  *	virtual image. The routine to re-draw a line can be replaced
273c80476e4SDavid E. O'Brien  *	easily in hopes of a smarter one being placed there.
274c80476e4SDavid E. O'Brien  */
275c80476e4SDavid E. O'Brien static int OldvcV = 0;
276c80476e4SDavid E. O'Brien void
277c80476e4SDavid E. O'Brien Refresh()
278c80476e4SDavid E. O'Brien {
279c80476e4SDavid E. O'Brien     register int cur_line;
280c80476e4SDavid E. O'Brien     register Char *cp;
281c80476e4SDavid E. O'Brien     int     cur_h, cur_v = 0, new_vcv;
282c80476e4SDavid E. O'Brien     int     rhdiff;
283c80476e4SDavid E. O'Brien     Char    oldgetting;
284c80476e4SDavid E. O'Brien 
285c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
286c80476e4SDavid E. O'Brien     dprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf));
287c80476e4SDavid E. O'Brien     dprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
288c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
289c80476e4SDavid E. O'Brien     oldgetting = GettingInput;
290c80476e4SDavid E. O'Brien     GettingInput = 0;		/* avoid re-entrance via SIGWINCH */
291c80476e4SDavid E. O'Brien 
292c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
293c80476e4SDavid E. O'Brien     vcursor_h = 0;
294c80476e4SDavid E. O'Brien     vcursor_v = 0;
295c80476e4SDavid E. O'Brien     RefreshPromptpart(NULL);
296c80476e4SDavid E. O'Brien     RefreshPromptpart(RPromptBuf);
297c80476e4SDavid E. O'Brien     rprompt_h = vcursor_h;
298c80476e4SDavid E. O'Brien     rprompt_v = vcursor_v;
299c80476e4SDavid E. O'Brien 
300c80476e4SDavid E. O'Brien     /* reset the Vdraw cursor, draw prompt */
301c80476e4SDavid E. O'Brien     vcursor_h = 0;
302c80476e4SDavid E. O'Brien     vcursor_v = 0;
303c80476e4SDavid E. O'Brien     RefreshPromptpart(NULL);
304c80476e4SDavid E. O'Brien     RefreshPromptpart(PromptBuf);
305c80476e4SDavid E. O'Brien     cur_h = -1;			/* set flag in case I'm not set */
306c80476e4SDavid E. O'Brien 
307c80476e4SDavid E. O'Brien     /* draw the current input buffer */
308c80476e4SDavid E. O'Brien     for (cp = InputBuf; (cp < LastChar); cp++) {
309c80476e4SDavid E. O'Brien 	if (cp == Cursor) {
310c80476e4SDavid E. O'Brien 	    cur_h = vcursor_h;	/* save for later */
311c80476e4SDavid E. O'Brien 	    cur_v = vcursor_v;
312c80476e4SDavid E. O'Brien 	}
313c80476e4SDavid E. O'Brien 	Draw(*cp);
314c80476e4SDavid E. O'Brien     }
315c80476e4SDavid E. O'Brien 
316c80476e4SDavid E. O'Brien     if (cur_h == -1) {		/* if I haven't been set yet, I'm at the end */
317c80476e4SDavid E. O'Brien 	cur_h = vcursor_h;
318c80476e4SDavid E. O'Brien 	cur_v = vcursor_v;
319c80476e4SDavid E. O'Brien     }
320c80476e4SDavid E. O'Brien 
321c80476e4SDavid E. O'Brien     rhdiff = TermH - vcursor_h - rprompt_h;
322c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
323c80476e4SDavid E. O'Brien 			/*
324c80476e4SDavid E. O'Brien 			 * have a right-hand side prompt that will fit on
325c80476e4SDavid E. O'Brien 			 * the end of the first line with at least one
326c80476e4SDavid E. O'Brien 			 * character gap to the input buffer.
327c80476e4SDavid E. O'Brien 			 */
328c80476e4SDavid E. O'Brien 	while (--rhdiff > 0)		/* pad out with spaces */
329c80476e4SDavid E. O'Brien 	    Draw(' ');
330c80476e4SDavid E. O'Brien 	RefreshPromptpart(RPromptBuf);
331c80476e4SDavid E. O'Brien     }
332c80476e4SDavid E. O'Brien     else {
333c80476e4SDavid E. O'Brien 	rprompt_h = 0;			/* flag "not using rprompt" */
334c80476e4SDavid E. O'Brien 	rprompt_v = 0;
335c80476e4SDavid E. O'Brien     }
336c80476e4SDavid E. O'Brien 
337c80476e4SDavid E. O'Brien     new_vcv = vcursor_v;	/* must be done BEFORE the NUL is written */
338c80476e4SDavid E. O'Brien     Vdraw('\0');		/* put NUL on end */
339c80476e4SDavid E. O'Brien 
340c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
341c80476e4SDavid E. O'Brien     dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
342c80476e4SDavid E. O'Brien 	    TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
343c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
344c80476e4SDavid E. O'Brien 
345c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
346c80476e4SDavid E. O'Brien     dprintf("updating %d lines.\r\n", new_vcv);
347c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
348c80476e4SDavid E. O'Brien     for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
349c80476e4SDavid E. O'Brien 	/* NOTE THAT update_line MAY CHANGE Display[cur_line] */
350c80476e4SDavid E. O'Brien 	update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
351c80476e4SDavid E. O'Brien #ifdef WINNT
352c80476e4SDavid E. O'Brien 	flush();
353c80476e4SDavid E. O'Brien #endif /* WINNT */
354c80476e4SDavid E. O'Brien 
355c80476e4SDavid E. O'Brien 	/*
356c80476e4SDavid E. O'Brien 	 * Copy the new line to be the current one, and pad out with spaces
357c80476e4SDavid E. O'Brien 	 * to the full width of the terminal so that if we try moving the
358c80476e4SDavid E. O'Brien 	 * cursor by writing the character that is at the end of the
359c80476e4SDavid E. O'Brien 	 * screen line, it won't be a NUL or some old leftover stuff.
360c80476e4SDavid E. O'Brien 	 */
361c80476e4SDavid E. O'Brien 	cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
362c80476e4SDavid E. O'Brien #ifdef notdef
363c80476e4SDavid E. O'Brien 	(void) Strncpy(Display[cur_line], Vdisplay[cur_line], (size_t) TermH);
364c80476e4SDavid E. O'Brien 	Display[cur_line][TermH] = '\0';	/* just in case */
365c80476e4SDavid E. O'Brien #endif
366c80476e4SDavid E. O'Brien     }
367c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
368c80476e4SDavid E. O'Brien     dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
369c80476e4SDavid E. O'Brien 	    vcursor_v, OldvcV, cur_line);
370c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
371c80476e4SDavid E. O'Brien     if (OldvcV > new_vcv) {
372c80476e4SDavid E. O'Brien 	for (; cur_line <= OldvcV; cur_line++) {
373c80476e4SDavid E. O'Brien 	    update_line(Display[cur_line], STRNULL, cur_line);
374c80476e4SDavid E. O'Brien 	    *Display[cur_line] = '\0';
375c80476e4SDavid E. O'Brien 	}
376c80476e4SDavid E. O'Brien     }
377c80476e4SDavid E. O'Brien     OldvcV = new_vcv;		/* set for next time */
378c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
379c80476e4SDavid E. O'Brien     dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
380c80476e4SDavid E. O'Brien 	    CursorH, CursorV, cur_h, cur_v);
381c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
382c80476e4SDavid E. O'Brien #ifdef WINNT
383c80476e4SDavid E. O'Brien     flush();
384c80476e4SDavid E. O'Brien #endif /* WINNT */
385c80476e4SDavid E. O'Brien     MoveToLine(cur_v);		/* go to where the cursor is */
386c80476e4SDavid E. O'Brien     MoveToChar(cur_h);
387c80476e4SDavid E. O'Brien     SetAttributes(0);		/* Clear all attributes */
388c80476e4SDavid E. O'Brien     flush();			/* send the output... */
389c80476e4SDavid E. O'Brien     GettingInput = oldgetting;	/* reset to old value */
390c80476e4SDavid E. O'Brien }
391c80476e4SDavid E. O'Brien 
392c80476e4SDavid E. O'Brien #ifdef notdef
393c80476e4SDavid E. O'Brien GotoBottom()
394c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
395c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
396c80476e4SDavid E. O'Brien }
397c80476e4SDavid E. O'Brien 
398c80476e4SDavid E. O'Brien #endif
399c80476e4SDavid E. O'Brien 
400c80476e4SDavid E. O'Brien void
401c80476e4SDavid E. O'Brien PastBottom()
402c80476e4SDavid E. O'Brien {				/* used to go to last used screen line */
403c80476e4SDavid E. O'Brien     MoveToLine(OldvcV);
404c80476e4SDavid E. O'Brien     (void) putraw('\r');
405c80476e4SDavid E. O'Brien     (void) putraw('\n');
406c80476e4SDavid E. O'Brien     ClearDisp();
407c80476e4SDavid E. O'Brien     flush();
408c80476e4SDavid E. O'Brien }
409c80476e4SDavid E. O'Brien 
410c80476e4SDavid E. O'Brien 
411c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat,
412c80476e4SDavid E. O'Brien    maximum length of d is dlen */
413c80476e4SDavid E. O'Brien static void
414c80476e4SDavid E. O'Brien str_insert(d, dat, dlen, s, num)
415c80476e4SDavid E. O'Brien     register Char *d;
416c80476e4SDavid E. O'Brien     register int dat, dlen;
417c80476e4SDavid E. O'Brien     register Char *s;
418c80476e4SDavid E. O'Brien     register int num;
419c80476e4SDavid E. O'Brien {
420c80476e4SDavid E. O'Brien     register Char *a, *b;
421c80476e4SDavid E. O'Brien 
422c80476e4SDavid E. O'Brien     if (num <= 0)
423c80476e4SDavid E. O'Brien 	return;
424c80476e4SDavid E. O'Brien     if (num > dlen - dat)
425c80476e4SDavid E. O'Brien 	num = dlen - dat;
426c80476e4SDavid E. O'Brien 
427c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
428c80476e4SDavid E. O'Brien     dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
429c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
430c80476e4SDavid E. O'Brien     dprintf("s == \"%s\"n", short2str(s));
431c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
432c80476e4SDavid E. O'Brien 
433c80476e4SDavid E. O'Brien     /* open up the space for num chars */
434c80476e4SDavid E. O'Brien     if (num > 0) {
435c80476e4SDavid E. O'Brien 	b = d + dlen - 1;
436c80476e4SDavid E. O'Brien 	a = b - num;
437c80476e4SDavid E. O'Brien 	while (a >= &d[dat])
438c80476e4SDavid E. O'Brien 	    *b-- = *a--;
439c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
440c80476e4SDavid E. O'Brien     }
441c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
442c80476e4SDavid E. O'Brien     dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
443c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
444c80476e4SDavid E. O'Brien     dprintf("s == \"%s\"n", short2str(s));
445c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
446c80476e4SDavid E. O'Brien 
447c80476e4SDavid E. O'Brien     /* copy the characters */
448c80476e4SDavid E. O'Brien     for (a = d + dat; (a < d + dlen) && (num > 0); num--)
449c80476e4SDavid E. O'Brien 	*a++ = *s++;
450c80476e4SDavid E. O'Brien 
451c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
452c80476e4SDavid E. O'Brien     dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
453c80476e4SDavid E. O'Brien 	    num, dat, dlen, d, short2str(s));
454c80476e4SDavid E. O'Brien     dprintf("s == \"%s\"n", short2str(s));
455c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
456c80476e4SDavid E. O'Brien }
457c80476e4SDavid E. O'Brien 
458c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */
459c80476e4SDavid E. O'Brien static void
460c80476e4SDavid E. O'Brien str_delete(d, dat, dlen, num)
461c80476e4SDavid E. O'Brien     register Char *d;
462c80476e4SDavid E. O'Brien     register int dat, dlen, num;
463c80476e4SDavid E. O'Brien {
464c80476e4SDavid E. O'Brien     register Char *a, *b;
465c80476e4SDavid E. O'Brien 
466c80476e4SDavid E. O'Brien     if (num <= 0)
467c80476e4SDavid E. O'Brien 	return;
468c80476e4SDavid E. O'Brien     if (dat + num >= dlen) {
469c80476e4SDavid E. O'Brien 	d[dat] = '\0';
470c80476e4SDavid E. O'Brien 	return;
471c80476e4SDavid E. O'Brien     }
472c80476e4SDavid E. O'Brien 
473c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
474c80476e4SDavid E. O'Brien     dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
475c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
476c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
477c80476e4SDavid E. O'Brien 
478c80476e4SDavid E. O'Brien     /* open up the space for num chars */
479c80476e4SDavid E. O'Brien     if (num > 0) {
480c80476e4SDavid E. O'Brien 	b = d + dat;
481c80476e4SDavid E. O'Brien 	a = b + num;
482c80476e4SDavid E. O'Brien 	while (a < &d[dlen])
483c80476e4SDavid E. O'Brien 	    *b++ = *a++;
484c80476e4SDavid E. O'Brien 	d[dlen] = '\0';		/* just in case */
485c80476e4SDavid E. O'Brien     }
486c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
487c80476e4SDavid E. O'Brien     dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
488c80476e4SDavid E. O'Brien 	    num, dat, dlen, short2str(d));
489c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
490c80476e4SDavid E. O'Brien }
491c80476e4SDavid E. O'Brien 
492c80476e4SDavid E. O'Brien static void
493c80476e4SDavid E. O'Brien str_cp(a, b, n)
494c80476e4SDavid E. O'Brien     register Char *a, *b;
495c80476e4SDavid E. O'Brien     register int n;
496c80476e4SDavid E. O'Brien {
497c80476e4SDavid E. O'Brien     while (n-- && *b)
498c80476e4SDavid E. O'Brien 	*a++ = *b++;
499c80476e4SDavid E. O'Brien }
500c80476e4SDavid E. O'Brien 
501c80476e4SDavid E. O'Brien 
502c80476e4SDavid E. O'Brien #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
503c80476e4SDavid E. O'Brien static Char *
504c80476e4SDavid E. O'Brien update_line_fix_mbyte_point(start, target, d)
505c80476e4SDavid E. O'Brien      Char *start, *target;
506c80476e4SDavid E. O'Brien      int d;
507c80476e4SDavid E. O'Brien {
508c80476e4SDavid E. O'Brien     if (_enable_mbdisp) {
509c80476e4SDavid E. O'Brien 	while (*start) {
510c80476e4SDavid E. O'Brien 	    if (target == start)
511c80476e4SDavid E. O'Brien 		break;
512c80476e4SDavid E. O'Brien 	    if (target < start)
513c80476e4SDavid E. O'Brien 		return target + d;
514c80476e4SDavid E. O'Brien 	    if (Ismbyte1(*start) && Ismbyte2(*(start + 1)))
515c80476e4SDavid E. O'Brien 		start++;
516c80476e4SDavid E. O'Brien 	    start++;
517c80476e4SDavid E. O'Brien 	}
518c80476e4SDavid E. O'Brien     }
519c80476e4SDavid E. O'Brien     return target;
520c80476e4SDavid E. O'Brien }
521c80476e4SDavid E. O'Brien #endif
522c80476e4SDavid E. O'Brien 
523c80476e4SDavid E. O'Brien /* ****************************************************************
524c80476e4SDavid E. O'Brien     update_line() is based on finding the middle difference of each line
525c80476e4SDavid E. O'Brien     on the screen; vis:
526c80476e4SDavid E. O'Brien 
527c80476e4SDavid E. O'Brien 			     /old first difference
528c80476e4SDavid E. O'Brien 	/beginning of line   |              /old last same       /old EOL
529c80476e4SDavid E. O'Brien 	v		     v              v                    v
530c80476e4SDavid E. O'Brien old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
531c80476e4SDavid E. O'Brien new:	eddie> Oh, my little buggy says to me, as lurgid as
532c80476e4SDavid E. O'Brien 	^		     ^        ^			   ^
533c80476e4SDavid E. O'Brien 	\beginning of line   |        \new last same	   \new end of line
534c80476e4SDavid E. O'Brien 			     \new first difference
535c80476e4SDavid E. O'Brien 
536c80476e4SDavid E. O'Brien     all are character pointers for the sake of speed.  Special cases for
537c80476e4SDavid E. O'Brien     no differences, as well as for end of line additions must be handled.
538c80476e4SDavid E. O'Brien **************************************************************** */
539c80476e4SDavid E. O'Brien 
540c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it".  This should be about
541c80476e4SDavid E. O'Brien  * half the "cost" of going into insert mode, inserting a character, and
542c80476e4SDavid E. O'Brien  * going back out.  This should really be calculated from the termcap
543c80476e4SDavid E. O'Brien  * data...  For the moment, a good number for ANSI terminals.
544c80476e4SDavid E. O'Brien  */
545c80476e4SDavid E. O'Brien #define MIN_END_KEEP	4
546c80476e4SDavid E. O'Brien 
547c80476e4SDavid E. O'Brien static void			/* could be changed to make it smarter */
548c80476e4SDavid E. O'Brien update_line(old, new, cur_line)
549c80476e4SDavid E. O'Brien     register Char *old, *new;
550c80476e4SDavid E. O'Brien     int     cur_line;
551c80476e4SDavid E. O'Brien {
552c80476e4SDavid E. O'Brien     register Char *o, *n, *p, c;
553c80476e4SDavid E. O'Brien     Char   *ofd, *ols, *oe, *nfd, *nls, *ne;
554c80476e4SDavid E. O'Brien     Char   *osb, *ose, *nsb, *nse;
555c80476e4SDavid E. O'Brien     int     fx, sx;
556c80476e4SDavid E. O'Brien 
557c80476e4SDavid E. O'Brien     /*
558c80476e4SDavid E. O'Brien      * find first diff
559c80476e4SDavid E. O'Brien      */
560c80476e4SDavid E. O'Brien     for (o = old, n = new; *o && (*o == *n); o++, n++)
561c80476e4SDavid E. O'Brien 	continue;
562c80476e4SDavid E. O'Brien     ofd = o;
563c80476e4SDavid E. O'Brien     nfd = n;
564c80476e4SDavid E. O'Brien 
565c80476e4SDavid E. O'Brien     /*
566c80476e4SDavid E. O'Brien      * Find the end of both old and new
567c80476e4SDavid E. O'Brien      */
568c80476e4SDavid E. O'Brien     while (*o)
569c80476e4SDavid E. O'Brien 	o++;
570c80476e4SDavid E. O'Brien     /*
571c80476e4SDavid E. O'Brien      * Remove any trailing blanks off of the end, being careful not to
572c80476e4SDavid E. O'Brien      * back up past the beginning.
573c80476e4SDavid E. O'Brien      */
574c80476e4SDavid E. O'Brien     while (ofd < o) {
575c80476e4SDavid E. O'Brien 	if (o[-1] != ' ')
576c80476e4SDavid E. O'Brien 	    break;
577c80476e4SDavid E. O'Brien 	o--;
578c80476e4SDavid E. O'Brien     }
579c80476e4SDavid E. O'Brien     oe = o;
580c80476e4SDavid E. O'Brien     *oe = (Char) 0;
581c80476e4SDavid E. O'Brien 
582c80476e4SDavid E. O'Brien     while (*n)
583c80476e4SDavid E. O'Brien 	n++;
584c80476e4SDavid E. O'Brien 
585c80476e4SDavid E. O'Brien     /* remove blanks from end of new */
586c80476e4SDavid E. O'Brien     while (nfd < n) {
587c80476e4SDavid E. O'Brien 	if (n[-1] != ' ')
588c80476e4SDavid E. O'Brien 	    break;
589c80476e4SDavid E. O'Brien 	n--;
590c80476e4SDavid E. O'Brien     }
591c80476e4SDavid E. O'Brien     ne = n;
592c80476e4SDavid E. O'Brien     *ne = (Char) 0;
593c80476e4SDavid E. O'Brien 
594c80476e4SDavid E. O'Brien     /*
595c80476e4SDavid E. O'Brien      * if no diff, continue to next line of redraw
596c80476e4SDavid E. O'Brien      */
597c80476e4SDavid E. O'Brien     if (*ofd == '\0' && *nfd == '\0') {
598c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
599c80476e4SDavid E. O'Brien 	dprintf("no difference.\r\n");
600c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
601c80476e4SDavid E. O'Brien 	return;
602c80476e4SDavid E. O'Brien     }
603c80476e4SDavid E. O'Brien 
604c80476e4SDavid E. O'Brien     /*
605c80476e4SDavid E. O'Brien      * find last same pointer
606c80476e4SDavid E. O'Brien      */
607c80476e4SDavid E. O'Brien     while ((o > ofd) && (n > nfd) && (*--o == *--n))
608c80476e4SDavid E. O'Brien 	continue;
609c80476e4SDavid E. O'Brien     ols = ++o;
610c80476e4SDavid E. O'Brien     nls = ++n;
611c80476e4SDavid E. O'Brien 
612c80476e4SDavid E. O'Brien     /*
613c80476e4SDavid E. O'Brien      * find same begining and same end
614c80476e4SDavid E. O'Brien      */
615c80476e4SDavid E. O'Brien     osb = ols;
616c80476e4SDavid E. O'Brien     nsb = nls;
617c80476e4SDavid E. O'Brien     ose = ols;
618c80476e4SDavid E. O'Brien     nse = nls;
619c80476e4SDavid E. O'Brien 
620c80476e4SDavid E. O'Brien     /*
621c80476e4SDavid E. O'Brien      * case 1: insert: scan from nfd to nls looking for *ofd
622c80476e4SDavid E. O'Brien      */
623c80476e4SDavid E. O'Brien     if (*ofd) {
624c80476e4SDavid E. O'Brien 	for (c = *ofd, n = nfd; n < nls; n++) {
625c80476e4SDavid E. O'Brien 	    if (c == *n) {
626c80476e4SDavid E. O'Brien 		for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
627c80476e4SDavid E. O'Brien 		    continue;
628c80476e4SDavid E. O'Brien 		/*
629c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
630c80476e4SDavid E. O'Brien 		 * take it
631c80476e4SDavid E. O'Brien 		 */
632c80476e4SDavid E. O'Brien 		if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
633c80476e4SDavid E. O'Brien 		    nsb = n;
634c80476e4SDavid E. O'Brien 		    nse = p;
635c80476e4SDavid E. O'Brien 		    osb = ofd;
636c80476e4SDavid E. O'Brien 		    ose = o;
637c80476e4SDavid E. O'Brien 		}
638c80476e4SDavid E. O'Brien 	    }
639c80476e4SDavid E. O'Brien 	}
640c80476e4SDavid E. O'Brien     }
641c80476e4SDavid E. O'Brien 
642c80476e4SDavid E. O'Brien     /*
643c80476e4SDavid E. O'Brien      * case 2: delete: scan from ofd to ols looking for *nfd
644c80476e4SDavid E. O'Brien      */
645c80476e4SDavid E. O'Brien     if (*nfd) {
646c80476e4SDavid E. O'Brien 	for (c = *nfd, o = ofd; o < ols; o++) {
647c80476e4SDavid E. O'Brien 	    if (c == *o) {
648c80476e4SDavid E. O'Brien 		for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
649c80476e4SDavid E. O'Brien 		    continue;
650c80476e4SDavid E. O'Brien 		/*
651c80476e4SDavid E. O'Brien 		 * if the new match is longer and it's worth keeping, then we
652c80476e4SDavid E. O'Brien 		 * take it
653c80476e4SDavid E. O'Brien 		 */
654c80476e4SDavid E. O'Brien 		if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
655c80476e4SDavid E. O'Brien 		    nsb = nfd;
656c80476e4SDavid E. O'Brien 		    nse = n;
657c80476e4SDavid E. O'Brien 		    osb = o;
658c80476e4SDavid E. O'Brien 		    ose = p;
659c80476e4SDavid E. O'Brien 		}
660c80476e4SDavid E. O'Brien 	    }
661c80476e4SDavid E. O'Brien 	}
662c80476e4SDavid E. O'Brien     }
663c80476e4SDavid E. O'Brien #ifdef notdef
664c80476e4SDavid E. O'Brien     /*
665c80476e4SDavid E. O'Brien      * If `last same' is before `same end' re-adjust
666c80476e4SDavid E. O'Brien      */
667c80476e4SDavid E. O'Brien     if (ols < ose)
668c80476e4SDavid E. O'Brien 	ols = ose;
669c80476e4SDavid E. O'Brien     if (nls < nse)
670c80476e4SDavid E. O'Brien 	nls = nse;
671c80476e4SDavid E. O'Brien #endif
672c80476e4SDavid E. O'Brien 
673c80476e4SDavid E. O'Brien     /*
674c80476e4SDavid E. O'Brien      * Pragmatics I: If old trailing whitespace or not enough characters to
675c80476e4SDavid E. O'Brien      * save to be worth it, then don't save the last same info.
676c80476e4SDavid E. O'Brien      */
677c80476e4SDavid E. O'Brien     if ((oe - ols) < MIN_END_KEEP) {
678c80476e4SDavid E. O'Brien 	ols = oe;
679c80476e4SDavid E. O'Brien 	nls = ne;
680c80476e4SDavid E. O'Brien     }
681c80476e4SDavid E. O'Brien 
682c80476e4SDavid E. O'Brien     /*
683c80476e4SDavid E. O'Brien      * Pragmatics II: if the terminal isn't smart enough, make the data dumber
684c80476e4SDavid E. O'Brien      * so the smart update doesn't try anything fancy
685c80476e4SDavid E. O'Brien      */
686c80476e4SDavid E. O'Brien 
687c80476e4SDavid E. O'Brien     /*
688c80476e4SDavid E. O'Brien      * fx is the number of characters we need to insert/delete: in the
689c80476e4SDavid E. O'Brien      * beginning to bring the two same begins together
690c80476e4SDavid E. O'Brien      */
691c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
692c80476e4SDavid E. O'Brien     /*
693c80476e4SDavid E. O'Brien      * sx is the number of characters we need to insert/delete: in the end to
694c80476e4SDavid E. O'Brien      * bring the two same last parts together
695c80476e4SDavid E. O'Brien      */
696c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
697c80476e4SDavid E. O'Brien 
698c80476e4SDavid E. O'Brien     if (!T_CanIns) {
699c80476e4SDavid E. O'Brien 	if (fx > 0) {
700c80476e4SDavid E. O'Brien 	    osb = ols;
701c80476e4SDavid E. O'Brien 	    ose = ols;
702c80476e4SDavid E. O'Brien 	    nsb = nls;
703c80476e4SDavid E. O'Brien 	    nse = nls;
704c80476e4SDavid E. O'Brien 	}
705c80476e4SDavid E. O'Brien 	if (sx > 0) {
706c80476e4SDavid E. O'Brien 	    ols = oe;
707c80476e4SDavid E. O'Brien 	    nls = ne;
708c80476e4SDavid E. O'Brien 	}
709c80476e4SDavid E. O'Brien 	if ((ols - ofd) < (nls - nfd)) {
710c80476e4SDavid E. O'Brien 	    ols = oe;
711c80476e4SDavid E. O'Brien 	    nls = ne;
712c80476e4SDavid E. O'Brien 	}
713c80476e4SDavid E. O'Brien     }
714c80476e4SDavid E. O'Brien     if (!T_CanDel) {
715c80476e4SDavid E. O'Brien 	if (fx < 0) {
716c80476e4SDavid E. O'Brien 	    osb = ols;
717c80476e4SDavid E. O'Brien 	    ose = ols;
718c80476e4SDavid E. O'Brien 	    nsb = nls;
719c80476e4SDavid E. O'Brien 	    nse = nls;
720c80476e4SDavid E. O'Brien 	}
721c80476e4SDavid E. O'Brien 	if (sx < 0) {
722c80476e4SDavid E. O'Brien 	    ols = oe;
723c80476e4SDavid E. O'Brien 	    nls = ne;
724c80476e4SDavid E. O'Brien 	}
725c80476e4SDavid E. O'Brien 	if ((ols - ofd) > (nls - nfd)) {
726c80476e4SDavid E. O'Brien 	    ols = oe;
727c80476e4SDavid E. O'Brien 	    nls = ne;
728c80476e4SDavid E. O'Brien 	}
729c80476e4SDavid E. O'Brien     }
730c80476e4SDavid E. O'Brien 
731c80476e4SDavid E. O'Brien     /*
732c80476e4SDavid E. O'Brien      * Pragmatics III: make sure the middle shifted pointers are correct if
733c80476e4SDavid E. O'Brien      * they don't point to anything (we may have moved ols or nls).
734c80476e4SDavid E. O'Brien      */
735c80476e4SDavid E. O'Brien     /* if the change isn't worth it, don't bother */
736c80476e4SDavid E. O'Brien     /* was: if (osb == ose) */
737c80476e4SDavid E. O'Brien     if ((ose - osb) < MIN_END_KEEP) {
738c80476e4SDavid E. O'Brien 	osb = ols;
739c80476e4SDavid E. O'Brien 	ose = ols;
740c80476e4SDavid E. O'Brien 	nsb = nls;
741c80476e4SDavid E. O'Brien 	nse = nls;
742c80476e4SDavid E. O'Brien     }
743c80476e4SDavid E. O'Brien 
744c80476e4SDavid E. O'Brien     /*
745c80476e4SDavid E. O'Brien      * Now that we are done with pragmatics we recompute fx, sx
746c80476e4SDavid E. O'Brien      */
747c80476e4SDavid E. O'Brien     fx = (int) ((nsb - nfd) - (osb - ofd));
748c80476e4SDavid E. O'Brien     sx = (int) ((nls - nse) - (ols - ose));
749c80476e4SDavid E. O'Brien 
750c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
751c80476e4SDavid E. O'Brien     dprintf("\n");
752c80476e4SDavid E. O'Brien     dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
753c80476e4SDavid E. O'Brien 	    ofd - old, osb - old, ose - old, ols - old, oe - old);
754c80476e4SDavid E. O'Brien     dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
755c80476e4SDavid E. O'Brien 	    nfd - new, nsb - new, nse - new, nls - new, ne - new);
756c80476e4SDavid E. O'Brien     dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
757c80476e4SDavid E. O'Brien     dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
758c80476e4SDavid E. O'Brien     dprintstr("old- oe", old, oe);
759c80476e4SDavid E. O'Brien     dprintstr("new- ne", new, ne);
760c80476e4SDavid E. O'Brien     dprintstr("old-ofd", old, ofd);
761c80476e4SDavid E. O'Brien     dprintstr("new-nfd", new, nfd);
762c80476e4SDavid E. O'Brien     dprintstr("ofd-osb", ofd, osb);
763c80476e4SDavid E. O'Brien     dprintstr("nfd-nsb", nfd, nsb);
764c80476e4SDavid E. O'Brien     dprintstr("osb-ose", osb, ose);
765c80476e4SDavid E. O'Brien     dprintstr("nsb-nse", nsb, nse);
766c80476e4SDavid E. O'Brien     dprintstr("ose-ols", ose, ols);
767c80476e4SDavid E. O'Brien     dprintstr("nse-nls", nse, nls);
768c80476e4SDavid E. O'Brien     dprintstr("ols- oe", ols, oe);
769c80476e4SDavid E. O'Brien     dprintstr("nls- ne", nls, ne);
770c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
771c80476e4SDavid E. O'Brien 
772c80476e4SDavid E. O'Brien     /*
773c80476e4SDavid E. O'Brien      * CursorV to this line cur_line MUST be in this routine so that if we
774c80476e4SDavid E. O'Brien      * don't have to change the line, we don't move to it. CursorH to first
775c80476e4SDavid E. O'Brien      * diff char
776c80476e4SDavid E. O'Brien      */
777c80476e4SDavid E. O'Brien     MoveToLine(cur_line);
778c80476e4SDavid E. O'Brien 
779c80476e4SDavid E. O'Brien #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
780c80476e4SDavid E. O'Brien     ofd = update_line_fix_mbyte_point(old, ofd, -1);
781c80476e4SDavid E. O'Brien     osb = update_line_fix_mbyte_point(old, osb,  1);
782c80476e4SDavid E. O'Brien     ose = update_line_fix_mbyte_point(old, ose, -1);
783c80476e4SDavid E. O'Brien     ols = update_line_fix_mbyte_point(old, ols,  1);
784c80476e4SDavid E. O'Brien     nfd = update_line_fix_mbyte_point(new, nfd, -1);
785c80476e4SDavid E. O'Brien     nsb = update_line_fix_mbyte_point(new, nsb,  1);
786c80476e4SDavid E. O'Brien     nse = update_line_fix_mbyte_point(new, nse, -1);
787c80476e4SDavid E. O'Brien     nls = update_line_fix_mbyte_point(new, nls,  1);
788c80476e4SDavid E. O'Brien #endif
789c80476e4SDavid E. O'Brien 
790c80476e4SDavid E. O'Brien     /*
791c80476e4SDavid E. O'Brien      * at this point we have something like this:
792c80476e4SDavid E. O'Brien      *
793c80476e4SDavid E. O'Brien      * /old                  /ofd    /osb               /ose    /ols     /oe
794c80476e4SDavid E. O'Brien      * v.....................v       v..................v       v........v
795c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
796c80476e4SDavid E. O'Brien      * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
797c80476e4SDavid E. O'Brien      * ^.....................^     ^..................^       ^........^
798c80476e4SDavid E. O'Brien      * \new                  \nfd  \nsb               \nse     \nls    \ne
799c80476e4SDavid E. O'Brien      *
800c80476e4SDavid E. O'Brien      * fx is the difference in length between the the chars between nfd and
801c80476e4SDavid E. O'Brien      * nsb, and the chars between ofd and osb, and is thus the number of
802c80476e4SDavid E. O'Brien      * characters to delete if < 0 (new is shorter than old, as above),
803c80476e4SDavid E. O'Brien      * or insert (new is longer than short).
804c80476e4SDavid E. O'Brien      *
805c80476e4SDavid E. O'Brien      * sx is the same for the second differences.
806c80476e4SDavid E. O'Brien      */
807c80476e4SDavid E. O'Brien 
808c80476e4SDavid E. O'Brien     /*
809c80476e4SDavid E. O'Brien      * if we have a net insert on the first difference, AND inserting the net
810c80476e4SDavid E. O'Brien      * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
811c80476e4SDavid E. O'Brien      * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
812c80476e4SDavid E. O'Brien      * (TermH - 1) else we do the deletes first so that we keep everything we
813c80476e4SDavid E. O'Brien      * need to.
814c80476e4SDavid E. O'Brien      */
815c80476e4SDavid E. O'Brien 
816c80476e4SDavid E. O'Brien     /*
817c80476e4SDavid E. O'Brien      * if the last same is the same like the end, there is no last same part,
818c80476e4SDavid E. O'Brien      * otherwise we want to keep the last same part set p to the last useful
819c80476e4SDavid E. O'Brien      * old character
820c80476e4SDavid E. O'Brien      */
821c80476e4SDavid E. O'Brien     p = (ols != oe) ? oe : ose;
822c80476e4SDavid E. O'Brien 
823c80476e4SDavid E. O'Brien     /*
824c80476e4SDavid E. O'Brien      * if (There is a diffence in the beginning) && (we need to insert
825c80476e4SDavid E. O'Brien      * characters) && (the number of characters to insert is less than the term
826c80476e4SDavid E. O'Brien      * width) We need to do an insert! else if (we need to delete characters)
827c80476e4SDavid E. O'Brien      * We need to delete characters! else No insert or delete
828c80476e4SDavid E. O'Brien      */
829c80476e4SDavid E. O'Brien     if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
830c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
831c80476e4SDavid E. O'Brien 	dprintf("first diff insert at %d...\r\n", nfd - new);
832c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
833c80476e4SDavid E. O'Brien 	/*
834c80476e4SDavid E. O'Brien 	 * Move to the first char to insert, where the first diff is.
835c80476e4SDavid E. O'Brien 	 */
836c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
837c80476e4SDavid E. O'Brien 	/*
838c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at end
839c80476e4SDavid E. O'Brien 	 */
840c80476e4SDavid E. O'Brien 	if (nsb != ne) {
841c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
842c80476e4SDavid E. O'Brien 	    dprintf("with stuff to keep at end\r\n");
843c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
844c80476e4SDavid E. O'Brien 	    /*
845c80476e4SDavid E. O'Brien 	     * insert fx chars of new starting at nfd
846c80476e4SDavid E. O'Brien 	     */
847c80476e4SDavid E. O'Brien 	    if (fx > 0) {
848c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
849c80476e4SDavid E. O'Brien 		if (!T_CanIns)
850c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot insert in early first diff\n");
851c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
852c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
853c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
854c80476e4SDavid E. O'Brien 	    }
855c80476e4SDavid E. O'Brien 	    /*
856c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
857c80476e4SDavid E. O'Brien 	     */
858c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
859c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
860c80476e4SDavid E. O'Brien 	}
861c80476e4SDavid E. O'Brien 	else {
862c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
863c80476e4SDavid E. O'Brien 	    dprintf("without anything to save\r\n");
864c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
865c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
866c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
867c80476e4SDavid E. O'Brien 	    /*
868c80476e4SDavid E. O'Brien 	     * Done
869c80476e4SDavid E. O'Brien 	     */
870c80476e4SDavid E. O'Brien 	    return;
871c80476e4SDavid E. O'Brien 	}
872c80476e4SDavid E. O'Brien     }
873c80476e4SDavid E. O'Brien     else if (fx < 0) {
874c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
875c80476e4SDavid E. O'Brien 	dprintf("first diff delete at %d...\r\n", ofd - old);
876c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
877c80476e4SDavid E. O'Brien 	/*
878c80476e4SDavid E. O'Brien 	 * move to the first char to delete where the first diff is
879c80476e4SDavid E. O'Brien 	 */
880c80476e4SDavid E. O'Brien 	MoveToChar(ofd - old);
881c80476e4SDavid E. O'Brien 	/*
882c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
883c80476e4SDavid E. O'Brien 	 */
884c80476e4SDavid E. O'Brien 	if (osb != oe) {
885c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
886c80476e4SDavid E. O'Brien 	    dprintf("with stuff to save at end\r\n");
887c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
888c80476e4SDavid E. O'Brien 	    /*
889c80476e4SDavid E. O'Brien 	     * fx is less than zero *always* here but we check for code
890c80476e4SDavid E. O'Brien 	     * symmetry
891c80476e4SDavid E. O'Brien 	     */
892c80476e4SDavid E. O'Brien 	    if (fx < 0) {
893c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
894c80476e4SDavid E. O'Brien 		if (!T_CanDel)
895c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot delete in first diff\n");
896c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
897c80476e4SDavid E. O'Brien 		DeleteChars(-fx);
898c80476e4SDavid E. O'Brien 		str_delete(old, (int) (ofd - old), TermH, -fx);
899c80476e4SDavid E. O'Brien 	    }
900c80476e4SDavid E. O'Brien 	    /*
901c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
902c80476e4SDavid E. O'Brien 	     */
903c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
904c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
905c80476e4SDavid E. O'Brien 
906c80476e4SDavid E. O'Brien 	}
907c80476e4SDavid E. O'Brien 	else {
908c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
909c80476e4SDavid E. O'Brien 	    dprintf("but with nothing left to save\r\n");
910c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
911c80476e4SDavid E. O'Brien 	    /*
912c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) chars of new starting at nfd
913c80476e4SDavid E. O'Brien 	     */
914c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
915c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
916c80476e4SDavid E. O'Brien 	    dprintf("cleareol %d\n", (oe - old) - (ne - new));
917c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
918c80476e4SDavid E. O'Brien #ifndef WINNT
919c80476e4SDavid E. O'Brien 	    ClearEOL((oe - old) - (ne - new));
920c80476e4SDavid E. O'Brien #else
921c80476e4SDavid E. O'Brien 	    /*
922c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
923c80476e4SDavid E. O'Brien 	     */
924c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
925c80476e4SDavid E. O'Brien #endif /*WINNT*/
926c80476e4SDavid E. O'Brien 	    /*
927c80476e4SDavid E. O'Brien 	     * Done
928c80476e4SDavid E. O'Brien 	     */
929c80476e4SDavid E. O'Brien 	    return;
930c80476e4SDavid E. O'Brien 	}
931c80476e4SDavid E. O'Brien     }
932c80476e4SDavid E. O'Brien     else
933c80476e4SDavid E. O'Brien 	fx = 0;
934c80476e4SDavid E. O'Brien 
935c80476e4SDavid E. O'Brien     if (sx < 0) {
936c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
937c80476e4SDavid E. O'Brien 	dprintf("second diff delete at %d...\r\n", (ose - old) + fx);
938c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
939c80476e4SDavid E. O'Brien 	/*
940c80476e4SDavid E. O'Brien 	 * Check if we have stuff to delete
941c80476e4SDavid E. O'Brien 	 */
942c80476e4SDavid E. O'Brien 	/*
943c80476e4SDavid E. O'Brien 	 * fx is the number of characters inserted (+) or deleted (-)
944c80476e4SDavid E. O'Brien 	 */
945c80476e4SDavid E. O'Brien 
946c80476e4SDavid E. O'Brien 	MoveToChar((ose - old) + fx);
947c80476e4SDavid E. O'Brien 	/*
948c80476e4SDavid E. O'Brien 	 * Check if we have stuff to save
949c80476e4SDavid E. O'Brien 	 */
950c80476e4SDavid E. O'Brien 	if (ols != oe) {
951c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
952c80476e4SDavid E. O'Brien 	    dprintf("with stuff to save at end\r\n");
953c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
954c80476e4SDavid E. O'Brien 	    /*
955c80476e4SDavid E. O'Brien 	     * Again a duplicate test.
956c80476e4SDavid E. O'Brien 	     */
957c80476e4SDavid E. O'Brien 	    if (sx < 0) {
958c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
959c80476e4SDavid E. O'Brien 		if (!T_CanDel)
960c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot delete in second diff\n");
961c80476e4SDavid E. O'Brien #endif  /* DEBUG_UPDATE */
962c80476e4SDavid E. O'Brien 		DeleteChars(-sx);
963c80476e4SDavid E. O'Brien 	    }
964c80476e4SDavid E. O'Brien 
965c80476e4SDavid E. O'Brien 	    /*
966c80476e4SDavid E. O'Brien 	     * write (nls-nse) chars of new starting at nse
967c80476e4SDavid E. O'Brien 	     */
968c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
969c80476e4SDavid E. O'Brien 	}
970c80476e4SDavid E. O'Brien 	else {
971c80476e4SDavid E. O'Brien 	    int olen = (int) (oe - old + fx);
972c80476e4SDavid E. O'Brien 	    if (olen > TermH)
973c80476e4SDavid E. O'Brien 		olen = TermH;
974c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
975c80476e4SDavid E. O'Brien 	    dprintf("but with nothing left to save\r\n");
976c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
977c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
978c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
979c80476e4SDavid E. O'Brien 	    dprintf("cleareol %d\n", olen - (ne - new));
980c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
981c80476e4SDavid E. O'Brien #ifndef WINNT
982c80476e4SDavid E. O'Brien 	    ClearEOL(olen - (ne - new));
983c80476e4SDavid E. O'Brien #else
984c80476e4SDavid E. O'Brien 	    /*
985c80476e4SDavid E. O'Brien 	     * The calculation above does not work too well on NT
986c80476e4SDavid E. O'Brien 	     */
987c80476e4SDavid E. O'Brien 	    ClearEOL(TermH - CursorH);
988c80476e4SDavid E. O'Brien #endif /*WINNT*/
989c80476e4SDavid E. O'Brien 	}
990c80476e4SDavid E. O'Brien     }
991c80476e4SDavid E. O'Brien 
992c80476e4SDavid E. O'Brien     /*
993c80476e4SDavid E. O'Brien      * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
994c80476e4SDavid E. O'Brien      */
995c80476e4SDavid E. O'Brien     if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
996c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
997c80476e4SDavid E. O'Brien 	dprintf("late first diff insert at %d...\r\n", nfd - new);
998c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
999c80476e4SDavid E. O'Brien 
1000c80476e4SDavid E. O'Brien 	MoveToChar(nfd - new);
1001c80476e4SDavid E. O'Brien 	/*
1002c80476e4SDavid E. O'Brien 	 * Check if we have stuff to keep at the end
1003c80476e4SDavid E. O'Brien 	 */
1004c80476e4SDavid E. O'Brien 	if (nsb != ne) {
1005c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1006c80476e4SDavid E. O'Brien 	    dprintf("with stuff to keep at end\r\n");
1007c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1008c80476e4SDavid E. O'Brien 	    /*
1009c80476e4SDavid E. O'Brien 	     * We have to recalculate fx here because we set it
1010c80476e4SDavid E. O'Brien 	     * to zero above as a flag saying that we hadn't done
1011c80476e4SDavid E. O'Brien 	     * an early first insert.
1012c80476e4SDavid E. O'Brien 	     */
1013c80476e4SDavid E. O'Brien 	    fx = (int) ((nsb - nfd) - (osb - ofd));
1014c80476e4SDavid E. O'Brien 	    if (fx > 0) {
1015c80476e4SDavid E. O'Brien 		/*
1016c80476e4SDavid E. O'Brien 		 * insert fx chars of new starting at nfd
1017c80476e4SDavid E. O'Brien 		 */
1018c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1019c80476e4SDavid E. O'Brien 		if (!T_CanIns)
1020c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot insert in late first diff\n");
1021c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1022c80476e4SDavid E. O'Brien 		Insert_write(nfd, fx);
1023c80476e4SDavid E. O'Brien 		str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1024c80476e4SDavid E. O'Brien 	    }
1025c80476e4SDavid E. O'Brien 
1026c80476e4SDavid E. O'Brien 	    /*
1027c80476e4SDavid E. O'Brien 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1028c80476e4SDavid E. O'Brien 	     */
1029c80476e4SDavid E. O'Brien 	    so_write(nfd + fx, (nsb - nfd) - fx);
1030c80476e4SDavid E. O'Brien 	    str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1031c80476e4SDavid E. O'Brien 	}
1032c80476e4SDavid E. O'Brien 	else {
1033c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1034c80476e4SDavid E. O'Brien 	    dprintf("without anything to save\r\n");
1035c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1036c80476e4SDavid E. O'Brien 	    so_write(nfd, (nsb - nfd));
1037c80476e4SDavid E. O'Brien 	    str_cp(ofd, nfd, (int) (nsb - nfd));
1038c80476e4SDavid E. O'Brien 	}
1039c80476e4SDavid E. O'Brien     }
1040c80476e4SDavid E. O'Brien 
1041c80476e4SDavid E. O'Brien     /*
1042c80476e4SDavid E. O'Brien      * line is now NEW up to nse
1043c80476e4SDavid E. O'Brien      */
1044c80476e4SDavid E. O'Brien     if (sx >= 0) {
1045c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1046c80476e4SDavid E. O'Brien 	dprintf("second diff insert at %d...\r\n", nse - new);
1047c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1048c80476e4SDavid E. O'Brien 	MoveToChar(nse - new);
1049c80476e4SDavid E. O'Brien 	if (ols != oe) {
1050c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1051c80476e4SDavid E. O'Brien 	    dprintf("with stuff to keep at end\r\n");
1052c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1053c80476e4SDavid E. O'Brien 	    if (sx > 0) {
1054c80476e4SDavid E. O'Brien 		/* insert sx chars of new starting at nse */
1055c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1056c80476e4SDavid E. O'Brien 		if (!T_CanIns)
1057c80476e4SDavid E. O'Brien 		    dprintf("   ERROR: cannot insert in second diff\n");
1058c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1059c80476e4SDavid E. O'Brien 		Insert_write(nse, sx);
1060c80476e4SDavid E. O'Brien 	    }
1061c80476e4SDavid E. O'Brien 
1062c80476e4SDavid E. O'Brien 	    /*
1063c80476e4SDavid E. O'Brien 	     * write (nls-nse) - sx chars of new starting at (nse + sx)
1064c80476e4SDavid E. O'Brien 	     */
1065c80476e4SDavid E. O'Brien 	    so_write(nse + sx, (nls - nse) - sx);
1066c80476e4SDavid E. O'Brien 	}
1067c80476e4SDavid E. O'Brien 	else {
1068c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1069c80476e4SDavid E. O'Brien 	    dprintf("without anything to save\r\n");
1070c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1071c80476e4SDavid E. O'Brien 	    so_write(nse, (nls - nse));
1072c80476e4SDavid E. O'Brien 
1073c80476e4SDavid E. O'Brien 	    /*
1074c80476e4SDavid E. O'Brien              * No need to do a clear-to-end here because we were doing
1075c80476e4SDavid E. O'Brien 	     * a second insert, so we will have over written all of the
1076c80476e4SDavid E. O'Brien 	     * old string.
1077c80476e4SDavid E. O'Brien 	     */
1078c80476e4SDavid E. O'Brien 	}
1079c80476e4SDavid E. O'Brien     }
1080c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1081c80476e4SDavid E. O'Brien     dprintf("done.\r\n");
1082c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1083c80476e4SDavid E. O'Brien }
1084c80476e4SDavid E. O'Brien 
1085c80476e4SDavid E. O'Brien 
1086c80476e4SDavid E. O'Brien static void
1087c80476e4SDavid E. O'Brien cpy_pad_spaces(dst, src, width)
1088c80476e4SDavid E. O'Brien     register Char *dst, *src;
1089c80476e4SDavid E. O'Brien     register int width;
1090c80476e4SDavid E. O'Brien {
1091c80476e4SDavid E. O'Brien     register int i;
1092c80476e4SDavid E. O'Brien 
1093c80476e4SDavid E. O'Brien     for (i = 0; i < width; i++) {
1094c80476e4SDavid E. O'Brien 	if (*src == (Char) 0)
1095c80476e4SDavid E. O'Brien 	    break;
1096c80476e4SDavid E. O'Brien 	*dst++ = *src++;
1097c80476e4SDavid E. O'Brien     }
1098c80476e4SDavid E. O'Brien 
1099c80476e4SDavid E. O'Brien     while (i < width) {
1100c80476e4SDavid E. O'Brien 	*dst++ = ' ';
1101c80476e4SDavid E. O'Brien 	i++;
1102c80476e4SDavid E. O'Brien     }
1103c80476e4SDavid E. O'Brien     *dst = (Char) 0;
1104c80476e4SDavid E. O'Brien }
1105c80476e4SDavid E. O'Brien 
1106c80476e4SDavid E. O'Brien void
1107c80476e4SDavid E. O'Brien RefCursor()
1108c80476e4SDavid E. O'Brien {				/* only move to new cursor pos */
1109c80476e4SDavid E. O'Brien     register Char *cp, c;
1110c80476e4SDavid E. O'Brien     register int h, th, v;
1111c80476e4SDavid E. O'Brien 
1112c80476e4SDavid E. O'Brien     /* first we must find where the cursor is... */
1113c80476e4SDavid E. O'Brien     h = 0;
1114c80476e4SDavid E. O'Brien     v = 0;
1115c80476e4SDavid E. O'Brien     th = TermH;			/* optimize for speed */
1116c80476e4SDavid E. O'Brien 
1117c80476e4SDavid E. O'Brien     for (cp = PromptBuf; *cp; cp++) {	/* do prompt */
1118c80476e4SDavid E. O'Brien 	if (*cp & LITERAL)
1119c80476e4SDavid E. O'Brien 	    continue;
1120c80476e4SDavid E. O'Brien 	c = *cp & CHAR;		/* extra speed plus strip the inverse */
1121c80476e4SDavid E. O'Brien 	h++;			/* all chars at least this long */
1122c80476e4SDavid E. O'Brien 
1123c80476e4SDavid E. O'Brien 	/* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
1124c80476e4SDavid E. O'Brien 	/* lets handle newline as part of the prompt */
1125c80476e4SDavid E. O'Brien 
1126c80476e4SDavid E. O'Brien 	if (c == '\n') {
1127c80476e4SDavid E. O'Brien 	    h = 0;
1128c80476e4SDavid E. O'Brien 	    v++;
1129c80476e4SDavid E. O'Brien 	}
1130c80476e4SDavid E. O'Brien 	else {
1131c80476e4SDavid E. O'Brien 	    if (c == '\t') {	/* if a tab, to next tab stop */
1132c80476e4SDavid E. O'Brien 		while (h & 07) {
1133c80476e4SDavid E. O'Brien 		    h++;
1134c80476e4SDavid E. O'Brien 		}
1135c80476e4SDavid E. O'Brien 	    }
1136c80476e4SDavid E. O'Brien 	    else if (Iscntrl(c)) {	/* if control char */
1137c80476e4SDavid E. O'Brien 		h++;
1138c80476e4SDavid E. O'Brien 		if (h > th) {	/* if overflow, compensate */
1139c80476e4SDavid E. O'Brien 		    h = 1;
1140c80476e4SDavid E. O'Brien 		    v++;
1141c80476e4SDavid E. O'Brien 		}
1142c80476e4SDavid E. O'Brien 	    }
1143c80476e4SDavid E. O'Brien 	    else if (!Isprint(c)) {
1144c80476e4SDavid E. O'Brien 		h += 3;
1145c80476e4SDavid E. O'Brien 		if (h > th) {	/* if overflow, compensate */
1146c80476e4SDavid E. O'Brien 		    h = h - th;
1147c80476e4SDavid E. O'Brien 		    v++;
1148c80476e4SDavid E. O'Brien 		}
1149c80476e4SDavid E. O'Brien 	    }
1150c80476e4SDavid E. O'Brien 	}
1151c80476e4SDavid E. O'Brien 
1152c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
1153c80476e4SDavid E. O'Brien 	    h = 0;
1154c80476e4SDavid E. O'Brien 	    v++;
1155c80476e4SDavid E. O'Brien 	}
1156c80476e4SDavid E. O'Brien     }
1157c80476e4SDavid E. O'Brien 
1158c80476e4SDavid E. O'Brien     for (cp = InputBuf; cp < Cursor; cp++) {	/* do input buffer to Cursor */
1159c80476e4SDavid E. O'Brien 	c = *cp & CHAR;		/* extra speed plus strip the inverse */
1160c80476e4SDavid E. O'Brien 	h++;			/* all chars at least this long */
1161c80476e4SDavid E. O'Brien 
1162c80476e4SDavid E. O'Brien 	if (c == '\n') {	/* handle newline in data part too */
1163c80476e4SDavid E. O'Brien 	    h = 0;
1164c80476e4SDavid E. O'Brien 	    v++;
1165c80476e4SDavid E. O'Brien 	}
1166c80476e4SDavid E. O'Brien 	else {
1167c80476e4SDavid E. O'Brien 	    if (c == '\t') {	/* if a tab, to next tab stop */
1168c80476e4SDavid E. O'Brien 		while (h & 07) {
1169c80476e4SDavid E. O'Brien 		    h++;
1170c80476e4SDavid E. O'Brien 		}
1171c80476e4SDavid E. O'Brien 	    }
1172c80476e4SDavid E. O'Brien 	    else if (Iscntrl(c)) {	/* if control char */
1173c80476e4SDavid E. O'Brien 		h++;
1174c80476e4SDavid E. O'Brien 		if (h > th) {	/* if overflow, compensate */
1175c80476e4SDavid E. O'Brien 		    h = 1;
1176c80476e4SDavid E. O'Brien 		    v++;
1177c80476e4SDavid E. O'Brien 		}
1178c80476e4SDavid E. O'Brien 	    }
1179c80476e4SDavid E. O'Brien 	    else if (!Isprint(c)) {
1180c80476e4SDavid E. O'Brien 		h += 3;
1181c80476e4SDavid E. O'Brien 		if (h > th) {	/* if overflow, compensate */
1182c80476e4SDavid E. O'Brien 		    h = h - th;
1183c80476e4SDavid E. O'Brien 		    v++;
1184c80476e4SDavid E. O'Brien 		}
1185c80476e4SDavid E. O'Brien 	    }
1186c80476e4SDavid E. O'Brien 	}
1187c80476e4SDavid E. O'Brien 
1188c80476e4SDavid E. O'Brien 	if (h >= th) {		/* check, extra long tabs picked up here also */
1189c80476e4SDavid E. O'Brien 	    h = 0;
1190c80476e4SDavid E. O'Brien 	    v++;
1191c80476e4SDavid E. O'Brien 	}
1192c80476e4SDavid E. O'Brien     }
1193c80476e4SDavid E. O'Brien 
1194c80476e4SDavid E. O'Brien     /* now go there */
1195c80476e4SDavid E. O'Brien     MoveToLine(v);
1196c80476e4SDavid E. O'Brien     MoveToChar(h);
1197c80476e4SDavid E. O'Brien     flush();
1198c80476e4SDavid E. O'Brien }
1199c80476e4SDavid E. O'Brien 
1200c80476e4SDavid E. O'Brien static void
1201c80476e4SDavid E. O'Brien PutPlusOne(c)
1202c80476e4SDavid E. O'Brien     int    c;
1203c80476e4SDavid E. O'Brien {
1204c80476e4SDavid E. O'Brien     (void) putraw(c);
1205c80476e4SDavid E. O'Brien     Display[CursorV][CursorH++] = (Char) c;
1206c80476e4SDavid E. O'Brien     if (CursorH >= TermH) {	/* if we must overflow */
1207c80476e4SDavid E. O'Brien 	CursorH = 0;
1208c80476e4SDavid E. O'Brien 	CursorV++;
1209c80476e4SDavid E. O'Brien 	OldvcV++;
1210c80476e4SDavid E. O'Brien 	if (T_Margin & MARGIN_AUTO) {
1211c80476e4SDavid E. O'Brien 	    if (T_Margin & MARGIN_MAGIC) {
1212c80476e4SDavid E. O'Brien 		(void) putraw(' ');
1213c80476e4SDavid E. O'Brien 		(void) putraw('\b');
1214c80476e4SDavid E. O'Brien 	    }
1215c80476e4SDavid E. O'Brien 	}
1216c80476e4SDavid E. O'Brien 	else {
1217c80476e4SDavid E. O'Brien 	    (void) putraw('\r');
1218c80476e4SDavid E. O'Brien 	    (void) putraw('\n');
1219c80476e4SDavid E. O'Brien 	}
1220c80476e4SDavid E. O'Brien     }
1221c80476e4SDavid E. O'Brien }
1222c80476e4SDavid E. O'Brien 
1223c80476e4SDavid E. O'Brien void
1224c80476e4SDavid E. O'Brien RefPlusOne()
1225c80476e4SDavid E. O'Brien {				/* we added just one char, handle it fast.
1226c80476e4SDavid E. O'Brien 				 * assumes that screen cursor == real cursor */
1227c80476e4SDavid E. O'Brien     register Char c, mc;
1228c80476e4SDavid E. O'Brien 
1229c80476e4SDavid E. O'Brien     c = Cursor[-1] & CHAR;	/* the char we just added */
1230c80476e4SDavid E. O'Brien 
1231c80476e4SDavid E. O'Brien     if (c == '\t' || Cursor != LastChar) {
1232c80476e4SDavid E. O'Brien 	Refresh();		/* too hard to handle */
1233c80476e4SDavid E. O'Brien 	return;
1234c80476e4SDavid E. O'Brien     }
1235c80476e4SDavid E. O'Brien 
1236c80476e4SDavid E. O'Brien     if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1237c80476e4SDavid E. O'Brien 	Refresh();		/* clear out rprompt if less than one char gap*/
1238c80476e4SDavid E. O'Brien 	return;
1239c80476e4SDavid E. O'Brien     }				/* else (only do at end of line, no TAB) */
1240c80476e4SDavid E. O'Brien 
1241c80476e4SDavid E. O'Brien     if (Iscntrl(c)) {		/* if control char, do caret */
1242c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX
1243c80476e4SDavid E. O'Brien 	mc = (c == '\177') ? '?' : (c | 0100);
1244c80476e4SDavid E. O'Brien 	PutPlusOne('^');
1245c80476e4SDavid E. O'Brien 	PutPlusOne(mc);
1246c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/
1247c80476e4SDavid E. O'Brien 	if (_toascii[c] == '\177' || Isupper(_toebcdic[_toascii[c]|0100])
1248c80476e4SDavid E. O'Brien 		|| strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
1249c80476e4SDavid E. O'Brien 	{
1250c80476e4SDavid E. O'Brien 	    mc = (_toascii[c] == '\177') ? '?' : _toebcdic[_toascii[c]|0100];
1251c80476e4SDavid E. O'Brien 	    PutPlusOne('^');
1252c80476e4SDavid E. O'Brien 	    PutPlusOne(mc);
1253c80476e4SDavid E. O'Brien 	}
1254c80476e4SDavid E. O'Brien 	else
1255c80476e4SDavid E. O'Brien 	{
1256c80476e4SDavid E. O'Brien 	    PutPlusOne('\\');
1257c80476e4SDavid E. O'Brien 	    PutPlusOne(((c >> 6) & 7) + '0');
1258c80476e4SDavid E. O'Brien 	    PutPlusOne(((c >> 3) & 7) + '0');
1259c80476e4SDavid E. O'Brien 	    PutPlusOne((c & 7) + '0');
1260c80476e4SDavid E. O'Brien 	}
1261c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/
1262c80476e4SDavid E. O'Brien     }
1263c80476e4SDavid E. O'Brien     else if (Isprint(c)) {	/* normal char */
1264c80476e4SDavid E. O'Brien 	PutPlusOne(c);
1265c80476e4SDavid E. O'Brien     }
1266c80476e4SDavid E. O'Brien #ifdef KANJI
1267c80476e4SDavid E. O'Brien     else if (!adrof(STRnokanji)) {
1268c80476e4SDavid E. O'Brien 	PutPlusOne(c);
1269c80476e4SDavid E. O'Brien     }
1270c80476e4SDavid E. O'Brien #endif
1271c80476e4SDavid E. O'Brien     else {
1272c80476e4SDavid E. O'Brien 	PutPlusOne('\\');
1273c80476e4SDavid E. O'Brien 	PutPlusOne(((c >> 6) & 7) + '0');
1274c80476e4SDavid E. O'Brien 	PutPlusOne(((c >> 3) & 7) + '0');
1275c80476e4SDavid E. O'Brien 	PutPlusOne((c & 7) + '0');
1276c80476e4SDavid E. O'Brien     }
1277c80476e4SDavid E. O'Brien     flush();
1278c80476e4SDavid E. O'Brien }
1279c80476e4SDavid E. O'Brien 
1280c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */
1281c80476e4SDavid E. O'Brien 
1282c80476e4SDavid E. O'Brien void
1283c80476e4SDavid E. O'Brien ClearDisp()
1284c80476e4SDavid E. O'Brien {
1285c80476e4SDavid E. O'Brien     register int i;
1286c80476e4SDavid E. O'Brien 
1287c80476e4SDavid E. O'Brien     CursorV = 0;		/* clear the display buffer */
1288c80476e4SDavid E. O'Brien     CursorH = 0;
1289c80476e4SDavid E. O'Brien     for (i = 0; i < TermV; i++)
1290c80476e4SDavid E. O'Brien 	(void) memset(Display[i], 0, TermH * sizeof(Display[0][0]));
1291c80476e4SDavid E. O'Brien     OldvcV = 0;
1292c80476e4SDavid E. O'Brien }
1293c80476e4SDavid E. O'Brien 
1294c80476e4SDavid E. O'Brien void
1295c80476e4SDavid E. O'Brien ClearLines()
1296c80476e4SDavid E. O'Brien {				/* Make sure all lines are *really* blank */
1297c80476e4SDavid E. O'Brien     register int i;
1298c80476e4SDavid E. O'Brien 
1299c80476e4SDavid E. O'Brien     if (T_CanCEOL) {
1300c80476e4SDavid E. O'Brien 	/*
1301c80476e4SDavid E. O'Brien 	 * Clear the lines from the bottom up so that if we try moving
1302c80476e4SDavid E. O'Brien 	 * the cursor down by writing the character that is at the end
1303c80476e4SDavid E. O'Brien 	 * of the screen line, we won't rewrite a character that shouldn't
1304c80476e4SDavid E. O'Brien 	 * be there.
1305c80476e4SDavid E. O'Brien 	 */
1306c80476e4SDavid E. O'Brien 	for (i = OldvcV; i >= 0; i--) {	/* for each line on the screen */
1307c80476e4SDavid E. O'Brien 	    MoveToLine(i);
1308c80476e4SDavid E. O'Brien 	    MoveToChar(0);
1309c80476e4SDavid E. O'Brien 	    ClearEOL(TermH);
1310c80476e4SDavid E. O'Brien 	}
1311c80476e4SDavid E. O'Brien     }
1312c80476e4SDavid E. O'Brien     else {
1313c80476e4SDavid E. O'Brien 	MoveToLine(OldvcV);	/* go to last line */
1314c80476e4SDavid E. O'Brien 	(void) putraw('\r');	/* go to BOL */
1315c80476e4SDavid E. O'Brien 	(void) putraw('\n');	/* go to new line */
1316c80476e4SDavid E. O'Brien     }
1317c80476e4SDavid E. O'Brien }
1318