xref: /freebsd/contrib/libedit/refresh.c (revision d0ef721ed3dc99bddc1e48605a6921ec60322efc)
1*d0ef721eSBaptiste Daroussin /*	$NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $	*/
2*d0ef721eSBaptiste Daroussin 
3*d0ef721eSBaptiste Daroussin /*-
4*d0ef721eSBaptiste Daroussin  * Copyright (c) 1992, 1993
5*d0ef721eSBaptiste Daroussin  *	The Regents of the University of California.  All rights reserved.
6*d0ef721eSBaptiste Daroussin  *
7*d0ef721eSBaptiste Daroussin  * This code is derived from software contributed to Berkeley by
8*d0ef721eSBaptiste Daroussin  * Christos Zoulas of Cornell University.
9*d0ef721eSBaptiste Daroussin  *
10*d0ef721eSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
11*d0ef721eSBaptiste Daroussin  * modification, are permitted provided that the following conditions
12*d0ef721eSBaptiste Daroussin  * are met:
13*d0ef721eSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
14*d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
15*d0ef721eSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
16*d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
17*d0ef721eSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
18*d0ef721eSBaptiste Daroussin  * 3. Neither the name of the University nor the names of its contributors
19*d0ef721eSBaptiste Daroussin  *    may be used to endorse or promote products derived from this software
20*d0ef721eSBaptiste Daroussin  *    without specific prior written permission.
21*d0ef721eSBaptiste Daroussin  *
22*d0ef721eSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*d0ef721eSBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*d0ef721eSBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*d0ef721eSBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*d0ef721eSBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*d0ef721eSBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*d0ef721eSBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*d0ef721eSBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*d0ef721eSBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*d0ef721eSBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*d0ef721eSBaptiste Daroussin  * SUCH DAMAGE.
33*d0ef721eSBaptiste Daroussin  */
34*d0ef721eSBaptiste Daroussin 
35*d0ef721eSBaptiste Daroussin #include "config.h"
36*d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID)
37*d0ef721eSBaptiste Daroussin #if 0
38*d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)refresh.c	8.1 (Berkeley) 6/4/93";
39*d0ef721eSBaptiste Daroussin #else
40*d0ef721eSBaptiste Daroussin __RCSID("$NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $");
41*d0ef721eSBaptiste Daroussin #endif
42*d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */
43*d0ef721eSBaptiste Daroussin 
44*d0ef721eSBaptiste Daroussin /*
45*d0ef721eSBaptiste Daroussin  * refresh.c: Lower level screen refreshing functions
46*d0ef721eSBaptiste Daroussin  */
47*d0ef721eSBaptiste Daroussin #include <stdio.h>
48*d0ef721eSBaptiste Daroussin #include <string.h>
49*d0ef721eSBaptiste Daroussin #include <unistd.h>
50*d0ef721eSBaptiste Daroussin 
51*d0ef721eSBaptiste Daroussin #include "el.h"
52*d0ef721eSBaptiste Daroussin 
53*d0ef721eSBaptiste Daroussin static void	re_nextline(EditLine *);
54*d0ef721eSBaptiste Daroussin static void	re_addc(EditLine *, wint_t);
55*d0ef721eSBaptiste Daroussin static void	re_update_line(EditLine *, wchar_t *, wchar_t *, int);
56*d0ef721eSBaptiste Daroussin static void	re_insert (EditLine *, wchar_t *, int, int, wchar_t *, int);
57*d0ef721eSBaptiste Daroussin static void	re_delete(EditLine *, wchar_t *, int, int, int);
58*d0ef721eSBaptiste Daroussin static void	re_fastputc(EditLine *, wint_t);
59*d0ef721eSBaptiste Daroussin static void	re_clear_eol(EditLine *, int, int, int);
60*d0ef721eSBaptiste Daroussin static void	re__strncopy(wchar_t *, wchar_t *, size_t);
61*d0ef721eSBaptiste Daroussin static void	re__copy_and_pad(wchar_t *, const wchar_t *, size_t);
62*d0ef721eSBaptiste Daroussin 
63*d0ef721eSBaptiste Daroussin #ifdef DEBUG_REFRESH
64*d0ef721eSBaptiste Daroussin static void	re_printstr(EditLine *, const char *, wchar_t *, wchar_t *);
65*d0ef721eSBaptiste Daroussin #define	__F el->el_errfile
66*d0ef721eSBaptiste Daroussin #define	ELRE_ASSERT(a, b, c)	do				\
67*d0ef721eSBaptiste Daroussin 				    if (/*CONSTCOND*/ a) {	\
68*d0ef721eSBaptiste Daroussin 					(void) fprintf b;	\
69*d0ef721eSBaptiste Daroussin 					c;			\
70*d0ef721eSBaptiste Daroussin 				    }				\
71*d0ef721eSBaptiste Daroussin 				while (/*CONSTCOND*/0)
72*d0ef721eSBaptiste Daroussin #define	ELRE_DEBUG(a, b)	ELRE_ASSERT(a,b,;)
73*d0ef721eSBaptiste Daroussin 
74*d0ef721eSBaptiste Daroussin /* re_printstr():
75*d0ef721eSBaptiste Daroussin  *	Print a string on the debugging pty
76*d0ef721eSBaptiste Daroussin  */
77*d0ef721eSBaptiste Daroussin static void
78*d0ef721eSBaptiste Daroussin re_printstr(EditLine *el, const char *str, wchar_t *f, wchar_t *t)
79*d0ef721eSBaptiste Daroussin {
80*d0ef721eSBaptiste Daroussin 
81*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "%s:\"", str));
82*d0ef721eSBaptiste Daroussin 	while (f < t)
83*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1, (__F, "%c", *f++ & 0177));
84*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "\"\r\n"));
85*d0ef721eSBaptiste Daroussin }
86*d0ef721eSBaptiste Daroussin #else
87*d0ef721eSBaptiste Daroussin #define	ELRE_ASSERT(a, b, c)
88*d0ef721eSBaptiste Daroussin #define	ELRE_DEBUG(a, b)
89*d0ef721eSBaptiste Daroussin #endif
90*d0ef721eSBaptiste Daroussin 
91*d0ef721eSBaptiste Daroussin /* re_nextline():
92*d0ef721eSBaptiste Daroussin  *	Move to the next line or scroll
93*d0ef721eSBaptiste Daroussin  */
94*d0ef721eSBaptiste Daroussin static void
95*d0ef721eSBaptiste Daroussin re_nextline(EditLine *el)
96*d0ef721eSBaptiste Daroussin {
97*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_cursor.h = 0;	/* reset it. */
98*d0ef721eSBaptiste Daroussin 
99*d0ef721eSBaptiste Daroussin 	/*
100*d0ef721eSBaptiste Daroussin 	 * If we would overflow (input is longer than terminal size),
101*d0ef721eSBaptiste Daroussin 	 * emulate scroll by dropping first line and shuffling the rest.
102*d0ef721eSBaptiste Daroussin 	 * We do this via pointer shuffling - it's safe in this case
103*d0ef721eSBaptiste Daroussin 	 * and we avoid memcpy().
104*d0ef721eSBaptiste Daroussin 	 */
105*d0ef721eSBaptiste Daroussin 	if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) {
106*d0ef721eSBaptiste Daroussin 		int i, lins = el->el_terminal.t_size.v;
107*d0ef721eSBaptiste Daroussin 		wchar_t *firstline = el->el_vdisplay[0];
108*d0ef721eSBaptiste Daroussin 
109*d0ef721eSBaptiste Daroussin 		for(i = 1; i < lins; i++)
110*d0ef721eSBaptiste Daroussin 			el->el_vdisplay[i - 1] = el->el_vdisplay[i];
111*d0ef721eSBaptiste Daroussin 
112*d0ef721eSBaptiste Daroussin 		firstline[0] = '\0';		/* empty the string */
113*d0ef721eSBaptiste Daroussin 		el->el_vdisplay[i - 1] = firstline;
114*d0ef721eSBaptiste Daroussin 	} else
115*d0ef721eSBaptiste Daroussin 		el->el_refresh.r_cursor.v++;
116*d0ef721eSBaptiste Daroussin 
117*d0ef721eSBaptiste Daroussin 	ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_terminal.t_size.v,
118*d0ef721eSBaptiste Daroussin 	    (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
119*d0ef721eSBaptiste Daroussin 	    el->el_refresh.r_cursor.v, el->el_terminal.t_size.v),
120*d0ef721eSBaptiste Daroussin 	    abort());
121*d0ef721eSBaptiste Daroussin }
122*d0ef721eSBaptiste Daroussin 
123*d0ef721eSBaptiste Daroussin /* re_addc():
124*d0ef721eSBaptiste Daroussin  *	Draw c, expanding tabs, control chars etc.
125*d0ef721eSBaptiste Daroussin  */
126*d0ef721eSBaptiste Daroussin static void
127*d0ef721eSBaptiste Daroussin re_addc(EditLine *el, wint_t c)
128*d0ef721eSBaptiste Daroussin {
129*d0ef721eSBaptiste Daroussin 	switch (ct_chr_class(c)) {
130*d0ef721eSBaptiste Daroussin 	case CHTYPE_TAB:        /* expand the tab */
131*d0ef721eSBaptiste Daroussin 		for (;;) {
132*d0ef721eSBaptiste Daroussin 			re_putc(el, ' ', 1);
133*d0ef721eSBaptiste Daroussin 			if ((el->el_refresh.r_cursor.h & 07) == 0)
134*d0ef721eSBaptiste Daroussin 				break;			/* go until tab stop */
135*d0ef721eSBaptiste Daroussin 		}
136*d0ef721eSBaptiste Daroussin 		break;
137*d0ef721eSBaptiste Daroussin 	case CHTYPE_NL: {
138*d0ef721eSBaptiste Daroussin 		int oldv = el->el_refresh.r_cursor.v;
139*d0ef721eSBaptiste Daroussin 		re_putc(el, '\0', 0);			/* assure end of line */
140*d0ef721eSBaptiste Daroussin 		if (oldv == el->el_refresh.r_cursor.v)	/* XXX */
141*d0ef721eSBaptiste Daroussin 			re_nextline(el);
142*d0ef721eSBaptiste Daroussin 		break;
143*d0ef721eSBaptiste Daroussin 	}
144*d0ef721eSBaptiste Daroussin 	case CHTYPE_PRINT:
145*d0ef721eSBaptiste Daroussin 		re_putc(el, c, 1);
146*d0ef721eSBaptiste Daroussin 		break;
147*d0ef721eSBaptiste Daroussin 	default: {
148*d0ef721eSBaptiste Daroussin 		wchar_t visbuf[VISUAL_WIDTH_MAX];
149*d0ef721eSBaptiste Daroussin 		ssize_t i, n =
150*d0ef721eSBaptiste Daroussin 		    ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
151*d0ef721eSBaptiste Daroussin 		for (i = 0; n-- > 0; ++i)
152*d0ef721eSBaptiste Daroussin 		    re_putc(el, visbuf[i], 1);
153*d0ef721eSBaptiste Daroussin 		break;
154*d0ef721eSBaptiste Daroussin 	}
155*d0ef721eSBaptiste Daroussin 	}
156*d0ef721eSBaptiste Daroussin }
157*d0ef721eSBaptiste Daroussin 
158*d0ef721eSBaptiste Daroussin /* re_putliteral():
159*d0ef721eSBaptiste Daroussin  *	Place the literal string given
160*d0ef721eSBaptiste Daroussin  */
161*d0ef721eSBaptiste Daroussin libedit_private void
162*d0ef721eSBaptiste Daroussin re_putliteral(EditLine *el, const wchar_t *begin, const wchar_t *end)
163*d0ef721eSBaptiste Daroussin {
164*d0ef721eSBaptiste Daroussin 	coord_t *cur = &el->el_refresh.r_cursor;
165*d0ef721eSBaptiste Daroussin 	wint_t c;
166*d0ef721eSBaptiste Daroussin 	int sizeh = el->el_terminal.t_size.h;
167*d0ef721eSBaptiste Daroussin 	int i, w;
168*d0ef721eSBaptiste Daroussin 
169*d0ef721eSBaptiste Daroussin 	c = literal_add(el, begin, end, &w);
170*d0ef721eSBaptiste Daroussin 	if (c == 0 || w <= 0)
171*d0ef721eSBaptiste Daroussin 		return;
172*d0ef721eSBaptiste Daroussin 	el->el_vdisplay[cur->v][cur->h] = c;
173*d0ef721eSBaptiste Daroussin 
174*d0ef721eSBaptiste Daroussin 	i = w;
175*d0ef721eSBaptiste Daroussin 	if (i > sizeh - cur->h)		/* avoid overflow */
176*d0ef721eSBaptiste Daroussin 		i = sizeh - cur->h;
177*d0ef721eSBaptiste Daroussin 	while (--i > 0)
178*d0ef721eSBaptiste Daroussin 		el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR;
179*d0ef721eSBaptiste Daroussin 
180*d0ef721eSBaptiste Daroussin 	cur->h += w;
181*d0ef721eSBaptiste Daroussin 	if (cur->h >= sizeh) {
182*d0ef721eSBaptiste Daroussin 		/* assure end of line */
183*d0ef721eSBaptiste Daroussin 		el->el_vdisplay[cur->v][sizeh] = '\0';
184*d0ef721eSBaptiste Daroussin 		re_nextline(el);
185*d0ef721eSBaptiste Daroussin 	}
186*d0ef721eSBaptiste Daroussin }
187*d0ef721eSBaptiste Daroussin 
188*d0ef721eSBaptiste Daroussin /* re_putc():
189*d0ef721eSBaptiste Daroussin  *	Draw the character given
190*d0ef721eSBaptiste Daroussin  */
191*d0ef721eSBaptiste Daroussin libedit_private void
192*d0ef721eSBaptiste Daroussin re_putc(EditLine *el, wint_t c, int shift)
193*d0ef721eSBaptiste Daroussin {
194*d0ef721eSBaptiste Daroussin 	coord_t *cur = &el->el_refresh.r_cursor;
195*d0ef721eSBaptiste Daroussin 	int i, w = wcwidth(c);
196*d0ef721eSBaptiste Daroussin 	int sizeh = el->el_terminal.t_size.h;
197*d0ef721eSBaptiste Daroussin 
198*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c));
199*d0ef721eSBaptiste Daroussin 	if (w == -1)
200*d0ef721eSBaptiste Daroussin 		w = 0;
201*d0ef721eSBaptiste Daroussin 
202*d0ef721eSBaptiste Daroussin 	while (shift && (cur->h + w > sizeh))
203*d0ef721eSBaptiste Daroussin 	    re_putc(el, ' ', 1);
204*d0ef721eSBaptiste Daroussin 
205*d0ef721eSBaptiste Daroussin 	el->el_vdisplay[cur->v][cur->h] = c;
206*d0ef721eSBaptiste Daroussin 	/* assumes !shift is only used for single-column chars */
207*d0ef721eSBaptiste Daroussin 	i = w;
208*d0ef721eSBaptiste Daroussin 	while (--i > 0)
209*d0ef721eSBaptiste Daroussin 		el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR;
210*d0ef721eSBaptiste Daroussin 
211*d0ef721eSBaptiste Daroussin 	if (!shift)
212*d0ef721eSBaptiste Daroussin 		return;
213*d0ef721eSBaptiste Daroussin 
214*d0ef721eSBaptiste Daroussin 	cur->h += w;	/* advance to next place */
215*d0ef721eSBaptiste Daroussin 	if (cur->h >= sizeh) {
216*d0ef721eSBaptiste Daroussin 		/* assure end of line */
217*d0ef721eSBaptiste Daroussin 		el->el_vdisplay[cur->v][sizeh] = '\0';
218*d0ef721eSBaptiste Daroussin 		re_nextline(el);
219*d0ef721eSBaptiste Daroussin 	}
220*d0ef721eSBaptiste Daroussin }
221*d0ef721eSBaptiste Daroussin 
222*d0ef721eSBaptiste Daroussin 
223*d0ef721eSBaptiste Daroussin /* re_refresh():
224*d0ef721eSBaptiste Daroussin  *	draws the new virtual screen image from the current input
225*d0ef721eSBaptiste Daroussin  *	line, then goes line-by-line changing the real image to the new
226*d0ef721eSBaptiste Daroussin  *	virtual image. The routine to re-draw a line can be replaced
227*d0ef721eSBaptiste Daroussin  *	easily in hopes of a smarter one being placed there.
228*d0ef721eSBaptiste Daroussin  */
229*d0ef721eSBaptiste Daroussin libedit_private void
230*d0ef721eSBaptiste Daroussin re_refresh(EditLine *el)
231*d0ef721eSBaptiste Daroussin {
232*d0ef721eSBaptiste Daroussin 	int i, rhdiff;
233*d0ef721eSBaptiste Daroussin 	wchar_t *cp, *st;
234*d0ef721eSBaptiste Daroussin 	coord_t cur;
235*d0ef721eSBaptiste Daroussin #ifdef notyet
236*d0ef721eSBaptiste Daroussin 	size_t termsz;
237*d0ef721eSBaptiste Daroussin #endif
238*d0ef721eSBaptiste Daroussin 
239*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%ls:\r\n",
240*d0ef721eSBaptiste Daroussin 	    el->el_line.buffer));
241*d0ef721eSBaptiste Daroussin 
242*d0ef721eSBaptiste Daroussin 	literal_clear(el);
243*d0ef721eSBaptiste Daroussin 	/* reset the Drawing cursor */
244*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_cursor.h = 0;
245*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_cursor.v = 0;
246*d0ef721eSBaptiste Daroussin 
247*d0ef721eSBaptiste Daroussin 	terminal_move_to_char(el, 0);
248*d0ef721eSBaptiste Daroussin 
249*d0ef721eSBaptiste Daroussin 	/* temporarily draw rprompt to calculate its size */
250*d0ef721eSBaptiste Daroussin 	prompt_print(el, EL_RPROMPT);
251*d0ef721eSBaptiste Daroussin 
252*d0ef721eSBaptiste Daroussin 	/* reset the Drawing cursor */
253*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_cursor.h = 0;
254*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_cursor.v = 0;
255*d0ef721eSBaptiste Daroussin 
256*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor >= el->el_line.lastchar) {
257*d0ef721eSBaptiste Daroussin 		if (el->el_map.current == el->el_map.alt
258*d0ef721eSBaptiste Daroussin 		    && el->el_line.lastchar != el->el_line.buffer)
259*d0ef721eSBaptiste Daroussin 			el->el_line.cursor = el->el_line.lastchar - 1;
260*d0ef721eSBaptiste Daroussin 		else
261*d0ef721eSBaptiste Daroussin 			el->el_line.cursor = el->el_line.lastchar;
262*d0ef721eSBaptiste Daroussin 	}
263*d0ef721eSBaptiste Daroussin 
264*d0ef721eSBaptiste Daroussin 	cur.h = -1;		/* set flag in case I'm not set */
265*d0ef721eSBaptiste Daroussin 	cur.v = 0;
266*d0ef721eSBaptiste Daroussin 
267*d0ef721eSBaptiste Daroussin 	prompt_print(el, EL_PROMPT);
268*d0ef721eSBaptiste Daroussin 
269*d0ef721eSBaptiste Daroussin 	/* draw the current input buffer */
270*d0ef721eSBaptiste Daroussin #if notyet
271*d0ef721eSBaptiste Daroussin 	termsz = el->el_terminal.t_size.h * el->el_terminal.t_size.v;
272*d0ef721eSBaptiste Daroussin 	if (el->el_line.lastchar - el->el_line.buffer > termsz) {
273*d0ef721eSBaptiste Daroussin 		/*
274*d0ef721eSBaptiste Daroussin 		 * If line is longer than terminal, process only part
275*d0ef721eSBaptiste Daroussin 		 * of line which would influence display.
276*d0ef721eSBaptiste Daroussin 		 */
277*d0ef721eSBaptiste Daroussin 		size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz;
278*d0ef721eSBaptiste Daroussin 
279*d0ef721eSBaptiste Daroussin 		st = el->el_line.lastchar - rem
280*d0ef721eSBaptiste Daroussin 			- (termsz - (((rem / el->el_terminal.t_size.v) - 1)
281*d0ef721eSBaptiste Daroussin 					* el->el_terminal.t_size.v));
282*d0ef721eSBaptiste Daroussin 	} else
283*d0ef721eSBaptiste Daroussin #endif
284*d0ef721eSBaptiste Daroussin 		st = el->el_line.buffer;
285*d0ef721eSBaptiste Daroussin 
286*d0ef721eSBaptiste Daroussin 	for (cp = st; cp < el->el_line.lastchar; cp++) {
287*d0ef721eSBaptiste Daroussin 		if (cp == el->el_line.cursor) {
288*d0ef721eSBaptiste Daroussin                         int w = wcwidth(*cp);
289*d0ef721eSBaptiste Daroussin 			/* save for later */
290*d0ef721eSBaptiste Daroussin 			cur.h = el->el_refresh.r_cursor.h;
291*d0ef721eSBaptiste Daroussin 			cur.v = el->el_refresh.r_cursor.v;
292*d0ef721eSBaptiste Daroussin                         /* handle being at a linebroken doublewidth char */
293*d0ef721eSBaptiste Daroussin                         if (w > 1 && el->el_refresh.r_cursor.h + w >
294*d0ef721eSBaptiste Daroussin 			    el->el_terminal.t_size.h) {
295*d0ef721eSBaptiste Daroussin 				cur.h = 0;
296*d0ef721eSBaptiste Daroussin 				cur.v++;
297*d0ef721eSBaptiste Daroussin                         }
298*d0ef721eSBaptiste Daroussin 		}
299*d0ef721eSBaptiste Daroussin 		re_addc(el, *cp);
300*d0ef721eSBaptiste Daroussin 	}
301*d0ef721eSBaptiste Daroussin 
302*d0ef721eSBaptiste Daroussin 	if (cur.h == -1) {	/* if I haven't been set yet, I'm at the end */
303*d0ef721eSBaptiste Daroussin 		cur.h = el->el_refresh.r_cursor.h;
304*d0ef721eSBaptiste Daroussin 		cur.v = el->el_refresh.r_cursor.v;
305*d0ef721eSBaptiste Daroussin 	}
306*d0ef721eSBaptiste Daroussin 	rhdiff = el->el_terminal.t_size.h - el->el_refresh.r_cursor.h -
307*d0ef721eSBaptiste Daroussin 	    el->el_rprompt.p_pos.h;
308*d0ef721eSBaptiste Daroussin 	if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v &&
309*d0ef721eSBaptiste Daroussin 	    !el->el_refresh.r_cursor.v && rhdiff > 1) {
310*d0ef721eSBaptiste Daroussin 		/*
311*d0ef721eSBaptiste Daroussin 		 * have a right-hand side prompt that will fit
312*d0ef721eSBaptiste Daroussin 		 * on the end of the first line with at least
313*d0ef721eSBaptiste Daroussin 		 * one character gap to the input buffer.
314*d0ef721eSBaptiste Daroussin 		 */
315*d0ef721eSBaptiste Daroussin 		while (--rhdiff > 0)	/* pad out with spaces */
316*d0ef721eSBaptiste Daroussin 			re_putc(el, ' ', 1);
317*d0ef721eSBaptiste Daroussin 		prompt_print(el, EL_RPROMPT);
318*d0ef721eSBaptiste Daroussin 	} else {
319*d0ef721eSBaptiste Daroussin 		el->el_rprompt.p_pos.h = 0;	/* flag "not using rprompt" */
320*d0ef721eSBaptiste Daroussin 		el->el_rprompt.p_pos.v = 0;
321*d0ef721eSBaptiste Daroussin 	}
322*d0ef721eSBaptiste Daroussin 
323*d0ef721eSBaptiste Daroussin 	re_putc(el, '\0', 0);	/* make line ended with NUL, no cursor shift */
324*d0ef721eSBaptiste Daroussin 
325*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
326*d0ef721eSBaptiste Daroussin 
327*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F,
328*d0ef721eSBaptiste Daroussin 		"term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
329*d0ef721eSBaptiste Daroussin 		el->el_terminal.t_size.h, el->el_refresh.r_cursor.h,
330*d0ef721eSBaptiste Daroussin 		el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0],
331*d0ef721eSBaptiste Daroussin 		&el->el_scratch)));
332*d0ef721eSBaptiste Daroussin 
333*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv));
334*d0ef721eSBaptiste Daroussin 	for (i = 0; i <= el->el_refresh.r_newcv; i++) {
335*d0ef721eSBaptiste Daroussin 		/* NOTE THAT re_update_line MAY CHANGE el_display[i] */
336*d0ef721eSBaptiste Daroussin 		re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
337*d0ef721eSBaptiste Daroussin 
338*d0ef721eSBaptiste Daroussin 		/*
339*d0ef721eSBaptiste Daroussin 		 * Copy the new line to be the current one, and pad out with
340*d0ef721eSBaptiste Daroussin 		 * spaces to the full width of the terminal so that if we try
341*d0ef721eSBaptiste Daroussin 		 * moving the cursor by writing the character that is at the
342*d0ef721eSBaptiste Daroussin 		 * end of the screen line, it won't be a NUL or some old
343*d0ef721eSBaptiste Daroussin 		 * leftover stuff.
344*d0ef721eSBaptiste Daroussin 		 */
345*d0ef721eSBaptiste Daroussin 		re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
346*d0ef721eSBaptiste Daroussin 		    (size_t) el->el_terminal.t_size.h);
347*d0ef721eSBaptiste Daroussin 	}
348*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F,
349*d0ef721eSBaptiste Daroussin 	"\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
350*d0ef721eSBaptiste Daroussin 	    el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i));
351*d0ef721eSBaptiste Daroussin 
352*d0ef721eSBaptiste Daroussin 	if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
353*d0ef721eSBaptiste Daroussin 		for (; i <= el->el_refresh.r_oldcv; i++) {
354*d0ef721eSBaptiste Daroussin 			terminal_move_to_line(el, i);
355*d0ef721eSBaptiste Daroussin 			terminal_move_to_char(el, 0);
356*d0ef721eSBaptiste Daroussin                         /* This wcslen should be safe even with MB_FILL_CHARs */
357*d0ef721eSBaptiste Daroussin 			terminal_clear_EOL(el, (int) wcslen(el->el_display[i]));
358*d0ef721eSBaptiste Daroussin #ifdef DEBUG_REFRESH
359*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, L"C\b", 2);
360*d0ef721eSBaptiste Daroussin #endif /* DEBUG_REFRESH */
361*d0ef721eSBaptiste Daroussin 			el->el_display[i][0] = '\0';
362*d0ef721eSBaptiste Daroussin 		}
363*d0ef721eSBaptiste Daroussin 
364*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */
365*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F,
366*d0ef721eSBaptiste Daroussin 	    "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
367*d0ef721eSBaptiste Daroussin 	    el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
368*d0ef721eSBaptiste Daroussin 	    cur.h, cur.v));
369*d0ef721eSBaptiste Daroussin 	terminal_move_to_line(el, cur.v);	/* go to where the cursor is */
370*d0ef721eSBaptiste Daroussin 	terminal_move_to_char(el, cur.h);
371*d0ef721eSBaptiste Daroussin }
372*d0ef721eSBaptiste Daroussin 
373*d0ef721eSBaptiste Daroussin 
374*d0ef721eSBaptiste Daroussin /* re_goto_bottom():
375*d0ef721eSBaptiste Daroussin  *	 used to go to last used screen line
376*d0ef721eSBaptiste Daroussin  */
377*d0ef721eSBaptiste Daroussin libedit_private void
378*d0ef721eSBaptiste Daroussin re_goto_bottom(EditLine *el)
379*d0ef721eSBaptiste Daroussin {
380*d0ef721eSBaptiste Daroussin 
381*d0ef721eSBaptiste Daroussin 	terminal_move_to_line(el, el->el_refresh.r_oldcv);
382*d0ef721eSBaptiste Daroussin 	terminal__putc(el, '\n');
383*d0ef721eSBaptiste Daroussin 	re_clear_display(el);
384*d0ef721eSBaptiste Daroussin 	terminal__flush(el);
385*d0ef721eSBaptiste Daroussin }
386*d0ef721eSBaptiste Daroussin 
387*d0ef721eSBaptiste Daroussin 
388*d0ef721eSBaptiste Daroussin /* re_insert():
389*d0ef721eSBaptiste Daroussin  *	insert num characters of s into d (in front of the character)
390*d0ef721eSBaptiste Daroussin  *	at dat, maximum length of d is dlen
391*d0ef721eSBaptiste Daroussin  */
392*d0ef721eSBaptiste Daroussin static void
393*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
394*d0ef721eSBaptiste Daroussin re_insert(EditLine *el __attribute__((__unused__)),
395*d0ef721eSBaptiste Daroussin     wchar_t *d, int dat, int dlen, wchar_t *s, int num)
396*d0ef721eSBaptiste Daroussin {
397*d0ef721eSBaptiste Daroussin 	wchar_t *a, *b;
398*d0ef721eSBaptiste Daroussin 
399*d0ef721eSBaptiste Daroussin 	if (num <= 0)
400*d0ef721eSBaptiste Daroussin 		return;
401*d0ef721eSBaptiste Daroussin 	if (num > dlen - dat)
402*d0ef721eSBaptiste Daroussin 		num = dlen - dat;
403*d0ef721eSBaptiste Daroussin 
404*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1,
405*d0ef721eSBaptiste Daroussin 	    (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
406*d0ef721eSBaptiste Daroussin 	    num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
407*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s,
408*d0ef721eSBaptiste Daroussin 	    &el->el_scratch)));
409*d0ef721eSBaptiste Daroussin 
410*d0ef721eSBaptiste Daroussin 	/* open up the space for num chars */
411*d0ef721eSBaptiste Daroussin 	if (num > 0) {
412*d0ef721eSBaptiste Daroussin 		b = d + dlen - 1;
413*d0ef721eSBaptiste Daroussin 		a = b - num;
414*d0ef721eSBaptiste Daroussin 		while (a >= &d[dat])
415*d0ef721eSBaptiste Daroussin 			*b-- = *a--;
416*d0ef721eSBaptiste Daroussin 		d[dlen] = '\0';	/* just in case */
417*d0ef721eSBaptiste Daroussin 	}
418*d0ef721eSBaptiste Daroussin 
419*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F,
420*d0ef721eSBaptiste Daroussin 		"re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
421*d0ef721eSBaptiste Daroussin 		num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
422*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s,
423*d0ef721eSBaptiste Daroussin 		&el->el_scratch)));
424*d0ef721eSBaptiste Daroussin 
425*d0ef721eSBaptiste Daroussin 	/* copy the characters */
426*d0ef721eSBaptiste Daroussin 	for (a = d + dat; (a < d + dlen) && (num > 0); num--)
427*d0ef721eSBaptiste Daroussin 		*a++ = *s++;
428*d0ef721eSBaptiste Daroussin 
429*d0ef721eSBaptiste Daroussin #ifdef notyet
430*d0ef721eSBaptiste Daroussin         /* ct_encode_string() uses a static buffer, so we can't conveniently
431*d0ef721eSBaptiste Daroussin          * encode both d & s here */
432*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1,
433*d0ef721eSBaptiste Daroussin 	    (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
434*d0ef721eSBaptiste Daroussin 	    num, dat, dlen, d, s));
435*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s));
436*d0ef721eSBaptiste Daroussin #endif
437*d0ef721eSBaptiste Daroussin }
438*d0ef721eSBaptiste Daroussin 
439*d0ef721eSBaptiste Daroussin 
440*d0ef721eSBaptiste Daroussin /* re_delete():
441*d0ef721eSBaptiste Daroussin  *	delete num characters d at dat, maximum length of d is dlen
442*d0ef721eSBaptiste Daroussin  */
443*d0ef721eSBaptiste Daroussin static void
444*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
445*d0ef721eSBaptiste Daroussin re_delete(EditLine *el __attribute__((__unused__)),
446*d0ef721eSBaptiste Daroussin     wchar_t *d, int dat, int dlen, int num)
447*d0ef721eSBaptiste Daroussin {
448*d0ef721eSBaptiste Daroussin 	wchar_t *a, *b;
449*d0ef721eSBaptiste Daroussin 
450*d0ef721eSBaptiste Daroussin 	if (num <= 0)
451*d0ef721eSBaptiste Daroussin 		return;
452*d0ef721eSBaptiste Daroussin 	if (dat + num >= dlen) {
453*d0ef721eSBaptiste Daroussin 		d[dat] = '\0';
454*d0ef721eSBaptiste Daroussin 		return;
455*d0ef721eSBaptiste Daroussin 	}
456*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1,
457*d0ef721eSBaptiste Daroussin 	    (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
458*d0ef721eSBaptiste Daroussin 	    num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
459*d0ef721eSBaptiste Daroussin 
460*d0ef721eSBaptiste Daroussin 	/* open up the space for num chars */
461*d0ef721eSBaptiste Daroussin 	if (num > 0) {
462*d0ef721eSBaptiste Daroussin 		b = d + dat;
463*d0ef721eSBaptiste Daroussin 		a = b + num;
464*d0ef721eSBaptiste Daroussin 		while (a < &d[dlen])
465*d0ef721eSBaptiste Daroussin 			*b++ = *a++;
466*d0ef721eSBaptiste Daroussin 		d[dlen] = '\0';	/* just in case */
467*d0ef721eSBaptiste Daroussin 	}
468*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1,
469*d0ef721eSBaptiste Daroussin 	    (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
470*d0ef721eSBaptiste Daroussin 	    num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
471*d0ef721eSBaptiste Daroussin }
472*d0ef721eSBaptiste Daroussin 
473*d0ef721eSBaptiste Daroussin 
474*d0ef721eSBaptiste Daroussin /* re__strncopy():
475*d0ef721eSBaptiste Daroussin  *	Like strncpy without padding.
476*d0ef721eSBaptiste Daroussin  */
477*d0ef721eSBaptiste Daroussin static void
478*d0ef721eSBaptiste Daroussin re__strncopy(wchar_t *a, wchar_t *b, size_t n)
479*d0ef721eSBaptiste Daroussin {
480*d0ef721eSBaptiste Daroussin 
481*d0ef721eSBaptiste Daroussin 	while (n-- && *b)
482*d0ef721eSBaptiste Daroussin 		*a++ = *b++;
483*d0ef721eSBaptiste Daroussin }
484*d0ef721eSBaptiste Daroussin 
485*d0ef721eSBaptiste Daroussin /* re_clear_eol():
486*d0ef721eSBaptiste Daroussin  *	Find the number of characters we need to clear till the end of line
487*d0ef721eSBaptiste Daroussin  *	in order to make sure that we have cleared the previous contents of
488*d0ef721eSBaptiste Daroussin  *	the line. fx and sx is the number of characters inserted or deleted
489*d0ef721eSBaptiste Daroussin  *	in the first or second diff, diff is the difference between the
490*d0ef721eSBaptiste Daroussin  *	number of characters between the new and old line.
491*d0ef721eSBaptiste Daroussin  */
492*d0ef721eSBaptiste Daroussin static void
493*d0ef721eSBaptiste Daroussin re_clear_eol(EditLine *el, int fx, int sx, int diff)
494*d0ef721eSBaptiste Daroussin {
495*d0ef721eSBaptiste Daroussin 
496*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "re_clear_eol sx %d, fx %d, diff %d\n",
497*d0ef721eSBaptiste Daroussin 	    sx, fx, diff));
498*d0ef721eSBaptiste Daroussin 
499*d0ef721eSBaptiste Daroussin 	if (fx < 0)
500*d0ef721eSBaptiste Daroussin 		fx = -fx;
501*d0ef721eSBaptiste Daroussin 	if (sx < 0)
502*d0ef721eSBaptiste Daroussin 		sx = -sx;
503*d0ef721eSBaptiste Daroussin 	if (fx > diff)
504*d0ef721eSBaptiste Daroussin 		diff = fx;
505*d0ef721eSBaptiste Daroussin 	if (sx > diff)
506*d0ef721eSBaptiste Daroussin 		diff = sx;
507*d0ef721eSBaptiste Daroussin 
508*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff));
509*d0ef721eSBaptiste Daroussin 	terminal_clear_EOL(el, diff);
510*d0ef721eSBaptiste Daroussin }
511*d0ef721eSBaptiste Daroussin 
512*d0ef721eSBaptiste Daroussin /*****************************************************************
513*d0ef721eSBaptiste Daroussin     re_update_line() is based on finding the middle difference of each line
514*d0ef721eSBaptiste Daroussin     on the screen; vis:
515*d0ef721eSBaptiste Daroussin 
516*d0ef721eSBaptiste Daroussin 			     /old first difference
517*d0ef721eSBaptiste Daroussin 	/beginning of line   |              /old last same       /old EOL
518*d0ef721eSBaptiste Daroussin 	v		     v              v                    v
519*d0ef721eSBaptiste Daroussin old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
520*d0ef721eSBaptiste Daroussin new:	eddie> Oh, my little buggy says to me, as lurgid as
521*d0ef721eSBaptiste Daroussin 	^		     ^        ^			   ^
522*d0ef721eSBaptiste Daroussin 	\beginning of line   |        \new last same	   \new end of line
523*d0ef721eSBaptiste Daroussin 			     \new first difference
524*d0ef721eSBaptiste Daroussin 
525*d0ef721eSBaptiste Daroussin     all are character pointers for the sake of speed.  Special cases for
526*d0ef721eSBaptiste Daroussin     no differences, as well as for end of line additions must be handled.
527*d0ef721eSBaptiste Daroussin **************************************************************** */
528*d0ef721eSBaptiste Daroussin 
529*d0ef721eSBaptiste Daroussin /* Minimum at which doing an insert it "worth it".  This should be about
530*d0ef721eSBaptiste Daroussin  * half the "cost" of going into insert mode, inserting a character, and
531*d0ef721eSBaptiste Daroussin  * going back out.  This should really be calculated from the termcap
532*d0ef721eSBaptiste Daroussin  * data...  For the moment, a good number for ANSI terminals.
533*d0ef721eSBaptiste Daroussin  */
534*d0ef721eSBaptiste Daroussin #define	MIN_END_KEEP	4
535*d0ef721eSBaptiste Daroussin 
536*d0ef721eSBaptiste Daroussin static void
537*d0ef721eSBaptiste Daroussin re_update_line(EditLine *el, wchar_t *old, wchar_t *new, int i)
538*d0ef721eSBaptiste Daroussin {
539*d0ef721eSBaptiste Daroussin 	wchar_t *o, *n, *p, c;
540*d0ef721eSBaptiste Daroussin 	wchar_t *ofd, *ols, *oe, *nfd, *nls, *ne;
541*d0ef721eSBaptiste Daroussin 	wchar_t *osb, *ose, *nsb, *nse;
542*d0ef721eSBaptiste Daroussin 	int fx, sx;
543*d0ef721eSBaptiste Daroussin 	size_t len;
544*d0ef721eSBaptiste Daroussin 
545*d0ef721eSBaptiste Daroussin 	/*
546*d0ef721eSBaptiste Daroussin          * find first diff
547*d0ef721eSBaptiste Daroussin          */
548*d0ef721eSBaptiste Daroussin 	for (o = old, n = new; *o && (*o == *n); o++, n++)
549*d0ef721eSBaptiste Daroussin 		continue;
550*d0ef721eSBaptiste Daroussin 	ofd = o;
551*d0ef721eSBaptiste Daroussin 	nfd = n;
552*d0ef721eSBaptiste Daroussin 
553*d0ef721eSBaptiste Daroussin 	/*
554*d0ef721eSBaptiste Daroussin          * Find the end of both old and new
555*d0ef721eSBaptiste Daroussin          */
556*d0ef721eSBaptiste Daroussin 	while (*o)
557*d0ef721eSBaptiste Daroussin 		o++;
558*d0ef721eSBaptiste Daroussin 	/*
559*d0ef721eSBaptiste Daroussin          * Remove any trailing blanks off of the end, being careful not to
560*d0ef721eSBaptiste Daroussin          * back up past the beginning.
561*d0ef721eSBaptiste Daroussin          */
562*d0ef721eSBaptiste Daroussin 	while (ofd < o) {
563*d0ef721eSBaptiste Daroussin 		if (o[-1] != ' ')
564*d0ef721eSBaptiste Daroussin 			break;
565*d0ef721eSBaptiste Daroussin 		o--;
566*d0ef721eSBaptiste Daroussin 	}
567*d0ef721eSBaptiste Daroussin 	oe = o;
568*d0ef721eSBaptiste Daroussin 	*oe = '\0';
569*d0ef721eSBaptiste Daroussin 
570*d0ef721eSBaptiste Daroussin 	while (*n)
571*d0ef721eSBaptiste Daroussin 		n++;
572*d0ef721eSBaptiste Daroussin 
573*d0ef721eSBaptiste Daroussin 	/* remove blanks from end of new */
574*d0ef721eSBaptiste Daroussin 	while (nfd < n) {
575*d0ef721eSBaptiste Daroussin 		if (n[-1] != ' ')
576*d0ef721eSBaptiste Daroussin 			break;
577*d0ef721eSBaptiste Daroussin 		n--;
578*d0ef721eSBaptiste Daroussin 	}
579*d0ef721eSBaptiste Daroussin 	ne = n;
580*d0ef721eSBaptiste Daroussin 	*ne = '\0';
581*d0ef721eSBaptiste Daroussin 
582*d0ef721eSBaptiste Daroussin 	/*
583*d0ef721eSBaptiste Daroussin          * if no diff, continue to next line of redraw
584*d0ef721eSBaptiste Daroussin          */
585*d0ef721eSBaptiste Daroussin 	if (*ofd == '\0' && *nfd == '\0') {
586*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1, (__F, "no difference.\r\n"));
587*d0ef721eSBaptiste Daroussin 		return;
588*d0ef721eSBaptiste Daroussin 	}
589*d0ef721eSBaptiste Daroussin 	/*
590*d0ef721eSBaptiste Daroussin          * find last same pointer
591*d0ef721eSBaptiste Daroussin          */
592*d0ef721eSBaptiste Daroussin 	while ((o > ofd) && (n > nfd) && (*--o == *--n))
593*d0ef721eSBaptiste Daroussin 		continue;
594*d0ef721eSBaptiste Daroussin 	ols = ++o;
595*d0ef721eSBaptiste Daroussin 	nls = ++n;
596*d0ef721eSBaptiste Daroussin 
597*d0ef721eSBaptiste Daroussin 	/*
598*d0ef721eSBaptiste Daroussin          * find same beginning and same end
599*d0ef721eSBaptiste Daroussin          */
600*d0ef721eSBaptiste Daroussin 	osb = ols;
601*d0ef721eSBaptiste Daroussin 	nsb = nls;
602*d0ef721eSBaptiste Daroussin 	ose = ols;
603*d0ef721eSBaptiste Daroussin 	nse = nls;
604*d0ef721eSBaptiste Daroussin 
605*d0ef721eSBaptiste Daroussin 	/*
606*d0ef721eSBaptiste Daroussin          * case 1: insert: scan from nfd to nls looking for *ofd
607*d0ef721eSBaptiste Daroussin          */
608*d0ef721eSBaptiste Daroussin 	if (*ofd) {
609*d0ef721eSBaptiste Daroussin 		for (c = *ofd, n = nfd; n < nls; n++) {
610*d0ef721eSBaptiste Daroussin 			if (c == *n) {
611*d0ef721eSBaptiste Daroussin 				for (o = ofd, p = n;
612*d0ef721eSBaptiste Daroussin 				    p < nls && o < ols && *o == *p;
613*d0ef721eSBaptiste Daroussin 				    o++, p++)
614*d0ef721eSBaptiste Daroussin 					continue;
615*d0ef721eSBaptiste Daroussin 				/*
616*d0ef721eSBaptiste Daroussin 				 * if the new match is longer and it's worth
617*d0ef721eSBaptiste Daroussin 				 * keeping, then we take it
618*d0ef721eSBaptiste Daroussin 				 */
619*d0ef721eSBaptiste Daroussin 				if (((nse - nsb) < (p - n)) &&
620*d0ef721eSBaptiste Daroussin 				    (2 * (p - n) > n - nfd)) {
621*d0ef721eSBaptiste Daroussin 					nsb = n;
622*d0ef721eSBaptiste Daroussin 					nse = p;
623*d0ef721eSBaptiste Daroussin 					osb = ofd;
624*d0ef721eSBaptiste Daroussin 					ose = o;
625*d0ef721eSBaptiste Daroussin 				}
626*d0ef721eSBaptiste Daroussin 			}
627*d0ef721eSBaptiste Daroussin 		}
628*d0ef721eSBaptiste Daroussin 	}
629*d0ef721eSBaptiste Daroussin 	/*
630*d0ef721eSBaptiste Daroussin          * case 2: delete: scan from ofd to ols looking for *nfd
631*d0ef721eSBaptiste Daroussin          */
632*d0ef721eSBaptiste Daroussin 	if (*nfd) {
633*d0ef721eSBaptiste Daroussin 		for (c = *nfd, o = ofd; o < ols; o++) {
634*d0ef721eSBaptiste Daroussin 			if (c == *o) {
635*d0ef721eSBaptiste Daroussin 				for (n = nfd, p = o;
636*d0ef721eSBaptiste Daroussin 				    p < ols && n < nls && *p == *n;
637*d0ef721eSBaptiste Daroussin 				    p++, n++)
638*d0ef721eSBaptiste Daroussin 					continue;
639*d0ef721eSBaptiste Daroussin 				/*
640*d0ef721eSBaptiste Daroussin 				 * if the new match is longer and it's worth
641*d0ef721eSBaptiste Daroussin 				 * keeping, then we take it
642*d0ef721eSBaptiste Daroussin 				 */
643*d0ef721eSBaptiste Daroussin 				if (((ose - osb) < (p - o)) &&
644*d0ef721eSBaptiste Daroussin 				    (2 * (p - o) > o - ofd)) {
645*d0ef721eSBaptiste Daroussin 					nsb = nfd;
646*d0ef721eSBaptiste Daroussin 					nse = n;
647*d0ef721eSBaptiste Daroussin 					osb = o;
648*d0ef721eSBaptiste Daroussin 					ose = p;
649*d0ef721eSBaptiste Daroussin 				}
650*d0ef721eSBaptiste Daroussin 			}
651*d0ef721eSBaptiste Daroussin 		}
652*d0ef721eSBaptiste Daroussin 	}
653*d0ef721eSBaptiste Daroussin 	/*
654*d0ef721eSBaptiste Daroussin          * Pragmatics I: If old trailing whitespace or not enough characters to
655*d0ef721eSBaptiste Daroussin          * save to be worth it, then don't save the last same info.
656*d0ef721eSBaptiste Daroussin          */
657*d0ef721eSBaptiste Daroussin 	if ((oe - ols) < MIN_END_KEEP) {
658*d0ef721eSBaptiste Daroussin 		ols = oe;
659*d0ef721eSBaptiste Daroussin 		nls = ne;
660*d0ef721eSBaptiste Daroussin 	}
661*d0ef721eSBaptiste Daroussin 	/*
662*d0ef721eSBaptiste Daroussin          * Pragmatics II: if the terminal isn't smart enough, make the data
663*d0ef721eSBaptiste Daroussin          * dumber so the smart update doesn't try anything fancy
664*d0ef721eSBaptiste Daroussin          */
665*d0ef721eSBaptiste Daroussin 
666*d0ef721eSBaptiste Daroussin 	/*
667*d0ef721eSBaptiste Daroussin          * fx is the number of characters we need to insert/delete: in the
668*d0ef721eSBaptiste Daroussin          * beginning to bring the two same begins together
669*d0ef721eSBaptiste Daroussin          */
670*d0ef721eSBaptiste Daroussin 	fx = (int)((nsb - nfd) - (osb - ofd));
671*d0ef721eSBaptiste Daroussin 	/*
672*d0ef721eSBaptiste Daroussin          * sx is the number of characters we need to insert/delete: in the
673*d0ef721eSBaptiste Daroussin          * end to bring the two same last parts together
674*d0ef721eSBaptiste Daroussin          */
675*d0ef721eSBaptiste Daroussin 	sx = (int)((nls - nse) - (ols - ose));
676*d0ef721eSBaptiste Daroussin 
677*d0ef721eSBaptiste Daroussin 	if (!EL_CAN_INSERT) {
678*d0ef721eSBaptiste Daroussin 		if (fx > 0) {
679*d0ef721eSBaptiste Daroussin 			osb = ols;
680*d0ef721eSBaptiste Daroussin 			ose = ols;
681*d0ef721eSBaptiste Daroussin 			nsb = nls;
682*d0ef721eSBaptiste Daroussin 			nse = nls;
683*d0ef721eSBaptiste Daroussin 		}
684*d0ef721eSBaptiste Daroussin 		if (sx > 0) {
685*d0ef721eSBaptiste Daroussin 			ols = oe;
686*d0ef721eSBaptiste Daroussin 			nls = ne;
687*d0ef721eSBaptiste Daroussin 		}
688*d0ef721eSBaptiste Daroussin 		if ((ols - ofd) < (nls - nfd)) {
689*d0ef721eSBaptiste Daroussin 			ols = oe;
690*d0ef721eSBaptiste Daroussin 			nls = ne;
691*d0ef721eSBaptiste Daroussin 		}
692*d0ef721eSBaptiste Daroussin 	}
693*d0ef721eSBaptiste Daroussin 	if (!EL_CAN_DELETE) {
694*d0ef721eSBaptiste Daroussin 		if (fx < 0) {
695*d0ef721eSBaptiste Daroussin 			osb = ols;
696*d0ef721eSBaptiste Daroussin 			ose = ols;
697*d0ef721eSBaptiste Daroussin 			nsb = nls;
698*d0ef721eSBaptiste Daroussin 			nse = nls;
699*d0ef721eSBaptiste Daroussin 		}
700*d0ef721eSBaptiste Daroussin 		if (sx < 0) {
701*d0ef721eSBaptiste Daroussin 			ols = oe;
702*d0ef721eSBaptiste Daroussin 			nls = ne;
703*d0ef721eSBaptiste Daroussin 		}
704*d0ef721eSBaptiste Daroussin 		if ((ols - ofd) > (nls - nfd)) {
705*d0ef721eSBaptiste Daroussin 			ols = oe;
706*d0ef721eSBaptiste Daroussin 			nls = ne;
707*d0ef721eSBaptiste Daroussin 		}
708*d0ef721eSBaptiste Daroussin 	}
709*d0ef721eSBaptiste Daroussin 	/*
710*d0ef721eSBaptiste Daroussin          * Pragmatics III: make sure the middle shifted pointers are correct if
711*d0ef721eSBaptiste Daroussin          * they don't point to anything (we may have moved ols or nls).
712*d0ef721eSBaptiste Daroussin          */
713*d0ef721eSBaptiste Daroussin 	/* if the change isn't worth it, don't bother */
714*d0ef721eSBaptiste Daroussin 	/* was: if (osb == ose) */
715*d0ef721eSBaptiste Daroussin 	if ((ose - osb) < MIN_END_KEEP) {
716*d0ef721eSBaptiste Daroussin 		osb = ols;
717*d0ef721eSBaptiste Daroussin 		ose = ols;
718*d0ef721eSBaptiste Daroussin 		nsb = nls;
719*d0ef721eSBaptiste Daroussin 		nse = nls;
720*d0ef721eSBaptiste Daroussin 	}
721*d0ef721eSBaptiste Daroussin 	/*
722*d0ef721eSBaptiste Daroussin          * Now that we are done with pragmatics we recompute fx, sx
723*d0ef721eSBaptiste Daroussin          */
724*d0ef721eSBaptiste Daroussin 	fx = (int)((nsb - nfd) - (osb - ofd));
725*d0ef721eSBaptiste Daroussin 	sx = (int)((nls - nse) - (ols - ose));
726*d0ef721eSBaptiste Daroussin 
727*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx));
728*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "ofd %td, osb %td, ose %td, ols %td, oe %td\n",
729*d0ef721eSBaptiste Daroussin 		ofd - old, osb - old, ose - old, ols - old, oe - old));
730*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "nfd %td, nsb %td, nse %td, nls %td, ne %td\n",
731*d0ef721eSBaptiste Daroussin 		nfd - new, nsb - new, nse - new, nls - new, ne - new));
732*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F,
733*d0ef721eSBaptiste Daroussin 		"xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"));
734*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F,
735*d0ef721eSBaptiste Daroussin 		"xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));
736*d0ef721eSBaptiste Daroussin #ifdef DEBUG_REFRESH
737*d0ef721eSBaptiste Daroussin 	re_printstr(el, "old- oe", old, oe);
738*d0ef721eSBaptiste Daroussin 	re_printstr(el, "new- ne", new, ne);
739*d0ef721eSBaptiste Daroussin 	re_printstr(el, "old-ofd", old, ofd);
740*d0ef721eSBaptiste Daroussin 	re_printstr(el, "new-nfd", new, nfd);
741*d0ef721eSBaptiste Daroussin 	re_printstr(el, "ofd-osb", ofd, osb);
742*d0ef721eSBaptiste Daroussin 	re_printstr(el, "nfd-nsb", nfd, nsb);
743*d0ef721eSBaptiste Daroussin 	re_printstr(el, "osb-ose", osb, ose);
744*d0ef721eSBaptiste Daroussin 	re_printstr(el, "nsb-nse", nsb, nse);
745*d0ef721eSBaptiste Daroussin 	re_printstr(el, "ose-ols", ose, ols);
746*d0ef721eSBaptiste Daroussin 	re_printstr(el, "nse-nls", nse, nls);
747*d0ef721eSBaptiste Daroussin 	re_printstr(el, "ols- oe", ols, oe);
748*d0ef721eSBaptiste Daroussin 	re_printstr(el, "nls- ne", nls, ne);
749*d0ef721eSBaptiste Daroussin #endif /* DEBUG_REFRESH */
750*d0ef721eSBaptiste Daroussin 
751*d0ef721eSBaptiste Daroussin 	/*
752*d0ef721eSBaptiste Daroussin          * el_cursor.v to this line i MUST be in this routine so that if we
753*d0ef721eSBaptiste Daroussin          * don't have to change the line, we don't move to it. el_cursor.h to
754*d0ef721eSBaptiste Daroussin          * first diff char
755*d0ef721eSBaptiste Daroussin          */
756*d0ef721eSBaptiste Daroussin 	terminal_move_to_line(el, i);
757*d0ef721eSBaptiste Daroussin 
758*d0ef721eSBaptiste Daroussin 	/*
759*d0ef721eSBaptiste Daroussin          * at this point we have something like this:
760*d0ef721eSBaptiste Daroussin          *
761*d0ef721eSBaptiste Daroussin          * /old                  /ofd    /osb               /ose    /ols     /oe
762*d0ef721eSBaptiste Daroussin          * v.....................v       v..................v       v........v
763*d0ef721eSBaptiste Daroussin          * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
764*d0ef721eSBaptiste Daroussin          * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
765*d0ef721eSBaptiste Daroussin          * ^.....................^     ^..................^       ^........^
766*d0ef721eSBaptiste Daroussin          * \new                  \nfd  \nsb               \nse     \nls    \ne
767*d0ef721eSBaptiste Daroussin          *
768*d0ef721eSBaptiste Daroussin          * fx is the difference in length between the chars between nfd and
769*d0ef721eSBaptiste Daroussin          * nsb, and the chars between ofd and osb, and is thus the number of
770*d0ef721eSBaptiste Daroussin          * characters to delete if < 0 (new is shorter than old, as above),
771*d0ef721eSBaptiste Daroussin          * or insert (new is longer than short).
772*d0ef721eSBaptiste Daroussin          *
773*d0ef721eSBaptiste Daroussin          * sx is the same for the second differences.
774*d0ef721eSBaptiste Daroussin          */
775*d0ef721eSBaptiste Daroussin 
776*d0ef721eSBaptiste Daroussin 	/*
777*d0ef721eSBaptiste Daroussin          * if we have a net insert on the first difference, AND inserting the
778*d0ef721eSBaptiste Daroussin          * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful
779*d0ef721eSBaptiste Daroussin          * character (which is ne if nls != ne, otherwise is nse) off the edge
780*d0ef721eSBaptiste Daroussin 	 * of the screen (el->el_terminal.t_size.h) else we do the deletes first
781*d0ef721eSBaptiste Daroussin 	 * so that we keep everything we need to.
782*d0ef721eSBaptiste Daroussin          */
783*d0ef721eSBaptiste Daroussin 
784*d0ef721eSBaptiste Daroussin 	/*
785*d0ef721eSBaptiste Daroussin          * if the last same is the same like the end, there is no last same
786*d0ef721eSBaptiste Daroussin          * part, otherwise we want to keep the last same part set p to the
787*d0ef721eSBaptiste Daroussin          * last useful old character
788*d0ef721eSBaptiste Daroussin          */
789*d0ef721eSBaptiste Daroussin 	p = (ols != oe) ? oe : ose;
790*d0ef721eSBaptiste Daroussin 
791*d0ef721eSBaptiste Daroussin 	/*
792*d0ef721eSBaptiste Daroussin          * if (There is a diffence in the beginning) && (we need to insert
793*d0ef721eSBaptiste Daroussin          *   characters) && (the number of characters to insert is less than
794*d0ef721eSBaptiste Daroussin          *   the term width)
795*d0ef721eSBaptiste Daroussin 	 *	We need to do an insert!
796*d0ef721eSBaptiste Daroussin 	 * else if (we need to delete characters)
797*d0ef721eSBaptiste Daroussin 	 *	We need to delete characters!
798*d0ef721eSBaptiste Daroussin 	 * else
799*d0ef721eSBaptiste Daroussin 	 *	No insert or delete
800*d0ef721eSBaptiste Daroussin          */
801*d0ef721eSBaptiste Daroussin 	if ((nsb != nfd) && fx > 0 &&
802*d0ef721eSBaptiste Daroussin 	    ((p - old) + fx <= el->el_terminal.t_size.h)) {
803*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1,
804*d0ef721eSBaptiste Daroussin 		    (__F, "first diff insert at %td...\r\n", nfd - new));
805*d0ef721eSBaptiste Daroussin 		/*
806*d0ef721eSBaptiste Daroussin 		 * Move to the first char to insert, where the first diff is.
807*d0ef721eSBaptiste Daroussin 		 */
808*d0ef721eSBaptiste Daroussin 		terminal_move_to_char(el, (int)(nfd - new));
809*d0ef721eSBaptiste Daroussin 		/*
810*d0ef721eSBaptiste Daroussin 		 * Check if we have stuff to keep at end
811*d0ef721eSBaptiste Daroussin 		 */
812*d0ef721eSBaptiste Daroussin 		if (nsb != ne) {
813*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
814*d0ef721eSBaptiste Daroussin 			/*
815*d0ef721eSBaptiste Daroussin 		         * insert fx chars of new starting at nfd
816*d0ef721eSBaptiste Daroussin 		         */
817*d0ef721eSBaptiste Daroussin 			if (fx > 0) {
818*d0ef721eSBaptiste Daroussin 				ELRE_DEBUG(!EL_CAN_INSERT, (__F,
819*d0ef721eSBaptiste Daroussin 				"ERROR: cannot insert in early first diff\n"));
820*d0ef721eSBaptiste Daroussin 				terminal_insertwrite(el, nfd, fx);
821*d0ef721eSBaptiste Daroussin 				re_insert(el, old, (int)(ofd - old),
822*d0ef721eSBaptiste Daroussin 				    el->el_terminal.t_size.h, nfd, fx);
823*d0ef721eSBaptiste Daroussin 			}
824*d0ef721eSBaptiste Daroussin 			/*
825*d0ef721eSBaptiste Daroussin 		         * write (nsb-nfd) - fx chars of new starting at
826*d0ef721eSBaptiste Daroussin 		         * (nfd + fx)
827*d0ef721eSBaptiste Daroussin 			 */
828*d0ef721eSBaptiste Daroussin 			len = (size_t) ((nsb - nfd) - fx);
829*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, (nfd + fx), len);
830*d0ef721eSBaptiste Daroussin 			re__strncopy(ofd + fx, nfd + fx, len);
831*d0ef721eSBaptiste Daroussin 		} else {
832*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
833*d0ef721eSBaptiste Daroussin 			len = (size_t)(nsb - nfd);
834*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nfd, len);
835*d0ef721eSBaptiste Daroussin 			re__strncopy(ofd, nfd, len);
836*d0ef721eSBaptiste Daroussin 			/*
837*d0ef721eSBaptiste Daroussin 		         * Done
838*d0ef721eSBaptiste Daroussin 		         */
839*d0ef721eSBaptiste Daroussin 			return;
840*d0ef721eSBaptiste Daroussin 		}
841*d0ef721eSBaptiste Daroussin 	} else if (fx < 0) {
842*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1,
843*d0ef721eSBaptiste Daroussin 		    (__F, "first diff delete at %td...\r\n", ofd - old));
844*d0ef721eSBaptiste Daroussin 		/*
845*d0ef721eSBaptiste Daroussin 		 * move to the first char to delete where the first diff is
846*d0ef721eSBaptiste Daroussin 		 */
847*d0ef721eSBaptiste Daroussin 		terminal_move_to_char(el, (int)(ofd - old));
848*d0ef721eSBaptiste Daroussin 		/*
849*d0ef721eSBaptiste Daroussin 		 * Check if we have stuff to save
850*d0ef721eSBaptiste Daroussin 		 */
851*d0ef721eSBaptiste Daroussin 		if (osb != oe) {
852*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
853*d0ef721eSBaptiste Daroussin 			/*
854*d0ef721eSBaptiste Daroussin 		         * fx is less than zero *always* here but we check
855*d0ef721eSBaptiste Daroussin 		         * for code symmetry
856*d0ef721eSBaptiste Daroussin 		         */
857*d0ef721eSBaptiste Daroussin 			if (fx < 0) {
858*d0ef721eSBaptiste Daroussin 				ELRE_DEBUG(!EL_CAN_DELETE, (__F,
859*d0ef721eSBaptiste Daroussin 				    "ERROR: cannot delete in first diff\n"));
860*d0ef721eSBaptiste Daroussin 				terminal_deletechars(el, -fx);
861*d0ef721eSBaptiste Daroussin 				re_delete(el, old, (int)(ofd - old),
862*d0ef721eSBaptiste Daroussin 				    el->el_terminal.t_size.h, -fx);
863*d0ef721eSBaptiste Daroussin 			}
864*d0ef721eSBaptiste Daroussin 			/*
865*d0ef721eSBaptiste Daroussin 		         * write (nsb-nfd) chars of new starting at nfd
866*d0ef721eSBaptiste Daroussin 		         */
867*d0ef721eSBaptiste Daroussin 			len = (size_t) (nsb - nfd);
868*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nfd, len);
869*d0ef721eSBaptiste Daroussin 			re__strncopy(ofd, nfd, len);
870*d0ef721eSBaptiste Daroussin 
871*d0ef721eSBaptiste Daroussin 		} else {
872*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F,
873*d0ef721eSBaptiste Daroussin 			    "but with nothing left to save\r\n"));
874*d0ef721eSBaptiste Daroussin 			/*
875*d0ef721eSBaptiste Daroussin 		         * write (nsb-nfd) chars of new starting at nfd
876*d0ef721eSBaptiste Daroussin 		         */
877*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nfd, (size_t)(nsb - nfd));
878*d0ef721eSBaptiste Daroussin 			re_clear_eol(el, fx, sx,
879*d0ef721eSBaptiste Daroussin 			    (int)((oe - old) - (ne - new)));
880*d0ef721eSBaptiste Daroussin 			/*
881*d0ef721eSBaptiste Daroussin 		         * Done
882*d0ef721eSBaptiste Daroussin 		         */
883*d0ef721eSBaptiste Daroussin 			return;
884*d0ef721eSBaptiste Daroussin 		}
885*d0ef721eSBaptiste Daroussin 	} else
886*d0ef721eSBaptiste Daroussin 		fx = 0;
887*d0ef721eSBaptiste Daroussin 
888*d0ef721eSBaptiste Daroussin 	if (sx < 0 && (ose - old) + fx < el->el_terminal.t_size.h) {
889*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1, (__F,
890*d0ef721eSBaptiste Daroussin 		    "second diff delete at %td...\r\n", (ose - old) + fx));
891*d0ef721eSBaptiste Daroussin 		/*
892*d0ef721eSBaptiste Daroussin 		 * Check if we have stuff to delete
893*d0ef721eSBaptiste Daroussin 		 */
894*d0ef721eSBaptiste Daroussin 		/*
895*d0ef721eSBaptiste Daroussin 		 * fx is the number of characters inserted (+) or deleted (-)
896*d0ef721eSBaptiste Daroussin 		 */
897*d0ef721eSBaptiste Daroussin 
898*d0ef721eSBaptiste Daroussin 		terminal_move_to_char(el, (int)((ose - old) + fx));
899*d0ef721eSBaptiste Daroussin 		/*
900*d0ef721eSBaptiste Daroussin 		 * Check if we have stuff to save
901*d0ef721eSBaptiste Daroussin 		 */
902*d0ef721eSBaptiste Daroussin 		if (ols != oe) {
903*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
904*d0ef721eSBaptiste Daroussin 			/*
905*d0ef721eSBaptiste Daroussin 		         * Again a duplicate test.
906*d0ef721eSBaptiste Daroussin 		         */
907*d0ef721eSBaptiste Daroussin 			if (sx < 0) {
908*d0ef721eSBaptiste Daroussin 				ELRE_DEBUG(!EL_CAN_DELETE, (__F,
909*d0ef721eSBaptiste Daroussin 				    "ERROR: cannot delete in second diff\n"));
910*d0ef721eSBaptiste Daroussin 				terminal_deletechars(el, -sx);
911*d0ef721eSBaptiste Daroussin 			}
912*d0ef721eSBaptiste Daroussin 			/*
913*d0ef721eSBaptiste Daroussin 		         * write (nls-nse) chars of new starting at nse
914*d0ef721eSBaptiste Daroussin 		         */
915*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nse, (size_t)(nls - nse));
916*d0ef721eSBaptiste Daroussin 		} else {
917*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F,
918*d0ef721eSBaptiste Daroussin 			    "but with nothing left to save\r\n"));
919*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nse, (size_t)(nls - nse));
920*d0ef721eSBaptiste Daroussin 			re_clear_eol(el, fx, sx,
921*d0ef721eSBaptiste Daroussin 			    (int)((oe - old) - (ne - new)));
922*d0ef721eSBaptiste Daroussin 		}
923*d0ef721eSBaptiste Daroussin 	}
924*d0ef721eSBaptiste Daroussin 	/*
925*d0ef721eSBaptiste Daroussin          * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
926*d0ef721eSBaptiste Daroussin          */
927*d0ef721eSBaptiste Daroussin 	if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
928*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1, (__F, "late first diff insert at %td...\r\n",
929*d0ef721eSBaptiste Daroussin 		    nfd - new));
930*d0ef721eSBaptiste Daroussin 
931*d0ef721eSBaptiste Daroussin 		terminal_move_to_char(el, (int)(nfd - new));
932*d0ef721eSBaptiste Daroussin 		/*
933*d0ef721eSBaptiste Daroussin 		 * Check if we have stuff to keep at the end
934*d0ef721eSBaptiste Daroussin 		 */
935*d0ef721eSBaptiste Daroussin 		if (nsb != ne) {
936*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
937*d0ef721eSBaptiste Daroussin 			/*
938*d0ef721eSBaptiste Daroussin 		         * We have to recalculate fx here because we set it
939*d0ef721eSBaptiste Daroussin 		         * to zero above as a flag saying that we hadn't done
940*d0ef721eSBaptiste Daroussin 		         * an early first insert.
941*d0ef721eSBaptiste Daroussin 		         */
942*d0ef721eSBaptiste Daroussin 			fx = (int)((nsb - nfd) - (osb - ofd));
943*d0ef721eSBaptiste Daroussin 			if (fx > 0) {
944*d0ef721eSBaptiste Daroussin 				/*
945*d0ef721eSBaptiste Daroussin 				 * insert fx chars of new starting at nfd
946*d0ef721eSBaptiste Daroussin 				 */
947*d0ef721eSBaptiste Daroussin 				ELRE_DEBUG(!EL_CAN_INSERT, (__F,
948*d0ef721eSBaptiste Daroussin 				 "ERROR: cannot insert in late first diff\n"));
949*d0ef721eSBaptiste Daroussin 				terminal_insertwrite(el, nfd, fx);
950*d0ef721eSBaptiste Daroussin 				re_insert(el, old, (int)(ofd - old),
951*d0ef721eSBaptiste Daroussin 				    el->el_terminal.t_size.h, nfd, fx);
952*d0ef721eSBaptiste Daroussin 			}
953*d0ef721eSBaptiste Daroussin 			/*
954*d0ef721eSBaptiste Daroussin 		         * write (nsb-nfd) - fx chars of new starting at
955*d0ef721eSBaptiste Daroussin 		         * (nfd + fx)
956*d0ef721eSBaptiste Daroussin 			 */
957*d0ef721eSBaptiste Daroussin 			len = (size_t) ((nsb - nfd) - fx);
958*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, (nfd + fx), len);
959*d0ef721eSBaptiste Daroussin 			re__strncopy(ofd + fx, nfd + fx, len);
960*d0ef721eSBaptiste Daroussin 		} else {
961*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
962*d0ef721eSBaptiste Daroussin 			len = (size_t) (nsb - nfd);
963*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nfd, len);
964*d0ef721eSBaptiste Daroussin 			re__strncopy(ofd, nfd, len);
965*d0ef721eSBaptiste Daroussin 		}
966*d0ef721eSBaptiste Daroussin 	}
967*d0ef721eSBaptiste Daroussin 	/*
968*d0ef721eSBaptiste Daroussin          * line is now NEW up to nse
969*d0ef721eSBaptiste Daroussin          */
970*d0ef721eSBaptiste Daroussin 	if (sx >= 0) {
971*d0ef721eSBaptiste Daroussin 		ELRE_DEBUG(1, (__F,
972*d0ef721eSBaptiste Daroussin 		    "second diff insert at %d...\r\n", (int)(nse - new)));
973*d0ef721eSBaptiste Daroussin 		terminal_move_to_char(el, (int)(nse - new));
974*d0ef721eSBaptiste Daroussin 		if (ols != oe) {
975*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
976*d0ef721eSBaptiste Daroussin 			if (sx > 0) {
977*d0ef721eSBaptiste Daroussin 				/* insert sx chars of new starting at nse */
978*d0ef721eSBaptiste Daroussin 				ELRE_DEBUG(!EL_CAN_INSERT, (__F,
979*d0ef721eSBaptiste Daroussin 				    "ERROR: cannot insert in second diff\n"));
980*d0ef721eSBaptiste Daroussin 				terminal_insertwrite(el, nse, sx);
981*d0ef721eSBaptiste Daroussin 			}
982*d0ef721eSBaptiste Daroussin 			/*
983*d0ef721eSBaptiste Daroussin 		         * write (nls-nse) - sx chars of new starting at
984*d0ef721eSBaptiste Daroussin 			 * (nse + sx)
985*d0ef721eSBaptiste Daroussin 		         */
986*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, (nse + sx),
987*d0ef721eSBaptiste Daroussin 			    (size_t)((nls - nse) - sx));
988*d0ef721eSBaptiste Daroussin 		} else {
989*d0ef721eSBaptiste Daroussin 			ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
990*d0ef721eSBaptiste Daroussin 			terminal_overwrite(el, nse, (size_t)(nls - nse));
991*d0ef721eSBaptiste Daroussin 
992*d0ef721eSBaptiste Daroussin 			/*
993*d0ef721eSBaptiste Daroussin 	                 * No need to do a clear-to-end here because we were
994*d0ef721eSBaptiste Daroussin 	                 * doing a second insert, so we will have over
995*d0ef721eSBaptiste Daroussin 	                 * written all of the old string.
996*d0ef721eSBaptiste Daroussin 		         */
997*d0ef721eSBaptiste Daroussin 		}
998*d0ef721eSBaptiste Daroussin 	}
999*d0ef721eSBaptiste Daroussin 	ELRE_DEBUG(1, (__F, "done.\r\n"));
1000*d0ef721eSBaptiste Daroussin }
1001*d0ef721eSBaptiste Daroussin 
1002*d0ef721eSBaptiste Daroussin 
1003*d0ef721eSBaptiste Daroussin /* re__copy_and_pad():
1004*d0ef721eSBaptiste Daroussin  *	Copy string and pad with spaces
1005*d0ef721eSBaptiste Daroussin  */
1006*d0ef721eSBaptiste Daroussin static void
1007*d0ef721eSBaptiste Daroussin re__copy_and_pad(wchar_t *dst, const wchar_t *src, size_t width)
1008*d0ef721eSBaptiste Daroussin {
1009*d0ef721eSBaptiste Daroussin 	size_t i;
1010*d0ef721eSBaptiste Daroussin 
1011*d0ef721eSBaptiste Daroussin 	for (i = 0; i < width; i++) {
1012*d0ef721eSBaptiste Daroussin 		if (*src == '\0')
1013*d0ef721eSBaptiste Daroussin 			break;
1014*d0ef721eSBaptiste Daroussin 		*dst++ = *src++;
1015*d0ef721eSBaptiste Daroussin 	}
1016*d0ef721eSBaptiste Daroussin 
1017*d0ef721eSBaptiste Daroussin 	for (; i < width; i++)
1018*d0ef721eSBaptiste Daroussin 		*dst++ = ' ';
1019*d0ef721eSBaptiste Daroussin 
1020*d0ef721eSBaptiste Daroussin 	*dst = '\0';
1021*d0ef721eSBaptiste Daroussin }
1022*d0ef721eSBaptiste Daroussin 
1023*d0ef721eSBaptiste Daroussin 
1024*d0ef721eSBaptiste Daroussin /* re_refresh_cursor():
1025*d0ef721eSBaptiste Daroussin  *	Move to the new cursor position
1026*d0ef721eSBaptiste Daroussin  */
1027*d0ef721eSBaptiste Daroussin libedit_private void
1028*d0ef721eSBaptiste Daroussin re_refresh_cursor(EditLine *el)
1029*d0ef721eSBaptiste Daroussin {
1030*d0ef721eSBaptiste Daroussin 	wchar_t *cp;
1031*d0ef721eSBaptiste Daroussin 	int h, v, th, w;
1032*d0ef721eSBaptiste Daroussin 
1033*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor >= el->el_line.lastchar) {
1034*d0ef721eSBaptiste Daroussin 		if (el->el_map.current == el->el_map.alt
1035*d0ef721eSBaptiste Daroussin 		    && el->el_line.lastchar != el->el_line.buffer)
1036*d0ef721eSBaptiste Daroussin 			el->el_line.cursor = el->el_line.lastchar - 1;
1037*d0ef721eSBaptiste Daroussin 		else
1038*d0ef721eSBaptiste Daroussin 			el->el_line.cursor = el->el_line.lastchar;
1039*d0ef721eSBaptiste Daroussin 	}
1040*d0ef721eSBaptiste Daroussin 
1041*d0ef721eSBaptiste Daroussin 	/* first we must find where the cursor is... */
1042*d0ef721eSBaptiste Daroussin 	h = el->el_prompt.p_pos.h;
1043*d0ef721eSBaptiste Daroussin 	v = el->el_prompt.p_pos.v;
1044*d0ef721eSBaptiste Daroussin 	th = el->el_terminal.t_size.h;	/* optimize for speed */
1045*d0ef721eSBaptiste Daroussin 
1046*d0ef721eSBaptiste Daroussin 	/* do input buffer to el->el_line.cursor */
1047*d0ef721eSBaptiste Daroussin 	for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
1048*d0ef721eSBaptiste Daroussin                 switch (ct_chr_class(*cp)) {
1049*d0ef721eSBaptiste Daroussin 		case CHTYPE_NL:  /* handle newline in data part too */
1050*d0ef721eSBaptiste Daroussin 			h = 0;
1051*d0ef721eSBaptiste Daroussin 			v++;
1052*d0ef721eSBaptiste Daroussin 			break;
1053*d0ef721eSBaptiste Daroussin 		case CHTYPE_TAB: /* if a tab, to next tab stop */
1054*d0ef721eSBaptiste Daroussin 			while (++h & 07)
1055*d0ef721eSBaptiste Daroussin 				continue;
1056*d0ef721eSBaptiste Daroussin 			break;
1057*d0ef721eSBaptiste Daroussin 		default:
1058*d0ef721eSBaptiste Daroussin 			w = wcwidth(*cp);
1059*d0ef721eSBaptiste Daroussin 			if (w > 1 && h + w > th) { /* won't fit on line */
1060*d0ef721eSBaptiste Daroussin 				h = 0;
1061*d0ef721eSBaptiste Daroussin 				v++;
1062*d0ef721eSBaptiste Daroussin 			}
1063*d0ef721eSBaptiste Daroussin 			h += ct_visual_width(*cp);
1064*d0ef721eSBaptiste Daroussin 			break;
1065*d0ef721eSBaptiste Daroussin                 }
1066*d0ef721eSBaptiste Daroussin 
1067*d0ef721eSBaptiste Daroussin 		if (h >= th) {	/* check, extra long tabs picked up here also */
1068*d0ef721eSBaptiste Daroussin 			h -= th;
1069*d0ef721eSBaptiste Daroussin 			v++;
1070*d0ef721eSBaptiste Daroussin 		}
1071*d0ef721eSBaptiste Daroussin 	}
1072*d0ef721eSBaptiste Daroussin         /* if we have a next character, and it's a doublewidth one, we need to
1073*d0ef721eSBaptiste Daroussin          * check whether we need to linebreak for it to fit */
1074*d0ef721eSBaptiste Daroussin         if (cp < el->el_line.lastchar && (w = wcwidth(*cp)) > 1)
1075*d0ef721eSBaptiste Daroussin                 if (h + w > th) {
1076*d0ef721eSBaptiste Daroussin                     h = 0;
1077*d0ef721eSBaptiste Daroussin                     v++;
1078*d0ef721eSBaptiste Daroussin                 }
1079*d0ef721eSBaptiste Daroussin 
1080*d0ef721eSBaptiste Daroussin 	/* now go there */
1081*d0ef721eSBaptiste Daroussin 	terminal_move_to_line(el, v);
1082*d0ef721eSBaptiste Daroussin 	terminal_move_to_char(el, h);
1083*d0ef721eSBaptiste Daroussin 	terminal__flush(el);
1084*d0ef721eSBaptiste Daroussin }
1085*d0ef721eSBaptiste Daroussin 
1086*d0ef721eSBaptiste Daroussin 
1087*d0ef721eSBaptiste Daroussin /* re_fastputc():
1088*d0ef721eSBaptiste Daroussin  *	Add a character fast.
1089*d0ef721eSBaptiste Daroussin  */
1090*d0ef721eSBaptiste Daroussin static void
1091*d0ef721eSBaptiste Daroussin re_fastputc(EditLine *el, wint_t c)
1092*d0ef721eSBaptiste Daroussin {
1093*d0ef721eSBaptiste Daroussin 	wchar_t *lastline;
1094*d0ef721eSBaptiste Daroussin 	int w;
1095*d0ef721eSBaptiste Daroussin 
1096*d0ef721eSBaptiste Daroussin 	w = wcwidth(c);
1097*d0ef721eSBaptiste Daroussin 	while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h)
1098*d0ef721eSBaptiste Daroussin 	    re_fastputc(el, ' ');
1099*d0ef721eSBaptiste Daroussin 
1100*d0ef721eSBaptiste Daroussin 	terminal__putc(el, c);
1101*d0ef721eSBaptiste Daroussin 	el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
1102*d0ef721eSBaptiste Daroussin 	while (--w > 0)
1103*d0ef721eSBaptiste Daroussin 		el->el_display[el->el_cursor.v][el->el_cursor.h++]
1104*d0ef721eSBaptiste Daroussin 			= MB_FILL_CHAR;
1105*d0ef721eSBaptiste Daroussin 
1106*d0ef721eSBaptiste Daroussin 	if (el->el_cursor.h >= el->el_terminal.t_size.h) {
1107*d0ef721eSBaptiste Daroussin 		/* if we must overflow */
1108*d0ef721eSBaptiste Daroussin 		el->el_cursor.h = 0;
1109*d0ef721eSBaptiste Daroussin 
1110*d0ef721eSBaptiste Daroussin 		/*
1111*d0ef721eSBaptiste Daroussin 		 * If we would overflow (input is longer than terminal size),
1112*d0ef721eSBaptiste Daroussin 		 * emulate scroll by dropping first line and shuffling the rest.
1113*d0ef721eSBaptiste Daroussin 		 * We do this via pointer shuffling - it's safe in this case
1114*d0ef721eSBaptiste Daroussin 		 * and we avoid memcpy().
1115*d0ef721eSBaptiste Daroussin 		 */
1116*d0ef721eSBaptiste Daroussin 		if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) {
1117*d0ef721eSBaptiste Daroussin 			int i, lins = el->el_terminal.t_size.v;
1118*d0ef721eSBaptiste Daroussin 
1119*d0ef721eSBaptiste Daroussin 			lastline = el->el_display[0];
1120*d0ef721eSBaptiste Daroussin 			for(i = 1; i < lins; i++)
1121*d0ef721eSBaptiste Daroussin 				el->el_display[i - 1] = el->el_display[i];
1122*d0ef721eSBaptiste Daroussin 
1123*d0ef721eSBaptiste Daroussin 			el->el_display[i - 1] = lastline;
1124*d0ef721eSBaptiste Daroussin 		} else {
1125*d0ef721eSBaptiste Daroussin 			el->el_cursor.v++;
1126*d0ef721eSBaptiste Daroussin 			lastline = el->el_display[++el->el_refresh.r_oldcv];
1127*d0ef721eSBaptiste Daroussin 		}
1128*d0ef721eSBaptiste Daroussin 		re__copy_and_pad(lastline, L"", (size_t)el->el_terminal.t_size.h);
1129*d0ef721eSBaptiste Daroussin 
1130*d0ef721eSBaptiste Daroussin 		if (EL_HAS_AUTO_MARGINS) {
1131*d0ef721eSBaptiste Daroussin 			if (EL_HAS_MAGIC_MARGINS) {
1132*d0ef721eSBaptiste Daroussin 				terminal__putc(el, ' ');
1133*d0ef721eSBaptiste Daroussin 				terminal__putc(el, '\b');
1134*d0ef721eSBaptiste Daroussin 			}
1135*d0ef721eSBaptiste Daroussin 		} else {
1136*d0ef721eSBaptiste Daroussin 			terminal__putc(el, '\r');
1137*d0ef721eSBaptiste Daroussin 			terminal__putc(el, '\n');
1138*d0ef721eSBaptiste Daroussin 		}
1139*d0ef721eSBaptiste Daroussin 	}
1140*d0ef721eSBaptiste Daroussin }
1141*d0ef721eSBaptiste Daroussin 
1142*d0ef721eSBaptiste Daroussin 
1143*d0ef721eSBaptiste Daroussin /* re_fastaddc():
1144*d0ef721eSBaptiste Daroussin  *	we added just one char, handle it fast.
1145*d0ef721eSBaptiste Daroussin  *	Assumes that screen cursor == real cursor
1146*d0ef721eSBaptiste Daroussin  */
1147*d0ef721eSBaptiste Daroussin libedit_private void
1148*d0ef721eSBaptiste Daroussin re_fastaddc(EditLine *el)
1149*d0ef721eSBaptiste Daroussin {
1150*d0ef721eSBaptiste Daroussin 	wchar_t c;
1151*d0ef721eSBaptiste Daroussin 	int rhdiff;
1152*d0ef721eSBaptiste Daroussin 
1153*d0ef721eSBaptiste Daroussin 	c = el->el_line.cursor[-1];
1154*d0ef721eSBaptiste Daroussin 
1155*d0ef721eSBaptiste Daroussin 	if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
1156*d0ef721eSBaptiste Daroussin 		re_refresh(el);	/* too hard to handle */
1157*d0ef721eSBaptiste Daroussin 		return;
1158*d0ef721eSBaptiste Daroussin 	}
1159*d0ef721eSBaptiste Daroussin 	rhdiff = el->el_terminal.t_size.h - el->el_cursor.h -
1160*d0ef721eSBaptiste Daroussin 	    el->el_rprompt.p_pos.h;
1161*d0ef721eSBaptiste Daroussin 	if (el->el_rprompt.p_pos.h && rhdiff < 3) {
1162*d0ef721eSBaptiste Daroussin 		re_refresh(el);	/* clear out rprompt if less than 1 char gap */
1163*d0ef721eSBaptiste Daroussin 		return;
1164*d0ef721eSBaptiste Daroussin 	}			/* else (only do at end of line, no TAB) */
1165*d0ef721eSBaptiste Daroussin 	switch (ct_chr_class(c)) {
1166*d0ef721eSBaptiste Daroussin 	case CHTYPE_TAB: /* already handled, should never happen here */
1167*d0ef721eSBaptiste Daroussin 		break;
1168*d0ef721eSBaptiste Daroussin 	case CHTYPE_NL:
1169*d0ef721eSBaptiste Daroussin 	case CHTYPE_PRINT:
1170*d0ef721eSBaptiste Daroussin 		re_fastputc(el, c);
1171*d0ef721eSBaptiste Daroussin 		break;
1172*d0ef721eSBaptiste Daroussin 	case CHTYPE_ASCIICTL:
1173*d0ef721eSBaptiste Daroussin 	case CHTYPE_NONPRINT: {
1174*d0ef721eSBaptiste Daroussin 		wchar_t visbuf[VISUAL_WIDTH_MAX];
1175*d0ef721eSBaptiste Daroussin 		ssize_t i, n =
1176*d0ef721eSBaptiste Daroussin 		    ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
1177*d0ef721eSBaptiste Daroussin 		for (i = 0; n-- > 0; ++i)
1178*d0ef721eSBaptiste Daroussin 			re_fastputc(el, visbuf[i]);
1179*d0ef721eSBaptiste Daroussin 		break;
1180*d0ef721eSBaptiste Daroussin 	}
1181*d0ef721eSBaptiste Daroussin 	}
1182*d0ef721eSBaptiste Daroussin 	terminal__flush(el);
1183*d0ef721eSBaptiste Daroussin }
1184*d0ef721eSBaptiste Daroussin 
1185*d0ef721eSBaptiste Daroussin 
1186*d0ef721eSBaptiste Daroussin /* re_clear_display():
1187*d0ef721eSBaptiste Daroussin  *	clear the screen buffers so that new new prompt starts fresh.
1188*d0ef721eSBaptiste Daroussin  */
1189*d0ef721eSBaptiste Daroussin libedit_private void
1190*d0ef721eSBaptiste Daroussin re_clear_display(EditLine *el)
1191*d0ef721eSBaptiste Daroussin {
1192*d0ef721eSBaptiste Daroussin 	int i;
1193*d0ef721eSBaptiste Daroussin 
1194*d0ef721eSBaptiste Daroussin 	el->el_cursor.v = 0;
1195*d0ef721eSBaptiste Daroussin 	el->el_cursor.h = 0;
1196*d0ef721eSBaptiste Daroussin 	for (i = 0; i < el->el_terminal.t_size.v; i++)
1197*d0ef721eSBaptiste Daroussin 		el->el_display[i][0] = '\0';
1198*d0ef721eSBaptiste Daroussin 	el->el_refresh.r_oldcv = 0;
1199*d0ef721eSBaptiste Daroussin }
1200*d0ef721eSBaptiste Daroussin 
1201*d0ef721eSBaptiste Daroussin 
1202*d0ef721eSBaptiste Daroussin /* re_clear_lines():
1203*d0ef721eSBaptiste Daroussin  *	Make sure all lines are *really* blank
1204*d0ef721eSBaptiste Daroussin  */
1205*d0ef721eSBaptiste Daroussin libedit_private void
1206*d0ef721eSBaptiste Daroussin re_clear_lines(EditLine *el)
1207*d0ef721eSBaptiste Daroussin {
1208*d0ef721eSBaptiste Daroussin 
1209*d0ef721eSBaptiste Daroussin 	if (EL_CAN_CEOL) {
1210*d0ef721eSBaptiste Daroussin 		int i;
1211*d0ef721eSBaptiste Daroussin 		for (i = el->el_refresh.r_oldcv; i >= 0; i--) {
1212*d0ef721eSBaptiste Daroussin 			/* for each line on the screen */
1213*d0ef721eSBaptiste Daroussin 			terminal_move_to_line(el, i);
1214*d0ef721eSBaptiste Daroussin 			terminal_move_to_char(el, 0);
1215*d0ef721eSBaptiste Daroussin 			terminal_clear_EOL(el, el->el_terminal.t_size.h);
1216*d0ef721eSBaptiste Daroussin 		}
1217*d0ef721eSBaptiste Daroussin 	} else {
1218*d0ef721eSBaptiste Daroussin 		terminal_move_to_line(el, el->el_refresh.r_oldcv);
1219*d0ef721eSBaptiste Daroussin 					/* go to last line */
1220*d0ef721eSBaptiste Daroussin 		terminal__putc(el, '\r');	/* go to BOL */
1221*d0ef721eSBaptiste Daroussin 		terminal__putc(el, '\n');	/* go to new line */
1222*d0ef721eSBaptiste Daroussin 	}
1223*d0ef721eSBaptiste Daroussin }
1224