145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/tc.bind.c,v 3.44 2006/03/02 18:46:44 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. 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 3545e5710bSMark Peek RCSID("$tcsh: tc.bind.c,v 3.44 2006/03/02 18:46:44 christos Exp $") 36c80476e4SDavid E. O'Brien 37c80476e4SDavid E. O'Brien #include "ed.h" 38c80476e4SDavid E. O'Brien #include "ed.defns.h" 39c80476e4SDavid E. O'Brien 4045e5710bSMark Peek static void printkey (const KEYCMD *, CStr *); 4145e5710bSMark Peek static KEYCMD parsecmd (Char *); 4245e5710bSMark Peek static void bad_spec (const Char *); 4345e5710bSMark Peek static CStr *parsestring (const Char *, CStr *); 4445e5710bSMark Peek static CStr *parsebind (const Char *, CStr *); 4545e5710bSMark Peek static void print_all_keys (void); 4645e5710bSMark Peek static void printkeys (KEYCMD *, int, int); 4745e5710bSMark Peek static void bindkey_usage (void); 4845e5710bSMark Peek static void list_functions (void); 49c80476e4SDavid E. O'Brien 50c80476e4SDavid E. O'Brien extern int MapsAreInited; 51c80476e4SDavid E. O'Brien 52c80476e4SDavid E. O'Brien 53c80476e4SDavid E. O'Brien 54c80476e4SDavid E. O'Brien 55c80476e4SDavid E. O'Brien /*ARGSUSED*/ 56c80476e4SDavid E. O'Brien void 5745e5710bSMark Peek dobindkey(Char **v, struct command *c) 58c80476e4SDavid E. O'Brien { 59c80476e4SDavid E. O'Brien KEYCMD *map; 6023338178SMark Peek int ntype, no, removeb, key, bindk; 61c80476e4SDavid E. O'Brien Char *par; 62c80476e4SDavid E. O'Brien Char p; 63c80476e4SDavid E. O'Brien KEYCMD cmd; 64c80476e4SDavid E. O'Brien CStr in; 65c80476e4SDavid E. O'Brien CStr out; 66c80476e4SDavid E. O'Brien uChar ch; 67c80476e4SDavid E. O'Brien 68c80476e4SDavid E. O'Brien USE(c); 69c80476e4SDavid E. O'Brien if (!MapsAreInited) 70c80476e4SDavid E. O'Brien ed_InitMaps(); 71c80476e4SDavid E. O'Brien 72c80476e4SDavid E. O'Brien map = CcKeyMap; 73c80476e4SDavid E. O'Brien ntype = XK_CMD; 7423338178SMark Peek key = removeb = bindk = 0; 75c80476e4SDavid E. O'Brien for (no = 1, par = v[no]; 76c80476e4SDavid E. O'Brien par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) { 77c80476e4SDavid E. O'Brien if ((p = (*par & CHAR)) == '-') { 78c80476e4SDavid E. O'Brien no++; 79c80476e4SDavid E. O'Brien break; 80c80476e4SDavid E. O'Brien } 81c80476e4SDavid E. O'Brien else 82c80476e4SDavid E. O'Brien switch (p) { 83c80476e4SDavid E. O'Brien case 'b': 8423338178SMark Peek bindk = 1; 85c80476e4SDavid E. O'Brien break; 86c80476e4SDavid E. O'Brien case 'k': 87c80476e4SDavid E. O'Brien key = 1; 88c80476e4SDavid E. O'Brien break; 89c80476e4SDavid E. O'Brien case 'a': 90c80476e4SDavid E. O'Brien map = CcAltMap; 91c80476e4SDavid E. O'Brien break; 92c80476e4SDavid E. O'Brien case 's': 93c80476e4SDavid E. O'Brien ntype = XK_STR; 94c80476e4SDavid E. O'Brien break; 95c80476e4SDavid E. O'Brien case 'c': 96c80476e4SDavid E. O'Brien ntype = XK_EXE; 97c80476e4SDavid E. O'Brien break; 98c80476e4SDavid E. O'Brien case 'r': 9923338178SMark Peek removeb = 1; 100c80476e4SDavid E. O'Brien break; 101c80476e4SDavid E. O'Brien case 'v': 102c80476e4SDavid E. O'Brien ed_InitVIMaps(); 103c80476e4SDavid E. O'Brien return; 104c80476e4SDavid E. O'Brien case 'e': 105c80476e4SDavid E. O'Brien ed_InitEmacsMaps(); 106c80476e4SDavid E. O'Brien return; 107c80476e4SDavid E. O'Brien case 'd': 108c80476e4SDavid E. O'Brien #ifdef VIDEFAULT 109c80476e4SDavid E. O'Brien ed_InitVIMaps(); 110c80476e4SDavid E. O'Brien #else /* EMACSDEFAULT */ 111c80476e4SDavid E. O'Brien ed_InitEmacsMaps(); 112c80476e4SDavid E. O'Brien #endif /* VIDEFAULT */ 113c80476e4SDavid E. O'Brien return; 114c80476e4SDavid E. O'Brien case 'l': 115c80476e4SDavid E. O'Brien list_functions(); 116c80476e4SDavid E. O'Brien return; 117c80476e4SDavid E. O'Brien default: 118c80476e4SDavid E. O'Brien bindkey_usage(); 119c80476e4SDavid E. O'Brien return; 120c80476e4SDavid E. O'Brien } 121c80476e4SDavid E. O'Brien } 122c80476e4SDavid E. O'Brien 123c80476e4SDavid E. O'Brien if (!v[no]) { 124c80476e4SDavid E. O'Brien print_all_keys(); 125c80476e4SDavid E. O'Brien return; 126c80476e4SDavid E. O'Brien } 127c80476e4SDavid E. O'Brien 128c80476e4SDavid E. O'Brien if (key) { 129c80476e4SDavid E. O'Brien if (!IsArrowKey(v[no])) 130c80476e4SDavid E. O'Brien xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]); 13145e5710bSMark Peek in.buf = Strsave(v[no++]); 132c80476e4SDavid E. O'Brien in.len = Strlen(in.buf); 133c80476e4SDavid E. O'Brien } 134c80476e4SDavid E. O'Brien else { 13523338178SMark Peek if (bindk) { 136c80476e4SDavid E. O'Brien if (parsebind(v[no++], &in) == NULL) 137c80476e4SDavid E. O'Brien return; 138c80476e4SDavid E. O'Brien } 139c80476e4SDavid E. O'Brien else { 140c80476e4SDavid E. O'Brien if (parsestring(v[no++], &in) == NULL) 141c80476e4SDavid E. O'Brien return; 142c80476e4SDavid E. O'Brien } 143c80476e4SDavid E. O'Brien } 14445e5710bSMark Peek cleanup_push(in.buf, xfree); 145c80476e4SDavid E. O'Brien 14623338178SMark Peek #ifndef WINNT_NATIVE 14723338178SMark Peek if (in.buf[0] > 0xFF) { 14823338178SMark Peek bad_spec(in.buf); 14945e5710bSMark Peek cleanup_until(in.buf); 15023338178SMark Peek return; 15123338178SMark Peek } 15223338178SMark Peek #endif 153c80476e4SDavid E. O'Brien ch = (uChar) in.buf[0]; 154c80476e4SDavid E. O'Brien 15523338178SMark Peek if (removeb) { 15645e5710bSMark Peek if (key) 157c80476e4SDavid E. O'Brien (void) ClearArrowKeys(&in); 15845e5710bSMark Peek else if (in.len > 1) { 159c80476e4SDavid E. O'Brien (void) DeleteXkey(&in); 160c80476e4SDavid E. O'Brien } 161c80476e4SDavid E. O'Brien else if (map[ch] == F_XKEY) { 162c80476e4SDavid E. O'Brien (void) DeleteXkey(&in); 163c80476e4SDavid E. O'Brien map[ch] = F_UNASSIGNED; 164c80476e4SDavid E. O'Brien } 165c80476e4SDavid E. O'Brien else { 166c80476e4SDavid E. O'Brien map[ch] = F_UNASSIGNED; 167c80476e4SDavid E. O'Brien } 16845e5710bSMark Peek cleanup_until(in.buf); 169c80476e4SDavid E. O'Brien return; 170c80476e4SDavid E. O'Brien } 171c80476e4SDavid E. O'Brien if (!v[no]) { 172c80476e4SDavid E. O'Brien if (key) 173c80476e4SDavid E. O'Brien PrintArrowKeys(&in); 174c80476e4SDavid E. O'Brien else 175c80476e4SDavid E. O'Brien printkey(map, &in); 17645e5710bSMark Peek cleanup_until(in.buf); 177c80476e4SDavid E. O'Brien return; 178c80476e4SDavid E. O'Brien } 179c80476e4SDavid E. O'Brien if (v[no + 1]) { 180c80476e4SDavid E. O'Brien bindkey_usage(); 18145e5710bSMark Peek cleanup_until(in.buf); 182c80476e4SDavid E. O'Brien return; 183c80476e4SDavid E. O'Brien } 184c80476e4SDavid E. O'Brien switch (ntype) { 185c80476e4SDavid E. O'Brien case XK_STR: 186c80476e4SDavid E. O'Brien case XK_EXE: 18745e5710bSMark Peek if (parsestring(v[no], &out) == NULL) { 18845e5710bSMark Peek cleanup_until(in.buf); 189c80476e4SDavid E. O'Brien return; 19045e5710bSMark Peek } 19145e5710bSMark Peek cleanup_push(out.buf, xfree); 192c80476e4SDavid E. O'Brien if (key) { 193c80476e4SDavid E. O'Brien if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1) 19423338178SMark Peek xprintf(CGETS(20, 2, "Bad key name: %S\n"), in.buf); 19545e5710bSMark Peek else 19645e5710bSMark Peek cleanup_ignore(out.buf); 197c80476e4SDavid E. O'Brien } 198c80476e4SDavid E. O'Brien else 199c80476e4SDavid E. O'Brien AddXkey(&in, XmapStr(&out), ntype); 200c80476e4SDavid E. O'Brien map[ch] = F_XKEY; 201c80476e4SDavid E. O'Brien break; 202c80476e4SDavid E. O'Brien case XK_CMD: 20345e5710bSMark Peek if ((cmd = parsecmd(v[no])) == 0) { 20445e5710bSMark Peek cleanup_until(in.buf); 205c80476e4SDavid E. O'Brien return; 20645e5710bSMark Peek } 207c80476e4SDavid E. O'Brien if (key) 208c80476e4SDavid E. O'Brien (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype); 209c80476e4SDavid E. O'Brien else { 210c80476e4SDavid E. O'Brien if (in.len > 1) { 211c80476e4SDavid E. O'Brien AddXkey(&in, XmapCmd((int) cmd), ntype); 212c80476e4SDavid E. O'Brien map[ch] = F_XKEY; 213c80476e4SDavid E. O'Brien } 214c80476e4SDavid E. O'Brien else { 215c80476e4SDavid E. O'Brien ClearXkey(map, &in); 216c80476e4SDavid E. O'Brien map[ch] = cmd; 217c80476e4SDavid E. O'Brien } 218c80476e4SDavid E. O'Brien } 219c80476e4SDavid E. O'Brien break; 220c80476e4SDavid E. O'Brien default: 221c80476e4SDavid E. O'Brien abort(); 222c80476e4SDavid E. O'Brien break; 223c80476e4SDavid E. O'Brien } 22445e5710bSMark Peek cleanup_until(in.buf); 225c80476e4SDavid E. O'Brien if (key) 226c80476e4SDavid E. O'Brien BindArrowKeys(); 227c80476e4SDavid E. O'Brien } 228c80476e4SDavid E. O'Brien 229c80476e4SDavid E. O'Brien static void 23045e5710bSMark Peek printkey(const KEYCMD *map, CStr *in) 231c80476e4SDavid E. O'Brien { 23223338178SMark Peek struct KeyFuncs *fp; 233c80476e4SDavid E. O'Brien 234c80476e4SDavid E. O'Brien if (in->len < 2) { 23545e5710bSMark Peek unsigned char *unparsed; 23645e5710bSMark Peek 23745e5710bSMark Peek unparsed = unparsestring(in, STRQQ); 23845e5710bSMark Peek cleanup_push(unparsed, xfree); 239c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 240c80476e4SDavid E. O'Brien if (fp->func == map[(uChar) *(in->buf)]) { 24145e5710bSMark Peek xprintf("%s\t->\t%s\n", unparsed, fp->name); 242c80476e4SDavid E. O'Brien } 243c80476e4SDavid E. O'Brien } 24445e5710bSMark Peek cleanup_until(unparsed); 245c80476e4SDavid E. O'Brien } 246c80476e4SDavid E. O'Brien else 247c80476e4SDavid E. O'Brien PrintXkey(in); 248c80476e4SDavid E. O'Brien } 249c80476e4SDavid E. O'Brien 250c80476e4SDavid E. O'Brien static KEYCMD 25145e5710bSMark Peek parsecmd(Char *str) 252c80476e4SDavid E. O'Brien { 25323338178SMark Peek struct KeyFuncs *fp; 254c80476e4SDavid E. O'Brien 255c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 256c80476e4SDavid E. O'Brien if (strcmp(short2str(str), fp->name) == 0) { 257c80476e4SDavid E. O'Brien return (KEYCMD) fp->func; 258c80476e4SDavid E. O'Brien } 259c80476e4SDavid E. O'Brien } 260c80476e4SDavid E. O'Brien xprintf(CGETS(20, 3, "Bad command name: %S\n"), str); 261c80476e4SDavid E. O'Brien return 0; 262c80476e4SDavid E. O'Brien } 263c80476e4SDavid E. O'Brien 264c80476e4SDavid E. O'Brien 265c80476e4SDavid E. O'Brien static void 26645e5710bSMark Peek bad_spec(const Char *str) 267c80476e4SDavid E. O'Brien { 268c80476e4SDavid E. O'Brien xprintf(CGETS(20, 4, "Bad key spec %S\n"), str); 269c80476e4SDavid E. O'Brien } 270c80476e4SDavid E. O'Brien 271c80476e4SDavid E. O'Brien static CStr * 27245e5710bSMark Peek parsebind(const Char *s, CStr *str) 273c80476e4SDavid E. O'Brien { 27445e5710bSMark Peek struct Strbuf b = Strbuf_INIT; 275c80476e4SDavid E. O'Brien 27645e5710bSMark Peek cleanup_push(&b, Strbuf_cleanup); 277c80476e4SDavid E. O'Brien if (Iscntrl(*s)) { 27845e5710bSMark Peek Strbuf_append1(&b, *s); 27945e5710bSMark Peek goto end; 280c80476e4SDavid E. O'Brien } 281c80476e4SDavid E. O'Brien 282c80476e4SDavid E. O'Brien switch (*s) { 283c80476e4SDavid E. O'Brien case '^': 284c80476e4SDavid E. O'Brien s++; 2853b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 28645e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? '\177' : ((*s & CHAR) & 0237)); 2873b6eaa7bSAndrey A. Chernov #else 28845e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? CTL_ESC('\177') 28945e5710bSMark Peek : _toebcdic[_toascii[*s & CHAR] & 0237]); 2903b6eaa7bSAndrey A. Chernov #endif 291c80476e4SDavid E. O'Brien break; 292c80476e4SDavid E. O'Brien 293c80476e4SDavid E. O'Brien case 'F': 294c80476e4SDavid E. O'Brien case 'M': 295c80476e4SDavid E. O'Brien case 'X': 296c80476e4SDavid E. O'Brien case 'C': 2973b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 298c80476e4SDavid E. O'Brien case 'N': 2993b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 30045e5710bSMark Peek if (s[1] != '-' || s[2] == '\0') 30145e5710bSMark Peek goto bad_spec; 302c80476e4SDavid E. O'Brien s += 2; 303c80476e4SDavid E. O'Brien switch (s[-2]) { 304c80476e4SDavid E. O'Brien case 'F': case 'f': /* Turn into ^[str */ 30545e5710bSMark Peek Strbuf_append1(&b, CTL_ESC('\033')); 30645e5710bSMark Peek Strbuf_append(&b, s); 307c80476e4SDavid E. O'Brien break; 308c80476e4SDavid E. O'Brien 309c80476e4SDavid E. O'Brien case 'C': case 'c': /* Turn into ^c */ 3103b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 31145e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? '\177' : ((*s & CHAR) & 0237)); 3123b6eaa7bSAndrey A. Chernov #else 31345e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? CTL_ESC('\177') 31445e5710bSMark Peek : _toebcdic[_toascii[*s & CHAR] & 0237]); 3153b6eaa7bSAndrey A. Chernov #endif 316c80476e4SDavid E. O'Brien break; 317c80476e4SDavid E. O'Brien 318c80476e4SDavid E. O'Brien case 'X' : case 'x': /* Turn into ^Xc */ 3193b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 32045e5710bSMark Peek Strbuf_append1(&b, 'X' & 0237); 3213b6eaa7bSAndrey A. Chernov #else 32245e5710bSMark Peek Strbuf_append1(&b, _toebcdic[_toascii['X'] & 0237]); 3233b6eaa7bSAndrey A. Chernov #endif 32445e5710bSMark Peek Strbuf_append1(&b, *s); 325c80476e4SDavid E. O'Brien break; 326c80476e4SDavid E. O'Brien 327c80476e4SDavid E. O'Brien case 'M' : case 'm': /* Turn into 0x80|c */ 328c80476e4SDavid E. O'Brien if (!NoNLSRebind) { 32945e5710bSMark Peek Strbuf_append1(&b, CTL_ESC('\033')); 33045e5710bSMark Peek Strbuf_append1(&b, *s); 331c80476e4SDavid E. O'Brien } else { 3323b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 33345e5710bSMark Peek Strbuf_append1(&b, *s | 0x80); 3343b6eaa7bSAndrey A. Chernov #else 33545e5710bSMark Peek Strbuf_append1(&b, _toebcdic[_toascii[*s] | 0x80]); 3363b6eaa7bSAndrey A. Chernov #endif 337c80476e4SDavid E. O'Brien } 338c80476e4SDavid E. O'Brien break; 3393b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 340c80476e4SDavid E. O'Brien case 'N' : case 'n': /* NT */ 341c80476e4SDavid E. O'Brien { 342c80476e4SDavid E. O'Brien Char bnt; 343c80476e4SDavid E. O'Brien 344c80476e4SDavid E. O'Brien bnt = nt_translate_bindkey(s); 345c80476e4SDavid E. O'Brien if (bnt != 0) 34645e5710bSMark Peek Strbuf_append1(&b, bnt); 347c80476e4SDavid E. O'Brien else 348c80476e4SDavid E. O'Brien bad_spec(s); 349c80476e4SDavid E. O'Brien } 350c80476e4SDavid E. O'Brien break; 3513b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 352c80476e4SDavid E. O'Brien 353c80476e4SDavid E. O'Brien default: 354c80476e4SDavid E. O'Brien abort(); 355c80476e4SDavid E. O'Brien } 356c80476e4SDavid E. O'Brien break; 357c80476e4SDavid E. O'Brien 358c80476e4SDavid E. O'Brien default: 35945e5710bSMark Peek goto bad_spec; 360c80476e4SDavid E. O'Brien } 361c80476e4SDavid E. O'Brien 36245e5710bSMark Peek end: 36345e5710bSMark Peek cleanup_ignore(&b); 36445e5710bSMark Peek cleanup_until(&b); 36545e5710bSMark Peek Strbuf_terminate(&b); 36645e5710bSMark Peek str->buf = xrealloc(b.s, (b.len + 1) * sizeof (*str->buf)); 36745e5710bSMark Peek str->len = b.len; 368c80476e4SDavid E. O'Brien return str; 36945e5710bSMark Peek 37045e5710bSMark Peek bad_spec: 37145e5710bSMark Peek bad_spec(s); 37245e5710bSMark Peek cleanup_until(&b); 37345e5710bSMark Peek return NULL; 374c80476e4SDavid E. O'Brien } 375c80476e4SDavid E. O'Brien 376c80476e4SDavid E. O'Brien 377c80476e4SDavid E. O'Brien static CStr * 37845e5710bSMark Peek parsestring(const Char *str, CStr *buf) 379c80476e4SDavid E. O'Brien { 38045e5710bSMark Peek struct Strbuf b = Strbuf_INIT; 381c80476e4SDavid E. O'Brien const Char *p; 38223338178SMark Peek eChar es; 383c80476e4SDavid E. O'Brien 384c80476e4SDavid E. O'Brien if (*str == 0) { 385c80476e4SDavid E. O'Brien xprintf(CGETS(20, 5, "Null string specification\n")); 386c80476e4SDavid E. O'Brien return NULL; 387c80476e4SDavid E. O'Brien } 388c80476e4SDavid E. O'Brien 38945e5710bSMark Peek cleanup_push(&b, Strbuf_cleanup); 390c80476e4SDavid E. O'Brien for (p = str; *p != 0; p++) { 391c80476e4SDavid E. O'Brien if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') { 39245e5710bSMark Peek if ((es = parseescape(&p)) == CHAR_ERR) { 39345e5710bSMark Peek cleanup_until(&b); 394c80476e4SDavid E. O'Brien return 0; 39545e5710bSMark Peek } else 39645e5710bSMark Peek Strbuf_append1(&b, es); 397c80476e4SDavid E. O'Brien } 398c80476e4SDavid E. O'Brien else 39945e5710bSMark Peek Strbuf_append1(&b, *p & CHAR); 400c80476e4SDavid E. O'Brien } 40145e5710bSMark Peek cleanup_ignore(&b); 40245e5710bSMark Peek cleanup_until(&b); 40345e5710bSMark Peek Strbuf_terminate(&b); 40445e5710bSMark Peek buf->buf = xrealloc(b.s, (b.len + 1) * sizeof (*buf->buf)); 40545e5710bSMark Peek buf->len = b.len; 406c80476e4SDavid E. O'Brien return buf; 407c80476e4SDavid E. O'Brien } 408c80476e4SDavid E. O'Brien 409c80476e4SDavid E. O'Brien static void 41045e5710bSMark Peek print_all_keys(void) 411c80476e4SDavid E. O'Brien { 412c80476e4SDavid E. O'Brien int prev, i; 413c80476e4SDavid E. O'Brien CStr nilstr; 414c80476e4SDavid E. O'Brien nilstr.buf = NULL; 415c80476e4SDavid E. O'Brien nilstr.len = 0; 416c80476e4SDavid E. O'Brien 417c80476e4SDavid E. O'Brien 418c80476e4SDavid E. O'Brien xprintf(CGETS(20, 6, "Standard key bindings\n")); 419c80476e4SDavid E. O'Brien prev = 0; 420c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) { 421c80476e4SDavid E. O'Brien if (CcKeyMap[prev] == CcKeyMap[i]) 422c80476e4SDavid E. O'Brien continue; 423c80476e4SDavid E. O'Brien printkeys(CcKeyMap, prev, i - 1); 424c80476e4SDavid E. O'Brien prev = i; 425c80476e4SDavid E. O'Brien } 426c80476e4SDavid E. O'Brien printkeys(CcKeyMap, prev, i - 1); 427c80476e4SDavid E. O'Brien 428c80476e4SDavid E. O'Brien xprintf(CGETS(20, 7, "Alternative key bindings\n")); 429c80476e4SDavid E. O'Brien prev = 0; 430c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) { 431c80476e4SDavid E. O'Brien if (CcAltMap[prev] == CcAltMap[i]) 432c80476e4SDavid E. O'Brien continue; 433c80476e4SDavid E. O'Brien printkeys(CcAltMap, prev, i - 1); 434c80476e4SDavid E. O'Brien prev = i; 435c80476e4SDavid E. O'Brien } 436c80476e4SDavid E. O'Brien printkeys(CcAltMap, prev, i - 1); 437c80476e4SDavid E. O'Brien xprintf(CGETS(20, 8, "Multi-character bindings\n")); 438c80476e4SDavid E. O'Brien PrintXkey(NULL); /* print all Xkey bindings */ 439c80476e4SDavid E. O'Brien xprintf(CGETS(20, 9, "Arrow key bindings\n")); 440c80476e4SDavid E. O'Brien PrintArrowKeys(&nilstr); 441c80476e4SDavid E. O'Brien } 442c80476e4SDavid E. O'Brien 443c80476e4SDavid E. O'Brien static void 44445e5710bSMark Peek printkeys(KEYCMD *map, int first, int last) 445c80476e4SDavid E. O'Brien { 44623338178SMark Peek struct KeyFuncs *fp; 447c80476e4SDavid E. O'Brien Char firstbuf[2], lastbuf[2]; 448c80476e4SDavid E. O'Brien CStr fb, lb; 44945e5710bSMark Peek unsigned char *unparsed; 450c80476e4SDavid E. O'Brien fb.buf = firstbuf; 451c80476e4SDavid E. O'Brien lb.buf = lastbuf; 452c80476e4SDavid E. O'Brien 453c80476e4SDavid E. O'Brien firstbuf[0] = (Char) first; 454c80476e4SDavid E. O'Brien firstbuf[1] = 0; 455c80476e4SDavid E. O'Brien lastbuf[0] = (Char) last; 456c80476e4SDavid E. O'Brien lastbuf[1] = 0; 457c80476e4SDavid E. O'Brien fb.len = 1; 458c80476e4SDavid E. O'Brien lb.len = 1; 459c80476e4SDavid E. O'Brien 46045e5710bSMark Peek unparsed = unparsestring(&fb, STRQQ); 46145e5710bSMark Peek cleanup_push(unparsed, xfree); 462c80476e4SDavid E. O'Brien if (map[first] == F_UNASSIGNED) { 463c80476e4SDavid E. O'Brien if (first == last) 46445e5710bSMark Peek xprintf(CGETS(20, 10, "%-15s-> is undefined\n"), unparsed); 46545e5710bSMark Peek cleanup_until(unparsed); 466c80476e4SDavid E. O'Brien return; 467c80476e4SDavid E. O'Brien } 468c80476e4SDavid E. O'Brien 469c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 470c80476e4SDavid E. O'Brien if (fp->func == map[first]) { 47145e5710bSMark Peek if (first == last) 47245e5710bSMark Peek xprintf("%-15s-> %s\n", unparsed, fp->name); 473c80476e4SDavid E. O'Brien else { 47445e5710bSMark Peek unsigned char *p; 47545e5710bSMark Peek 47645e5710bSMark Peek p = unparsestring(&lb, STRQQ); 47745e5710bSMark Peek cleanup_push(p, xfree); 47845e5710bSMark Peek xprintf("%-4s to %-7s-> %s\n", unparsed, p, fp->name); 479c80476e4SDavid E. O'Brien } 48045e5710bSMark Peek cleanup_until(unparsed); 481c80476e4SDavid E. O'Brien return; 482c80476e4SDavid E. O'Brien } 483c80476e4SDavid E. O'Brien } 48445e5710bSMark Peek xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), unparsed); 48545e5710bSMark Peek if (map == CcKeyMap) 486c80476e4SDavid E. O'Brien xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]); 48745e5710bSMark Peek else 488c80476e4SDavid E. O'Brien xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]); 48945e5710bSMark Peek cleanup_until(unparsed); 490c80476e4SDavid E. O'Brien } 491c80476e4SDavid E. O'Brien 492c80476e4SDavid E. O'Brien static void 49345e5710bSMark Peek bindkey_usage(void) 494c80476e4SDavid E. O'Brien { 495c80476e4SDavid E. O'Brien xprintf(CGETS(20, 12, 496c80476e4SDavid E. O'Brien "Usage: bindkey [options] [--] [KEY [COMMAND]]\n")); 497c80476e4SDavid E. O'Brien xprintf(CGETS(20, 13, 498c80476e4SDavid E. O'Brien " -a list or bind KEY in alternative key map\n")); 499c80476e4SDavid E. O'Brien xprintf(CGETS(20, 14, 500c80476e4SDavid E. O'Brien " -b interpret KEY as a C-, M-, F- or X- key name\n")); 501c80476e4SDavid E. O'Brien xprintf(CGETS(20, 15, 502c80476e4SDavid E. O'Brien " -s interpret COMMAND as a literal string to be output\n")); 503c80476e4SDavid E. O'Brien xprintf(CGETS(20, 16, 504c80476e4SDavid E. O'Brien " -c interpret COMMAND as a builtin or external command\n")); 505c80476e4SDavid E. O'Brien xprintf(CGETS(20, 17, 506c80476e4SDavid E. O'Brien " -v bind all keys to vi bindings\n")); 507c80476e4SDavid E. O'Brien xprintf(CGETS(20, 18, 508c80476e4SDavid E. O'Brien " -e bind all keys to emacs bindings\n")); 509c80476e4SDavid E. O'Brien xprintf(CGETS(20, 19, 510c80476e4SDavid E. O'Brien " -d bind all keys to default editor's bindings\n")); 511c80476e4SDavid E. O'Brien xprintf(CGETS(20, 20, 512c80476e4SDavid E. O'Brien " -l list editor commands with descriptions\n")); 513c80476e4SDavid E. O'Brien xprintf(CGETS(20, 21, 514c80476e4SDavid E. O'Brien " -r remove KEY's binding\n")); 515c80476e4SDavid E. O'Brien xprintf(CGETS(20, 22, 516c80476e4SDavid E. O'Brien " -k interpret KEY as a symbolic arrow-key name\n")); 517c80476e4SDavid E. O'Brien xprintf(CGETS(20, 23, 518c80476e4SDavid E. O'Brien " -- force a break from option processing\n")); 519c80476e4SDavid E. O'Brien xprintf(CGETS(20, 24, 520c80476e4SDavid E. O'Brien " -u (or any invalid option) this message\n")); 521c80476e4SDavid E. O'Brien xprintf("\n"); 522c80476e4SDavid E. O'Brien xprintf(CGETS(20, 25, 523c80476e4SDavid E. O'Brien "Without KEY or COMMAND, prints all bindings\n")); 524c80476e4SDavid E. O'Brien xprintf(CGETS(20, 26, 525c80476e4SDavid E. O'Brien "Without COMMAND, prints the binding for KEY.\n")); 526c80476e4SDavid E. O'Brien } 527c80476e4SDavid E. O'Brien 528c80476e4SDavid E. O'Brien static void 52945e5710bSMark Peek list_functions(void) 530c80476e4SDavid E. O'Brien { 53123338178SMark Peek struct KeyFuncs *fp; 532c80476e4SDavid E. O'Brien 533c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) { 534c80476e4SDavid E. O'Brien xprintf("%s\n %s\n", fp->name, fp->desc); 535c80476e4SDavid E. O'Brien } 536c80476e4SDavid E. O'Brien } 537