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