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

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