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