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