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