diff --git a/bind.c b/bind.c index 9734e3c..b2c7ba7 100644 --- a/bind.c +++ b/bind.c @@ -36,7 +36,6 @@ static int buildlist( char *mstring) ; static void cmdstr( int c, char *seq) ; static unsigned int getckey( int mflag) ; static unsigned int stock( char *keyname) ; -static boolean unbindchar( unsigned c) ; static const char *getfname( unsigned keycode, char *failmsg) ; @@ -123,7 +122,7 @@ BINDABLE( bindtokey) { /* get the command sequence to bind */ boolean prefix_f = (kfunc == metafn) || (kfunc == cex) || (kfunc == unarg) || (kfunc == ctrlg) ; - unsigned c = getckey( prefix_f) ; + int c = getckey( prefix_f) ; /* change it to something we can print as well */ cmdstr( c, outseq) ; @@ -131,12 +130,26 @@ BINDABLE( bindtokey) { /* and dump it out */ ostring( outseq) ; +/* key sequence can't be an active prefix key */ + if( c == metac || c == ctlxc || c == reptc || c == abortc) { + if( (c == metac && kfunc == metafn) + || (c == ctlxc && kfunc == cex) + || (c == reptc && kfunc == unarg) + || (c == abortc && kfunc == ctrlg)) + return TRUE ; + + mlwrite( "(Can't bind to active prefix)") ; + return FALSE ; + } + /* if the function is a prefix key */ if( prefix_f) { - /* search and remove all existing binding for the prefix */ + /* remove existing binding for the prefix */ for( ktp = keytab ; ktp->k_code != 0 ; ktp++) - if( ktp->k_nbp == nbp) - unbindchar( ktp->k_code) ; + if( ktp->k_nbp == nbp) { + delkeybinding( ktp->k_code) ; + break ; + } /* set the appropriate global prefix variable */ if( kfunc == metafn) @@ -149,29 +162,13 @@ BINDABLE( bindtokey) { abortc = c ; } -/* search the table to see if it exists */ - for( ktp = keytab ; ktp->k_code != 0 ; ktp++) { - if( ktp->k_code == c) { - /* it exists, just change it then */ - ktp->k_nbp = nbp ; - return TRUE ; - } - } - -/* otherwise we need to add it to the end */ - /* if we run out of binding room, bitch */ - if( ktp >= &keytab[ NBINDS]) { + ktp = setkeybinding( c, nbp) ; + if( ktp->k_code == 0) { mlwrite( "Binding table FULL!") ; - return FALSE ; - } + return FALSE ; + } - ktp->k_code = c; /* add keycode */ - ktp->k_nbp = nbp ; - ++ktp; /* and make sure the next is null */ - ktp->k_code = 0; - ktp->k_nbp = NULL ; - - return TRUE; + return TRUE ; } /* @@ -180,60 +177,34 @@ BINDABLE( bindtokey) { * * int f, n; command arguments [IGNORED] */ -int unbindkey(int f, int n) -{ - int c; /* command key to unbind */ - char outseq[80]; /* output buffer for keystroke sequence */ +BINDABLE( unbindkey) { + char outseq[ 80] ; /* output buffer for keystroke sequence */ - /* prompt the user to type in a key to unbind */ - mlwrite("unbind-key: "); +/* prompt the user to type in a key to unbind */ + mlwrite( "unbind-key: ") ; - /* get the command sequence to unbind */ - c = getckey(FALSE); /* get a command sequence */ +/* get the command sequence to unbind */ + int c = getckey( FALSE) ; /* get a command sequence */ - /* change it to something we can print as well */ - cmdstr(c, &outseq[0]); +/* change it to something we can print as well */ + cmdstr( c, outseq) ; - /* and dump it out */ - ostring(outseq); +/* and dump it out */ + ostring( outseq) ; - /* if it isn't bound, bitch */ - if (unbindchar(c) == FALSE) { - mlwrite("(Key not bound)"); - return FALSE; +/* prefix key sequence can't be undound, just redefined */ + if( c == reptc || c == abortc) { + mlwrite( "(Can't unbind prefix)") ; + return FALSE ; + } + +/* if it isn't bound, bitch */ + if( delkeybinding( c) == FALSE) { + mlwrite( "(Key not bound)") ; + return FALSE ; } - return TRUE; -} - - -/* - * unbindchar() - * - * int c; command key to unbind - */ -static boolean unbindchar( unsigned c) { - key_tab *ktp ; /* pointer into the command table */ - -/* search the table to see if the key exists */ - for( ktp = keytab ; ktp->k_code != 0 ; ktp++) { - if (ktp->k_code == c) { - /* save the pointer and scan to the end of the table */ - key_tab *sav_ktp = ktp ; - while( (++ktp)->k_code != 0) ; - ktp -= 1 ; /* backup to the last legit entry */ - - /* copy the last entry to the current one */ - sav_ktp->k_code = ktp->k_code ; - sav_ktp->k_nbp = ktp->k_nbp ; - - /* null out the last one */ - ktp->k_code = 0 ; - ktp->k_nbp = NULL ; - return TRUE ; - } - } - - return FALSE ; + + return TRUE ; } #if APROP @@ -452,8 +423,10 @@ static void cmdstr( int c, char *seq) { /* apply ^X sequence if needed */ if (c & CTLX) { - *ptr++ = '^'; - *ptr++ = 'X'; + if( ctlxc & CONTROL) + *ptr++ = '^' ; + + *ptr++ = ctlxc & 0x1FFFFF ; } /* apply SPEC sequence if needed */ @@ -469,7 +442,7 @@ static void cmdstr( int c, char *seq) { /* and output the final sequence */ - *ptr++ = c & 255; /* strip the prefixes */ + *ptr++ = c & 0x1FFFFF ; /* strip the prefixes */ *ptr = 0; /* terminate the string */ } diff --git a/main.c b/main.c index ec50fa9..dd507c2 100644 --- a/main.c +++ b/main.c @@ -165,7 +165,10 @@ int main(int argc, char **argv) } /* Initialize the editor. */ - init_bindings() ; /* initialize mapping of function to name and key */ + if( !init_bindings()) { /* initialize mapping of function to name and key */ + return( EXIT_FAILURE) ; + } + vtinit(); /* Display */ mloutfmt = mlwrite ; edinit("main"); /* Buffers, windows */ diff --git a/names.c b/names.c index bb8faa1..4b94876 100644 --- a/names.c +++ b/names.c @@ -1,8 +1,6 @@ /* names.c -- implements names.h */ #include "names.h" -#define PARANOID 1 - /* Name to function binding table. * * This table gives the names of all the bindable functions and their C @@ -10,9 +8,8 @@ * command line parsing. */ -#ifdef PARANOID #include -#endif +#include #include #include "basic.h" @@ -216,7 +213,7 @@ const name_bind names[] = { {" set", setvar, CTLX | 'A'} , {" set-fill-column", setfillcol, CTLX | 'F'} , {" set-mark", (fnp_t) setmark, META | ' '} , /* M. */ - {" shell-command", spawn, CTLX | '?'} , + {" shell-command", spawn, CTLX | '!'} , {" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} , {" split-current-window", splitwind, CTLX | '2'} , {" store-macro", storemac, 0} , @@ -275,77 +272,129 @@ const name_bind names[] = { { NULL, NULL, 0} } ; -static int lastidx = 0 ; - -key_tab keytab[ NBINDS] = { - {0, NULL} -} ; +static int lastnmidx = 0 ; /* index of last name entry */ -void init_bindings( void) { +key_tab *keytab ; +static int ktsize = 140 ; /* last check: need at least 133 + 1 */ + + +boolean init_bindings( void) { +/* allocate table */ + keytab = malloc( ktsize * sizeof *keytab) ; + if( keytab == NULL) + return FALSE ; + +/* insert end of table mark */ + keytab->k_code = 0 ; + keytab->k_nbp = NULL ; + /* Add default key bindings */ - key_tab *ktp = keytab ; const name_bind *nbp ; for( nbp = names ; nbp->n_func != NULL ; nbp++) { -#ifdef PARANOID /* Check entries and strict order */ assert( (nbp->n_name != NULL) && ((nbp == names) || (0 > strcmp( bind_name( nbp - 1), bind_name( nbp))) ) ) ; -#endif /* Add key definition */ if( nbp->n_keycode) { - ktp->k_code = nbp->n_keycode ; - ktp->k_nbp = nbp ; - ktp += 1 ; + key_tab *ktp = setkeybinding( nbp->n_keycode, nbp) ; + /* check it was indeed an insertion at end of table not a + * key code re-definition */ + assert( (++ktp)->k_code == 0) ; } } /* memorize position after last valid function entry */ - lastidx = nbp - names ; + lastnmidx = nbp - names ; /* Process extra key bindings if any */ for( nbp++ ; nbp->n_func != NULL ; nbp++) { -#ifdef PARANOID /* Check entry */ assert( nbp->n_keycode && (nbp->n_name == NULL)) ; -#endif /* Look for corresponding function and add extra key binding */ const name_bind *fnbp ; for( fnbp = names ; fnbp->n_func != NULL ; fnbp++) if( fnbp->n_func == nbp->n_func) { - ktp->k_code = nbp->n_keycode ; - ktp->k_nbp = fnbp ; - ktp += 1 ; + setkeybinding( nbp->n_keycode, fnbp) ; break ; } -#ifdef PARANOID - /* Insure there is a name entry for the keycode and no double keycode */ + /* Insure there is a name entry for the keycode */ assert( fnbp->n_func != NULL) ; - int kcnt = 0 ; - for( key_tab *kktp = keytab ; kktp < ktp ; kktp++) - if( kktp->k_code == (ktp - 1)->k_code) - kcnt += 1 ; - - assert( kcnt == 1) ; -#endif } -/* Mark position after last valid key entry */ - ktp->k_code = 0 ; + return TRUE ; +} + +key_tab *setkeybinding( unsigned key, const name_bind *nbp) { + key_tab *ktp ; + +/* search the table to see if it exists */ + for( ktp = keytab ; ktp->k_code != 0 ; ktp++) + if( ktp->k_code == key) { + /* it exists, just change it then */ + ktp->k_nbp = nbp ; + return ktp ; + } + +/* otherwise we need to add it to the end */ + /* check if the end marker is at the end of the table */ + if( ktp == &keytab[ ktsize - 1]) { + /* out of binding room */ + int newsize = ktsize + 10 ; + key_tab *newkeytab = realloc( keytab, newsize * sizeof *keytab) ; + if( newkeytab == NULL) + /* out of space */ + return ktp ; + + keytab = newkeytab ; + ktp = &keytab[ ktsize - 1] ; + ktsize = newsize ; + } + + ktp->k_code = key ; /* add keycode */ + ktp->k_nbp = nbp ; + ++ktp ; /* and make sure the next is null */ + ktp->k_code = 0 ; ktp->k_nbp = NULL ; + return ktp - 1 ; +} + +boolean delkeybinding( unsigned key) { + key_tab *ktp ; /* pointer into the key binding table */ + +/* search the table to see if the key exists */ + for( ktp = keytab ; ktp->k_code != 0 ; ktp++) { + if( ktp->k_code == key) { + /* save the pointer and scan to the end of the table */ + key_tab *sav_ktp = ktp ; + while( (++ktp)->k_code != 0) ; + ktp -= 1 ; /* backup to the last legit entry */ + + /* copy the last entry to the current one */ + sav_ktp->k_code = ktp->k_code ; + sav_ktp->k_nbp = ktp->k_nbp ; + + /* null out the last one */ + ktp->k_code = 0 ; + ktp->k_nbp = NULL ; + return TRUE ; + } + } + + return FALSE ; } #define BINARY 1 const name_bind *fncmatch( char *name) { #ifdef BINARY - int found = lastidx ; + int found = lastnmidx ; int low = 0 ; int high = found - 1 ; do { diff --git a/names.h b/names.h index 1d0b4ac..11ed227 100644 --- a/names.h +++ b/names.h @@ -3,6 +3,9 @@ #ifndef _NAMES_H_ #define _NAMES_H_ +#include "retcode.h" + + /* Bindable uEMACS function pointer type and definition template */ #define BINDABLE( fname) int fname( int f, int n) @@ -26,14 +29,13 @@ typedef struct { } key_tab ; -extern const name_bind names[] ; /* name to function mapping table */ - -/* keycode to function mapping table */ -#define NBINDS 256 /* max # of bound keys */ -extern key_tab keytab[ NBINDS] ; /* key bind to functions table */ +extern const name_bind names[] ; /* name to function mapping table */ +extern key_tab *keytab ; /* key bind to functions table */ -void init_bindings( void) ; +boolean init_bindings( void) ; +key_tab *setkeybinding( unsigned key, const name_bind *nbp) ; +boolean delkeybinding( unsigned key) ; const name_bind *fncmatch( char *name) ; /* look up by name */ /* bindable functions mapped to prefix keys and hooks */