[BACK]Return to refresh.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libedit

Annotation of src/lib/libedit/refresh.c, Revision 1.40

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

CVSweb <webmaster@jp.NetBSD.org>