Annotation of coherent/g/usr/bin/me/execute.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * This program is in public domain; written by Dave G. Conroy.
                      3:  * This file contains the functions that bind keys to macros and functions,
                      4:  * as well as the execution of macros and functions.
                      5:  * code, for the MicroEMACS screen editor.
                      6:  */
                      7: #include       <stdio.h>
                      8: #include       "ed.h"
                      9: BIND bind;
                     10: short  *kbdm;          /* Current Macro                */
                     11: unsigned kbdlen;       /* Curent Macro len in bytes    */
                     12: short  *kbdmip;        /* Input  for above             */
                     13: short  *kbdmop;        /* Output for above             */
                     14: int    thisflag;       /* Flags, this command          */
                     15: int    lastflag;       /* Flags, last command          */
                     16: extern  char   *realloc();
                     17: extern FILE    *ffp;
                     18: /*
                     19:  * find keybinding or return NULL
                     20:  */
                     21: static KEYTAB *
                     22: findBind(c, tab)
                     23: int c;
                     24: KEYTAB *tab;
                     25: {
                     26:        register KEYTAB *ktp;
                     27:        register int i;
                     28: 
                     29:        for (i = c % HASHP; -1 != i; i = ktp->k_synonym)
                     30:                if ((ktp = tab + i)->k_code == c)
                     31:                        return (ktp);
                     32:        return (NULL);
                     33: }
                     34:        
                     35: /*
                     36:  * This is the general command execution routine.
                     37:  * It handles the fake binding of all the keys to "self-insert".
                     38:  * It also clears out the "thisflag" word, and arranges to move it
                     39:  * to the "lastflag", so that the next command can look at it.
                     40:  * Return the status of command.
                     41:  */
                     42: execute(c, f, n)
                     43: register int c;
                     44: {
                     45:        register KEYTAB *ktp;
                     46:        int     status;
                     47: 
                     48:        if ((NULL != (ktp = findBind(c, bind.table))) ||
                     49:            (NULL != (ktp = findBind((c & ~OBND), keytab)))) {
                     50:                        thisflag = 0;
                     51:                        status = (ktp->k_fun < 0) ?
                     52:                                doMac(bind.macs - (2 + ktp->k_fun), f, n) :
                     53:                                (*(funtab[ktp->k_fun].f_fp))(f, n);
                     54:                        lastflag = thisflag;
                     55:                        return (status);
                     56:        }
                     57: 
                     58:        if (c >= 0x20 && c <= 0xFF)     {       /* Self inserting.      */
                     59:                if (n <= 0) {                   /* Fenceposts.          */
                     60:                        lastflag = 0;
                     61:                        return (n<0 ? FALSE : TRUE);
                     62:                }
                     63:                thisflag = 0;                   /* For the future.      */
                     64:                status   = linsert(n, c);
                     65:                lastflag = thisflag;
                     66: 
                     67:                /*
                     68:                 * If fill column is defined perform word wrap.
                     69:                 */
                     70:                if (bind.fillcol)
                     71:                        wrapword();
                     72: 
                     73:                return (status);
                     74:        }
                     75:        lastflag = 0;                           /* Fake last flags.     */
                     76:        return (FALSE);
                     77: }
                     78: 
                     79: /*
                     80:  * Begin a keyboard macro.
                     81:  * Error if not at the top level in keyboard processing.
                     82:  * Set up variables and return.
                     83:  */
                     84: ctlxlp(f, n)
                     85: {
                     86:        if (kbdmip!=NULL) {
                     87:                mlwrite("Not now");
                     88:                return (FALSE);
                     89:        }
                     90:        if (NULL != kbdm)
                     91:                free(kbdm);
                     92:        mlwrite("[Start macro]");
                     93:        if (NULL == (kbdmip = kbdm = malloc(kbdlen = NKBDM))) {
                     94:                mlwrite("Out of space");
                     95:                return (FALSE);
                     96:        }
                     97:        return (TRUE);
                     98: }
                     99: 
                    100: /*
                    101:  * End keyboard macro.  Check for the same limit conditions as the
                    102:  * above routine.  Set up the variables and return to the caller.
                    103:  */
                    104: ctlxrp(f, n)
                    105: {
                    106:        if (kbdmip == NULL) {
                    107:                mlwrite("Not now");
                    108:                return (FALSE);
                    109:        }
                    110:        mlwrite("[End macro]");
                    111:        kbdmip[-1] = -1;                        /* unique end marker */
                    112:        *kbdmip++ = 0;
                    113:        kbdm = realloc(kbdm, kbdlen = ((char *)kbdmip) - ((char *)kbdm));
                    114:        kbdmip = NULL;
                    115:        return (TRUE);
                    116: }
                    117: 
                    118: /*
                    119:  * Execute default macro.
                    120:  */
                    121: ctlxe(f, n)
                    122: {
                    123:        if (kbdmip!=NULL) { /* close macro first */
                    124:                mlwrite("Not now");
                    125:                return (FALSE);
                    126:        }
                    127:        return (doMac(&kbdm, f, n));
                    128: }
                    129: 
                    130: /*
                    131:  * Get a keybinding and remove it.
                    132:  * return the binding.
                    133:  */
                    134: static
                    135: unBind(c)
                    136: {
                    137:        register short  i;
                    138:        register KEYTAB *ktp;
                    139: 
                    140:        mlerase();
                    141:        if (NULL == (ktp = findBind(c, bind.table)))
                    142:                return;
                    143:        if ((i = ktp->k_fun) < 0) {
                    144:                free(bind.macs[i = -(2 + i)]);
                    145:                bind.macs[i] = NULL;
                    146:                bind.maclen[i] = 0;
                    147:        }
                    148:        if (-1 != (i = ktp->k_synonym)) {
                    149:                memcpy(ktp, (bind.table + i), sizeof(*ktp));
                    150:                bind.table[i].k_code = bind.table[i].k_synonym = -1;
                    151:        }               
                    152:        else
                    153:                ktp->k_code = -1;
                    154: }
                    155: 
                    156: /*
                    157:  * Create a new binding in bind.table.
                    158:  */
                    159: static
                    160: reBind(c, i)
                    161: {
                    162:        register KEYTAB *ktp, *kh;
                    163: 
                    164:        kh = ktp = bind.table + (c % HASHP);
                    165:        if (-1 != ktp->k_code) {
                    166:                for (ktp = bind.table + MAXREB; --ktp >= bind.table; )
                    167:                        if (-1 == ktp->k_code)
                    168:                                break;
                    169:                if (ktp < bind.table) {
                    170:                        mlwrite("No free spaces in mod tab");
                    171:                        return (FALSE);
                    172:                }
                    173:                ktp->k_synonym = kh->k_synonym;
                    174:                kh->k_synonym  = ktp - bind.table;
                    175:        }
                    176:        ktp->k_code = c;
                    177:        ktp->k_fun = i;
                    178:        return (TRUE);
                    179: }
                    180: 
                    181: /*
                    182:  * Bind a function PFX1|'R' to another function.
                    183:  */
                    184: bindFun()
                    185: {
                    186:        register int c, d;
                    187:        register KEYTAB *ktp;
                    188: 
                    189:        mlwrite("Enter old keybinding ");
                    190:        d = getbind(0);
                    191:        ktp = findBind(d, keytab);
                    192:        mlwrite("Enter new keybinding ");
                    193:        if ((PFX1|'R') == (c = getbind(0))) {
                    194:                mlwrite("Cannot rebind <ctl>-x r");
                    195:                return (FALSE);
                    196:        }
                    197:        if (d == c) {
                    198:                unBind(c);
                    199:                return (TRUE);
                    200:        }
                    201:        if (NULL == ktp) {
                    202:                mlwrite("Non existant binding");
                    203:                return (FALSE);
                    204:        }
                    205:        unBind(c);
                    206:        return (reBind(c, ktp->k_fun));
                    207: }
                    208: 
                    209: /*
                    210:  * Load flexable bindings from file.
                    211:  */
                    212: loadBinds()
                    213: {
                    214:        uchar           fname[NFILEN];
                    215: 
                    216:        if (mlreply("Load bindings file: ", fname, NFILEN) != TRUE)
                    217:                return (FALSE);
                    218:        return (loadBup(fname, FALSE));
                    219: }
                    220: 
                    221: /*
                    222:  * report io error in various ways.
                    223:  */
                    224: ioTrouble(fname, startsw)
                    225: uchar *fname;
                    226: {
                    227:        switch (startsw) {
                    228:        case FALSE:     /* callec from ctl-x l */
                    229:                mlwrite("I/O toruble with %s", fname);
                    230:                return (FALSE);
                    231:        case ABORT:     /* called from -f switch */
                    232:                fprintf(stderr, "I/O trouble with %s\n", fname);
                    233:                exit(1);
                    234:        case TRUE:      /* default bindings file */
                    235:                return (TRUE);
                    236:        }
                    237: }
                    238: /*
                    239:  * Actual work of load bindings.
                    240:  */
                    241: loadBup(fname, startsw)
                    242: uchar *fname;
                    243: {
                    244:        register int i;
                    245:        short magic;
                    246: 
                    247:        if (((ffp=fopen(fname, "rb")) == NULL) ||
                    248:            (1 != fread(&magic, sizeof(magic), 1, ffp)) ||
                    249:            (magic != BINDID))
                    250:                return (ioTrouble(fname, startsw));
                    251: 
                    252:        if (1 != fread(&bind, sizeof(bind), 1, ffp))
                    253:                return (ioTrouble(fname, ABORT));
                    254:        
                    255:        for (i = 0; i < (MAXMAC + 2); i++) {
                    256:                if (NULL != bind.macs[i]) {
                    257:                        if (NULL == (bind.macs[i] = malloc(bind.maclen[i]))) {
                    258:                                mlwrite("Out of memory");
                    259:                                for (; i <= MAXMAC; i++)
                    260:                                        bind.macs[i] = NULL;
                    261:                                return (FALSE);
                    262:                        }
                    263:                        if (1 != fread(bind.macs[i], bind.maclen[i], 1, ffp))
                    264:                                return (ioTrouble(fname, ABORT));
                    265:                }
                    266:        }
                    267:        if (NULL != bind.macs[MAXMAC+1]) {
                    268:                if (NULL != kbdm)
                    269:                        free(kbdm);
                    270:                kbdmip = NULL;
                    271:                kbdm = bind.macs[MAXMAC+1];
                    272:                kbdlen = bind.maclen[MAXMAC+1];
                    273:        }
                    274:        ffclose();
                    275:        return (TRUE);
                    276: }
                    277: 
                    278: /*
                    279:  * Store flexable bindings to a file.
                    280:  */
                    281: storBinds()
                    282: {
                    283:        register int i;
                    284:        static  short magic = BINDID;
                    285:        uchar   fname[NFILEN];
                    286: 
                    287:        if (mlreply("Store bindings file: ", fname, NFILEN) != TRUE)
                    288:                return (FALSE);
                    289:        if (FIOSUC != ffwopen(fname, "wb"))
                    290:                return (FALSE);
                    291:        if (kbdmip != NULL || kbdm == NULL)     /* store closed mac only */
                    292:                bind.macs[MAXMAC+1] = NULL;
                    293:        else {
                    294:                bind.macs[MAXMAC+1]   = kbdm;
                    295:                bind.maclen[MAXMAC+1] = kbdlen;
                    296:        }
                    297:        fwrite(&magic, sizeof(magic), 1, ffp);
                    298:        fwrite(&bind, sizeof(bind), 1, ffp);
                    299:        for (i = 0; i < (MAXMAC + 2); i++)
                    300:                if (NULL != bind.macs[i])
                    301:                        fwrite(bind.macs[i], bind.maclen[i], 1, ffp);
                    302:        ffclose();
                    303: }
                    304: 
                    305: /*
                    306:  * declare macro to be a binding. PFX1|'M'
                    307:  */
                    308: nameMac()
                    309: {
                    310:        register int i, c;
                    311: 
                    312:        if (kbdmip != NULL)
                    313:                ctlxrp();
                    314:        if (kbdm == NULL) {
                    315:                mlwrite("Not now");
                    316:                return (FALSE);
                    317:        }
                    318:        mlwrite("Enter keybinding for macro ");
                    319:        if ((PFX1|'R') == (c = getbind(0))) {
                    320:                mlwrite("Cannot rebind <ctl>-x r");
                    321:                return (FALSE);
                    322:        }
                    323:        unBind(c);
                    324: 
                    325:        for (i = 0; (i < MAXMAC) && (NULL != bind.macs[i]); i++)
                    326:                ;
                    327:        if (MAXMAC == i) {
                    328:                mlwrite("Too many macros bound");
                    329:                return (FALSE);
                    330:        }
                    331:        if (reBind(c, -(i + 2)) == FALSE)
                    332:                return (FALSE);
                    333:        bind.macs[i] = kbdm;
                    334:        bind.maclen[i] = kbdlen;
                    335:        kbdm = NULL;
                    336:        kbdlen = 0;
                    337:        return (TRUE);
                    338: }
                    339: 
                    340: /*
                    341:  * Bind current macro to initialization macro.
                    342:  */
                    343: initMac()
                    344: {
                    345:        if (kbdmip!=NULL || kbdmop!=NULL) {
                    346:                mlwrite("Not now");
                    347:                return (FALSE);
                    348:        }
                    349:        bind.macs[MAXMAC] = kbdm;
                    350:        bind.maclen[MAXMAC]  = kbdlen;
                    351:        kbdm = NULL;
                    352:        kbdlen = 0;
                    353:        mlwrite("init mac bound");
                    354:        return (TRUE);
                    355: }
                    356: 
                    357: /*
                    358:  * Execute a macro.
                    359:  * The command argument is the number of times to loop.  Quit as
                    360:  * soon as a command gets an error.
                    361:  * Return TRUE if all ok, else FALSE.
                    362:  */
                    363: doMac(macro, f, n)
                    364: uchar **macro;
                    365: {
                    366:        register int    c;
                    367:        register int    af;
                    368:        register int    an;
                    369:        register int    s;
                    370:        short *kbdsav;
                    371:        uchar  *macsav;
                    372: 
                    373:        if (!n) 
                    374:                return (TRUE);
                    375:        if (NULL == (macsav = *macro)) {
                    376:                mlwrite("Not now");
                    377:                return (FALSE);
                    378:        }
                    379:        *macro = NULL;  /* prevent regress */
                    380:        kbdsav = kbdmop;
                    381:        do {
                    382:                kbdmop = macsav;
                    383:                do {
                    384:                        af = FALSE;
                    385:                        an = 1;
                    386:                        if ((c = *kbdmop++) == bind.repeat) {
                    387:                                af = TRUE;
                    388:                                an = *kbdmop++;
                    389:                                c  = *kbdmop++;
                    390:                        }
                    391:                        s = TRUE;
                    392:                } while ((c != -1) && (s = execute(c, af, an)) == TRUE);
                    393:        } while ((s == TRUE) && ((-1 == n) || --n));
                    394:        if (-1 == n)
                    395:                s = TRUE;
                    396:        kbdmop = kbdsav;
                    397:        *macro = macsav;
                    398:        return (s);
                    399: }
                    400: 
                    401: static
                    402: setpf(loc, no)
                    403: int *loc, no;
                    404: {
                    405:        mlwrite("Enter prefix character %d or space ", no);
                    406:        if (' ' != (no = getkey()))
                    407:                *loc = no;
                    408: }
                    409: 
                    410: /*
                    411:  * Set prefix characters.
                    412:  */
                    413: setPrefix()
                    414: {
                    415:        int c;
                    416: 
                    417:        setpf(&bind.pfx1, 1);
                    418:        setpf(&bind.pfx2, 2);
                    419:        setpf(&bind.pfx3, 3);
                    420:        mlwrite("Enter repeat code or space ");
                    421:        if (' ' != (c = getkey()))
                    422:                bind.repeat = c;
                    423:        mlerase();
                    424: }

unix.superglobalmegacorp.com

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