Annotation of coherent/g/usr/bin/me/execute.c, revision 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.