[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.30

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

CVSweb <webmaster@jp.NetBSD.org>