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