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

1.19    ! vincent     1: /*     $OpenBSD: extend.c,v 1.18 2001/07/05 17:36:05 matthieu 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.19    ! vincent   498: define_key(int f, int n)
1.1       deraadt   499: {
1.19    ! vincent   500:        static char buf[48];
        !           501:        char tmp[32];
        !           502:        KEYMAP *mp;
1.4       millert   503:
1.19    ! vincent   504:        strlcpy(buf, "Define key map: ", sizeof buf);
        !           505:        if (eread(buf, tmp, sizeof tmp, EFNEW) != TRUE)
1.4       millert   506:                return FALSE;
1.19    ! vincent   507:        strlcat(buf, tmp, sizeof buf);
        !           508:        if ((mp = name_map(tmp)) == NULL) {
        !           509:                ewprintf("Unknown map %s", tmp);
1.4       millert   510:                return FALSE;
                    511:        }
1.19    ! vincent   512:        strlcat(buf, "key: ", sizeof buf);
        !           513:
1.10      art       514:        return dobind(mp, buf, FALSE);
1.1       deraadt   515: }
                    516:
1.4       millert   517: int
1.1       deraadt   518: unbindtokey(f, n)
1.4       millert   519:        int f, n;
1.1       deraadt   520: {
1.11      art       521:        return dobind(fundamental_map, "Global unset key: ", TRUE);
1.1       deraadt   522: }
                    523:
1.4       millert   524: int
1.1       deraadt   525: localunbind(f, n)
1.4       millert   526:        int f, n;
1.1       deraadt   527: {
1.4       millert   528:        return dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
                    529:            "Local unset key: ", TRUE);
1.1       deraadt   530: }
                    531:
                    532: /*
1.15      mickey    533:  * Extended command. Call the message line routine to read in the command
                    534:  * name and apply autocompletion to it. When it comes back, look the name
                    535:  * up in the symbol table and run the command if it is found.  Print an
1.5       millert   536:  * error if there is anything wrong.
1.1       deraadt   537:  */
1.4       millert   538: int
1.1       deraadt   539: extend(f, n)
1.5       millert   540:        int f, n;
1.1       deraadt   541: {
1.5       millert   542:        PF       funct;
                    543:        int      s;
                    544:        char     xname[NXNAME];
1.4       millert   545:
                    546:        if (!(f & FFARG))
                    547:                s = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC);
                    548:        else
                    549:                s = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n);
                    550:        if (s != TRUE)
                    551:                return s;
                    552:        if ((funct = name_function(xname)) != NULL) {
1.1       deraadt   553: #ifndef NO_MACRO
1.4       millert   554:                if (macrodef) {
1.5       millert   555:                        LINE    *lp = maclcur;
1.4       millert   556:                        macro[macrocount - 1].m_funct = funct;
                    557:                        maclcur = lp->l_bp;
                    558:                        maclcur->l_fp = lp->l_fp;
1.5       millert   559:                        free((char *)lp);
1.4       millert   560:                }
1.5       millert   561: #endif /* !NO_MACRO */
                    562:                return (*funct)(f, n);
1.1       deraadt   563:        }
                    564:        ewprintf("[No match]");
                    565:        return FALSE;
                    566: }
                    567:
                    568: #ifndef NO_STARTUP
                    569: /*
                    570:  * Define the commands needed to do startup-file processing.
                    571:  * This code is mostly a kludge just so we can get startup-file processing.
                    572:  *
                    573:  * If you're serious about having this code, you should rewrite it.
                    574:  * To wit:
                    575:  *     It has lots of funny things in it to make the startup-file look
                    576:  *     like a GNU startup file; mostly dealing with parens and semicolons.
                    577:  *     This should all vanish.
                    578:  *
                    579:  * We define eval-expression because it's easy.         It can make
                    580:  * *-set-key or define-key set an arbitrary key sequence, so it isn't
                    581:  * useless.
                    582:  */
                    583:
                    584: /*
                    585:  * evalexpr - get one line from the user, and run it.
                    586:  */
1.4       millert   587: /* ARGSUSED */
                    588: int
1.1       deraadt   589: evalexpr(f, n)
1.5       millert   590:        int f, n;
1.1       deraadt   591: {
1.5       millert   592:        int      s;
                    593:        char     exbuf[128];
1.1       deraadt   594:
                    595:        if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
                    596:                return s;
                    597:        return excline(exbuf);
                    598: }
1.4       millert   599:
1.1       deraadt   600: /*
1.15      mickey    601:  * evalbuffer - evaluate the current buffer as line commands. Useful for
1.5       millert   602:  * testing startup files.
1.1       deraadt   603:  */
1.4       millert   604: /* ARGSUSED */
                    605: int
1.1       deraadt   606: evalbuffer(f, n)
1.5       millert   607:        int f, n;
1.1       deraadt   608: {
1.5       millert   609:        LINE            *lp;
                    610:        BUFFER          *bp = curbp;
                    611:        int              s;
                    612:        static char      excbuf[128];
1.1       deraadt   613:
                    614:        for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
1.4       millert   615:                if (llength(lp) >= 128)
                    616:                        return FALSE;
1.12      art       617:                (void)strncpy(excbuf, ltext(lp), llength(lp));
1.5       millert   618:
                    619:                /* make sure it's terminated */
                    620:                excbuf[llength(lp)] = '\0';
1.4       millert   621:                if ((s = excline(excbuf)) != TRUE)
                    622:                        return s;
1.1       deraadt   623:        }
                    624:        return TRUE;
                    625: }
1.4       millert   626:
1.1       deraadt   627: /*
                    628:  * evalfile - go get a file and evaluate it as line commands. You can
                    629:  *     go get your own startup file if need be.
                    630:  */
1.4       millert   631: /* ARGSUSED */
                    632: int
1.1       deraadt   633: evalfile(f, n)
1.5       millert   634:        int f, n;
1.1       deraadt   635: {
1.5       millert   636:        int      s;
                    637:        char     fname[NFILEN];
1.1       deraadt   638:
                    639:        if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
                    640:                return s;
                    641:        return load(fname);
                    642: }
                    643:
                    644: /*
                    645:  * load - go load the file name we got passed.
                    646:  */
1.4       millert   647: int
                    648: load(fname)
1.5       millert   649:        char *fname;
1.4       millert   650: {
1.5       millert   651:        int      s = TRUE;
1.18      matthieu  652:        int      nbytes = 0;
1.5       millert   653:        char     excbuf[128];
1.1       deraadt   654:
                    655:        if ((fname = adjustname(fname)) == NULL)
1.5       millert   656:                /* just to be careful */
                    657:                return FALSE;
1.1       deraadt   658:
1.13      art       659:        if (ffropen(fname, NULL) != FIOSUC)
1.4       millert   660:                return FALSE;
1.5       millert   661:
1.4       millert   662:        while ((s = ffgetline(excbuf, sizeof(excbuf) - 1, &nbytes)) == FIOSUC) {
1.1       deraadt   663:                excbuf[nbytes] = '\0';
                    664:                if (excline(excbuf) != TRUE) {
                    665:                        s = FIOERR;
                    666:                        ewprintf("Error loading file %s", fname);
                    667:                        break;
                    668:                }
                    669:        }
1.13      art       670:        (void)ffclose(NULL);
1.1       deraadt   671:        excbuf[nbytes] = '\0';
1.4       millert   672:        if (s != FIOEOF || (nbytes && excline(excbuf) != TRUE))
1.1       deraadt   673:                return FALSE;
                    674:        return TRUE;
                    675: }
                    676:
                    677: /*
1.15      mickey    678:  * excline - run a line from a load file or eval-expression.  if FKEYS is
                    679:  * defined, duplicate functionallity of dobind so function key values don't
1.5       millert   680:  * have to fit in type char.
1.1       deraadt   681:  */
1.4       millert   682: int
1.1       deraadt   683: excline(line)
1.5       millert   684:        char *line;
1.1       deraadt   685: {
1.5       millert   686:        PF       fp;
                    687:        LINE    *lp, *np;
                    688:        int      status, c, f, n;
                    689:        char    *funcp;
                    690:        char    *argp = NULL;
                    691: #ifdef FKEYS
                    692:        int      bind;
                    693:        KEYMAP  *curmap;
                    694: #define BINDARG                0  /* this arg is key to bind (local/global set key) */
                    695: #define        BINDNO          1  /* not binding or non-quoted BINDARG */
                    696: #define BINDNEXT       2  /* next arg " (define-key) */
                    697: #define BINDDO         3  /* already found key to bind */
                    698: #define BINDEXT                1  /* space for trailing \0 */
                    699: #else /* FKEYS */
                    700: #define BINDEXT                0
                    701: #endif /* FKEYS */
                    702:
                    703:        lp = NULL;
1.1       deraadt   704:
1.4       millert   705:        if (macrodef || inmacro) {
1.1       deraadt   706:                ewprintf("Not now!");
                    707:                return FALSE;
                    708:        }
                    709:        f = 0;
                    710:        n = 1;
                    711:        funcp = skipwhite(line);
1.4       millert   712:        if (*funcp == '\0')
                    713:                return TRUE;    /* No error on blank lines */
1.1       deraadt   714:        line = parsetoken(funcp);
                    715:        if (*line != '\0') {
                    716:                *line++ = '\0';
                    717:                line = skipwhite(line);
                    718:                if ((*line >= '0' && *line <= '9') || *line == '-') {
                    719:                        argp = line;
                    720:                        line = parsetoken(line);
                    721:                }
                    722:        }
                    723:        if (argp != NULL) {
                    724:                f = FFARG;
                    725:                n = atoi(argp);
                    726:        }
1.4       millert   727:        if ((fp = name_function(funcp)) == NULL) {
                    728:                ewprintf("Unknown function: %s", funcp);
                    729:                return FALSE;
1.1       deraadt   730:        }
                    731: #ifdef FKEYS
1.4       millert   732:        if (fp == bindtokey || fp == unbindtokey) {
1.1       deraadt   733:                bind = BINDARG;
1.11      art       734:                curmap = fundamental_map;
1.4       millert   735:        } else if (fp == localbind || fp == localunbind) {
1.1       deraadt   736:                bind = BINDARG;
                    737:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.4       millert   738:        } else if (fp == define_key)
                    739:                bind = BINDNEXT;
                    740:        else
                    741:                bind = BINDNO;
1.5       millert   742: #endif /* FKEYS */
                    743:        /* Pack away all the args now... */
1.4       millert   744:        if ((np = lalloc(0)) == FALSE)
                    745:                return FALSE;
1.1       deraadt   746:        np->l_fp = np->l_bp = maclcur = np;
                    747:        while (*line != '\0') {
                    748:                argp = skipwhite(line);
1.4       millert   749:                if (*argp == '\0')
                    750:                        break;
1.1       deraadt   751:                line = parsetoken(argp);
                    752:                if (*argp != '"') {
1.4       millert   753:                        if (*argp == '\'')
                    754:                                ++argp;
                    755:                        if (!(lp = lalloc((int) (line - argp) + BINDEXT))) {
                    756:                                status = FALSE;
                    757:                                goto cleanup;
                    758:                        }
1.5       millert   759:                        bcopy(argp, ltext(lp), (int)(line - argp));
1.1       deraadt   760: #ifdef FKEYS
1.5       millert   761:                        /* don't count BINDEXT */
                    762:                        lp->l_used--;
1.4       millert   763:                        if (bind == BINDARG)
                    764:                                bind = BINDNO;
1.5       millert   765: #endif /* FKEYS */
                    766:                } else {
                    767:                        /* quoted strings are special */
1.4       millert   768:                        ++argp;
1.1       deraadt   769: #ifdef FKEYS
1.4       millert   770:                        if (bind != BINDARG) {
1.5       millert   771: #endif /* FKEYS */
                    772:                                lp = lalloc((int)(line - argp) + BINDEXT);
1.4       millert   773:                                if (lp == NULL) {
                    774:                                        status = FALSE;
                    775:                                        goto cleanup;
                    776:                                }
                    777:                                lp->l_used = 0;
1.1       deraadt   778: #ifdef FKEYS
1.4       millert   779:                        } else {
                    780:                                key.k_count = 0;
1.1       deraadt   781:                        }
1.5       millert   782: #endif /* FKEYS */
1.4       millert   783:                        while (*argp != '"' && *argp != '\0') {
                    784:                                if (*argp != '\\')
                    785:                                        c = *argp++;
                    786:                                else {
                    787:                                        switch (*++argp) {
                    788:                                        case 't':
                    789:                                        case 'T':
                    790:                                                c = CCHR('I');
                    791:                                                break;
                    792:                                        case 'n':
                    793:                                        case 'N':
                    794:                                                c = CCHR('J');
                    795:                                                break;
                    796:                                        case 'r':
                    797:                                        case 'R':
                    798:                                                c = CCHR('M');
                    799:                                                break;
                    800:                                        case 'e':
                    801:                                        case 'E':
                    802:                                                c = CCHR('[');
                    803:                                                break;
                    804:                                        case '^':
                    805:                                                /*
                    806:                                                 * split into two statements
                    807:                                                 * due to bug in OSK cpp
                    808:                                                 */
                    809:                                                c = CHARMASK(*++argp);
                    810:                                                c = ISLOWER(c) ?
                    811:                                                    CCHR(TOUPPER(c)) : CCHR(c);
                    812:                                                break;
                    813:                                        case '0':
                    814:                                        case '1':
                    815:                                        case '2':
                    816:                                        case '3':
                    817:                                        case '4':
                    818:                                        case '5':
                    819:                                        case '6':
                    820:                                        case '7':
                    821:                                                c = *argp - '0';
1.15      mickey    822:                                                if (argp[1] <= '7' &&
1.5       millert   823:                                                    argp[1] >= '0') {
1.4       millert   824:                                                        c <<= 3;
                    825:                                                        c += *++argp - '0';
                    826:                                                        if (argp[1] <= '7' &&
                    827:                                                            argp[1] >= '0') {
                    828:                                                                c <<= 3;
                    829:                                                                c += *++argp
                    830:                                                                    - '0';
                    831:                                                        }
                    832:                                                }
                    833:                                                break;
                    834: #ifdef FKEYS
                    835:                                        case 'f':
                    836:                                        case 'F':
                    837:                                                c = *++argp - '0';
                    838:                                                if (ISDIGIT(argp[1])) {
                    839:                                                        c *= 10;
                    840:                                                        c += *++argp - '0';
                    841:                                                }
                    842:                                                c += KFIRST;
                    843:                                                break;
1.5       millert   844: #endif /* FKEYS */
1.4       millert   845:                                        default:
                    846:                                                c = CHARMASK(*argp);
                    847:                                                break;
                    848:                                        }
                    849:                                        argp++;
                    850:                                }
1.1       deraadt   851: #ifdef FKEYS
1.4       millert   852:                                if (bind == BINDARG)
                    853:                                        key.k_chars[key.k_count++] = c;
                    854:                                else
1.5       millert   855: #endif /* FKEYS */
1.4       millert   856:                                        lp->l_text[lp->l_used++] = c;
                    857:                        }
                    858:                        if (*line)
                    859:                                line++;
1.1       deraadt   860:                }
                    861: #ifdef FKEYS
1.4       millert   862:                switch (bind) {
                    863:                case BINDARG:
1.1       deraadt   864:                        bind = BINDDO;
                    865:                        break;
1.4       millert   866:                case BINDNEXT:
1.1       deraadt   867:                        lp->l_text[lp->l_used] = '\0';
1.10      art       868:                        if ((curmap = name_map(lp->l_text)) == NULL) {
1.4       millert   869:                                ewprintf("No such mode: %s", lp->l_text);
                    870:                                status = FALSE;
1.5       millert   871:                                free((char *)lp);
1.4       millert   872:                                goto cleanup;
1.1       deraadt   873:                        }
1.5       millert   874:                        free((char *)lp);
1.1       deraadt   875:                        bind = BINDARG;
                    876:                        break;
1.4       millert   877:                default:
1.5       millert   878: #endif /* FKEYS */
1.1       deraadt   879:                        lp->l_fp = np->l_fp;
                    880:                        lp->l_bp = np;
                    881:                        np->l_fp = lp;
                    882:                        np = lp;
                    883: #ifdef FKEYS
                    884:                }
1.5       millert   885: #endif /* FKEYS */
1.1       deraadt   886:        }
                    887: #ifdef FKEYS
1.4       millert   888:        switch (bind) {
                    889:        default:
1.1       deraadt   890:                ewprintf("Bad args to set key");
                    891:                status = FALSE;
                    892:                break;
1.4       millert   893:        case BINDDO:
                    894:                if (fp != unbindtokey && fp != localunbind) {
                    895:                        lp->l_text[lp->l_used] = '\0';
                    896:                        status = bindkey(&curmap, lp->l_text, key.k_chars,
                    897:                            key.k_count);
1.13      art       898:                } else {
                    899:                        status = bindkey(&curmap, NULL, key.k_chars,
1.4       millert   900:                            key.k_count);
1.13      art       901:                }
1.1       deraadt   902:                break;
1.4       millert   903:        case BINDNO:
1.5       millert   904: #endif /* FKEYS */
1.1       deraadt   905:                inmacro = TRUE;
                    906:                maclcur = maclcur->l_fp;
1.5       millert   907:                status = (*fp)(f, n);
1.1       deraadt   908:                inmacro = FALSE;
                    909: #ifdef FKEYS
                    910:        }
1.5       millert   911: #endif /* FKEYS */
1.1       deraadt   912: cleanup:
                    913:        lp = maclcur->l_fp;
1.4       millert   914:        while (lp != maclcur) {
                    915:                np = lp->l_fp;
1.5       millert   916:                free((char *)lp);
1.4       millert   917:                lp = np;
1.1       deraadt   918:        }
1.5       millert   919:        free((char *)lp);
1.1       deraadt   920:        return status;
                    921: }
                    922:
                    923: /*
                    924:  * a pair of utility functions for the above
                    925:  */
                    926: static char *
                    927: skipwhite(s)
1.5       millert   928:        char *s;
1.1       deraadt   929: {
1.4       millert   930:        while (*s == ' ' || *s == '\t' || *s == ')' || *s == '(')
                    931:                s++;
                    932:        if (*s == ';')
                    933:                *s = '\0';
1.1       deraadt   934:        return s;
                    935: }
                    936:
                    937: static char *
                    938: parsetoken(s)
1.4       millert   939:        char  *s;
1.1       deraadt   940: {
                    941:        if (*s != '"') {
1.4       millert   942:                while (*s && *s != ' ' && *s != '\t' && *s != ')' && *s != '(')
                    943:                        s++;
                    944:                if (*s == ';')
                    945:                        *s = '\0';
1.1       deraadt   946:        } else
1.5       millert   947:                do {
1.15      mickey    948:                        /*
                    949:                         * Strings get special treatment.
                    950:                         * Beware: You can \ out the end of the string!
1.5       millert   951:                         */
1.4       millert   952:                        if (*s == '\\')
                    953:                                ++s;
                    954:                } while (*++s != '"' && *s != '\0');
1.1       deraadt   955:        return s;
                    956: }
1.5       millert   957: #endif /* !NO_STARTUP */