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

1.16    ! art         1: /*     $OpenBSD: extend.c,v 1.15 2001/05/24 03:05:22 mickey 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.5       millert   266:        KEYMAP  *mp;
                    267:        int      i;
1.4       millert   268:
1.5       millert   269:        if ((mp = (KEYMAP *)malloc((unsigned)(sizeof(KEYMAP) +
1.15      mickey    270:            (curmap->map_max + (MAPGROW - 1)) *
1.5       millert   271:            sizeof(MAP_ELEMENT)))) == NULL) {
1.4       millert   272:                ewprintf("Out of memory");
                    273:                return NULL;
                    274:        }
                    275:        mp->map_num = curmap->map_num;
                    276:        mp->map_max = curmap->map_max + MAPGROW;
                    277:        mp->map_default = curmap->map_default;
                    278:        for (i = curmap->map_num; i--;) {
                    279:                mp->map_element[i].k_base = curmap->map_element[i].k_base;
                    280:                mp->map_element[i].k_num = curmap->map_element[i].k_num;
                    281:                mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp;
                    282:                mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap;
                    283:        }
                    284:        for (i = nmaps; i--;) {
                    285:                if (map_table[i].p_map == curmap)
                    286:                        map_table[i].p_map = mp;
                    287:                else
                    288:                        fixmap(curmap, mp, map_table[i].p_map);
                    289:        }
                    290:        ele = &mp->map_element[ele - &curmap->map_element[0]];
                    291:        return mp;
                    292: }
                    293:
                    294: /*
                    295:  * Fix references to a reallocated keymap (recursive).
                    296:  */
1.12      art       297: static void
1.4       millert   298: fixmap(curmap, mp, mt)
                    299:        KEYMAP *mt;
                    300:        KEYMAP *curmap;
                    301:        KEYMAP *mp;
                    302: {
1.5       millert   303:        int      i;
1.4       millert   304:
                    305:        for (i = mt->map_num; i--;) {
                    306:                if (mt->map_element[i].k_prefmap != NULL) {
                    307:                        if (mt->map_element[i].k_prefmap == curmap)
                    308:                                mt->map_element[i].k_prefmap = mp;
                    309:                        else
                    310:                                fixmap(curmap, mp, mt->map_element[i].k_prefmap);
                    311:                }
1.1       deraadt   312:        }
                    313: }
                    314:
                    315: /*
                    316:  * do the input for local-set-key, global-set-key  and define-key
                    317:  * then call remap to do the work.
                    318:  */
1.4       millert   319: static int
                    320: dobind(curmap, p, unbind)
1.15      mickey    321:        KEYMAP  *curmap;
                    322:        char    *p;
                    323:        int     unbind;
1.4       millert   324: {
1.5       millert   325:        KEYMAP  *pref_map = NULL;
                    326:        PF       funct;
                    327:        char     prompt[80];
                    328:        char    *pep;
                    329:        int      c, s;
1.1       deraadt   330:
                    331: #ifndef NO_MACRO
1.4       millert   332:        if (macrodef) {
                    333:                /*
                    334:                 * Keystrokes aren't collected. Not hard, but pretty useless.
                    335:                 * Would not work for function keys in any case.
                    336:                 */
                    337:                ewprintf("Can't rebind key in macro");
                    338:                return FALSE;
1.1       deraadt   339:        }
                    340: #ifndef NO_STARTUP
1.4       millert   341:        if (inmacro) {
                    342:                for (s = 0; s < maclcur->l_used - 1; s++) {
1.8       art       343:                        if (doscan(curmap, c = CHARMASK(maclcur->l_text[s]), &curmap)
1.7       art       344:                            != NULL) {
1.13      art       345:                                if (remap(curmap, c, NULL, NULL)
1.4       millert   346:                                    != TRUE)
                    347:                                        return FALSE;
                    348:                        }
1.1       deraadt   349:                }
1.12      art       350:                (void)doscan(curmap, c = maclcur->l_text[s], NULL);
1.4       millert   351:                maclcur = maclcur->l_fp;
1.1       deraadt   352:        } else {
1.5       millert   353: #endif /* !NO_STARTUP */
                    354: #endif /* !NO_MACRO */
1.14      mickey    355:                pep = prompt + strlcpy(prompt, p, sizeof(prompt));
1.4       millert   356:                for (;;) {
                    357:                        ewprintf("%s", prompt);
                    358:                        pep[-1] = ' ';
1.14      mickey    359:                        pep = keyname(pep, sizeof(prompt) - (pep - prompt),
                    360:                            c = getkey(FALSE));
1.8       art       361:                        if (doscan(curmap, c, &curmap) != NULL)
1.4       millert   362:                                break;
                    363:                        *pep++ = '-';
                    364:                        *pep = '\0';
                    365:                }
1.1       deraadt   366: #ifndef NO_STARTUP
                    367:        }
1.5       millert   368: #endif /* !NO_STARTUP */
1.4       millert   369:        if (unbind)
                    370:                funct = rescan;
1.1       deraadt   371:        else {
1.4       millert   372:                if ((s = eread("%s to command: ", prompt, 80, EFFUNC | EFNEW,
                    373:                    prompt)) != TRUE)
                    374:                        return s;
1.7       art       375:                if (((funct = name_function(prompt)) == NULL) ?
1.4       millert   376:                    (pref_map = name_map(prompt)) == NULL : funct == NULL) {
                    377:                        ewprintf("[No match]");
                    378:                        return FALSE;
                    379:                }
1.1       deraadt   380:        }
                    381:        return remap(curmap, c, funct, pref_map);
                    382: }
                    383:
                    384: /*
1.15      mickey    385:  * bindkey: bind key sequence to a function in the specified map.  Used by
                    386:  * excline so it can bind function keys.  To close to release to change
                    387:  * calling sequence, should just pass KEYMAP *curmap rather than
1.5       millert   388:  * KEYMAP **mapp.
                    389:  */
1.1       deraadt   390: #ifdef BINDKEY
1.5       millert   391: static int
1.1       deraadt   392: bindkey(mapp, fname, keys, kcount)
1.15      mickey    393:        KEYMAP  **mapp;
                    394:        char    *fname;
                    395:        KCHAR   *keys;
                    396:        int     kcount;
1.5       millert   397: {
                    398:        KEYMAP  *curmap = *mapp;
                    399:        KEYMAP  *pref_map = NULL;
                    400:        PF       funct;
                    401:        int      c;
1.1       deraadt   402:
1.4       millert   403:        if (fname == NULL)
                    404:                funct = rescan;
1.7       art       405:        else if (((funct = name_function(fname)) == NULL) ?
1.5       millert   406:            (pref_map = name_map(fname)) == NULL : funct == NULL) {
1.4       millert   407:                ewprintf("[No match: %s]", fname);
                    408:                return FALSE;
                    409:        }
                    410:        while (--kcount) {
1.8       art       411:                if (doscan(curmap, c = *keys++, &curmap) != NULL) {
1.13      art       412:                        if (remap(curmap, c, NULL, NULL) != TRUE)
1.4       millert   413:                                return FALSE;
1.9       art       414:                        /*
                    415:                         * XXX - Bizzarreness. remap creates an empty KEYMAP
                    416:                         *       that the last key is supposed to point to.
                    417:                         */
                    418:                        curmap = ele->k_prefmap;
1.4       millert   419:                }
1.1       deraadt   420:        }
1.12      art       421:        (void)doscan(curmap, c = *keys, NULL);
1.1       deraadt   422:        return remap(curmap, c, funct, pref_map);
                    423: }
1.3       millert   424:
                    425: #ifdef FKEYS
                    426: /*
                    427:  * Wrapper for bindkey() that converts escapes.
                    428:  */
                    429: int
                    430: dobindkey(map, func, str)
                    431:        KEYMAP *map;
1.4       millert   432:        char   *func;
                    433:        char   *str;
1.3       millert   434: {
1.5       millert   435:        int      i;
1.3       millert   436:
                    437:        for (i = 0; *str && i < MAXKEY; i++) {
                    438:                /* XXX - convert numbers w/ strol()? */
                    439:                if (*str != '\\')
                    440:                        key.k_chars[i] = *str;
                    441:                else {
1.4       millert   442:                        switch (*++str) {
                    443:                        case 't':
                    444:                        case 'T':
1.3       millert   445:                                key.k_chars[i] = '\t';
                    446:                                break;
1.4       millert   447:                        case 'n':
                    448:                        case 'N':
1.3       millert   449:                                key.k_chars[i] = '\n';
                    450:                                break;
1.4       millert   451:                        case 'r':
                    452:                        case 'R':
1.3       millert   453:                                key.k_chars[i] = '\r';
                    454:                                break;
1.4       millert   455:                        case 'e':
                    456:                        case 'E':
1.3       millert   457:                                key.k_chars[i] = CCHR('[');
                    458:                                break;
                    459:                        }
                    460:                }
                    461:                str++;
                    462:        }
                    463:        key.k_count = i;
1.4       millert   464:        return (bindkey(&map, func, key.k_chars, key.k_count));
1.3       millert   465: }
1.5       millert   466: #endif /* FKEYS */
                    467: #endif /* BINDKEY */
1.1       deraadt   468:
                    469: /*
                    470:  * This function modifies the fundamental keyboard map.
                    471:  */
1.4       millert   472: /* ARGSUSED */
                    473: int
1.1       deraadt   474: bindtokey(f, n)
1.4       millert   475:        int f, n;
1.1       deraadt   476: {
1.11      art       477:        return dobind(fundamental_map, "Global set key: ", FALSE);
1.1       deraadt   478: }
                    479:
                    480: /*
                    481:  * This function modifies the current mode's keyboard map.
                    482:  */
1.4       millert   483: /* ARGSUSED */
                    484: int
1.1       deraadt   485: localbind(f, n)
1.4       millert   486:        int f, n;
1.1       deraadt   487: {
1.15      mickey    488:        return dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
1.5       millert   489:            "Local set key: ", FALSE);
1.1       deraadt   490: }
                    491:
                    492: /*
                    493:  * This function redefines a key in any keymap.
                    494:  */
1.4       millert   495: /* ARGSUSED */
                    496: int
1.1       deraadt   497: define_key(f, n)
1.4       millert   498:        int f, n;
1.1       deraadt   499: {
1.5       millert   500:        static char      buf[48] = "Define key map: ";
1.10      art       501:        KEYMAP          *mp;
1.4       millert   502:
                    503:        buf[16] = '\0';
                    504:        if (eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE)
                    505:                return FALSE;
1.10      art       506:        if ((mp = name_map(&buf[16])) == NULL) {
1.4       millert   507:                ewprintf("Unknown map %s", &buf[16]);
                    508:                return FALSE;
                    509:        }
1.12      art       510:        (void)strncat(&buf[16], " key: ", 48 - 16 - 1);
1.10      art       511:        return dobind(mp, buf, FALSE);
1.1       deraadt   512: }
                    513:
1.4       millert   514: int
1.1       deraadt   515: unbindtokey(f, n)
1.4       millert   516:        int f, n;
1.1       deraadt   517: {
1.11      art       518:        return dobind(fundamental_map, "Global unset key: ", TRUE);
1.1       deraadt   519: }
                    520:
1.4       millert   521: int
1.1       deraadt   522: localunbind(f, n)
1.4       millert   523:        int f, n;
1.1       deraadt   524: {
1.4       millert   525:        return dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
                    526:            "Local unset key: ", TRUE);
1.1       deraadt   527: }
                    528:
                    529: /*
1.15      mickey    530:  * Extended command. Call the message line routine to read in the command
                    531:  * name and apply autocompletion to it. When it comes back, look the name
                    532:  * up in the symbol table and run the command if it is found.  Print an
1.5       millert   533:  * error if there is anything wrong.
1.1       deraadt   534:  */
1.4       millert   535: int
1.1       deraadt   536: extend(f, n)
1.5       millert   537:        int f, n;
1.1       deraadt   538: {
1.5       millert   539:        PF       funct;
                    540:        int      s;
                    541:        char     xname[NXNAME];
1.4       millert   542:
                    543:        if (!(f & FFARG))
                    544:                s = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC);
                    545:        else
                    546:                s = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n);
                    547:        if (s != TRUE)
                    548:                return s;
                    549:        if ((funct = name_function(xname)) != NULL) {
1.1       deraadt   550: #ifndef NO_MACRO
1.4       millert   551:                if (macrodef) {
1.5       millert   552:                        LINE    *lp = maclcur;
1.4       millert   553:                        macro[macrocount - 1].m_funct = funct;
                    554:                        maclcur = lp->l_bp;
                    555:                        maclcur->l_fp = lp->l_fp;
1.5       millert   556:                        free((char *)lp);
1.4       millert   557:                }
1.5       millert   558: #endif /* !NO_MACRO */
                    559:                return (*funct)(f, n);
1.1       deraadt   560:        }
                    561:        ewprintf("[No match]");
                    562:        return FALSE;
                    563: }
                    564:
                    565: #ifndef NO_STARTUP
                    566: /*
                    567:  * Define the commands needed to do startup-file processing.
                    568:  * This code is mostly a kludge just so we can get startup-file processing.
                    569:  *
                    570:  * If you're serious about having this code, you should rewrite it.
                    571:  * To wit:
                    572:  *     It has lots of funny things in it to make the startup-file look
                    573:  *     like a GNU startup file; mostly dealing with parens and semicolons.
                    574:  *     This should all vanish.
                    575:  *
                    576:  * We define eval-expression because it's easy.         It can make
                    577:  * *-set-key or define-key set an arbitrary key sequence, so it isn't
                    578:  * useless.
                    579:  */
                    580:
                    581: /*
                    582:  * evalexpr - get one line from the user, and run it.
                    583:  */
1.4       millert   584: /* ARGSUSED */
                    585: int
1.1       deraadt   586: evalexpr(f, n)
1.5       millert   587:        int f, n;
1.1       deraadt   588: {
1.5       millert   589:        int      s;
                    590:        char     exbuf[128];
1.1       deraadt   591:
                    592:        if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
                    593:                return s;
                    594:        return excline(exbuf);
                    595: }
1.4       millert   596:
1.1       deraadt   597: /*
1.15      mickey    598:  * evalbuffer - evaluate the current buffer as line commands. Useful for
1.5       millert   599:  * testing startup files.
1.1       deraadt   600:  */
1.4       millert   601: /* ARGSUSED */
                    602: int
1.1       deraadt   603: evalbuffer(f, n)
1.5       millert   604:        int f, n;
1.1       deraadt   605: {
1.5       millert   606:        LINE            *lp;
                    607:        BUFFER          *bp = curbp;
                    608:        int              s;
                    609:        static char      excbuf[128];
1.1       deraadt   610:
                    611:        for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
1.4       millert   612:                if (llength(lp) >= 128)
                    613:                        return FALSE;
1.12      art       614:                (void)strncpy(excbuf, ltext(lp), llength(lp));
1.5       millert   615:
                    616:                /* make sure it's terminated */
                    617:                excbuf[llength(lp)] = '\0';
1.4       millert   618:                if ((s = excline(excbuf)) != TRUE)
                    619:                        return s;
1.1       deraadt   620:        }
                    621:        return TRUE;
                    622: }
1.4       millert   623:
1.1       deraadt   624: /*
                    625:  * evalfile - go get a file and evaluate it as line commands. You can
                    626:  *     go get your own startup file if need be.
                    627:  */
1.4       millert   628: /* ARGSUSED */
                    629: int
1.1       deraadt   630: evalfile(f, n)
1.5       millert   631:        int f, n;
1.1       deraadt   632: {
1.5       millert   633:        int      s;
                    634:        char     fname[NFILEN];
1.1       deraadt   635:
                    636:        if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
                    637:                return s;
                    638:        return load(fname);
                    639: }
                    640:
                    641: /*
                    642:  * load - go load the file name we got passed.
                    643:  */
1.4       millert   644: int
                    645: load(fname)
1.5       millert   646:        char *fname;
1.4       millert   647: {
1.5       millert   648:        int      s = TRUE;
                    649:        int      nbytes;
                    650:        char     excbuf[128];
1.1       deraadt   651:
                    652:        if ((fname = adjustname(fname)) == NULL)
1.5       millert   653:                /* just to be careful */
                    654:                return FALSE;
1.1       deraadt   655:
1.13      art       656:        if (ffropen(fname, NULL) != FIOSUC)
1.4       millert   657:                return FALSE;
1.5       millert   658:
1.4       millert   659:        while ((s = ffgetline(excbuf, sizeof(excbuf) - 1, &nbytes)) == FIOSUC) {
1.1       deraadt   660:                excbuf[nbytes] = '\0';
                    661:                if (excline(excbuf) != TRUE) {
                    662:                        s = FIOERR;
                    663:                        ewprintf("Error loading file %s", fname);
                    664:                        break;
                    665:                }
                    666:        }
1.13      art       667:        (void)ffclose(NULL);
1.1       deraadt   668:        excbuf[nbytes] = '\0';
1.4       millert   669:        if (s != FIOEOF || (nbytes && excline(excbuf) != TRUE))
1.1       deraadt   670:                return FALSE;
                    671:        return TRUE;
                    672: }
                    673:
                    674: /*
1.15      mickey    675:  * excline - run a line from a load file or eval-expression.  if FKEYS is
                    676:  * defined, duplicate functionallity of dobind so function key values don't
1.5       millert   677:  * have to fit in type char.
1.1       deraadt   678:  */
1.4       millert   679: int
1.1       deraadt   680: excline(line)
1.5       millert   681:        char *line;
1.1       deraadt   682: {
1.5       millert   683:        PF       fp;
                    684:        LINE    *lp, *np;
                    685:        int      status, c, f, n;
                    686:        char    *funcp;
                    687:        char    *argp = NULL;
                    688: #ifdef FKEYS
                    689:        int      bind;
                    690:        KEYMAP  *curmap;
                    691: #define BINDARG                0  /* this arg is key to bind (local/global set key) */
                    692: #define        BINDNO          1  /* not binding or non-quoted BINDARG */
                    693: #define BINDNEXT       2  /* next arg " (define-key) */
                    694: #define BINDDO         3  /* already found key to bind */
                    695: #define BINDEXT                1  /* space for trailing \0 */
                    696: #else /* FKEYS */
                    697: #define BINDEXT                0
                    698: #endif /* FKEYS */
                    699:
                    700:        lp = NULL;
1.1       deraadt   701:
1.4       millert   702:        if (macrodef || inmacro) {
1.1       deraadt   703:                ewprintf("Not now!");
                    704:                return FALSE;
                    705:        }
                    706:        f = 0;
                    707:        n = 1;
                    708:        funcp = skipwhite(line);
1.4       millert   709:        if (*funcp == '\0')
                    710:                return TRUE;    /* No error on blank lines */
1.1       deraadt   711:        line = parsetoken(funcp);
                    712:        if (*line != '\0') {
                    713:                *line++ = '\0';
                    714:                line = skipwhite(line);
                    715:                if ((*line >= '0' && *line <= '9') || *line == '-') {
                    716:                        argp = line;
                    717:                        line = parsetoken(line);
                    718:                }
                    719:        }
                    720:        if (argp != NULL) {
                    721:                f = FFARG;
                    722:                n = atoi(argp);
                    723:        }
1.4       millert   724:        if ((fp = name_function(funcp)) == NULL) {
                    725:                ewprintf("Unknown function: %s", funcp);
                    726:                return FALSE;
1.1       deraadt   727:        }
                    728: #ifdef FKEYS
1.4       millert   729:        if (fp == bindtokey || fp == unbindtokey) {
1.1       deraadt   730:                bind = BINDARG;
1.11      art       731:                curmap = fundamental_map;
1.4       millert   732:        } else if (fp == localbind || fp == localunbind) {
1.1       deraadt   733:                bind = BINDARG;
                    734:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.4       millert   735:        } else if (fp == define_key)
                    736:                bind = BINDNEXT;
                    737:        else
                    738:                bind = BINDNO;
1.5       millert   739: #endif /* FKEYS */
                    740:        /* Pack away all the args now... */
1.4       millert   741:        if ((np = lalloc(0)) == FALSE)
                    742:                return FALSE;
1.1       deraadt   743:        np->l_fp = np->l_bp = maclcur = np;
                    744:        while (*line != '\0') {
                    745:                argp = skipwhite(line);
1.4       millert   746:                if (*argp == '\0')
                    747:                        break;
1.1       deraadt   748:                line = parsetoken(argp);
                    749:                if (*argp != '"') {
1.4       millert   750:                        if (*argp == '\'')
                    751:                                ++argp;
                    752:                        if (!(lp = lalloc((int) (line - argp) + BINDEXT))) {
                    753:                                status = FALSE;
                    754:                                goto cleanup;
                    755:                        }
1.5       millert   756:                        bcopy(argp, ltext(lp), (int)(line - argp));
1.1       deraadt   757: #ifdef FKEYS
1.5       millert   758:                        /* don't count BINDEXT */
                    759:                        lp->l_used--;
1.4       millert   760:                        if (bind == BINDARG)
                    761:                                bind = BINDNO;
1.5       millert   762: #endif /* FKEYS */
                    763:                } else {
                    764:                        /* quoted strings are special */
1.4       millert   765:                        ++argp;
1.1       deraadt   766: #ifdef FKEYS
1.4       millert   767:                        if (bind != BINDARG) {
1.5       millert   768: #endif /* FKEYS */
                    769:                                lp = lalloc((int)(line - argp) + BINDEXT);
1.4       millert   770:                                if (lp == NULL) {
                    771:                                        status = FALSE;
                    772:                                        goto cleanup;
                    773:                                }
                    774:                                lp->l_used = 0;
1.1       deraadt   775: #ifdef FKEYS
1.4       millert   776:                        } else {
                    777:                                key.k_count = 0;
1.1       deraadt   778:                        }
1.5       millert   779: #endif /* FKEYS */
1.4       millert   780:                        while (*argp != '"' && *argp != '\0') {
                    781:                                if (*argp != '\\')
                    782:                                        c = *argp++;
                    783:                                else {
                    784:                                        switch (*++argp) {
                    785:                                        case 't':
                    786:                                        case 'T':
                    787:                                                c = CCHR('I');
                    788:                                                break;
                    789:                                        case 'n':
                    790:                                        case 'N':
                    791:                                                c = CCHR('J');
                    792:                                                break;
                    793:                                        case 'r':
                    794:                                        case 'R':
                    795:                                                c = CCHR('M');
                    796:                                                break;
                    797:                                        case 'e':
                    798:                                        case 'E':
                    799:                                                c = CCHR('[');
                    800:                                                break;
                    801:                                        case '^':
                    802:                                                /*
                    803:                                                 * split into two statements
                    804:                                                 * due to bug in OSK cpp
                    805:                                                 */
                    806:                                                c = CHARMASK(*++argp);
                    807:                                                c = ISLOWER(c) ?
                    808:                                                    CCHR(TOUPPER(c)) : CCHR(c);
                    809:                                                break;
                    810:                                        case '0':
                    811:                                        case '1':
                    812:                                        case '2':
                    813:                                        case '3':
                    814:                                        case '4':
                    815:                                        case '5':
                    816:                                        case '6':
                    817:                                        case '7':
                    818:                                                c = *argp - '0';
1.15      mickey    819:                                                if (argp[1] <= '7' &&
1.5       millert   820:                                                    argp[1] >= '0') {
1.4       millert   821:                                                        c <<= 3;
                    822:                                                        c += *++argp - '0';
                    823:                                                        if (argp[1] <= '7' &&
                    824:                                                            argp[1] >= '0') {
                    825:                                                                c <<= 3;
                    826:                                                                c += *++argp
                    827:                                                                    - '0';
                    828:                                                        }
                    829:                                                }
                    830:                                                break;
                    831: #ifdef FKEYS
                    832:                                        case 'f':
                    833:                                        case 'F':
                    834:                                                c = *++argp - '0';
                    835:                                                if (ISDIGIT(argp[1])) {
                    836:                                                        c *= 10;
                    837:                                                        c += *++argp - '0';
                    838:                                                }
                    839:                                                c += KFIRST;
                    840:                                                break;
1.5       millert   841: #endif /* FKEYS */
1.4       millert   842:                                        default:
                    843:                                                c = CHARMASK(*argp);
                    844:                                                break;
                    845:                                        }
                    846:                                        argp++;
                    847:                                }
1.1       deraadt   848: #ifdef FKEYS
1.4       millert   849:                                if (bind == BINDARG)
                    850:                                        key.k_chars[key.k_count++] = c;
                    851:                                else
1.5       millert   852: #endif /* FKEYS */
1.4       millert   853:                                        lp->l_text[lp->l_used++] = c;
                    854:                        }
                    855:                        if (*line)
                    856:                                line++;
1.1       deraadt   857:                }
                    858: #ifdef FKEYS
1.4       millert   859:                switch (bind) {
                    860:                case BINDARG:
1.1       deraadt   861:                        bind = BINDDO;
                    862:                        break;
1.4       millert   863:                case BINDNEXT:
1.1       deraadt   864:                        lp->l_text[lp->l_used] = '\0';
1.10      art       865:                        if ((curmap = name_map(lp->l_text)) == NULL) {
1.4       millert   866:                                ewprintf("No such mode: %s", lp->l_text);
                    867:                                status = FALSE;
1.5       millert   868:                                free((char *)lp);
1.4       millert   869:                                goto cleanup;
1.1       deraadt   870:                        }
1.5       millert   871:                        free((char *)lp);
1.1       deraadt   872:                        bind = BINDARG;
                    873:                        break;
1.4       millert   874:                default:
1.5       millert   875: #endif /* FKEYS */
1.1       deraadt   876:                        lp->l_fp = np->l_fp;
                    877:                        lp->l_bp = np;
                    878:                        np->l_fp = lp;
                    879:                        np = lp;
                    880: #ifdef FKEYS
                    881:                }
1.5       millert   882: #endif /* FKEYS */
1.1       deraadt   883:        }
                    884: #ifdef FKEYS
1.4       millert   885:        switch (bind) {
                    886:        default:
1.1       deraadt   887:                ewprintf("Bad args to set key");
                    888:                status = FALSE;
                    889:                break;
1.4       millert   890:        case BINDDO:
                    891:                if (fp != unbindtokey && fp != localunbind) {
                    892:                        lp->l_text[lp->l_used] = '\0';
                    893:                        status = bindkey(&curmap, lp->l_text, key.k_chars,
                    894:                            key.k_count);
1.13      art       895:                } else {
                    896:                        status = bindkey(&curmap, NULL, key.k_chars,
1.4       millert   897:                            key.k_count);
1.13      art       898:                }
1.1       deraadt   899:                break;
1.4       millert   900:        case BINDNO:
1.5       millert   901: #endif /* FKEYS */
1.1       deraadt   902:                inmacro = TRUE;
                    903:                maclcur = maclcur->l_fp;
1.5       millert   904:                status = (*fp)(f, n);
1.1       deraadt   905:                inmacro = FALSE;
                    906: #ifdef FKEYS
                    907:        }
1.5       millert   908: #endif /* FKEYS */
1.1       deraadt   909: cleanup:
                    910:        lp = maclcur->l_fp;
1.4       millert   911:        while (lp != maclcur) {
                    912:                np = lp->l_fp;
1.5       millert   913:                free((char *)lp);
1.4       millert   914:                lp = np;
1.1       deraadt   915:        }
1.5       millert   916:        free((char *)lp);
1.1       deraadt   917:        return status;
                    918: }
                    919:
                    920: /*
                    921:  * a pair of utility functions for the above
                    922:  */
                    923: static char *
                    924: skipwhite(s)
1.5       millert   925:        char *s;
1.1       deraadt   926: {
1.4       millert   927:        while (*s == ' ' || *s == '\t' || *s == ')' || *s == '(')
                    928:                s++;
                    929:        if (*s == ';')
                    930:                *s = '\0';
1.1       deraadt   931:        return s;
                    932: }
                    933:
                    934: static char *
                    935: parsetoken(s)
1.4       millert   936:        char  *s;
1.1       deraadt   937: {
                    938:        if (*s != '"') {
1.4       millert   939:                while (*s && *s != ' ' && *s != '\t' && *s != ')' && *s != '(')
                    940:                        s++;
                    941:                if (*s == ';')
                    942:                        *s = '\0';
1.1       deraadt   943:        } else
1.5       millert   944:                do {
1.15      mickey    945:                        /*
                    946:                         * Strings get special treatment.
                    947:                         * Beware: You can \ out the end of the string!
1.5       millert   948:                         */
1.4       millert   949:                        if (*s == '\\')
                    950:                                ++s;
                    951:                } while (*++s != '"' && *s != '\0');
1.1       deraadt   952:        return s;
                    953: }
1.5       millert   954: #endif /* !NO_STARTUP */