This is kbd.c in view mode; [Download] [Up]
/* Key-map handler Copyright (C) 1992 Joseph H. Allen This file is part of JOE (Joe's Own Editor) JOE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. JOE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JOE; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "macro.h" #include "termcap.h" #include "vs.h" #include "kbd.h" /* Create a KBD */ KBD *mkkbd(kmap) KMAP *kmap; { KBD *kbd=(KBD *)malloc(sizeof(KBD)); kbd->topmap=kmap; kbd->curmap=kmap; kbd->x=0; return kbd; } /* Eliminate a KBD */ void rmkbd(k) KBD *k; { free(k); } /* Process next key for KBD */ void *dokey(kbd,n) KBD *kbd; { void *bind=0; /* If we were passed a negative character */ if(n<0) n+=256; /* If we're starting from scratch, clear the keymap sequence buffer */ if(kbd->curmap==kbd->topmap) kbd->x=0; if(kbd->curmap->keys[n].k==1) { /* A prefix key was found */ kbd->seq[kbd->x++]=n; kbd->curmap=kbd->curmap->keys[n].value.submap; } else { /* A complete key sequence was entered or an unbound key was found */ bind=kbd->curmap->keys[n].value.bind; /* kbd->seq[kbd->x++]=n; */ kbd->x=0; kbd->curmap=kbd->topmap; } return bind; } /* Return key code for key name or -1 for syntax error */ static int keyval(s) char *s; { if(s[0]=='^' && s[1] && !s[2]) if(s[1]=='?') return 127; else return s[1]&0x1F; else if((s[0]=='S'||s[0]=='s') && (s[1]=='P'||s[1]=='p') && !s[2]) return ' '; else if(s[1] || !s[0]) return -1; else return (unsigned char)s[0]; } /* Create an empty keymap */ KMAP *mkkmap() { KMAP *kmap=(KMAP *)calloc(sizeof(KMAP),1); return kmap; } /* Eliminate a keymap */ void rmkmap(kmap) KMAP *kmap; { int x; if(!kmap) return; for(x=0;x!=KEYS;++x) if(kmap->keys[x].k==1) rmkmap(kmap->keys[x].value.submap); free(kmap); } /* Parse a range */ static char *range(seq,vv,ww) char *seq; int *vv, *ww; { char c; int x, v, w; for(x=0;seq[x] && seq[x]!=' ';++x); /* Skip to a space */ c=seq[x]; seq[x]=0; /* Zero terminate the string */ v=keyval(seq); /* Get key */ w=v; if(w<0) return 0; seq[x]=c; /* Restore the space or 0 */ for(seq+=x;*seq==' ';++seq); /* Skip over spaces */ /* Check for 'TO ' */ if((seq[0]=='T' || seq[0]=='t') && (seq[1]=='O' || seq[1]=='o') && seq[2]==' ') { for(seq+=2;*seq==' ';++seq); /* Skip over spaces */ for(x=0;seq[x] && seq[x]!=' ';++x); /* Skip to space */ c=seq[x]; seq[x]=0; /* Zero terminate the string */ w=keyval(seq); /* Get key */ if(w<0) return 0; seq[x]=c; /* Restore the space or 0 */ for(seq+=x;*seq==' ';++seq); /* Skip over spaces */ } if(v>w) return 0; *vv=v; *ww=w; return seq; } /* Add a binding to a keymap */ static KMAP *kbuild(cap,kmap,seq,bind,err,capseq,seql) CAP *cap; KMAP *kmap; char *seq; void *bind; int *err; char *capseq; { int v, w; if(!seql && seq[0]=='.' && seq[1]) { int x, c; char *s; for(x=0;seq[x] && seq[x]!=' ';++x); c=seq[x]; seq[x]=0; #ifdef __MSDOS__ if(!zcmp(seq+1,"ku")) capseq="\0H", seql=2; else if(!zcmp(seq+1,"kd")) capseq="\0P", seql=2; else if(!zcmp(seq+1,"kl")) capseq="\0K", seql=2; else if(!zcmp(seq+1,"kr")) capseq="\0M", seql=2; else if(!zcmp(seq+1,"kI")) capseq="\0R", seql=2; else if(!zcmp(seq+1,"kD")) capseq="\0S", seql=2; else if(!zcmp(seq+1,"kh")) capseq="\0G", seql=2; else if(!zcmp(seq+1,"kH")) capseq="\0O", seql=2; else if(!zcmp(seq+1,"kP")) capseq="\0I", seql=2; else if(!zcmp(seq+1,"kN")) capseq="\0Q", seql=2; else if(!zcmp(seq+1,"k1")) capseq="\0;", seql=2; else if(!zcmp(seq+1,"k2")) capseq="\0<", seql=2; else if(!zcmp(seq+1,"k3")) capseq="\0=", seql=2; else if(!zcmp(seq+1,"k4")) capseq="\0>", seql=2; else if(!zcmp(seq+1,"k5")) capseq="\0?", seql=2; else if(!zcmp(seq+1,"k6")) capseq="\0@", seql=2; else if(!zcmp(seq+1,"k7")) capseq="\0A", seql=2; else if(!zcmp(seq+1,"k8")) capseq="\0B", seql=2; else if(!zcmp(seq+1,"k9")) capseq="\0C", seql=2; else if(!zcmp(seq+1,"k0")) capseq="\0D", seql=2; seq[x]=c; if(seql) { for(seq+=x;*seq==' ';++seq); } #else s=jgetstr(cap,seq+1); seq[x]=c; if(s && (s=tcompile(cap,s)) && (sLEN(s)>1 || s[0]<0)) { capseq=s; seql=sLEN(s); for(seq+=x;*seq==' ';++seq); } #endif else { *err= -2; return kmap; } } if(seql) { v=w= (unsigned char)*capseq++; --seql; } else { seq=range(seq,&v,&w); if(!seq) { *err= -1; return kmap; } } if(!kmap) kmap=mkkmap(); /* Create new keymap if 'kmap' was NULL */ /* Make bindings between v and w */ while(v<=w) { if(*seq || seql) { if(kmap->keys[v].k==0) kmap->keys[v].value.submap=0; kmap->keys[v].k=1; kmap->keys[v].value.submap=kbuild(cap,kmap->keys[v].value.bind,seq,bind,err,capseq,seql); } else { if(kmap->keys[v].k==1) rmkmap(kmap->keys[v].value.submap); kmap->keys[v].k=0; kmap->keys[v].value.bind= /* This bit of code sticks the key value in the macro */ (v==w?macstk(bind,v):dupmacro(macstk(bind,v))); } ++v; } return kmap; } int kadd(cap,kmap,seq,bind) CAP *cap; KMAP *kmap; char *seq; void *bind; { int err=0; kbuild(cap,kmap,seq,bind,&err,NULL,0); return err; } void kcpy(dest,src) KMAP *dest, *src; { int x; for(x=0;x!=KEYS;++x) if(src->keys[x].k==1) { if(dest->keys[x].k!=1) { dest->keys[x].k=1; dest->keys[x].value.submap=mkkmap(); } kcpy(dest->keys[x].value.submap,src->keys[x].value.submap); } else if(src->keys[x].k==0 && src->keys[x].value.bind) { if(dest->keys[x].k==1) rmkmap(dest->keys[x].value.submap); dest->keys[x].value.bind=src->keys[x].value.bind; dest->keys[x].k=0; } } /* Remove a binding from a keymap */ int kdel(kmap,seq) KMAP *kmap; char *seq; { int err=1; int v, w; seq=range(seq,&v,&w); if(!seq) return -1; /* Clear bindings between v and w */ while(v<=w) { if(*seq) { if(kmap->keys[v].k==1) { int r=kdel(kmap->keys[v].value.submap,seq); if(err!= -1) err=r; } } else { if(kmap->keys[v].k==1) rmkmap(kmap->keys[v].value.submap); kmap->keys[v].k=0; kmap->keys[v].value.bind=0; if(err!= -1) err=0; } ++v; } return err; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.