1 /* $Header: /p/tcsh/cvsroot/tcsh/tc.bind.c,v 3.45 2009/06/25 21:15:37 christos Exp $ */
3 * tc.bind.c: Key binding functions
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 RCSID("$tcsh: tc.bind.c,v 3.45 2009/06/25 21:15:37 christos Exp $")
40 static void printkey (const KEYCMD
*, CStr
*);
41 static KEYCMD
parsecmd (Char
*);
42 static void bad_spec (const Char
*);
43 static CStr
*parsestring (const Char
*, CStr
*);
44 static CStr
*parsebind (const Char
*, CStr
*);
45 static void print_all_keys (void);
46 static void printkeys (KEYCMD
*, int, int);
47 static void bindkey_usage (void);
48 static void list_functions (void);
50 extern int MapsAreInited
;
57 dobindkey(Char
**v
, struct command
*c
)
60 int ntype
, no
, removeb
, key
, bindk
;
74 key
= removeb
= bindk
= 0;
75 for (no
= 1, par
= v
[no
];
76 par
!= NULL
&& (*par
++ & CHAR
) == '-'; no
++, par
= v
[no
]) {
77 if ((p
= (*par
& CHAR
)) == '-') {
110 #else /* EMACSDEFAULT */
112 #endif /* VIDEFAULT */
129 if (!IsArrowKey(v
[no
]))
130 xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v
[no
]);
131 in
.buf
= Strsave(v
[no
++]);
132 in
.len
= Strlen(in
.buf
);
136 if (parsebind(v
[no
++], &in
) == NULL
)
140 if (parsestring(v
[no
++], &in
) == NULL
)
144 cleanup_push(in
.buf
, xfree
);
147 if (in
.buf
[0] > 0xFF) {
149 cleanup_until(in
.buf
);
153 ch
= (uChar
) in
.buf
[0];
157 (void) ClearArrowKeys(&in
);
158 else if (in
.len
> 1) {
159 (void) DeleteXkey(&in
);
161 else if (map
[ch
] == F_XKEY
) {
162 (void) DeleteXkey(&in
);
163 map
[ch
] = F_UNASSIGNED
;
166 map
[ch
] = F_UNASSIGNED
;
168 cleanup_until(in
.buf
);
176 cleanup_until(in
.buf
);
181 cleanup_until(in
.buf
);
187 if (parsestring(v
[no
], &out
) == NULL
) {
188 cleanup_until(in
.buf
);
191 cleanup_push(out
.buf
, xfree
);
193 if (SetArrowKeys(&in
, XmapStr(&out
), ntype
) == -1)
194 xprintf(CGETS(20, 2, "Bad key name: %S\n"), in
.buf
);
196 cleanup_ignore(out
.buf
);
199 AddXkey(&in
, XmapStr(&out
), ntype
);
203 if ((cmd
= parsecmd(v
[no
])) == 0) {
204 cleanup_until(in
.buf
);
208 (void) SetArrowKeys(&in
, XmapCmd((int) cmd
), ntype
);
211 AddXkey(&in
, XmapCmd((int) cmd
), ntype
);
224 cleanup_until(in
.buf
);
230 printkey(const KEYCMD
*map
, CStr
*in
)
235 unsigned char *unparsed
;
237 unparsed
= unparsestring(in
, STRQQ
);
238 cleanup_push(unparsed
, xfree
);
239 for (fp
= FuncNames
; fp
->name
; fp
++) {
240 if (fp
->func
== map
[(uChar
) *(in
->buf
)]) {
241 xprintf("%s\t->\t%s\n", unparsed
, fp
->name
);
244 cleanup_until(unparsed
);
255 for (fp
= FuncNames
; fp
->name
; fp
++) {
256 if (strcmp(short2str(str
), fp
->name
) == 0) {
257 return (KEYCMD
) fp
->func
;
260 xprintf(CGETS(20, 3, "Bad command name: %S\n"), str
);
266 bad_spec(const Char
*str
)
268 xprintf(CGETS(20, 4, "Bad key spec %S\n"), str
);
272 parsebind(const Char
*s
, CStr
*str
)
274 struct Strbuf b
= Strbuf_INIT
;
276 cleanup_push(&b
, Strbuf_cleanup
);
278 Strbuf_append1(&b
, *s
);
286 Strbuf_append1(&b
, (*s
== '?') ? '\177' : ((*s
& CHAR
) & 0237));
288 Strbuf_append1(&b
, (*s
== '?') ? CTL_ESC('\177')
289 : _toebcdic
[_toascii
[*s
& CHAR
] & 0237]);
299 #endif /* WINNT_NATIVE */
300 if (s
[1] != '-' || s
[2] == '\0')
304 case 'F': case 'f': /* Turn into ^[str */
305 Strbuf_append1(&b
, CTL_ESC('\033'));
306 Strbuf_append(&b
, s
);
309 case 'C': case 'c': /* Turn into ^c */
311 Strbuf_append1(&b
, (*s
== '?') ? '\177' : ((*s
& CHAR
) & 0237));
313 Strbuf_append1(&b
, (*s
== '?') ? CTL_ESC('\177')
314 : _toebcdic
[_toascii
[*s
& CHAR
] & 0237]);
318 case 'X' : case 'x': /* Turn into ^Xc */
320 Strbuf_append1(&b
, 'X' & 0237);
322 Strbuf_append1(&b
, _toebcdic
[_toascii
['X'] & 0237]);
324 Strbuf_append1(&b
, *s
);
327 case 'M' : case 'm': /* Turn into 0x80|c */
329 Strbuf_append1(&b
, CTL_ESC('\033'));
330 Strbuf_append1(&b
, *s
);
333 Strbuf_append1(&b
, *s
| 0x80);
335 Strbuf_append1(&b
, _toebcdic
[_toascii
[*s
] | 0x80]);
340 case 'N' : case 'n': /* NT */
344 bnt
= nt_translate_bindkey(s
);
346 Strbuf_append1(&b
, bnt
);
351 #endif /* WINNT_NATIVE */
365 Strbuf_terminate(&b
);
366 str
->buf
= xrealloc(b
.s
, (b
.len
+ 1) * sizeof (*str
->buf
));
378 parsestring(const Char
*str
, CStr
*buf
)
380 struct Strbuf b
= Strbuf_INIT
;
385 xprintf("%s", CGETS(20, 5, "Null string specification\n"));
389 cleanup_push(&b
, Strbuf_cleanup
);
390 for (p
= str
; *p
!= 0; p
++) {
391 if ((*p
& CHAR
) == '\\' || (*p
& CHAR
) == '^') {
392 if ((es
= parseescape(&p
)) == CHAR_ERR
) {
396 Strbuf_append1(&b
, es
);
399 Strbuf_append1(&b
, *p
& CHAR
);
403 Strbuf_terminate(&b
);
404 buf
->buf
= xrealloc(b
.s
, (b
.len
+ 1) * sizeof (*buf
->buf
));
418 xprintf("%s", CGETS(20, 6, "Standard key bindings\n"));
420 for (i
= 0; i
< 256; i
++) {
421 if (CcKeyMap
[prev
] == CcKeyMap
[i
])
423 printkeys(CcKeyMap
, prev
, i
- 1);
426 printkeys(CcKeyMap
, prev
, i
- 1);
428 xprintf("%s", CGETS(20, 7, "Alternative key bindings\n"));
430 for (i
= 0; i
< 256; i
++) {
431 if (CcAltMap
[prev
] == CcAltMap
[i
])
433 printkeys(CcAltMap
, prev
, i
- 1);
436 printkeys(CcAltMap
, prev
, i
- 1);
437 xprintf("%s", CGETS(20, 8, "Multi-character bindings\n"));
438 PrintXkey(NULL
); /* print all Xkey bindings */
439 xprintf("%s", CGETS(20, 9, "Arrow key bindings\n"));
440 PrintArrowKeys(&nilstr
);
444 printkeys(KEYCMD
*map
, int first
, int last
)
447 Char firstbuf
[2], lastbuf
[2];
449 unsigned char *unparsed
;
453 firstbuf
[0] = (Char
) first
;
455 lastbuf
[0] = (Char
) last
;
460 unparsed
= unparsestring(&fb
, STRQQ
);
461 cleanup_push(unparsed
, xfree
);
462 if (map
[first
] == F_UNASSIGNED
) {
464 xprintf(CGETS(20, 10, "%-15s-> is undefined\n"), unparsed
);
465 cleanup_until(unparsed
);
469 for (fp
= FuncNames
; fp
->name
; fp
++) {
470 if (fp
->func
== map
[first
]) {
472 xprintf("%-15s-> %s\n", unparsed
, fp
->name
);
476 p
= unparsestring(&lb
, STRQQ
);
477 cleanup_push(p
, xfree
);
478 xprintf("%-4s to %-7s-> %s\n", unparsed
, p
, fp
->name
);
480 cleanup_until(unparsed
);
484 xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"), unparsed
);
486 xprintf("CcKeyMap[%d] == %d\n", first
, CcKeyMap
[first
]);
488 xprintf("CcAltMap[%d] == %d\n", first
, CcAltMap
[first
]);
489 cleanup_until(unparsed
);
495 xprintf("%s", CGETS(20, 12,
496 "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
497 xprintf("%s", CGETS(20, 13,
498 " -a list or bind KEY in alternative key map\n"));
499 xprintf("%s", CGETS(20, 14,
500 " -b interpret KEY as a C-, M-, F- or X- key name\n"));
501 xprintf("%s", CGETS(20, 15,
502 " -s interpret COMMAND as a literal string to be output\n"));
503 xprintf("%s", CGETS(20, 16,
504 " -c interpret COMMAND as a builtin or external command\n"));
505 xprintf("%s", CGETS(20, 17,
506 " -v bind all keys to vi bindings\n"));
507 xprintf("%s", CGETS(20, 18,
508 " -e bind all keys to emacs bindings\n"));
509 xprintf("%s", CGETS(20, 19,
510 " -d bind all keys to default editor's bindings\n"));
511 xprintf("%s", CGETS(20, 20,
512 " -l list editor commands with descriptions\n"));
513 xprintf("%s", CGETS(20, 21,
514 " -r remove KEY's binding\n"));
515 xprintf("%s", CGETS(20, 22,
516 " -k interpret KEY as a symbolic arrow-key name\n"));
517 xprintf("%s", CGETS(20, 23,
518 " -- force a break from option processing\n"));
519 xprintf("%s", CGETS(20, 24,
520 " -u (or any invalid option) this message\n"));
522 xprintf("%s", CGETS(20, 25,
523 "Without KEY or COMMAND, prints all bindings\n"));
524 xprintf("%s", CGETS(20, 26,
525 "Without COMMAND, prints the binding for KEY.\n"));
533 for (fp
= FuncNames
; fp
->name
; fp
++) {
534 xprintf("%s\n %s\n", fp
->name
, fp
->desc
);