summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh/tc.bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcsh/tc.bind.c')
-rw-r--r--contrib/tcsh/tc.bind.c1079
1 files changed, 1079 insertions, 0 deletions
diff --git a/contrib/tcsh/tc.bind.c b/contrib/tcsh/tc.bind.c
new file mode 100644
index 0000000..3ff3839
--- /dev/null
+++ b/contrib/tcsh/tc.bind.c
@@ -0,0 +1,1079 @@
+/* $Header: /src/pub/tcsh/tc.bind.c,v 3.33 1998/11/24 18:17:40 christos Exp $ */
+/*
+ * tc.bind.c: Key binding functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.bind.c,v 3.33 1998/11/24 18:17:40 christos Exp $")
+
+#include "ed.h"
+#include "ed.defns.h"
+
+#ifdef OBSOLETE
+static int tocontrol __P((int));
+static char *unparsekey __P((int));
+static KEYCMD getkeycmd __P((Char **));
+static int parsekey __P((Char **));
+static void pkeys __P((int, int));
+#endif /* OBSOLETE */
+
+static void printkey __P((KEYCMD *, CStr *));
+static KEYCMD parsecmd __P((Char *));
+static void bad_spec __P((Char *));
+static CStr *parsestring __P((Char *, CStr *));
+static CStr *parsebind __P((Char *, CStr *));
+static void print_all_keys __P((void));
+static void printkeys __P((KEYCMD *, int, int));
+static void bindkey_usage __P((void));
+static void list_functions __P((void));
+
+extern int MapsAreInited;
+
+
+
+
+/*ARGSUSED*/
+void
+dobindkey(v, c)
+ Char **v;
+ struct command *c;
+{
+ KEYCMD *map;
+ int ntype, no, remove, key, bind;
+ Char *par;
+ Char p;
+ KEYCMD cmd;
+ CStr in;
+ CStr out;
+ Char inbuf[200];
+ Char outbuf[200];
+ uChar ch;
+ in.buf = inbuf;
+ out.buf = outbuf;
+ in.len = 0;
+ out.len = 0;
+
+ USE(c);
+ if (!MapsAreInited)
+ ed_InitMaps();
+
+ map = CcKeyMap;
+ ntype = XK_CMD;
+ key = remove = bind = 0;
+ for (no = 1, par = v[no];
+ par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
+ if ((p = (*par & CHAR)) == '-') {
+ no++;
+ break;
+ }
+ else
+ switch (p) {
+ case 'b':
+ bind = 1;
+ break;
+ case 'k':
+ key = 1;
+ break;
+ case 'a':
+ map = CcAltMap;
+ break;
+ case 's':
+ ntype = XK_STR;
+ break;
+ case 'c':
+ ntype = XK_EXE;
+ break;
+ case 'r':
+ remove = 1;
+ break;
+ case 'v':
+ ed_InitVIMaps();
+ return;
+ case 'e':
+ ed_InitEmacsMaps();
+ return;
+ case 'd':
+#ifdef VIDEFAULT
+ ed_InitVIMaps();
+#else /* EMACSDEFAULT */
+ ed_InitEmacsMaps();
+#endif /* VIDEFAULT */
+ return;
+ case 'l':
+ list_functions();
+ return;
+ default:
+ bindkey_usage();
+ return;
+ }
+ }
+
+ if (!v[no]) {
+ print_all_keys();
+ return;
+ }
+
+ if (key) {
+ if (!IsArrowKey(v[no]))
+ xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]);
+ in.buf = v[no++];
+ in.len = Strlen(in.buf);
+ }
+ else {
+ if (bind) {
+ if (parsebind(v[no++], &in) == NULL)
+ return;
+ }
+ else {
+ if (parsestring(v[no++], &in) == NULL)
+ return;
+ }
+ }
+
+ ch = (uChar) in.buf[0];
+
+ if (remove) {
+ if (key) {
+ (void) ClearArrowKeys(&in);
+ return;
+ }
+ if (in.len > 1) {
+ (void) DeleteXkey(&in);
+ }
+ else if (map[ch] == F_XKEY) {
+ (void) DeleteXkey(&in);
+ map[ch] = F_UNASSIGNED;
+ }
+ else {
+ map[ch] = F_UNASSIGNED;
+ }
+ return;
+ }
+ if (!v[no]) {
+ if (key)
+ PrintArrowKeys(&in);
+ else
+ printkey(map, &in);
+ return;
+ }
+ if (v[no + 1]) {
+ bindkey_usage();
+ return;
+ }
+ switch (ntype) {
+ case XK_STR:
+ case XK_EXE:
+ if (parsestring(v[no], &out) == NULL)
+ return;
+ if (key) {
+ if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1)
+ xprintf(CGETS(20, 2, "Bad key name: %S\n"), in);
+ }
+ else
+ AddXkey(&in, XmapStr(&out), ntype);
+ map[ch] = F_XKEY;
+ break;
+ case XK_CMD:
+ if ((cmd = parsecmd(v[no])) == 0)
+ return;
+ if (key)
+ (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype);
+ else {
+ if (in.len > 1) {
+ AddXkey(&in, XmapCmd((int) cmd), ntype);
+ map[ch] = F_XKEY;
+ }
+ else {
+ ClearXkey(map, &in);
+ map[ch] = cmd;
+ }
+ }
+ break;
+ default:
+ abort();
+ break;
+ }
+ if (key)
+ BindArrowKeys();
+}
+
+static void
+printkey(map, in)
+ KEYCMD *map;
+ CStr *in;
+{
+ unsigned char outbuf[100];
+ register struct KeyFuncs *fp;
+
+ if (in->len < 2) {
+ (void) unparsestring(in, outbuf, STRQQ);
+ for (fp = FuncNames; fp->name; fp++) {
+ if (fp->func == map[(uChar) *(in->buf)]) {
+ xprintf("%s\t->\t%s\n", outbuf, fp->name);
+ }
+ }
+ }
+ else
+ PrintXkey(in);
+}
+
+static KEYCMD
+parsecmd(str)
+ Char *str;
+{
+ register struct KeyFuncs *fp;
+
+ for (fp = FuncNames; fp->name; fp++) {
+ if (strcmp(short2str(str), fp->name) == 0) {
+ return (KEYCMD) fp->func;
+ }
+ }
+ xprintf(CGETS(20, 3, "Bad command name: %S\n"), str);
+ return 0;
+}
+
+
+static void
+bad_spec(str)
+ Char *str;
+{
+ xprintf(CGETS(20, 4, "Bad key spec %S\n"), str);
+}
+
+static CStr *
+parsebind(s, str)
+ Char *s;
+ CStr *str;
+{
+#ifdef DSPMBYTE
+ extern bool NoNLSRebind;
+#endif /* DSPMBYTE */
+ Char *b = str->buf;
+
+ if (Iscntrl(*s)) {
+ *b++ = *s;
+ *b = '\0';
+ str->len = (int) (b - str->buf);
+ return str;
+ }
+
+ switch (*s) {
+ case '^':
+ s++;
+#ifndef _OSD_POSIX
+ *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
+#else /*_OSD_POSIX*/
+ *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
+#endif /*_OSD_POSIX*/
+ *b = '\0';
+ break;
+
+ case 'F':
+ case 'M':
+ case 'X':
+ case 'C':
+#ifdef WINNT
+ case 'N':
+#endif /* WINNT */
+ if (s[1] != '-' || s[2] == '\0') {
+ bad_spec(s);
+ return NULL;
+ }
+ s += 2;
+ switch (s[-2]) {
+ case 'F': case 'f': /* Turn into ^[str */
+ *b++ = CTL_ESC('\033');
+ while ((*b++ = *s++) != '\0')
+ continue;
+ b--;
+ break;
+
+ case 'C': case 'c': /* Turn into ^c */
+#ifndef _OSD_POSIX
+ *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
+#else /*_OSD_POSIX*/
+ *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
+#endif /*_OSD_POSIX*/
+ *b = '\0';
+ break;
+
+ case 'X' : case 'x': /* Turn into ^Xc */
+#ifndef _OSD_POSIX
+ *b++ = 'X' & 0237;
+#else /*_OSD_POSIX*/
+ *b++ = _toebcdic[_toascii['X'] & 0237];
+#endif /*_OSD_POSIX*/
+ *b++ = *s;
+ *b = '\0';
+ break;
+
+ case 'M' : case 'm': /* Turn into 0x80|c */
+#ifdef DSPMBYTE
+ if (!NoNLSRebind) {
+ *b++ = CTL_ESC('\033');
+ *b++ = *s;
+ } else {
+#endif /* DSPMBYTE */
+#ifndef _OSD_POSIX
+ *b++ = *s | 0x80;
+#else /*_OSD_POSIX*/
+ *b++ = _toebcdic[_toascii[*s] | 0x80];
+#endif /*_OSD_POSIX*/
+#ifdef DSPMBYTE
+ }
+#endif /* DSPMBYTE */
+ *b = '\0';
+ break;
+#ifdef WINNT
+ case 'N' : case 'n': /* NT */
+ {
+ Char bnt;
+
+ bnt = nt_translate_bindkey(s);
+ if (bnt != 0)
+ *b++ = bnt;
+ else
+ bad_spec(s);
+ }
+ break;
+#endif /* WINNT */
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ return NULL;
+ }
+ break;
+
+ default:
+ bad_spec(s);
+ return NULL;
+ }
+
+ str->len = (int) (b - str->buf);
+ return str;
+}
+
+
+static CStr *
+parsestring(str, buf)
+ Char *str;
+ CStr *buf;
+{
+ Char *b;
+ const Char *p;
+ int es;
+
+ b = buf->buf;
+ if (*str == 0) {
+ xprintf(CGETS(20, 5, "Null string specification\n"));
+ return NULL;
+ }
+
+ for (p = str; *p != 0; p++) {
+ if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
+ if ((es = parseescape(&p)) == -1)
+ return 0;
+ else
+ *b++ = (Char) es;
+ }
+ else
+ *b++ = *p & CHAR;
+ }
+ *b = 0;
+ buf->len = (int) (b - buf->buf);
+ return buf;
+}
+
+static void
+print_all_keys()
+{
+ int prev, i;
+ CStr nilstr;
+ nilstr.buf = NULL;
+ nilstr.len = 0;
+
+
+ xprintf(CGETS(20, 6, "Standard key bindings\n"));
+ prev = 0;
+ for (i = 0; i < 256; i++) {
+ if (CcKeyMap[prev] == CcKeyMap[i])
+ continue;
+ printkeys(CcKeyMap, prev, i - 1);
+ prev = i;
+ }
+ printkeys(CcKeyMap, prev, i - 1);
+
+ xprintf(CGETS(20, 7, "Alternative key bindings\n"));
+ prev = 0;
+ for (i = 0; i < 256; i++) {
+ if (CcAltMap[prev] == CcAltMap[i])
+ continue;
+ printkeys(CcAltMap, prev, i - 1);
+ prev = i;
+ }
+ printkeys(CcAltMap, prev, i - 1);
+ xprintf(CGETS(20, 8, "Multi-character bindings\n"));
+ PrintXkey(NULL); /* print all Xkey bindings */
+ xprintf(CGETS(20, 9, "Arrow key bindings\n"));
+ PrintArrowKeys(&nilstr);
+}
+
+static void
+printkeys(map, first, last)
+ KEYCMD *map;
+ int first, last;
+{
+ register struct KeyFuncs *fp;
+ Char firstbuf[2], lastbuf[2];
+ CStr fb, lb;
+ unsigned char unparsbuf[10], extrabuf[10];
+ fb.buf = firstbuf;
+ lb.buf = lastbuf;
+
+ firstbuf[0] = (Char) first;
+ firstbuf[1] = 0;
+ lastbuf[0] = (Char) last;
+ lastbuf[1] = 0;
+ fb.len = 1;
+ lb.len = 1;
+
+ if (map[first] == F_UNASSIGNED) {
+ if (first == last)
+ xprintf(CGETS(20, 10, "%-15s-> is undefined\n"),
+ unparsestring(&fb, unparsbuf, STRQQ));
+ return;
+ }
+
+ for (fp = FuncNames; fp->name; fp++) {
+ if (fp->func == map[first]) {
+ if (first == last) {
+ xprintf("%-15s-> %s\n",
+ unparsestring(&fb, unparsbuf, STRQQ), fp->name);
+ }
+ else {
+ xprintf("%-4s to %-7s-> %s\n",
+ unparsestring(&fb, unparsbuf, STRQQ),
+ unparsestring(&lb, extrabuf, STRQQ), fp->name);
+ }
+ return;
+ }
+ }
+ if (map == CcKeyMap) {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsestring(&fb, unparsbuf, STRQQ));
+ xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
+ }
+ else {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsestring(&fb, unparsbuf, STRQQ));
+ xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
+ }
+}
+
+static void
+bindkey_usage()
+{
+ xprintf(CGETS(20, 12,
+ "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
+ xprintf(CGETS(20, 13,
+ " -a list or bind KEY in alternative key map\n"));
+ xprintf(CGETS(20, 14,
+ " -b interpret KEY as a C-, M-, F- or X- key name\n"));
+ xprintf(CGETS(20, 15,
+ " -s interpret COMMAND as a literal string to be output\n"));
+ xprintf(CGETS(20, 16,
+ " -c interpret COMMAND as a builtin or external command\n"));
+ xprintf(CGETS(20, 17,
+ " -v bind all keys to vi bindings\n"));
+ xprintf(CGETS(20, 18,
+ " -e bind all keys to emacs bindings\n"));
+ xprintf(CGETS(20, 19,
+ " -d bind all keys to default editor's bindings\n"));
+ xprintf(CGETS(20, 20,
+ " -l list editor commands with descriptions\n"));
+ xprintf(CGETS(20, 21,
+ " -r remove KEY's binding\n"));
+ xprintf(CGETS(20, 22,
+ " -k interpret KEY as a symbolic arrow-key name\n"));
+ xprintf(CGETS(20, 23,
+ " -- force a break from option processing\n"));
+ xprintf(CGETS(20, 24,
+ " -u (or any invalid option) this message\n"));
+ xprintf("\n");
+ xprintf(CGETS(20, 25,
+ "Without KEY or COMMAND, prints all bindings\n"));
+ xprintf(CGETS(20, 26,
+ "Without COMMAND, prints the binding for KEY.\n"));
+}
+
+static void
+list_functions()
+{
+ register struct KeyFuncs *fp;
+
+ for (fp = FuncNames; fp->name; fp++) {
+ xprintf("%s\n %s\n", fp->name, fp->desc);
+ }
+}
+
+#ifdef OBSOLETE
+
+/*
+ * Unfortunately the apollo optimizer does not like & operations
+ * with 0377, and produces illegal instructions. So we make it
+ * an unsigned char, and hope for the best.
+ * Of-course the compiler is smart enough to produce bad assembly
+ * language instructions, but dumb when it comes to fold the constant :-)
+ */
+#ifdef apollo
+static unsigned char APOLLO_0377 = 0377;
+#else /* sane */
+# define APOLLO_0377 0377
+#endif /* apollo */
+
+static int
+tocontrol(c)
+ int c;
+{
+ c &= CHAR;
+ if (Islower(c))
+ c = Toupper(c);
+ else if (c == ' ')
+ c = '@';
+ if (c == '?')
+ c = CTL_ESC('\177');
+ else
+#ifndef _OSD_POSIX
+ c &= 037;
+#else /* EBCDIC: simulate ASCII-behavior by transforming to ASCII and back */
+ c = _toebcdic[_toascii[c] & 037];
+#endif
+ return (c);
+}
+
+static char *
+unparsekey(c) /* 'c' -> "c", '^C' -> "^" + "C" */
+ register int c;
+{
+ register char *cp;
+ static char tmp[10];
+
+ cp = tmp;
+
+ if (c & 0400) {
+ *cp++ = 'A';
+ *cp++ = '-';
+ c &= APOLLO_0377;
+ }
+ if ((c & META) && !(Isprint(c) || (Iscntrl(c) && Isprint(c | 0100)))) {
+ *cp++ = 'M';
+ *cp++ = '-';
+ c &= ASCII;
+ }
+ if (Isprint(c)) {
+ *cp++ = (char) c;
+ *cp = '\0';
+ return (tmp);
+ }
+ switch (c) {
+ case ' ':
+ (void) strcpy(cp, "Spc");
+ return (tmp);
+ case '\n':
+ (void) strcpy(cp, "Lfd");
+ return (tmp);
+ case '\r':
+ (void) strcpy(cp, "Ret");
+ return (tmp);
+ case '\t':
+ (void) strcpy(cp, "Tab");
+ return (tmp);
+#ifndef _OSD_POSIX
+ case '\033':
+ (void) strcpy(cp, "Esc");
+ return (tmp);
+ case '\177':
+ (void) strcpy(cp, "Del");
+ return (tmp);
+ default:
+ *cp++ = '^';
+ if (c == '\177') {
+ *cp++ = '?';
+ }
+ else {
+ *cp++ = c | 0100;
+ }
+ *cp = '\0';
+ return (tmp);
+#else /*_OSD_POSIX*/
+ default:
+ if (*cp == CTL_ESC('\033')) {
+ (void) strcpy(cp, "Esc");
+ return (tmp);
+ }
+ else if (*cp == CTL_ESC('\177')) {
+ (void) strcpy(cp, "Del");
+ return (tmp);
+ }
+ else if (Isupper(_toebcdic[_toascii[c]|0100])
+ || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL) {
+ *cp++ = '^';
+ *cp++ = _toebcdic[_toascii[c]|0100]
+ }
+ else {
+ xsnprintf(cp, 3, "\\%3.3o", c);
+ cp += 4;
+ }
+#endif /*_OSD_POSIX*/
+ }
+}
+
+static KEYCMD
+getkeycmd(sp)
+ Char **sp;
+{
+ register Char *s = *sp;
+ register char c;
+ register KEYCMD keycmd = F_UNASSIGNED;
+ KEYCMD *map;
+ int meta = 0;
+ Char *ret_sp = s;
+
+ map = CcKeyMap;
+
+ while (*s) {
+ if (*s == '^' && s[1]) {
+ s++;
+ c = tocontrol(*s++);
+ }
+ else
+ c = *s++;
+
+ if (*s == '\0')
+ break;
+
+ switch (map[c | meta]) {
+ case F_METANEXT:
+ meta = META;
+ keycmd = F_METANEXT;
+ ret_sp = s;
+ break;
+
+ case F_XKEY:
+ keycmd = F_XKEY;
+ ret_sp = s;
+ /* FALLTHROUGH */
+
+ default:
+ *sp = ret_sp;
+ return (keycmd);
+
+ }
+ }
+ *sp = ret_sp;
+ return (keycmd);
+}
+
+static int
+parsekey(sp)
+ Char **sp; /* Return position of first unparsed character
+ * for return value -2 (xkeynext) */
+{
+ register int c, meta = 0, control = 0, ctrlx = 0;
+ Char *s = *sp;
+ KEYCMD keycmd;
+
+ if (s == NULL) {
+ xprintf(CGETS(20, 27, "bad key specification -- null string\n"));
+ return -1;
+ }
+ if (*s == 0) {
+ xprintf(CGETS(20, 28, "bad key specification -- empty string\n"));
+ return -1;
+ }
+
+ (void) strip(s); /* trim to 7 bits. */
+
+ if (s[1] == 0) /* single char */
+ return (s[0] & APOLLO_0377);
+
+ if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') {
+ if (s[2] == 0) {
+ xprintf(CGETS(20, 29,
+ "Bad function-key specification. Null key not allowed\n"));
+ return (-1);
+ }
+ *sp = s + 2;
+ return (-2);
+ }
+
+ if (s[0] == '0' && s[1] == 'x') { /* if 0xn, then assume number */
+ c = 0;
+ for (s += 2; *s; s++) { /* convert to hex; skip the first 0 */
+ c *= 16;
+ if (!Isxdigit(*s)) {
+ xprintf(CGETS(20, 30,
+ "bad key specification -- malformed hex number\n"));
+ return -1; /* error */
+ }
+ if (Isdigit(*s))
+ c += *s - '0';
+ else if (*s >= 'a' && *s <= 'f')
+ c += *s - 'a' + 0xA;
+ else if (*s >= 'F' && *s <= 'F')
+ c += *s - 'A' + 0xA;
+ }
+ }
+ else if (s[0] == '0' && Isdigit(s[1])) { /* if 0n, then assume number */
+ c = 0;
+ for (s++; *s; s++) { /* convert to octal; skip the first 0 */
+ if (!Isdigit(*s) || *s == '8' || *s == '9') {
+ xprintf(CGETS(20, 31,
+ "bad key specification -- malformed octal number\n"));
+ return -1; /* error */
+ }
+ c = (c * 8) + *s - '0';
+ }
+ }
+ else if (Isdigit(s[0]) && Isdigit(s[1])) { /* decimal number */
+ c = 0;
+ for (; *s; s++) { /* convert to octal; skip the first 0 */
+ if (!Isdigit(*s)) {
+ xprintf(CGETS(20, 32,
+ "bad key specification -- malformed decimal number\n"));
+ return -1; /* error */
+ }
+ c = (c * 10) + *s - '0';
+ }
+ }
+ else {
+ keycmd = getkeycmd(&s);
+
+ if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') { /* X- */
+ ctrlx++;
+ s += 2;
+ keycmd = getkeycmd(&s);
+ }
+ if ((*s == 'm' || *s == 'M') && s[1] == '-') { /* meta */
+ meta++;
+ s += 2;
+ keycmd = getkeycmd(&s);
+ }
+ else if (keycmd == F_METANEXT && *s) { /* meta */
+ meta++;
+ keycmd = getkeycmd(&s);
+ }
+ if (*s == '^' && s[1]) {
+ control++;
+ s++;
+ keycmd = getkeycmd(&s);
+ }
+ else if ((*s == 'c' || *s == 'C') && s[1] == '-') { /* control */
+ control++;
+ s += 2;
+ keycmd = getkeycmd(&s);
+ }
+
+ if (keycmd == F_XKEY) {
+ if (*s == 0) {
+ xprintf(CGETS(20, 33,
+ "Bad function-key specification.\n"));
+ xprintf(CGETS(20, 34, "Null key not allowed\n"));
+ return (-1);
+ }
+ *sp = s;
+ return (-2);
+ }
+
+ if (s[1] != 0) { /* if symbolic name */
+ char *ts;
+
+ ts = short2str(s);
+ if (!strcmp(ts, "space") || !strcmp(ts, "Spc"))
+ c = ' ';
+ else if (!strcmp(ts, "return") || !strcmp(ts, "Ret"))
+ c = '\r';
+ else if (!strcmp(ts, "newline") || !strcmp(ts, "Lfd"))
+ c = '\n';
+ else if (!strcmp(ts, "linefeed"))
+ c = '\n';
+ else if (!strcmp(ts, "tab"))
+ c = '\t';
+ else if (!strcmp(ts, "escape") || !strcmp(ts, "Esc"))
+ c = CTL_ESC('\033');
+ else if (!strcmp(ts, "backspace"))
+ c = '\b';
+ else if (!strcmp(ts, "delete"))
+ c = CTL_ESC('\177');
+ else {
+ xprintf(CGETS(20, 35,
+ "bad key specification -- unknown name \"%S\"\n"), s);
+ return -1; /* error */
+ }
+ }
+ else
+ c = *s; /* just a single char */
+
+ if (control)
+ c = tocontrol(c);
+ if (meta)
+ c |= META;
+ if (ctrlx)
+ c |= 0400;
+ }
+ return (c & 0777);
+}
+
+
+/*ARGSUSED*/
+void
+dobind(v, dummy)
+ register Char **v;
+ struct command *dummy;
+{
+ register int c;
+ register struct KeyFuncs *fp;
+ register int i, prev;
+ Char *p, *l;
+ CStr cstr;
+ Char buf[1000];
+
+ USE(dummy);
+ /*
+ * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name,
+ * and the key; or 'bind' key to print the func for that key.
+ */
+
+ if (!MapsAreInited)
+ ed_InitMaps();
+
+ if (v[1] && v[2] && v[3]) {
+ xprintf(CGETS(20, 36,
+ "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n"));
+ return;
+ }
+
+ if (v[1] && v[2]) { /* if bind FUNCTION KEY */
+ for (fp = FuncNames; fp->name; fp++) {
+ if (strcmp(short2str(v[1]), fp->name) == 0) {
+ Char *s = v[2];
+
+ if ((c = parsekey(&s)) == -1)
+ return;
+ if (c == -2) { /* extended key */
+ for (i = 0; i < 256; i++) {
+ if (i != CTL_ESC('\033') && (CcKeyMap[i] == F_XKEY ||
+ CcAltMap[i] == F_XKEY)) {
+ p = buf;
+#ifndef _OSD_POSIX /* this is only for ASCII, not for EBCDIC */
+ if (i > 0177) {
+ *p++ = 033;
+ *p++ = i & ASCII;
+ }
+ else {
+ *p++ = (Char) i;
+ }
+#else /*_OSD_POSIX*/
+ *p++ = (Char) i;
+#endif /*_OSD_POSIX*/
+ for (l = s; *l != 0; l++) {
+ *p++ = *l;
+ }
+ *p = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ }
+ }
+ return;
+ }
+ if (c & 0400) {
+ if (VImode) {
+ CcAltMap[c & APOLLO_0377] = fp->func;
+ /* bind the vi cmd mode key */
+ if (c & META) {
+ buf[0] = CTL_ESC('\033');
+ buf[1] = c & ASCII;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ }
+ }
+ else {
+ buf[0] = CTL_ESC('\030'); /* ^X */
+ buf[1] = c & APOLLO_0377;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ CcKeyMap[CTL_ESC('\030')] = F_XKEY;
+ }
+ }
+ else {
+ CcKeyMap[c] = fp->func; /* bind the key */
+ if (c & META) {
+ buf[0] = CTL_ESC('\033');
+ buf[1] = c & ASCII;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ }
+ }
+ return;
+ }
+ }
+ stderror(ERR_NAME | ERR_STRING, CGETS(20, 37, "Invalid function"));
+ }
+ else if (v[1]) {
+ char *cv = short2str(v[1]);
+
+ if (strcmp(cv, "list") == 0) {
+ for (fp = FuncNames; fp->name; fp++) {
+ xprintf("%s\n", fp->name);
+ }
+ return;
+ }
+ if ((strcmp(cv, "emacs") == 0) ||
+#ifndef VIDEFAULT
+ (strcmp(cv, "defaults") == 0) ||
+ (strcmp(cv, "default") == 0) ||
+#endif
+ (strcmp(cv, "mg") == 0) ||
+ (strcmp(cv, "gnumacs") == 0)) {
+ /* reset keys to default */
+ ed_InitEmacsMaps();
+#ifdef VIDEFAULT
+ }
+ else if ((strcmp(cv, "vi") == 0)
+ || (strcmp(cv, "default") == 0)
+ || (strcmp(cv, "defaults") == 0)) {
+#else
+ }
+ else if (strcmp(cv, "vi") == 0) {
+#endif
+ ed_InitVIMaps();
+ }
+ else { /* want to know what this key does */
+ Char *s = v[1];
+
+ if ((c = parsekey(&s)) == -1)
+ return;
+ if (c == -2) { /* extended key */
+ cstr.buf = s;
+ cstr.len = Strlen(s);
+ PrintXkey(&cstr);
+ return;
+ }
+ pkeys(c, c); /* must be regular key */
+ }
+ }
+ else { /* list all the bindings */
+ prev = 0;
+ for (i = 0; i < 256; i++) {
+ if (CcKeyMap[prev] == CcKeyMap[i])
+ continue;
+ pkeys(prev, i - 1);
+ prev = i;
+ }
+ pkeys(prev, i - 1);
+ prev = 0;
+ for (i = 256; i < 512; i++) {
+ if (CcAltMap[prev & APOLLO_0377] == CcAltMap[i & APOLLO_0377])
+ continue;
+ pkeys(prev, i - 1);
+ prev = i;
+ }
+ pkeys(prev, i - 1);
+ cstr.buf = NULL;
+ cstr.len = 0;
+ PrintXkey(&cstr); /* print all Xkey bindings */
+ }
+ return;
+}
+
+static void
+pkeys(first, last)
+ register int first, last;
+{
+ register struct KeyFuncs *fp;
+ register KEYCMD *map;
+ int mask;
+ char buf[8];
+
+ if (last & 0400) {
+ map = CcAltMap;
+ first &= APOLLO_0377;
+ last &= APOLLO_0377;
+ mask = 0400;
+ }
+ else {
+ map = CcKeyMap;
+ mask = 0;
+ }
+ if (map[first] == F_UNASSIGNED) {
+ if (first == last)
+ xprintf(CGETS(20, 38, " %s\t\tis undefined\n"),
+ unparsekey(first | mask));
+ return;
+ }
+
+ for (fp = FuncNames; fp->name; fp++) {
+ if (fp->func == map[first]) {
+ if (first == last)
+ xprintf(" %s\t\t%s\n",
+ unparsekey((first & APOLLO_0377) | mask), fp->name);
+ else {
+ (void) strcpy(buf, unparsekey((first & APOLLO_0377) | mask));
+ xprintf(" %s..%s\t\t%s\n", buf,
+ unparsekey((last & APOLLO_0377) | mask), fp->name);
+ }
+ return;
+ }
+ }
+ if (map == CcKeyMap) {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsekey(first));
+ xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
+ }
+ else {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsekey(first & 0400));
+ xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
+ }
+}
+#endif /* OBSOLETE */
OpenPOWER on IntegriCloud