[BACK]Return to extend.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/extend.c, Revision 1.17

1.17    ! art         1: /*     $OpenBSD: extend.c,v 1.16 2001/05/24 09:47:33 art Exp $ */
1.6       niklas      2:
1.1       deraadt     3: /*
1.5       millert     4:  *     Extended (M-X) commands, rebinding, and startup file processing.
1.1       deraadt     5:  */
1.5       millert     6:
                      7: #include "def.h"
                      8: #include "kbd.h"
1.16      art         9: #include "funmap.h"
1.1       deraadt    10:
                     11: #ifndef NO_MACRO
1.5       millert    12: #include "macro.h"
                     13: #endif /* !NO_MACRO */
1.1       deraadt    14:
                     15: #ifdef FKEYS
1.5       millert    16: #include "key.h"
1.1       deraadt    17: #ifndef        NO_STARTUP
                     18: #ifndef        BINDKEY
1.4       millert    19: #define        BINDKEY                 /* bindkey is used by FKEYS startup code */
1.5       millert    20: #endif /* !BINDKEY */
                     21: #endif /* !NO_STARTUP */
                     22: #endif /* FKEYS */
                     23:
                     24: static int      remap          __P((KEYMAP *, int, PF, KEYMAP *));
                     25: static KEYMAP  *realocmap      __P((KEYMAP *));
1.12      art        26: static void     fixmap         __P((KEYMAP *, KEYMAP *, KEYMAP *));
1.5       millert    27: static int      dobind         __P((KEYMAP *, char *, int));
                     28: static char    *skipwhite      __P((char *));
                     29: static char    *parsetoken     __P((char *));
                     30: static int      bindkey        __P((KEYMAP **, char *, KCHAR *, int));
1.1       deraadt    31:
1.15      mickey     32: /*
                     33:  * Insert a string, mainly for use from macros (created by selfinsert)
1.5       millert    34:  */
1.4       millert    35: /* ARGSUSED */
                     36: int
1.1       deraadt    37: insert(f, n)
1.4       millert    38:        int f, n;
1.1       deraadt    39: {
1.5       millert    40:        char    *cp;
                     41:        char     buf[128];
1.1       deraadt    42: #ifndef NO_MACRO
1.5       millert    43:        int      count, c;
1.1       deraadt    44:
1.4       millert    45:        if (inmacro) {
                     46:                while (--n >= 0) {
                     47:                        for (count = 0; count < maclcur->l_used; count++) {
                     48:                                if ((((c = maclcur->l_text[count]) == '\n')
                     49:                                    ? lnewline() : linsert(1, c)) != TRUE)
                     50:                                        return FALSE;
                     51:                        }
                     52:                }
                     53:                maclcur = maclcur->l_fp;
                     54:                return TRUE;
1.1       deraadt    55:        }
1.4       millert    56:        if (n == 1)
1.5       millert    57:                /* CFINS means selfinsert can tack on the end */
                     58:                thisflag |= CFINS;
                     59: #endif /* !NO_MACRO */
1.4       millert    60:        if (eread("Insert: ", buf, sizeof(buf), EFNEW) == FALSE)
1.1       deraadt    61:                return FALSE;
1.4       millert    62:        while (--n >= 0) {
                     63:                cp = buf;
                     64:                while (*cp) {
                     65:                        if (((*cp == '\n') ? lnewline() : linsert(1, *cp))
                     66:                            != TRUE)
                     67:                                return FALSE;
                     68:                        cp++;
                     69:                }
1.1       deraadt    70:        }
1.4       millert    71:        return TRUE;
1.1       deraadt    72: }
                     73:
                     74: /*
                     75:  * Bind a key to a function.  Cases range from the trivial (replacing an
                     76:  * existing binding) to the extremly complex (creating a new prefix in a
                     77:  * map_element that already has one, so the map_element must be split,
                     78:  * but the keymap doesn't have enough room for another map_element, so
                     79:  * the keymap is reallocated). No attempt is made to reclaim space no
                     80:  * longer used, if this is a problem flags must be added to indicate
                     81:  * malloced verses static storage in both keymaps and map_elements.
                     82:  * Structure assignments would come in real handy, but K&R based compilers
                     83:  * don't have them.  Care is taken so running out of memory will leave
                     84:  * the keymap in a usable state.
                     85:  */
1.4       millert    86: static int
                     87: remap(curmap, c, funct, pref_map)
1.15      mickey     88:        KEYMAP  *curmap;        /* pointer to the map being changed */
                     89:        int     c;              /* character being changed */
                     90:        PF      funct;          /* function being changed to */
                     91:        KEYMAP  *pref_map;      /* if funct==NULL, map to bind to or
1.4       millert    92:                                   NULL for new */
1.1       deraadt    93: {
1.5       millert    94:        int              i, n1, n2, nold;
                     95:        KEYMAP          *mp;
                     96:        PF              *pfp;
                     97:        MAP_ELEMENT     *mep;
1.4       millert    98:
                     99:        if (ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) {
1.7       art       100:                if (ele > &curmap->map_element[0] && (funct != NULL ||
1.5       millert   101:                    (ele - 1)->k_prefmap == NULL))
1.4       millert   102:                        n1 = c - (ele - 1)->k_num;
1.5       millert   103:                else
1.4       millert   104:                        n1 = HUGE;
                    105:                if (ele < &curmap->map_element[curmap->map_num] &&
1.7       art       106:                    (funct != NULL || ele->k_prefmap == NULL))
1.4       millert   107:                        n2 = ele->k_base - c;
1.5       millert   108:                else
1.4       millert   109:                        n2 = HUGE;
                    110:                if (n1 <= MAPELEDEF && n1 <= n2) {
                    111:                        ele--;
1.5       millert   112:                        if ((pfp = (PF *)malloc((c - ele->k_base + 1) *
1.4       millert   113:                            sizeof(PF))) == NULL) {
                    114:                                ewprintf("Out of memory");
                    115:                                return FALSE;
                    116:                        }
                    117:                        nold = ele->k_num - ele->k_base + 1;
                    118:                        for (i = 0; i < nold; i++)
                    119:                                pfp[i] = ele->k_funcp[i];
                    120:                        while (--n1)
                    121:                                pfp[i++] = curmap->map_default;
                    122:                        pfp[i] = funct;
                    123:                        ele->k_num = c;
                    124:                        ele->k_funcp = pfp;
                    125:                } else if (n2 <= MAPELEDEF) {
1.5       millert   126:                        if ((pfp = (PF *)malloc((ele->k_num - c + 1) *
                    127:                            sizeof(PF))) == NULL) {
1.4       millert   128:                                ewprintf("Out of memory");
                    129:                                return FALSE;
                    130:                        }
                    131:                        nold = ele->k_num - ele->k_base + 1;
                    132:                        for (i = 0; i < nold; i++)
                    133:                                pfp[i + n2] = ele->k_funcp[i];
                    134:                        while (--n2)
                    135:                                pfp[n2] = curmap->map_default;
                    136:                        pfp[0] = funct;
                    137:                        ele->k_base = c;
                    138:                        ele->k_funcp = pfp;
1.1       deraadt   139:                } else {
1.4       millert   140:                        if (curmap->map_num >= curmap->map_max &&
                    141:                            (curmap = realocmap(curmap)) == NULL)
                    142:                                return FALSE;
1.13      art       143:                        if ((pfp = malloc(sizeof(PF))) == NULL) {
1.4       millert   144:                                ewprintf("Out of memory");
                    145:                                return FALSE;
                    146:                        }
                    147:                        pfp[0] = funct;
                    148:                        for (mep = &curmap->map_element[curmap->map_num];
                    149:                            mep > ele; mep--) {
                    150:                                mep->k_base = (mep - 1)->k_base;
                    151:                                mep->k_num = (mep - 1)->k_num;
                    152:                                mep->k_funcp = (mep - 1)->k_funcp;
                    153:                                mep->k_prefmap = (mep - 1)->k_prefmap;
                    154:                        }
                    155:                        ele->k_base = c;
                    156:                        ele->k_num = c;
                    157:                        ele->k_funcp = pfp;
                    158:                        ele->k_prefmap = NULL;
                    159:                        curmap->map_num++;
                    160:                }
1.7       art       161:                if (funct == NULL) {
1.4       millert   162:                        if (pref_map != NULL) {
                    163:                                ele->k_prefmap = pref_map;
                    164:                        } else {
1.5       millert   165:                                if (!(mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
1.4       millert   166:                                    (MAPINIT - 1) * sizeof(MAP_ELEMENT)))) {
                    167:                                        ewprintf("Out of memory");
                    168:                                        ele->k_funcp[c - ele->k_base] =
                    169:                                            curmap->map_default;
                    170:                                        return FALSE;
                    171:                                }
                    172:                                mp->map_num = 0;
                    173:                                mp->map_max = MAPINIT;
                    174:                                mp->map_default = rescan;
                    175:                                ele->k_prefmap = mp;
                    176:                        }
1.1       deraadt   177:                }
                    178:        } else {
1.4       millert   179:                n1 = c - ele->k_base;
1.7       art       180:                if (ele->k_funcp[n1] == funct && (funct != NULL ||
1.4       millert   181:                    pref_map == NULL || pref_map == ele->k_prefmap))
1.5       millert   182:                        /* no change */
                    183:                        return TRUE;
1.7       art       184:                if (funct != NULL || ele->k_prefmap == NULL) {
                    185:                        if (ele->k_funcp[n1] == NULL)
1.13      art       186:                                ele->k_prefmap = NULL;
1.5       millert   187:                        /* easy case */
                    188:                        ele->k_funcp[n1] = funct;
1.7       art       189:                        if (funct == NULL) {
1.4       millert   190:                                if (pref_map != NULL)
                    191:                                        ele->k_prefmap = pref_map;
                    192:                                else {
                    193:                                        if (!(mp = malloc(sizeof(KEYMAP) +
1.15      mickey    194:                                            (MAPINIT - 1) *
1.5       millert   195:                                            sizeof(MAP_ELEMENT)))) {
1.4       millert   196:                                                ewprintf("Out of memory");
                    197:                                                ele->k_funcp[c - ele->k_base] =
                    198:                                                    curmap->map_default;
                    199:                                                return FALSE;
                    200:                                        }
                    201:                                        mp->map_num = 0;
                    202:                                        mp->map_max = MAPINIT;
                    203:                                        mp->map_default = rescan;
                    204:                                        ele->k_prefmap = mp;
                    205:                                }
                    206:                        }
                    207:                } else {
                    208:                        /*
1.5       millert   209:                         * This case is the splits.
                    210:                         * Determine which side of the break c goes on
1.4       millert   211:                         * 0 = after break; 1 = before break
                    212:                         */
                    213:                        n2 = 1;
                    214:                        for (i = 0; n2 && i < n1; i++)
1.7       art       215:                                n2 &= ele->k_funcp[i] != NULL;
1.4       millert   216:                        if (curmap->map_num >= curmap->map_max &&
                    217:                            (curmap = realocmap(curmap)) == NULL)
                    218:                                return FALSE;
1.15      mickey    219:                        if ((pfp = malloc((ele->k_num - c + !n2) *
1.5       millert   220:                            sizeof(PF))) == NULL) {
1.4       millert   221:                                ewprintf("Out of memory");
                    222:                                return FALSE;
                    223:                        }
1.7       art       224:                        ele->k_funcp[n1] = NULL;
1.4       millert   225:                        for (i = n1 + n2; i <= ele->k_num - ele->k_base; i++)
                    226:                                pfp[i - n1 - n2] = ele->k_funcp[i];
                    227:                        for (mep = &curmap->map_element[curmap->map_num];
                    228:                            mep > ele; mep--) {
                    229:                                mep->k_base = (mep - 1)->k_base;
                    230:                                mep->k_num = (mep - 1)->k_num;
                    231:                                mep->k_funcp = (mep - 1)->k_funcp;
                    232:                                mep->k_prefmap = (mep - 1)->k_prefmap;
                    233:                        }
                    234:                        ele->k_num = c - !n2;
                    235:                        (ele + 1)->k_base = c + n2;
                    236:                        (ele + 1)->k_funcp = pfp;
                    237:                        ele += !n2;
                    238:                        ele->k_prefmap = NULL;
                    239:                        curmap->map_num++;
                    240:                        if (pref_map == NULL) {
                    241:                                if ((mp = malloc(sizeof(KEYMAP) + (MAPINIT - 1)
                    242:                                    * sizeof(MAP_ELEMENT))) == NULL) {
                    243:                                        ewprintf("Out of memory");
                    244:                                        ele->k_funcp[c - ele->k_base] =
                    245:                                            curmap->map_default;
                    246:                                        return FALSE;
                    247:                                }
                    248:                                mp->map_num = 0;
                    249:                                mp->map_max = MAPINIT;
                    250:                                mp->map_default = rescan;
                    251:                                ele->k_prefmap = mp;
                    252:                        } else
                    253:                                ele->k_prefmap = pref_map;
                    254:                }
1.1       deraadt   255:        }
                    256:        return TRUE;
                    257: }
                    258:
1.4       millert   259: /*
                    260:  * Reallocate a keymap, used above.
                    261:  */
                    262: static KEYMAP *
                    263: realocmap(curmap)
1.5       millert   264:        KEYMAP *curmap;
1.4       millert   265: {
1.17    ! art       266:        MAPS *mps;
1.5       millert   267:        KEYMAP  *mp;
                    268:        int      i;
1.4       millert   269:
1.5       millert   270:        if ((mp = (KEYMAP *)malloc((unsigned)(sizeof(KEYMAP) +
1.15      mickey    271:            (curmap->map_max + (MAPGROW - 1)) *
1.5       millert   272:            sizeof(MAP_ELEMENT)))) == NULL) {
1.4       millert   273:                ewprintf("Out of memory");
                    274:                return NULL;
                    275:        }
                    276:        mp->map_num = curmap->map_num;
                    277:        mp->map_max = curmap->map_max + MAPGROW;
                    278:        mp->map_default = curmap->map_default;
                    279:        for (i = curmap->map_num; i--;) {
                    280:                mp->map_element[i].k_base = curmap->map_element[i].k_base;
                    281:                mp->map_element[i].k_num = curmap->map_element[i].k_num;
                    282:                mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp;
                    283:                mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap;
                    284:        }
1.17    ! art       285:        for (mps = maps; mps != NULL; mps = mps->p_next) {
        !           286:                if (mps->p_map == curmap)
        !           287:                        mps->p_map = mp;
1.4       millert   288:                else
1.17    ! art       289:                        fixmap(curmap, mp, mps->p_map);
1.4       millert   290:        }
                    291:        ele = &mp->map_element[ele - &curmap->map_element[0]];
                    292:        return mp;
                    293: }
                    294:
                    295: /*
                    296:  * Fix references to a reallocated keymap (recursive).
                    297:  */
1.12      art       298: static void
1.4       millert   299: fixmap(curmap, mp, mt)
                    300:        KEYMAP *mt;
                    301:        KEYMAP *curmap;
                    302:        KEYMAP *mp;
                    303: {
1.5       millert   304:        int      i;
1.4       millert   305:
                    306:        for (i = mt->map_num; i--;) {
                    307:                if (mt->map_element[i].k_prefmap != NULL) {
                    308:                        if (mt->map_element[i].k_prefmap == curmap)
                    309:                                mt->map_element[i].k_prefmap = mp;
                    310:                        else
                    311:                                fixmap(curmap, mp, mt->map_element[i].k_prefmap);
                    312:                }
1.1       deraadt   313:        }
                    314: }
                    315:
                    316: /*
                    317:  * do the input for local-set-key, global-set-key  and define-key
                    318:  * then call remap to do the work.
                    319:  */
1.4       millert   320: static int
                    321: dobind(curmap, p, unbind)
1.15      mickey    322:        KEYMAP  *curmap;
                    323:        char    *p;
                    324:        int     unbind;
1.4       millert   325: {
1.5       millert   326:        KEYMAP  *pref_map = NULL;
                    327:        PF       funct;
                    328:        char     prompt[80];
                    329:        char    *pep;
                    330:        int      c, s;
1.1       deraadt   331:
                    332: #ifndef NO_MACRO
1.4       millert   333:        if (macrodef) {
                    334:                /*
                    335:                 * Keystrokes aren't collected. Not hard, but pretty useless.
                    336:                 * Would not work for function keys in any case.
                    337:                 */
                    338:                ewprintf("Can't rebind key in macro");
                    339:                return FALSE;
1.1       deraadt   340:        }
                    341: #ifndef NO_STARTUP
1.4       millert   342:        if (inmacro) {
                    343:                for (s = 0; s < maclcur->l_used - 1; s++) {
1.8       art       344:                        if (doscan(curmap, c = CHARMASK(maclcur->l_text[s]), &curmap)
1.7       art       345:                            != NULL) {
1.13      art       346:                                if (remap(curmap, c, NULL, NULL)
1.4       millert   347:                                    != TRUE)
                    348:                                        return FALSE;
                    349:                        }
1.1       deraadt   350:                }
1.12      art       351:                (void)doscan(curmap, c = maclcur->l_text[s], NULL);
1.4       millert   352:                maclcur = maclcur->l_fp;
1.1       deraadt   353:        } else {
1.5       millert   354: #endif /* !NO_STARTUP */
                    355: #endif /* !NO_MACRO */
1.14      mickey    356:                pep = prompt + strlcpy(prompt, p, sizeof(prompt));
1.4       millert   357:                for (;;) {
                    358:                        ewprintf("%s", prompt);
                    359:                        pep[-1] = ' ';
1.14      mickey    360:                        pep = keyname(pep, sizeof(prompt) - (pep - prompt),
                    361:                            c = getkey(FALSE));
1.8       art       362:                        if (doscan(curmap, c, &curmap) != NULL)
1.4       millert   363:                                break;
                    364:                        *pep++ = '-';
                    365:                        *pep = '\0';
                    366:                }
1.1       deraadt   367: #ifndef NO_STARTUP
                    368:        }
1.5       millert   369: #endif /* !NO_STARTUP */
1.4       millert   370:        if (unbind)
                    371:                funct = rescan;
1.1       deraadt   372:        else {
1.4       millert   373:                if ((s = eread("%s to command: ", prompt, 80, EFFUNC | EFNEW,
                    374:                    prompt)) != TRUE)
                    375:                        return s;
1.7       art       376:                if (((funct = name_function(prompt)) == NULL) ?
1.4       millert   377:                    (pref_map = name_map(prompt)) == NULL : funct == NULL) {
                    378:                        ewprintf("[No match]");
                    379:                        return FALSE;
                    380:                }
1.1       deraadt   381:        }
                    382:        return remap(curmap, c, funct, pref_map);
                    383: }
                    384:
                    385: /*
1.15      mickey    386:  * bindkey: bind key sequence to a function in the specified map.  Used by
                    387:  * excline so it can bind function keys.  To close to release to change
                    388:  * calling sequence, should just pass KEYMAP *curmap rather than
1.5       millert   389:  * KEYMAP **mapp.
                    390:  */
1.1       deraadt   391: #ifdef BINDKEY
1.5       millert   392: static int
1.1       deraadt   393: bindkey(mapp, fname, keys, kcount)
1.15      mickey    394:        KEYMAP  **mapp;
                    395:        char    *fname;
                    396:        KCHAR   *keys;
                    397:        int     kcount;
1.5       millert   398: {
                    399:        KEYMAP  *curmap = *mapp;
                    400:        KEYMAP  *pref_map = NULL;
                    401:        PF       funct;
                    402:        int      c;
1.1       deraadt   403:
1.4       millert   404:        if (fname == NULL)
                    405:                funct = rescan;
1.7       art       406:        else if (((funct = name_function(fname)) == NULL) ?
1.5       millert   407:            (pref_map = name_map(fname)) == NULL : funct == NULL) {
1.4       millert   408:                ewprintf("[No match: %s]", fname);
                    409:                return FALSE;
                    410:        }
                    411:        while (--kcount) {
1.8       art       412:                if (doscan(curmap, c = *keys++, &curmap) != NULL) {
1.13      art       413:                        if (remap(curmap, c, NULL, NULL) != TRUE)
1.4       millert   414:                                return FALSE;
1.9       art       415:                        /*
                    416:                         * XXX - Bizzarreness. remap creates an empty KEYMAP
                    417:                         *       that the last key is supposed to point to.
                    418:                         */
                    419:                        curmap = ele->k_prefmap;
1.4       millert   420:                }
1.1       deraadt   421:        }
1.12      art       422:        (void)doscan(curmap, c = *keys, NULL);
1.1       deraadt   423:        return remap(curmap, c, funct, pref_map);
                    424: }
1.3       millert   425:
                    426: #ifdef FKEYS
                    427: /*
                    428:  * Wrapper for bindkey() that converts escapes.
                    429:  */
                    430: int
                    431: dobindkey(map, func, str)
                    432:        KEYMAP *map;
1.4       millert   433:        char   *func;
                    434:        char   *str;
1.3       millert   435: {
1.5       millert   436:        int      i;
1.3       millert   437:
                    438:        for (i = 0; *str && i < MAXKEY; i++) {
                    439:                /* XXX - convert numbers w/ strol()? */
                    440:                if (*str != '\\')
                    441:                        key.k_chars[i] = *str;
                    442:                else {
1.4       millert   443:                        switch (*++str) {
                    444:                        case 't':
                    445:                        case 'T':
1.3       millert   446:                                key.k_chars[i] = '\t';
                    447:                                break;
1.4       millert   448:                        case 'n':
                    449:                        case 'N':
1.3       millert   450:                                key.k_chars[i] = '\n';
                    451:                                break;
1.4       millert   452:                        case 'r':
                    453:                        case 'R':
1.3       millert   454:                                key.k_chars[i] = '\r';
                    455:                                break;
1.4       millert   456:                        case 'e':
                    457:                        case 'E':
1.3       millert   458:                                key.k_chars[i] = CCHR('[');
                    459:                                break;
                    460:                        }
                    461:                }
                    462:                str++;
                    463:        }
                    464:        key.k_count = i;
1.4       millert   465:        return (bindkey(&map, func, key.k_chars, key.k_count));
1.3       millert   466: }
1.5       millert   467: #endif /* FKEYS */
                    468: #endif /* BINDKEY */
1.1       deraadt   469:
                    470: /*
                    471:  * This function modifies the fundamental keyboard map.
                    472:  */
1.4       millert   473: /* ARGSUSED */
                    474: int
1.1       deraadt   475: bindtokey(f, n)
1.4       millert   476:        int f, n;
1.1       deraadt   477: {
1.11      art       478:        return dobind(fundamental_map, "Global set key: ", FALSE);
1.1       deraadt   479: }
                    480:
                    481: /*
                    482:  * This function modifies the current mode's keyboard map.
                    483:  */
1.4       millert   484: /* ARGSUSED */
                    485: int
1.1       deraadt   486: localbind(f, n)
1.4       millert   487:        int f, n;
1.1       deraadt   488: {
1.15      mickey    489:        return dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
1.5       millert   490:            "Local set key: ", FALSE);
1.1       deraadt   491: }
                    492:
                    493: /*
                    494:  * This function redefines a key in any keymap.
                    495:  */
1.4       millert   496: /* ARGSUSED */
                    497: int
1.1       deraadt   498: define_key(f, n)
1.4       millert   499:        int f, n;
1.1       deraadt   500: {
1.5       millert   501:        static char      buf[48] = "Define key map: ";
1.10      art       502:        KEYMAP          *mp;
1.4       millert   503:
                    504:        buf[16] = '\0';
                    505:        if (eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE)
                    506:                return FALSE;
1.10      art       507:        if ((mp = name_map(&buf[16])) == NULL) {
1.4       millert   508:                ewprintf("Unknown map %s", &buf[16]);
                    509:                return FALSE;
                    510:        }
1.12      art       511:        (void)strncat(&buf[16], " key: ", 48 - 16 - 1);
1.10      art       512:        return dobind(mp, buf, FALSE);
1.1       deraadt   513: }
                    514:
1.4       millert   515: int
1.1       deraadt   516: unbindtokey(f, n)
1.4       millert   517:        int f, n;
1.1       deraadt   518: {
1.11      art       519:        return dobind(fundamental_map, "Global unset key: ", TRUE);
1.1       deraadt   520: }
                    521:
1.4       millert   522: int
1.1       deraadt   523: localunbind(f, n)
1.4       millert   524:        int f, n;
1.1       deraadt   525: {
1.4       millert   526:        return dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
                    527:            "Local unset key: ", TRUE);
1.1       deraadt   528: }
                    529:
                    530: /*
1.15      mickey    531:  * Extended command. Call the message line routine to read in the command
                    532:  * name and apply autocompletion to it. When it comes back, look the name
                    533:  * up in the symbol table and run the command if it is found.  Print an
1.5       millert   534:  * error if there is anything wrong.
1.1       deraadt   535:  */
1.4       millert   536: int
1.1       deraadt   537: extend(f, n)
1.5       millert   538:        int f, n;
1.1       deraadt   539: {
1.5       millert   540:        PF       funct;
                    541:        int      s;
                    542:        char     xname[NXNAME];
1.4       millert   543:
                    544:        if (!(f & FFARG))
                    545:                s = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC);
                    546:        else
                    547:                s = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n);
                    548:        if (s != TRUE)
                    549:                return s;
                    550:        if ((funct = name_function(xname)) != NULL) {
1.1       deraadt   551: #ifndef NO_MACRO
1.4       millert   552:                if (macrodef) {
1.5       millert   553:                        LINE    *lp = maclcur;
1.4       millert   554:                        macro[macrocount - 1].m_funct = funct;
                    555:                        maclcur = lp->l_bp;
                    556:                        maclcur->l_fp = lp->l_fp;
1.5       millert   557:                        free((char *)lp);
1.4       millert   558:                }
1.5       millert   559: #endif /* !NO_MACRO */
                    560:                return (*funct)(f, n);
1.1       deraadt   561:        }
                    562:        ewprintf("[No match]");
                    563:        return FALSE;
                    564: }
                    565:
                    566: #ifndef NO_STARTUP
                    567: /*
                    568:  * Define the commands needed to do startup-file processing.
                    569:  * This code is mostly a kludge just so we can get startup-file processing.
                    570:  *
                    571:  * If you're serious about having this code, you should rewrite it.
                    572:  * To wit:
                    573:  *     It has lots of funny things in it to make the startup-file look
                    574:  *     like a GNU startup file; mostly dealing with parens and semicolons.
                    575:  *     This should all vanish.
                    576:  *
                    577:  * We define eval-expression because it's easy.         It can make
                    578:  * *-set-key or define-key set an arbitrary key sequence, so it isn't
                    579:  * useless.
                    580:  */
                    581:
                    582: /*
                    583:  * evalexpr - get one line from the user, and run it.
                    584:  */
1.4       millert   585: /* ARGSUSED */
                    586: int
1.1       deraadt   587: evalexpr(f, n)
1.5       millert   588:        int f, n;
1.1       deraadt   589: {
1.5       millert   590:        int      s;
                    591:        char     exbuf[128];
1.1       deraadt   592:
                    593:        if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
                    594:                return s;
                    595:        return excline(exbuf);
                    596: }
1.4       millert   597:
1.1       deraadt   598: /*
1.15      mickey    599:  * evalbuffer - evaluate the current buffer as line commands. Useful for
1.5       millert   600:  * testing startup files.
1.1       deraadt   601:  */
1.4       millert   602: /* ARGSUSED */
                    603: int
1.1       deraadt   604: evalbuffer(f, n)
1.5       millert   605:        int f, n;
1.1       deraadt   606: {
1.5       millert   607:        LINE            *lp;
                    608:        BUFFER          *bp = curbp;
                    609:        int              s;
                    610:        static char      excbuf[128];
1.1       deraadt   611:
                    612:        for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
1.4       millert   613:                if (llength(lp) >= 128)
                    614:                        return FALSE;
1.12      art       615:                (void)strncpy(excbuf, ltext(lp), llength(lp));
1.5       millert   616:
                    617:                /* make sure it's terminated */
                    618:                excbuf[llength(lp)] = '\0';
1.4       millert   619:                if ((s = excline(excbuf)) != TRUE)
                    620:                        return s;
1.1       deraadt   621:        }
                    622:        return TRUE;
                    623: }
1.4       millert   624:
1.1       deraadt   625: /*
                    626:  * evalfile - go get a file and evaluate it as line commands. You can
                    627:  *     go get your own startup file if need be.
                    628:  */
1.4       millert   629: /* ARGSUSED */
                    630: int
1.1       deraadt   631: evalfile(f, n)
1.5       millert   632:        int f, n;
1.1       deraadt   633: {
1.5       millert   634:        int      s;
                    635:        char     fname[NFILEN];
1.1       deraadt   636:
                    637:        if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
                    638:                return s;
                    639:        return load(fname);
                    640: }
                    641:
                    642: /*
                    643:  * load - go load the file name we got passed.
                    644:  */
1.4       millert   645: int
                    646: load(fname)
1.5       millert   647:        char *fname;
1.4       millert   648: {
1.5       millert   649:        int      s = TRUE;
                    650:        int      nbytes;
                    651:        char     excbuf[128];
1.1       deraadt   652:
                    653:        if ((fname = adjustname(fname)) == NULL)
1.5       millert   654:                /* just to be careful */
                    655:                return FALSE;
1.1       deraadt   656:
1.13      art       657:        if (ffropen(fname, NULL) != FIOSUC)
1.4       millert   658:                return FALSE;
1.5       millert   659:
1.4       millert   660:        while ((s = ffgetline(excbuf, sizeof(excbuf) - 1, &nbytes)) == FIOSUC) {
1.1       deraadt   661:                excbuf[nbytes] = '\0';
                    662:                if (excline(excbuf) != TRUE) {
                    663:                        s = FIOERR;
                    664:                        ewprintf("Error loading file %s", fname);
                    665:                        break;
                    666:                }
                    667:        }
1.13      art       668:        (void)ffclose(NULL);
1.1       deraadt   669:        excbuf[nbytes] = '\0';
1.4       millert   670:        if (s != FIOEOF || (nbytes && excline(excbuf) != TRUE))
1.1       deraadt   671:                return FALSE;
                    672:        return TRUE;
                    673: }
                    674:
                    675: /*
1.15      mickey    676:  * excline - run a line from a load file or eval-expression.  if FKEYS is
                    677:  * defined, duplicate functionallity of dobind so function key values don't
1.5       millert   678:  * have to fit in type char.
1.1       deraadt   679:  */
1.4       millert   680: int
1.1       deraadt   681: excline(line)
1.5       millert   682:        char *line;
1.1       deraadt   683: {
1.5       millert   684:        PF       fp;
                    685:        LINE    *lp, *np;
                    686:        int      status, c, f, n;
                    687:        char    *funcp;
                    688:        char    *argp = NULL;
                    689: #ifdef FKEYS
                    690:        int      bind;
                    691:        KEYMAP  *curmap;
                    692: #define BINDARG                0  /* this arg is key to bind (local/global set key) */
                    693: #define        BINDNO          1  /* not binding or non-quoted BINDARG */
                    694: #define BINDNEXT       2  /* next arg " (define-key) */
                    695: #define BINDDO         3  /* already found key to bind */
                    696: #define BINDEXT                1  /* space for trailing \0 */
                    697: #else /* FKEYS */
                    698: #define BINDEXT                0
                    699: #endif /* FKEYS */
                    700:
                    701:        lp = NULL;
1.1       deraadt   702:
1.4       millert   703:        if (macrodef || inmacro) {
1.1       deraadt   704:                ewprintf("Not now!");
                    705:                return FALSE;
                    706:        }
                    707:        f = 0;
                    708:        n = 1;
                    709:        funcp = skipwhite(line);
1.4       millert   710:        if (*funcp == '\0')
                    711:                return TRUE;    /* No error on blank lines */
1.1       deraadt   712:        line = parsetoken(funcp);
                    713:        if (*line != '\0') {
                    714:                *line++ = '\0';
                    715:                line = skipwhite(line);
                    716:                if ((*line >= '0' && *line <= '9') || *line == '-') {
                    717:                        argp = line;
                    718:                        line = parsetoken(line);
                    719:                }
                    720:        }
                    721:        if (argp != NULL) {
                    722:                f = FFARG;
                    723:                n = atoi(argp);
                    724:        }
1.4       millert   725:        if ((fp = name_function(funcp)) == NULL) {
                    726:                ewprintf("Unknown function: %s", funcp);
                    727:                return FALSE;
1.1       deraadt   728:        }
                    729: #ifdef FKEYS
1.4       millert   730:        if (fp == bindtokey || fp == unbindtokey) {
1.1       deraadt   731:                bind = BINDARG;
1.11      art       732:                curmap = fundamental_map;
1.4       millert   733:        } else if (fp == localbind || fp == localunbind) {
1.1       deraadt   734:                bind = BINDARG;
                    735:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.4       millert   736:        } else if (fp == define_key)
                    737:                bind = BINDNEXT;
                    738:        else
                    739:                bind = BINDNO;
1.5       millert   740: #endif /* FKEYS */
                    741:        /* Pack away all the args now... */
1.4       millert   742:        if ((np = lalloc(0)) == FALSE)
                    743:                return FALSE;
1.1       deraadt   744:        np->l_fp = np->l_bp = maclcur = np;
                    745:        while (*line != '\0') {
                    746:                argp = skipwhite(line);
1.4       millert   747:                if (*argp == '\0')
                    748:                        break;
1.1       deraadt   749:                line = parsetoken(argp);
                    750:                if (*argp != '"') {
1.4       millert   751:                        if (*argp == '\'')
                    752:                                ++argp;
                    753:                        if (!(lp = lalloc((int) (line - argp) + BINDEXT))) {
                    754:                                status = FALSE;
                    755:                                goto cleanup;
                    756:                        }
1.5       millert   757:                        bcopy(argp, ltext(lp), (int)(line - argp));
1.1       deraadt   758: #ifdef FKEYS
1.5       millert   759:                        /* don't count BINDEXT */
                    760:                        lp->l_used--;
1.4       millert   761:                        if (bind == BINDARG)
                    762:                                bind = BINDNO;
1.5       millert   763: #endif /* FKEYS */
                    764:                } else {
                    765:                        /* quoted strings are special */
1.4       millert   766:                        ++argp;
1.1       deraadt   767: #ifdef FKEYS
1.4       millert   768:                        if (bind != BINDARG) {
1.5       millert   769: #endif /* FKEYS */
                    770:                                lp = lalloc((int)(line - argp) + BINDEXT);
1.4       millert   771:                                if (lp == NULL) {
                    772:                                        status = FALSE;
                    773:                                        goto cleanup;
                    774:                                }
                    775:                                lp->l_used = 0;
1.1       deraadt   776: #ifdef FKEYS
1.4       millert   777:                        } else {
                    778:                                key.k_count = 0;
1.1       deraadt   779:                        }
1.5       millert   780: #endif /* FKEYS */
1.4       millert   781:                        while (*argp != '"' && *argp != '\0') {
                    782:                                if (*argp != '\\')
                    783:                                        c = *argp++;
                    784:                                else {
                    785:                                        switch (*++argp) {
                    786:                                        case 't':
                    787:                                        case 'T':
                    788:                                                c = CCHR('I');
                    789:                                                break;
                    790:                                        case 'n':
                    791:                                        case 'N':
                    792:                                                c = CCHR('J');
                    793:                                                break;
                    794:                                        case 'r':
                    795:                                        case 'R':
                    796:                                                c = CCHR('M');
                    797:                                                break;
                    798:                                        case 'e':
                    799:                                        case 'E':
                    800:                                                c = CCHR('[');
                    801:                                                break;
                    802:                                        case '^':
                    803:                                                /*
                    804:                                                 * split into two statements
                    805:                                                 * due to bug in OSK cpp
                    806:                                                 */
                    807:                                                c = CHARMASK(*++argp);
                    808:                                                c = ISLOWER(c) ?
                    809:                                                    CCHR(TOUPPER(c)) : CCHR(c);
                    810:                                                break;
                    811:                                        case '0':
                    812:                                        case '1':
                    813:                                        case '2':
                    814:                                        case '3':
                    815:                                        case '4':
                    816:                                        case '5':
                    817:                                        case '6':
                    818:                                        case '7':
                    819:                                                c = *argp - '0';
1.15      mickey    820:                                                if (argp[1] <= '7' &&
1.5       millert   821:                                                    argp[1] >= '0') {
1.4       millert   822:                                                        c <<= 3;
                    823:                                                        c += *++argp - '0';
                    824:                                                        if (argp[1] <= '7' &&
                    825:                                                            argp[1] >= '0') {
                    826:                                                                c <<= 3;
                    827:                                                                c += *++argp
                    828:                                                                    - '0';
                    829:                                                        }
                    830:                                                }
                    831:                                                break;
                    832: #ifdef FKEYS
                    833:                                        case 'f':
                    834:                                        case 'F':
                    835:                                                c = *++argp - '0';
                    836:                                                if (ISDIGIT(argp[1])) {
                    837:                                                        c *= 10;
                    838:                                                        c += *++argp - '0';
                    839:                                                }
                    840:                                                c += KFIRST;
                    841:                                                break;
1.5       millert   842: #endif /* FKEYS */
1.4       millert   843:                                        default:
                    844:                                                c = CHARMASK(*argp);
                    845:                                                break;
                    846:                                        }
                    847:                                        argp++;
                    848:                                }
1.1       deraadt   849: #ifdef FKEYS
1.4       millert   850:                                if (bind == BINDARG)
                    851:                                        key.k_chars[key.k_count++] = c;
                    852:                                else
1.5       millert   853: #endif /* FKEYS */
1.4       millert   854:                                        lp->l_text[lp->l_used++] = c;
                    855:                        }
                    856:                        if (*line)
                    857:                                line++;
1.1       deraadt   858:                }
                    859: #ifdef FKEYS
1.4       millert   860:                switch (bind) {
                    861:                case BINDARG:
1.1       deraadt   862:                        bind = BINDDO;
                    863:                        break;
1.4       millert   864:                case BINDNEXT:
1.1       deraadt   865:                        lp->l_text[lp->l_used] = '\0';
1.10      art       866:                        if ((curmap = name_map(lp->l_text)) == NULL) {
1.4       millert   867:                                ewprintf("No such mode: %s", lp->l_text);
                    868:                                status = FALSE;
1.5       millert   869:                                free((char *)lp);
1.4       millert   870:                                goto cleanup;
1.1       deraadt   871:                        }
1.5       millert   872:                        free((char *)lp);
1.1       deraadt   873:                        bind = BINDARG;
                    874:                        break;
1.4       millert   875:                default:
1.5       millert   876: #endif /* FKEYS */
1.1       deraadt   877:                        lp->l_fp = np->l_fp;
                    878:                        lp->l_bp = np;
                    879:                        np->l_fp = lp;
                    880:                        np = lp;
                    881: #ifdef FKEYS
                    882:                }
1.5       millert   883: #endif /* FKEYS */
1.1       deraadt   884:        }
                    885: #ifdef FKEYS
1.4       millert   886:        switch (bind) {
                    887:        default:
1.1       deraadt   888:                ewprintf("Bad args to set key");
                    889:                status = FALSE;
                    890:                break;
1.4       millert   891:        case BINDDO:
                    892:                if (fp != unbindtokey && fp != localunbind) {
                    893:                        lp->l_text[lp->l_used] = '\0';
                    894:                        status = bindkey(&curmap, lp->l_text, key.k_chars,
                    895:                            key.k_count);
1.13      art       896:                } else {
                    897:                        status = bindkey(&curmap, NULL, key.k_chars,
1.4       millert   898:                            key.k_count);
1.13      art       899:                }
1.1       deraadt   900:                break;
1.4       millert   901:        case BINDNO:
1.5       millert   902: #endif /* FKEYS */
1.1       deraadt   903:                inmacro = TRUE;
                    904:                maclcur = maclcur->l_fp;
1.5       millert   905:                status = (*fp)(f, n);
1.1       deraadt   906:                inmacro = FALSE;
                    907: #ifdef FKEYS
                    908:        }
1.5       millert   909: #endif /* FKEYS */
1.1       deraadt   910: cleanup:
                    911:        lp = maclcur->l_fp;
1.4       millert   912:        while (lp != maclcur) {
                    913:                np = lp->l_fp;
1.5       millert   914:                free((char *)lp);
1.4       millert   915:                lp = np;
1.1       deraadt   916:        }
1.5       millert   917:        free((char *)lp);
1.1       deraadt   918:        return status;
                    919: }
                    920:
                    921: /*
                    922:  * a pair of utility functions for the above
                    923:  */
                    924: static char *
                    925: skipwhite(s)
1.5       millert   926:        char *s;
1.1       deraadt   927: {
1.4       millert   928:        while (*s == ' ' || *s == '\t' || *s == ')' || *s == '(')
                    929:                s++;
                    930:        if (*s == ';')
                    931:                *s = '\0';
1.1       deraadt   932:        return s;
                    933: }
                    934:
                    935: static char *
                    936: parsetoken(s)
1.4       millert   937:        char  *s;
1.1       deraadt   938: {
                    939:        if (*s != '"') {
1.4       millert   940:                while (*s && *s != ' ' && *s != '\t' && *s != ')' && *s != '(')
                    941:                        s++;
                    942:                if (*s == ';')
                    943:                        *s = '\0';
1.1       deraadt   944:        } else
1.5       millert   945:                do {
1.15      mickey    946:                        /*
                    947:                         * Strings get special treatment.
                    948:                         * Beware: You can \ out the end of the string!
1.5       millert   949:                         */
1.4       millert   950:                        if (*s == '\\')
                    951:                                ++s;
                    952:                } while (*++s != '"' && *s != '\0');
1.1       deraadt   953:        return s;
                    954: }
1.5       millert   955: #endif /* !NO_STARTUP */