xref: /dragonfly/contrib/tcsh-6/tc.bind.c (revision d6ab524c)
17d8fb588SMatthias Schmidt /*
27d8fb588SMatthias Schmidt  * tc.bind.c: Key binding functions
37d8fb588SMatthias Schmidt  */
47d8fb588SMatthias Schmidt /*-
57d8fb588SMatthias Schmidt  * Copyright (c) 1980, 1991 The Regents of the University of California.
67d8fb588SMatthias Schmidt  * All rights reserved.
77d8fb588SMatthias Schmidt  *
87d8fb588SMatthias Schmidt  * Redistribution and use in source and binary forms, with or without
97d8fb588SMatthias Schmidt  * modification, are permitted provided that the following conditions
107d8fb588SMatthias Schmidt  * are met:
117d8fb588SMatthias Schmidt  * 1. Redistributions of source code must retain the above copyright
127d8fb588SMatthias Schmidt  *    notice, this list of conditions and the following disclaimer.
137d8fb588SMatthias Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
147d8fb588SMatthias Schmidt  *    notice, this list of conditions and the following disclaimer in the
157d8fb588SMatthias Schmidt  *    documentation and/or other materials provided with the distribution.
167d8fb588SMatthias Schmidt  * 3. Neither the name of the University nor the names of its contributors
177d8fb588SMatthias Schmidt  *    may be used to endorse or promote products derived from this software
187d8fb588SMatthias Schmidt  *    without specific prior written permission.
197d8fb588SMatthias Schmidt  *
207d8fb588SMatthias Schmidt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217d8fb588SMatthias Schmidt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227d8fb588SMatthias Schmidt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237d8fb588SMatthias Schmidt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247d8fb588SMatthias Schmidt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257d8fb588SMatthias Schmidt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267d8fb588SMatthias Schmidt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277d8fb588SMatthias Schmidt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287d8fb588SMatthias Schmidt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297d8fb588SMatthias Schmidt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307d8fb588SMatthias Schmidt  * SUCH DAMAGE.
317d8fb588SMatthias Schmidt  */
327d8fb588SMatthias Schmidt #include "sh.h"
337d8fb588SMatthias Schmidt #include "ed.h"
347d8fb588SMatthias Schmidt #include "ed.defns.h"
35*d6ab524cSAntonio Huete Jimenez #include "tw.h"
367d8fb588SMatthias Schmidt 
377d8fb588SMatthias Schmidt static	void   printkey		(const KEYCMD *, CStr *);
387d8fb588SMatthias Schmidt static	KEYCMD parsecmd		(Char *);
397d8fb588SMatthias Schmidt static  void   bad_spec		(const Char *);
407d8fb588SMatthias Schmidt static	CStr  *parsestring	(const Char *, CStr *);
417d8fb588SMatthias Schmidt static	CStr  *parsebind	(const Char *, CStr *);
427d8fb588SMatthias Schmidt static	void   print_all_keys	(void);
437d8fb588SMatthias Schmidt static	void   printkeys	(KEYCMD *, int, int);
447d8fb588SMatthias Schmidt static	void   bindkey_usage	(void);
457d8fb588SMatthias Schmidt static	void   list_functions	(void);
467d8fb588SMatthias Schmidt 
477d8fb588SMatthias Schmidt extern int MapsAreInited;
487d8fb588SMatthias Schmidt 
497d8fb588SMatthias Schmidt 
507d8fb588SMatthias Schmidt 
517d8fb588SMatthias Schmidt 
527d8fb588SMatthias Schmidt /*ARGSUSED*/
537d8fb588SMatthias Schmidt void
dobindkey(Char ** v,struct command * c)547d8fb588SMatthias Schmidt dobindkey(Char **v, struct command *c)
557d8fb588SMatthias Schmidt {
567d8fb588SMatthias Schmidt     KEYCMD *map;
577d8fb588SMatthias Schmidt     int     ntype, no, removeb, key, bindk;
587d8fb588SMatthias Schmidt     Char   *par;
597d8fb588SMatthias Schmidt     Char    p;
607d8fb588SMatthias Schmidt     KEYCMD  cmd;
617d8fb588SMatthias Schmidt     CStr    in;
627d8fb588SMatthias Schmidt     CStr    out;
637d8fb588SMatthias Schmidt     uChar   ch;
647d8fb588SMatthias Schmidt 
657d8fb588SMatthias Schmidt     USE(c);
667d8fb588SMatthias Schmidt     if (!MapsAreInited)
677d8fb588SMatthias Schmidt 	ed_InitMaps();
687d8fb588SMatthias Schmidt 
697d8fb588SMatthias Schmidt     map = CcKeyMap;
707d8fb588SMatthias Schmidt     ntype = XK_CMD;
717d8fb588SMatthias Schmidt     key = removeb = bindk = 0;
727d8fb588SMatthias Schmidt     for (no = 1, par = v[no];
737d8fb588SMatthias Schmidt 	 par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
747d8fb588SMatthias Schmidt 	if ((p = (*par & CHAR)) == '-') {
757d8fb588SMatthias Schmidt 	    no++;
767d8fb588SMatthias Schmidt 	    break;
777d8fb588SMatthias Schmidt 	}
787d8fb588SMatthias Schmidt 	else
797d8fb588SMatthias Schmidt 	    switch (p) {
807d8fb588SMatthias Schmidt 	    case 'b':
817d8fb588SMatthias Schmidt 		bindk = 1;
827d8fb588SMatthias Schmidt 		break;
837d8fb588SMatthias Schmidt 	    case 'k':
847d8fb588SMatthias Schmidt 		key = 1;
857d8fb588SMatthias Schmidt 		break;
867d8fb588SMatthias Schmidt 	    case 'a':
877d8fb588SMatthias Schmidt 		map = CcAltMap;
887d8fb588SMatthias Schmidt 		break;
897d8fb588SMatthias Schmidt 	    case 's':
907d8fb588SMatthias Schmidt 		ntype = XK_STR;
917d8fb588SMatthias Schmidt 		break;
927d8fb588SMatthias Schmidt 	    case 'c':
937d8fb588SMatthias Schmidt 		ntype = XK_EXE;
947d8fb588SMatthias Schmidt 		break;
957d8fb588SMatthias Schmidt 	    case 'r':
967d8fb588SMatthias Schmidt 		removeb = 1;
977d8fb588SMatthias Schmidt 		break;
987d8fb588SMatthias Schmidt 	    case 'v':
997d8fb588SMatthias Schmidt 		ed_InitVIMaps();
1007d8fb588SMatthias Schmidt 		return;
1017d8fb588SMatthias Schmidt 	    case 'e':
1027d8fb588SMatthias Schmidt 		ed_InitEmacsMaps();
1037d8fb588SMatthias Schmidt 		return;
1047d8fb588SMatthias Schmidt 	    case 'd':
1057d8fb588SMatthias Schmidt #ifdef VIDEFAULT
1067d8fb588SMatthias Schmidt 		ed_InitVIMaps();
1077d8fb588SMatthias Schmidt #else /* EMACSDEFAULT */
1087d8fb588SMatthias Schmidt 		ed_InitEmacsMaps();
1097d8fb588SMatthias Schmidt #endif /* VIDEFAULT */
1107d8fb588SMatthias Schmidt 		return;
1117d8fb588SMatthias Schmidt 	    case 'l':
1127d8fb588SMatthias Schmidt 		list_functions();
1137d8fb588SMatthias Schmidt 		return;
1147d8fb588SMatthias Schmidt 	    default:
1157d8fb588SMatthias Schmidt 		bindkey_usage();
1167d8fb588SMatthias Schmidt 		return;
1177d8fb588SMatthias Schmidt 	    }
1187d8fb588SMatthias Schmidt     }
1197d8fb588SMatthias Schmidt 
1207d8fb588SMatthias Schmidt     if (!v[no]) {
1217d8fb588SMatthias Schmidt 	print_all_keys();
1227d8fb588SMatthias Schmidt 	return;
1237d8fb588SMatthias Schmidt     }
1247d8fb588SMatthias Schmidt 
1257d8fb588SMatthias Schmidt     if (key) {
1267d8fb588SMatthias Schmidt 	if (!IsArrowKey(v[no]))
1277d8fb588SMatthias Schmidt 	    xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]);
1287d8fb588SMatthias Schmidt 	in.buf = Strsave(v[no++]);
1297d8fb588SMatthias Schmidt 	in.len = Strlen(in.buf);
1307d8fb588SMatthias Schmidt     }
1317d8fb588SMatthias Schmidt     else {
1327d8fb588SMatthias Schmidt 	if (bindk) {
1337d8fb588SMatthias Schmidt 	    if (parsebind(v[no++], &in) == NULL)
1347d8fb588SMatthias Schmidt 		return;
1357d8fb588SMatthias Schmidt 	}
1367d8fb588SMatthias Schmidt 	else {
1377d8fb588SMatthias Schmidt 	    if (parsestring(v[no++], &in) == NULL)
1387d8fb588SMatthias Schmidt 		return;
1397d8fb588SMatthias Schmidt 	}
1407d8fb588SMatthias Schmidt     }
1417d8fb588SMatthias Schmidt     cleanup_push(in.buf, xfree);
1427d8fb588SMatthias Schmidt 
143*d6ab524cSAntonio Huete Jimenez #if !defined(WINNT_NATIVE) && defined(SHORT_STRINGS)
1447d8fb588SMatthias Schmidt     if (in.buf[0] > 0xFF) {
1457d8fb588SMatthias Schmidt 	bad_spec(in.buf);
1467d8fb588SMatthias Schmidt 	cleanup_until(in.buf);
1477d8fb588SMatthias Schmidt 	return;
1487d8fb588SMatthias Schmidt     }
1497d8fb588SMatthias Schmidt #endif
1507d8fb588SMatthias Schmidt     ch = (uChar) in.buf[0];
1517d8fb588SMatthias Schmidt 
1527d8fb588SMatthias Schmidt     if (removeb) {
1537d8fb588SMatthias Schmidt 	if (key)
1547d8fb588SMatthias Schmidt 	    (void) ClearArrowKeys(&in);
1557d8fb588SMatthias Schmidt 	else if (in.len > 1) {
1567d8fb588SMatthias Schmidt 	    (void) DeleteXkey(&in);
1577d8fb588SMatthias Schmidt 	}
1587d8fb588SMatthias Schmidt 	else if (map[ch] == F_XKEY) {
1597d8fb588SMatthias Schmidt 	    (void) DeleteXkey(&in);
1607d8fb588SMatthias Schmidt 	    map[ch] = F_UNASSIGNED;
1617d8fb588SMatthias Schmidt 	}
1627d8fb588SMatthias Schmidt 	else {
1637d8fb588SMatthias Schmidt 	    map[ch] = F_UNASSIGNED;
1647d8fb588SMatthias Schmidt 	}
1657d8fb588SMatthias Schmidt 	cleanup_until(in.buf);
1667d8fb588SMatthias Schmidt 	return;
1677d8fb588SMatthias Schmidt     }
1687d8fb588SMatthias Schmidt     if (!v[no]) {
1697d8fb588SMatthias Schmidt 	if (key)
1707d8fb588SMatthias Schmidt 	    PrintArrowKeys(&in);
1717d8fb588SMatthias Schmidt 	else
1727d8fb588SMatthias Schmidt 	    printkey(map, &in);
1737d8fb588SMatthias Schmidt 	cleanup_until(in.buf);
1747d8fb588SMatthias Schmidt 	return;
1757d8fb588SMatthias Schmidt     }
1767d8fb588SMatthias Schmidt     if (v[no + 1]) {
1777d8fb588SMatthias Schmidt 	bindkey_usage();
1787d8fb588SMatthias Schmidt 	cleanup_until(in.buf);
1797d8fb588SMatthias Schmidt 	return;
1807d8fb588SMatthias Schmidt     }
1817d8fb588SMatthias Schmidt     switch (ntype) {
1827d8fb588SMatthias Schmidt     case XK_STR:
1837d8fb588SMatthias Schmidt     case XK_EXE:
1847d8fb588SMatthias Schmidt 	if (parsestring(v[no], &out) == NULL) {
1857d8fb588SMatthias Schmidt 	    cleanup_until(in.buf);
1867d8fb588SMatthias Schmidt 	    return;
1877d8fb588SMatthias Schmidt 	}
1887d8fb588SMatthias Schmidt 	cleanup_push(out.buf, xfree);
1897d8fb588SMatthias Schmidt 	if (key) {
1907d8fb588SMatthias Schmidt 	    if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1)
1917d8fb588SMatthias Schmidt 		xprintf(CGETS(20, 2, "Bad key name: %S\n"), in.buf);
1927d8fb588SMatthias Schmidt 	    else
1937d8fb588SMatthias Schmidt 		cleanup_ignore(out.buf);
1947d8fb588SMatthias Schmidt 	}
1957d8fb588SMatthias Schmidt 	else
1967d8fb588SMatthias Schmidt 	    AddXkey(&in, XmapStr(&out), ntype);
1977d8fb588SMatthias Schmidt 	map[ch] = F_XKEY;
1987d8fb588SMatthias Schmidt 	break;
1997d8fb588SMatthias Schmidt     case XK_CMD:
2007d8fb588SMatthias Schmidt 	if ((cmd = parsecmd(v[no])) == 0) {
2017d8fb588SMatthias Schmidt 	    cleanup_until(in.buf);
2027d8fb588SMatthias Schmidt 	    return;
2037d8fb588SMatthias Schmidt 	}
2047d8fb588SMatthias Schmidt 	if (key)
2057d8fb588SMatthias Schmidt 	    (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype);
2067d8fb588SMatthias Schmidt 	else {
2077d8fb588SMatthias Schmidt 	    if (in.len > 1) {
2087d8fb588SMatthias Schmidt 		AddXkey(&in, XmapCmd((int) cmd), ntype);
2097d8fb588SMatthias Schmidt 		map[ch] = F_XKEY;
2107d8fb588SMatthias Schmidt 	    }
2117d8fb588SMatthias Schmidt 	    else {
2127d8fb588SMatthias Schmidt 		ClearXkey(map, &in);
2137d8fb588SMatthias Schmidt 		map[ch] = cmd;
2147d8fb588SMatthias Schmidt 	    }
2157d8fb588SMatthias Schmidt 	}
2167d8fb588SMatthias Schmidt 	break;
2177d8fb588SMatthias Schmidt     default:
2187d8fb588SMatthias Schmidt 	abort();
2197d8fb588SMatthias Schmidt 	break;
2207d8fb588SMatthias Schmidt     }
2217d8fb588SMatthias Schmidt     cleanup_until(in.buf);
2227d8fb588SMatthias Schmidt     if (key)
2237d8fb588SMatthias Schmidt 	BindArrowKeys();
2247d8fb588SMatthias Schmidt }
2257d8fb588SMatthias Schmidt 
2267d8fb588SMatthias Schmidt static void
printkey(const KEYCMD * map,CStr * in)2277d8fb588SMatthias Schmidt printkey(const KEYCMD *map, CStr *in)
2287d8fb588SMatthias Schmidt {
2297d8fb588SMatthias Schmidt     struct KeyFuncs *fp;
2307d8fb588SMatthias Schmidt 
2317d8fb588SMatthias Schmidt     if (in->len < 2) {
2327d8fb588SMatthias Schmidt 	unsigned char *unparsed;
2337d8fb588SMatthias Schmidt 
2347d8fb588SMatthias Schmidt 	unparsed = unparsestring(in, STRQQ);
2357d8fb588SMatthias Schmidt 	cleanup_push(unparsed, xfree);
2367d8fb588SMatthias Schmidt 	for (fp = FuncNames; fp->name; fp++) {
2377d8fb588SMatthias Schmidt 	    if (fp->func == map[(uChar) *(in->buf)]) {
2387d8fb588SMatthias Schmidt 		xprintf("%s\t->\t%s\n", unparsed, fp->name);
2397d8fb588SMatthias Schmidt 	    }
2407d8fb588SMatthias Schmidt 	}
2417d8fb588SMatthias Schmidt 	cleanup_until(unparsed);
2427d8fb588SMatthias Schmidt     }
2437d8fb588SMatthias Schmidt     else
2447d8fb588SMatthias Schmidt 	PrintXkey(in);
2457d8fb588SMatthias Schmidt }
2467d8fb588SMatthias Schmidt 
2477d8fb588SMatthias Schmidt static  KEYCMD
parsecmd(Char * str)2487d8fb588SMatthias Schmidt parsecmd(Char *str)
2497d8fb588SMatthias Schmidt {
2507d8fb588SMatthias Schmidt     struct KeyFuncs *fp;
2517d8fb588SMatthias Schmidt 
2527d8fb588SMatthias Schmidt     for (fp = FuncNames; fp->name; fp++) {
2537d8fb588SMatthias Schmidt 	if (strcmp(short2str(str), fp->name) == 0) {
2547d8fb588SMatthias Schmidt 	    return (KEYCMD) fp->func;
2557d8fb588SMatthias Schmidt 	}
2567d8fb588SMatthias Schmidt     }
2577d8fb588SMatthias Schmidt     xprintf(CGETS(20, 3, "Bad command name: %S\n"), str);
2587d8fb588SMatthias Schmidt     return 0;
2597d8fb588SMatthias Schmidt }
2607d8fb588SMatthias Schmidt 
2617d8fb588SMatthias Schmidt 
2627d8fb588SMatthias Schmidt static void
bad_spec(const Char * str)2637d8fb588SMatthias Schmidt bad_spec(const Char *str)
2647d8fb588SMatthias Schmidt {
2657d8fb588SMatthias Schmidt     xprintf(CGETS(20, 4, "Bad key spec %S\n"), str);
2667d8fb588SMatthias Schmidt }
2677d8fb588SMatthias Schmidt 
2687d8fb588SMatthias Schmidt static CStr *
parsebind(const Char * s,CStr * str)2697d8fb588SMatthias Schmidt parsebind(const Char *s, CStr *str)
2707d8fb588SMatthias Schmidt {
2717d8fb588SMatthias Schmidt     struct Strbuf b = Strbuf_INIT;
2727d8fb588SMatthias Schmidt 
2737d8fb588SMatthias Schmidt     cleanup_push(&b, Strbuf_cleanup);
2747d8fb588SMatthias Schmidt     if (Iscntrl(*s)) {
2757d8fb588SMatthias Schmidt 	Strbuf_append1(&b, *s);
2767d8fb588SMatthias Schmidt 	goto end;
2777d8fb588SMatthias Schmidt     }
2787d8fb588SMatthias Schmidt 
2797d8fb588SMatthias Schmidt     switch (*s) {
2807d8fb588SMatthias Schmidt     case '^':
2817d8fb588SMatthias Schmidt 	s++;
2827d8fb588SMatthias Schmidt #ifdef IS_ASCII
2837d8fb588SMatthias Schmidt 	Strbuf_append1(&b, (*s == '?') ? '\177' : ((*s & CHAR) & 0237));
2847d8fb588SMatthias Schmidt #else
2857d8fb588SMatthias Schmidt 	Strbuf_append1(&b, (*s == '?') ? CTL_ESC('\177')
2867d8fb588SMatthias Schmidt 		       : _toebcdic[_toascii[*s & CHAR] & 0237]);
2877d8fb588SMatthias Schmidt #endif
2887d8fb588SMatthias Schmidt 	break;
2897d8fb588SMatthias Schmidt 
2907d8fb588SMatthias Schmidt     case 'F':
2917d8fb588SMatthias Schmidt     case 'M':
2927d8fb588SMatthias Schmidt     case 'X':
2937d8fb588SMatthias Schmidt     case 'C':
2947d8fb588SMatthias Schmidt #ifdef WINNT_NATIVE
2957d8fb588SMatthias Schmidt     case 'N':
2967d8fb588SMatthias Schmidt #endif /* WINNT_NATIVE */
2977d8fb588SMatthias Schmidt 	if (s[1] != '-' || s[2] == '\0')
2987d8fb588SMatthias Schmidt 	    goto bad_spec;
2997d8fb588SMatthias Schmidt 	s += 2;
3007d8fb588SMatthias Schmidt 	switch (s[-2]) {
3017d8fb588SMatthias Schmidt 	case 'F': case 'f':	/* Turn into ^[str */
3027d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, CTL_ESC('\033'));
3037d8fb588SMatthias Schmidt 	    Strbuf_append(&b, s);
3047d8fb588SMatthias Schmidt 	    break;
3057d8fb588SMatthias Schmidt 
3067d8fb588SMatthias Schmidt 	case 'C': case 'c':	/* Turn into ^c */
3077d8fb588SMatthias Schmidt #ifdef IS_ASCII
3087d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, (*s == '?') ? '\177' : ((*s & CHAR) & 0237));
3097d8fb588SMatthias Schmidt #else
3107d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, (*s == '?') ? CTL_ESC('\177')
3117d8fb588SMatthias Schmidt 			   : _toebcdic[_toascii[*s & CHAR] & 0237]);
3127d8fb588SMatthias Schmidt #endif
3137d8fb588SMatthias Schmidt 	    break;
3147d8fb588SMatthias Schmidt 
3157d8fb588SMatthias Schmidt 	case 'X' : case 'x':	/* Turn into ^Xc */
3167d8fb588SMatthias Schmidt #ifdef IS_ASCII
3177d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, 'X' & 0237);
3187d8fb588SMatthias Schmidt #else
3197d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, _toebcdic[_toascii['X'] & 0237]);
3207d8fb588SMatthias Schmidt #endif
3217d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, *s);
3227d8fb588SMatthias Schmidt 	    break;
3237d8fb588SMatthias Schmidt 
3247d8fb588SMatthias Schmidt 	case 'M' : case 'm':	/* Turn into 0x80|c */
3257d8fb588SMatthias Schmidt 	    if (!NoNLSRebind) {
3267d8fb588SMatthias Schmidt 		Strbuf_append1(&b, CTL_ESC('\033'));
3277d8fb588SMatthias Schmidt 	    	Strbuf_append1(&b, *s);
3287d8fb588SMatthias Schmidt 	    } else {
3297d8fb588SMatthias Schmidt #ifdef IS_ASCII
3307d8fb588SMatthias Schmidt 		Strbuf_append1(&b, *s | 0x80);
3317d8fb588SMatthias Schmidt #else
3327d8fb588SMatthias Schmidt 		Strbuf_append1(&b, _toebcdic[_toascii[*s] | 0x80]);
3337d8fb588SMatthias Schmidt #endif
3347d8fb588SMatthias Schmidt 	    }
3357d8fb588SMatthias Schmidt 	    break;
3367d8fb588SMatthias Schmidt #ifdef WINNT_NATIVE
3377d8fb588SMatthias Schmidt 	case 'N' : case 'n':	/* NT */
3387d8fb588SMatthias Schmidt 		{
3397d8fb588SMatthias Schmidt 			Char bnt;
3407d8fb588SMatthias Schmidt 
3417d8fb588SMatthias Schmidt 			bnt = nt_translate_bindkey(s);
3427d8fb588SMatthias Schmidt 			if (bnt != 0)
3437d8fb588SMatthias Schmidt 			        Strbuf_append1(&b, bnt);
3447d8fb588SMatthias Schmidt 			else
3457d8fb588SMatthias Schmidt 				bad_spec(s);
3467d8fb588SMatthias Schmidt 		}
3477d8fb588SMatthias Schmidt 	    break;
3487d8fb588SMatthias Schmidt #endif /* WINNT_NATIVE */
3497d8fb588SMatthias Schmidt 
3507d8fb588SMatthias Schmidt 	default:
3517d8fb588SMatthias Schmidt 	    abort();
3527d8fb588SMatthias Schmidt 	}
3537d8fb588SMatthias Schmidt 	break;
3547d8fb588SMatthias Schmidt 
3557d8fb588SMatthias Schmidt     default:
3567d8fb588SMatthias Schmidt 	goto bad_spec;
3577d8fb588SMatthias Schmidt     }
3587d8fb588SMatthias Schmidt 
3597d8fb588SMatthias Schmidt  end:
3607d8fb588SMatthias Schmidt     cleanup_ignore(&b);
3617d8fb588SMatthias Schmidt     cleanup_until(&b);
3627d8fb588SMatthias Schmidt     Strbuf_terminate(&b);
3637d8fb588SMatthias Schmidt     str->buf = xrealloc(b.s, (b.len + 1) * sizeof (*str->buf));
3647d8fb588SMatthias Schmidt     str->len = b.len;
3657d8fb588SMatthias Schmidt     return str;
3667d8fb588SMatthias Schmidt 
3677d8fb588SMatthias Schmidt  bad_spec:
3687d8fb588SMatthias Schmidt     bad_spec(s);
3697d8fb588SMatthias Schmidt     cleanup_until(&b);
3707d8fb588SMatthias Schmidt     return NULL;
3717d8fb588SMatthias Schmidt }
3727d8fb588SMatthias Schmidt 
3737d8fb588SMatthias Schmidt 
3747d8fb588SMatthias Schmidt static CStr *
parsestring(const Char * str,CStr * buf)3757d8fb588SMatthias Schmidt parsestring(const Char *str, CStr *buf)
3767d8fb588SMatthias Schmidt {
3777d8fb588SMatthias Schmidt     struct Strbuf b = Strbuf_INIT;
3787d8fb588SMatthias Schmidt     const Char   *p;
3797d8fb588SMatthias Schmidt     eChar  es;
3807d8fb588SMatthias Schmidt 
3817d8fb588SMatthias Schmidt     if (*str == 0) {
38257e3f2b5SSimon 'corecode' Schubert 	xprintf("%s", CGETS(20, 5, "Null string specification\n"));
3837d8fb588SMatthias Schmidt 	return NULL;
3847d8fb588SMatthias Schmidt     }
3857d8fb588SMatthias Schmidt 
3867d8fb588SMatthias Schmidt     cleanup_push(&b, Strbuf_cleanup);
3877d8fb588SMatthias Schmidt     for (p = str; *p != 0; p++) {
3887d8fb588SMatthias Schmidt 	if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
389*d6ab524cSAntonio Huete Jimenez 	    if ((es = parseescape(&p, TRUE)) == CHAR_ERR) {
3907d8fb588SMatthias Schmidt 		cleanup_until(&b);
3917d8fb588SMatthias Schmidt 		return 0;
3927d8fb588SMatthias Schmidt 	    } else
3937d8fb588SMatthias Schmidt 		Strbuf_append1(&b, es);
3947d8fb588SMatthias Schmidt 	}
3957d8fb588SMatthias Schmidt 	else
3967d8fb588SMatthias Schmidt 	    Strbuf_append1(&b, *p & CHAR);
3977d8fb588SMatthias Schmidt     }
3987d8fb588SMatthias Schmidt     cleanup_ignore(&b);
3997d8fb588SMatthias Schmidt     cleanup_until(&b);
4007d8fb588SMatthias Schmidt     Strbuf_terminate(&b);
4017d8fb588SMatthias Schmidt     buf->buf = xrealloc(b.s, (b.len + 1) * sizeof (*buf->buf));
4027d8fb588SMatthias Schmidt     buf->len = b.len;
4037d8fb588SMatthias Schmidt     return buf;
4047d8fb588SMatthias Schmidt }
4057d8fb588SMatthias Schmidt 
4067d8fb588SMatthias Schmidt static void
print_all_keys(void)4077d8fb588SMatthias Schmidt print_all_keys(void)
4087d8fb588SMatthias Schmidt {
4097d8fb588SMatthias Schmidt     int     prev, i;
4107d8fb588SMatthias Schmidt     CStr nilstr;
4117d8fb588SMatthias Schmidt     nilstr.buf = NULL;
4127d8fb588SMatthias Schmidt     nilstr.len = 0;
4137d8fb588SMatthias Schmidt 
4147d8fb588SMatthias Schmidt 
41557e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 6, "Standard key bindings\n"));
4167d8fb588SMatthias Schmidt     prev = 0;
4177d8fb588SMatthias Schmidt     for (i = 0; i < 256; i++) {
4187d8fb588SMatthias Schmidt 	if (CcKeyMap[prev] == CcKeyMap[i])
4197d8fb588SMatthias Schmidt 	    continue;
4207d8fb588SMatthias Schmidt 	printkeys(CcKeyMap, prev, i - 1);
4217d8fb588SMatthias Schmidt 	prev = i;
4227d8fb588SMatthias Schmidt     }
4237d8fb588SMatthias Schmidt     printkeys(CcKeyMap, prev, i - 1);
4247d8fb588SMatthias Schmidt 
42557e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 7, "Alternative key bindings\n"));
4267d8fb588SMatthias Schmidt     prev = 0;
4277d8fb588SMatthias Schmidt     for (i = 0; i < 256; i++) {
4287d8fb588SMatthias Schmidt 	if (CcAltMap[prev] == CcAltMap[i])
4297d8fb588SMatthias Schmidt 	    continue;
4307d8fb588SMatthias Schmidt 	printkeys(CcAltMap, prev, i - 1);
4317d8fb588SMatthias Schmidt 	prev = i;
4327d8fb588SMatthias Schmidt     }
4337d8fb588SMatthias Schmidt     printkeys(CcAltMap, prev, i - 1);
43457e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 8, "Multi-character bindings\n"));
4357d8fb588SMatthias Schmidt     PrintXkey(NULL);	/* print all Xkey bindings */
43657e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 9, "Arrow key bindings\n"));
4377d8fb588SMatthias Schmidt     PrintArrowKeys(&nilstr);
4387d8fb588SMatthias Schmidt }
4397d8fb588SMatthias Schmidt 
4407d8fb588SMatthias Schmidt static void
printkeys(KEYCMD * map,int first,int last)4417d8fb588SMatthias Schmidt printkeys(KEYCMD *map, int first, int last)
4427d8fb588SMatthias Schmidt {
4437d8fb588SMatthias Schmidt     struct KeyFuncs *fp;
4447d8fb588SMatthias Schmidt     Char    firstbuf[2], lastbuf[2];
4457d8fb588SMatthias Schmidt     CStr fb, lb;
4467d8fb588SMatthias Schmidt     unsigned char *unparsed;
4477d8fb588SMatthias Schmidt     fb.buf = firstbuf;
4487d8fb588SMatthias Schmidt     lb.buf = lastbuf;
4497d8fb588SMatthias Schmidt 
4507d8fb588SMatthias Schmidt     firstbuf[0] = (Char) first;
4517d8fb588SMatthias Schmidt     firstbuf[1] = 0;
4527d8fb588SMatthias Schmidt     lastbuf[0] = (Char) last;
4537d8fb588SMatthias Schmidt     lastbuf[1] = 0;
4547d8fb588SMatthias Schmidt     fb.len = 1;
4557d8fb588SMatthias Schmidt     lb.len = 1;
4567d8fb588SMatthias Schmidt 
4577d8fb588SMatthias Schmidt     unparsed = unparsestring(&fb, STRQQ);
4587d8fb588SMatthias Schmidt     cleanup_push(unparsed, xfree);
4597d8fb588SMatthias Schmidt     if (map[first] == F_UNASSIGNED) {
4607d8fb588SMatthias Schmidt 	if (first == last)
4617d8fb588SMatthias Schmidt 	    xprintf(CGETS(20, 10, "%-15s->  is undefined\n"), unparsed);
4627d8fb588SMatthias Schmidt 	cleanup_until(unparsed);
4637d8fb588SMatthias Schmidt 	return;
4647d8fb588SMatthias Schmidt     }
4657d8fb588SMatthias Schmidt 
4667d8fb588SMatthias Schmidt     for (fp = FuncNames; fp->name; fp++) {
4677d8fb588SMatthias Schmidt 	if (fp->func == map[first]) {
4687d8fb588SMatthias Schmidt 	    if (first == last)
4697d8fb588SMatthias Schmidt 		xprintf("%-15s->  %s\n", unparsed, fp->name);
4707d8fb588SMatthias Schmidt 	    else {
4717d8fb588SMatthias Schmidt 		unsigned char *p;
4727d8fb588SMatthias Schmidt 
4737d8fb588SMatthias Schmidt 		p = unparsestring(&lb, STRQQ);
4747d8fb588SMatthias Schmidt 		cleanup_push(p, xfree);
4757d8fb588SMatthias Schmidt 		xprintf("%-4s to %-7s->  %s\n", unparsed, p, fp->name);
4767d8fb588SMatthias Schmidt 	    }
4777d8fb588SMatthias Schmidt 	    cleanup_until(unparsed);
4787d8fb588SMatthias Schmidt 	    return;
4797d8fb588SMatthias Schmidt 	}
4807d8fb588SMatthias Schmidt     }
4817d8fb588SMatthias Schmidt     xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), unparsed);
4827d8fb588SMatthias Schmidt     if (map == CcKeyMap)
4837d8fb588SMatthias Schmidt 	xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
4847d8fb588SMatthias Schmidt     else
4857d8fb588SMatthias Schmidt 	xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
4867d8fb588SMatthias Schmidt     cleanup_until(unparsed);
4877d8fb588SMatthias Schmidt }
4887d8fb588SMatthias Schmidt 
4897d8fb588SMatthias Schmidt static void
bindkey_usage(void)4907d8fb588SMatthias Schmidt bindkey_usage(void)
4917d8fb588SMatthias Schmidt {
49257e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 12,
4937d8fb588SMatthias Schmidt 	    "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
49457e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 13,
4957d8fb588SMatthias Schmidt     	    "    -a   list or bind KEY in alternative key map\n"));
49657e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 14,
4977d8fb588SMatthias Schmidt 	    "    -b   interpret KEY as a C-, M-, F- or X- key name\n"));
49857e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 15,
4997d8fb588SMatthias Schmidt             "    -s   interpret COMMAND as a literal string to be output\n"));
50057e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 16,
5017d8fb588SMatthias Schmidt             "    -c   interpret COMMAND as a builtin or external command\n"));
50257e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 17,
5037d8fb588SMatthias Schmidt 	    "    -v   bind all keys to vi bindings\n"));
50457e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 18,
5057d8fb588SMatthias Schmidt 	    "    -e   bind all keys to emacs bindings\n"));
506653fab9eSSascha Wildner     xprintf(CGETS(20, 19,
507653fab9eSSascha Wildner 	    "    -d   bind all keys to default editor's bindings (%s)\n"),
508653fab9eSSascha Wildner #ifdef VIDEFAULT
509653fab9eSSascha Wildner 	    "vi"
510653fab9eSSascha Wildner #else /* EMACSDEFAULT */
511653fab9eSSascha Wildner 	    "emacs"
512653fab9eSSascha Wildner #endif /* VIDEFAULT */
513653fab9eSSascha Wildner 	    );
51457e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 20,
5157d8fb588SMatthias Schmidt 	    "    -l   list editor commands with descriptions\n"));
51657e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 21,
5177d8fb588SMatthias Schmidt 	    "    -r   remove KEY's binding\n"));
51857e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 22,
5197d8fb588SMatthias Schmidt 	    "    -k   interpret KEY as a symbolic arrow-key name\n"));
52057e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 23,
5217d8fb588SMatthias Schmidt 	    "    --   force a break from option processing\n"));
52257e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 24,
5237d8fb588SMatthias Schmidt 	    "    -u   (or any invalid option) this message\n"));
5247d8fb588SMatthias Schmidt     xprintf("\n");
52557e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 25,
5267d8fb588SMatthias Schmidt 	    "Without KEY or COMMAND, prints all bindings\n"));
52757e3f2b5SSimon 'corecode' Schubert     xprintf("%s", CGETS(20, 26,
5287d8fb588SMatthias Schmidt 	    "Without COMMAND, prints the binding for KEY.\n"));
5297d8fb588SMatthias Schmidt }
5307d8fb588SMatthias Schmidt 
5317d8fb588SMatthias Schmidt static void
list_functions(void)5327d8fb588SMatthias Schmidt list_functions(void)
5337d8fb588SMatthias Schmidt {
5347d8fb588SMatthias Schmidt     struct KeyFuncs *fp;
5357d8fb588SMatthias Schmidt 
5367d8fb588SMatthias Schmidt     for (fp = FuncNames; fp->name; fp++) {
5377d8fb588SMatthias Schmidt 	xprintf("%s\n          %s\n", fp->name, fp->desc);
5387d8fb588SMatthias Schmidt     }
5397d8fb588SMatthias Schmidt }
540