1c80476e4SDavid E. O'Brien /* $Header: /src/pub/tcsh/tc.bind.c,v 3.33 1998/11/24 18:17:40 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * tc.bind.c: Key binding functions 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 17c80476e4SDavid E. O'Brien * 3. All advertising materials mentioning features or use of this software 18c80476e4SDavid E. O'Brien * must display the following acknowledgement: 19c80476e4SDavid E. O'Brien * This product includes software developed by the University of 20c80476e4SDavid E. O'Brien * California, Berkeley and its contributors. 21c80476e4SDavid E. O'Brien * 4. Neither the name of the University nor the names of its contributors 22c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 23c80476e4SDavid E. O'Brien * without specific prior written permission. 24c80476e4SDavid E. O'Brien * 25c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35c80476e4SDavid E. O'Brien * SUCH DAMAGE. 36c80476e4SDavid E. O'Brien */ 37c80476e4SDavid E. O'Brien #include "sh.h" 38c80476e4SDavid E. O'Brien 39c80476e4SDavid E. O'Brien RCSID("$Id: tc.bind.c,v 3.33 1998/11/24 18:17:40 christos Exp $") 40c80476e4SDavid E. O'Brien 41c80476e4SDavid E. O'Brien #include "ed.h" 42c80476e4SDavid E. O'Brien #include "ed.defns.h" 43c80476e4SDavid E. O'Brien 44c80476e4SDavid E. O'Brien #ifdef OBSOLETE 45c80476e4SDavid E. O'Brien static int tocontrol __P((int)); 46c80476e4SDavid E. O'Brien static char *unparsekey __P((int)); 47c80476e4SDavid E. O'Brien static KEYCMD getkeycmd __P((Char **)); 48c80476e4SDavid E. O'Brien static int parsekey __P((Char **)); 49c80476e4SDavid E. O'Brien static void pkeys __P((int, int)); 50c80476e4SDavid E. O'Brien #endif /* OBSOLETE */ 51c80476e4SDavid E. O'Brien 52c80476e4SDavid E. O'Brien static void printkey __P((KEYCMD *, CStr *)); 53c80476e4SDavid E. O'Brien static KEYCMD parsecmd __P((Char *)); 54c80476e4SDavid E. O'Brien static void bad_spec __P((Char *)); 55c80476e4SDavid E. O'Brien static CStr *parsestring __P((Char *, CStr *)); 56c80476e4SDavid E. O'Brien static CStr *parsebind __P((Char *, CStr *)); 57c80476e4SDavid E. O'Brien static void print_all_keys __P((void)); 58c80476e4SDavid E. O'Brien static void printkeys __P((KEYCMD *, int, int)); 59c80476e4SDavid E. O'Brien static void bindkey_usage __P((void)); 60c80476e4SDavid E. O'Brien static void list_functions __P((void)); 61c80476e4SDavid E. O'Brien 62c80476e4SDavid E. O'Brien extern int MapsAreInited; 63c80476e4SDavid E. O'Brien 64c80476e4SDavid E. O'Brien 65c80476e4SDavid E. O'Brien 66c80476e4SDavid E. O'Brien 67c80476e4SDavid E. O'Brien /*ARGSUSED*/ 68c80476e4SDavid E. O'Brien void 69c80476e4SDavid E. O'Brien dobindkey(v, c) 70c80476e4SDavid E. O'Brien Char **v; 71c80476e4SDavid E. O'Brien struct command *c; 72c80476e4SDavid E. O'Brien { 73c80476e4SDavid E. O'Brien KEYCMD *map; 74c80476e4SDavid E. O'Brien int ntype, no, remove, key, bind; 75c80476e4SDavid E. O'Brien Char *par; 76c80476e4SDavid E. O'Brien Char p; 77c80476e4SDavid E. O'Brien KEYCMD cmd; 78c80476e4SDavid E. O'Brien CStr in; 79c80476e4SDavid E. O'Brien CStr out; 80c80476e4SDavid E. O'Brien Char inbuf[200]; 81c80476e4SDavid E. O'Brien Char outbuf[200]; 82c80476e4SDavid E. O'Brien uChar ch; 83c80476e4SDavid E. O'Brien in.buf = inbuf; 84c80476e4SDavid E. O'Brien out.buf = outbuf; 85c80476e4SDavid E. O'Brien in.len = 0; 86c80476e4SDavid E. O'Brien out.len = 0; 87c80476e4SDavid E. O'Brien 88c80476e4SDavid E. O'Brien USE(c); 89c80476e4SDavid E. O'Brien if (!MapsAreInited) 90c80476e4SDavid E. O'Brien ed_InitMaps(); 91c80476e4SDavid E. O'Brien 92c80476e4SDavid E. O'Brien map = CcKeyMap; 93c80476e4SDavid E. O'Brien ntype = XK_CMD; 94c80476e4SDavid E. O'Brien key = remove = bind = 0; 95c80476e4SDavid E. O'Brien for (no = 1, par = v[no]; 96c80476e4SDavid E. O'Brien par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) { 97c80476e4SDavid E. O'Brien if ((p = (*par & CHAR)) == '-') { 98c80476e4SDavid E. O'Brien no++; 99c80476e4SDavid E. O'Brien break; 100c80476e4SDavid E. O'Brien } 101c80476e4SDavid E. O'Brien else 102c80476e4SDavid E. O'Brien switch (p) { 103c80476e4SDavid E. O'Brien case 'b': 104c80476e4SDavid E. O'Brien bind = 1; 105c80476e4SDavid E. O'Brien break; 106c80476e4SDavid E. O'Brien case 'k': 107c80476e4SDavid E. O'Brien key = 1; 108c80476e4SDavid E. O'Brien break; 109c80476e4SDavid E. O'Brien case 'a': 110c80476e4SDavid E. O'Brien map = CcAltMap; 111c80476e4SDavid E. O'Brien break; 112c80476e4SDavid E. O'Brien case 's': 113c80476e4SDavid E. O'Brien ntype = XK_STR; 114c80476e4SDavid E. O'Brien break; 115c80476e4SDavid E. O'Brien case 'c': 116c80476e4SDavid E. O'Brien ntype = XK_EXE; 117c80476e4SDavid E. O'Brien break; 118c80476e4SDavid E. O'Brien case 'r': 119c80476e4SDavid E. O'Brien remove = 1; 120c80476e4SDavid E. O'Brien break; 121c80476e4SDavid E. O'Brien case 'v': 122c80476e4SDavid E. O'Brien ed_InitVIMaps(); 123c80476e4SDavid E. O'Brien return; 124c80476e4SDavid E. O'Brien case 'e': 125c80476e4SDavid E. O'Brien ed_InitEmacsMaps(); 126c80476e4SDavid E. O'Brien return; 127c80476e4SDavid E. O'Brien case 'd': 128c80476e4SDavid E. O'Brien #ifdef VIDEFAULT 129c80476e4SDavid E. O'Brien ed_InitVIMaps(); 130c80476e4SDavid E. O'Brien #else /* EMACSDEFAULT */ 131c80476e4SDavid E. O'Brien ed_InitEmacsMaps(); 132c80476e4SDavid E. O'Brien #endif /* VIDEFAULT */ 133c80476e4SDavid E. O'Brien return; 134c80476e4SDavid E. O'Brien case 'l': 135c80476e4SDavid E. O'Brien list_functions(); 136c80476e4SDavid E. O'Brien return; 137c80476e4SDavid E. O'Brien default: 138c80476e4SDavid E. O'Brien bindkey_usage(); 139c80476e4SDavid E. O'Brien return; 140c80476e4SDavid E. O'Brien } 141c80476e4SDavid E. O'Brien } 142c80476e4SDavid E. O'Brien 143c80476e4SDavid E. O'Brien if (!v[no]) { 144c80476e4SDavid E. O'Brien print_all_keys(); 145c80476e4SDavid E. O'Brien return; 146c80476e4SDavid E. O'Brien } 147c80476e4SDavid E. O'Brien 148c80476e4SDavid E. O'Brien if (key) { 149c80476e4SDavid E. O'Brien if (!IsArrowKey(v[no])) 150c80476e4SDavid E. O'Brien xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]); 151c80476e4SDavid E. O'Brien in.buf = v[no++]; 152c80476e4SDavid E. O'Brien in.len = Strlen(in.buf); 153c80476e4SDavid E. O'Brien } 154c80476e4SDavid E. O'Brien else { 155c80476e4SDavid E. O'Brien if (bind) { 156c80476e4SDavid E. O'Brien if (parsebind(v[no++], &in) == NULL) 157c80476e4SDavid E. O'Brien return; 158c80476e4SDavid E. O'Brien } 159c80476e4SDavid E. O'Brien else { 160c80476e4SDavid E. O'Brien if (parsestring(v[no++], &in) == NULL) 161c80476e4SDavid E. O'Brien return; 162c80476e4SDavid E. O'Brien } 163c80476e4SDavid E. O'Brien } 164c80476e4SDavid E. O'Brien 165c80476e4SDavid E. O'Brien ch = (uChar) in.buf[0]; 166c80476e4SDavid E. O'Brien 167c80476e4SDavid E. O'Brien if (remove) { 168c80476e4SDavid E. O'Brien if (key) { 169c80476e4SDavid E. O'Brien (void) ClearArrowKeys(&in); 170c80476e4SDavid E. O'Brien return; 171c80476e4SDavid E. O'Brien } 172c80476e4SDavid E. O'Brien if (in.len > 1) { 173c80476e4SDavid E. O'Brien (void) DeleteXkey(&in); 174c80476e4SDavid E. O'Brien } 175c80476e4SDavid E. O'Brien else if (map[ch] == F_XKEY) { 176c80476e4SDavid E. O'Brien (void) DeleteXkey(&in); 177c80476e4SDavid E. O'Brien map[ch] = F_UNASSIGNED; 178c80476e4SDavid E. O'Brien } 179c80476e4SDavid E. O'Brien else { 180c80476e4SDavid E. O'Brien map[ch] = F_UNASSIGNED; 181c80476e4SDavid E. O'Brien } 182c80476e4SDavid E. O'Brien return; 183c80476e4SDavid E. O'Brien } 184c80476e4SDavid E. O'Brien if (!v[no]) { 185c80476e4SDavid E. O'Brien if (key) 186c80476e4SDavid E. O'Brien PrintArrowKeys(&in); 187c80476e4SDavid E. O'Brien else 188c80476e4SDavid E. O'Brien printkey(map, &in); 189c80476e4SDavid E. O'Brien return; 190c80476e4SDavid E. O'Brien } 191c80476e4SDavid E. O'Brien if (v[no + 1]) { 192c80476e4SDavid E. O'Brien bindkey_usage(); 193c80476e4SDavid E. O'Brien return; 194c80476e4SDavid E. O'Brien } 195c80476e4SDavid E. O'Brien switch (ntype) { 196c80476e4SDavid E. O'Brien case XK_STR: 197c80476e4SDavid E. O'Brien case XK_EXE: 198c80476e4SDavid E. O'Brien if (parsestring(v[no], &out) == NULL) 199c80476e4SDavid E. O'Brien return; 200c80476e4SDavid E. O'Brien if (key) { 201c80476e4SDavid E. O'Brien if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1) 202c80476e4SDavid E. O'Brien xprintf(CGETS(20, 2, "Bad key name: %S\n"), in); 203c80476e4SDavid E. O'Brien } 204c80476e4SDavid E. O'Brien else 205c80476e4SDavid E. O'Brien AddXkey(&in, XmapStr(&out), ntype); 206c80476e4SDavid E. O'Brien map[ch] = F_XKEY; 207c80476e4SDavid E. O'Brien break; 208c80476e4SDavid E. O'Brien case XK_CMD: 209c80476e4SDavid E. O'Brien if ((cmd = parsecmd(v[no])) == 0) 210c80476e4SDavid E. O'Brien return; 211c80476e4SDavid E. O'Brien if (key) 212c80476e4SDavid E. O'Brien (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype); 213c80476e4SDavid E. O'Brien else { 214c80476e4SDavid E. O'Brien if (in.len > 1) { 215c80476e4SDavid E. O'Brien AddXkey(&in, XmapCmd((int) cmd), ntype); 216c80476e4SDavid E. O'Brien map[ch] = F_XKEY; 217c80476e4SDavid E. O'Brien } 218c80476e4SDavid E. O'Brien else { 219c80476e4SDavid E. O'Brien ClearXkey(map, &in); 220c80476e4SDavid E. O'Brien map[ch] = cmd; 221c80476e4SDavid E. O'Brien } 222c80476e4SDavid E. O'Brien } 223c80476e4SDavid E. O'Brien break; 224c80476e4SDavid E. O'Brien default: 225c80476e4SDavid E. O'Brien abort(); 226c80476e4SDavid E. O'Brien break; 227c80476e4SDavid E. O'Brien } 228c80476e4SDavid E. O'Brien if (key) 229c80476e4SDavid E. O'Brien BindArrowKeys(); 230c80476e4SDavid E. O'Brien } 231c80476e4SDavid E. O'Brien 232c80476e4SDavid E. O'Brien static void 233c80476e4SDavid E. O'Brien printkey(map, in) 234c80476e4SDavid E. O'Brien KEYCMD *map; 235c80476e4SDavid E. O'Brien CStr *in; 236c80476e4SDavid E. O'Brien { 237c80476e4SDavid E. O'Brien unsigned char outbuf[100]; 238c80476e4SDavid E. O'Brien register struct KeyFuncs *fp; 239c80476e4SDavid E. O'Brien 240c80476e4SDavid E. O'Brien if (in->len < 2) { 241c80476e4SDavid E. O'Brien (void) unparsestring(in, outbuf, STRQQ); 242c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 243c80476e4SDavid E. O'Brien if (fp->func == map[(uChar) *(in->buf)]) { 244c80476e4SDavid E. O'Brien xprintf("%s\t->\t%s\n", outbuf, fp->name); 245c80476e4SDavid E. O'Brien } 246c80476e4SDavid E. O'Brien } 247c80476e4SDavid E. O'Brien } 248c80476e4SDavid E. O'Brien else 249c80476e4SDavid E. O'Brien PrintXkey(in); 250c80476e4SDavid E. O'Brien } 251c80476e4SDavid E. O'Brien 252c80476e4SDavid E. O'Brien static KEYCMD 253c80476e4SDavid E. O'Brien parsecmd(str) 254c80476e4SDavid E. O'Brien Char *str; 255c80476e4SDavid E. O'Brien { 256c80476e4SDavid E. O'Brien register struct KeyFuncs *fp; 257c80476e4SDavid E. O'Brien 258c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 259c80476e4SDavid E. O'Brien if (strcmp(short2str(str), fp->name) == 0) { 260c80476e4SDavid E. O'Brien return (KEYCMD) fp->func; 261c80476e4SDavid E. O'Brien } 262c80476e4SDavid E. O'Brien } 263c80476e4SDavid E. O'Brien xprintf(CGETS(20, 3, "Bad command name: %S\n"), str); 264c80476e4SDavid E. O'Brien return 0; 265c80476e4SDavid E. O'Brien } 266c80476e4SDavid E. O'Brien 267c80476e4SDavid E. O'Brien 268c80476e4SDavid E. O'Brien static void 269c80476e4SDavid E. O'Brien bad_spec(str) 270c80476e4SDavid E. O'Brien Char *str; 271c80476e4SDavid E. O'Brien { 272c80476e4SDavid E. O'Brien xprintf(CGETS(20, 4, "Bad key spec %S\n"), str); 273c80476e4SDavid E. O'Brien } 274c80476e4SDavid E. O'Brien 275c80476e4SDavid E. O'Brien static CStr * 276c80476e4SDavid E. O'Brien parsebind(s, str) 277c80476e4SDavid E. O'Brien Char *s; 278c80476e4SDavid E. O'Brien CStr *str; 279c80476e4SDavid E. O'Brien { 280c80476e4SDavid E. O'Brien #ifdef DSPMBYTE 281c80476e4SDavid E. O'Brien extern bool NoNLSRebind; 282c80476e4SDavid E. O'Brien #endif /* DSPMBYTE */ 283c80476e4SDavid E. O'Brien Char *b = str->buf; 284c80476e4SDavid E. O'Brien 285c80476e4SDavid E. O'Brien if (Iscntrl(*s)) { 286c80476e4SDavid E. O'Brien *b++ = *s; 287c80476e4SDavid E. O'Brien *b = '\0'; 288c80476e4SDavid E. O'Brien str->len = (int) (b - str->buf); 289c80476e4SDavid E. O'Brien return str; 290c80476e4SDavid E. O'Brien } 291c80476e4SDavid E. O'Brien 292c80476e4SDavid E. O'Brien switch (*s) { 293c80476e4SDavid E. O'Brien case '^': 294c80476e4SDavid E. O'Brien s++; 295c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 296c80476e4SDavid E. O'Brien *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237); 297c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 298c80476e4SDavid E. O'Brien *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237]; 299c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 300c80476e4SDavid E. O'Brien *b = '\0'; 301c80476e4SDavid E. O'Brien break; 302c80476e4SDavid E. O'Brien 303c80476e4SDavid E. O'Brien case 'F': 304c80476e4SDavid E. O'Brien case 'M': 305c80476e4SDavid E. O'Brien case 'X': 306c80476e4SDavid E. O'Brien case 'C': 307c80476e4SDavid E. O'Brien #ifdef WINNT 308c80476e4SDavid E. O'Brien case 'N': 309c80476e4SDavid E. O'Brien #endif /* WINNT */ 310c80476e4SDavid E. O'Brien if (s[1] != '-' || s[2] == '\0') { 311c80476e4SDavid E. O'Brien bad_spec(s); 312c80476e4SDavid E. O'Brien return NULL; 313c80476e4SDavid E. O'Brien } 314c80476e4SDavid E. O'Brien s += 2; 315c80476e4SDavid E. O'Brien switch (s[-2]) { 316c80476e4SDavid E. O'Brien case 'F': case 'f': /* Turn into ^[str */ 317c80476e4SDavid E. O'Brien *b++ = CTL_ESC('\033'); 318c80476e4SDavid E. O'Brien while ((*b++ = *s++) != '\0') 319c80476e4SDavid E. O'Brien continue; 320c80476e4SDavid E. O'Brien b--; 321c80476e4SDavid E. O'Brien break; 322c80476e4SDavid E. O'Brien 323c80476e4SDavid E. O'Brien case 'C': case 'c': /* Turn into ^c */ 324c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 325c80476e4SDavid E. O'Brien *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237); 326c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 327c80476e4SDavid E. O'Brien *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237]; 328c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 329c80476e4SDavid E. O'Brien *b = '\0'; 330c80476e4SDavid E. O'Brien break; 331c80476e4SDavid E. O'Brien 332c80476e4SDavid E. O'Brien case 'X' : case 'x': /* Turn into ^Xc */ 333c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 334c80476e4SDavid E. O'Brien *b++ = 'X' & 0237; 335c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 336c80476e4SDavid E. O'Brien *b++ = _toebcdic[_toascii['X'] & 0237]; 337c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 338c80476e4SDavid E. O'Brien *b++ = *s; 339c80476e4SDavid E. O'Brien *b = '\0'; 340c80476e4SDavid E. O'Brien break; 341c80476e4SDavid E. O'Brien 342c80476e4SDavid E. O'Brien case 'M' : case 'm': /* Turn into 0x80|c */ 343c80476e4SDavid E. O'Brien #ifdef DSPMBYTE 344c80476e4SDavid E. O'Brien if (!NoNLSRebind) { 345c80476e4SDavid E. O'Brien *b++ = CTL_ESC('\033'); 346c80476e4SDavid E. O'Brien *b++ = *s; 347c80476e4SDavid E. O'Brien } else { 348c80476e4SDavid E. O'Brien #endif /* DSPMBYTE */ 349c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 350c80476e4SDavid E. O'Brien *b++ = *s | 0x80; 351c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 352c80476e4SDavid E. O'Brien *b++ = _toebcdic[_toascii[*s] | 0x80]; 353c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 354c80476e4SDavid E. O'Brien #ifdef DSPMBYTE 355c80476e4SDavid E. O'Brien } 356c80476e4SDavid E. O'Brien #endif /* DSPMBYTE */ 357c80476e4SDavid E. O'Brien *b = '\0'; 358c80476e4SDavid E. O'Brien break; 359c80476e4SDavid E. O'Brien #ifdef WINNT 360c80476e4SDavid E. O'Brien case 'N' : case 'n': /* NT */ 361c80476e4SDavid E. O'Brien { 362c80476e4SDavid E. O'Brien Char bnt; 363c80476e4SDavid E. O'Brien 364c80476e4SDavid E. O'Brien bnt = nt_translate_bindkey(s); 365c80476e4SDavid E. O'Brien if (bnt != 0) 366c80476e4SDavid E. O'Brien *b++ = bnt; 367c80476e4SDavid E. O'Brien else 368c80476e4SDavid E. O'Brien bad_spec(s); 369c80476e4SDavid E. O'Brien } 370c80476e4SDavid E. O'Brien break; 371c80476e4SDavid E. O'Brien #endif /* WINNT */ 372c80476e4SDavid E. O'Brien 373c80476e4SDavid E. O'Brien default: 374c80476e4SDavid E. O'Brien abort(); 375c80476e4SDavid E. O'Brien /*NOTREACHED*/ 376c80476e4SDavid E. O'Brien return NULL; 377c80476e4SDavid E. O'Brien } 378c80476e4SDavid E. O'Brien break; 379c80476e4SDavid E. O'Brien 380c80476e4SDavid E. O'Brien default: 381c80476e4SDavid E. O'Brien bad_spec(s); 382c80476e4SDavid E. O'Brien return NULL; 383c80476e4SDavid E. O'Brien } 384c80476e4SDavid E. O'Brien 385c80476e4SDavid E. O'Brien str->len = (int) (b - str->buf); 386c80476e4SDavid E. O'Brien return str; 387c80476e4SDavid E. O'Brien } 388c80476e4SDavid E. O'Brien 389c80476e4SDavid E. O'Brien 390c80476e4SDavid E. O'Brien static CStr * 391c80476e4SDavid E. O'Brien parsestring(str, buf) 392c80476e4SDavid E. O'Brien Char *str; 393c80476e4SDavid E. O'Brien CStr *buf; 394c80476e4SDavid E. O'Brien { 395c80476e4SDavid E. O'Brien Char *b; 396c80476e4SDavid E. O'Brien const Char *p; 397c80476e4SDavid E. O'Brien int es; 398c80476e4SDavid E. O'Brien 399c80476e4SDavid E. O'Brien b = buf->buf; 400c80476e4SDavid E. O'Brien if (*str == 0) { 401c80476e4SDavid E. O'Brien xprintf(CGETS(20, 5, "Null string specification\n")); 402c80476e4SDavid E. O'Brien return NULL; 403c80476e4SDavid E. O'Brien } 404c80476e4SDavid E. O'Brien 405c80476e4SDavid E. O'Brien for (p = str; *p != 0; p++) { 406c80476e4SDavid E. O'Brien if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') { 407c80476e4SDavid E. O'Brien if ((es = parseescape(&p)) == -1) 408c80476e4SDavid E. O'Brien return 0; 409c80476e4SDavid E. O'Brien else 410c80476e4SDavid E. O'Brien *b++ = (Char) es; 411c80476e4SDavid E. O'Brien } 412c80476e4SDavid E. O'Brien else 413c80476e4SDavid E. O'Brien *b++ = *p & CHAR; 414c80476e4SDavid E. O'Brien } 415c80476e4SDavid E. O'Brien *b = 0; 416c80476e4SDavid E. O'Brien buf->len = (int) (b - buf->buf); 417c80476e4SDavid E. O'Brien return buf; 418c80476e4SDavid E. O'Brien } 419c80476e4SDavid E. O'Brien 420c80476e4SDavid E. O'Brien static void 421c80476e4SDavid E. O'Brien print_all_keys() 422c80476e4SDavid E. O'Brien { 423c80476e4SDavid E. O'Brien int prev, i; 424c80476e4SDavid E. O'Brien CStr nilstr; 425c80476e4SDavid E. O'Brien nilstr.buf = NULL; 426c80476e4SDavid E. O'Brien nilstr.len = 0; 427c80476e4SDavid E. O'Brien 428c80476e4SDavid E. O'Brien 429c80476e4SDavid E. O'Brien xprintf(CGETS(20, 6, "Standard key bindings\n")); 430c80476e4SDavid E. O'Brien prev = 0; 431c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) { 432c80476e4SDavid E. O'Brien if (CcKeyMap[prev] == CcKeyMap[i]) 433c80476e4SDavid E. O'Brien continue; 434c80476e4SDavid E. O'Brien printkeys(CcKeyMap, prev, i - 1); 435c80476e4SDavid E. O'Brien prev = i; 436c80476e4SDavid E. O'Brien } 437c80476e4SDavid E. O'Brien printkeys(CcKeyMap, prev, i - 1); 438c80476e4SDavid E. O'Brien 439c80476e4SDavid E. O'Brien xprintf(CGETS(20, 7, "Alternative key bindings\n")); 440c80476e4SDavid E. O'Brien prev = 0; 441c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) { 442c80476e4SDavid E. O'Brien if (CcAltMap[prev] == CcAltMap[i]) 443c80476e4SDavid E. O'Brien continue; 444c80476e4SDavid E. O'Brien printkeys(CcAltMap, prev, i - 1); 445c80476e4SDavid E. O'Brien prev = i; 446c80476e4SDavid E. O'Brien } 447c80476e4SDavid E. O'Brien printkeys(CcAltMap, prev, i - 1); 448c80476e4SDavid E. O'Brien xprintf(CGETS(20, 8, "Multi-character bindings\n")); 449c80476e4SDavid E. O'Brien PrintXkey(NULL); /* print all Xkey bindings */ 450c80476e4SDavid E. O'Brien xprintf(CGETS(20, 9, "Arrow key bindings\n")); 451c80476e4SDavid E. O'Brien PrintArrowKeys(&nilstr); 452c80476e4SDavid E. O'Brien } 453c80476e4SDavid E. O'Brien 454c80476e4SDavid E. O'Brien static void 455c80476e4SDavid E. O'Brien printkeys(map, first, last) 456c80476e4SDavid E. O'Brien KEYCMD *map; 457c80476e4SDavid E. O'Brien int first, last; 458c80476e4SDavid E. O'Brien { 459c80476e4SDavid E. O'Brien register struct KeyFuncs *fp; 460c80476e4SDavid E. O'Brien Char firstbuf[2], lastbuf[2]; 461c80476e4SDavid E. O'Brien CStr fb, lb; 462c80476e4SDavid E. O'Brien unsigned char unparsbuf[10], extrabuf[10]; 463c80476e4SDavid E. O'Brien fb.buf = firstbuf; 464c80476e4SDavid E. O'Brien lb.buf = lastbuf; 465c80476e4SDavid E. O'Brien 466c80476e4SDavid E. O'Brien firstbuf[0] = (Char) first; 467c80476e4SDavid E. O'Brien firstbuf[1] = 0; 468c80476e4SDavid E. O'Brien lastbuf[0] = (Char) last; 469c80476e4SDavid E. O'Brien lastbuf[1] = 0; 470c80476e4SDavid E. O'Brien fb.len = 1; 471c80476e4SDavid E. O'Brien lb.len = 1; 472c80476e4SDavid E. O'Brien 473c80476e4SDavid E. O'Brien if (map[first] == F_UNASSIGNED) { 474c80476e4SDavid E. O'Brien if (first == last) 475c80476e4SDavid E. O'Brien xprintf(CGETS(20, 10, "%-15s-> is undefined\n"), 476c80476e4SDavid E. O'Brien unparsestring(&fb, unparsbuf, STRQQ)); 477c80476e4SDavid E. O'Brien return; 478c80476e4SDavid E. O'Brien } 479c80476e4SDavid E. O'Brien 480c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 481c80476e4SDavid E. O'Brien if (fp->func == map[first]) { 482c80476e4SDavid E. O'Brien if (first == last) { 483c80476e4SDavid E. O'Brien xprintf("%-15s-> %s\n", 484c80476e4SDavid E. O'Brien unparsestring(&fb, unparsbuf, STRQQ), fp->name); 485c80476e4SDavid E. O'Brien } 486c80476e4SDavid E. O'Brien else { 487c80476e4SDavid E. O'Brien xprintf("%-4s to %-7s-> %s\n", 488c80476e4SDavid E. O'Brien unparsestring(&fb, unparsbuf, STRQQ), 489c80476e4SDavid E. O'Brien unparsestring(&lb, extrabuf, STRQQ), fp->name); 490c80476e4SDavid E. O'Brien } 491c80476e4SDavid E. O'Brien return; 492c80476e4SDavid E. O'Brien } 493c80476e4SDavid E. O'Brien } 494c80476e4SDavid E. O'Brien if (map == CcKeyMap) { 495c80476e4SDavid E. O'Brien xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), 496c80476e4SDavid E. O'Brien unparsestring(&fb, unparsbuf, STRQQ)); 497c80476e4SDavid E. O'Brien xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]); 498c80476e4SDavid E. O'Brien } 499c80476e4SDavid E. O'Brien else { 500c80476e4SDavid E. O'Brien xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), 501c80476e4SDavid E. O'Brien unparsestring(&fb, unparsbuf, STRQQ)); 502c80476e4SDavid E. O'Brien xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]); 503c80476e4SDavid E. O'Brien } 504c80476e4SDavid E. O'Brien } 505c80476e4SDavid E. O'Brien 506c80476e4SDavid E. O'Brien static void 507c80476e4SDavid E. O'Brien bindkey_usage() 508c80476e4SDavid E. O'Brien { 509c80476e4SDavid E. O'Brien xprintf(CGETS(20, 12, 510c80476e4SDavid E. O'Brien "Usage: bindkey [options] [--] [KEY [COMMAND]]\n")); 511c80476e4SDavid E. O'Brien xprintf(CGETS(20, 13, 512c80476e4SDavid E. O'Brien " -a list or bind KEY in alternative key map\n")); 513c80476e4SDavid E. O'Brien xprintf(CGETS(20, 14, 514c80476e4SDavid E. O'Brien " -b interpret KEY as a C-, M-, F- or X- key name\n")); 515c80476e4SDavid E. O'Brien xprintf(CGETS(20, 15, 516c80476e4SDavid E. O'Brien " -s interpret COMMAND as a literal string to be output\n")); 517c80476e4SDavid E. O'Brien xprintf(CGETS(20, 16, 518c80476e4SDavid E. O'Brien " -c interpret COMMAND as a builtin or external command\n")); 519c80476e4SDavid E. O'Brien xprintf(CGETS(20, 17, 520c80476e4SDavid E. O'Brien " -v bind all keys to vi bindings\n")); 521c80476e4SDavid E. O'Brien xprintf(CGETS(20, 18, 522c80476e4SDavid E. O'Brien " -e bind all keys to emacs bindings\n")); 523c80476e4SDavid E. O'Brien xprintf(CGETS(20, 19, 524c80476e4SDavid E. O'Brien " -d bind all keys to default editor's bindings\n")); 525c80476e4SDavid E. O'Brien xprintf(CGETS(20, 20, 526c80476e4SDavid E. O'Brien " -l list editor commands with descriptions\n")); 527c80476e4SDavid E. O'Brien xprintf(CGETS(20, 21, 528c80476e4SDavid E. O'Brien " -r remove KEY's binding\n")); 529c80476e4SDavid E. O'Brien xprintf(CGETS(20, 22, 530c80476e4SDavid E. O'Brien " -k interpret KEY as a symbolic arrow-key name\n")); 531c80476e4SDavid E. O'Brien xprintf(CGETS(20, 23, 532c80476e4SDavid E. O'Brien " -- force a break from option processing\n")); 533c80476e4SDavid E. O'Brien xprintf(CGETS(20, 24, 534c80476e4SDavid E. O'Brien " -u (or any invalid option) this message\n")); 535c80476e4SDavid E. O'Brien xprintf("\n"); 536c80476e4SDavid E. O'Brien xprintf(CGETS(20, 25, 537c80476e4SDavid E. O'Brien "Without KEY or COMMAND, prints all bindings\n")); 538c80476e4SDavid E. O'Brien xprintf(CGETS(20, 26, 539c80476e4SDavid E. O'Brien "Without COMMAND, prints the binding for KEY.\n")); 540c80476e4SDavid E. O'Brien } 541c80476e4SDavid E. O'Brien 542c80476e4SDavid E. O'Brien static void 543c80476e4SDavid E. O'Brien list_functions() 544c80476e4SDavid E. O'Brien { 545c80476e4SDavid E. O'Brien register struct KeyFuncs *fp; 546c80476e4SDavid E. O'Brien 547c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 548c80476e4SDavid E. O'Brien xprintf("%s\n %s\n", fp->name, fp->desc); 549c80476e4SDavid E. O'Brien } 550c80476e4SDavid E. O'Brien } 551c80476e4SDavid E. O'Brien 552c80476e4SDavid E. O'Brien #ifdef OBSOLETE 553c80476e4SDavid E. O'Brien 554c80476e4SDavid E. O'Brien /* 555c80476e4SDavid E. O'Brien * Unfortunately the apollo optimizer does not like & operations 556c80476e4SDavid E. O'Brien * with 0377, and produces illegal instructions. So we make it 557c80476e4SDavid E. O'Brien * an unsigned char, and hope for the best. 558c80476e4SDavid E. O'Brien * Of-course the compiler is smart enough to produce bad assembly 559c80476e4SDavid E. O'Brien * language instructions, but dumb when it comes to fold the constant :-) 560c80476e4SDavid E. O'Brien */ 561c80476e4SDavid E. O'Brien #ifdef apollo 562c80476e4SDavid E. O'Brien static unsigned char APOLLO_0377 = 0377; 563c80476e4SDavid E. O'Brien #else /* sane */ 564c80476e4SDavid E. O'Brien # define APOLLO_0377 0377 565c80476e4SDavid E. O'Brien #endif /* apollo */ 566c80476e4SDavid E. O'Brien 567c80476e4SDavid E. O'Brien static int 568c80476e4SDavid E. O'Brien tocontrol(c) 569c80476e4SDavid E. O'Brien int c; 570c80476e4SDavid E. O'Brien { 571c80476e4SDavid E. O'Brien c &= CHAR; 572c80476e4SDavid E. O'Brien if (Islower(c)) 573c80476e4SDavid E. O'Brien c = Toupper(c); 574c80476e4SDavid E. O'Brien else if (c == ' ') 575c80476e4SDavid E. O'Brien c = '@'; 576c80476e4SDavid E. O'Brien if (c == '?') 577c80476e4SDavid E. O'Brien c = CTL_ESC('\177'); 578c80476e4SDavid E. O'Brien else 579c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 580c80476e4SDavid E. O'Brien c &= 037; 581c80476e4SDavid E. O'Brien #else /* EBCDIC: simulate ASCII-behavior by transforming to ASCII and back */ 582c80476e4SDavid E. O'Brien c = _toebcdic[_toascii[c] & 037]; 583c80476e4SDavid E. O'Brien #endif 584c80476e4SDavid E. O'Brien return (c); 585c80476e4SDavid E. O'Brien } 586c80476e4SDavid E. O'Brien 587c80476e4SDavid E. O'Brien static char * 588c80476e4SDavid E. O'Brien unparsekey(c) /* 'c' -> "c", '^C' -> "^" + "C" */ 589c80476e4SDavid E. O'Brien register int c; 590c80476e4SDavid E. O'Brien { 591c80476e4SDavid E. O'Brien register char *cp; 592c80476e4SDavid E. O'Brien static char tmp[10]; 593c80476e4SDavid E. O'Brien 594c80476e4SDavid E. O'Brien cp = tmp; 595c80476e4SDavid E. O'Brien 596c80476e4SDavid E. O'Brien if (c & 0400) { 597c80476e4SDavid E. O'Brien *cp++ = 'A'; 598c80476e4SDavid E. O'Brien *cp++ = '-'; 599c80476e4SDavid E. O'Brien c &= APOLLO_0377; 600c80476e4SDavid E. O'Brien } 601c80476e4SDavid E. O'Brien if ((c & META) && !(Isprint(c) || (Iscntrl(c) && Isprint(c | 0100)))) { 602c80476e4SDavid E. O'Brien *cp++ = 'M'; 603c80476e4SDavid E. O'Brien *cp++ = '-'; 604c80476e4SDavid E. O'Brien c &= ASCII; 605c80476e4SDavid E. O'Brien } 606c80476e4SDavid E. O'Brien if (Isprint(c)) { 607c80476e4SDavid E. O'Brien *cp++ = (char) c; 608c80476e4SDavid E. O'Brien *cp = '\0'; 609c80476e4SDavid E. O'Brien return (tmp); 610c80476e4SDavid E. O'Brien } 611c80476e4SDavid E. O'Brien switch (c) { 612c80476e4SDavid E. O'Brien case ' ': 613c80476e4SDavid E. O'Brien (void) strcpy(cp, "Spc"); 614c80476e4SDavid E. O'Brien return (tmp); 615c80476e4SDavid E. O'Brien case '\n': 616c80476e4SDavid E. O'Brien (void) strcpy(cp, "Lfd"); 617c80476e4SDavid E. O'Brien return (tmp); 618c80476e4SDavid E. O'Brien case '\r': 619c80476e4SDavid E. O'Brien (void) strcpy(cp, "Ret"); 620c80476e4SDavid E. O'Brien return (tmp); 621c80476e4SDavid E. O'Brien case '\t': 622c80476e4SDavid E. O'Brien (void) strcpy(cp, "Tab"); 623c80476e4SDavid E. O'Brien return (tmp); 624c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 625c80476e4SDavid E. O'Brien case '\033': 626c80476e4SDavid E. O'Brien (void) strcpy(cp, "Esc"); 627c80476e4SDavid E. O'Brien return (tmp); 628c80476e4SDavid E. O'Brien case '\177': 629c80476e4SDavid E. O'Brien (void) strcpy(cp, "Del"); 630c80476e4SDavid E. O'Brien return (tmp); 631c80476e4SDavid E. O'Brien default: 632c80476e4SDavid E. O'Brien *cp++ = '^'; 633c80476e4SDavid E. O'Brien if (c == '\177') { 634c80476e4SDavid E. O'Brien *cp++ = '?'; 635c80476e4SDavid E. O'Brien } 636c80476e4SDavid E. O'Brien else { 637c80476e4SDavid E. O'Brien *cp++ = c | 0100; 638c80476e4SDavid E. O'Brien } 639c80476e4SDavid E. O'Brien *cp = '\0'; 640c80476e4SDavid E. O'Brien return (tmp); 641c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 642c80476e4SDavid E. O'Brien default: 643c80476e4SDavid E. O'Brien if (*cp == CTL_ESC('\033')) { 644c80476e4SDavid E. O'Brien (void) strcpy(cp, "Esc"); 645c80476e4SDavid E. O'Brien return (tmp); 646c80476e4SDavid E. O'Brien } 647c80476e4SDavid E. O'Brien else if (*cp == CTL_ESC('\177')) { 648c80476e4SDavid E. O'Brien (void) strcpy(cp, "Del"); 649c80476e4SDavid E. O'Brien return (tmp); 650c80476e4SDavid E. O'Brien } 651c80476e4SDavid E. O'Brien else if (Isupper(_toebcdic[_toascii[c]|0100]) 652c80476e4SDavid E. O'Brien || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL) { 653c80476e4SDavid E. O'Brien *cp++ = '^'; 654c80476e4SDavid E. O'Brien *cp++ = _toebcdic[_toascii[c]|0100] 655c80476e4SDavid E. O'Brien } 656c80476e4SDavid E. O'Brien else { 657c80476e4SDavid E. O'Brien xsnprintf(cp, 3, "\\%3.3o", c); 658c80476e4SDavid E. O'Brien cp += 4; 659c80476e4SDavid E. O'Brien } 660c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 661c80476e4SDavid E. O'Brien } 662c80476e4SDavid E. O'Brien } 663c80476e4SDavid E. O'Brien 664c80476e4SDavid E. O'Brien static KEYCMD 665c80476e4SDavid E. O'Brien getkeycmd(sp) 666c80476e4SDavid E. O'Brien Char **sp; 667c80476e4SDavid E. O'Brien { 668c80476e4SDavid E. O'Brien register Char *s = *sp; 669c80476e4SDavid E. O'Brien register char c; 670c80476e4SDavid E. O'Brien register KEYCMD keycmd = F_UNASSIGNED; 671c80476e4SDavid E. O'Brien KEYCMD *map; 672c80476e4SDavid E. O'Brien int meta = 0; 673c80476e4SDavid E. O'Brien Char *ret_sp = s; 674c80476e4SDavid E. O'Brien 675c80476e4SDavid E. O'Brien map = CcKeyMap; 676c80476e4SDavid E. O'Brien 677c80476e4SDavid E. O'Brien while (*s) { 678c80476e4SDavid E. O'Brien if (*s == '^' && s[1]) { 679c80476e4SDavid E. O'Brien s++; 680c80476e4SDavid E. O'Brien c = tocontrol(*s++); 681c80476e4SDavid E. O'Brien } 682c80476e4SDavid E. O'Brien else 683c80476e4SDavid E. O'Brien c = *s++; 684c80476e4SDavid E. O'Brien 685c80476e4SDavid E. O'Brien if (*s == '\0') 686c80476e4SDavid E. O'Brien break; 687c80476e4SDavid E. O'Brien 688c80476e4SDavid E. O'Brien switch (map[c | meta]) { 689c80476e4SDavid E. O'Brien case F_METANEXT: 690c80476e4SDavid E. O'Brien meta = META; 691c80476e4SDavid E. O'Brien keycmd = F_METANEXT; 692c80476e4SDavid E. O'Brien ret_sp = s; 693c80476e4SDavid E. O'Brien break; 694c80476e4SDavid E. O'Brien 695c80476e4SDavid E. O'Brien case F_XKEY: 696c80476e4SDavid E. O'Brien keycmd = F_XKEY; 697c80476e4SDavid E. O'Brien ret_sp = s; 698c80476e4SDavid E. O'Brien /* FALLTHROUGH */ 699c80476e4SDavid E. O'Brien 700c80476e4SDavid E. O'Brien default: 701c80476e4SDavid E. O'Brien *sp = ret_sp; 702c80476e4SDavid E. O'Brien return (keycmd); 703c80476e4SDavid E. O'Brien 704c80476e4SDavid E. O'Brien } 705c80476e4SDavid E. O'Brien } 706c80476e4SDavid E. O'Brien *sp = ret_sp; 707c80476e4SDavid E. O'Brien return (keycmd); 708c80476e4SDavid E. O'Brien } 709c80476e4SDavid E. O'Brien 710c80476e4SDavid E. O'Brien static int 711c80476e4SDavid E. O'Brien parsekey(sp) 712c80476e4SDavid E. O'Brien Char **sp; /* Return position of first unparsed character 713c80476e4SDavid E. O'Brien * for return value -2 (xkeynext) */ 714c80476e4SDavid E. O'Brien { 715c80476e4SDavid E. O'Brien register int c, meta = 0, control = 0, ctrlx = 0; 716c80476e4SDavid E. O'Brien Char *s = *sp; 717c80476e4SDavid E. O'Brien KEYCMD keycmd; 718c80476e4SDavid E. O'Brien 719c80476e4SDavid E. O'Brien if (s == NULL) { 720c80476e4SDavid E. O'Brien xprintf(CGETS(20, 27, "bad key specification -- null string\n")); 721c80476e4SDavid E. O'Brien return -1; 722c80476e4SDavid E. O'Brien } 723c80476e4SDavid E. O'Brien if (*s == 0) { 724c80476e4SDavid E. O'Brien xprintf(CGETS(20, 28, "bad key specification -- empty string\n")); 725c80476e4SDavid E. O'Brien return -1; 726c80476e4SDavid E. O'Brien } 727c80476e4SDavid E. O'Brien 728c80476e4SDavid E. O'Brien (void) strip(s); /* trim to 7 bits. */ 729c80476e4SDavid E. O'Brien 730c80476e4SDavid E. O'Brien if (s[1] == 0) /* single char */ 731c80476e4SDavid E. O'Brien return (s[0] & APOLLO_0377); 732c80476e4SDavid E. O'Brien 733c80476e4SDavid E. O'Brien if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') { 734c80476e4SDavid E. O'Brien if (s[2] == 0) { 735c80476e4SDavid E. O'Brien xprintf(CGETS(20, 29, 736c80476e4SDavid E. O'Brien "Bad function-key specification. Null key not allowed\n")); 737c80476e4SDavid E. O'Brien return (-1); 738c80476e4SDavid E. O'Brien } 739c80476e4SDavid E. O'Brien *sp = s + 2; 740c80476e4SDavid E. O'Brien return (-2); 741c80476e4SDavid E. O'Brien } 742c80476e4SDavid E. O'Brien 743c80476e4SDavid E. O'Brien if (s[0] == '0' && s[1] == 'x') { /* if 0xn, then assume number */ 744c80476e4SDavid E. O'Brien c = 0; 745c80476e4SDavid E. O'Brien for (s += 2; *s; s++) { /* convert to hex; skip the first 0 */ 746c80476e4SDavid E. O'Brien c *= 16; 747c80476e4SDavid E. O'Brien if (!Isxdigit(*s)) { 748c80476e4SDavid E. O'Brien xprintf(CGETS(20, 30, 749c80476e4SDavid E. O'Brien "bad key specification -- malformed hex number\n")); 750c80476e4SDavid E. O'Brien return -1; /* error */ 751c80476e4SDavid E. O'Brien } 752c80476e4SDavid E. O'Brien if (Isdigit(*s)) 753c80476e4SDavid E. O'Brien c += *s - '0'; 754c80476e4SDavid E. O'Brien else if (*s >= 'a' && *s <= 'f') 755c80476e4SDavid E. O'Brien c += *s - 'a' + 0xA; 756c80476e4SDavid E. O'Brien else if (*s >= 'F' && *s <= 'F') 757c80476e4SDavid E. O'Brien c += *s - 'A' + 0xA; 758c80476e4SDavid E. O'Brien } 759c80476e4SDavid E. O'Brien } 760c80476e4SDavid E. O'Brien else if (s[0] == '0' && Isdigit(s[1])) { /* if 0n, then assume number */ 761c80476e4SDavid E. O'Brien c = 0; 762c80476e4SDavid E. O'Brien for (s++; *s; s++) { /* convert to octal; skip the first 0 */ 763c80476e4SDavid E. O'Brien if (!Isdigit(*s) || *s == '8' || *s == '9') { 764c80476e4SDavid E. O'Brien xprintf(CGETS(20, 31, 765c80476e4SDavid E. O'Brien "bad key specification -- malformed octal number\n")); 766c80476e4SDavid E. O'Brien return -1; /* error */ 767c80476e4SDavid E. O'Brien } 768c80476e4SDavid E. O'Brien c = (c * 8) + *s - '0'; 769c80476e4SDavid E. O'Brien } 770c80476e4SDavid E. O'Brien } 771c80476e4SDavid E. O'Brien else if (Isdigit(s[0]) && Isdigit(s[1])) { /* decimal number */ 772c80476e4SDavid E. O'Brien c = 0; 773c80476e4SDavid E. O'Brien for (; *s; s++) { /* convert to octal; skip the first 0 */ 774c80476e4SDavid E. O'Brien if (!Isdigit(*s)) { 775c80476e4SDavid E. O'Brien xprintf(CGETS(20, 32, 776c80476e4SDavid E. O'Brien "bad key specification -- malformed decimal number\n")); 777c80476e4SDavid E. O'Brien return -1; /* error */ 778c80476e4SDavid E. O'Brien } 779c80476e4SDavid E. O'Brien c = (c * 10) + *s - '0'; 780c80476e4SDavid E. O'Brien } 781c80476e4SDavid E. O'Brien } 782c80476e4SDavid E. O'Brien else { 783c80476e4SDavid E. O'Brien keycmd = getkeycmd(&s); 784c80476e4SDavid E. O'Brien 785c80476e4SDavid E. O'Brien if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') { /* X- */ 786c80476e4SDavid E. O'Brien ctrlx++; 787c80476e4SDavid E. O'Brien s += 2; 788c80476e4SDavid E. O'Brien keycmd = getkeycmd(&s); 789c80476e4SDavid E. O'Brien } 790c80476e4SDavid E. O'Brien if ((*s == 'm' || *s == 'M') && s[1] == '-') { /* meta */ 791c80476e4SDavid E. O'Brien meta++; 792c80476e4SDavid E. O'Brien s += 2; 793c80476e4SDavid E. O'Brien keycmd = getkeycmd(&s); 794c80476e4SDavid E. O'Brien } 795c80476e4SDavid E. O'Brien else if (keycmd == F_METANEXT && *s) { /* meta */ 796c80476e4SDavid E. O'Brien meta++; 797c80476e4SDavid E. O'Brien keycmd = getkeycmd(&s); 798c80476e4SDavid E. O'Brien } 799c80476e4SDavid E. O'Brien if (*s == '^' && s[1]) { 800c80476e4SDavid E. O'Brien control++; 801c80476e4SDavid E. O'Brien s++; 802c80476e4SDavid E. O'Brien keycmd = getkeycmd(&s); 803c80476e4SDavid E. O'Brien } 804c80476e4SDavid E. O'Brien else if ((*s == 'c' || *s == 'C') && s[1] == '-') { /* control */ 805c80476e4SDavid E. O'Brien control++; 806c80476e4SDavid E. O'Brien s += 2; 807c80476e4SDavid E. O'Brien keycmd = getkeycmd(&s); 808c80476e4SDavid E. O'Brien } 809c80476e4SDavid E. O'Brien 810c80476e4SDavid E. O'Brien if (keycmd == F_XKEY) { 811c80476e4SDavid E. O'Brien if (*s == 0) { 812c80476e4SDavid E. O'Brien xprintf(CGETS(20, 33, 813c80476e4SDavid E. O'Brien "Bad function-key specification.\n")); 814c80476e4SDavid E. O'Brien xprintf(CGETS(20, 34, "Null key not allowed\n")); 815c80476e4SDavid E. O'Brien return (-1); 816c80476e4SDavid E. O'Brien } 817c80476e4SDavid E. O'Brien *sp = s; 818c80476e4SDavid E. O'Brien return (-2); 819c80476e4SDavid E. O'Brien } 820c80476e4SDavid E. O'Brien 821c80476e4SDavid E. O'Brien if (s[1] != 0) { /* if symbolic name */ 822c80476e4SDavid E. O'Brien char *ts; 823c80476e4SDavid E. O'Brien 824c80476e4SDavid E. O'Brien ts = short2str(s); 825c80476e4SDavid E. O'Brien if (!strcmp(ts, "space") || !strcmp(ts, "Spc")) 826c80476e4SDavid E. O'Brien c = ' '; 827c80476e4SDavid E. O'Brien else if (!strcmp(ts, "return") || !strcmp(ts, "Ret")) 828c80476e4SDavid E. O'Brien c = '\r'; 829c80476e4SDavid E. O'Brien else if (!strcmp(ts, "newline") || !strcmp(ts, "Lfd")) 830c80476e4SDavid E. O'Brien c = '\n'; 831c80476e4SDavid E. O'Brien else if (!strcmp(ts, "linefeed")) 832c80476e4SDavid E. O'Brien c = '\n'; 833c80476e4SDavid E. O'Brien else if (!strcmp(ts, "tab")) 834c80476e4SDavid E. O'Brien c = '\t'; 835c80476e4SDavid E. O'Brien else if (!strcmp(ts, "escape") || !strcmp(ts, "Esc")) 836c80476e4SDavid E. O'Brien c = CTL_ESC('\033'); 837c80476e4SDavid E. O'Brien else if (!strcmp(ts, "backspace")) 838c80476e4SDavid E. O'Brien c = '\b'; 839c80476e4SDavid E. O'Brien else if (!strcmp(ts, "delete")) 840c80476e4SDavid E. O'Brien c = CTL_ESC('\177'); 841c80476e4SDavid E. O'Brien else { 842c80476e4SDavid E. O'Brien xprintf(CGETS(20, 35, 843c80476e4SDavid E. O'Brien "bad key specification -- unknown name \"%S\"\n"), s); 844c80476e4SDavid E. O'Brien return -1; /* error */ 845c80476e4SDavid E. O'Brien } 846c80476e4SDavid E. O'Brien } 847c80476e4SDavid E. O'Brien else 848c80476e4SDavid E. O'Brien c = *s; /* just a single char */ 849c80476e4SDavid E. O'Brien 850c80476e4SDavid E. O'Brien if (control) 851c80476e4SDavid E. O'Brien c = tocontrol(c); 852c80476e4SDavid E. O'Brien if (meta) 853c80476e4SDavid E. O'Brien c |= META; 854c80476e4SDavid E. O'Brien if (ctrlx) 855c80476e4SDavid E. O'Brien c |= 0400; 856c80476e4SDavid E. O'Brien } 857c80476e4SDavid E. O'Brien return (c & 0777); 858c80476e4SDavid E. O'Brien } 859c80476e4SDavid E. O'Brien 860c80476e4SDavid E. O'Brien 861c80476e4SDavid E. O'Brien /*ARGSUSED*/ 862c80476e4SDavid E. O'Brien void 863c80476e4SDavid E. O'Brien dobind(v, dummy) 864c80476e4SDavid E. O'Brien register Char **v; 865c80476e4SDavid E. O'Brien struct command *dummy; 866c80476e4SDavid E. O'Brien { 867c80476e4SDavid E. O'Brien register int c; 868c80476e4SDavid E. O'Brien register struct KeyFuncs *fp; 869c80476e4SDavid E. O'Brien register int i, prev; 870c80476e4SDavid E. O'Brien Char *p, *l; 871c80476e4SDavid E. O'Brien CStr cstr; 872c80476e4SDavid E. O'Brien Char buf[1000]; 873c80476e4SDavid E. O'Brien 874c80476e4SDavid E. O'Brien USE(dummy); 875c80476e4SDavid E. O'Brien /* 876c80476e4SDavid E. O'Brien * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name, 877c80476e4SDavid E. O'Brien * and the key; or 'bind' key to print the func for that key. 878c80476e4SDavid E. O'Brien */ 879c80476e4SDavid E. O'Brien 880c80476e4SDavid E. O'Brien if (!MapsAreInited) 881c80476e4SDavid E. O'Brien ed_InitMaps(); 882c80476e4SDavid E. O'Brien 883c80476e4SDavid E. O'Brien if (v[1] && v[2] && v[3]) { 884c80476e4SDavid E. O'Brien xprintf(CGETS(20, 36, 885c80476e4SDavid E. O'Brien "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n")); 886c80476e4SDavid E. O'Brien return; 887c80476e4SDavid E. O'Brien } 888c80476e4SDavid E. O'Brien 889c80476e4SDavid E. O'Brien if (v[1] && v[2]) { /* if bind FUNCTION KEY */ 890c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 891c80476e4SDavid E. O'Brien if (strcmp(short2str(v[1]), fp->name) == 0) { 892c80476e4SDavid E. O'Brien Char *s = v[2]; 893c80476e4SDavid E. O'Brien 894c80476e4SDavid E. O'Brien if ((c = parsekey(&s)) == -1) 895c80476e4SDavid E. O'Brien return; 896c80476e4SDavid E. O'Brien if (c == -2) { /* extended key */ 897c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) { 898c80476e4SDavid E. O'Brien if (i != CTL_ESC('\033') && (CcKeyMap[i] == F_XKEY || 899c80476e4SDavid E. O'Brien CcAltMap[i] == F_XKEY)) { 900c80476e4SDavid E. O'Brien p = buf; 901c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX /* this is only for ASCII, not for EBCDIC */ 902c80476e4SDavid E. O'Brien if (i > 0177) { 903c80476e4SDavid E. O'Brien *p++ = 033; 904c80476e4SDavid E. O'Brien *p++ = i & ASCII; 905c80476e4SDavid E. O'Brien } 906c80476e4SDavid E. O'Brien else { 907c80476e4SDavid E. O'Brien *p++ = (Char) i; 908c80476e4SDavid E. O'Brien } 909c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 910c80476e4SDavid E. O'Brien *p++ = (Char) i; 911c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 912c80476e4SDavid E. O'Brien for (l = s; *l != 0; l++) { 913c80476e4SDavid E. O'Brien *p++ = *l; 914c80476e4SDavid E. O'Brien } 915c80476e4SDavid E. O'Brien *p = 0; 916c80476e4SDavid E. O'Brien cstr.buf = buf; 917c80476e4SDavid E. O'Brien cstr.len = Strlen(buf); 918c80476e4SDavid E. O'Brien AddXkey(&cstr, XmapCmd(fp->func), XK_CMD); 919c80476e4SDavid E. O'Brien } 920c80476e4SDavid E. O'Brien } 921c80476e4SDavid E. O'Brien return; 922c80476e4SDavid E. O'Brien } 923c80476e4SDavid E. O'Brien if (c & 0400) { 924c80476e4SDavid E. O'Brien if (VImode) { 925c80476e4SDavid E. O'Brien CcAltMap[c & APOLLO_0377] = fp->func; 926c80476e4SDavid E. O'Brien /* bind the vi cmd mode key */ 927c80476e4SDavid E. O'Brien if (c & META) { 928c80476e4SDavid E. O'Brien buf[0] = CTL_ESC('\033'); 929c80476e4SDavid E. O'Brien buf[1] = c & ASCII; 930c80476e4SDavid E. O'Brien buf[2] = 0; 931c80476e4SDavid E. O'Brien cstr.buf = buf; 932c80476e4SDavid E. O'Brien cstr.len = Strlen(buf); 933c80476e4SDavid E. O'Brien AddXkey(&cstr, XmapCmd(fp->func), XK_CMD); 934c80476e4SDavid E. O'Brien } 935c80476e4SDavid E. O'Brien } 936c80476e4SDavid E. O'Brien else { 937c80476e4SDavid E. O'Brien buf[0] = CTL_ESC('\030'); /* ^X */ 938c80476e4SDavid E. O'Brien buf[1] = c & APOLLO_0377; 939c80476e4SDavid E. O'Brien buf[2] = 0; 940c80476e4SDavid E. O'Brien cstr.buf = buf; 941c80476e4SDavid E. O'Brien cstr.len = Strlen(buf); 942c80476e4SDavid E. O'Brien AddXkey(&cstr, XmapCmd(fp->func), XK_CMD); 943c80476e4SDavid E. O'Brien CcKeyMap[CTL_ESC('\030')] = F_XKEY; 944c80476e4SDavid E. O'Brien } 945c80476e4SDavid E. O'Brien } 946c80476e4SDavid E. O'Brien else { 947c80476e4SDavid E. O'Brien CcKeyMap[c] = fp->func; /* bind the key */ 948c80476e4SDavid E. O'Brien if (c & META) { 949c80476e4SDavid E. O'Brien buf[0] = CTL_ESC('\033'); 950c80476e4SDavid E. O'Brien buf[1] = c & ASCII; 951c80476e4SDavid E. O'Brien buf[2] = 0; 952c80476e4SDavid E. O'Brien cstr.buf = buf; 953c80476e4SDavid E. O'Brien cstr.len = Strlen(buf); 954c80476e4SDavid E. O'Brien AddXkey(&cstr, XmapCmd(fp->func), XK_CMD); 955c80476e4SDavid E. O'Brien } 956c80476e4SDavid E. O'Brien } 957c80476e4SDavid E. O'Brien return; 958c80476e4SDavid E. O'Brien } 959c80476e4SDavid E. O'Brien } 960c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_STRING, CGETS(20, 37, "Invalid function")); 961c80476e4SDavid E. O'Brien } 962c80476e4SDavid E. O'Brien else if (v[1]) { 963c80476e4SDavid E. O'Brien char *cv = short2str(v[1]); 964c80476e4SDavid E. O'Brien 965c80476e4SDavid E. O'Brien if (strcmp(cv, "list") == 0) { 966c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 967c80476e4SDavid E. O'Brien xprintf("%s\n", fp->name); 968c80476e4SDavid E. O'Brien } 969c80476e4SDavid E. O'Brien return; 970c80476e4SDavid E. O'Brien } 971c80476e4SDavid E. O'Brien if ((strcmp(cv, "emacs") == 0) || 972c80476e4SDavid E. O'Brien #ifndef VIDEFAULT 973c80476e4SDavid E. O'Brien (strcmp(cv, "defaults") == 0) || 974c80476e4SDavid E. O'Brien (strcmp(cv, "default") == 0) || 975c80476e4SDavid E. O'Brien #endif 976c80476e4SDavid E. O'Brien (strcmp(cv, "mg") == 0) || 977c80476e4SDavid E. O'Brien (strcmp(cv, "gnumacs") == 0)) { 978c80476e4SDavid E. O'Brien /* reset keys to default */ 979c80476e4SDavid E. O'Brien ed_InitEmacsMaps(); 980c80476e4SDavid E. O'Brien #ifdef VIDEFAULT 981c80476e4SDavid E. O'Brien } 982c80476e4SDavid E. O'Brien else if ((strcmp(cv, "vi") == 0) 983c80476e4SDavid E. O'Brien || (strcmp(cv, "default") == 0) 984c80476e4SDavid E. O'Brien || (strcmp(cv, "defaults") == 0)) { 985c80476e4SDavid E. O'Brien #else 986c80476e4SDavid E. O'Brien } 987c80476e4SDavid E. O'Brien else if (strcmp(cv, "vi") == 0) { 988c80476e4SDavid E. O'Brien #endif 989c80476e4SDavid E. O'Brien ed_InitVIMaps(); 990c80476e4SDavid E. O'Brien } 991c80476e4SDavid E. O'Brien else { /* want to know what this key does */ 992c80476e4SDavid E. O'Brien Char *s = v[1]; 993c80476e4SDavid E. O'Brien 994c80476e4SDavid E. O'Brien if ((c = parsekey(&s)) == -1) 995c80476e4SDavid E. O'Brien return; 996c80476e4SDavid E. O'Brien if (c == -2) { /* extended key */ 997c80476e4SDavid E. O'Brien cstr.buf = s; 998c80476e4SDavid E. O'Brien cstr.len = Strlen(s); 999c80476e4SDavid E. O'Brien PrintXkey(&cstr); 1000c80476e4SDavid E. O'Brien return; 1001c80476e4SDavid E. O'Brien } 1002c80476e4SDavid E. O'Brien pkeys(c, c); /* must be regular key */ 1003c80476e4SDavid E. O'Brien } 1004c80476e4SDavid E. O'Brien } 1005c80476e4SDavid E. O'Brien else { /* list all the bindings */ 1006c80476e4SDavid E. O'Brien prev = 0; 1007c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) { 1008c80476e4SDavid E. O'Brien if (CcKeyMap[prev] == CcKeyMap[i]) 1009c80476e4SDavid E. O'Brien continue; 1010c80476e4SDavid E. O'Brien pkeys(prev, i - 1); 1011c80476e4SDavid E. O'Brien prev = i; 1012c80476e4SDavid E. O'Brien } 1013c80476e4SDavid E. O'Brien pkeys(prev, i - 1); 1014c80476e4SDavid E. O'Brien prev = 0; 1015c80476e4SDavid E. O'Brien for (i = 256; i < 512; i++) { 1016c80476e4SDavid E. O'Brien if (CcAltMap[prev & APOLLO_0377] == CcAltMap[i & APOLLO_0377]) 1017c80476e4SDavid E. O'Brien continue; 1018c80476e4SDavid E. O'Brien pkeys(prev, i - 1); 1019c80476e4SDavid E. O'Brien prev = i; 1020c80476e4SDavid E. O'Brien } 1021c80476e4SDavid E. O'Brien pkeys(prev, i - 1); 1022c80476e4SDavid E. O'Brien cstr.buf = NULL; 1023c80476e4SDavid E. O'Brien cstr.len = 0; 1024c80476e4SDavid E. O'Brien PrintXkey(&cstr); /* print all Xkey bindings */ 1025c80476e4SDavid E. O'Brien } 1026c80476e4SDavid E. O'Brien return; 1027c80476e4SDavid E. O'Brien } 1028c80476e4SDavid E. O'Brien 1029c80476e4SDavid E. O'Brien static void 1030c80476e4SDavid E. O'Brien pkeys(first, last) 1031c80476e4SDavid E. O'Brien register int first, last; 1032c80476e4SDavid E. O'Brien { 1033c80476e4SDavid E. O'Brien register struct KeyFuncs *fp; 1034c80476e4SDavid E. O'Brien register KEYCMD *map; 1035c80476e4SDavid E. O'Brien int mask; 1036c80476e4SDavid E. O'Brien char buf[8]; 1037c80476e4SDavid E. O'Brien 1038c80476e4SDavid E. O'Brien if (last & 0400) { 1039c80476e4SDavid E. O'Brien map = CcAltMap; 1040c80476e4SDavid E. O'Brien first &= APOLLO_0377; 1041c80476e4SDavid E. O'Brien last &= APOLLO_0377; 1042c80476e4SDavid E. O'Brien mask = 0400; 1043c80476e4SDavid E. O'Brien } 1044c80476e4SDavid E. O'Brien else { 1045c80476e4SDavid E. O'Brien map = CcKeyMap; 1046c80476e4SDavid E. O'Brien mask = 0; 1047c80476e4SDavid E. O'Brien } 1048c80476e4SDavid E. O'Brien if (map[first] == F_UNASSIGNED) { 1049c80476e4SDavid E. O'Brien if (first == last) 1050c80476e4SDavid E. O'Brien xprintf(CGETS(20, 38, " %s\t\tis undefined\n"), 1051c80476e4SDavid E. O'Brien unparsekey(first | mask)); 1052c80476e4SDavid E. O'Brien return; 1053c80476e4SDavid E. O'Brien } 1054c80476e4SDavid E. O'Brien 1055c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 1056c80476e4SDavid E. O'Brien if (fp->func == map[first]) { 1057c80476e4SDavid E. O'Brien if (first == last) 1058c80476e4SDavid E. O'Brien xprintf(" %s\t\t%s\n", 1059c80476e4SDavid E. O'Brien unparsekey((first & APOLLO_0377) | mask), fp->name); 1060c80476e4SDavid E. O'Brien else { 1061c80476e4SDavid E. O'Brien (void) strcpy(buf, unparsekey((first & APOLLO_0377) | mask)); 1062c80476e4SDavid E. O'Brien xprintf(" %s..%s\t\t%s\n", buf, 1063c80476e4SDavid E. O'Brien unparsekey((last & APOLLO_0377) | mask), fp->name); 1064c80476e4SDavid E. O'Brien } 1065c80476e4SDavid E. O'Brien return; 1066c80476e4SDavid E. O'Brien } 1067c80476e4SDavid E. O'Brien } 1068c80476e4SDavid E. O'Brien if (map == CcKeyMap) { 1069c80476e4SDavid E. O'Brien xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), 1070c80476e4SDavid E. O'Brien unparsekey(first)); 1071c80476e4SDavid E. O'Brien xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]); 1072c80476e4SDavid E. O'Brien } 1073c80476e4SDavid E. O'Brien else { 1074c80476e4SDavid E. O'Brien xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), 1075c80476e4SDavid E. O'Brien unparsekey(first & 0400)); 1076c80476e4SDavid E. O'Brien xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]); 1077c80476e4SDavid E. O'Brien } 1078c80476e4SDavid E. O'Brien } 1079c80476e4SDavid E. O'Brien #endif /* OBSOLETE */ 1080