xref: /csrg-svn/lib/libedit/refresh.c (revision 54229)
1*54229Sbostic /*-
2*54229Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*54229Sbostic  * All rights reserved.
4*54229Sbostic  *
5*54229Sbostic  * This code is derived from software contributed to Berkeley by
6*54229Sbostic  * Christos Zoulas of Cornell University.
7*54229Sbostic  *
8*54229Sbostic  * %sccs.include.redist.c%
9*54229Sbostic  */
10*54229Sbostic 
11*54229Sbostic #ifndef lint
12*54229Sbostic static char sccsid[] = "@(#)refresh.c	5.1 (Berkeley) 06/22/92";
13*54229Sbostic #endif /* not lint */
14*54229Sbostic 
15*54229Sbostic /*
16*54229Sbostic  * ed.refresh.c: Lower level screen refreshing functions
17*54229Sbostic  */
18*54229Sbostic #include "sys.h"
19*54229Sbostic #include <stdio.h>
20*54229Sbostic #include <ctype.h>
21*54229Sbostic #include <unistd.h>
22*54229Sbostic #include <string.h>
23*54229Sbostic 
24*54229Sbostic #include "el.h"
25*54229Sbostic 
26*54229Sbostic private	void	re_addc 		__P((EditLine *, int));
27*54229Sbostic private	void	re_update_line 		__P((EditLine *, char *, char *, int));
28*54229Sbostic private	void	re_insert		__P((EditLine *, char *, int, int,
29*54229Sbostic 					     char *, int));
30*54229Sbostic private	void	re_delete		__P((EditLine *, char *, int, int,
31*54229Sbostic 					     int));
32*54229Sbostic private	void	re_fastputc		__P((EditLine *, int));
33*54229Sbostic 
34*54229Sbostic private	void	re__strncopy		__P((char *, char *, size_t));
35*54229Sbostic private	void	re__copy_and_pad	__P((char *, char *, size_t));
36*54229Sbostic 
37*54229Sbostic #ifdef DEBUG_REFRESH
38*54229Sbostic private	void	re_printstr		__P((EditLine *, char *, char *,
39*54229Sbostic 					     char *));
40*54229Sbostic # define __F el->el_errfile
41*54229Sbostic # define RE_DEBUG(a, b, c)	do 				\
42*54229Sbostic 				    if (a) {			\
43*54229Sbostic 					(void) fprintf b;	\
44*54229Sbostic 					c;			\
45*54229Sbostic 				    }				\
46*54229Sbostic 				while (0)
47*54229Sbostic /* re_printstr():
48*54229Sbostic  *	Print a string on the debugging pty
49*54229Sbostic  */
50*54229Sbostic private void
51*54229Sbostic re_printstr(el, str, f, t)
52*54229Sbostic     EditLine *el;
53*54229Sbostic     char *str;
54*54229Sbostic     char *f, *t;
55*54229Sbostic {
56*54229Sbostic     RE_DEBUG(1,(__F, "%s:\"", str),);
57*54229Sbostic     while (f < t)
58*54229Sbostic 	RE_DEBUG(1,(__F, "%c", *f++ & 0177),);
59*54229Sbostic     RE_DEBUG(1,(__F, "\"\r\n"),);
60*54229Sbostic }
61*54229Sbostic #else
62*54229Sbostic # define RE_DEBUG(a, b, c)
63*54229Sbostic #endif
64*54229Sbostic 
65*54229Sbostic 
66*54229Sbostic /* re_addc():
67*54229Sbostic  *	Draw c, expanding tabs, control chars etc.
68*54229Sbostic  */
69*54229Sbostic private void
70*54229Sbostic re_addc(el, c)
71*54229Sbostic     EditLine *el;
72*54229Sbostic     int c;
73*54229Sbostic {
74*54229Sbostic     if (isprint(c)) {
75*54229Sbostic 	re_putc(el, c);
76*54229Sbostic 	return;
77*54229Sbostic     }
78*54229Sbostic     if (c == '\n') {			/* expand the newline	 */
79*54229Sbostic 	re_putc(el, '\0');		/* assure end of line	 */
80*54229Sbostic 	el->el_refresh.r_cursor.h = 0;	/* reset cursor pos	 */
81*54229Sbostic 	el->el_refresh.r_cursor.v++;
82*54229Sbostic 	return;
83*54229Sbostic     }
84*54229Sbostic     if (c == '\t') {		/* expand the tab 	 */
85*54229Sbostic 	for (;;) {
86*54229Sbostic 	    re_putc(el, ' ');
87*54229Sbostic 	    if ((el->el_refresh.r_cursor.h & 07) == 0)
88*54229Sbostic 		break;		/* go until tab stop	 */
89*54229Sbostic 	}
90*54229Sbostic     }
91*54229Sbostic     else if (iscntrl(c)) {
92*54229Sbostic 	re_putc(el, '^');
93*54229Sbostic 	if (c == '\177')
94*54229Sbostic 	    re_putc(el, '?');
95*54229Sbostic 	else
96*54229Sbostic 	    /* uncontrolify it; works only for iso8859-1 like sets */
97*54229Sbostic 	    re_putc(el, (c | 0100));
98*54229Sbostic     }
99*54229Sbostic     else {
100*54229Sbostic 	re_putc(el, '\\');
101*54229Sbostic 	re_putc(el, ((c >> 6) & 07) + '0');
102*54229Sbostic 	re_putc(el, ((c >> 3) & 07) + '0');
103*54229Sbostic 	re_putc(el, (c & 07) + '0');
104*54229Sbostic     }
105*54229Sbostic } /* end re_addc */
106*54229Sbostic 
107*54229Sbostic 
108*54229Sbostic /* re_putc():
109*54229Sbostic  *	Draw the character given
110*54229Sbostic  */
111*54229Sbostic protected void
112*54229Sbostic re_putc(el, c)
113*54229Sbostic     EditLine *el;
114*54229Sbostic     int c;
115*54229Sbostic {
116*54229Sbostic     RE_DEBUG(1,(__F, "printing %3.3o '%c'\r\n", c, c),);
117*54229Sbostic 
118*54229Sbostic     el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c;
119*54229Sbostic     el->el_refresh.r_cursor.h++;				/* advance to next place */
120*54229Sbostic     if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) {
121*54229Sbostic 	el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0';
122*54229Sbostic 						/* assure end of line */
123*54229Sbostic 	el->el_refresh.r_cursor.h = 0;				/* reset it. */
124*54229Sbostic 	el->el_refresh.r_cursor.v++;
125*54229Sbostic 	RE_DEBUG(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
126*54229Sbostic 		 (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
127*54229Sbostic 		  el->el_refresh.r_cursor.v, el->el_term.t_size.v), abort());
128*54229Sbostic     }
129*54229Sbostic } /* end re_putc */
130*54229Sbostic 
131*54229Sbostic 
132*54229Sbostic /* re_refresh():
133*54229Sbostic  *	draws the new virtual screen image from the current input
134*54229Sbostic  *  	line, then goes line-by-line changing the real image to the new
135*54229Sbostic  *	virtual image. The routine to re-draw a line can be replaced
136*54229Sbostic  *	easily in hopes of a smarter one being placed there.
137*54229Sbostic  */
138*54229Sbostic protected void
139*54229Sbostic re_refresh(el)
140*54229Sbostic     EditLine *el;
141*54229Sbostic {
142*54229Sbostic     int i;
143*54229Sbostic     char *cp;
144*54229Sbostic     coord_t     cur;
145*54229Sbostic 
146*54229Sbostic     RE_DEBUG(1,(__F, "el->el_line.buffer = :%s:\r\n", el->el_line.buffer),);
147*54229Sbostic 
148*54229Sbostic     /* reset the Drawing cursor */
149*54229Sbostic     el->el_refresh.r_cursor.h = 0;
150*54229Sbostic     el->el_refresh.r_cursor.v = 0;
151*54229Sbostic 
152*54229Sbostic     cur.h = -1;			/* set flag in case I'm not set */
153*54229Sbostic     cur.v = 0;
154*54229Sbostic 
155*54229Sbostic     prompt_print(el);
156*54229Sbostic 
157*54229Sbostic     /* draw the current input buffer */
158*54229Sbostic     for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
159*54229Sbostic 	if (cp == el->el_line.cursor) {
160*54229Sbostic 	    cur.h = el->el_refresh.r_cursor.h;	/* save for later */
161*54229Sbostic 	    cur.v = el->el_refresh.r_cursor.v;
162*54229Sbostic 	}
163*54229Sbostic 	re_addc(el, *cp);
164*54229Sbostic     }
165*54229Sbostic 
166*54229Sbostic     if (cur.h == -1) {		/* if I haven't been set yet, I'm at the end */
167*54229Sbostic 	cur.h = el->el_refresh.r_cursor.h;
168*54229Sbostic 	cur.v = el->el_refresh.r_cursor.v;
169*54229Sbostic     }
170*54229Sbostic     /* must be done BEFORE the NUL is written */
171*54229Sbostic     el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
172*54229Sbostic     re_putc(el, '\0');		/* put NUL on end */
173*54229Sbostic 
174*54229Sbostic     RE_DEBUG(1,(__F,
175*54229Sbostic 	     "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
176*54229Sbostic 	     el->el_term.t_size.h, el->el_refresh.r_cursor.h,
177*54229Sbostic 	     el->el_refresh.r_cursor.v, el->el_vdisplay[0]),);
178*54229Sbostic 
179*54229Sbostic     RE_DEBUG(1,(__F, "updating %d lines.\r\n", el->el_refresh.r_newcv),);
180*54229Sbostic     for (i = 0; i <= el->el_refresh.r_newcv; i++) {
181*54229Sbostic 	/* NOTE THAT re_update_line MAY CHANGE el_display[i] */
182*54229Sbostic 	re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
183*54229Sbostic 
184*54229Sbostic 	/*
185*54229Sbostic 	 * Copy the new line to be the current one, and pad out with spaces
186*54229Sbostic 	 * to the full width of the terminal so that if we try moving the
187*54229Sbostic 	 * cursor by writing the character that is at the end of the
188*54229Sbostic 	 * screen line, it won't be a NUL or some old leftover stuff.
189*54229Sbostic 	 */
190*54229Sbostic 	re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
191*54229Sbostic 			el->el_term.t_size.h);
192*54229Sbostic     }
193*54229Sbostic     RE_DEBUG(1,(__F,
194*54229Sbostic 	 "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
195*54229Sbostic 	 el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i),);
196*54229Sbostic 
197*54229Sbostic     if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
198*54229Sbostic 	for (; i <= el->el_refresh.r_oldcv; i++) {
199*54229Sbostic 	    term_move_to_line(el, i);
200*54229Sbostic 	    term_move_to_char(el, 0);
201*54229Sbostic 	    term_clear_EOL(el, strlen(el->el_display[i]));
202*54229Sbostic #ifdef DEBUG_REFRESH
203*54229Sbostic 	    term_overwrite(el, "C\b", 2);
204*54229Sbostic #endif /* DEBUG_REFRESH */
205*54229Sbostic 	    *el->el_display[i] = '\0';
206*54229Sbostic 	}
207*54229Sbostic 
208*54229Sbostic     el->el_refresh.r_oldcv = el->el_refresh.r_newcv;	/* set for next time */
209*54229Sbostic     RE_DEBUG(1,(__F,
210*54229Sbostic 		"\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
211*54229Sbostic 		el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
212*54229Sbostic 		cur.h, cur.v),);
213*54229Sbostic     term_move_to_line(el, cur.v);		/* go to where the cursor is */
214*54229Sbostic     term_move_to_char(el, cur.h);
215*54229Sbostic } /* end re_refresh */
216*54229Sbostic 
217*54229Sbostic 
218*54229Sbostic /* re_goto_bottom():
219*54229Sbostic  *	 used to go to last used screen line
220*54229Sbostic  */
221*54229Sbostic protected void
222*54229Sbostic re_goto_bottom(el)
223*54229Sbostic     EditLine *el;
224*54229Sbostic {
225*54229Sbostic     term_move_to_line(el, el->el_refresh.r_oldcv);
226*54229Sbostic     term__putc('\r');
227*54229Sbostic     term__putc('\n');
228*54229Sbostic     re_clear_display(el);
229*54229Sbostic     term__flush();
230*54229Sbostic } /* end re_goto_bottom */
231*54229Sbostic 
232*54229Sbostic 
233*54229Sbostic /* re_insert():
234*54229Sbostic  *	insert num characters of s into d (in front of the character)
235*54229Sbostic  *	at dat, maximum length of d is dlen
236*54229Sbostic  */
237*54229Sbostic private void
238*54229Sbostic /*ARGSUSED*/
239*54229Sbostic re_insert(el, d, dat, dlen, s, num)
240*54229Sbostic     EditLine *el;
241*54229Sbostic     char *d;
242*54229Sbostic     int dat, dlen;
243*54229Sbostic     char *s;
244*54229Sbostic     int num;
245*54229Sbostic {
246*54229Sbostic     char *a, *b;
247*54229Sbostic 
248*54229Sbostic     if (num <= 0)
249*54229Sbostic 	return;
250*54229Sbostic     if (num > dlen - dat)
251*54229Sbostic 	num = dlen - dat;
252*54229Sbostic 
253*54229Sbostic     RE_DEBUG(1,(__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
254*54229Sbostic 	    num, dat, dlen, d),);
255*54229Sbostic     RE_DEBUG(1,(__F, "s == \"%s\"n", s),);
256*54229Sbostic 
257*54229Sbostic     /* open up the space for num chars */
258*54229Sbostic     if (num > 0) {
259*54229Sbostic 	b = d + dlen - 1;
260*54229Sbostic 	a = b - num;
261*54229Sbostic 	while (a >= &d[dat])
262*54229Sbostic 	    *b-- = *a--;
263*54229Sbostic 	d[dlen] = '\0';		/* just in case */
264*54229Sbostic     }
265*54229Sbostic     RE_DEBUG(1,(__F,
266*54229Sbostic 		"re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
267*54229Sbostic 		num, dat, dlen, d),);
268*54229Sbostic     RE_DEBUG(1,(__F, "s == \"%s\"n", s),);
269*54229Sbostic 
270*54229Sbostic     /* copy the characters */
271*54229Sbostic     for (a = d + dat; (a < d + dlen) && (num > 0); num--)
272*54229Sbostic 	*a++ = *s++;
273*54229Sbostic 
274*54229Sbostic     RE_DEBUG(1,(__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
275*54229Sbostic 	     num, dat, dlen, d, s),);
276*54229Sbostic     RE_DEBUG(1,(__F, "s == \"%s\"n", s),);
277*54229Sbostic } /* end re_insert */
278*54229Sbostic 
279*54229Sbostic 
280*54229Sbostic /* re_delete():
281*54229Sbostic  *	delete num characters d at dat, maximum length of d is dlen
282*54229Sbostic  */
283*54229Sbostic private void
284*54229Sbostic /*ARGSUSED*/
285*54229Sbostic re_delete(el, d, dat, dlen, num)
286*54229Sbostic     EditLine *el;
287*54229Sbostic     char *d;
288*54229Sbostic     int dat, dlen, num;
289*54229Sbostic {
290*54229Sbostic     char *a, *b;
291*54229Sbostic 
292*54229Sbostic     if (num <= 0)
293*54229Sbostic 	return;
294*54229Sbostic     if (dat + num >= dlen) {
295*54229Sbostic 	d[dat] = '\0';
296*54229Sbostic 	return;
297*54229Sbostic     }
298*54229Sbostic 
299*54229Sbostic     RE_DEBUG(1,(__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
300*54229Sbostic 	    num, dat, dlen, d),);
301*54229Sbostic 
302*54229Sbostic     /* open up the space for num chars */
303*54229Sbostic     if (num > 0) {
304*54229Sbostic 	b = d + dat;
305*54229Sbostic 	a = b + num;
306*54229Sbostic 	while (a < &d[dlen])
307*54229Sbostic 	    *b++ = *a++;
308*54229Sbostic 	d[dlen] = '\0';		/* just in case */
309*54229Sbostic     }
310*54229Sbostic     RE_DEBUG(1,(__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
311*54229Sbostic 	    num, dat, dlen, d),);
312*54229Sbostic } /* end re_delete */
313*54229Sbostic 
314*54229Sbostic 
315*54229Sbostic /* re__strncopy():
316*54229Sbostic  *	Like strncpy without padding.
317*54229Sbostic  */
318*54229Sbostic private void
319*54229Sbostic re__strncopy(a, b, n)
320*54229Sbostic     char *a, *b;
321*54229Sbostic     size_t n;
322*54229Sbostic {
323*54229Sbostic     while (n-- && *b)
324*54229Sbostic 	*a++ = *b++;
325*54229Sbostic } /* end re__strncopy */
326*54229Sbostic 
327*54229Sbostic 
328*54229Sbostic /* ****************************************************************
329*54229Sbostic     re_update_line() is based on finding the middle difference of each line
330*54229Sbostic     on the screen; vis:
331*54229Sbostic 
332*54229Sbostic 			     /old first difference
333*54229Sbostic 	/beginning of line   |              /old last same       /old EOL
334*54229Sbostic 	v		     v              v                    v
335*54229Sbostic old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
336*54229Sbostic new:	eddie> Oh, my little buggy says to me, as lurgid as
337*54229Sbostic 	^		     ^        ^			   ^
338*54229Sbostic 	\beginning of line   |        \new last same	   \new end of line
339*54229Sbostic 			     \new first difference
340*54229Sbostic 
341*54229Sbostic     all are character pointers for the sake of speed.  Special cases for
342*54229Sbostic     no differences, as well as for end of line additions must be handled.
343*54229Sbostic **************************************************************** */
344*54229Sbostic 
345*54229Sbostic /* Minimum at which doing an insert it "worth it".  This should be about
346*54229Sbostic  * half the "cost" of going into insert mode, inserting a character, and
347*54229Sbostic  * going back out.  This should really be calculated from the termcap
348*54229Sbostic  * data...  For the moment, a good number for ANSI terminals.
349*54229Sbostic  */
350*54229Sbostic #define MIN_END_KEEP	4
351*54229Sbostic 
352*54229Sbostic private void
353*54229Sbostic re_update_line(el, old, new, i)
354*54229Sbostic     EditLine *el;
355*54229Sbostic     char *old, *new;
356*54229Sbostic     int     i;
357*54229Sbostic {
358*54229Sbostic     char *o, *n, *p, c;
359*54229Sbostic     char   *ofd, *ols, *oe, *nfd, *nls, *ne;
360*54229Sbostic     char   *osb, *ose, *nsb, *nse;
361*54229Sbostic     int     fx, sx;
362*54229Sbostic 
363*54229Sbostic     /*
364*54229Sbostic      * find first diff
365*54229Sbostic      */
366*54229Sbostic     for (o = old, n = new; *o && (*o == *n); o++, n++)
367*54229Sbostic 	continue;
368*54229Sbostic     ofd = o;
369*54229Sbostic     nfd = n;
370*54229Sbostic 
371*54229Sbostic     /*
372*54229Sbostic      * Find the end of both old and new
373*54229Sbostic      */
374*54229Sbostic     while (*o)
375*54229Sbostic 	o++;
376*54229Sbostic     /*
377*54229Sbostic      * Remove any trailing blanks off of the end, being careful not to
378*54229Sbostic      * back up past the beginning.
379*54229Sbostic      */
380*54229Sbostic     while (ofd < o) {
381*54229Sbostic 	if (o[-1] != ' ')
382*54229Sbostic 	    break;
383*54229Sbostic 	o--;
384*54229Sbostic     }
385*54229Sbostic     oe = o;
386*54229Sbostic     *oe = '\0';
387*54229Sbostic 
388*54229Sbostic     while (*n)
389*54229Sbostic 	n++;
390*54229Sbostic 
391*54229Sbostic     /* remove blanks from end of new */
392*54229Sbostic     while (nfd < n) {
393*54229Sbostic 	if (n[-1] != ' ')
394*54229Sbostic 	    break;
395*54229Sbostic 	n--;
396*54229Sbostic     }
397*54229Sbostic     ne = n;
398*54229Sbostic     *ne = '\0';
399*54229Sbostic 
400*54229Sbostic     /*
401*54229Sbostic      * if no diff, continue to next line of redraw
402*54229Sbostic      */
403*54229Sbostic     if (*ofd == '\0' && *nfd == '\0') {
404*54229Sbostic 	RE_DEBUG(1,(__F, "no difference.\r\n"),);
405*54229Sbostic 	return;
406*54229Sbostic     }
407*54229Sbostic 
408*54229Sbostic     /*
409*54229Sbostic      * find last same pointer
410*54229Sbostic      */
411*54229Sbostic     while ((o > ofd) && (n > nfd) && (*--o == *--n))
412*54229Sbostic 	continue;
413*54229Sbostic     ols = ++o;
414*54229Sbostic     nls = ++n;
415*54229Sbostic 
416*54229Sbostic     /*
417*54229Sbostic      * find same begining and same end
418*54229Sbostic      */
419*54229Sbostic     osb = ols;
420*54229Sbostic     nsb = nls;
421*54229Sbostic     ose = ols;
422*54229Sbostic     nse = nls;
423*54229Sbostic 
424*54229Sbostic     /*
425*54229Sbostic      * case 1: insert: scan from nfd to nls looking for *ofd
426*54229Sbostic      */
427*54229Sbostic     if (*ofd) {
428*54229Sbostic 	for (c = *ofd, n = nfd; n < nls; n++) {
429*54229Sbostic 	    if (c == *n) {
430*54229Sbostic 		for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
431*54229Sbostic 		    continue;
432*54229Sbostic 		/*
433*54229Sbostic 		 * if the new match is longer and it's worth keeping, then we
434*54229Sbostic 		 * take it
435*54229Sbostic 		 */
436*54229Sbostic 		if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
437*54229Sbostic 		    nsb = n;
438*54229Sbostic 		    nse = p;
439*54229Sbostic 		    osb = ofd;
440*54229Sbostic 		    ose = o;
441*54229Sbostic 		}
442*54229Sbostic 	    }
443*54229Sbostic 	}
444*54229Sbostic     }
445*54229Sbostic 
446*54229Sbostic     /*
447*54229Sbostic      * case 2: delete: scan from ofd to ols looking for *nfd
448*54229Sbostic      */
449*54229Sbostic     if (*nfd) {
450*54229Sbostic 	for (c = *nfd, o = ofd; o < ols; o++) {
451*54229Sbostic 	    if (c == *o) {
452*54229Sbostic 		for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
453*54229Sbostic 		    continue;
454*54229Sbostic 		/*
455*54229Sbostic 		 * if the new match is longer and it's worth keeping, then we
456*54229Sbostic 		 * take it
457*54229Sbostic 		 */
458*54229Sbostic 		if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
459*54229Sbostic 		    nsb = nfd;
460*54229Sbostic 		    nse = n;
461*54229Sbostic 		    osb = o;
462*54229Sbostic 		    ose = p;
463*54229Sbostic 		}
464*54229Sbostic 	    }
465*54229Sbostic 	}
466*54229Sbostic     }
467*54229Sbostic 
468*54229Sbostic     /*
469*54229Sbostic      * Pragmatics I: If old trailing whitespace or not enough characters to
470*54229Sbostic      * save to be worth it, then don't save the last same info.
471*54229Sbostic      */
472*54229Sbostic     if ((oe - ols) < MIN_END_KEEP) {
473*54229Sbostic 	ols = oe;
474*54229Sbostic 	nls = ne;
475*54229Sbostic     }
476*54229Sbostic 
477*54229Sbostic     /*
478*54229Sbostic      * Pragmatics II: if the terminal isn't smart enough, make the data dumber
479*54229Sbostic      * so the smart update doesn't try anything fancy
480*54229Sbostic      */
481*54229Sbostic 
482*54229Sbostic     /*
483*54229Sbostic      * fx is the number of characters we need to insert/delete: in the
484*54229Sbostic      * beginning to bring the two same begins together
485*54229Sbostic      */
486*54229Sbostic     fx = (nsb - nfd) - (osb - ofd);
487*54229Sbostic     /*
488*54229Sbostic      * sx is the number of characters we need to insert/delete: in the end to
489*54229Sbostic      * bring the two same last parts together
490*54229Sbostic      */
491*54229Sbostic     sx = (nls - nse) - (ols - ose);
492*54229Sbostic 
493*54229Sbostic     if (!EL_CAN_INSERT) {
494*54229Sbostic 	if (fx > 0) {
495*54229Sbostic 	    osb = ols;
496*54229Sbostic 	    ose = ols;
497*54229Sbostic 	    nsb = nls;
498*54229Sbostic 	    nse = nls;
499*54229Sbostic 	}
500*54229Sbostic 	if (sx > 0) {
501*54229Sbostic 	    ols = oe;
502*54229Sbostic 	    nls = ne;
503*54229Sbostic 	}
504*54229Sbostic 	if ((ols - ofd) < (nls - nfd)) {
505*54229Sbostic 	    ols = oe;
506*54229Sbostic 	    nls = ne;
507*54229Sbostic 	}
508*54229Sbostic     }
509*54229Sbostic     if (!EL_CAN_DELETE) {
510*54229Sbostic 	if (fx < 0) {
511*54229Sbostic 	    osb = ols;
512*54229Sbostic 	    ose = ols;
513*54229Sbostic 	    nsb = nls;
514*54229Sbostic 	    nse = nls;
515*54229Sbostic 	}
516*54229Sbostic 	if (sx < 0) {
517*54229Sbostic 	    ols = oe;
518*54229Sbostic 	    nls = ne;
519*54229Sbostic 	}
520*54229Sbostic 	if ((ols - ofd) > (nls - nfd)) {
521*54229Sbostic 	    ols = oe;
522*54229Sbostic 	    nls = ne;
523*54229Sbostic 	}
524*54229Sbostic     }
525*54229Sbostic 
526*54229Sbostic     /*
527*54229Sbostic      * Pragmatics III: make sure the middle shifted pointers are correct if
528*54229Sbostic      * they don't point to anything (we may have moved ols or nls).
529*54229Sbostic      */
530*54229Sbostic     /* if the change isn't worth it, don't bother */
531*54229Sbostic     /* was: if (osb == ose) */
532*54229Sbostic     if ((ose - osb) < MIN_END_KEEP) {
533*54229Sbostic 	osb = ols;
534*54229Sbostic 	ose = ols;
535*54229Sbostic 	nsb = nls;
536*54229Sbostic 	nse = nls;
537*54229Sbostic     }
538*54229Sbostic 
539*54229Sbostic     /*
540*54229Sbostic      * Now that we are done with pragmatics we recompute fx, sx
541*54229Sbostic      */
542*54229Sbostic     fx = (nsb - nfd) - (osb - ofd);
543*54229Sbostic     sx = (nls - nse) - (ols - ose);
544*54229Sbostic 
545*54229Sbostic     RE_DEBUG(1,(__F, "\n"),);
546*54229Sbostic     RE_DEBUG(1,(__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n",
547*54229Sbostic 	    ofd - old, osb - old, ose - old, ols - old, oe - old),);
548*54229Sbostic     RE_DEBUG(1,(__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
549*54229Sbostic 	    nfd - new, nsb - new, nse - new, nls - new, ne - new),);
550*54229Sbostic     RE_DEBUG(1,(__F,
551*54229Sbostic 		"xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"),);
552*54229Sbostic     RE_DEBUG(1,(__F,
553*54229Sbostic 		"xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"),);
554*54229Sbostic #ifdef DEBUG_REFRESH
555*54229Sbostic     re_printstr(el, "old- oe", old, oe);
556*54229Sbostic     re_printstr(el, "new- ne", new, ne);
557*54229Sbostic     re_printstr(el, "old-ofd", old, ofd);
558*54229Sbostic     re_printstr(el, "new-nfd", new, nfd);
559*54229Sbostic     re_printstr(el, "ofd-osb", ofd, osb);
560*54229Sbostic     re_printstr(el, "nfd-nsb", nfd, nsb);
561*54229Sbostic     re_printstr(el, "osb-ose", osb, ose);
562*54229Sbostic     re_printstr(el, "nsb-nse", nsb, nse);
563*54229Sbostic     re_printstr(el, "ose-ols", ose, ols);
564*54229Sbostic     re_printstr(el, "nse-nls", nse, nls);
565*54229Sbostic     re_printstr(el, "ols- oe", ols, oe);
566*54229Sbostic     re_printstr(el, "nls- ne", nls, ne);
567*54229Sbostic #endif /* DEBUG_REFRESH */
568*54229Sbostic 
569*54229Sbostic     /*
570*54229Sbostic      * el_cursor.v to this line i MUST be in this routine so that if we
571*54229Sbostic      * don't have to change the line, we don't move to it. el_cursor.h to first
572*54229Sbostic      * diff char
573*54229Sbostic      */
574*54229Sbostic     term_move_to_line(el, i);
575*54229Sbostic 
576*54229Sbostic     /*
577*54229Sbostic      * at this point we have something like this:
578*54229Sbostic      *
579*54229Sbostic      * /old                  /ofd    /osb               /ose    /ols     /oe
580*54229Sbostic      * v.....................v       v..................v       v........v
581*54229Sbostic      * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
582*54229Sbostic      * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
583*54229Sbostic      * ^.....................^     ^..................^       ^........^
584*54229Sbostic      * \new                  \nfd  \nsb               \nse     \nls    \ne
585*54229Sbostic      *
586*54229Sbostic      * fx is the difference in length between the the chars between nfd and
587*54229Sbostic      * nsb, and the chars between ofd and osb, and is thus the number of
588*54229Sbostic      * characters to delete if < 0 (new is shorter than old, as above),
589*54229Sbostic      * or insert (new is longer than short).
590*54229Sbostic      *
591*54229Sbostic      * sx is the same for the second differences.
592*54229Sbostic      */
593*54229Sbostic 
594*54229Sbostic     /*
595*54229Sbostic      * if we have a net insert on the first difference, AND inserting the net
596*54229Sbostic      * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
597*54229Sbostic      * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
598*54229Sbostic      * (el->el_term.t_size.h) else we do the deletes first so that we keep everything we need
599*54229Sbostic      * to.
600*54229Sbostic      */
601*54229Sbostic 
602*54229Sbostic     /*
603*54229Sbostic      * if the last same is the same like the end, there is no last same part,
604*54229Sbostic      * otherwise we want to keep the last same part set p to the last useful
605*54229Sbostic      * old character
606*54229Sbostic      */
607*54229Sbostic     p = (ols != oe) ? oe : ose;
608*54229Sbostic 
609*54229Sbostic     /*
610*54229Sbostic      * if (There is a diffence in the beginning) && (we need to insert
611*54229Sbostic      * characters) && (the number of characters to insert is less than the term
612*54229Sbostic      * width) We need to do an insert! else if (we need to delete characters)
613*54229Sbostic      * We need to delete characters! else No insert or delete
614*54229Sbostic      */
615*54229Sbostic     if ((nsb != nfd) && fx > 0 && ((p - old) + fx <= el->el_term.t_size.h)) {
616*54229Sbostic 	RE_DEBUG(1,(__F, "first diff insert at %d...\r\n", nfd - new),);
617*54229Sbostic 	/*
618*54229Sbostic 	 * Move to the first char to insert, where the first diff is.
619*54229Sbostic 	 */
620*54229Sbostic 	term_move_to_char(el, nfd - new);
621*54229Sbostic 	/*
622*54229Sbostic 	 * Check if we have stuff to keep at end
623*54229Sbostic 	 */
624*54229Sbostic 	if (nsb != ne) {
625*54229Sbostic 	    RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),);
626*54229Sbostic 	    /*
627*54229Sbostic 	     * insert fx chars of new starting at nfd
628*54229Sbostic 	     */
629*54229Sbostic 	    if (fx > 0) {
630*54229Sbostic 		RE_DEBUG(!EL_CAN_INSERT,
631*54229Sbostic 			 (__F, "ERROR: cannot insert in early first diff\n"),);
632*54229Sbostic 		term_insertwrite(el, nfd, fx);
633*54229Sbostic 		re_insert(el, old, ofd - old, el->el_term.t_size.h, nfd, fx);
634*54229Sbostic 	    }
635*54229Sbostic 	    /*
636*54229Sbostic 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
637*54229Sbostic 	     */
638*54229Sbostic 	    term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
639*54229Sbostic 	    re__strncopy(ofd + fx, nfd + fx, (nsb - nfd) - fx);
640*54229Sbostic 	}
641*54229Sbostic 	else {
642*54229Sbostic 	    RE_DEBUG(1,(__F, "without anything to save\r\n"),);
643*54229Sbostic 	    term_overwrite(el, nfd, (nsb - nfd));
644*54229Sbostic 	    re__strncopy(ofd, nfd, (nsb - nfd));
645*54229Sbostic 	    /*
646*54229Sbostic 	     * Done
647*54229Sbostic 	     */
648*54229Sbostic 	    return;
649*54229Sbostic 	}
650*54229Sbostic     }
651*54229Sbostic     else if (fx < 0) {
652*54229Sbostic 	RE_DEBUG(1,(__F, "first diff delete at %d...\r\n", ofd - old),);
653*54229Sbostic 	/*
654*54229Sbostic 	 * move to the first char to delete where the first diff is
655*54229Sbostic 	 */
656*54229Sbostic 	term_move_to_char(el, ofd - old);
657*54229Sbostic 	/*
658*54229Sbostic 	 * Check if we have stuff to save
659*54229Sbostic 	 */
660*54229Sbostic 	if (osb != oe) {
661*54229Sbostic 	    RE_DEBUG(1,(__F, "with stuff to save at end\r\n"),);
662*54229Sbostic 	    /*
663*54229Sbostic 	     * fx is less than zero *always* here but we check for code
664*54229Sbostic 	     * symmetry
665*54229Sbostic 	     */
666*54229Sbostic 	    if (fx < 0) {
667*54229Sbostic 		RE_DEBUG(!EL_CAN_DELETE,
668*54229Sbostic 			 (__F, "ERROR: cannot delete in first diff\n"),);
669*54229Sbostic 		term_deletechars(el, -fx);
670*54229Sbostic 		re_delete(el, old, ofd - old, el->el_term.t_size.h, -fx);
671*54229Sbostic 	    }
672*54229Sbostic 	    /*
673*54229Sbostic 	     * write (nsb-nfd) chars of new starting at nfd
674*54229Sbostic 	     */
675*54229Sbostic 	    term_overwrite(el, nfd, (nsb - nfd));
676*54229Sbostic 	    re__strncopy(ofd, nfd, (nsb - nfd));
677*54229Sbostic 
678*54229Sbostic 	}
679*54229Sbostic 	else {
680*54229Sbostic 	    RE_DEBUG(1,(__F, "but with nothing left to save\r\n"),);
681*54229Sbostic 	    /*
682*54229Sbostic 	     * write (nsb-nfd) chars of new starting at nfd
683*54229Sbostic 	     */
684*54229Sbostic 	    term_overwrite(el, nfd, (nsb - nfd));
685*54229Sbostic 	    RE_DEBUG(1,(__F, "cleareol %d\n", (oe - old) - (ne - new)),);
686*54229Sbostic 	    term_clear_EOL(el, (oe - old) - (ne - new));
687*54229Sbostic 	    /*
688*54229Sbostic 	     * Done
689*54229Sbostic 	     */
690*54229Sbostic 	    return;
691*54229Sbostic 	}
692*54229Sbostic     }
693*54229Sbostic     else
694*54229Sbostic 	fx = 0;
695*54229Sbostic 
696*54229Sbostic     if (sx < 0) {
697*54229Sbostic 	RE_DEBUG(1,(__F, "second diff delete at %d...\r\n", (ose - old) + fx),);
698*54229Sbostic 	/*
699*54229Sbostic 	 * Check if we have stuff to delete
700*54229Sbostic 	 */
701*54229Sbostic 	/*
702*54229Sbostic 	 * fx is the number of characters inserted (+) or deleted (-)
703*54229Sbostic 	 */
704*54229Sbostic 
705*54229Sbostic 	term_move_to_char(el, (ose - old) + fx);
706*54229Sbostic 	/*
707*54229Sbostic 	 * Check if we have stuff to save
708*54229Sbostic 	 */
709*54229Sbostic 	if (ols != oe) {
710*54229Sbostic 	    RE_DEBUG(1,(__F, "with stuff to save at end\r\n"),);
711*54229Sbostic 	    /*
712*54229Sbostic 	     * Again a duplicate test.
713*54229Sbostic 	     */
714*54229Sbostic 	    if (sx < 0) {
715*54229Sbostic 		RE_DEBUG(!EL_CAN_DELETE,
716*54229Sbostic 			 (__F, "ERROR: cannot delete in second diff\n"),);
717*54229Sbostic 		term_deletechars(el, -sx);
718*54229Sbostic 	    }
719*54229Sbostic 
720*54229Sbostic 	    /*
721*54229Sbostic 	     * write (nls-nse) chars of new starting at nse
722*54229Sbostic 	     */
723*54229Sbostic 	    term_overwrite(el, nse, (nls - nse));
724*54229Sbostic 	}
725*54229Sbostic 	else {
726*54229Sbostic 	    RE_DEBUG(1,(__F, "but with nothing left to save\r\n"),);
727*54229Sbostic 	    term_overwrite(el, nse, (nls - nse));
728*54229Sbostic 	    RE_DEBUG(1,(__F, "cleareol %d\n", (oe - old) - (ne - new)),);
729*54229Sbostic 	    term_clear_EOL(el, (oe - old) - (ne - new));
730*54229Sbostic 	}
731*54229Sbostic     }
732*54229Sbostic 
733*54229Sbostic     /*
734*54229Sbostic      * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
735*54229Sbostic      */
736*54229Sbostic     if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
737*54229Sbostic 	RE_DEBUG(1,(__F, "late first diff insert at %d...\r\n", nfd - new),);
738*54229Sbostic 
739*54229Sbostic 	term_move_to_char(el, nfd - new);
740*54229Sbostic 	/*
741*54229Sbostic 	 * Check if we have stuff to keep at the end
742*54229Sbostic 	 */
743*54229Sbostic 	if (nsb != ne) {
744*54229Sbostic 	    RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),);
745*54229Sbostic 	    /*
746*54229Sbostic 	     * We have to recalculate fx here because we set it
747*54229Sbostic 	     * to zero above as a flag saying that we hadn't done
748*54229Sbostic 	     * an early first insert.
749*54229Sbostic 	     */
750*54229Sbostic 	    fx = (nsb - nfd) - (osb - ofd);
751*54229Sbostic 	    if (fx > 0) {
752*54229Sbostic 		/*
753*54229Sbostic 		 * insert fx chars of new starting at nfd
754*54229Sbostic 		 */
755*54229Sbostic 		RE_DEBUG(!EL_CAN_INSERT,
756*54229Sbostic 			 (__F, "ERROR: cannot insert in late first diff\n"),);
757*54229Sbostic 		term_insertwrite(el, nfd, fx);
758*54229Sbostic 		re_insert(el, old, ofd - old, el->el_term.t_size.h, nfd, fx);
759*54229Sbostic 	    }
760*54229Sbostic 
761*54229Sbostic 	    /*
762*54229Sbostic 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
763*54229Sbostic 	     */
764*54229Sbostic 	    term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
765*54229Sbostic 	    re__strncopy(ofd + fx, nfd + fx, (nsb - nfd) - fx);
766*54229Sbostic 	}
767*54229Sbostic 	else {
768*54229Sbostic 	    RE_DEBUG(1,(__F, "without anything to save\r\n"),);
769*54229Sbostic 	    term_overwrite(el, nfd, (nsb - nfd));
770*54229Sbostic 	    re__strncopy(ofd, nfd, (nsb - nfd));
771*54229Sbostic 	}
772*54229Sbostic     }
773*54229Sbostic 
774*54229Sbostic     /*
775*54229Sbostic      * line is now NEW up to nse
776*54229Sbostic      */
777*54229Sbostic     if (sx >= 0) {
778*54229Sbostic 	RE_DEBUG(1,(__F, "second diff insert at %d...\r\n", nse - new),);
779*54229Sbostic 	term_move_to_char(el, nse - new);
780*54229Sbostic 	if (ols != oe) {
781*54229Sbostic 	    RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),);
782*54229Sbostic 	    if (sx > 0) {
783*54229Sbostic 		/* insert sx chars of new starting at nse */
784*54229Sbostic 		RE_DEBUG(!EL_CAN_INSERT,
785*54229Sbostic 		         (__F, "ERROR: cannot insert in second diff\n"),);
786*54229Sbostic 		term_insertwrite(el, nse, sx);
787*54229Sbostic 	    }
788*54229Sbostic 
789*54229Sbostic 	    /*
790*54229Sbostic 	     * write (nls-nse) - sx chars of new starting at (nse + sx)
791*54229Sbostic 	     */
792*54229Sbostic 	    term_overwrite(el, nse + sx, (nls - nse) - sx);
793*54229Sbostic 	}
794*54229Sbostic 	else {
795*54229Sbostic 	    RE_DEBUG(1,(__F, "without anything to save\r\n"),);
796*54229Sbostic 	    term_overwrite(el, nse, (nls - nse));
797*54229Sbostic 
798*54229Sbostic 	    /*
799*54229Sbostic              * No need to do a clear-to-end here because we were doing
800*54229Sbostic 	     * a second insert, so we will have over written all of the
801*54229Sbostic 	     * old string.
802*54229Sbostic 	     */
803*54229Sbostic 	}
804*54229Sbostic     }
805*54229Sbostic     RE_DEBUG(1,(__F, "done.\r\n"),);
806*54229Sbostic } /* re_update_line */
807*54229Sbostic 
808*54229Sbostic 
809*54229Sbostic /* re__copy_and_pad():
810*54229Sbostic  *	Copy string and pad with spaces
811*54229Sbostic  */
812*54229Sbostic private void
813*54229Sbostic re__copy_and_pad(dst, src, width)
814*54229Sbostic     char *dst, *src;
815*54229Sbostic     size_t width;
816*54229Sbostic {
817*54229Sbostic     int i;
818*54229Sbostic 
819*54229Sbostic     for (i = 0; i < width; i++) {
820*54229Sbostic 	if (*src == '\0')
821*54229Sbostic 	    break;
822*54229Sbostic 	*dst++ = *src++;
823*54229Sbostic     }
824*54229Sbostic 
825*54229Sbostic     while (i < width) {
826*54229Sbostic 	*dst++ = ' ';
827*54229Sbostic 	i++;
828*54229Sbostic     }
829*54229Sbostic     *dst = '\0';
830*54229Sbostic } /* end re__copy_and_pad */
831*54229Sbostic 
832*54229Sbostic 
833*54229Sbostic /* re_refresh_cursor():
834*54229Sbostic  *	Move to the new cursor position
835*54229Sbostic  */
836*54229Sbostic protected void
837*54229Sbostic re_refresh_cursor(el)
838*54229Sbostic     EditLine *el;
839*54229Sbostic {
840*54229Sbostic     char *cp, c;
841*54229Sbostic     int h, v, th;
842*54229Sbostic 
843*54229Sbostic     /* first we must find where the cursor is... */
844*54229Sbostic     h  = el->el_prompt.p_pos.h;
845*54229Sbostic     v  = el->el_prompt.p_pos.v;
846*54229Sbostic     th = el->el_term.t_size.h;		/* optimize for speed 		*/
847*54229Sbostic 
848*54229Sbostic     /* do input buffer to el->el_line.cursor */
849*54229Sbostic     for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
850*54229Sbostic 	c = *cp;
851*54229Sbostic 	h++;			/* all chars at least this long */
852*54229Sbostic 
853*54229Sbostic 	if (c == '\n') {	/* handle newline in data part too */
854*54229Sbostic 	    h = 0;
855*54229Sbostic 	    v++;
856*54229Sbostic 	}
857*54229Sbostic 	else {
858*54229Sbostic 	    if (c == '\t') {	/* if a tab, to next tab stop */
859*54229Sbostic 		while (h & 07) {
860*54229Sbostic 		    h++;
861*54229Sbostic 		}
862*54229Sbostic 	    }
863*54229Sbostic 	    else if (iscntrl(c)) {	/* if control char */
864*54229Sbostic 		h++;
865*54229Sbostic 		if (h > th) {	/* if overflow, compensate */
866*54229Sbostic 		    h = 1;
867*54229Sbostic 		    v++;
868*54229Sbostic 		}
869*54229Sbostic 	    }
870*54229Sbostic 	    else if (!isprint(c)) {
871*54229Sbostic 		h += 3;
872*54229Sbostic 		if (h > th) {	/* if overflow, compensate */
873*54229Sbostic 		    h = h - th;
874*54229Sbostic 		    v++;
875*54229Sbostic 		}
876*54229Sbostic 	    }
877*54229Sbostic 	}
878*54229Sbostic 
879*54229Sbostic 	if (h >= th) {		/* check, extra long tabs picked up here also */
880*54229Sbostic 	    h = 0;
881*54229Sbostic 	    v++;
882*54229Sbostic 	}
883*54229Sbostic     }
884*54229Sbostic 
885*54229Sbostic     /* now go there */
886*54229Sbostic     term_move_to_line(el, v);
887*54229Sbostic     term_move_to_char(el, h);
888*54229Sbostic     term__flush();
889*54229Sbostic } /* re_refresh_cursor */
890*54229Sbostic 
891*54229Sbostic 
892*54229Sbostic /* re_fastputc():
893*54229Sbostic  *	Add a character fast.
894*54229Sbostic  */
895*54229Sbostic private void
896*54229Sbostic re_fastputc(el, c)
897*54229Sbostic     EditLine *el;
898*54229Sbostic     int    c;
899*54229Sbostic {
900*54229Sbostic     term__putc(c);
901*54229Sbostic     el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
902*54229Sbostic     if (el->el_cursor.h >= el->el_term.t_size.h) {
903*54229Sbostic 	/* if we must overflow */
904*54229Sbostic 	el->el_cursor.h = 0;
905*54229Sbostic 	el->el_cursor.v++;
906*54229Sbostic 	el->el_refresh.r_oldcv++;
907*54229Sbostic 	term__putc('\r');
908*54229Sbostic 	term__putc('\n');
909*54229Sbostic     }
910*54229Sbostic } /* end re_fastputc */
911*54229Sbostic 
912*54229Sbostic 
913*54229Sbostic /* re_fastaddc():
914*54229Sbostic  *	we added just one char, handle it fast.
915*54229Sbostic  *	Assumes that screen cursor == real cursor
916*54229Sbostic  */
917*54229Sbostic protected void
918*54229Sbostic re_fastaddc(el)
919*54229Sbostic     EditLine *el;
920*54229Sbostic {
921*54229Sbostic     char c;
922*54229Sbostic 
923*54229Sbostic     c = el->el_line.cursor[-1];
924*54229Sbostic 
925*54229Sbostic     if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
926*54229Sbostic 	re_refresh(el);		/* too hard to handle */
927*54229Sbostic 	return;
928*54229Sbostic     }				/* else (only do at end of line, no TAB) */
929*54229Sbostic 
930*54229Sbostic     if (iscntrl(c)) {		/* if control char, do caret */
931*54229Sbostic 	char mc = (c == '\177') ? '?' : (c | 0100);
932*54229Sbostic 	re_fastputc(el, '^');
933*54229Sbostic 	re_fastputc(el, mc);
934*54229Sbostic     }
935*54229Sbostic     else if (isprint(c)) {	/* normal char */
936*54229Sbostic 	re_fastputc(el, c);
937*54229Sbostic     }
938*54229Sbostic     else {
939*54229Sbostic 	re_fastputc(el, '\\');
940*54229Sbostic 	re_fastputc(el, ((c >> 6) & 7) + '0');
941*54229Sbostic 	re_fastputc(el, ((c >> 3) & 7) + '0');
942*54229Sbostic 	re_fastputc(el, (c & 7) + '0');
943*54229Sbostic     }
944*54229Sbostic     term__flush();
945*54229Sbostic } /* end re_fastaddc */
946*54229Sbostic 
947*54229Sbostic 
948*54229Sbostic /* re_clear_display():
949*54229Sbostic  *	clear the screen buffers so that new new prompt starts fresh.
950*54229Sbostic  */
951*54229Sbostic protected void
952*54229Sbostic re_clear_display(el)
953*54229Sbostic     EditLine *el;
954*54229Sbostic {
955*54229Sbostic     int i;
956*54229Sbostic 
957*54229Sbostic     el->el_cursor.v = 0;
958*54229Sbostic     el->el_cursor.h = 0;
959*54229Sbostic     for (i = 0; i < el->el_term.t_size.v; i++)
960*54229Sbostic 	el->el_display[i][0] = '\0';
961*54229Sbostic     el->el_refresh.r_oldcv = 0;
962*54229Sbostic } /* end re_clear_display */
963*54229Sbostic 
964*54229Sbostic 
965*54229Sbostic /* re_clear_lines():
966*54229Sbostic  *	Make sure all lines are *really* blank
967*54229Sbostic  */
968*54229Sbostic protected void
969*54229Sbostic re_clear_lines(el)
970*54229Sbostic     EditLine *el;
971*54229Sbostic {
972*54229Sbostic     if (EL_CAN_CEOL) {
973*54229Sbostic 	int i;
974*54229Sbostic 	term_move_to_char(el, 0);
975*54229Sbostic 	for (i = 0; i <= el->el_refresh.r_oldcv; i++) {
976*54229Sbostic 	    /* for each line on the screen */
977*54229Sbostic 	    term_move_to_line(el, i);
978*54229Sbostic 	    term_clear_EOL(el, el->el_term.t_size.h);
979*54229Sbostic 	}
980*54229Sbostic 	term_move_to_line(el, 0);
981*54229Sbostic     }
982*54229Sbostic     else {
983*54229Sbostic 	term_move_to_line(el, el->el_refresh.r_oldcv);	/* go to last line */
984*54229Sbostic 	term__putc('\r');				/* go to BOL */
985*54229Sbostic 	term__putc('\n');				/* go to new line */
986*54229Sbostic     }
987*54229Sbostic } /* end re_clear_lines */
988