home *** CD-ROM | disk | FTP | other *** search
- /*{{{}}}*/
- /*{{{ #includes*/
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
-
- #define KEYTAB_C
-
- #include "keybind.h"
- #include <h/rcformat.h>
- #include <h/envvar_str.h>
- #include <lib/ori_rc_lib.h>
- #include <lib/ori_add_lib.h>
- /*}}} */
-
- /*{{{ overload prefix handling*/
- typedef struct overload_entry
- { char *name;
- int len;
- struct overload_entry *next;
- } overload_entry;
- private overload_entry *overloads=0;
-
- /*{{{ overload_prefix*/
- public void overload_prefix(void)
- {
- begin_parse();
- for (;;)
- { switch (get_full_token())
- { case END: break;
- /*{{{ NAME: a new mode*/
- case NAME:
- { overload_entry *x;
- /*{{{ check, if conflicting*/
- { int l;
- for (x=overloads,l=ustrlen(tk_string);x;x=x->next)
- if (!strncmp((char*)tk_string,x->name,(x->len<l)?x->len:l))
- m_exit(F_OVER_CON,tk_string,x->name);
- }
- /*}}} */
- /*{{{ new node*/
- x=kbd_malloc(sizeof(overload_entry)+ustrlen(tk_string)+1);
- strcpy(x->name=(char*)(x+1),(char*)tk_string);
- x->len=ustrlen(tk_string);
- x->next=overloads;
- overloads=x;
- if (verbose_level>0)
- fprintf(stderr,F_OVER_PRE,tk_string);
- /*}}} */
- continue;
- }
- /*}}} */
- /*{{{ error*/
- default:
- m_exit(M_OVER_ERR);
- /*}}} */
- }
- break;
- }
- end_parse(M_WANTEND);
- }
- /*}}} */
- /*{{{ cut_overload*/
- public unsigned char const *cut_overload(unsigned char const *name)
- { overload_entry *x;
-
- for (x=overloads;x;x=x->next)
- if (!strncmp((char*)name,x->name,x->len))
- return(name+x->len);
-
- return(name);
- }
- /*}}} */
- /*}}} */
- /*{{{ mouse handling*/
- typedef struct
- { unsigned char* name;
- unsigned char* code;
- int code_lg;
- } mouse_supports;
- private boolean mouse=False;
- private mouse_supports m_list[]=
- /*{{{ init values*/
- { {(unsigned char*)"scann",(unsigned char*)0,0},
- # ifdef XTERM
- { (unsigned char*)XTERM_MOUSE_NAME,(unsigned char*)XTERM_MOUSE_CODE,XTERM_MOUSE_LG },
- # endif
- # ifdef MGR
- { (unsigned char*)MGR_MOUSE_NAME,(unsigned char*)MGR_MOUSE_CODE,MGR_MOUSE_LG },
- # endif
- # ifdef OS_MOUSE_TAG
- { (unsigned char*)OS_MOUSE_NAME,(unsigned char*)OS_MOUSE_CODE,OS_MOUSE_LG },
- # endif
- { (unsigned char*)NO_MOUSE,(unsigned char*)0,0 },
- { (unsigned char*)0,(unsigned char*)0,0 }
- };
- /*}}} */
- public unsigned char *m_name=(unsigned char*)DEFAULT_MOUSE;
-
- /*{{{ init_mouse*/
- private void init_mouse(void)
- { mouse_supports *x=m_list;
-
- do
- if (!strncmp((char*)x->name,(char*)m_name,ustrlen(x->name)))
- return;
- while ((x++)->name);
-
- /*{{{ error exit*/
- fprintf(stderr,"unknown mouse set\n");
- fprintf(stderr,M_MICE);
- show_mice(stderr);
- fputc('\n',stderr);
- kbd_exit(1);
- /*}}} */
- }
- /*}}} */
- /*{{{ show_mice*/
- public void show_mice(FILE *f)
- { mouse_supports *x=m_list;
- boolean first=True;
-
- fprintf(f,"%s(",m_name);
- while (x->name) { fprintf(f,first?"%s":",%s",(x++)->name);first=False; }
- fprintf(f,")");
- }
- /*}}} */
- /*{{{ mouse_code*/
- public void mouse_code(void)
- { tokens token;
- int i=0;
- TOKEN map[MAX_MOUSE_BUTTONS];
-
- /*{{{ multiple mouse?*/
- if (mouse)
- m_exit(M_MOUSE);
- mouse=True;
- /*}}} */
- while ((token=get_full_token())!=END)
- /*{{{ handle a button*/
- { if (token==OPCODE)
- /*{{{ opcode*/
- { if ((map[i]=tk_key->num)!=O_NOP)
- write_bind
- ( tk_key->name,
- (unsigned char*)(REF_COUNT_BASE+i),
- mouse_kbd
- );
- }
- /*}}} */
- else if (token==MACRO && ustrlen(tk_string)==1)
- /*{{{ simple*/
- { unsigned char simple[3];
-
- simple[0]='\"';
- simple[1]=map[i]=tk_string[0];
- simple[2]='\0';
- write_bind
- ( simple,
- (unsigned char*)(REF_COUNT_BASE+i),
- mouse_kbd
- );
- }
- /*}}} */
- else if (token==OPERATION)
- /*{{{ operation*/
- { TOKEN k;
-
- if (tk_operation->place>=0)
- k=(TOKEN)((int)O_EXE_MACRO+tk_operation->place);
- else if (tk_operation->length==1)
- k=tk_operation->ops[0];
- else
- m_exit(M_NODEBOUND);
- if ((map[i]=k)!=O_NOP)
- write_bind
- ( tk_operation->op_name,
- (unsigned char*)(REF_COUNT_BASE+i),
- mouse_kbd
- );
- }
- /*}}} */
- else
- /*{{{ error*/
- m_exit(M_NOCOMMAND);
- /*}}} */
- if (++i==MAX_MOUSE_BUTTONS)
- /*{{{ memory-crash*/
- m_exit(M_NOMEMORY);
- /*}}} */
- }
- /*}}} */
- write_buttons_rc(map,i);
- }
- /*}}} */
- /*}}} */
- /*{{{ alias handling*/
- /*{{{ ALIAS_LIST*/
- typedef struct ALIAS_LIST
- { const unsigned char *key_name;
- struct acl
- { int length;
- struct acl *next;
- TOKEN codes[1];
- } *code;
- struct ALIAS_LIST *next;
- } ALIAS_LIST;
- /*}}} */
- private const ALIAS_LIST init_al_list={ undef,0,0 };
- private ALIAS_LIST *alias_list=(ALIAS_LIST*)&init_al_list;
-
- /*{{{ create an alias entry*/
- private void creat_alias(unsigned char *name,int lg,TOKEN *code)
- { ALIAS_LIST *ap;
-
- for (ap=alias_list;;ap=ap->next)
- if (!ap)
- /*{{{ unknown alias -> new node*/
- {
- /*{{{ new node at head of alias list*/
- ap=kbd_malloc(sizeof(ALIAS_LIST));
- ap->next=alias_list;
- alias_list=ap;
- /*}}} */
- /*{{{ no sequences till now*/
- ap->code=0;
- /*}}} */
- /*{{{ name in node*/
- ap->key_name=mstrcpy(name);
- /*}}} */
- break;
- }
- /*}}} */
- else if (!ustrcmp(name,ap->key_name))
- /*{{{ break, alias uses more than one sequence*/
- { if (warning)
- { error_po();
- fprintf(stderr,F_2ALIAS,name);
- }
- break;
- }
- /*}}} */
- /*{{{ code in node*/
- { struct acl *x;
-
- x=kbd_malloc(sizeof(struct acl)+(lg-1)*sizeof(TOKEN));
- x->next=ap->code;
- ap->code=x;
- x->length=lg;
- memcpy(x->codes,code,lg*sizeof(TOKEN));
- }
- /*}}} */
- if (verbose_level>1)
- fprintf(stderr,F_ALIAS,name);
- }
- /*}}} */
- /*{{{ init alias list*/
- public void init_alias(void)
- { TOKEN esc=033;
-
- creat_alias((unsigned char*)"esc",1,&esc);
- }
- /*}}} */
- /*}}} */
- /*{{{ keytables*/
- /*{{{ types*/
- /*{{{ KEY_LONG*/
- typedef struct kl_struct
- { union
- { int id;
- struct kl_struct *hash;
- } x;
- TOKEN code;
- TOKEN key;
- struct kl_struct *next;
- struct kl_struct *n_level;
- } KEY_LONG;
- /*}}} */
- /*{{{ TERMINALS*/
- typedef struct t_lst
- { unsigned char tname[NAME_LG+1];
- int id;
- struct t_lst *next;
- } TERMINALS;
- /*}}} */
- /*{{{ KEYTABLE*/
- typedef struct kt
- { int id;
- unsigned char mode[NAME_LG+1];
- boolean def;
- struct ktbl
- { TERMINALS *t;
- KEY_LONG *top_level;
- int mark;
- struct ktbl *next;
- } keys;
- struct kt *next;
- } KEYTABLE;
- /*}}} */
- /*{{{ KEYSEQUENCE*/
- typedef struct
- { unsigned char protocol[NAME_LG+1];
- struct ksl
- { TERMINALS *t;
- int lg;
- TOKEN codes[ALIAS_LG];
- struct ksl *next;
- } *key_list;
- } KEYSEQUENCE;
- /*}}} */
- /*}}} */
- /*{{{ variables*/
- /* do not change DEF_TERM, origami needs the empty word for detecting */
- /* the default table! */
- /* do not change DEF_MODE_ID, origami uses this table as startup table! */
- #define DEF_TERM ""
- #define DEF_TERM_ID 0
- #define DEF_MODE ""
- #define DEF_MODE_ID 0
-
- private unsigned char const def_term_name[]=DEF_TERM;
- private TERMINALS const def_terminal={ DEF_TERM,DEF_TERM_ID,0 };
- private TERMINALS *term_list= (TERMINALS*)&def_terminal;
- private int last_used_term_id=DEF_TERM_ID;
-
- private unsigned char const def_mode_name[]=DEF_MODE;
- private KEYTABLE *key_table_list=0;
- private int last_ktbl_id=DEF_MODE_ID;
-
- private boolean ab_set=False;
- private boolean def_kbd_used=False;
- private int modes_used;
- private int bind_help_id=usr_kbd;
- /*}}} */
-
- /*{{{ struct ksl mallocing*/
- private struct ksl *ksl_f_list=0;
-
- /*{{{ ks_malloc*/
- private struct ksl *ks_malloc(void)
- {
- struct ksl *k;
-
- if ((k=ksl_f_list))
- ksl_f_list=k->next;
- else
- k=kbd_malloc(sizeof(struct ksl));
-
- return(k);
- }
- /*}}} */
- /*{{{ ks_free*/
- private void ks_free(struct ksl *kl)
- {
- kl->next=ksl_f_list;
- ksl_f_list=kl;
- }
- /*}}} */
- /*{{{ ksl_free*/
- private void ksl_free(struct ksl *kl)
- {
- for (;kl;)
- { struct ksl *kl1;
-
- kl1=kl->next;
- ks_free(kl);
- kl=kl1;
- }
- }
- /*}}} */
- /*}}} */
- /*{{{ TERMINALS mallocing*/
- private TERMINALS *t_f_list=0;
-
- /*{{{ t_malloc*/
- private TERMINALS *t_malloc(void)
- {
- TERMINALS *t;
-
- if ((t=t_f_list))
- t_f_list=t->next;
- else
- t=kbd_malloc(sizeof(TERMINALS));
-
- return(t);
- }
- /*}}} */
- /*{{{ t_free*/
- private void t_free(TERMINALS *t)
- {
- t->next=t_f_list;
- t_f_list=t;
- }
- /*}}} */
- /*{{{ tl_free*/
- private void tl_free(TERMINALS *t)
- {
- while (t)
- { TERMINALS *tx;
-
- tx=t->next;
- t_free(t);
- t=tx;
- }
- }
- /*}}} */
- /*}}} */
-
- /*{{{ name2terminal*/
- private TERMINALS *name2terminal(unsigned char const * const term)
- {
- TERMINALS *t;
-
- for (t=term_list;;t=t->next)
- if (!t)
- /*{{{ define new terminal*/
- { t=t_malloc();
- ustrcpy(t->tname,term);
- t->id=++last_used_term_id;
- t->next=term_list;
- term_list=t;
- break;
- }
- /*}}} */
- else if (!ustrcmp(term,t->tname))
- break;
-
- return(t);
- }
- /*}}} */
- /*{{{ name2mode*/
- private KEYTABLE *name2mode(unsigned char const*const s)
- {
- KEYTABLE *x;
-
- for (x=key_table_list;;x=x->next)
- if (!x || !ustrcmp(s,x->mode))
- break;
-
- return(x);
- }
- /*}}} */
- /*{{{ id2mode*/
- private KEYTABLE *id2mode(int id)
- {
- KEYTABLE *x;
-
- for (x=key_table_list;;x=x->next)
- if (!x)
- m_exit(M_CRASH);
- else if (id==x->id)
- break;
-
- return(x);
- }
- /*}}} */
- /*{{{ get_term_token*/
- private tokens get_term_token(void)
- { tokens x=get_full_token();
-
- switch (x)
- { case DEFAULT:
- ustrcpy(tk_string,def_mode_name);
- x=NAME;
- break;
- case OPCODE:
- case OPERATION:
- case VARIABLE:
- if (isalnum(tk_string[0]))
- x=NAME;
- default:
- break;
- }
- return(x);
- }
- /*}}} */
-
- /*{{{ KEY_LONG node handling*/
- private KEY_LONG *k_freed=0;
-
- /*{{{ key_alloc*/
- private KEY_LONG *key_alloc(void)
- {
- KEY_LONG *x;
-
- if (k_freed)
- /*{{{ use freed node*/
- { x=k_freed;
- k_freed=k_freed->next;
- }
- /*}}} */
- else
- /*{{{ use new one*/
- { static KEY_LONG *km;
- static int key_malloced=0;
- # define KEY_PAKET 128
-
- if (!key_malloced)
- /*{{{ get paket of key structs*/
- { km=kbd_malloc(KEY_PAKET*sizeof(KEY_LONG));
- key_malloced=KEY_PAKET;
- }
- /*}}} */
- x=km++;
- key_malloced--;
- }
- /*}}} */
- x->next=x->n_level=0;
- x->code=x->key=0;
-
- return(x);
- }
- /*}}} */
- /*{{{ key_free*/
- private void key_free(KEY_LONG * const x)
- {
- x->next=k_freed;
- k_freed=x;
- }
- /*}}} */
- /*{{{ key_copy*/
- private KEY_LONG *key_copy(KEY_LONG *p)
- { KEY_LONG *n;
-
- if (!p)
- return(0);
- n=key_alloc();
- *n = *p;
- if (n->next)
- n->next=key_copy(p->next);
- if (n->n_level)
- n->n_level=key_copy(p->n_level);
-
- return(n);
- }
- /*}}} */
- /*}}} */
-
- /*{{{ init_ktb*/
- private struct ktbl *find_term(KEYTABLE * const k,TERMINALS const * const t);
-
- private void init_ktb
- ( unsigned char const*const mode,
- unsigned char const*const term
- )
- {
- TERMINALS *t;
- struct ktbl *kl;
- KEYTABLE *x;
-
- for (x=key_table_list;;x=x->next)
- if (!x)
- /*{{{ get a new table for mode*/
- {
- /*{{{ get new space*/
- x=kbd_malloc(sizeof(KEYTABLE));
- x->next=key_table_list;
- key_table_list=x;
- /*}}} */
- x->id=last_ktbl_id++;
- /*{{{ init data for the mode/default table*/
- ustrcpy(x->mode,mode);
- x->def=False;
- x->keys.t=(TERMINALS*)&def_terminal;
- x->keys.top_level=key_alloc();
- x->keys.mark=bind_help_id++;
- x->keys.next=0;
- if (bind_help_id&0x8000)
- m_exit(M_T_MAX);
- /*}}} */
- break;
- }
- /*}}} */
- else if (!ustrcmp(mode,x->mode))
- break;
- for (t=name2terminal(term),kl= &x->keys;;kl=kl->next)
- if (!kl)
- /*{{{ define a new table for current terminal*/
- { kl=kbd_malloc(sizeof(struct ktbl));
- kl->t=t;
- kl->top_level=key_copy
- ( find_term
- ( x,
- (TERMINALS*)&def_terminal
- )->top_level
- );
- kl->mark=bind_help_id++;
- kl->next=x->keys.next;
- x->keys.next=kl;
- break;
- }
- /*}}} */
- else if (kl->t->id==t->id)
- break;
- }
- /*}}} */
- /*{{{ find_term*/
- private struct ktbl *find_term(KEYTABLE * const k,TERMINALS const * const t)
- {
- struct ktbl *x;
-
- for (x= &k->keys;;x=x->next)
- if (!x)
- { init_ktb(k->mode,t->tname);
- x=find_term(k,t);
- break;
- }
- else if (x->t->id==t->id)
- break;
-
- return(x);
- }
- /*}}} */
-
- /*{{{ init_keytables*/
- public void init_keytables(void)
- {
- init_mouse();
- init_ktb(def_mode_name,def_term_name);
- }
- /*}}} */
- /*{{{ token2mode*/
- public int token2mode(tokens t)
- {
- KEYTABLE *k;
-
- if (t!=OPERATION || !(k=name2mode((unsigned char const*const)tk_string)))
- return(-1);
- else
- return(k->id);
- }
- /*}}} */
-
- /*{{{ define_k_modes*/
- public void define_k_modes(void)
- {
- boolean begin_end_used=False;
-
- if (def_kbd_used)
- m_exit(M_KBD_KEY);
- for (;;)
- { switch (get_full_token())
- {
- /*{{{ END: end loop*/
- case END:
- break;
- /*}}} */
- /*{{{ BEGIN:mark list read*/
- case BEGIN:
- if (begin_end_used)
- goto mkbd_error;
- begin_end_used=True;
- continue;
- /*}}} */
- /*{{{ NAME: a new mode*/
- case NAME:
- { int mode_number;
-
- /*{{{ set mode number*/
- { KEYTABLE *k;
-
- k=name2mode(tk_string);
- mode_number=k?k->id:-1;
- }
- /*}}} */
- if (mode_number==-1)
- { KEYTABLE *k;
-
- if (modes_used)
- init_ktb(tk_string,def_term_name);
- mode_number=modes_used;
- k=id2mode(mode_number);
- ustrcpy(k->mode,tk_string);
- /*{{{ verbose?*/
- if (verbose_level>0)
- fprintf(stderr,F_KBDS,k->mode,modes_used);
- /*}}} */
- /*{{{ gen kbd switch macro*/
- { TOKEN t[2];
-
- t[0]=M_SW_KBD;
- t[1]=modes_used;
- verbose_level--;
- creat_op(k->mode,True,2,t,-1,False,0);
- verbose_level++;
- }
- /*}}} */
- /*{{{ maybe gen rc comment*/
- if (commenting && !dest_mac)
- { char buff[NAME_LG+NAME_LG];
- char *tp=buff;
-
- sprintf(buff,"%s is mode %d",tk_string,mode_number);
- rc_put_c(RC_COMMENT,rc.fp);
- do rc_put_c(*tp,rc.fp); while (*tp++);
- }
- /*}}} */
- modes_used++;
- }
- continue;
- }
- /*}}} */
- /*{{{ error*/
- default:
- mkbd_error:
- m_exit(M_KBD_ERR);
- /*}}} */
- }
- break;
- }
- if (begin_end_used)
- end_parse(M_WANTEND);
- }
- /*}}} */
- /*{{{ check_k_modes*/
- public void check_k_modes(void)
- {
- int i;
-
- for (i=modes_used;i--;)
- { KEYTABLE *k;
-
- k=id2mode(i);
- if (!k->def)
- m_exit(F_KBD_MISS,k->mode);
- }
- }
- /*}}} */
-
- /*{{{ add_keyseq*/
- /*{{{ decode*/
- private unsigned char *decode(TOKEN keynumber)
- { KEYNAME *seek = bindings;
- int off;
- static unsigned char name[NAME_LG];
-
- /*{{{ store offset to first fix-macro*/
- if (keynumber>=O_CALL_FIX)
- { off=keynumber-O_CALL_FIX+1;
- keynumber=O_CALL_FIX;
- }
- else
- off=0;
- /*}}} */
- while (seek->name)
- if ((seek->num)==(TOKEN) keynumber)
- /*{{{ return the name*/
- if (off)
- { sprintf((char*)name,"%d=%s %d",keynumber,seek->name,off);
- return(name);
- }
- else
- { sprintf((char*)name,"%d=%s",keynumber,seek->name);
- return(name);
- }
- /*}}} */
- else
- seek++;
- sprintf((char*)name,F_NOKEYNUMBER,keynumber);
- return(name);
- }
- /*}}} */
- /*{{{ add_key*/
- private KEY_LONG *add_key(TOKEN key,KEY_LONG *current,TOKEN op)
- {
- KEY_LONG *x;
-
- for (x=current->n_level;;x=x->next)
- if (!x)
- /*{{{ get new node*/
- { x=key_alloc();
- x->key=key;
- x->next=current->n_level;
- current->n_level=x;
- break;
- }
- /*}}} */
- else if (x->key == key)
- /*{{{ key already in list, end search or error*/
- { if (x->code)
- if (x->code==op)
- /*{{{ maybe warn*/
- { if (warning)
- { error_po();
- fprintf(stderr,F_DBL_BIND,decode(op));
- }
- }
- /*}}} */
- else
- /*{{{ return error*/
- { error_po();
- fprintf(stderr,F_ISMASKED,decode(x->code));
- x=0;
- }
- /*}}} */
- break;
- }
- /*}}} */
-
- return (x);
- }
- /*}}} */
- /*{{{ set_key_code*/
- private boolean set_key_code (TOKEN code,KEY_LONG *current)
- {
- if (current->n_level)
- { error_po();
- fprintf(stderr,F_MASKS,decode(code));
- return(True);
- }
- current->code = code;
-
- return (False);
- }
- /*}}} */
-
- private void add_keyseq(struct ktbl *kt,TOKEN k,int lg,TOKEN *s)
- { KEY_LONG *key_point;
-
- if (kt)
- { key_point=kt->top_level;
- for (;lg;lg--)
- if (!(key_point=add_key(*s++,key_point,((lg>1)?0:k))))
- goto error_out;
- if (set_key_code(k,key_point))
- goto error_out;
- }
- return;
- error_out:
- m_exit
- ( F_CUR_TERM,
- kt->t->id==DEF_TERM_ID
- ? (unsigned char*)"default"
- : kt->t->tname
- );
- }
- /*}}} */
- /*{{{ parse_keysequence*/
- /*{{{ add_k_c*/
- private void add_k_c(struct ksl *k,TOKEN c)
- {
- int l;
-
- if ((l=k->lg++)==ALIAS_LG)
- m_exit(M_LONG_KEY);
- k->codes[l]=c;
- }
- /*}}} */
- /*{{{ add_kl_c*/
- private void add_kl_c(struct ksl *kl,TOKEN c)
- {
- for (;kl;kl=kl->next)
- add_k_c(kl,c);
- }
- /*}}} */
- /*{{{ add_k_alias*/
- private struct ksl *add_k_alias(struct ksl *k,ALIAS_LIST *a)
- {
- struct acl *c,*cn;
-
- for (c=a->code;;c=cn,k=k->next)
- { cn=c->next;
- if (cn)
- /*{{{ double current sequence for next alias version*/
- { struct ksl *x;
-
- x=ks_malloc();
- *x = *k;
- k->next=x;
- }
- /*}}} */
- /*{{{ append string*/
- { TOKEN *s;
- int lg;
-
- for (lg=c->length,s=c->codes;lg;s++,lg--)
- add_k_c(k,*s);
- }
- /*}}} */
- if (!cn)
- return(k);
- }
- }
- /*}}} */
- /*{{{ add_kl_alias*/
- private void add_kl_alias(struct ksl *k,ALIAS_LIST *a)
- {
- while (k)
- { if (!(k=add_k_alias(k,a)))
- kbd_exit(1);
- k=k->next;
- }
- }
- /*}}} */
-
- private void parse_keysequence(TERMINALS *t,KEYSEQUENCE *k)
- {
- char *p;
- tokens token;
-
- /*{{{ check for valid term*/
- if (!t || t->id==-1)
- t=0;
- /*}}} */
- /*{{{ build empty KEYSEQUENCE list for given terms*/
- { TERMINALS *tx;
- struct ksl *kl;
-
- (p=(char*)k->protocol)[0]='\0';
- for (tx=t,k->key_list=0;tx;tx=tx->next)
- { kl=ks_malloc();
- kl->t=tx;
- kl->lg=0;
- kl->next=k->key_list;
- k->key_list=kl;
- }
- }
- /*}}} */
- begin_parse();
- for (;;)
- { switch ((token=get_keycode_token()))
- {
- /*{{{ all*/
- case MULT:
- add_kl_c(k->key_list,keytaball);
- strcat(p,"* ");
- continue;
- /*}}} */
- /*{{{ hex or normal char*/
- case HEX:
- case CHAR:
- add_kl_c(k->key_list,tk_char);
- /*{{{ generate protocol of this binding*/
- if (token==HEX)
- { strcat(p,(char*)tk_string);
- strcat(p," ");
- }
- else if (tk_char==127)
- strcat(p,"C-? ");
- else if (tk_char==' ')
- strcat(p,"space ");
- else if ((unsigned int)tk_char>(unsigned int)' ')
- { char x[3];
-
- x[0]=(char)tk_char;
- x[1]=' ';
- x[2]='\0';
- strcat(p,x);
- }
- else
- { char x[5];
-
- x[0]='C';
- x[1]='-';
- x[2]=CTRL_CHARS[tk_char];
- x[3]=' ';
- x[4]='\0';
- strcat(p,x);
- }
- /*}}} */
- continue;
- /*}}} */
- /*{{{ meta*/
- case META:
- add_kl_c(k->key_list,27);
- strcat(p,"M-");
- continue;
- /*}}} */
- /*{{{ alias*/
- case DOLLAR:
- { ALIAS_LIST *ap;
-
- ap=alias_list;
- while (ap && ustrcmp(ap->key_name,tk_string))
- ap=ap->next;
- if (ap)
- /*{{{ alias found -> normal alias, copy to all sequences*/
- add_kl_alias(k->key_list,ap);
- /*}}} */
- else
- /*{{{ handle as terminal-alias*/
- { struct ksl *kl;
-
- for (kl=k->key_list;kl;)
- { unsigned char an[NAME_LG];
-
- /*{{{ create correct name*/
- ustrcpy(an,kl->t->tname);
- strcat((char*)an,"@");
- ustrcat(an,tk_string);
- /*}}} */
- ap=alias_list;
- while (ap && ustrcmp(ap->key_name,an))
- ap=ap->next;
- if (ap)
- /*{{{ alias found*/
- { if (!(kl=add_k_alias(kl,ap)))
- kbd_exit(1);
- kl=kl->next;
- }
- /*}}} */
- else
- /*{{{ don't bind this term-alias!*/
- { if (warning)
- { error_po();
- fprintf(stderr,F_MISALIAS,an);
- }
- if (kl==k->key_list)
- { k->key_list=kl->next;
- ks_free(kl);
- kl=k->key_list;
- }
- else
- { struct ksl *kx;
-
- for (kx=k->key_list;;kx=kx->next)
- if (kx->next==kl)
- { kx->next=kl->next;
- ks_free(kl);
- kl=kx->next;
- break;
- }
- }
- }
- /*}}} */
- }
- }
- /*}}} */
- strcat(p,(char*)tk_string);
- strcat(p," ");
- continue;
- }
- /*}}} */
- /*{{{ )*/
- case END: break;
- /*}}} */
- /*{{{ errors*/
- default:
- m_exit(M_WANTEND);
- case ERROR:
- kbd_exit(1);
- /*}}} */
- }
- break;
- }
- }
- /*}}} */
- /*{{{ keydef_body*/
- private void keydef_body(KEYTABLE *kt,TERMINALS *tl,boolean ab_allowed)
- { KEYSEQUENCE k;
- TOKEN operation;
- unsigned char *n;
- struct ksl *kl;
-
- /*{{{ get binding object*/
- switch (get_full_token())
- { default:
- invalid_bind_object:
- m_exit(M_NOCOMMAND);
- /*{{{ OPCODE, use table values*/
- case OPCODE:
- n=(unsigned char*)tk_key->name;
- operation=tk_key->num;
- break;
- /*}}} */
- /*{{{ MACRO, generate simple string from tk_string*/
- case MACRO:
- if (ustrlen(tk_string)==1)
- { static unsigned char simple_char_name[3];
-
- simple_char_name[0]='\"';
- simple_char_name[1]=tk_string[0];
- simple_char_name[2]='\0';
- operation=tk_macro[0];
- n=simple_char_name;
- break;
- }
- else
- goto invalid_bind_object;
- /*}}} */
- /*{{{ OPERATION: use deffun or defmac value*/
- case OPERATION:
- if (tk_operation->place<0)
- { if (tk_operation->length!=1)
- m_exit(M_NODEBOUND);
- else
- operation= *(tk_operation->ops);
- }
- else
- operation=(TOKEN)((int)O_EXE_MACRO+tk_operation->place);
- n=tk_operation->op_name;
- break;
- /*}}} */
- /*{{{ MINUS: key-not-bound*/
- case MINUS:
- operation=keytabknb;
- n=0;
- break;
- /*}}} */
- }
- /*}}} */
- /*{{{ get sequence*/
- parse_keysequence(tl,&k);
- end_parse(M_KEYEND);
- /*}}} */
- if (operation==O_BREAK)
- if (ab_allowed)
- /*{{{ handle abort*/
- {
- /*{{{ incorrect sequence*/
- if
- ( !k.key_list
- || k.key_list->lg!=1
- || k.key_list->codes[0]>=O_NOP
- || k.key_list->codes[0]<'\0'
- || !n
- )
- m_exit(M_NOABORT);
- /*}}} */
- /*{{{ double*/
- if (ab_set)
- m_exit(M_DUPAB);
- /*}}} */
- general_abort_key=k.key_list->codes[0];
- write_bind(n,k.protocol,abort_kbd);
- ab_set=True;
- }
- /*}}} */
- else
- /*{{{ error*/
- m_exit(M_KBD_KEY);
- /*}}} */
- else
- /*{{{ normal key*/
- { if (ab_allowed)
- if (modes_used)
- /*{{{ multiple keytables used -> crash*/
- m_exit(M_KBD_KEY);
- /*}}} */
- else
- def_kbd_used=True;
- /*{{{ copy all not already used terminal-trees*/
- for (kl=k.key_list;kl;kl=kl->next)
- find_term(kt,kl->t);
- /*}}} */
- /*{{{ add sequence to trees*/
- for (kl=k.key_list;kl;kl=kl->next)
- { struct ktbl *ktb;
-
- ktb=find_term(kt,kl->t);
- add_keyseq(ktb,operation,kl->lg,kl->codes);
- }
- /*}}} */
- if (n)
- /*{{{ write to helpfile*/
- { TERMINALS *tp;
-
- for (tp=term_list;tp;tp=tp->next)
- for (kl=k.key_list;kl;kl=kl->next)
- { if (kl->t->id==tp->id)
- { struct ktbl *ktb;
-
- ktb=find_term(kt,kl->t);
- write_bind(n,k.protocol,ktb->mark);
- break;
- }
- }
- }
- /*}}} */
- }
- /*}}} */
- ksl_free(k.key_list);
- }
- /*}}} */
- /*{{{ terminal_body*/
- private void terminal_body(KEYTABLE *ktb)
- {
- TERMINALS *term_l;
- boolean no_mode_set;
-
- if (!ktb)
- { no_mode_set=True;
- ktb=id2mode(DEF_MODE_ID);
- }
- else
- no_mode_set=False;
- /*{{{ get correct terminals*/
- switch (get_term_token())
- { case NAME:
- case NUMBER:
- /*{{{ single terminal*/
- term_l=t_malloc();
- *term_l= *name2terminal(tk_string);
- term_l->next=0;
- break;
- /*}}} */
- case BEGIN:
- /*{{{ list of terminals*/
- { for (term_l=0;;)
- { switch (get_term_token())
- { case END:
- break;
- case NAME:
- case NUMBER:
- /*{{{ copy name*/
- { TERMINALS *x;
-
- x=t_malloc();
- *x= *name2terminal(tk_string);
- x->next=term_l;
- term_l=x;
- continue;
- }
- /*}}} */
- default:
- goto term_expected;
- }
- break;
- }
- break;
- }
- /*}}} */
- default:
- term_expected:
- m_exit(M_T_NAME);
- }
- if (verbose_level>3)
- /*{{{ show all opened terminals*/
- { TERMINALS *x;
-
- for (x=term_l;x && x->id!=-1;x=x->next)
- fprintf(stderr,F_T_START,x->tname);
- }
- /*}}} */
- /*}}} */
- for (;;)
- { switch (get_full_token())
- { case END:
- break;
- case BEGIN:
- switch (get_full_token())
- { case KEYDEF:
- keydef_body(ktb,term_l,False);
- continue;
- case KEYALIAS:
- if (no_mode_set)
- /*{{{ do the alias*/
- { unsigned char name[NAME_LG+1];
- KEYSEQUENCE k;
- struct ksl *kl;
-
- name_parse(name,M_EXPALIAS,True);
- parse_keysequence(term_l,&k);
- for (kl=k.key_list;kl;kl=kl->next)
- { unsigned char tname[2*NAME_LG+1];
-
- ustrcpy(tname,kl->t->tname);
- strcat((char*)tname,"@");
- ustrcat(tname,name);
- if (ustrlen(tname)>NAME_LG)
- m_exit(M_CRASH);
- creat_alias(tname,kl->lg,kl->codes);
- }
- ksl_free(k.key_list);
- end_parse(M_WANTEND);
- continue;
- }
- /*}}} */
- default:
- break;
- }
- default:
- m_exit(M_KBD_BEGIN);
- }
- break;
- }
- tl_free(term_l);
- if (verbose_level>3)
- /*{{{ show all opened terminals*/
- { TERMINALS *x;
-
- for (x=term_l;x && x->id!=-1;x=x->next)
- fprintf(stderr,M_T_END,x->tname);
- }
- /*}}} */
- }
- /*}}} */
- /*{{{ def_keybind_code*/
- public void def_keybind_code(void)
- {
- keydef_body(name2mode(def_mode_name),term_list,True);
- }
- /*}}} */
- /*{{{ set_alias*/
- public void set_alias(void)
- { unsigned char name[NAME_LG];
- KEYSEQUENCE k;
-
- name_parse(name,M_EXPALIAS,True);
- parse_keysequence((TERMINALS*)&def_terminal,&k);
- if (k.key_list)
- creat_alias(name,k.key_list->lg,k.key_list->codes);
- }
- /*}}} */
- /*{{{ mode_code*/
- public void mode_code(void)
- {
- tokens t;
- int mode_number;
- KEYTABLE *ktb;
-
- if (!modes_used)
- m_exit(M_KBD_KEY);
- /*{{{ get correct kbd-no*/
- if ((mode_number=token2mode(get_full_token()))<0)
- kbd_exit(1);
- ktb=id2mode(mode_number);
- if (mode_number && !ktb->def)
- init_ktb(ktb->mode,def_term_name);
- /*}}} */
- if (verbose_level>0)
- fprintf(stderr,F_BEG_MODE,ktb->mode);
- ktb->def=True;
- while ((t=get_full_token())!=END)
- switch (t)
- { case BEGIN:
- switch(get_full_token())
- { case KEYDEF:
- keydef_body(ktb,term_list,False);
- break;
- case TERMINAL:
- terminal_body(ktb);
- break;
- default:
- goto mode_error;
-
- }
- break;
- default:
- mode_error:
- m_exit(M_KBD_BEGIN);
- }
- if (verbose_level>0)
- fprintf(stderr,F_END_MODE,ktb->mode);
- }
- /*}}} */
- /*{{{ terminal_cmd*/
- public void terminal_cmd(void)
- {
- terminal_body(0);
- }
- /*}}} */
-
- /*{{{ write_kbds*/
- /*{{{ write_t_ktbs*/
- typedef enum { FAR_NEXT_KEY=O_NOP,WRITTEN_KEY,TOP_KEY } special_key;
- #define BASE_ID 0
- #define CLEARED_ID (BASE_ID-1)
- private int joined;
-
- /*{{{ opti_id_ktb*/
- /*{{{ ktb_set_id*/
- /*{{{ comment*/
- /* genereate unique identifiers for all nodes, shared next-nodes will
- * lead to far-next-nodes, to gurantee, that next-nodes are directly
- * after their parent!
- * returns the number of used nodes!
- */
- /*}}} */
- /*{{{ ktb_clear_id*/
- private void ktb_clear_id(KEY_LONG * const n)
- {
- if (n)
- { n->x.id=CLEARED_ID;
- ktb_clear_id(n->next);
- ktb_clear_id(n->n_level);
- }
- }
- /*}}} */
- /*{{{ rec_ktb_set_id*/
- private int rec_ktb_set_id(KEY_LONG * const n,int base)
- {
- if (base&0x8000)
- m_exit(M_TOOMANYKEYS);
- if (n && n->x.id==CLEARED_ID)
- { n->x.id=base++;
- if (n->next)
- { if (n->next->x.id!=CLEARED_ID)
- /*{{{ generate far-next-node*/
- { KEY_LONG *c;
-
- c=key_alloc();
- c->x.id=CLEARED_ID;
- c->key=FAR_NEXT_KEY;
- c->n_level=n->next;
- n->next=c;
- joined--;
- }
- /*}}} */
- base=rec_ktb_set_id(n->next,base);
- }
- base=rec_ktb_set_id(n->n_level,base);
- }
-
- return(base);
- }
- /*}}} */
-
- private int ktb_set_id(KEY_LONG * const ktb)
- {
- ktb_clear_id(ktb);
- return(rec_ktb_set_id(ktb,BASE_ID));
- }
- /*}}} */
- /*{{{ sort_ktb*/
- private void sort_ktb(KEY_LONG * const n,boolean const full)
- {
- if (n)
- { if (full)
- sort_ktb(n->n_level,True);
- if (n->next)
- { if (full)
- sort_ktb(n->next,True);
- if
- ( n->key<TOP_KEY
- && ( n->key==keytaball
- || (n->key>n->next->key && n->next->key!=keytaball)
- )
- )
- /*{{{ change nodes*/
- { KEY_LONG x;
-
- x = *n;
- *n = *(x.next);
- *(x.next) = x;
- x.next->next=n->next;
- n->next=x.next;
- sort_ktb(n->next,False);
- }
- /*}}} */
- }
- }
- }
- /*}}} */
- #ifndef NO_OPTI
- /*{{{ join_tree*/
- /* transform the keytable tree into an directed-acyclic-graph,
- * sharing common sub-trees
- */
- /*{{{ ktb hashing*/
- private KEY_LONG *hash[O_NOP];
-
- /*{{{ ktb_init_hash*/
- /*{{{ ktb_r_i_h*/
- private void ktb_r_i_h(KEY_LONG * const n)
- {
- if (n)
- { ktb_r_i_h(n->n_level);
- if (n->key>=0 && n->key<O_NOP)
- { n->x.hash=hash[n->key];
- hash[n->key]=n;
- }
- ktb_r_i_h(n->next);
- }
- }
- /*}}} */
-
- private void ktb_init_hash(KEY_LONG * const n)
- {
- /*{{{ empty lists*/
- { int i;
-
- for (i=O_NOP;--i>=0;hash[i]=0);
- }
- /*}}} */
- ktb_r_i_h(n);
- }
- /*}}} */
- /*{{{ ktb_find_hash*/
- private KEY_LONG *ktb_find_hash(KEY_LONG const * const n)
- {
- KEY_LONG *x;
-
- if (n->key>=0 && n->key<O_NOP)
- { for (x=n->x.hash;x;x=x->x.hash)
- if
- ( x!=n
- && x->code==n->code
- && x->next==n->next
- && x->n_level==n->n_level
- )
- break;
- }
- else
- x=0;
-
- return(x);
- }
- /*}}} */
- /*{{{ ktb_del_hash*/
- private void ktb_del_hash(KEY_LONG const * const n)
- {
- if (n->key>=0 && n->key<O_NOP)
- if (hash[n->key]==n)
- hash[n->key]=n->x.hash;
- else
- { KEY_LONG *x;
-
- for (x=hash[n->key];x;x=x->x.hash)
- if (x->x.hash==n)
- { x->x.hash=n->x.hash;
- break;
- }
- }
- }
- /*}}} */
- /*}}} */
- /*{{{ rec_join_tree*/
- private boolean rec_join_tree(KEY_LONG * const n)
- {
- boolean ret;
-
- ret=False;
- if (n)
- { KEY_LONG *c;
-
- /*{{{ maybe use copy of n_level node*/
- if (n->n_level)
- { ret=rec_join_tree(n->n_level);
- if ((c=ktb_find_hash(n->n_level)))
- { ktb_del_hash(n->n_level);
- key_free(n->n_level);
- n->n_level=c;
- joined++;
- ret=True;
- }
- }
- /*}}} */
- /*{{{ maybe use copy of next node*/
- if (n->next)
- { ret|=rec_join_tree(n->next);
- if ((c=ktb_find_hash(n->next)))
- /*{{{ replace next by found copy*/
- { ktb_del_hash(n->next);
- key_free(n->next);
- n->next=c;
- joined++;
- ret=True;
- }
- /*}}} */
- }
- /*}}} */
- }
- return(ret);
- }
- /*}}} */
-
- private void join_tree(KEY_LONG * const ktb)
- {
- joined=0;
- ktb_init_hash(ktb);
- while (rec_join_tree(ktb));
- }
- /*}}} */
- #endif
-
- private int opti_id_ktb(KEY_LONG * const ktb)
- {
- joined=0;
- /*{{{ set top_level key's to special values, and sort level entries*/
- { KEY_LONG *t;
- int m;
-
- for (m=TOP_KEY,t=ktb;t;t->key=m,m++,t=t->next)
- sort_ktb(t->n_level,True);
- }
- /*}}} */
- # ifndef NO_OPTI
- join_tree(ktb);
- # endif
-
- return(ktb_set_id(ktb));
- }
- /*}}} */
- /*{{{ write_single_keynode*/
- private void write_single_keynode(KEY_LONG *n)
- {
- if (n && n->key!=WRITTEN_KEY && !dest_mac)
- { if (ab_set && n->key==general_abort_key)
- m_exit(M_ABORTUSED);
- /*{{{ create and write compressed keytab node*/
- { KEY ks;
-
- ks.flags=NOT_USED;
- ks.code=n->code;
- if (n->key==keytaball)
- { ks.key='\0';
- ks.flags|=MAGIC_KEY;
- }
- else
- ks.key=n->key;
- if (n->next)
- ks.flags|=NEXT_USED;
- if (n->n_level)
- { ks.flags|=LEVEL_USED;
- if (n->key==FAR_NEXT_KEY)
- { ks.flags|=FAR_NEXT;
- ks.key=0;
- }
- ks.code=n->n_level->x.id-n->x.id;
- }
- put_key_data(&ks,rc.fp);
- }
- /*}}} */
- n->key=WRITTEN_KEY;
- write_single_keynode(n->next);
- write_single_keynode(n->n_level);
- }
- }
- /*}}} */
-
- private void write_t_ktbs(TERMINALS const * const t)
- {
- KEY_LONG *top,*tail;
- int nodes;
-
- /*{{{ generate single tree for all modes*/
- { int m;
- for (top=0,m=0;m<modes_used;m++)
- { KEYTABLE const *k;
- struct ktbl *x;
-
- /*{{{ get ktbl for mode/terminal, adding mouse keys*/
- k=id2mode(m);
- x=find_term((KEYTABLE*)k,t);
- /*{{{ add mouse for this terminal*/
- { mouse_supports *m_ptr;
- unsigned char const *m_n;
-
- /*{{{ m_ptr=current mouse, or default*/
- for (m_ptr=m_list,m_n=(t->id!=DEF_TERM_ID)?t->tname:m_name;;)
- { if
- ( m_ptr->name
- && strncmp((char*)m_ptr->name,(char*)m_n,ustrlen(m_ptr->name))
- )
- m_ptr++;
- else if (!(m_ptr->name) && (m_n==t->tname))
- { m_n=m_name;m_ptr=m_list; }
- else
- break;
- }
- /*}}} */
- if
- ( m_ptr
- && m_ptr->code_lg
- )
- { TOKEN codes[ALIAS_LG];
- int i;
-
- for (i=0;i<m_ptr->code_lg;i++)
- codes[i]=m_ptr->code[i];
- add_keyseq(x,K_MOUSE,m_ptr->code_lg,codes);
- }
- }
- /*}}} */
- /*}}} */
- /*{{{ append to tree for mode*/
- if (top)
- tail->next=x->top_level;
- else
- top=x->top_level;
- tail=x->top_level;
- /*}}} */
- }
- }
- /*}}} */
- nodes=opti_id_ktb(top);
- /*{{{ write the keytable*/
- rc_put_c(RC_DEFKEY,rc.fp);
- /*{{{ write name*/
- { unsigned char const *term;
-
- term=t->tname;
- do
- rc_put_c(*term,rc.fp);
- while (*term++);
- }
- /*}}} */
- rc_put_w(nodes,rc.fp);
- /*{{{ write help marks*/
- { int m;
-
- for (m=0;m<modes_used;m++)
- rc_put_w(find_term(id2mode(m),t)->mark,rc.fp);
- }
- /*}}} */
- if (verbose_level>0)
- fprintf(stderr,F_NODES,t->tname,nodes,joined);
- write_single_keynode(top);
- /*}}} */
- }
- /*}}} */
-
- public void write_kbds(void)
- {
- TERMINALS *t;
-
- if (def_kbd_used)
- modes_used=1;
- ktb_count=modes_used;
- for (t=term_list;t;t=t->next)
- if (t->id!=DEF_TERM_ID)
- write_t_ktbs(t);
- write_t_ktbs(&def_terminal);
- }
- /*}}} */
- /*}}} */
-