1 /* $Header: /src/pub/tcsh/tc.bind.c,v 3.36 2002/03/08 17:36:47 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("$Id: tc.bind.c,v 3.36 2002/03/08 17:36:47 christos Exp $")
41 static int tocontrol
__P((int));
42 static char *unparsekey
__P((int));
43 static KEYCMD getkeycmd
__P((Char
**));
44 static int parsekey
__P((Char
**));
45 static void pkeys
__P((int, int));
48 static void printkey
__P((KEYCMD
*, CStr
*));
49 static KEYCMD parsecmd
__P((Char
*));
50 static void bad_spec
__P((Char
*));
51 static CStr
*parsestring
__P((Char
*, CStr
*));
52 static CStr
*parsebind
__P((Char
*, CStr
*));
53 static void print_all_keys
__P((void));
54 static void printkeys
__P((KEYCMD
*, int, int));
55 static void bindkey_usage
__P((void));
56 static void list_functions
__P((void));
58 extern int MapsAreInited
;
70 int ntype
, no
, remove
, key
, bind
;
90 key
= remove
= bind
= 0;
91 for (no
= 1, par
= v
[no
];
92 par
!= NULL
&& (*par
++ & CHAR
) == '-'; no
++, par
= v
[no
]) {
93 if ((p
= (*par
& CHAR
)) == '-') {
126 #else /* EMACSDEFAULT */
128 #endif /* VIDEFAULT */
145 if (!IsArrowKey(v
[no
]))
146 xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v
[no
]);
148 in
.len
= Strlen(in
.buf
);
152 if (parsebind(v
[no
++], &in
) == NULL
)
156 if (parsestring(v
[no
++], &in
) == NULL
)
161 ch
= (uChar
) in
.buf
[0];
165 (void) ClearArrowKeys(&in
);
169 (void) DeleteXkey(&in
);
171 else if (map
[ch
] == F_XKEY
) {
172 (void) DeleteXkey(&in
);
173 map
[ch
] = F_UNASSIGNED
;
176 map
[ch
] = F_UNASSIGNED
;
194 if (parsestring(v
[no
], &out
) == NULL
)
197 if (SetArrowKeys(&in
, XmapStr(&out
), ntype
) == -1)
198 xprintf(CGETS(20, 2, "Bad key name: %S\n"), in
);
201 AddXkey(&in
, XmapStr(&out
), ntype
);
205 if ((cmd
= parsecmd(v
[no
])) == 0)
208 (void) SetArrowKeys(&in
, XmapCmd((int) cmd
), ntype
);
211 AddXkey(&in
, XmapCmd((int) cmd
), ntype
);
233 unsigned char outbuf
[100];
234 register struct KeyFuncs
*fp
;
237 (void) unparsestring(in
, outbuf
, STRQQ
);
238 for (fp
= FuncNames
; fp
->name
; fp
++) {
239 if (fp
->func
== map
[(uChar
) *(in
->buf
)]) {
240 xprintf("%s\t->\t%s\n", outbuf
, fp
->name
);
252 register struct KeyFuncs
*fp
;
254 for (fp
= FuncNames
; fp
->name
; fp
++) {
255 if (strcmp(short2str(str
), fp
->name
) == 0) {
256 return (KEYCMD
) fp
->func
;
259 xprintf(CGETS(20, 3, "Bad command name: %S\n"), str
);
268 xprintf(CGETS(20, 4, "Bad key spec %S\n"), str
);
277 extern bool NoNLSRebind
;
278 #endif /* DSPMBYTE */
284 str
->len
= (int) (b
- str
->buf
);
292 *b
++ = (*s
== '?') ? '\177' : ((*s
& CHAR
) & 0237);
294 *b
++ = (*s
== '?') ? CTL_ESC('\177') : _toebcdic
[_toascii
[*s
& CHAR
] & 0237];
305 #endif /* WINNT_NATIVE */
306 if (s
[1] != '-' || s
[2] == '\0') {
312 case 'F': case 'f': /* Turn into ^[str */
313 *b
++ = CTL_ESC('\033');
314 while ((*b
++ = *s
++) != '\0')
319 case 'C': case 'c': /* Turn into ^c */
321 *b
++ = (*s
== '?') ? '\177' : ((*s
& CHAR
) & 0237);
323 *b
++ = (*s
== '?') ? CTL_ESC('\177') : _toebcdic
[_toascii
[*s
& CHAR
] & 0237];
328 case 'X' : case 'x': /* Turn into ^Xc */
332 *b
++ = _toebcdic
[_toascii
['X'] & 0237];
338 case 'M' : case 'm': /* Turn into 0x80|c */
341 *b
++ = CTL_ESC('\033');
344 #endif /* DSPMBYTE */
348 *b
++ = _toebcdic
[_toascii
[*s
] | 0x80];
352 #endif /* DSPMBYTE */
356 case 'N' : case 'n': /* NT */
360 bnt
= nt_translate_bindkey(s
);
367 #endif /* WINNT_NATIVE */
381 str
->len
= (int) (b
- str
->buf
);
387 parsestring(str
, buf
)
397 xprintf(CGETS(20, 5, "Null string specification\n"));
401 for (p
= str
; *p
!= 0; p
++) {
402 if ((*p
& CHAR
) == '\\' || (*p
& CHAR
) == '^') {
403 if ((es
= parseescape(&p
)) == -1)
412 buf
->len
= (int) (b
- buf
->buf
);
425 xprintf(CGETS(20, 6, "Standard key bindings\n"));
427 for (i
= 0; i
< 256; i
++) {
428 if (CcKeyMap
[prev
] == CcKeyMap
[i
])
430 printkeys(CcKeyMap
, prev
, i
- 1);
433 printkeys(CcKeyMap
, prev
, i
- 1);
435 xprintf(CGETS(20, 7, "Alternative key bindings\n"));
437 for (i
= 0; i
< 256; i
++) {
438 if (CcAltMap
[prev
] == CcAltMap
[i
])
440 printkeys(CcAltMap
, prev
, i
- 1);
443 printkeys(CcAltMap
, prev
, i
- 1);
444 xprintf(CGETS(20, 8, "Multi-character bindings\n"));
445 PrintXkey(NULL
); /* print all Xkey bindings */
446 xprintf(CGETS(20, 9, "Arrow key bindings\n"));
447 PrintArrowKeys(&nilstr
);
451 printkeys(map
, first
, last
)
455 register struct KeyFuncs
*fp
;
456 Char firstbuf
[2], lastbuf
[2];
458 unsigned char unparsbuf
[10], extrabuf
[10];
462 firstbuf
[0] = (Char
) first
;
464 lastbuf
[0] = (Char
) last
;
469 if (map
[first
] == F_UNASSIGNED
) {
471 xprintf(CGETS(20, 10, "%-15s-> is undefined\n"),
472 unparsestring(&fb
, unparsbuf
, STRQQ
));
476 for (fp
= FuncNames
; fp
->name
; fp
++) {
477 if (fp
->func
== map
[first
]) {
479 xprintf("%-15s-> %s\n",
480 unparsestring(&fb
, unparsbuf
, STRQQ
), fp
->name
);
483 xprintf("%-4s to %-7s-> %s\n",
484 unparsestring(&fb
, unparsbuf
, STRQQ
),
485 unparsestring(&lb
, extrabuf
, STRQQ
), fp
->name
);
490 if (map
== CcKeyMap
) {
491 xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
492 unparsestring(&fb
, unparsbuf
, STRQQ
));
493 xprintf("CcKeyMap[%d] == %d\n", first
, CcKeyMap
[first
]);
496 xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
497 unparsestring(&fb
, unparsbuf
, STRQQ
));
498 xprintf("CcAltMap[%d] == %d\n", first
, CcAltMap
[first
]);
505 xprintf(CGETS(20, 12,
506 "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
507 xprintf(CGETS(20, 13,
508 " -a list or bind KEY in alternative key map\n"));
509 xprintf(CGETS(20, 14,
510 " -b interpret KEY as a C-, M-, F- or X- key name\n"));
511 xprintf(CGETS(20, 15,
512 " -s interpret COMMAND as a literal string to be output\n"));
513 xprintf(CGETS(20, 16,
514 " -c interpret COMMAND as a builtin or external command\n"));
515 xprintf(CGETS(20, 17,
516 " -v bind all keys to vi bindings\n"));
517 xprintf(CGETS(20, 18,
518 " -e bind all keys to emacs bindings\n"));
519 xprintf(CGETS(20, 19,
520 " -d bind all keys to default editor's bindings\n"));
521 xprintf(CGETS(20, 20,
522 " -l list editor commands with descriptions\n"));
523 xprintf(CGETS(20, 21,
524 " -r remove KEY's binding\n"));
525 xprintf(CGETS(20, 22,
526 " -k interpret KEY as a symbolic arrow-key name\n"));
527 xprintf(CGETS(20, 23,
528 " -- force a break from option processing\n"));
529 xprintf(CGETS(20, 24,
530 " -u (or any invalid option) this message\n"));
532 xprintf(CGETS(20, 25,
533 "Without KEY or COMMAND, prints all bindings\n"));
534 xprintf(CGETS(20, 26,
535 "Without COMMAND, prints the binding for KEY.\n"));
541 register struct KeyFuncs
*fp
;
543 for (fp
= FuncNames
; fp
->name
; fp
++) {
544 xprintf("%s\n %s\n", fp
->name
, fp
->desc
);
551 * Unfortunately the apollo optimizer does not like & operations
552 * with 0377, and produces illegal instructions. So we make it
553 * an unsigned char, and hope for the best.
554 * Of-course the compiler is smart enough to produce bad assembly
555 * language instructions, but dumb when it comes to fold the constant :-)
558 static unsigned char APOLLO_0377
= 0377;
560 # define APOLLO_0377 0377
578 /* EBCDIC: simulate ASCII-behavior by transforming to ASCII and back */
579 c
= _toebcdic
[_toascii
[c
] & 037];
585 unparsekey(c
) /* 'c' -> "c", '^C' -> "^" + "C" */
598 if ((c
& META
) && !(Isprint(c
) || (Iscntrl(c
) && Isprint(c
| 0100)))) {
610 (void) strcpy(cp
, "Spc");
613 (void) strcpy(cp
, "Lfd");
616 (void) strcpy(cp
, "Ret");
619 (void) strcpy(cp
, "Tab");
623 (void) strcpy(cp
, "Esc");
626 (void) strcpy(cp
, "Del");
640 if (*cp
== CTL_ESC('\033')) {
641 (void) strcpy(cp
, "Esc");
644 else if (*cp
== CTL_ESC('\177')) {
645 (void) strcpy(cp
, "Del");
648 else if (Isupper(_toebcdic
[_toascii
[c
]|0100])
649 || strchr("@[\\]^_", _toebcdic
[_toascii
[c
]|0100]) != NULL
) {
651 *cp
++ = _toebcdic
[_toascii
[c
]|0100]
654 xsnprintf(cp
, 3, "\\%3.3o", c
);
657 #endif /* IS_ASCII */
665 register Char
*s
= *sp
;
667 register KEYCMD keycmd
= F_UNASSIGNED
;
675 if (*s
== '^' && s
[1]) {
685 switch (map
[c
| meta
]) {
709 Char
**sp
; /* Return position of first unparsed character
710 * for return value -2 (xkeynext) */
712 register int c
, meta
= 0, control
= 0, ctrlx
= 0;
717 xprintf(CGETS(20, 27, "bad key specification -- null string\n"));
721 xprintf(CGETS(20, 28, "bad key specification -- empty string\n"));
725 (void) strip(s
); /* trim to 7 bits. */
727 if (s
[1] == 0) /* single char */
728 return (s
[0] & APOLLO_0377
);
730 if ((s
[0] == 'F' || s
[0] == 'f') && s
[1] == '-') {
732 xprintf(CGETS(20, 29,
733 "Bad function-key specification. Null key not allowed\n"));
740 if (s
[0] == '0' && s
[1] == 'x') { /* if 0xn, then assume number */
742 for (s
+= 2; *s
; s
++) { /* convert to hex; skip the first 0 */
745 xprintf(CGETS(20, 30,
746 "bad key specification -- malformed hex number\n"));
747 return -1; /* error */
751 else if (*s
>= 'a' && *s
<= 'f')
753 else if (*s
>= 'F' && *s
<= 'F')
757 else if (s
[0] == '0' && Isdigit(s
[1])) { /* if 0n, then assume number */
759 for (s
++; *s
; s
++) { /* convert to octal; skip the first 0 */
760 if (!Isdigit(*s
) || *s
== '8' || *s
== '9') {
761 xprintf(CGETS(20, 31,
762 "bad key specification -- malformed octal number\n"));
763 return -1; /* error */
765 c
= (c
* 8) + *s
- '0';
768 else if (Isdigit(s
[0]) && Isdigit(s
[1])) { /* decimal number */
770 for (; *s
; s
++) { /* convert to octal; skip the first 0 */
772 xprintf(CGETS(20, 32,
773 "bad key specification -- malformed decimal number\n"));
774 return -1; /* error */
776 c
= (c
* 10) + *s
- '0';
780 keycmd
= getkeycmd(&s
);
782 if ((s
[0] == 'X' || s
[0] == 'x') && s
[1] == '-') { /* X- */
785 keycmd
= getkeycmd(&s
);
787 if ((*s
== 'm' || *s
== 'M') && s
[1] == '-') { /* meta */
790 keycmd
= getkeycmd(&s
);
792 else if (keycmd
== F_METANEXT
&& *s
) { /* meta */
794 keycmd
= getkeycmd(&s
);
796 if (*s
== '^' && s
[1]) {
799 keycmd
= getkeycmd(&s
);
801 else if ((*s
== 'c' || *s
== 'C') && s
[1] == '-') { /* control */
804 keycmd
= getkeycmd(&s
);
807 if (keycmd
== F_XKEY
) {
809 xprintf(CGETS(20, 33,
810 "Bad function-key specification.\n"));
811 xprintf(CGETS(20, 34, "Null key not allowed\n"));
818 if (s
[1] != 0) { /* if symbolic name */
822 if (!strcmp(ts
, "space") || !strcmp(ts
, "Spc"))
824 else if (!strcmp(ts
, "return") || !strcmp(ts
, "Ret"))
826 else if (!strcmp(ts
, "newline") || !strcmp(ts
, "Lfd"))
828 else if (!strcmp(ts
, "linefeed"))
830 else if (!strcmp(ts
, "tab"))
832 else if (!strcmp(ts
, "escape") || !strcmp(ts
, "Esc"))
834 else if (!strcmp(ts
, "backspace"))
836 else if (!strcmp(ts
, "delete"))
839 xprintf(CGETS(20, 35,
840 "bad key specification -- unknown name \"%S\"\n"), s
);
841 return -1; /* error */
845 c
= *s
; /* just a single char */
862 struct command
*dummy
;
865 register struct KeyFuncs
*fp
;
866 register int i
, prev
;
873 * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name,
874 * and the key; or 'bind' key to print the func for that key.
880 if (v
[1] && v
[2] && v
[3]) {
881 xprintf(CGETS(20, 36,
882 "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n"));
886 if (v
[1] && v
[2]) { /* if bind FUNCTION KEY */
887 for (fp
= FuncNames
; fp
->name
; fp
++) {
888 if (strcmp(short2str(v
[1]), fp
->name
) == 0) {
891 if ((c
= parsekey(&s
)) == -1)
893 if (c
== -2) { /* extended key */
894 for (i
= 0; i
< 256; i
++) {
895 if (i
!= CTL_ESC('\033') && (CcKeyMap
[i
] == F_XKEY
||
896 CcAltMap
[i
] == F_XKEY
)) {
909 for (l
= s
; *l
!= 0; l
++) {
914 cstr
.len
= Strlen(buf
);
915 AddXkey(&cstr
, XmapCmd(fp
->func
), XK_CMD
);
922 CcAltMap
[c
& APOLLO_0377
] = fp
->func
;
923 /* bind the vi cmd mode key */
925 buf
[0] = CTL_ESC('\033');
929 cstr
.len
= Strlen(buf
);
930 AddXkey(&cstr
, XmapCmd(fp
->func
), XK_CMD
);
934 buf
[0] = CTL_ESC('\030'); /* ^X */
935 buf
[1] = c
& APOLLO_0377
;
938 cstr
.len
= Strlen(buf
);
939 AddXkey(&cstr
, XmapCmd(fp
->func
), XK_CMD
);
940 CcKeyMap
[CTL_ESC('\030')] = F_XKEY
;
944 CcKeyMap
[c
] = fp
->func
; /* bind the key */
946 buf
[0] = CTL_ESC('\033');
950 cstr
.len
= Strlen(buf
);
951 AddXkey(&cstr
, XmapCmd(fp
->func
), XK_CMD
);
957 stderror(ERR_NAME
| ERR_STRING
, CGETS(20, 37, "Invalid function"));
960 char *cv
= short2str(v
[1]);
962 if (strcmp(cv
, "list") == 0) {
963 for (fp
= FuncNames
; fp
->name
; fp
++) {
964 xprintf("%s\n", fp
->name
);
968 if ((strcmp(cv
, "emacs") == 0) ||
970 (strcmp(cv
, "defaults") == 0) ||
971 (strcmp(cv
, "default") == 0) ||
973 (strcmp(cv
, "mg") == 0) ||
974 (strcmp(cv
, "gnumacs") == 0)) {
975 /* reset keys to default */
979 else if ((strcmp(cv
, "vi") == 0)
980 || (strcmp(cv
, "default") == 0)
981 || (strcmp(cv
, "defaults") == 0)) {
984 else if (strcmp(cv
, "vi") == 0) {
988 else { /* want to know what this key does */
991 if ((c
= parsekey(&s
)) == -1)
993 if (c
== -2) { /* extended key */
995 cstr
.len
= Strlen(s
);
999 pkeys(c
, c
); /* must be regular key */
1002 else { /* list all the bindings */
1004 for (i
= 0; i
< 256; i
++) {
1005 if (CcKeyMap
[prev
] == CcKeyMap
[i
])
1012 for (i
= 256; i
< 512; i
++) {
1013 if (CcAltMap
[prev
& APOLLO_0377
] == CcAltMap
[i
& APOLLO_0377
])
1021 PrintXkey(&cstr
); /* print all Xkey bindings */
1028 register int first
, last
;
1030 register struct KeyFuncs
*fp
;
1031 register KEYCMD
*map
;
1037 first
&= APOLLO_0377
;
1038 last
&= APOLLO_0377
;
1045 if (map
[first
] == F_UNASSIGNED
) {
1047 xprintf(CGETS(20, 38, " %s\t\tis undefined\n"),
1048 unparsekey(first
| mask
));
1052 for (fp
= FuncNames
; fp
->name
; fp
++) {
1053 if (fp
->func
== map
[first
]) {
1055 xprintf(" %s\t\t%s\n",
1056 unparsekey((first
& APOLLO_0377
) | mask
), fp
->name
);
1058 (void) strcpy(buf
, unparsekey((first
& APOLLO_0377
) | mask
));
1059 xprintf(" %s..%s\t\t%s\n", buf
,
1060 unparsekey((last
& APOLLO_0377
) | mask
), fp
->name
);
1065 if (map
== CcKeyMap
) {
1066 xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
1068 xprintf("CcKeyMap[%d] == %d\n", first
, CcKeyMap
[first
]);
1071 xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
1072 unparsekey(first
& 0400));
1073 xprintf("CcAltMap[%d] == %d\n", first
, CcAltMap
[first
]);
1076 #endif /* OBSOLETE */