1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien * tc.bind.c: Key binding functions
3c80476e4SDavid E. O'Brien */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien * All rights reserved.
7c80476e4SDavid E. O'Brien *
8c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien * are met:
11c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1629301572SMark Peek * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien * without specific prior written permission.
19c80476e4SDavid E. O'Brien *
20c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "ed.h"
34c80476e4SDavid E. O'Brien #include "ed.defns.h"
35c80476e4SDavid E. O'Brien
3645e5710bSMark Peek static void printkey (const KEYCMD *, CStr *);
3745e5710bSMark Peek static KEYCMD parsecmd (Char *);
3845e5710bSMark Peek static void bad_spec (const Char *);
3945e5710bSMark Peek static CStr *parsestring (const Char *, CStr *);
4045e5710bSMark Peek static CStr *parsebind (const Char *, CStr *);
4145e5710bSMark Peek static void print_all_keys (void);
4245e5710bSMark Peek static void printkeys (KEYCMD *, int, int);
4345e5710bSMark Peek static void bindkey_usage (void);
4445e5710bSMark Peek static void list_functions (void);
45c80476e4SDavid E. O'Brien
46c80476e4SDavid E. O'Brien extern int MapsAreInited;
47c80476e4SDavid E. O'Brien
48c80476e4SDavid E. O'Brien
49c80476e4SDavid E. O'Brien
50c80476e4SDavid E. O'Brien
51c80476e4SDavid E. O'Brien /*ARGSUSED*/
52c80476e4SDavid E. O'Brien void
dobindkey(Char ** v,struct command * c)5345e5710bSMark Peek dobindkey(Char **v, struct command *c)
54c80476e4SDavid E. O'Brien {
55c80476e4SDavid E. O'Brien KEYCMD *map;
5623338178SMark Peek int ntype, no, removeb, key, bindk;
57c80476e4SDavid E. O'Brien Char *par;
58c80476e4SDavid E. O'Brien Char p;
59c80476e4SDavid E. O'Brien KEYCMD cmd;
60c80476e4SDavid E. O'Brien CStr in;
61c80476e4SDavid E. O'Brien CStr out;
62c80476e4SDavid E. O'Brien uChar ch;
63c80476e4SDavid E. O'Brien
64c80476e4SDavid E. O'Brien USE(c);
65c80476e4SDavid E. O'Brien if (!MapsAreInited)
66c80476e4SDavid E. O'Brien ed_InitMaps();
67c80476e4SDavid E. O'Brien
68c80476e4SDavid E. O'Brien map = CcKeyMap;
69c80476e4SDavid E. O'Brien ntype = XK_CMD;
7023338178SMark Peek key = removeb = bindk = 0;
71c80476e4SDavid E. O'Brien for (no = 1, par = v[no];
72c80476e4SDavid E. O'Brien par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
73c80476e4SDavid E. O'Brien if ((p = (*par & CHAR)) == '-') {
74c80476e4SDavid E. O'Brien no++;
75c80476e4SDavid E. O'Brien break;
76c80476e4SDavid E. O'Brien }
77c80476e4SDavid E. O'Brien else
78c80476e4SDavid E. O'Brien switch (p) {
79c80476e4SDavid E. O'Brien case 'b':
8023338178SMark Peek bindk = 1;
81c80476e4SDavid E. O'Brien break;
82c80476e4SDavid E. O'Brien case 'k':
83c80476e4SDavid E. O'Brien key = 1;
84c80476e4SDavid E. O'Brien break;
85c80476e4SDavid E. O'Brien case 'a':
86c80476e4SDavid E. O'Brien map = CcAltMap;
87c80476e4SDavid E. O'Brien break;
88c80476e4SDavid E. O'Brien case 's':
89c80476e4SDavid E. O'Brien ntype = XK_STR;
90c80476e4SDavid E. O'Brien break;
91c80476e4SDavid E. O'Brien case 'c':
92c80476e4SDavid E. O'Brien ntype = XK_EXE;
93c80476e4SDavid E. O'Brien break;
94c80476e4SDavid E. O'Brien case 'r':
9523338178SMark Peek removeb = 1;
96c80476e4SDavid E. O'Brien break;
97c80476e4SDavid E. O'Brien case 'v':
98c80476e4SDavid E. O'Brien ed_InitVIMaps();
99c80476e4SDavid E. O'Brien return;
100c80476e4SDavid E. O'Brien case 'e':
101c80476e4SDavid E. O'Brien ed_InitEmacsMaps();
102c80476e4SDavid E. O'Brien return;
103c80476e4SDavid E. O'Brien case 'd':
104c80476e4SDavid E. O'Brien #ifdef VIDEFAULT
105c80476e4SDavid E. O'Brien ed_InitVIMaps();
106c80476e4SDavid E. O'Brien #else /* EMACSDEFAULT */
107c80476e4SDavid E. O'Brien ed_InitEmacsMaps();
108c80476e4SDavid E. O'Brien #endif /* VIDEFAULT */
109c80476e4SDavid E. O'Brien return;
110c80476e4SDavid E. O'Brien case 'l':
111c80476e4SDavid E. O'Brien list_functions();
112c80476e4SDavid E. O'Brien return;
113c80476e4SDavid E. O'Brien default:
114c80476e4SDavid E. O'Brien bindkey_usage();
115c80476e4SDavid E. O'Brien return;
116c80476e4SDavid E. O'Brien }
117c80476e4SDavid E. O'Brien }
118c80476e4SDavid E. O'Brien
119c80476e4SDavid E. O'Brien if (!v[no]) {
120c80476e4SDavid E. O'Brien print_all_keys();
121c80476e4SDavid E. O'Brien return;
122c80476e4SDavid E. O'Brien }
123c80476e4SDavid E. O'Brien
124c80476e4SDavid E. O'Brien if (key) {
125c80476e4SDavid E. O'Brien if (!IsArrowKey(v[no]))
126c80476e4SDavid E. O'Brien xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]);
12745e5710bSMark Peek in.buf = Strsave(v[no++]);
128c80476e4SDavid E. O'Brien in.len = Strlen(in.buf);
129c80476e4SDavid E. O'Brien }
130c80476e4SDavid E. O'Brien else {
13123338178SMark Peek if (bindk) {
132c80476e4SDavid E. O'Brien if (parsebind(v[no++], &in) == NULL)
133c80476e4SDavid E. O'Brien return;
134c80476e4SDavid E. O'Brien }
135c80476e4SDavid E. O'Brien else {
136c80476e4SDavid E. O'Brien if (parsestring(v[no++], &in) == NULL)
137c80476e4SDavid E. O'Brien return;
138c80476e4SDavid E. O'Brien }
139c80476e4SDavid E. O'Brien }
14045e5710bSMark Peek cleanup_push(in.buf, xfree);
141c80476e4SDavid E. O'Brien
14223338178SMark Peek #ifndef WINNT_NATIVE
14323338178SMark Peek if (in.buf[0] > 0xFF) {
14423338178SMark Peek bad_spec(in.buf);
14545e5710bSMark Peek cleanup_until(in.buf);
14623338178SMark Peek return;
14723338178SMark Peek }
14823338178SMark Peek #endif
149c80476e4SDavid E. O'Brien ch = (uChar) in.buf[0];
150c80476e4SDavid E. O'Brien
15123338178SMark Peek if (removeb) {
15245e5710bSMark Peek if (key)
153c80476e4SDavid E. O'Brien (void) ClearArrowKeys(&in);
15445e5710bSMark Peek else if (in.len > 1) {
155c80476e4SDavid E. O'Brien (void) DeleteXkey(&in);
156c80476e4SDavid E. O'Brien }
157c80476e4SDavid E. O'Brien else if (map[ch] == F_XKEY) {
158c80476e4SDavid E. O'Brien (void) DeleteXkey(&in);
159c80476e4SDavid E. O'Brien map[ch] = F_UNASSIGNED;
160c80476e4SDavid E. O'Brien }
161c80476e4SDavid E. O'Brien else {
162c80476e4SDavid E. O'Brien map[ch] = F_UNASSIGNED;
163c80476e4SDavid E. O'Brien }
16445e5710bSMark Peek cleanup_until(in.buf);
165c80476e4SDavid E. O'Brien return;
166c80476e4SDavid E. O'Brien }
167c80476e4SDavid E. O'Brien if (!v[no]) {
168c80476e4SDavid E. O'Brien if (key)
169c80476e4SDavid E. O'Brien PrintArrowKeys(&in);
170c80476e4SDavid E. O'Brien else
171c80476e4SDavid E. O'Brien printkey(map, &in);
17245e5710bSMark Peek cleanup_until(in.buf);
173c80476e4SDavid E. O'Brien return;
174c80476e4SDavid E. O'Brien }
175c80476e4SDavid E. O'Brien if (v[no + 1]) {
176c80476e4SDavid E. O'Brien bindkey_usage();
17745e5710bSMark Peek cleanup_until(in.buf);
178c80476e4SDavid E. O'Brien return;
179c80476e4SDavid E. O'Brien }
180c80476e4SDavid E. O'Brien switch (ntype) {
181c80476e4SDavid E. O'Brien case XK_STR:
182c80476e4SDavid E. O'Brien case XK_EXE:
18345e5710bSMark Peek if (parsestring(v[no], &out) == NULL) {
18445e5710bSMark Peek cleanup_until(in.buf);
185c80476e4SDavid E. O'Brien return;
18645e5710bSMark Peek }
18745e5710bSMark Peek cleanup_push(out.buf, xfree);
188c80476e4SDavid E. O'Brien if (key) {
189c80476e4SDavid E. O'Brien if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1)
19023338178SMark Peek xprintf(CGETS(20, 2, "Bad key name: %S\n"), in.buf);
19145e5710bSMark Peek else
19245e5710bSMark Peek cleanup_ignore(out.buf);
193c80476e4SDavid E. O'Brien }
194c80476e4SDavid E. O'Brien else
195c80476e4SDavid E. O'Brien AddXkey(&in, XmapStr(&out), ntype);
196c80476e4SDavid E. O'Brien map[ch] = F_XKEY;
197c80476e4SDavid E. O'Brien break;
198c80476e4SDavid E. O'Brien case XK_CMD:
19945e5710bSMark Peek if ((cmd = parsecmd(v[no])) == 0) {
20045e5710bSMark Peek cleanup_until(in.buf);
201c80476e4SDavid E. O'Brien return;
20245e5710bSMark Peek }
203c80476e4SDavid E. O'Brien if (key)
204c80476e4SDavid E. O'Brien (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype);
205c80476e4SDavid E. O'Brien else {
206c80476e4SDavid E. O'Brien if (in.len > 1) {
207c80476e4SDavid E. O'Brien AddXkey(&in, XmapCmd((int) cmd), ntype);
208c80476e4SDavid E. O'Brien map[ch] = F_XKEY;
209c80476e4SDavid E. O'Brien }
210c80476e4SDavid E. O'Brien else {
211c80476e4SDavid E. O'Brien ClearXkey(map, &in);
212c80476e4SDavid E. O'Brien map[ch] = cmd;
213c80476e4SDavid E. O'Brien }
214c80476e4SDavid E. O'Brien }
215c80476e4SDavid E. O'Brien break;
216c80476e4SDavid E. O'Brien default:
217c80476e4SDavid E. O'Brien abort();
218c80476e4SDavid E. O'Brien break;
219c80476e4SDavid E. O'Brien }
22045e5710bSMark Peek cleanup_until(in.buf);
221c80476e4SDavid E. O'Brien if (key)
222c80476e4SDavid E. O'Brien BindArrowKeys();
223c80476e4SDavid E. O'Brien }
224c80476e4SDavid E. O'Brien
225c80476e4SDavid E. O'Brien static void
printkey(const KEYCMD * map,CStr * in)22645e5710bSMark Peek printkey(const KEYCMD *map, CStr *in)
227c80476e4SDavid E. O'Brien {
22823338178SMark Peek struct KeyFuncs *fp;
229c80476e4SDavid E. O'Brien
230c80476e4SDavid E. O'Brien if (in->len < 2) {
23145e5710bSMark Peek unsigned char *unparsed;
23245e5710bSMark Peek
23345e5710bSMark Peek unparsed = unparsestring(in, STRQQ);
23445e5710bSMark Peek cleanup_push(unparsed, xfree);
235c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) {
236c80476e4SDavid E. O'Brien if (fp->func == map[(uChar) *(in->buf)]) {
23745e5710bSMark Peek xprintf("%s\t->\t%s\n", unparsed, fp->name);
238c80476e4SDavid E. O'Brien }
239c80476e4SDavid E. O'Brien }
24045e5710bSMark Peek cleanup_until(unparsed);
241c80476e4SDavid E. O'Brien }
242c80476e4SDavid E. O'Brien else
243c80476e4SDavid E. O'Brien PrintXkey(in);
244c80476e4SDavid E. O'Brien }
245c80476e4SDavid E. O'Brien
246c80476e4SDavid E. O'Brien static KEYCMD
parsecmd(Char * str)24745e5710bSMark Peek parsecmd(Char *str)
248c80476e4SDavid E. O'Brien {
24923338178SMark Peek struct KeyFuncs *fp;
250c80476e4SDavid E. O'Brien
251c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) {
252c80476e4SDavid E. O'Brien if (strcmp(short2str(str), fp->name) == 0) {
253c80476e4SDavid E. O'Brien return (KEYCMD) fp->func;
254c80476e4SDavid E. O'Brien }
255c80476e4SDavid E. O'Brien }
256c80476e4SDavid E. O'Brien xprintf(CGETS(20, 3, "Bad command name: %S\n"), str);
257c80476e4SDavid E. O'Brien return 0;
258c80476e4SDavid E. O'Brien }
259c80476e4SDavid E. O'Brien
260c80476e4SDavid E. O'Brien
261c80476e4SDavid E. O'Brien static void
bad_spec(const Char * str)26245e5710bSMark Peek bad_spec(const Char *str)
263c80476e4SDavid E. O'Brien {
264c80476e4SDavid E. O'Brien xprintf(CGETS(20, 4, "Bad key spec %S\n"), str);
265c80476e4SDavid E. O'Brien }
266c80476e4SDavid E. O'Brien
267c80476e4SDavid E. O'Brien static CStr *
parsebind(const Char * s,CStr * str)26845e5710bSMark Peek parsebind(const Char *s, CStr *str)
269c80476e4SDavid E. O'Brien {
27045e5710bSMark Peek struct Strbuf b = Strbuf_INIT;
271c80476e4SDavid E. O'Brien
27245e5710bSMark Peek cleanup_push(&b, Strbuf_cleanup);
273c80476e4SDavid E. O'Brien if (Iscntrl(*s)) {
27445e5710bSMark Peek Strbuf_append1(&b, *s);
27545e5710bSMark Peek goto end;
276c80476e4SDavid E. O'Brien }
277c80476e4SDavid E. O'Brien
278c80476e4SDavid E. O'Brien switch (*s) {
279c80476e4SDavid E. O'Brien case '^':
280c80476e4SDavid E. O'Brien s++;
2813b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
28245e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? '\177' : ((*s & CHAR) & 0237));
2833b6eaa7bSAndrey A. Chernov #else
28445e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? CTL_ESC('\177')
28545e5710bSMark Peek : _toebcdic[_toascii[*s & CHAR] & 0237]);
2863b6eaa7bSAndrey A. Chernov #endif
287c80476e4SDavid E. O'Brien break;
288c80476e4SDavid E. O'Brien
289c80476e4SDavid E. O'Brien case 'F':
290c80476e4SDavid E. O'Brien case 'M':
291c80476e4SDavid E. O'Brien case 'X':
292c80476e4SDavid E. O'Brien case 'C':
2933b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
294c80476e4SDavid E. O'Brien case 'N':
2953b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
29645e5710bSMark Peek if (s[1] != '-' || s[2] == '\0')
29745e5710bSMark Peek goto bad_spec;
298c80476e4SDavid E. O'Brien s += 2;
299c80476e4SDavid E. O'Brien switch (s[-2]) {
300c80476e4SDavid E. O'Brien case 'F': case 'f': /* Turn into ^[str */
30145e5710bSMark Peek Strbuf_append1(&b, CTL_ESC('\033'));
30245e5710bSMark Peek Strbuf_append(&b, s);
303c80476e4SDavid E. O'Brien break;
304c80476e4SDavid E. O'Brien
305c80476e4SDavid E. O'Brien case 'C': case 'c': /* Turn into ^c */
3063b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
30745e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? '\177' : ((*s & CHAR) & 0237));
3083b6eaa7bSAndrey A. Chernov #else
30945e5710bSMark Peek Strbuf_append1(&b, (*s == '?') ? CTL_ESC('\177')
31045e5710bSMark Peek : _toebcdic[_toascii[*s & CHAR] & 0237]);
3113b6eaa7bSAndrey A. Chernov #endif
312c80476e4SDavid E. O'Brien break;
313c80476e4SDavid E. O'Brien
314c80476e4SDavid E. O'Brien case 'X' : case 'x': /* Turn into ^Xc */
3153b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
31645e5710bSMark Peek Strbuf_append1(&b, 'X' & 0237);
3173b6eaa7bSAndrey A. Chernov #else
31845e5710bSMark Peek Strbuf_append1(&b, _toebcdic[_toascii['X'] & 0237]);
3193b6eaa7bSAndrey A. Chernov #endif
32045e5710bSMark Peek Strbuf_append1(&b, *s);
321c80476e4SDavid E. O'Brien break;
322c80476e4SDavid E. O'Brien
323c80476e4SDavid E. O'Brien case 'M' : case 'm': /* Turn into 0x80|c */
324c80476e4SDavid E. O'Brien if (!NoNLSRebind) {
32545e5710bSMark Peek Strbuf_append1(&b, CTL_ESC('\033'));
32645e5710bSMark Peek Strbuf_append1(&b, *s);
327c80476e4SDavid E. O'Brien } else {
3283b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
32945e5710bSMark Peek Strbuf_append1(&b, *s | 0x80);
3303b6eaa7bSAndrey A. Chernov #else
33145e5710bSMark Peek Strbuf_append1(&b, _toebcdic[_toascii[*s] | 0x80]);
3323b6eaa7bSAndrey A. Chernov #endif
333c80476e4SDavid E. O'Brien }
334c80476e4SDavid E. O'Brien break;
3353b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
336c80476e4SDavid E. O'Brien case 'N' : case 'n': /* NT */
337c80476e4SDavid E. O'Brien {
338c80476e4SDavid E. O'Brien Char bnt;
339c80476e4SDavid E. O'Brien
340c80476e4SDavid E. O'Brien bnt = nt_translate_bindkey(s);
341c80476e4SDavid E. O'Brien if (bnt != 0)
34245e5710bSMark Peek Strbuf_append1(&b, bnt);
343c80476e4SDavid E. O'Brien else
344c80476e4SDavid E. O'Brien bad_spec(s);
345c80476e4SDavid E. O'Brien }
346c80476e4SDavid E. O'Brien break;
3473b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
348c80476e4SDavid E. O'Brien
349c80476e4SDavid E. O'Brien default:
350c80476e4SDavid E. O'Brien abort();
351c80476e4SDavid E. O'Brien }
352c80476e4SDavid E. O'Brien break;
353c80476e4SDavid E. O'Brien
354c80476e4SDavid E. O'Brien default:
35545e5710bSMark Peek goto bad_spec;
356c80476e4SDavid E. O'Brien }
357c80476e4SDavid E. O'Brien
35845e5710bSMark Peek end:
35945e5710bSMark Peek cleanup_ignore(&b);
36045e5710bSMark Peek cleanup_until(&b);
36145e5710bSMark Peek Strbuf_terminate(&b);
36245e5710bSMark Peek str->buf = xrealloc(b.s, (b.len + 1) * sizeof (*str->buf));
36345e5710bSMark Peek str->len = b.len;
364c80476e4SDavid E. O'Brien return str;
36545e5710bSMark Peek
36645e5710bSMark Peek bad_spec:
36745e5710bSMark Peek bad_spec(s);
36845e5710bSMark Peek cleanup_until(&b);
36945e5710bSMark Peek return NULL;
370c80476e4SDavid E. O'Brien }
371c80476e4SDavid E. O'Brien
372c80476e4SDavid E. O'Brien
373c80476e4SDavid E. O'Brien static CStr *
parsestring(const Char * str,CStr * buf)37445e5710bSMark Peek parsestring(const Char *str, CStr *buf)
375c80476e4SDavid E. O'Brien {
37645e5710bSMark Peek struct Strbuf b = Strbuf_INIT;
377c80476e4SDavid E. O'Brien const Char *p;
37823338178SMark Peek eChar es;
379c80476e4SDavid E. O'Brien
380c80476e4SDavid E. O'Brien if (*str == 0) {
381a15e6f9aSMark Peek xprintf("%s", CGETS(20, 5, "Null string specification\n"));
382c80476e4SDavid E. O'Brien return NULL;
383c80476e4SDavid E. O'Brien }
384c80476e4SDavid E. O'Brien
38545e5710bSMark Peek cleanup_push(&b, Strbuf_cleanup);
386c80476e4SDavid E. O'Brien for (p = str; *p != 0; p++) {
387c80476e4SDavid E. O'Brien if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
38845e5710bSMark Peek if ((es = parseescape(&p)) == CHAR_ERR) {
38945e5710bSMark Peek cleanup_until(&b);
390c80476e4SDavid E. O'Brien return 0;
39145e5710bSMark Peek } else
39245e5710bSMark Peek Strbuf_append1(&b, es);
393c80476e4SDavid E. O'Brien }
394c80476e4SDavid E. O'Brien else
39545e5710bSMark Peek Strbuf_append1(&b, *p & CHAR);
396c80476e4SDavid E. O'Brien }
39745e5710bSMark Peek cleanup_ignore(&b);
39845e5710bSMark Peek cleanup_until(&b);
39945e5710bSMark Peek Strbuf_terminate(&b);
40045e5710bSMark Peek buf->buf = xrealloc(b.s, (b.len + 1) * sizeof (*buf->buf));
40145e5710bSMark Peek buf->len = b.len;
402c80476e4SDavid E. O'Brien return buf;
403c80476e4SDavid E. O'Brien }
404c80476e4SDavid E. O'Brien
405c80476e4SDavid E. O'Brien static void
print_all_keys(void)40645e5710bSMark Peek print_all_keys(void)
407c80476e4SDavid E. O'Brien {
408c80476e4SDavid E. O'Brien int prev, i;
409c80476e4SDavid E. O'Brien CStr nilstr;
410c80476e4SDavid E. O'Brien nilstr.buf = NULL;
411c80476e4SDavid E. O'Brien nilstr.len = 0;
412c80476e4SDavid E. O'Brien
413c80476e4SDavid E. O'Brien
414a15e6f9aSMark Peek xprintf("%s", CGETS(20, 6, "Standard key bindings\n"));
415c80476e4SDavid E. O'Brien prev = 0;
416c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) {
417c80476e4SDavid E. O'Brien if (CcKeyMap[prev] == CcKeyMap[i])
418c80476e4SDavid E. O'Brien continue;
419c80476e4SDavid E. O'Brien printkeys(CcKeyMap, prev, i - 1);
420c80476e4SDavid E. O'Brien prev = i;
421c80476e4SDavid E. O'Brien }
422c80476e4SDavid E. O'Brien printkeys(CcKeyMap, prev, i - 1);
423c80476e4SDavid E. O'Brien
424a15e6f9aSMark Peek xprintf("%s", CGETS(20, 7, "Alternative key bindings\n"));
425c80476e4SDavid E. O'Brien prev = 0;
426c80476e4SDavid E. O'Brien for (i = 0; i < 256; i++) {
427c80476e4SDavid E. O'Brien if (CcAltMap[prev] == CcAltMap[i])
428c80476e4SDavid E. O'Brien continue;
429c80476e4SDavid E. O'Brien printkeys(CcAltMap, prev, i - 1);
430c80476e4SDavid E. O'Brien prev = i;
431c80476e4SDavid E. O'Brien }
432c80476e4SDavid E. O'Brien printkeys(CcAltMap, prev, i - 1);
433a15e6f9aSMark Peek xprintf("%s", CGETS(20, 8, "Multi-character bindings\n"));
434c80476e4SDavid E. O'Brien PrintXkey(NULL); /* print all Xkey bindings */
435a15e6f9aSMark Peek xprintf("%s", CGETS(20, 9, "Arrow key bindings\n"));
436c80476e4SDavid E. O'Brien PrintArrowKeys(&nilstr);
437c80476e4SDavid E. O'Brien }
438c80476e4SDavid E. O'Brien
439c80476e4SDavid E. O'Brien static void
printkeys(KEYCMD * map,int first,int last)44045e5710bSMark Peek printkeys(KEYCMD *map, int first, int last)
441c80476e4SDavid E. O'Brien {
44223338178SMark Peek struct KeyFuncs *fp;
443c80476e4SDavid E. O'Brien Char firstbuf[2], lastbuf[2];
444c80476e4SDavid E. O'Brien CStr fb, lb;
44545e5710bSMark Peek unsigned char *unparsed;
446c80476e4SDavid E. O'Brien fb.buf = firstbuf;
447c80476e4SDavid E. O'Brien lb.buf = lastbuf;
448c80476e4SDavid E. O'Brien
449c80476e4SDavid E. O'Brien firstbuf[0] = (Char) first;
450c80476e4SDavid E. O'Brien firstbuf[1] = 0;
451c80476e4SDavid E. O'Brien lastbuf[0] = (Char) last;
452c80476e4SDavid E. O'Brien lastbuf[1] = 0;
453c80476e4SDavid E. O'Brien fb.len = 1;
454c80476e4SDavid E. O'Brien lb.len = 1;
455c80476e4SDavid E. O'Brien
45645e5710bSMark Peek unparsed = unparsestring(&fb, STRQQ);
45745e5710bSMark Peek cleanup_push(unparsed, xfree);
458c80476e4SDavid E. O'Brien if (map[first] == F_UNASSIGNED) {
459c80476e4SDavid E. O'Brien if (first == last)
46045e5710bSMark Peek xprintf(CGETS(20, 10, "%-15s-> is undefined\n"), unparsed);
46145e5710bSMark Peek cleanup_until(unparsed);
462c80476e4SDavid E. O'Brien return;
463c80476e4SDavid E. O'Brien }
464c80476e4SDavid E. O'Brien
465c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) {
466c80476e4SDavid E. O'Brien if (fp->func == map[first]) {
46745e5710bSMark Peek if (first == last)
46845e5710bSMark Peek xprintf("%-15s-> %s\n", unparsed, fp->name);
469c80476e4SDavid E. O'Brien else {
47045e5710bSMark Peek unsigned char *p;
47145e5710bSMark Peek
47245e5710bSMark Peek p = unparsestring(&lb, STRQQ);
47345e5710bSMark Peek cleanup_push(p, xfree);
47445e5710bSMark Peek xprintf("%-4s to %-7s-> %s\n", unparsed, p, fp->name);
475c80476e4SDavid E. O'Brien }
47645e5710bSMark Peek cleanup_until(unparsed);
477c80476e4SDavid E. O'Brien return;
478c80476e4SDavid E. O'Brien }
479c80476e4SDavid E. O'Brien }
48045e5710bSMark Peek xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), unparsed);
48145e5710bSMark Peek if (map == CcKeyMap)
482c80476e4SDavid E. O'Brien xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
48345e5710bSMark Peek else
484c80476e4SDavid E. O'Brien xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
48545e5710bSMark Peek cleanup_until(unparsed);
486c80476e4SDavid E. O'Brien }
487c80476e4SDavid E. O'Brien
488c80476e4SDavid E. O'Brien static void
bindkey_usage(void)48945e5710bSMark Peek bindkey_usage(void)
490c80476e4SDavid E. O'Brien {
491a15e6f9aSMark Peek xprintf("%s", CGETS(20, 12,
492c80476e4SDavid E. O'Brien "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
493a15e6f9aSMark Peek xprintf("%s", CGETS(20, 13,
494c80476e4SDavid E. O'Brien " -a list or bind KEY in alternative key map\n"));
495a15e6f9aSMark Peek xprintf("%s", CGETS(20, 14,
496c80476e4SDavid E. O'Brien " -b interpret KEY as a C-, M-, F- or X- key name\n"));
497a15e6f9aSMark Peek xprintf("%s", CGETS(20, 15,
498c80476e4SDavid E. O'Brien " -s interpret COMMAND as a literal string to be output\n"));
499a15e6f9aSMark Peek xprintf("%s", CGETS(20, 16,
500c80476e4SDavid E. O'Brien " -c interpret COMMAND as a builtin or external command\n"));
501a15e6f9aSMark Peek xprintf("%s", CGETS(20, 17,
502c80476e4SDavid E. O'Brien " -v bind all keys to vi bindings\n"));
503a15e6f9aSMark Peek xprintf("%s", CGETS(20, 18,
504c80476e4SDavid E. O'Brien " -e bind all keys to emacs bindings\n"));
505*19d2e3deSDmitry Chagin xprintf(CGETS(20, 19,
506*19d2e3deSDmitry Chagin " -d bind all keys to default editor's bindings (%s)\n"),
507*19d2e3deSDmitry Chagin #ifdef VIDEFAULT
508*19d2e3deSDmitry Chagin "vi"
509*19d2e3deSDmitry Chagin #else /* EMACSDEFAULT */
510*19d2e3deSDmitry Chagin "emacs"
511*19d2e3deSDmitry Chagin #endif /* VIDEFAULT */
512*19d2e3deSDmitry Chagin );
513a15e6f9aSMark Peek xprintf("%s", CGETS(20, 20,
514c80476e4SDavid E. O'Brien " -l list editor commands with descriptions\n"));
515a15e6f9aSMark Peek xprintf("%s", CGETS(20, 21,
516c80476e4SDavid E. O'Brien " -r remove KEY's binding\n"));
517a15e6f9aSMark Peek xprintf("%s", CGETS(20, 22,
518c80476e4SDavid E. O'Brien " -k interpret KEY as a symbolic arrow-key name\n"));
519a15e6f9aSMark Peek xprintf("%s", CGETS(20, 23,
520c80476e4SDavid E. O'Brien " -- force a break from option processing\n"));
521a15e6f9aSMark Peek xprintf("%s", CGETS(20, 24,
522c80476e4SDavid E. O'Brien " -u (or any invalid option) this message\n"));
523c80476e4SDavid E. O'Brien xprintf("\n");
524a15e6f9aSMark Peek xprintf("%s", CGETS(20, 25,
525c80476e4SDavid E. O'Brien "Without KEY or COMMAND, prints all bindings\n"));
526a15e6f9aSMark Peek xprintf("%s", CGETS(20, 26,
527c80476e4SDavid E. O'Brien "Without COMMAND, prints the binding for KEY.\n"));
528c80476e4SDavid E. O'Brien }
529c80476e4SDavid E. O'Brien
530c80476e4SDavid E. O'Brien static void
list_functions(void)53145e5710bSMark Peek list_functions(void)
532c80476e4SDavid E. O'Brien {
53323338178SMark Peek struct KeyFuncs *fp;
534c80476e4SDavid E. O'Brien
535c80476e4SDavid E. O'Brien for (fp = FuncNames; fp->name; fp++) {
536c80476e4SDavid E. O'Brien xprintf("%s\n %s\n", fp->name, fp->desc);
537c80476e4SDavid E. O'Brien }
538c80476e4SDavid E. O'Brien }
539