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