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

1.5     ! christos    1: /*     $NetBSD: chared.c,v 1.4 1998/02/03 19:12:37 perry 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.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
                     22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  */
                     38:
1.3       christos   39: #include <sys/cdefs.h>
1.1       cgd        40: #if !defined(lint) && !defined(SCCSID)
1.2       lukem      41: #if 0
1.1       cgd        42: static char sccsid[] = "@(#)chared.c   8.1 (Berkeley) 6/4/93";
1.2       lukem      43: #else
1.5     ! christos   44: __RCSID("$NetBSD: chared.c,v 1.4 1998/02/03 19:12:37 perry Exp $");
1.2       lukem      45: #endif
1.1       cgd        46: #endif /* not lint && not SCCSID */
                     47:
                     48: /*
                     49:  * chared.c: Character editor utilities
                     50:  */
                     51: #include "sys.h"
                     52:
                     53: #include <stdlib.h>
                     54: #include "el.h"
                     55:
                     56: /* cv_undo():
                     57:  *     Handle state for the vi undo command
                     58:  */
                     59: protected void
                     60: cv_undo(el, action, size, ptr)
                     61:     EditLine *el;
1.5     ! christos   62:     int action;
        !            63:     size_t size;
1.1       cgd        64:     char *ptr;
                     65: {
                     66:     c_undo_t *vu = &el->el_chared.c_undo;
                     67:     vu->action = action;
                     68:     vu->ptr    = ptr;
                     69:     vu->isize  = size;
                     70:     (void) memcpy(vu->buf, vu->ptr, size);
                     71: #ifdef DEBUG_UNDO
                     72:     (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
                     73:                   vu->ptr, vu->isize, vu->dsize);
                     74: #endif
                     75: }
                     76:
                     77:
                     78: /* c_insert():
                     79:  *     Insert num characters
                     80:  */
                     81: protected void
                     82: c_insert(el, num)
                     83:     EditLine *el;
                     84:     int num;
                     85: {
                     86:     char *cp;
                     87:
                     88:     if (el->el_line.lastchar + num >= el->el_line.limit)
                     89:        return;                 /* can't go past end of buffer */
                     90:
                     91:     if (el->el_line.cursor < el->el_line.lastchar) {
                     92:        /* if I must move chars */
                     93:        for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
                     94:            cp[num] = *cp;
                     95:     }
                     96:     el->el_line.lastchar += num;
                     97: } /* end c_insert */
                     98:
                     99:
                    100: /* c_delafter():
                    101:  *     Delete num characters after the cursor
                    102:  */
                    103: protected void
                    104: c_delafter(el, num)
                    105:     EditLine *el;
                    106:     int num;
                    107: {
                    108:
                    109:     if (el->el_line.cursor + num > el->el_line.lastchar)
                    110:        num = el->el_line.lastchar - el->el_line.cursor;
                    111:
                    112:     if (num > 0) {
                    113:        char *cp;
                    114:
                    115:        if (el->el_map.current != el->el_map.emacs)
                    116:            cv_undo(el, INSERT, num, el->el_line.cursor);
                    117:
                    118:        for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
                    119:            *cp = cp[num];
                    120:
                    121:        el->el_line.lastchar -= num;
                    122:     }
                    123: }
                    124:
                    125:
                    126: /* c_delbefore():
                    127:  *     Delete num characters before the cursor
                    128:  */
                    129: protected void
                    130: c_delbefore(el, num)
                    131:     EditLine *el;
                    132:     int num;
                    133: {
                    134:
                    135:     if (el->el_line.cursor - num < el->el_line.buffer)
                    136:        num = el->el_line.cursor - el->el_line.buffer;
                    137:
                    138:     if (num > 0) {
                    139:        char *cp;
                    140:
                    141:        if (el->el_map.current != el->el_map.emacs)
                    142:            cv_undo(el, INSERT, num, el->el_line.cursor - num);
                    143:
                    144:        for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++)
                    145:            *cp = cp[num];
                    146:
                    147:        el->el_line.lastchar -= num;
                    148:     }
                    149: }
                    150:
                    151:
                    152: /* ce__isword():
                    153:  *     Return if p is part of a word according to emacs
                    154:  */
                    155: protected int
                    156: ce__isword(p)
                    157:     int p;
                    158: {
                    159:     return isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL;
                    160: }
                    161:
                    162:
                    163: /* cv__isword():
                    164:  *     Return if p is part of a word according to vi
                    165:  */
                    166: protected int
                    167: cv__isword(p)
                    168:     int p;
                    169: {
                    170:     return !isspace(p);
                    171: }
                    172:
                    173:
                    174: /* c__prev_word():
                    175:  *     Find the previous word
                    176:  */
                    177: protected char *
                    178: c__prev_word(p, low, n, wtest)
1.4       perry     179:     char *p, *low;
                    180:     int n;
1.1       cgd       181:     int (*wtest) __P((int));
                    182: {
                    183:     p--;
                    184:
                    185:     while (n--) {
                    186:        while ((p >= low) && !(*wtest)((unsigned char) *p))
                    187:            p--;
                    188:        while ((p >= low) && (*wtest)((unsigned char) *p))
                    189:            p--;
                    190:     }
                    191:
                    192:     /* cp now points to one character before the word */
                    193:     p++;
                    194:     if (p < low)
                    195:        p = low;
                    196:     /* cp now points where we want it */
                    197:     return p;
                    198: }
                    199:
                    200:
                    201: /* c__next_word():
                    202:  *     Find the next word
                    203:  */
                    204: protected char *
                    205: c__next_word(p, high, n, wtest)
1.4       perry     206:     char *p, *high;
                    207:     int n;
1.1       cgd       208:     int (*wtest) __P((int));
                    209: {
                    210:     while (n--) {
                    211:        while ((p < high) && !(*wtest)((unsigned char) *p))
                    212:            p++;
                    213:        while ((p < high) && (*wtest)((unsigned char) *p))
                    214:            p++;
                    215:     }
                    216:     if (p > high)
                    217:        p = high;
                    218:     /* p now points where we want it */
                    219:     return p;
                    220: }
                    221:
                    222: /* cv_next_word():
                    223:  *     Find the next word vi style
                    224:  */
                    225: protected char *
                    226: cv_next_word(el, p, high, n, wtest)
                    227:     EditLine *el;
1.4       perry     228:     char *p, *high;
                    229:     int n;
1.1       cgd       230:     int (*wtest) __P((int));
                    231: {
                    232:     int test;
                    233:
                    234:     while (n--) {
                    235:        test = (*wtest)((unsigned char) *p);
                    236:        while ((p < high) && (*wtest)((unsigned char) *p) == test)
                    237:            p++;
                    238:        /*
                    239:         * vi historically deletes with cw only the word preserving the
                    240:         * trailing whitespace! This is not what 'w' does..
                    241:         */
                    242:        if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
                    243:            while ((p < high) && isspace((unsigned char) *p))
                    244:                p++;
                    245:     }
                    246:
                    247:     /* p now points where we want it */
                    248:     if (p > high)
                    249:        return high;
                    250:     else
                    251:        return p;
                    252: }
                    253:
                    254:
                    255: /* cv_prev_word():
                    256:  *     Find the previous word vi style
                    257:  */
                    258: protected char *
                    259: cv_prev_word(el, p, low, n, wtest)
                    260:     EditLine *el;
1.4       perry     261:     char *p, *low;
                    262:     int n;
1.1       cgd       263:     int (*wtest) __P((int));
                    264: {
                    265:     int test;
                    266:
                    267:     while (n--) {
                    268:        p--;
                    269:        /*
                    270:         * vi historically deletes with cb only the word preserving the
                    271:         * leading whitespace! This is not what 'b' does..
                    272:         */
                    273:        if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
                    274:            while ((p > low) && isspace((unsigned char) *p))
                    275:                p--;
                    276:        test = (*wtest)((unsigned char) *p);
                    277:        while ((p >= low) && (*wtest)((unsigned char) *p) == test)
                    278:            p--;
                    279:        p++;
                    280:        while (isspace((unsigned char) *p))
                    281:                p++;
                    282:     }
                    283:
                    284:     /* p now points where we want it */
                    285:     if (p < low)
                    286:        return low;
                    287:     else
                    288:        return p;
                    289: }
                    290:
                    291:
                    292: #ifdef notdef
                    293: /* c__number():
                    294:  *     Ignore character p points to, return number appearing after that.
                    295:  *     A '$' by itself means a big number; "$-" is for negative; '^' means 1.
                    296:  *     Return p pointing to last char used.
                    297:  */
                    298: protected char *
                    299: c__number(p, num, dval)
                    300:     char *p;   /* character position */
                    301:     int *num;  /* Return value */
                    302:     int dval;  /* dval is the number to subtract from like $-3 */
                    303: {
1.4       perry     304:     int i;
                    305:     int sign = 1;
1.1       cgd       306:
                    307:     if (*++p == '^') {
                    308:        *num = 1;
                    309:        return p;
                    310:     }
                    311:     if (*p == '$') {
                    312:        if (*++p != '-') {
                    313:            *num = 0x7fffffff;  /* Handle $ */
                    314:            return --p;
                    315:        }
                    316:        sign = -1;              /* Handle $- */
                    317:        ++p;
                    318:     }
                    319:     for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
                    320:        continue;
                    321:     *num = (sign < 0 ? dval - i : i);
                    322:     return --p;
                    323: }
                    324: #endif
                    325:
                    326: /* cv_delfini():
                    327:  *     Finish vi delete action
                    328:  */
                    329: protected void
                    330: cv_delfini(el)
                    331:     EditLine *el;
                    332: {
1.4       perry     333:     int size;
1.1       cgd       334:     int oaction;
                    335:
                    336:     if (el->el_chared.c_vcmd.action & INSERT)
                    337:        el->el_map.current = el->el_map.key;
                    338:
                    339:     oaction = el->el_chared.c_vcmd.action;
                    340:     el->el_chared.c_vcmd.action = NOP;
                    341:
                    342:     if (el->el_chared.c_vcmd.pos == 0)
                    343:        return;
                    344:
                    345:
                    346:     if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
                    347:        size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
                    348:        c_delbefore(el, size);
                    349:        el->el_line.cursor = el->el_chared.c_vcmd.pos;
                    350:        re_refresh_cursor(el);
                    351:     }
                    352:     else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
                    353:        size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
                    354:        c_delafter(el, size);
                    355:     }
                    356:     else {
                    357:        size = 1;
                    358:        c_delafter(el, size);
                    359:     }
                    360:     switch (oaction) {
                    361:     case DELETE|INSERT:
                    362:        el->el_chared.c_undo.action = DELETE|INSERT;
                    363:        break;
                    364:     case DELETE:
                    365:        el->el_chared.c_undo.action = INSERT;
                    366:        break;
                    367:     case NOP:
                    368:     case INSERT:
                    369:     default:
                    370:        abort();
                    371:        break;
                    372:     }
                    373:
                    374:
                    375:     el->el_chared.c_undo.ptr = el->el_line.cursor;
                    376:     el->el_chared.c_undo.dsize = size;
                    377: }
                    378:
                    379:
                    380: #ifdef notdef
                    381: /* ce__endword():
                    382:  *     Go to the end of this word according to emacs
                    383:  */
                    384: protected char *
                    385: ce__endword(p, high, n)
                    386:     char *p, *high;
                    387:     int n;
                    388: {
                    389:     p++;
                    390:
                    391:     while (n--) {
                    392:        while ((p < high) && isspace((unsigned char) *p))
                    393:            p++;
                    394:        while ((p < high) && !isspace((unsigned char) *p))
                    395:            p++;
                    396:     }
                    397:
                    398:     p--;
                    399:     return p;
                    400: }
                    401: #endif
                    402:
                    403:
                    404: /* cv__endword():
                    405:  *     Go to the end of this word according to vi
                    406:  */
                    407: protected char *
                    408: cv__endword(p, high, n)
                    409:     char *p, *high;
                    410:     int n;
                    411: {
                    412:     p++;
                    413:
                    414:     while (n--) {
                    415:        while ((p < high) && isspace((unsigned char) *p))
                    416:            p++;
                    417:
                    418:        if (isalnum((unsigned char) *p))
                    419:            while ((p < high) && isalnum((unsigned char) *p))
                    420:                p++;
                    421:        else
                    422:            while ((p < high) && !(isspace((unsigned char) *p) ||
                    423:                                   isalnum((unsigned char) *p)))
                    424:                p++;
                    425:     }
                    426:     p--;
                    427:     return p;
                    428: }
                    429:
                    430: /* ch_init():
                    431:  *     Initialize the character editor
                    432:  */
                    433: protected int
                    434: ch_init(el)
                    435:     EditLine *el;
                    436: {
                    437:     el->el_line.buffer              = (char *)  el_malloc(EL_BUFSIZ);
                    438:     (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
                    439:     el->el_line.cursor              = el->el_line.buffer;
                    440:     el->el_line.lastchar            = el->el_line.buffer;
                    441:     el->el_line.limit                      = &el->el_line.buffer[EL_BUFSIZ - 2];
                    442:
                    443:     el->el_chared.c_undo.buf        = (char *)  el_malloc(EL_BUFSIZ);
                    444:     (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
                    445:     el->el_chared.c_undo.action     = NOP;
                    446:     el->el_chared.c_undo.isize      = 0;
                    447:     el->el_chared.c_undo.dsize      = 0;
                    448:     el->el_chared.c_undo.ptr        = el->el_line.buffer;
                    449:
                    450:     el->el_chared.c_vcmd.action     = NOP;
                    451:     el->el_chared.c_vcmd.pos        = el->el_line.buffer;
                    452:     el->el_chared.c_vcmd.ins        = el->el_line.buffer;
                    453:
                    454:     el->el_chared.c_kill.buf        = (char *)  el_malloc(EL_BUFSIZ);
                    455:     (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
                    456:     el->el_chared.c_kill.mark       = el->el_line.buffer;
                    457:     el->el_chared.c_kill.last       = el->el_chared.c_kill.buf;
                    458:
                    459:     el->el_map.current              = el->el_map.key;
                    460:
                    461:     el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
                    462:     el->el_state.doingarg  = 0;
                    463:     el->el_state.metanext  = 0;
                    464:     el->el_state.argument  = 1;
                    465:     el->el_state.lastcmd   = ED_UNASSIGNED;
                    466:
                    467:     el->el_chared.c_macro.nline     = NULL;
                    468:     el->el_chared.c_macro.level     = -1;
                    469:     el->el_chared.c_macro.macro     = (char **) el_malloc(EL_MAXMACRO *
                    470:                                                          sizeof(char *));
                    471:     return 0;
                    472: }
                    473:
                    474: /* ch_reset():
                    475:  *     Reset the character editor
                    476:  */
                    477: protected void
                    478: ch_reset(el)
                    479:     EditLine *el;
                    480: {
                    481:     el->el_line.cursor              = el->el_line.buffer;
                    482:     el->el_line.lastchar            = el->el_line.buffer;
                    483:
                    484:     el->el_chared.c_undo.action     = NOP;
                    485:     el->el_chared.c_undo.isize      = 0;
                    486:     el->el_chared.c_undo.dsize      = 0;
                    487:     el->el_chared.c_undo.ptr        = el->el_line.buffer;
                    488:
                    489:     el->el_chared.c_vcmd.action     = NOP;
                    490:     el->el_chared.c_vcmd.pos        = el->el_line.buffer;
                    491:     el->el_chared.c_vcmd.ins        = el->el_line.buffer;
                    492:
                    493:     el->el_chared.c_kill.mark       = el->el_line.buffer;
                    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:
                    503:     el->el_chared.c_macro.level     = -1;
                    504:
                    505:     el->el_history.eventno = 0;
                    506: }
                    507:
                    508:
                    509: /* ch_end():
                    510:  *     Free the data structures used by the editor
                    511:  */
                    512: protected void
                    513: ch_end(el)
                    514:     EditLine *el;
                    515: {
                    516:     el_free((ptr_t) el->el_line.buffer);
                    517:     el->el_line.buffer = NULL;
                    518:     el->el_line.limit = NULL;
                    519:     el_free((ptr_t) el->el_chared.c_undo.buf);
                    520:     el->el_chared.c_undo.buf = NULL;
                    521:     el_free((ptr_t) el->el_chared.c_kill.buf);
                    522:     el->el_chared.c_kill.buf = NULL;
                    523:     el_free((ptr_t) el->el_chared.c_macro.macro);
                    524:     el->el_chared.c_macro.macro = NULL;
                    525:     ch_reset(el);
                    526: }
                    527:
                    528:
                    529: /* el_insertstr():
                    530:  *     Insert string at cursorI
                    531:  */
                    532: public int
                    533: el_insertstr(el, s)
                    534:     EditLine *el;
                    535:     char   *s;
                    536: {
                    537:     int len;
                    538:
                    539:     if ((len = strlen(s)) == 0)
                    540:        return -1;
                    541:     if (el->el_line.lastchar + len >= el->el_line.limit)
                    542:        return -1;
                    543:
                    544:     c_insert(el, len);
                    545:     while (*s)
                    546:        *el->el_line.cursor++ = *s++;
                    547:     return 0;
                    548: }
                    549:
                    550:
                    551: /* el_deletestr():
                    552:  *     Delete num characters before the cursor
                    553:  */
                    554: public void
                    555: el_deletestr(el, n)
                    556:     EditLine *el;
                    557:     int     n;
                    558: {
                    559:     if (n <= 0)
                    560:        return;
                    561:
                    562:     if (el->el_line.cursor < &el->el_line.buffer[n])
                    563:        return;
                    564:
                    565:     c_delbefore(el, n);                /* delete before dot */
                    566:     el->el_line.cursor -= n;
                    567:     if (el->el_line.cursor < el->el_line.buffer)
                    568:        el->el_line.cursor = el->el_line.buffer;
                    569: }
                    570:
                    571: /* c_gets():
                    572:  *     Get a string
                    573:  */
                    574: protected int
                    575: c_gets(el, buf)
                    576:     EditLine *el;
                    577:     char *buf;
                    578: {
                    579:     char ch;
                    580:     int len = 0;
                    581:
                    582:     for (ch = 0; ch == 0;) {
                    583:        if (el_getc(el, &ch) != 1)
                    584:            return ed_end_of_file(el, 0);
                    585:        switch (ch) {
                    586:        case 0010:      /* Delete and backspace */
                    587:        case 0177:
                    588:            if (len > 1) {
                    589:                *el->el_line.cursor-- = '\0';
                    590:                el->el_line.lastchar = el->el_line.cursor;
                    591:                buf[len--] = '\0';
                    592:            }
                    593:            else {
                    594:                el->el_line.buffer[0] = '\0';
                    595:                el->el_line.lastchar = el->el_line.buffer;
                    596:                el->el_line.cursor = el->el_line.buffer;
                    597:                return CC_REFRESH;
                    598:            }
                    599:            re_refresh(el);
                    600:            ch = 0;
                    601:            break;
                    602:
                    603:        case 0033:      /* ESC */
                    604:        case '\r':      /* Newline */
                    605:        case '\n':
                    606:            break;
                    607:
                    608:        default:
                    609:            if (len >= EL_BUFSIZ)
                    610:                term_beep(el);
                    611:            else {
                    612:                buf[len++] = ch;
                    613:                *el->el_line.cursor++ = ch;
                    614:                el->el_line.lastchar = el->el_line.cursor;
                    615:            }
                    616:            re_refresh(el);
                    617:            ch = 0;
                    618:            break;
                    619:        }
                    620:     }
                    621:     buf[len] = ch;
                    622:     return len;
                    623: }
                    624:
                    625:
                    626: /* c_hpos():
                    627:  *     Return the current horizontal position of the cursor
                    628:  */
                    629: protected int
                    630: c_hpos(el)
                    631:     EditLine *el;
                    632: {
                    633:     char *ptr;
                    634:
                    635:     /*
                    636:      * Find how many characters till the beginning of this line.
                    637:      */
                    638:     if (el->el_line.cursor == el->el_line.buffer)
                    639:        return 0;
                    640:     else {
                    641:        for (ptr = el->el_line.cursor - 1;
                    642:             ptr >= el->el_line.buffer && *ptr != '\n';
                    643:             ptr--)
                    644:            continue;
                    645:        return el->el_line.cursor - ptr - 1;
                    646:     }
                    647: }

CVSweb <webmaster@jp.NetBSD.org>