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