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