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

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