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