source: trunk/third/tcsh/tc.bind.c @ 22036

Revision 22036, 22.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22035, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tc.bind.c,v 1.1.1.3 2005-06-03 14:35:55 ghudson Exp $ */
2/*
3 * tc.bind.c: Key binding functions
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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.
20 *
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
31 * SUCH DAMAGE.
32 */
33#include "sh.h"
34
35RCSID("$Id: tc.bind.c,v 1.1.1.3 2005-06-03 14:35:55 ghudson Exp $")
36
37#include "ed.h"
38#include "ed.defns.h"
39
40#ifdef OBSOLETE
41static  int    tocontrol        __P((int));
42static  char  *unparsekey       __P((int));
43static  KEYCMD getkeycmd        __P((Char **));
44static  int    parsekey         __P((Char **));
45static  void   pkeys            __P((int, int));
46#endif /* OBSOLETE */
47
48static  void   printkey         __P((KEYCMD *, CStr *));
49static  KEYCMD parsecmd         __P((Char *));
50static  void   bad_spec         __P((Char *));
51static  CStr  *parsestring      __P((Char *, CStr *));
52static  CStr  *parsebind        __P((Char *, CStr *));
53static  void   print_all_keys   __P((void));
54static  void   printkeys        __P((KEYCMD *, int, int));
55static  void   bindkey_usage    __P((void));
56static  void   list_functions   __P((void));
57
58extern int MapsAreInited;
59
60
61
62
63/*ARGSUSED*/
64void
65dobindkey(v, c)
66    Char  **v;
67    struct command *c;
68{
69    KEYCMD *map;
70    int     ntype, no, removeb, key, bindk;
71    Char   *par;
72    Char    p;
73    KEYCMD  cmd;
74    CStr    in;
75    CStr    out;
76    Char    inbuf[200];
77    Char    outbuf[200];
78    uChar   ch;
79    in.buf = inbuf;
80    out.buf = outbuf;
81    in.len = 0;
82    out.len = 0;
83
84    USE(c);
85    if (!MapsAreInited)
86        ed_InitMaps();
87
88    map = CcKeyMap;
89    ntype = XK_CMD;
90    key = removeb = bindk = 0;
91    for (no = 1, par = v[no];
92         par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
93        if ((p = (*par & CHAR)) == '-') {
94            no++;
95            break;
96        }
97        else
98            switch (p) {
99            case 'b':
100                bindk = 1;
101                break;
102            case 'k':
103                key = 1;
104                break;
105            case 'a':
106                map = CcAltMap;
107                break;
108            case 's':
109                ntype = XK_STR;
110                break;
111            case 'c':
112                ntype = XK_EXE;
113                break;
114            case 'r':
115                removeb = 1;
116                break;
117            case 'v':
118                ed_InitVIMaps();
119                return;
120            case 'e':
121                ed_InitEmacsMaps();
122                return;
123            case 'd':
124#ifdef VIDEFAULT
125                ed_InitVIMaps();
126#else /* EMACSDEFAULT */
127                ed_InitEmacsMaps();
128#endif /* VIDEFAULT */
129                return;
130            case 'l':
131                list_functions();
132                return;
133            default:
134                bindkey_usage();
135                return;
136            }
137    }
138
139    if (!v[no]) {
140        print_all_keys();
141        return;
142    }
143
144    if (key) {
145        if (!IsArrowKey(v[no]))
146            xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]);
147        in.buf = v[no++];
148        in.len = Strlen(in.buf);
149    }
150    else {
151        if (bindk) {
152            if (parsebind(v[no++], &in) == NULL)
153                return;
154        }
155        else {
156            if (parsestring(v[no++], &in) == NULL)
157                return;
158        }
159    }
160
161#ifndef WINNT_NATIVE
162    if (in.buf[0] > 0xFF) {
163        bad_spec(in.buf);
164        return;
165    }
166#endif
167    ch = (uChar) in.buf[0];
168
169    if (removeb) {
170        if (key) {
171            (void) ClearArrowKeys(&in);
172            return;
173        }
174        if (in.len > 1) {
175            (void) DeleteXkey(&in);
176        }
177        else if (map[ch] == F_XKEY) {
178            (void) DeleteXkey(&in);
179            map[ch] = F_UNASSIGNED;
180        }
181        else {
182            map[ch] = F_UNASSIGNED;
183        }
184        return;
185    }
186    if (!v[no]) {
187        if (key)
188            PrintArrowKeys(&in);
189        else
190            printkey(map, &in);
191        return;
192    }
193    if (v[no + 1]) {
194        bindkey_usage();
195        return;
196    }
197    switch (ntype) {
198    case XK_STR:
199    case XK_EXE:
200        if (parsestring(v[no], &out) == NULL)
201            return;
202        if (key) {
203            if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1)
204                xprintf(CGETS(20, 2, "Bad key name: %S\n"), in.buf);
205        }
206        else
207            AddXkey(&in, XmapStr(&out), ntype);
208        map[ch] = F_XKEY;
209        break;
210    case XK_CMD:
211        if ((cmd = parsecmd(v[no])) == 0)
212            return;
213        if (key)
214            (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype);
215        else {
216            if (in.len > 1) {
217                AddXkey(&in, XmapCmd((int) cmd), ntype);
218                map[ch] = F_XKEY;
219            }
220            else {
221                ClearXkey(map, &in);
222                map[ch] = cmd;
223            }
224        }
225        break;
226    default:
227        abort();
228        break;
229    }
230    if (key)
231        BindArrowKeys();
232}
233
234static void
235printkey(map, in)
236    KEYCMD *map;
237    CStr   *in;
238{
239    unsigned char outbuf[100];
240    struct KeyFuncs *fp;
241
242    if (in->len < 2) {
243        (void) unparsestring(in, outbuf, STRQQ);
244        for (fp = FuncNames; fp->name; fp++) {
245            if (fp->func == map[(uChar) *(in->buf)]) {
246                xprintf("%s\t->\t%s\n", outbuf, fp->name);
247            }
248        }
249    }
250    else
251        PrintXkey(in);
252}
253
254static  KEYCMD
255parsecmd(str)
256    Char   *str;
257{
258    struct KeyFuncs *fp;
259
260    for (fp = FuncNames; fp->name; fp++) {
261        if (strcmp(short2str(str), fp->name) == 0) {
262            return (KEYCMD) fp->func;
263        }
264    }
265    xprintf(CGETS(20, 3, "Bad command name: %S\n"), str);
266    return 0;
267}
268
269
270static void
271bad_spec(str)
272    Char *str;
273{
274    xprintf(CGETS(20, 4, "Bad key spec %S\n"), str);
275}
276
277static CStr *
278parsebind(s, str)
279    Char *s;
280    CStr *str;
281{
282    Char *b = str->buf;
283
284    if (Iscntrl(*s)) {
285        *b++ = *s;
286        *b = '\0';
287        str->len = (int) (b - str->buf);
288        return str;
289    }
290
291    switch (*s) {
292    case '^':
293        s++;
294#ifdef IS_ASCII
295        *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
296#else
297        *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
298#endif
299        *b = '\0';
300        break;
301
302    case 'F':
303    case 'M':
304    case 'X':
305    case 'C':
306#ifdef WINNT_NATIVE
307    case 'N':
308#endif /* WINNT_NATIVE */
309        if (s[1] != '-' || s[2] == '\0') {
310            bad_spec(s);
311            return NULL;
312        }
313        s += 2;
314        switch (s[-2]) {
315        case 'F': case 'f':     /* Turn into ^[str */
316            *b++ = CTL_ESC('\033');
317            while ((*b++ = *s++) != '\0')
318                continue;
319            b--;
320            break;
321
322        case 'C': case 'c':     /* Turn into ^c */
323#ifdef IS_ASCII
324            *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
325#else
326            *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
327#endif
328            *b = '\0';
329            break;
330
331        case 'X' : case 'x':    /* Turn into ^Xc */
332#ifdef IS_ASCII
333            *b++ = 'X' & 0237;
334#else
335            *b++ = _toebcdic[_toascii['X'] & 0237];
336#endif
337            *b++ = *s;
338            *b = '\0';
339            break;
340
341        case 'M' : case 'm':    /* Turn into 0x80|c */
342            if (!NoNLSRebind) {
343                *b++ = CTL_ESC('\033');
344                *b++ = *s;
345            } else {
346#ifdef IS_ASCII
347            *b++ = *s | 0x80;
348#else
349            *b++ = _toebcdic[_toascii[*s] | 0x80];
350#endif
351            }
352            *b = '\0';
353            break;
354#ifdef WINNT_NATIVE
355        case 'N' : case 'n':    /* NT */
356                {
357                        Char bnt;
358
359                        bnt = nt_translate_bindkey(s);
360                        if (bnt != 0)
361                                *b++ = bnt;
362                        else
363                                bad_spec(s);
364                }
365            break;
366#endif /* WINNT_NATIVE */
367
368        default:
369            abort();
370            /*NOTREACHED*/
371            return NULL;
372        }
373        break;
374
375    default:
376        bad_spec(s);
377        return NULL;
378    }
379
380    str->len = (int) (b - str->buf);
381    return str;
382}
383
384
385static CStr *
386parsestring(str, buf)
387    Char   *str;
388    CStr   *buf;
389{
390    Char   *b;
391    const Char   *p;
392    eChar  es;
393
394    b = buf->buf;
395    if (*str == 0) {
396        xprintf(CGETS(20, 5, "Null string specification\n"));
397        return NULL;
398    }
399
400    for (p = str; *p != 0; p++) {
401        if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
402            if ((es = parseescape(&p)) == CHAR_ERR)
403                return 0;
404            else
405                *b++ = (Char) es;
406        }
407        else
408            *b++ = *p & CHAR;
409    }
410    *b = 0;
411    buf->len = (int) (b - buf->buf);
412    return buf;
413}
414
415static void
416print_all_keys()
417{
418    int     prev, i;
419    CStr nilstr;
420    nilstr.buf = NULL;
421    nilstr.len = 0;
422
423
424    xprintf(CGETS(20, 6, "Standard key bindings\n"));
425    prev = 0;
426    for (i = 0; i < 256; i++) {
427        if (CcKeyMap[prev] == CcKeyMap[i])
428            continue;
429        printkeys(CcKeyMap, prev, i - 1);
430        prev = i;
431    }
432    printkeys(CcKeyMap, prev, i - 1);
433
434    xprintf(CGETS(20, 7, "Alternative key bindings\n"));
435    prev = 0;
436    for (i = 0; i < 256; i++) {
437        if (CcAltMap[prev] == CcAltMap[i])
438            continue;
439        printkeys(CcAltMap, prev, i - 1);
440        prev = i;
441    }
442    printkeys(CcAltMap, prev, i - 1);
443    xprintf(CGETS(20, 8, "Multi-character bindings\n"));
444    PrintXkey(NULL);    /* print all Xkey bindings */
445    xprintf(CGETS(20, 9, "Arrow key bindings\n"));
446    PrintArrowKeys(&nilstr);
447}
448
449static void
450printkeys(map, first, last)
451    KEYCMD *map;
452    int     first, last;
453{
454    struct KeyFuncs *fp;
455    Char    firstbuf[2], lastbuf[2];
456    CStr fb, lb;
457    unsigned char unparsbuf[10], extrabuf[10];
458    fb.buf = firstbuf;
459    lb.buf = lastbuf;
460
461    firstbuf[0] = (Char) first;
462    firstbuf[1] = 0;
463    lastbuf[0] = (Char) last;
464    lastbuf[1] = 0;
465    fb.len = 1;
466    lb.len = 1;
467
468    if (map[first] == F_UNASSIGNED) {
469        if (first == last)
470            xprintf(CGETS(20, 10, "%-15s->  is undefined\n"),
471                    unparsestring(&fb, unparsbuf, STRQQ));
472        return;
473    }
474
475    for (fp = FuncNames; fp->name; fp++) {
476        if (fp->func == map[first]) {
477            if (first == last) {
478                xprintf("%-15s->  %s\n",
479                        unparsestring(&fb, unparsbuf, STRQQ), fp->name);
480            }
481            else {
482                xprintf("%-4s to %-7s->  %s\n",
483                        unparsestring(&fb, unparsbuf, STRQQ),
484                        unparsestring(&lb, extrabuf, STRQQ), fp->name);
485            }
486            return;
487        }
488    }
489    if (map == CcKeyMap) {
490        xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
491                unparsestring(&fb, unparsbuf, STRQQ));
492        xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
493    }
494    else {
495        xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
496                unparsestring(&fb, unparsbuf, STRQQ));
497        xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
498    }
499}
500
501static void
502bindkey_usage()
503{
504    xprintf(CGETS(20, 12,
505            "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
506    xprintf(CGETS(20, 13,
507            "    -a   list or bind KEY in alternative key map\n"));
508    xprintf(CGETS(20, 14,
509            "    -b   interpret KEY as a C-, M-, F- or X- key name\n"));
510    xprintf(CGETS(20, 15,
511            "    -s   interpret COMMAND as a literal string to be output\n"));
512    xprintf(CGETS(20, 16,
513            "    -c   interpret COMMAND as a builtin or external command\n"));
514    xprintf(CGETS(20, 17,
515            "    -v   bind all keys to vi bindings\n"));
516    xprintf(CGETS(20, 18,
517            "    -e   bind all keys to emacs bindings\n"));
518    xprintf(CGETS(20, 19,
519            "    -d   bind all keys to default editor's bindings\n"));
520    xprintf(CGETS(20, 20,
521            "    -l   list editor commands with descriptions\n"));
522    xprintf(CGETS(20, 21,
523            "    -r   remove KEY's binding\n"));
524    xprintf(CGETS(20, 22,
525            "    -k   interpret KEY as a symbolic arrow-key name\n"));
526    xprintf(CGETS(20, 23,
527            "    --   force a break from option processing\n"));
528    xprintf(CGETS(20, 24,
529            "    -u   (or any invalid option) this message\n"));
530    xprintf("\n");
531    xprintf(CGETS(20, 25,
532            "Without KEY or COMMAND, prints all bindings\n"));
533    xprintf(CGETS(20, 26,
534            "Without COMMAND, prints the binding for KEY.\n"));
535}
536
537static void
538list_functions()
539{
540    struct KeyFuncs *fp;
541
542    for (fp = FuncNames; fp->name; fp++) {
543        xprintf("%s\n          %s\n", fp->name, fp->desc);
544    }
545}
546
547#ifdef OBSOLETE
548
549/*
550 * Unfortunately the apollo optimizer does not like & operations
551 * with 0377, and produces illegal instructions. So we make it
552 * an unsigned char, and hope for the best.
553 * Of-course the compiler is smart enough to produce bad assembly
554 * language instructions, but dumb when it comes to fold the constant :-)
555 */
556#ifdef apollo
557static unsigned char APOLLO_0377 = 0377;
558#else /* sane */
559# define APOLLO_0377    0377
560#endif /* apollo */
561
562static int
563tocontrol(c)
564    int    c;
565{
566    c &= CHAR;
567    if (Islower(c))
568        c = Toupper(c);
569    else if (c == ' ')
570        c = '@';
571    if (c == '?')
572        c = CTL_ESC('\177');
573    else
574#ifdef IS_ASCII
575        c &= 037;
576#else
577        /* EBCDIC: simulate ASCII-behavior by transforming to ASCII and back */
578        c  = _toebcdic[_toascii[c] & 037];
579#endif
580    return (c);
581}
582
583static char *
584unparsekey(c)                   /* 'c' -> "c", '^C' -> "^" + "C" */
585    int c;
586{
587    char *cp;
588    static char tmp[10];
589
590    cp = tmp;
591
592    if (c & 0400) {
593        *cp++ = 'A';
594        *cp++ = '-';
595        c &= APOLLO_0377;
596    }
597    if ((c & META) && !(Isprint(c) || (Iscntrl(c) && Isprint(c | 0100)))) {
598        *cp++ = 'M';
599        *cp++ = '-';
600        c &= ASCII;
601    }
602    if (Isprint(c)) {
603        *cp++ = (char) c;
604        *cp = '\0';
605        return (tmp);
606    }
607    switch (c) {
608    case ' ':
609        (void) strcpy(cp, "Spc");
610        return (tmp);
611    case '\n':
612        (void) strcpy(cp, "Lfd");
613        return (tmp);
614    case '\r':
615        (void) strcpy(cp, "Ret");
616        return (tmp);
617    case '\t':
618        (void) strcpy(cp, "Tab");
619        return (tmp);
620#ifdef IS_ASCII
621    case '\033':
622        (void) strcpy(cp, "Esc");
623        return (tmp);
624    case '\177':
625        (void) strcpy(cp, "Del");
626        return (tmp);
627    default:
628        *cp++ = '^';
629        if (c == '\177') {
630            *cp++ = '?';
631        }
632        else {
633            *cp++ = c | 0100;
634        }
635        *cp = '\0';
636        return (tmp);
637#else /* IS_ASCII */
638    default:
639        if (*cp == CTL_ESC('\033')) {
640            (void) strcpy(cp, "Esc");
641            return (tmp);
642        }
643        else if (*cp == CTL_ESC('\177')) {
644            (void) strcpy(cp, "Del");
645            return (tmp);
646        }
647        else if (Isupper(_toebcdic[_toascii[c]|0100])
648                || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL) {
649            *cp++ = '^';
650            *cp++ = _toebcdic[_toascii[c]|0100]
651        }
652        else {
653            xsnprintf(cp, 3, "\\%3.3o", c);
654            cp += 4;
655        }
656#endif /* IS_ASCII */
657    }
658}
659
660static  KEYCMD
661getkeycmd(sp)
662    Char  **sp;
663{
664    Char *s = *sp;
665    char c;
666    KEYCMD keycmd = F_UNASSIGNED;
667    KEYCMD *map;
668    int     meta = 0;
669    Char   *ret_sp = s;
670
671    map = CcKeyMap;
672
673    while (*s) {
674        if (*s == '^' && s[1]) {
675            s++;
676            c = tocontrol(*s++);
677        }
678        else
679            c = *s++;
680
681        if (*s == '\0')
682            break;
683
684        switch (map[c | meta]) {
685        case F_METANEXT:
686            meta = META;
687            keycmd = F_METANEXT;
688            ret_sp = s;
689            break;
690
691        case F_XKEY:
692            keycmd = F_XKEY;
693            ret_sp = s;
694            /* FALLTHROUGH */
695
696        default:
697            *sp = ret_sp;
698            return (keycmd);
699
700        }
701    }
702    *sp = ret_sp;
703    return (keycmd);
704}
705
706static int
707parsekey(sp)
708    Char  **sp;                 /* Return position of first unparsed character
709                                 * for return value -2 (xkeynext) */
710{
711    int c, meta = 0, control = 0, ctrlx = 0;
712    Char   *s = *sp;
713    KEYCMD  keycmd;
714
715    if (s == NULL) {
716        xprintf(CGETS(20, 27, "bad key specification -- null string\n"));
717        return -1;
718    }
719    if (*s == 0) {
720        xprintf(CGETS(20, 28, "bad key specification -- empty string\n"));
721        return -1;
722    }
723
724    (void) strip(s);            /* trim to 7 bits. */
725
726    if (s[1] == 0)              /* single char */
727        return (s[0] & APOLLO_0377);
728
729    if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') {
730        if (s[2] == 0) {
731            xprintf(CGETS(20, 29,
732                   "Bad function-key specification.  Null key not allowed\n"));
733            return (-1);
734        }
735        *sp = s + 2;
736        return (-2);
737    }
738
739    if (s[0] == '0' && s[1] == 'x') {   /* if 0xn, then assume number */
740        c = 0;
741        for (s += 2; *s; s++) { /* convert to hex; skip the first 0 */
742            c *= 16;
743            if (!Isxdigit(*s)) {
744                xprintf(CGETS(20, 30,
745                        "bad key specification -- malformed hex number\n"));
746                return -1;      /* error */
747            }
748            if (Isdigit(*s))
749                c += *s - '0';
750            else if (*s >= 'a' && *s <= 'f')
751                c += *s - 'a' + 0xA;
752            else if (*s >= 'F' && *s <= 'F')
753                c += *s - 'A' + 0xA;
754        }
755    }
756    else if (s[0] == '0' && Isdigit(s[1])) {    /* if 0n, then assume number */
757        c = 0;
758        for (s++; *s; s++) {    /* convert to octal; skip the first 0 */
759            if (!Isdigit(*s) || *s == '8' || *s == '9') {
760                xprintf(CGETS(20, 31,
761                        "bad key specification -- malformed octal number\n"));
762                return -1;      /* error */
763            }
764            c = (c * 8) + *s - '0';
765        }
766    }
767    else if (Isdigit(s[0]) && Isdigit(s[1])) {  /* decimal number */
768        c = 0;
769        for (; *s; s++) {       /* convert to octal; skip the first 0 */
770            if (!Isdigit(*s)) {
771                xprintf(CGETS(20, 32,
772                       "bad key specification -- malformed decimal number\n"));
773                return -1;      /* error */
774            }
775            c = (c * 10) + *s - '0';
776        }
777    }
778    else {
779        keycmd = getkeycmd(&s);
780
781        if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') {      /* X- */
782            ctrlx++;
783            s += 2;
784            keycmd = getkeycmd(&s);
785        }
786        if ((*s == 'm' || *s == 'M') && s[1] == '-') {  /* meta */
787            meta++;
788            s += 2;
789            keycmd = getkeycmd(&s);
790        }
791        else if (keycmd == F_METANEXT && *s) {  /* meta */
792            meta++;
793            keycmd = getkeycmd(&s);
794        }
795        if (*s == '^' && s[1]) {
796            control++;
797            s++;
798            keycmd = getkeycmd(&s);
799        }
800        else if ((*s == 'c' || *s == 'C') && s[1] == '-') {     /* control */
801            control++;
802            s += 2;
803            keycmd = getkeycmd(&s);
804        }
805
806        if (keycmd == F_XKEY) {
807            if (*s == 0) {
808                xprintf(CGETS(20, 33,
809                              "Bad function-key specification.\n"));
810                xprintf(CGETS(20, 34, "Null key not allowed\n"));
811                return (-1);
812            }
813            *sp = s;
814            return (-2);
815        }
816
817        if (s[1] != 0) {        /* if symbolic name */
818            char   *ts;
819
820            ts = short2str(s);
821            if (!strcmp(ts, "space") || !strcmp(ts, "Spc"))
822                c = ' ';
823            else if (!strcmp(ts, "return") || !strcmp(ts, "Ret"))
824                c = '\r';
825            else if (!strcmp(ts, "newline") || !strcmp(ts, "Lfd"))
826                c = '\n';
827            else if (!strcmp(ts, "linefeed"))
828                c = '\n';
829            else if (!strcmp(ts, "tab"))
830                c = '\t';
831            else if (!strcmp(ts, "escape") || !strcmp(ts, "Esc"))
832                c = CTL_ESC('\033');
833            else if (!strcmp(ts, "backspace"))
834                c = '\b';
835            else if (!strcmp(ts, "delete"))
836                c = CTL_ESC('\177');
837            else {
838                xprintf(CGETS(20, 35,
839                        "bad key specification -- unknown name \"%S\"\n"), s);
840                return -1;      /* error */
841            }
842        }
843        else
844            c = *s;             /* just a single char */
845
846        if (control)
847            c = tocontrol(c);
848        if (meta)
849            c |= META;
850        if (ctrlx)
851            c |= 0400;
852    }
853    return (c & 0777);
854}
855
856
857/*ARGSUSED*/
858void
859dobind(v, dummy)
860    Char **v;
861    struct command *dummy;
862{
863    int c;
864    struct KeyFuncs *fp;
865    int i, prev;
866    Char   *p, *l;
867    CStr    cstr;
868    Char    buf[1000];
869
870    USE(dummy);
871    /*
872     * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name,
873     * and the key; or 'bind' key to print the func for that key.
874     */
875
876    if (!MapsAreInited)
877        ed_InitMaps();
878
879    if (v[1] && v[2] && v[3]) {
880        xprintf(CGETS(20, 36,
881         "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n"));
882        return;
883    }
884
885    if (v[1] && v[2]) {         /* if bind FUNCTION KEY */
886        for (fp = FuncNames; fp->name; fp++) {
887            if (strcmp(short2str(v[1]), fp->name) == 0) {
888                Char   *s = v[2];
889
890                if ((c = parsekey(&s)) == -1)
891                    return;
892                if (c == -2) {  /* extended key */
893                    for (i = 0; i < 256; i++) {
894                        if (i != CTL_ESC('\033') && (CcKeyMap[i] == F_XKEY ||
895                                         CcAltMap[i] == F_XKEY)) {
896                            p = buf;
897#ifdef IS_ASCII
898                            if (i > 0177) {
899                                *p++ = 033;
900                                *p++ = i & ASCII;
901                            }
902                            else {
903                                *p++ = (Char) i;
904                            }
905#else
906                            *p++ = (Char) i;
907#endif
908                            for (l = s; *l != 0; l++) {
909                                *p++ = *l;
910                            }
911                            *p = 0;
912                            cstr.buf = buf;
913                            cstr.len = Strlen(buf);
914                            AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
915                        }
916                    }
917                    return;
918                }
919                if (c & 0400) {
920                    if (VImode) {
921                        CcAltMap[c & APOLLO_0377] = fp->func;   
922                        /* bind the vi cmd mode key */
923                        if (c & META) {
924                            buf[0] = CTL_ESC('\033');
925                            buf[1] = c & ASCII;
926                            buf[2] = 0;
927                            cstr.buf = buf;
928                            cstr.len = Strlen(buf);
929                            AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
930                        }
931                    }
932                    else {
933                        buf[0] = CTL_ESC('\030');       /* ^X */
934                        buf[1] = c & APOLLO_0377;
935                        buf[2] = 0;
936                        cstr.buf = buf;
937                        cstr.len = Strlen(buf);
938                        AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
939                        CcKeyMap[CTL_ESC('\030')] = F_XKEY;
940                    }
941                }
942                else {
943                    CcKeyMap[c] = fp->func;     /* bind the key */
944                    if (c & META) {
945                        buf[0] = CTL_ESC('\033');
946                        buf[1] = c & ASCII;
947                        buf[2] = 0;
948                        cstr.buf = buf;
949                        cstr.len = Strlen(buf);
950                        AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
951                    }
952                }
953                return;
954            }
955        }
956        stderror(ERR_NAME | ERR_STRING, CGETS(20, 37, "Invalid function"));
957    }
958    else if (v[1]) {
959        char   *cv = short2str(v[1]);
960
961        if (strcmp(cv, "list") == 0) {
962            for (fp = FuncNames; fp->name; fp++) {
963                xprintf("%s\n", fp->name);
964            }
965            return;
966        }
967        if ((strcmp(cv, "emacs") == 0) ||
968#ifndef VIDEFAULT
969            (strcmp(cv, "defaults") == 0) ||
970            (strcmp(cv, "default") == 0) ||
971#endif
972            (strcmp(cv, "mg") == 0) ||
973            (strcmp(cv, "gnumacs") == 0)) {
974            /* reset keys to default */
975            ed_InitEmacsMaps();
976#ifdef VIDEFAULT
977        }
978        else if ((strcmp(cv, "vi") == 0)
979                 || (strcmp(cv, "default") == 0)
980                 || (strcmp(cv, "defaults") == 0)) {
981#else
982        }
983        else if (strcmp(cv, "vi") == 0) {
984#endif
985            ed_InitVIMaps();
986        }
987        else {                  /* want to know what this key does */
988            Char   *s = v[1];
989
990            if ((c = parsekey(&s)) == -1)
991                return;
992            if (c == -2) {      /* extended key */
993                cstr.buf = s;
994                cstr.len = Strlen(s);
995                PrintXkey(&cstr);
996                return;
997            }
998            pkeys(c, c);        /* must be regular key */
999        }
1000    }
1001    else {                      /* list all the bindings */
1002        prev = 0;
1003        for (i = 0; i < 256; i++) {
1004            if (CcKeyMap[prev] == CcKeyMap[i])
1005                continue;
1006            pkeys(prev, i - 1);
1007            prev = i;
1008        }
1009        pkeys(prev, i - 1);
1010        prev = 0;
1011        for (i = 256; i < 512; i++) {
1012            if (CcAltMap[prev & APOLLO_0377] == CcAltMap[i & APOLLO_0377])
1013                continue;
1014            pkeys(prev, i - 1);
1015            prev = i;
1016        }
1017        pkeys(prev, i - 1);
1018        cstr.buf = NULL;
1019        cstr.len = 0;
1020        PrintXkey(&cstr);       /* print all Xkey bindings */
1021    }
1022    return;
1023}
1024
1025static void
1026pkeys(first, last)
1027    int first, last;
1028{
1029    struct KeyFuncs *fp;
1030    KEYCMD *map;
1031    int mask;
1032    char    buf[8];
1033
1034    if (last & 0400) {
1035        map = CcAltMap;
1036        first &= APOLLO_0377;
1037        last &= APOLLO_0377;
1038        mask = 0400;
1039    }
1040    else {
1041        map = CcKeyMap;
1042        mask = 0;
1043    }
1044    if (map[first] == F_UNASSIGNED) {
1045        if (first == last)
1046            xprintf(CGETS(20, 38, " %s\t\tis undefined\n"),
1047                    unparsekey(first | mask));
1048        return;
1049    }
1050
1051    for (fp = FuncNames; fp->name; fp++) {
1052        if (fp->func == map[first]) {
1053            if (first == last)
1054                xprintf(" %s\t\t%s\n",
1055                        unparsekey((first & APOLLO_0377) | mask), fp->name);
1056            else {
1057                (void) strcpy(buf, unparsekey((first & APOLLO_0377) | mask));
1058                xprintf(" %s..%s\t\t%s\n", buf,
1059                        unparsekey((last & APOLLO_0377) | mask), fp->name);
1060            }
1061            return;
1062        }
1063    }
1064    if (map == CcKeyMap) {
1065        xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
1066                unparsekey(first));
1067        xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
1068    }
1069    else {
1070        xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
1071                unparsekey(first & 0400));
1072        xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
1073    }
1074}
1075#endif /* OBSOLETE */
Note: See TracBrowser for help on using the repository browser.