mirror of
https://github.com/rfivet/uemacs.git
synced 2024-12-18 15:26:23 -05:00
Manage key binding table dynamically.
Avoid deleting or binding to active prefix keys.
This commit is contained in:
parent
ba1bfcd0db
commit
735aefc166
123
bind.c
123
bind.c
@ -36,7 +36,6 @@ static int buildlist( char *mstring) ;
|
|||||||
static void cmdstr( int c, char *seq) ;
|
static void cmdstr( int c, char *seq) ;
|
||||||
static unsigned int getckey( int mflag) ;
|
static unsigned int getckey( int mflag) ;
|
||||||
static unsigned int stock( char *keyname) ;
|
static unsigned int stock( char *keyname) ;
|
||||||
static boolean unbindchar( unsigned c) ;
|
|
||||||
static const char *getfname( unsigned keycode, char *failmsg) ;
|
static const char *getfname( unsigned keycode, char *failmsg) ;
|
||||||
|
|
||||||
|
|
||||||
@ -123,7 +122,7 @@ BINDABLE( bindtokey) {
|
|||||||
/* get the command sequence to bind */
|
/* get the command sequence to bind */
|
||||||
boolean prefix_f = (kfunc == metafn) || (kfunc == cex) ||
|
boolean prefix_f = (kfunc == metafn) || (kfunc == cex) ||
|
||||||
(kfunc == unarg) || (kfunc == ctrlg) ;
|
(kfunc == unarg) || (kfunc == ctrlg) ;
|
||||||
unsigned c = getckey( prefix_f) ;
|
int c = getckey( prefix_f) ;
|
||||||
|
|
||||||
/* change it to something we can print as well */
|
/* change it to something we can print as well */
|
||||||
cmdstr( c, outseq) ;
|
cmdstr( c, outseq) ;
|
||||||
@ -131,12 +130,26 @@ BINDABLE( bindtokey) {
|
|||||||
/* and dump it out */
|
/* and dump it out */
|
||||||
ostring( outseq) ;
|
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 the function is a prefix key */
|
||||||
if( prefix_f) {
|
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++)
|
for( ktp = keytab ; ktp->k_code != 0 ; ktp++)
|
||||||
if( ktp->k_nbp == nbp)
|
if( ktp->k_nbp == nbp) {
|
||||||
unbindchar( ktp->k_code) ;
|
delkeybinding( ktp->k_code) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
/* set the appropriate global prefix variable */
|
/* set the appropriate global prefix variable */
|
||||||
if( kfunc == metafn)
|
if( kfunc == metafn)
|
||||||
@ -149,29 +162,13 @@ BINDABLE( bindtokey) {
|
|||||||
abortc = c ;
|
abortc = c ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search the table to see if it exists */
|
ktp = setkeybinding( c, nbp) ;
|
||||||
for( ktp = keytab ; ktp->k_code != 0 ; ktp++) {
|
if( ktp->k_code == 0) {
|
||||||
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]) {
|
|
||||||
mlwrite( "Binding table FULL!") ;
|
mlwrite( "Binding table FULL!") ;
|
||||||
return FALSE ;
|
return FALSE ;
|
||||||
}
|
}
|
||||||
|
|
||||||
ktp->k_code = c; /* add keycode */
|
return TRUE ;
|
||||||
ktp->k_nbp = nbp ;
|
|
||||||
++ktp; /* and make sure the next is null */
|
|
||||||
ktp->k_code = 0;
|
|
||||||
ktp->k_nbp = NULL ;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -180,60 +177,34 @@ BINDABLE( bindtokey) {
|
|||||||
*
|
*
|
||||||
* int f, n; command arguments [IGNORED]
|
* int f, n; command arguments [IGNORED]
|
||||||
*/
|
*/
|
||||||
int unbindkey(int f, int n)
|
BINDABLE( unbindkey) {
|
||||||
{
|
char outseq[ 80] ; /* output buffer for keystroke sequence */
|
||||||
int c; /* command key to unbind */
|
|
||||||
char outseq[80]; /* output buffer for keystroke sequence */
|
|
||||||
|
|
||||||
/* prompt the user to type in a key to unbind */
|
/* prompt the user to type in a key to unbind */
|
||||||
mlwrite("unbind-key: ");
|
mlwrite( "unbind-key: ") ;
|
||||||
|
|
||||||
/* get the command sequence to unbind */
|
/* get the command sequence to unbind */
|
||||||
c = getckey(FALSE); /* get a command sequence */
|
int c = getckey( FALSE) ; /* get a command sequence */
|
||||||
|
|
||||||
/* change it to something we can print as well */
|
/* change it to something we can print as well */
|
||||||
cmdstr(c, &outseq[0]);
|
cmdstr( c, outseq) ;
|
||||||
|
|
||||||
/* and dump it out */
|
/* and dump it out */
|
||||||
ostring(outseq);
|
ostring( outseq) ;
|
||||||
|
|
||||||
/* if it isn't bound, bitch */
|
|
||||||
if (unbindchar(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 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* prefix key sequence can't be undound, just redefined */
|
||||||
|
if( c == reptc || c == abortc) {
|
||||||
|
mlwrite( "(Can't unbind prefix)") ;
|
||||||
return FALSE ;
|
return FALSE ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if it isn't bound, bitch */
|
||||||
|
if( delkeybinding( c) == FALSE) {
|
||||||
|
mlwrite( "(Key not bound)") ;
|
||||||
|
return FALSE ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if APROP
|
#if APROP
|
||||||
@ -452,8 +423,10 @@ static void cmdstr( int c, char *seq) {
|
|||||||
|
|
||||||
/* apply ^X sequence if needed */
|
/* apply ^X sequence if needed */
|
||||||
if (c & CTLX) {
|
if (c & CTLX) {
|
||||||
*ptr++ = '^';
|
if( ctlxc & CONTROL)
|
||||||
*ptr++ = 'X';
|
*ptr++ = '^' ;
|
||||||
|
|
||||||
|
*ptr++ = ctlxc & 0x1FFFFF ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply SPEC sequence if needed */
|
/* apply SPEC sequence if needed */
|
||||||
@ -469,7 +442,7 @@ static void cmdstr( int c, char *seq) {
|
|||||||
|
|
||||||
/* and output the final sequence */
|
/* and output the final sequence */
|
||||||
|
|
||||||
*ptr++ = c & 255; /* strip the prefixes */
|
*ptr++ = c & 0x1FFFFF ; /* strip the prefixes */
|
||||||
|
|
||||||
*ptr = 0; /* terminate the string */
|
*ptr = 0; /* terminate the string */
|
||||||
}
|
}
|
||||||
|
5
main.c
5
main.c
@ -165,7 +165,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the editor. */
|
/* 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 */
|
vtinit(); /* Display */
|
||||||
mloutfmt = mlwrite ;
|
mloutfmt = mlwrite ;
|
||||||
edinit("main"); /* Buffers, windows */
|
edinit("main"); /* Buffers, windows */
|
||||||
|
117
names.c
117
names.c
@ -1,8 +1,6 @@
|
|||||||
/* names.c -- implements names.h */
|
/* names.c -- implements names.h */
|
||||||
#include "names.h"
|
#include "names.h"
|
||||||
|
|
||||||
#define PARANOID 1
|
|
||||||
|
|
||||||
/* Name to function binding table.
|
/* Name to function binding table.
|
||||||
*
|
*
|
||||||
* This table gives the names of all the bindable functions and their C
|
* This table gives the names of all the bindable functions and their C
|
||||||
@ -10,9 +8,8 @@
|
|||||||
* command line parsing.
|
* command line parsing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef PARANOID
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#endif
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
@ -216,7 +213,7 @@ const name_bind names[] = {
|
|||||||
{" set", setvar, CTLX | 'A'} ,
|
{" set", setvar, CTLX | 'A'} ,
|
||||||
{" set-fill-column", setfillcol, CTLX | 'F'} ,
|
{" set-fill-column", setfillcol, CTLX | 'F'} ,
|
||||||
{" set-mark", (fnp_t) setmark, META | ' '} , /* M. */
|
{" set-mark", (fnp_t) setmark, META | ' '} , /* M. */
|
||||||
{" shell-command", spawn, CTLX | '?'} ,
|
{" shell-command", spawn, CTLX | '!'} ,
|
||||||
{" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} ,
|
{" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} ,
|
||||||
{" split-current-window", splitwind, CTLX | '2'} ,
|
{" split-current-window", splitwind, CTLX | '2'} ,
|
||||||
{" store-macro", storemac, 0} ,
|
{" store-macro", storemac, 0} ,
|
||||||
@ -275,77 +272,129 @@ const name_bind names[] = {
|
|||||||
{ NULL, NULL, 0}
|
{ NULL, NULL, 0}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
static int lastidx = 0 ;
|
static int lastnmidx = 0 ; /* index of last name entry */
|
||||||
|
|
||||||
key_tab keytab[ NBINDS] = {
|
|
||||||
{0, NULL}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
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 */
|
/* Add default key bindings */
|
||||||
key_tab *ktp = keytab ;
|
|
||||||
const name_bind *nbp ;
|
const name_bind *nbp ;
|
||||||
for( nbp = names ; nbp->n_func != NULL ; nbp++) {
|
for( nbp = names ; nbp->n_func != NULL ; nbp++) {
|
||||||
#ifdef PARANOID
|
|
||||||
/* Check entries and strict order */
|
/* Check entries and strict order */
|
||||||
assert( (nbp->n_name != NULL) &&
|
assert( (nbp->n_name != NULL) &&
|
||||||
((nbp == names) ||
|
((nbp == names) ||
|
||||||
(0 > strcmp( bind_name( nbp - 1), bind_name( nbp)))
|
(0 > strcmp( bind_name( nbp - 1), bind_name( nbp)))
|
||||||
)
|
)
|
||||||
) ;
|
) ;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add key definition */
|
/* Add key definition */
|
||||||
if( nbp->n_keycode) {
|
if( nbp->n_keycode) {
|
||||||
ktp->k_code = nbp->n_keycode ;
|
key_tab *ktp = setkeybinding( nbp->n_keycode, nbp) ;
|
||||||
ktp->k_nbp = nbp ;
|
/* check it was indeed an insertion at end of table not a
|
||||||
ktp += 1 ;
|
* key code re-definition */
|
||||||
|
assert( (++ktp)->k_code == 0) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* memorize position after last valid function entry */
|
/* memorize position after last valid function entry */
|
||||||
lastidx = nbp - names ;
|
lastnmidx = nbp - names ;
|
||||||
|
|
||||||
/* Process extra key bindings if any */
|
/* Process extra key bindings if any */
|
||||||
for( nbp++ ; nbp->n_func != NULL ; nbp++) {
|
for( nbp++ ; nbp->n_func != NULL ; nbp++) {
|
||||||
#ifdef PARANOID
|
|
||||||
/* Check entry */
|
/* Check entry */
|
||||||
assert( nbp->n_keycode && (nbp->n_name == NULL)) ;
|
assert( nbp->n_keycode && (nbp->n_name == NULL)) ;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Look for corresponding function and add extra key binding */
|
/* Look for corresponding function and add extra key binding */
|
||||||
const name_bind *fnbp ;
|
const name_bind *fnbp ;
|
||||||
for( fnbp = names ; fnbp->n_func != NULL ; fnbp++)
|
for( fnbp = names ; fnbp->n_func != NULL ; fnbp++)
|
||||||
if( fnbp->n_func == nbp->n_func) {
|
if( fnbp->n_func == nbp->n_func) {
|
||||||
ktp->k_code = nbp->n_keycode ;
|
setkeybinding( nbp->n_keycode, fnbp) ;
|
||||||
ktp->k_nbp = fnbp ;
|
|
||||||
ktp += 1 ;
|
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PARANOID
|
/* Insure there is a name entry for the keycode */
|
||||||
/* Insure there is a name entry for the keycode and no double keycode */
|
|
||||||
assert( fnbp->n_func != NULL) ;
|
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 */
|
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_code = 0 ;
|
||||||
ktp->k_nbp = NULL ;
|
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
|
#define BINARY 1
|
||||||
|
|
||||||
const name_bind *fncmatch( char *name) {
|
const name_bind *fncmatch( char *name) {
|
||||||
#ifdef BINARY
|
#ifdef BINARY
|
||||||
int found = lastidx ;
|
int found = lastnmidx ;
|
||||||
int low = 0 ;
|
int low = 0 ;
|
||||||
int high = found - 1 ;
|
int high = found - 1 ;
|
||||||
do {
|
do {
|
||||||
|
12
names.h
12
names.h
@ -3,6 +3,9 @@
|
|||||||
#ifndef _NAMES_H_
|
#ifndef _NAMES_H_
|
||||||
#define _NAMES_H_
|
#define _NAMES_H_
|
||||||
|
|
||||||
|
#include "retcode.h"
|
||||||
|
|
||||||
|
|
||||||
/* Bindable uEMACS function pointer type and definition template */
|
/* Bindable uEMACS function pointer type and definition template */
|
||||||
#define BINDABLE( fname) int fname( int f, int n)
|
#define BINDABLE( fname) int fname( int f, int n)
|
||||||
|
|
||||||
@ -27,13 +30,12 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
extern const name_bind names[] ; /* name to function mapping table */
|
extern const name_bind names[] ; /* name to function mapping table */
|
||||||
|
extern key_tab *keytab ; /* key bind to functions table */
|
||||||
/* keycode to function mapping table */
|
|
||||||
#define NBINDS 256 /* max # of bound keys */
|
|
||||||
extern key_tab keytab[ NBINDS] ; /* 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 */
|
const name_bind *fncmatch( char *name) ; /* look up by name */
|
||||||
|
|
||||||
/* bindable functions mapped to prefix keys and hooks */
|
/* bindable functions mapped to prefix keys and hooks */
|
||||||
|
Loading…
Reference in New Issue
Block a user