Annotation of 43BSDReno/contrib/jove/keymaps.c, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
                      3:  * is provided to you without charge, and with no warranty.  You may give  *
                      4:  * away copies of JOVE, including sources, provided that this notice is    *
                      5:  * included in all the files.                                              *
                      6:  ***************************************************************************/
                      7: 
                      8: #include "jove.h"
                      9: #include "list.h"
                     10: #include "fp.h"
                     11: #include "termcap.h"
                     12: #include "chars.h"
                     13: #include "disp.h"
                     14: #include "re.h"
                     15: 
                     16: /* Up until now a keymap was an array of pointers to
                     17:    data_obj's.  A data_obj was either a pointer to a built-in
                     18:    command or a keyboard macro.  Now a data_obj can be a
                     19:    pointer to a keymap as well, which is how prefix keys will
                     20:    be handled.
                     21: 
                     22:    There will be a way to build keymaps and give them names,
                     23:    and to look those keymaps up by name, attach them to keys.
                     24:    There will be a way to specify a string of key strokes and
                     25:    have a series of keymaps built automatically for those
                     26:    sequences. */
                     27: 
                     28: private        void
                     29:        fb_aux proto((data_obj *, struct keymap *, char *, char *)),
                     30:        find_binds proto((data_obj *, char *));
                     31: 
                     32: private List   *keymaps;               /* list of all keymaps */
                     33: private struct keymap  *mainmap;
                     34: #if defined(IPROCS)
                     35: private struct keymap  *procsmap;
                     36: #endif
                     37: 
                     38: /* make a new keymap, give it name NAME, initialize the keys array
                     39:    to keys, if nonzero, or make an empty one, otherwise */
                     40: 
                     41: private struct keymap *
                     42: km_new(name, keys)
                     43: char   *name;
                     44: data_obj       **keys;
                     45: {
                     46:        struct keymap   *km;
                     47: 
                     48:        km = (struct keymap *) emalloc(sizeof *km);
                     49:        (void) list_push(&keymaps, (Element *) km);
                     50:        km->Type = KEYMAP;
                     51:        km->Name = name;
                     52:        if (keys != 0) {
                     53:                km->k_keys = keys;
                     54:                km->k_alloc_p = NO;
                     55:        } else {
                     56:                km->k_keys = (data_obj **) emalloc(NCHARS * sizeof (data_obj *));
                     57:                byte_zero((char *) km->k_keys, NCHARS * sizeof (data_obj *));
                     58:                km->k_alloc_p = YES;
                     59:        }
                     60:        return km;
                     61: }
                     62: 
                     63: #ifdef NEVER_USED
                     64: 
                     65: /* free up a keymap */
                     66: 
                     67: private void
                     68: km_destroy(km)
                     69: struct keymap  *km;
                     70: {
                     71:        if (km->k_alloc_p == YES)
                     72:                free((char *) km->k_keys);
                     73:        km->k_keys = 0;
                     74:        free((char *) km);
                     75: }
                     76: 
                     77: /* lookup a keymap by name */
                     78: 
                     79: private struct keymap *
                     80: km_lookup(name)
                     81: char   *name;
                     82: {
                     83:        List    *lp;
                     84: 
                     85:        for (lp = keymaps; lp != 0; lp = list_next(lp))
                     86:                if (strcmp(name, ((struct keymap *) list_data(lp))->Name) == 0)
                     87:                        break;
                     88:        if (lp == 0)
                     89:                return 0;
                     90:        return (struct keymap *) list_data(lp);
                     91: }
                     92: 
                     93: #endif
                     94: 
                     95: /* given a map and a key, return the object bound to that key */
                     96: 
                     97: #define km_getkey(m, c)        ((m)->k_keys[(c) & CHARMASK])
                     98: 
                     99: #ifndef km_getkey
                    100: data_obj *
                    101: km_getkey(m, c)
                    102: struct keymap  *m;
                    103: int    c;
                    104: {
                    105:        return (m->k_keys[c & CHARMASK]);
                    106: }
                    107: #endif
                    108: 
                    109: private void
                    110: km_setkey(m, c, d)
                    111: struct keymap  *m;
                    112: int    c;
                    113: data_obj       *d;
                    114: {
                    115:        m->k_keys[c & CHARMASK] = d;
                    116: }
                    117: 
                    118: /* get the currently active keymaps into km_buf */
                    119: 
                    120: private int
                    121: get_keymaps(km_buf)
                    122: struct keymap  **km_buf;
                    123: {
                    124:        int     nmaps = 0;
                    125: 
                    126: #ifdef IPROCS
                    127:        if (curbuf->b_process != 0)
                    128:                km_buf[nmaps++] = procsmap;
                    129: #endif
                    130:        if (curbuf->b_map != 0)
                    131:                km_buf[nmaps++] = curbuf->b_map;
                    132:        km_buf[nmaps++] = mainmap;
                    133: 
                    134:        return nmaps;
                    135: }
                    136: 
                    137: private struct keymap *
                    138: IsPrefix(cp)
                    139: data_obj       *cp;
                    140: {
                    141:        if (cp == 0 || (cp->Type & TYPEMASK) != KEYMAP)
                    142:                return 0;
                    143:        return (struct keymap *) cp;
                    144: }
                    145: 
                    146: /* Is `c' a prefix character */
                    147: 
                    148: int
                    149: PrefChar(c)
                    150: int    c;
                    151: {
                    152:        return (int) IsPrefix(km_getkey(mainmap, c));
                    153: }
                    154: 
                    155: void
                    156: UnbindC()
                    157: {
                    158:        char    *keys;
                    159:        struct keymap   *map = mainmap;
                    160: 
                    161:        keys = ask((char *) 0, ProcFmt);
                    162:        for (;;) {
                    163:                if (keys[1] == '\0')
                    164:                        break;
                    165:                if ((map = IsPrefix(km_getkey(map, *keys))) == 0)
                    166:                        break;
                    167:                keys += 1;
                    168:        }
                    169:        if (keys[1] != 0)
                    170:                complain("That's not a legitimate key sequence.");
                    171:        km_setkey(map, keys[0], (data_obj *) 0);
                    172: }
                    173: 
                    174: void
                    175: BindWMap(map, lastkey, cmd)
                    176: struct keymap  *map;
                    177: int    lastkey;
                    178: data_obj       *cmd;
                    179: {
                    180:        struct keymap   *nextmap;
                    181:        int     c;
                    182: 
                    183:        c = addgetc();
                    184:        if (c == EOF) {
                    185:                if (lastkey == EOF)
                    186:                        complain("[Empty key sequence]");
                    187:                complain("[Premature end of key sequence]");
                    188:        } else {
                    189:                if ((nextmap = IsPrefix(km_getkey(map, c))) != NULL)
                    190:                        BindWMap(nextmap, c, cmd);
                    191:                else {
                    192:                        km_setkey(map, c, cmd);
                    193: #ifdef MAC
                    194:                        ((struct cmd *) cmd)->c_key = c;        /* see about_j() in mac.c */
                    195:                        if (map->k_keys == MainKeys)
                    196:                                ((struct cmd *) cmd)->c_map = F_MAINMAP;
                    197:                        else if (map->k_keys == EscKeys)
                    198:                                ((struct cmd *) cmd)->c_map = F_PREF1MAP;
                    199:                        else if (map == (struct keymap *) CtlxKeys)
                    200:                                ((struct cmd *) cmd)->c_map = F_PREF2MAP;
                    201: #endif
                    202:                }
                    203:        }
                    204: }
                    205: 
                    206: void
                    207: BindSomething(proc, map)
                    208: #if defined(MAC) || defined(IBMPC)
                    209: data_obj       *(*proc)();
                    210: #else
                    211: data_obj       *(*proc) proto((char *));
                    212: #endif
                    213: struct keymap  *map;
                    214: {
                    215:        data_obj        *d;
                    216: 
                    217:        if ((d = (*proc)(ProcFmt)) == 0)
                    218:                return;
                    219:        s_mess(": %f %s ", d->Name);
                    220:        BindWMap(map, EOF, d);
                    221: }
                    222: 
                    223: void
                    224: BindAKey()
                    225: {
                    226:        BindSomething(findcom, mainmap);
                    227: }
                    228: 
                    229: void
                    230: BindMac()
                    231: {
                    232:        BindSomething(findmac, mainmap);
                    233: }
                    234: 
                    235: void
                    236: DescWMap(map, key)
                    237: struct keymap  *map;
                    238: int    key;
                    239: {
                    240:        data_obj        *cp = km_getkey(map, key);
                    241:        struct keymap   *prefp;
                    242: 
                    243:        if (cp == 0)
                    244:                add_mess("is unbound.");
                    245:        else if ((prefp = IsPrefix(cp)) != NULL)
                    246:                DescWMap(prefp, addgetc());
                    247:        else
                    248:                add_mess("is bound to %s.", cp->Name);
                    249: }
                    250: 
                    251: void
                    252: KeyDesc()
                    253: {
                    254:        s_mess(ProcFmt);
                    255:        DescWMap(mainmap, addgetc());
                    256: }
                    257: 
                    258: void
                    259: DescBindings()
                    260: {
                    261:        TOstart("Key Bindings", TRUE);
                    262:        DescMap(mainmap, NullStr);
                    263:        TOstop();
                    264: }
                    265: 
                    266: void
                    267: DescMap(map, pref)
                    268: struct keymap  *map;
                    269: char   *pref;
                    270: {
                    271:        int     c1,
                    272:                c2 = 0,
                    273:                numbetween;
                    274:        char    keydescbuf[40];
                    275:        struct keymap   *prefp;
                    276: 
                    277:        for (c1 = 0; c1 < NCHARS && c2 < NCHARS; c1 = c2 + 1) {
                    278:                c2 = c1;
                    279:                if (km_getkey(map, c1) == 0)
                    280:                        continue;
                    281:                while (++c2 < NCHARS && km_getkey(map, c1) == km_getkey(map, c2))
                    282:                        ;
                    283:                c2 -= 1;
                    284:                numbetween = c2 - c1;
                    285:                if (numbetween == 1)
                    286:                        swritef(keydescbuf, "%s {%p,%p}", pref, c1, c2);
                    287:                else if (numbetween == 0)
                    288:                        swritef(keydescbuf, "%s %p", pref, c1);
                    289:                else
                    290:                        swritef(keydescbuf, "%s [%p-%p]", pref, c1, c2);
                    291:                if ((prefp = IsPrefix(km_getkey(map, c1)))!=NULL && (prefp != map)) {
                    292:                        Typeout("%-18s KEYMAP %s", keydescbuf, km_getkey(map, c1)->Name);
                    293:                        DescMap(prefp, keydescbuf);
                    294:                }
                    295:                else
                    296:                        Typeout("%-18s %s", keydescbuf, km_getkey(map, c1)->Name);
                    297:        }
                    298: }
                    299: 
                    300: private void
                    301: find_binds(dp, buf)
                    302: data_obj       *dp;
                    303: char   *buf;
                    304: {
                    305:        char    *endp;
                    306: 
                    307:        buf[0] = '\0';
                    308:        fb_aux(dp, mainmap, (char *) 0, buf);
                    309:        endp = buf + strlen(buf) - 2;
                    310:        if ((endp > buf) && (strcmp(endp, ", ") == 0))
                    311:                *endp = '\0';
                    312: }
                    313: 
                    314: private void
                    315: fb_aux(cp, map, prefix, buf)
                    316: register data_obj      *cp;
                    317: struct keymap  *map;
                    318: char   *buf,
                    319:        *prefix;
                    320: {
                    321:        int     c1,
                    322:                c2;
                    323:        char    *bufp = buf + strlen(buf),
                    324:                prefbuf[20];
                    325:        struct keymap   *prefp;
                    326: 
                    327:        for (c1 = c2 = 0; c1 < NCHARS && c2 < NCHARS; c1 = c2 + 1) {
                    328:                c2 = c1;
                    329:                if (km_getkey(map, c1) == cp) {
                    330:                        while (++c2 < NCHARS && km_getkey(map, c1) == km_getkey(map, c2))
                    331:                                ;
                    332:                        c2 -= 1;
                    333:                        if (prefix)
                    334:                                swritef(bufp, "%s ", prefix);
                    335:                        bufp += strlen(bufp);
                    336:                        switch (c2 - c1) {
                    337:                        case 0:
                    338:                                swritef(bufp, "%p, ", c1);
                    339:                                break;
                    340: 
                    341:                        case 1:
                    342:                                swritef(bufp, "{%p,%p}, ", c1, c2);
                    343:                                break;
                    344: 
                    345:                        default:
                    346:                                swritef(bufp, "[%p-%p], ", c1, c2);
                    347:                                break;
                    348:                        }
                    349:                }
                    350:                if ((prefp = IsPrefix(km_getkey(map, c1)))!=NULL && (prefp != map))  {
                    351:                        swritef(prefbuf, "%p", c1);
                    352:                        fb_aux(cp, prefp, prefbuf, bufp);
                    353:                }
                    354:                bufp += strlen(bufp);
                    355:        }
                    356: }
                    357: 
                    358: void
                    359: DescCom()
                    360: {
                    361:        data_obj        *dp;
                    362:        char    pattern[100],
                    363:                *doc_type,
                    364:                *file = CmdDb;
                    365:        static char var_type[] = "Variable";
                    366:        static char cmd_type[] = "Command";
                    367:        File    *fp;
                    368: 
                    369:        if (!strcmp(LastCmd->Name, "describe-variable")) {
                    370:                doc_type = var_type;
                    371:                dp = (data_obj *) findvar(ProcFmt);
                    372:        } else {
                    373:                doc_type = cmd_type;
                    374:                dp = (data_obj *) findcom(ProcFmt);
                    375:        }
                    376:        if (dp == 0)
                    377:                return;
                    378:        fp = open_file(file, iobuff, F_READ, YES, YES);
                    379:        Placur(ILI, 0);
                    380:        flusho();
                    381:        swritef(pattern, "^:entry \"%s\" \"%s\"$", dp->Name, doc_type);
                    382:        TOstart("Help", TRUE);
                    383:        for (;;) {
                    384:                if (f_gets(fp, genbuf, (size_t)LBSIZE) == EOF) {
                    385:                        Typeout("There is no documentation for \"%s\".", dp->Name);
                    386:                        break;
                    387:                }
                    388:                if (genbuf[0] == ':' && LookingAt(pattern, genbuf, 0)) {
                    389:                        /* found it ... let's print it */
                    390:                        if (doc_type == var_type)
                    391:                                Typeout(dp->Name);
                    392:                        else if (doc_type == cmd_type) {
                    393:                                char    binding[128];
                    394: 
                    395:                                find_binds(dp, binding);
                    396:                                if (blnkp(binding))
                    397:                                        Typeout("To invoke %s, type \"ESC X %s<cr>\".",
                    398:                                                dp->Name, dp->Name);
                    399:                                else
                    400:                                        Typeout("Type \"%s\" to invoke %s.",
                    401:                                                binding, dp->Name);
                    402:                        }
                    403:                        Typeout("");
                    404:                        while (f_gets(fp, genbuf, (size_t)LBSIZE) != EOF
                    405:                        && strncmp(genbuf, ":entry", (size_t)6) != 0) {
                    406:                                Typeout("%s", genbuf);
                    407:                        }
                    408:                        break;
                    409:                }
                    410:        }
                    411:        f_close(fp);
                    412:        TOstop();
                    413: }
                    414: 
                    415: 
                    416: void
                    417: Apropos()
                    418: {
                    419:        register const struct cmd       *cp;
                    420:        register struct macro   *m;
                    421:        register const struct variable  *v;
                    422:        register List   *klp;
                    423:        char    *ans;
                    424:        int     anyfs = NO,
                    425:                anyvs = NO,
                    426:                anyms = NO,
                    427:                anykms = NO;
                    428:        char    buf[256];
                    429: 
                    430:        ans = ask((char *) 0, ": %f (keyword) ");
                    431:        TOstart("Help", TRUE);
                    432:        for (cp = commands; cp->Name != 0; cp++)
                    433:                if (sindex(ans, cp->Name)) {
                    434:                        if (anyfs == NO) {
                    435:                                Typeout("Commands");
                    436:                                Typeout("--------");
                    437:                                anyfs = YES;
                    438:                        }
                    439:                        find_binds((data_obj *) cp, buf);
                    440:                        if (buf[0])
                    441:                                Typeout(": %-35s (%s)", cp->Name, buf);
                    442:                        else
                    443:                                Typeout(": %s", cp->Name);
                    444:                }
                    445:        if (anyfs == YES)
                    446:                Typeout(NullStr);
                    447:        for (v = variables; v->Name != 0; v++)
                    448:                if (sindex(ans, v->Name)) {
                    449:                        if (anyvs == NO) {
                    450:                                Typeout("Variables");
                    451:                                Typeout("---------");
                    452:                                anyvs = YES;
                    453:                        }
                    454:                        vpr_aux(v, buf);
                    455:                        Typeout(": set %-26s %s", v->Name, buf);
                    456:                }
                    457:        if (anyvs == YES)
                    458:                Typeout(NullStr);
                    459:        for (m = macros; m != 0; m = m->m_nextm)
                    460:                if (sindex(ans, m->Name)) {
                    461:                        if (anyms == NO) {
                    462:                                Typeout("Macros");
                    463:                                Typeout("------");
                    464:                                anyms = YES;
                    465:                        }
                    466:                        find_binds((data_obj *) m, buf);
                    467:                        if (buf[0])
                    468:                                Typeout(": %-35s (%s)", m->Name, buf);
                    469:                        else
                    470:                                Typeout(": %-35s %s", "execute-macro", m->Name);
                    471:                }
                    472:        if (anyms == YES)
                    473:                Typeout(NullStr);
                    474:        for (klp = keymaps; klp; klp = list_next(klp)) {
                    475:                register struct keymap *km = (struct keymap *)list_data(klp);
                    476: 
                    477:                if (sindex(ans, km->Name)) {
                    478:                        if (anykms == NO) {
                    479:                                Typeout("Keymaps");
                    480:                                Typeout("-------");
                    481:                                anykms = YES;
                    482:                        }
                    483:                        find_binds((data_obj *) km, buf);
                    484:                        if (buf[0])
                    485:                                Typeout(": %-35s (%s)", km->Name, buf);
                    486:                        else
                    487:                                Typeout(": %s", km->Name);
                    488:                }
                    489:        }
                    490:        TOstop();
                    491: }
                    492: 
                    493: #ifdef NEVER_USED
                    494: private char *
                    495: km_newname()
                    496: {
                    497:        char    buffer[128];
                    498:        static int      km_count = 1;
                    499: 
                    500:        swritef(buffer, "keymap-%d", km_count++);
                    501:        return copystr(buffer);
                    502: }
                    503: #endif
                    504: 
                    505: void
                    506: InitKeymaps()
                    507: {
                    508:        struct keymap   *km;
                    509: 
                    510:        mainmap = km_new(copystr("mainmap"), MainKeys);
                    511: 
                    512:        /* setup ESC map */
                    513:        km = km_new(copystr("ESC-map"), EscKeys);
                    514:        km_setkey(mainmap, ESC, (data_obj *) km);
                    515: 
                    516:        /* setup Ctlx map */
                    517:        km = km_new(copystr("CTLX-map"), CtlxKeys);
                    518:        km_setkey(mainmap, CTL('X'), (data_obj *) km);
                    519: }
                    520: 
                    521: void
                    522: MakeKMap()
                    523: {
                    524:        char    *name;
                    525: 
                    526:        name = ask((char *) 0, ProcFmt);
                    527:        (void) km_new(copystr(name), (data_obj **) 0);
                    528: }
                    529: 
                    530: private data_obj *
                    531: findmap(fmt)
                    532: char   *fmt;
                    533: {
                    534:        List    *lp;
                    535:        char    *strings[128];
                    536:        int     i;
                    537: 
                    538:        for (lp = keymaps, i = 0; lp != 0; lp = list_next(lp))
                    539:                strings[i++] = ((struct keymap *) list_data(lp))->Name;
                    540:        strings[i] = 0;
                    541: 
                    542:        i = complete(strings, fmt, 0);
                    543:        if (i < 0)
                    544:                return 0;
                    545:        lp = keymaps;
                    546:        while (--i >= 0)
                    547:                lp = list_next(lp);
                    548:        return (data_obj *) list_data(lp);
                    549: }
                    550: 
                    551: #ifdef IPROCS
                    552: private void
                    553: mk_proc_km()
                    554: {
                    555:        procsmap = km_new("process-keymap", (data_obj **) 0);
                    556: }
                    557: 
                    558: void
                    559: ProcBind()
                    560: {
                    561:        data_obj        *d;
                    562: 
                    563:        if (procsmap == 0)
                    564:                mk_proc_km();
                    565: 
                    566:        if ((d = findcom(ProcFmt)) == 0)
                    567:                return;
                    568:        s_mess(": %f %s ", d->Name);
                    569:        BindWMap(procsmap, EOF, d);
                    570: }
                    571: 
                    572: void
                    573: ProcKmBind()
                    574: {
                    575:        data_obj        *d;
                    576: 
                    577:        if (procsmap == 0)
                    578:                mk_proc_km();
                    579:        if ((d = findmap(ProcFmt)) == 0)
                    580:                return;
                    581:        s_mess(": %f %s ", d->Name);
                    582:        BindWMap(procsmap, EOF, d);
                    583: }
                    584: 
                    585: #endif
                    586: 
                    587: void
                    588: KmBind()
                    589: {
                    590:        BindSomething(findmap, mainmap);
                    591: }
                    592: 
                    593: void
                    594: dispatch(c)
                    595: register int   c;
                    596: {
                    597:        data_obj        *cp;
                    598:        struct keymap   *maps[10];      /* never more than 10 active
                    599:                                           maps at a time, I promise */
                    600:        int     nmaps;
                    601: 
                    602:        this_cmd = 0;
                    603:        nmaps = get_keymaps(maps);
                    604: 
                    605:        for (;;) {
                    606:                int     i,
                    607:                        nvalid,
                    608:                        slow = NO;
                    609: 
                    610:                for (i = 0, nvalid = 0; i < nmaps; i++) {
                    611:                        if (maps[i] == 0)
                    612:                                continue;
                    613:                        cp = km_getkey(maps[i], c);
                    614:                        if (cp != 0) {
                    615:                                if (obj_type(cp) != KEYMAP) {
                    616:                                        ExecCmd(cp);
                    617:                                        return;
                    618:                                }
                    619:                                nvalid += 1;
                    620:                        }
                    621:                        maps[i] = (struct keymap *) cp;
                    622:                }
                    623:                if (nvalid == 0) {
                    624:                        char    strokes[128];
                    625: 
                    626:                        pp_key_strokes(strokes, sizeof (strokes));
                    627:                        s_mess("[%sunbound]", strokes);
                    628:                        rbell();
                    629:                        clr_arg_value();
                    630:                        errormsg = NO;
                    631:                        return;
                    632:                }
                    633: 
                    634:                c = waitchar(&slow);
                    635:                if (c == AbortChar) {
                    636:                        message("[Aborted]");
                    637:                        rbell();
                    638:                        return;
                    639:                }
                    640:        }
                    641: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.