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

Annotation of src/lib/libedit/chared.c, Revision 1.51

1.51    ! christos    1: /*     $NetBSD: chared.c,v 1.50 2016/04/09 18:43:17 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.19      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.15      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[] = "@(#)chared.c   8.1 (Berkeley) 6/4/93";
1.2       lukem      39: #else
1.51    ! christos   40: __RCSID("$NetBSD: chared.c,v 1.50 2016/04/09 18:43:17 christos Exp $");
1.2       lukem      41: #endif
1.1       cgd        42: #endif /* not lint && not SCCSID */
                     43:
1.7       simonb     44: /*
1.1       cgd        45:  * chared.c: Character editor utilities
                     46:  */
1.46      christos   47: #include <ctype.h>
1.1       cgd        48: #include <stdlib.h>
1.46      christos   49: #include <string.h>
1.45      christos   50:
1.1       cgd        51: #include "el.h"
1.45      christos   52: #include "common.h"
1.1       cgd        53:
1.26      sketch     54: private void ch__clearmacro (EditLine *);
1.24      christos   55:
1.12      jdolecek   56: /* value to leave unused in line buffer */
                     57: #define        EL_LEAVE        2
                     58:
1.1       cgd        59: /* cv_undo():
                     60:  *     Handle state for the vi undo command
                     61:  */
                     62: protected void
1.17      christos   63: cv_undo(EditLine *el)
1.9       lukem      64: {
                     65:        c_undo_t *vu = &el->el_chared.c_undo;
1.17      christos   66:        c_redo_t *r = &el->el_chared.c_redo;
1.27      christos   67:        size_t size;
1.16      christos   68:
1.17      christos   69:        /* Save entire line for undo */
1.35      christos   70:        size = (size_t)(el->el_line.lastchar - el->el_line.buffer);
                     71:        vu->len = (ssize_t)size;
1.27      christos   72:        vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
1.28      christos   73:        (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
1.16      christos   74:
1.17      christos   75:        /* save command info for redo */
                     76:        r->count = el->el_state.doingarg ? el->el_state.argument : 0;
                     77:        r->action = el->el_chared.c_vcmd.action;
                     78:        r->pos = r->buf;
                     79:        r->cmd = el->el_state.thiscmd;
                     80:        r->ch = el->el_state.thisch;
                     81: }
                     82:
                     83: /* cv_yank():
                     84:  *     Save yank/delete data for paste
                     85:  */
                     86: protected void
1.28      christos   87: cv_yank(EditLine *el, const Char *ptr, int size)
1.17      christos   88: {
                     89:        c_kill_t *k = &el->el_chared.c_kill;
                     90:
1.35      christos   91:        (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf));
1.17      christos   92:        k->last = k->buf + size;
1.1       cgd        93: }
                     94:
                     95:
1.7       simonb     96: /* c_insert():
1.1       cgd        97:  *     Insert num characters
                     98:  */
                     99: protected void
1.9       lukem     100: c_insert(EditLine *el, int num)
                    101: {
1.28      christos  102:        Char *cp;
1.9       lukem     103:
1.17      christos  104:        if (el->el_line.lastchar + num >= el->el_line.limit) {
1.27      christos  105:                if (!ch_enlargebufs(el, (size_t)num))
1.17      christos  106:                        return;         /* can't go past end of buffer */
                    107:        }
1.9       lukem     108:
                    109:        if (el->el_line.cursor < el->el_line.lastchar) {
                    110:                /* if I must move chars */
                    111:                for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
                    112:                        cp[num] = *cp;
                    113:        }
                    114:        el->el_line.lastchar += num;
                    115: }
1.1       cgd       116:
                    117:
                    118: /* c_delafter():
                    119:  *     Delete num characters after the cursor
                    120:  */
                    121: protected void
1.9       lukem     122: c_delafter(EditLine *el, int num)
1.1       cgd       123: {
                    124:
1.9       lukem     125:        if (el->el_line.cursor + num > el->el_line.lastchar)
1.27      christos  126:                num = (int)(el->el_line.lastchar - el->el_line.cursor);
1.1       cgd       127:
1.17      christos  128:        if (el->el_map.current != el->el_map.emacs) {
                    129:                cv_undo(el);
                    130:                cv_yank(el, el->el_line.cursor, num);
                    131:        }
1.16      christos  132:
1.9       lukem     133:        if (num > 0) {
1.28      christos  134:                Char *cp;
1.1       cgd       135:
1.9       lukem     136:                for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
                    137:                        *cp = cp[num];
1.1       cgd       138:
1.9       lukem     139:                el->el_line.lastchar -= num;
                    140:        }
1.1       cgd       141: }
                    142:
                    143:
1.22      mycroft   144: /* c_delafter1():
                    145:  *     Delete the character after the cursor, do not yank
                    146:  */
                    147: protected void
                    148: c_delafter1(EditLine *el)
                    149: {
1.28      christos  150:        Char *cp;
1.22      mycroft   151:
                    152:        for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
                    153:                *cp = cp[1];
                    154:
                    155:        el->el_line.lastchar--;
                    156: }
                    157:
                    158:
1.1       cgd       159: /* c_delbefore():
                    160:  *     Delete num characters before the cursor
                    161:  */
                    162: protected void
1.9       lukem     163: c_delbefore(EditLine *el, int num)
1.1       cgd       164: {
                    165:
1.9       lukem     166:        if (el->el_line.cursor - num < el->el_line.buffer)
1.27      christos  167:                num = (int)(el->el_line.cursor - el->el_line.buffer);
1.1       cgd       168:
1.17      christos  169:        if (el->el_map.current != el->el_map.emacs) {
                    170:                cv_undo(el);
                    171:                cv_yank(el, el->el_line.cursor - num, num);
                    172:        }
1.16      christos  173:
1.9       lukem     174:        if (num > 0) {
1.28      christos  175:                Char *cp;
1.1       cgd       176:
1.9       lukem     177:                for (cp = el->el_line.cursor - num;
                    178:                    cp <= el->el_line.lastchar;
                    179:                    cp++)
                    180:                        *cp = cp[num];
1.1       cgd       181:
1.9       lukem     182:                el->el_line.lastchar -= num;
                    183:        }
1.1       cgd       184: }
                    185:
                    186:
1.22      mycroft   187: /* c_delbefore1():
                    188:  *     Delete the character before the cursor, do not yank
                    189:  */
                    190: protected void
                    191: c_delbefore1(EditLine *el)
                    192: {
1.28      christos  193:        Char *cp;
1.22      mycroft   194:
                    195:        for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
                    196:                *cp = cp[1];
                    197:
                    198:        el->el_line.lastchar--;
                    199: }
                    200:
                    201:
1.1       cgd       202: /* ce__isword():
                    203:  *     Return if p is part of a word according to emacs
                    204:  */
                    205: protected int
1.41      christos  206: ce__isword(wint_t p)
1.1       cgd       207: {
1.51    ! christos  208:        return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL;
1.1       cgd       209: }
                    210:
                    211:
                    212: /* cv__isword():
                    213:  *     Return if p is part of a word according to vi
                    214:  */
                    215: protected int
1.41      christos  216: cv__isword(wint_t p)
1.1       cgd       217: {
1.50      christos  218:        if (iswalnum(p) || p == L'_')
1.17      christos  219:                return 1;
1.50      christos  220:        if (iswgraph(p))
1.17      christos  221:                return 2;
                    222:        return 0;
1.16      christos  223: }
                    224:
                    225:
                    226: /* cv__isWord():
                    227:  *     Return if p is part of a big word according to vi
                    228:  */
                    229: protected int
1.41      christos  230: cv__isWord(wint_t p)
1.16      christos  231: {
1.50      christos  232:        return !iswspace(p);
1.1       cgd       233: }
                    234:
                    235:
                    236: /* c__prev_word():
                    237:  *     Find the previous word
                    238:  */
1.28      christos  239: protected Char *
1.41      christos  240: c__prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t))
1.9       lukem     241: {
                    242:        p--;
                    243:
                    244:        while (n--) {
1.28      christos  245:                while ((p >= low) && !(*wtest)(*p))
1.9       lukem     246:                        p--;
1.28      christos  247:                while ((p >= low) && (*wtest)(*p))
1.9       lukem     248:                        p--;
                    249:        }
                    250:
                    251:        /* cp now points to one character before the word */
                    252:        p++;
                    253:        if (p < low)
                    254:                p = low;
                    255:        /* cp now points where we want it */
1.32      christos  256:        return p;
1.1       cgd       257: }
                    258:
                    259:
                    260: /* c__next_word():
                    261:  *     Find the next word
                    262:  */
1.28      christos  263: protected Char *
1.41      christos  264: c__next_word(Char *p, Char *high, int n, int (*wtest)(wint_t))
1.9       lukem     265: {
                    266:        while (n--) {
1.28      christos  267:                while ((p < high) && !(*wtest)(*p))
1.9       lukem     268:                        p++;
1.28      christos  269:                while ((p < high) && (*wtest)(*p))
1.9       lukem     270:                        p++;
                    271:        }
                    272:        if (p > high)
                    273:                p = high;
                    274:        /* p now points where we want it */
1.32      christos  275:        return p;
1.1       cgd       276: }
                    277:
                    278: /* cv_next_word():
                    279:  *     Find the next word vi style
                    280:  */
1.28      christos  281: protected Char *
1.41      christos  282: cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(wint_t))
1.9       lukem     283: {
                    284:        int test;
                    285:
                    286:        while (n--) {
1.28      christos  287:                test = (*wtest)(*p);
                    288:                while ((p < high) && (*wtest)(*p) == test)
1.9       lukem     289:                        p++;
                    290:                /*
                    291:                 * vi historically deletes with cw only the word preserving the
                    292:                 * trailing whitespace! This is not what 'w' does..
                    293:                 */
1.16      christos  294:                if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
1.50      christos  295:                        while ((p < high) && iswspace(*p))
1.9       lukem     296:                                p++;
                    297:        }
1.1       cgd       298:
1.9       lukem     299:        /* p now points where we want it */
                    300:        if (p > high)
1.32      christos  301:                return high;
1.9       lukem     302:        else
1.32      christos  303:                return p;
1.1       cgd       304: }
                    305:
                    306:
                    307: /* cv_prev_word():
                    308:  *     Find the previous word vi style
                    309:  */
1.28      christos  310: protected Char *
1.41      christos  311: cv_prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t))
1.1       cgd       312: {
1.9       lukem     313:        int test;
1.1       cgd       314:
1.16      christos  315:        p--;
1.9       lukem     316:        while (n--) {
1.50      christos  317:                while ((p > low) && iswspace(*p))
1.16      christos  318:                        p--;
1.28      christos  319:                test = (*wtest)(*p);
                    320:                while ((p >= low) && (*wtest)(*p) == test)
1.9       lukem     321:                        p--;
                    322:        }
1.16      christos  323:        p++;
1.1       cgd       324:
1.9       lukem     325:        /* p now points where we want it */
                    326:        if (p < low)
1.32      christos  327:                return low;
1.9       lukem     328:        else
1.32      christos  329:                return p;
1.1       cgd       330: }
                    331:
                    332:
                    333: /* cv_delfini():
                    334:  *     Finish vi delete action
                    335:  */
                    336: protected void
1.9       lukem     337: cv_delfini(EditLine *el)
1.1       cgd       338: {
1.9       lukem     339:        int size;
1.17      christos  340:        int action = el->el_chared.c_vcmd.action;
1.1       cgd       341:
1.17      christos  342:        if (action & INSERT)
1.9       lukem     343:                el->el_map.current = el->el_map.key;
1.1       cgd       344:
1.9       lukem     345:        if (el->el_chared.c_vcmd.pos == 0)
1.17      christos  346:                /* sanity */
1.9       lukem     347:                return;
                    348:
1.27      christos  349:        size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
1.17      christos  350:        if (size == 0)
                    351:                size = 1;
1.16      christos  352:        el->el_line.cursor = el->el_chared.c_vcmd.pos;
1.17      christos  353:        if (action & YANK) {
                    354:                if (size > 0)
                    355:                        cv_yank(el, el->el_line.cursor, size);
                    356:                else
                    357:                        cv_yank(el, el->el_line.cursor + size, -size);
1.9       lukem     358:        } else {
1.17      christos  359:                if (size > 0) {
                    360:                        c_delafter(el, size);
                    361:                        re_refresh_cursor(el);
                    362:                } else  {
                    363:                        c_delbefore(el, -size);
                    364:                        el->el_line.cursor += size;
                    365:                }
1.9       lukem     366:        }
1.17      christos  367:        el->el_chared.c_vcmd.action = NOP;
1.1       cgd       368: }
                    369:
                    370:
                    371: /* cv__endword():
                    372:  *     Go to the end of this word according to vi
                    373:  */
1.28      christos  374: protected Char *
1.41      christos  375: cv__endword(Char *p, Char *high, int n, int (*wtest)(wint_t))
1.9       lukem     376: {
1.16      christos  377:        int test;
                    378:
1.9       lukem     379:        p++;
1.1       cgd       380:
1.9       lukem     381:        while (n--) {
1.50      christos  382:                while ((p < high) && iswspace(*p))
1.9       lukem     383:                        p++;
                    384:
1.28      christos  385:                test = (*wtest)(*p);
                    386:                while ((p < high) && (*wtest)(*p) == test)
1.16      christos  387:                        p++;
1.9       lukem     388:        }
                    389:        p--;
1.32      christos  390:        return p;
1.1       cgd       391: }
                    392:
                    393: /* ch_init():
                    394:  *     Initialize the character editor
                    395:  */
                    396: protected int
1.9       lukem     397: ch_init(EditLine *el)
1.1       cgd       398: {
1.24      christos  399:        c_macro_t *ma = &el->el_chared.c_macro;
                    400:
1.28      christos  401:        el->el_line.buffer              = el_malloc(EL_BUFSIZ *
                    402:            sizeof(*el->el_line.buffer));
1.11      christos  403:        if (el->el_line.buffer == NULL)
1.32      christos  404:                return -1;
1.11      christos  405:
1.28      christos  406:        (void) memset(el->el_line.buffer, 0, EL_BUFSIZ *
                    407:            sizeof(*el->el_line.buffer));
1.9       lukem     408:        el->el_line.cursor              = el->el_line.buffer;
                    409:        el->el_line.lastchar            = el->el_line.buffer;
1.16      christos  410:        el->el_line.limit               = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
1.9       lukem     411:
1.28      christos  412:        el->el_chared.c_undo.buf        = el_malloc(EL_BUFSIZ *
                    413:            sizeof(*el->el_chared.c_undo.buf));
1.11      christos  414:        if (el->el_chared.c_undo.buf == NULL)
1.32      christos  415:                return -1;
1.28      christos  416:        (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ *
                    417:            sizeof(*el->el_chared.c_undo.buf));
1.16      christos  418:        el->el_chared.c_undo.len        = -1;
                    419:        el->el_chared.c_undo.cursor     = 0;
1.28      christos  420:        el->el_chared.c_redo.buf        = el_malloc(EL_BUFSIZ *
                    421:            sizeof(*el->el_chared.c_redo.buf));
1.17      christos  422:        if (el->el_chared.c_redo.buf == NULL)
1.32      christos  423:                return -1;
1.17      christos  424:        el->el_chared.c_redo.pos        = el->el_chared.c_redo.buf;
                    425:        el->el_chared.c_redo.lim        = el->el_chared.c_redo.buf + EL_BUFSIZ;
                    426:        el->el_chared.c_redo.cmd        = ED_UNASSIGNED;
1.9       lukem     427:
                    428:        el->el_chared.c_vcmd.action     = NOP;
                    429:        el->el_chared.c_vcmd.pos        = el->el_line.buffer;
                    430:
1.28      christos  431:        el->el_chared.c_kill.buf        = el_malloc(EL_BUFSIZ *
                    432:            sizeof(*el->el_chared.c_kill.buf));
1.11      christos  433:        if (el->el_chared.c_kill.buf == NULL)
1.32      christos  434:                return -1;
1.28      christos  435:        (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ *
                    436:            sizeof(*el->el_chared.c_kill.buf));
1.9       lukem     437:        el->el_chared.c_kill.mark       = el->el_line.buffer;
                    438:        el->el_chared.c_kill.last       = el->el_chared.c_kill.buf;
1.29      christos  439:        el->el_chared.c_resizefun       = NULL;
                    440:        el->el_chared.c_resizearg       = NULL;
1.40      christos  441:        el->el_chared.c_aliasfun        = NULL;
                    442:        el->el_chared.c_aliasarg        = NULL;
1.9       lukem     443:
                    444:        el->el_map.current              = el->el_map.key;
                    445:
                    446:        el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
                    447:        el->el_state.doingarg           = 0;
                    448:        el->el_state.metanext           = 0;
                    449:        el->el_state.argument           = 1;
                    450:        el->el_state.lastcmd            = ED_UNASSIGNED;
                    451:
1.24      christos  452:        ma->level       = -1;
                    453:        ma->offset      = 0;
1.28      christos  454:        ma->macro       = el_malloc(EL_MAXMACRO * sizeof(*ma->macro));
1.24      christos  455:        if (ma->macro == NULL)
1.32      christos  456:                return -1;
                    457:        return 0;
1.1       cgd       458: }
                    459:
                    460: /* ch_reset():
                    461:  *     Reset the character editor
                    462:  */
                    463: protected void
1.24      christos  464: ch_reset(EditLine *el, int mclear)
1.1       cgd       465: {
1.9       lukem     466:        el->el_line.cursor              = el->el_line.buffer;
                    467:        el->el_line.lastchar            = el->el_line.buffer;
1.1       cgd       468:
1.16      christos  469:        el->el_chared.c_undo.len        = -1;
                    470:        el->el_chared.c_undo.cursor     = 0;
1.1       cgd       471:
1.9       lukem     472:        el->el_chared.c_vcmd.action     = NOP;
                    473:        el->el_chared.c_vcmd.pos        = el->el_line.buffer;
1.1       cgd       474:
1.9       lukem     475:        el->el_chared.c_kill.mark       = el->el_line.buffer;
1.1       cgd       476:
1.9       lukem     477:        el->el_map.current              = el->el_map.key;
1.1       cgd       478:
1.9       lukem     479:        el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
                    480:        el->el_state.doingarg           = 0;
                    481:        el->el_state.metanext           = 0;
                    482:        el->el_state.argument           = 1;
                    483:        el->el_state.lastcmd            = ED_UNASSIGNED;
1.1       cgd       484:
1.25      christos  485:        el->el_history.eventno          = 0;
                    486:
1.24      christos  487:        if (mclear)
                    488:                ch__clearmacro(el);
                    489: }
1.1       cgd       490:
1.24      christos  491: private void
1.27      christos  492: ch__clearmacro(EditLine *el)
1.24      christos  493: {
                    494:        c_macro_t *ma = &el->el_chared.c_macro;
                    495:        while (ma->level >= 0)
1.31      christos  496:                el_free(ma->macro[ma->level--]);
1.1       cgd       497: }
                    498:
1.12      jdolecek  499: /* ch_enlargebufs():
                    500:  *     Enlarge line buffer to be able to hold twice as much characters.
                    501:  *     Returns 1 if successful, 0 if not.
                    502:  */
                    503: protected int
1.27      christos  504: ch_enlargebufs(EditLine *el, size_t addlen)
1.12      jdolecek  505: {
1.13      lukem     506:        size_t sz, newsz;
1.28      christos  507:        Char *newbuffer, *oldbuf, *oldkbuf;
1.12      jdolecek  508:
1.35      christos  509:        sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
1.13      lukem     510:        newsz = sz * 2;
                    511:        /*
                    512:         * If newly required length is longer than current buffer, we need
                    513:         * to make the buffer big enough to hold both old and new stuff.
                    514:         */
                    515:        if (addlen > sz) {
                    516:                while(newsz - sz < addlen)
                    517:                        newsz *= 2;
                    518:        }
                    519:
                    520:        /*
                    521:         * Reallocate line buffer.
                    522:         */
1.28      christos  523:        newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
1.13      lukem     524:        if (!newbuffer)
                    525:                return 0;
                    526:
                    527:        /* zero the newly added memory, leave old data in */
1.28      christos  528:        (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
1.47      christos  529:
1.13      lukem     530:        oldbuf = el->el_line.buffer;
                    531:
                    532:        el->el_line.buffer = newbuffer;
                    533:        el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
                    534:        el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
1.16      christos  535:        /* don't set new size until all buffers are enlarged */
                    536:        el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
1.13      lukem     537:
                    538:        /*
                    539:         * Reallocate kill buffer.
                    540:         */
1.31      christos  541:        newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
                    542:            sizeof(*newbuffer));
1.13      lukem     543:        if (!newbuffer)
                    544:                return 0;
1.12      jdolecek  545:
1.13      lukem     546:        /* zero the newly added memory, leave old data in */
1.28      christos  547:        (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
1.12      jdolecek  548:
1.13      lukem     549:        oldkbuf = el->el_chared.c_kill.buf;
1.12      jdolecek  550:
1.13      lukem     551:        el->el_chared.c_kill.buf = newbuffer;
                    552:        el->el_chared.c_kill.last = newbuffer +
1.12      jdolecek  553:                                        (el->el_chared.c_kill.last - oldkbuf);
1.13      lukem     554:        el->el_chared.c_kill.mark = el->el_line.buffer +
1.12      jdolecek  555:                                        (el->el_chared.c_kill.mark - oldbuf);
                    556:
1.13      lukem     557:        /*
                    558:         * Reallocate undo buffer.
                    559:         */
1.28      christos  560:        newbuffer = el_realloc(el->el_chared.c_undo.buf,
                    561:            newsz * sizeof(*newbuffer));
1.13      lukem     562:        if (!newbuffer)
                    563:                return 0;
                    564:
                    565:        /* zero the newly added memory, leave old data in */
1.28      christos  566:        (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
1.16      christos  567:        el->el_chared.c_undo.buf = newbuffer;
1.13      lukem     568:
1.28      christos  569:        newbuffer = el_realloc(el->el_chared.c_redo.buf,
                    570:            newsz * sizeof(*newbuffer));
1.16      christos  571:        if (!newbuffer)
                    572:                return 0;
1.17      christos  573:        el->el_chared.c_redo.pos = newbuffer +
                    574:                        (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
                    575:        el->el_chared.c_redo.lim = newbuffer +
                    576:                        (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
                    577:        el->el_chared.c_redo.buf = newbuffer;
1.47      christos  578:
1.13      lukem     579:        if (!hist_enlargebuf(el, sz, newsz))
                    580:                return 0;
1.12      jdolecek  581:
1.16      christos  582:        /* Safe to set enlarged buffer size */
1.21      christos  583:        el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
1.29      christos  584:        if (el->el_chared.c_resizefun)
                    585:                (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
1.13      lukem     586:        return 1;
1.12      jdolecek  587: }
1.1       cgd       588:
                    589: /* ch_end():
                    590:  *     Free the data structures used by the editor
                    591:  */
                    592: protected void
1.9       lukem     593: ch_end(EditLine *el)
1.1       cgd       594: {
1.31      christos  595:        el_free(el->el_line.buffer);
1.9       lukem     596:        el->el_line.buffer = NULL;
                    597:        el->el_line.limit = NULL;
1.31      christos  598:        el_free(el->el_chared.c_undo.buf);
1.9       lukem     599:        el->el_chared.c_undo.buf = NULL;
1.31      christos  600:        el_free(el->el_chared.c_redo.buf);
1.17      christos  601:        el->el_chared.c_redo.buf = NULL;
                    602:        el->el_chared.c_redo.pos = NULL;
                    603:        el->el_chared.c_redo.lim = NULL;
                    604:        el->el_chared.c_redo.cmd = ED_UNASSIGNED;
1.31      christos  605:        el_free(el->el_chared.c_kill.buf);
1.9       lukem     606:        el->el_chared.c_kill.buf = NULL;
1.24      christos  607:        ch_reset(el, 1);
1.31      christos  608:        el_free(el->el_chared.c_macro.macro);
1.9       lukem     609:        el->el_chared.c_macro.macro = NULL;
1.1       cgd       610: }
                    611:
                    612:
                    613: /* el_insertstr():
                    614:  *     Insert string at cursorI
                    615:  */
                    616: public int
1.51    ! christos  617: el_winsertstr(EditLine *el, const Char *s)
1.9       lukem     618: {
1.14      christos  619:        size_t len;
1.9       lukem     620:
1.51    ! christos  621:        if (s == NULL || (len = wcslen(s)) == 0)
1.32      christos  622:                return -1;
1.12      jdolecek  623:        if (el->el_line.lastchar + len >= el->el_line.limit) {
                    624:                if (!ch_enlargebufs(el, len))
1.32      christos  625:                        return -1;
1.12      jdolecek  626:        }
1.9       lukem     627:
1.14      christos  628:        c_insert(el, (int)len);
1.9       lukem     629:        while (*s)
                    630:                *el->el_line.cursor++ = *s++;
1.32      christos  631:        return 0;
1.1       cgd       632: }
                    633:
                    634:
                    635: /* el_deletestr():
                    636:  *     Delete num characters before the cursor
                    637:  */
                    638: public void
1.9       lukem     639: el_deletestr(EditLine *el, int n)
                    640: {
                    641:        if (n <= 0)
                    642:                return;
                    643:
                    644:        if (el->el_line.cursor < &el->el_line.buffer[n])
                    645:                return;
                    646:
                    647:        c_delbefore(el, n);             /* delete before dot */
                    648:        el->el_line.cursor -= n;
                    649:        if (el->el_line.cursor < el->el_line.buffer)
                    650:                el->el_line.cursor = el->el_line.buffer;
1.1       cgd       651: }
                    652:
1.38      christos  653: /* el_cursor():
                    654:  *     Move the cursor to the left or the right of the current position
                    655:  */
                    656: public int
                    657: el_cursor(EditLine *el, int n)
                    658: {
                    659:        if (n == 0)
                    660:                goto out;
                    661:
                    662:        el->el_line.cursor += n;
                    663:
                    664:        if (el->el_line.cursor < el->el_line.buffer)
                    665:                el->el_line.cursor = el->el_line.buffer;
                    666:        if (el->el_line.cursor > el->el_line.lastchar)
                    667:                el->el_line.cursor = el->el_line.lastchar;
                    668: out:
1.39      christos  669:        return (int)(el->el_line.cursor - el->el_line.buffer);
1.38      christos  670: }
                    671:
1.1       cgd       672: /* c_gets():
                    673:  *     Get a string
                    674:  */
                    675: protected int
1.28      christos  676: c_gets(EditLine *el, Char *buf, const Char *prompt)
1.9       lukem     677: {
1.48      christos  678:        wchar_t wch;
1.27      christos  679:        ssize_t len;
1.48      christos  680:        Char *cp = el->el_line.buffer, ch;
1.18      christos  681:
                    682:        if (prompt) {
1.51    ! christos  683:                len = (ssize_t)wcslen(prompt);
1.35      christos  684:                (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
1.18      christos  685:                cp += len;
                    686:        }
                    687:        len = 0;
                    688:
                    689:        for (;;) {
                    690:                el->el_line.cursor = cp;
                    691:                *cp = ' ';
                    692:                el->el_line.lastchar = cp + 1;
                    693:                re_refresh(el);
                    694:
1.48      christos  695:                if (el_wgetc(el, &wch) != 1) {
1.18      christos  696:                        ed_end_of_file(el, 0);
                    697:                        len = -1;
                    698:                        break;
                    699:                }
1.48      christos  700:                ch = (Char)wch;
1.1       cgd       701:
1.9       lukem     702:                switch (ch) {
1.18      christos  703:
1.48      christos  704:                case L'\b':     /* Delete and backspace */
1.9       lukem     705:                case 0177:
1.27      christos  706:                        if (len == 0) {
1.18      christos  707:                                len = -1;
                    708:                                break;
1.9       lukem     709:                        }
1.49      christos  710:                        len--;
1.18      christos  711:                        cp--;
                    712:                        continue;
1.9       lukem     713:
                    714:                case 0033:      /* ESC */
1.48      christos  715:                case L'\r':     /* Newline */
                    716:                case L'\n':
1.18      christos  717:                        buf[len] = ch;
1.9       lukem     718:                        break;
                    719:
                    720:                default:
1.34      christos  721:                        if (len >= (ssize_t)(EL_BUFSIZ - 16))
1.30      christos  722:                                terminal_beep(el);
1.9       lukem     723:                        else {
                    724:                                buf[len++] = ch;
1.18      christos  725:                                *cp++ = ch;
1.9       lukem     726:                        }
1.18      christos  727:                        continue;
1.9       lukem     728:                }
1.18      christos  729:                break;
1.9       lukem     730:        }
1.18      christos  731:
                    732:        el->el_line.buffer[0] = '\0';
                    733:        el->el_line.lastchar = el->el_line.buffer;
                    734:        el->el_line.cursor = el->el_line.buffer;
1.27      christos  735:        return (int)len;
1.1       cgd       736: }
                    737:
                    738:
                    739: /* c_hpos():
                    740:  *     Return the current horizontal position of the cursor
                    741:  */
                    742: protected int
1.9       lukem     743: c_hpos(EditLine *el)
1.1       cgd       744: {
1.28      christos  745:        Char *ptr;
1.1       cgd       746:
1.9       lukem     747:        /*
                    748:         * Find how many characters till the beginning of this line.
                    749:         */
                    750:        if (el->el_line.cursor == el->el_line.buffer)
1.32      christos  751:                return 0;
1.9       lukem     752:        else {
                    753:                for (ptr = el->el_line.cursor - 1;
                    754:                     ptr >= el->el_line.buffer && *ptr != '\n';
                    755:                     ptr--)
                    756:                        continue;
1.27      christos  757:                return (int)(el->el_line.cursor - ptr - 1);
1.9       lukem     758:        }
1.1       cgd       759: }
1.29      christos  760:
                    761: protected int
                    762: ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
                    763: {
                    764:        el->el_chared.c_resizefun = f;
                    765:        el->el_chared.c_resizearg = a;
                    766:        return 0;
                    767: }
1.40      christos  768:
                    769: protected int
                    770: ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
                    771: {
                    772:        el->el_chared.c_aliasfun = f;
                    773:        el->el_chared.c_aliasarg = a;
                    774:        return 0;
                    775: }

CVSweb <webmaster@jp.NetBSD.org>