1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.bind.c,v 3.0 1991/07/04 21:49:28 christos 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 "config.h" 38: #if !defined(lint) && !defined(pdp11) 39: static char *rcsid() 40: { return "$Id: tc.bind.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; } 41: #endif 42: 43: #include "sh.h" 44: #include "ed.h" 45: #include "ed.defns.h" 46: 47: static int str7cmp __P((char *, char *)); 48: static int tocontrol __P((int)); 49: static char *u_p_key __P((int)); 50: static KEYCMD getkeycmd __P((Char **)); 51: static int parsekey __P((Char **)); 52: static void prntky __P((KEYCMD *, Char *)); 53: static KEYCMD parsecmd __P((Char *)); 54: static Char *parsestring __P((Char *, Char *)); 55: static void print_all_keys __P((void)); 56: static void prntkys __P((KEYCMD *, int, int)); 57: static void bindkey_usage __P((void)); 58: static void list_functions __P((void)); 59: static void pkeys __P((int, int)); 60: 61: extern int MapsAreInited; 62: 63: /* like strcmp, but compairisons are striped to 7 bits 64: (due to shell stupidness) */ 65: static int 66: str7cmp(a, b) 67: register char *a, *b; 68: { 69: while ((*a & TRIM) == (*b++ & TRIM)) 70: if (!*a++) 71: return (0); 72: b--; 73: return ((*a & TRIM) - (*b & TRIM)); 74: } 75: static int 76: tocontrol(c) 77: int c; 78: { 79: c &= CHAR; 80: if (Islower(c)) 81: c = Toupper(c); 82: else if (c == ' ') 83: c = '@'; 84: if (c == '?') 85: c = 0177; 86: else 87: c &= 037; 88: return (c); 89: } 90: 91: static char * 92: u_p_key(c) /* 'c' -> "c", '^C' -> "^" + "C" */ 93: register int c; 94: { 95: register char *cp; 96: static char tmp[10]; 97: 98: cp = tmp; 99: 100: if (c & 0400) { 101: *cp++ = 'A'; 102: *cp++ = '-'; 103: c &= 0377; 104: } 105: if ((c & META) && !(Isprint(c) || Iscntrl(c) && Isprint(c | 0100))) { 106: *cp++ = 'M'; 107: *cp++ = '-'; 108: c &= ASCII; 109: } 110: if (Isprint(c)) { 111: *cp++ = c; 112: *cp = '\0'; 113: return (tmp); 114: } 115: else if (c == ' ') { 116: (void) strcpy(cp, "Spc"); 117: return (tmp); 118: } 119: else if (c == '\n') { 120: (void) strcpy(cp, "Lfd"); 121: return (tmp); 122: } 123: else if (c == '\r') { 124: (void) strcpy(cp, "Ret"); 125: return (tmp); 126: } 127: else if (c == '\t') { 128: (void) strcpy(cp, "Tab"); 129: return (tmp); 130: } 131: else if (c == '\033') { 132: (void) strcpy(cp, "Esc"); 133: return (tmp); 134: } 135: else if (c == '\177') { 136: (void) strcpy(cp, "Del"); 137: return (tmp); 138: } 139: else { 140: *cp++ = '^'; 141: if (c == '\177') { 142: *cp++ = '?'; 143: } 144: else { 145: *cp++ = c | 0100; 146: } 147: *cp = '\0'; 148: return (tmp); 149: } 150: } 151: 152: static KEYCMD 153: getkeycmd(sp) 154: Char **sp; 155: { 156: register Char *s = *sp; 157: register char c; 158: register KEYCMD keycmd = F_UNASSIGNED; 159: KEYCMD *map; 160: int meta = 0; 161: Char *ret_sp = s; 162: 163: map = CcKeyMap; 164: 165: while (*s) { 166: if (*s == '^' && s[1]) { 167: s++; 168: c = tocontrol(*s++); 169: } 170: else 171: c = *s++; 172: 173: if (*s == '\0') 174: break; 175: 176: switch (map[c | meta]) { 177: case F_METANEXT: 178: meta = META; 179: keycmd = F_METANEXT; 180: ret_sp = s; 181: break; 182: 183: case F_XKEY: 184: keycmd = F_XKEY; 185: ret_sp = s; 186: /* FALLTHROUGH */ 187: 188: default: 189: *sp = ret_sp; 190: return (keycmd); 191: 192: } 193: } 194: *sp = ret_sp; 195: return (keycmd); 196: } 197: 198: static int 199: parsekey(sp) 200: Char **sp; /* Return position of first u_p_d character 201: * for return value -2 (xkeynext) */ 202: { 203: register int c, meta = 0, control = 0, ctrlx = 0; 204: Char *s = *sp; 205: KEYCMD keycmd; 206: 207: if (s == NULL) { 208: xprintf("bad key specification -- null string\n"); 209: return -1; 210: } 211: if (*s == 0) { 212: xprintf("bad key specification -- empty string\n"); 213: return -1; 214: } 215: 216: (void) strip(s); /* trim to 7 bits. */ 217: 218: if (s[1] == 0) /* single char */ 219: return (s[0] & 0377); 220: 221: if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') { 222: if (s[2] == 0) { 223: xprintf("Bad function-key specification. Null key not allowed\n"); 224: return (-1); 225: } 226: *sp = s + 2; 227: return (-2); 228: } 229: 230: if (s[0] == '0' && s[1] == 'x') { /* if 0xn, then assume number */ 231: c = 0; 232: for (s += 2; *s; s++) { /* convert to hex; skip the first 0 */ 233: c *= 16; 234: if (!Isxdigit(*s)) { 235: xprintf("bad key specification -- malformed hex number\n"); 236: return -1; /* error */ 237: } 238: if (Isdigit(*s)) 239: c += *s - '0'; 240: else if (*s >= 'a' && *s <= 'f') 241: c += *s - 'a' + 0xA; 242: else if (*s >= 'F' && *s <= 'F') 243: c += *s - 'A' + 0xA; 244: } 245: } 246: else if (s[0] == '0' && Isdigit(s[1])) { /* if 0n, then assume number */ 247: c = 0; 248: for (s++; *s; s++) { /* convert to octal; skip the first 0 */ 249: if (!Isdigit(*s) || *s == '8' || *s == '9') { 250: xprintf("bad key specification -- malformed octal number\n"); 251: return -1; /* error */ 252: } 253: c = (c * 8) + *s - '0'; 254: } 255: } 256: else if (Isdigit(s[0]) && Isdigit(s[1])) { /* decimal number */ 257: c = 0; 258: for (; *s; s++) { /* convert to octal; skip the first 0 */ 259: if (!Isdigit(*s)) { 260: xprintf("bad key specification -- malformed decimal number\n"); 261: return -1; /* error */ 262: } 263: c = (c * 10) + *s - '0'; 264: } 265: } 266: else { 267: keycmd = getkeycmd(&s); 268: 269: if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') { /* X- */ 270: ctrlx++; 271: s += 2; 272: keycmd = getkeycmd(&s); 273: } 274: if ((*s == 'm' || *s == 'M') && s[1] == '-') { /* meta */ 275: meta++; 276: s += 2; 277: keycmd = getkeycmd(&s); 278: } 279: else if (keycmd == F_METANEXT && *s) { /* meta */ 280: meta++; 281: keycmd = getkeycmd(&s); 282: } 283: if (*s == '^' && s[1]) { 284: control++; 285: s++; 286: keycmd = getkeycmd(&s); 287: } 288: else if ((*s == 'c' || *s == 'C') && s[1] == '-') { /* control */ 289: control++; 290: s += 2; 291: keycmd = getkeycmd(&s); 292: } 293: 294: if (keycmd == F_XKEY) { 295: if (*s == 0) { 296: xprintf("Bad function-key specification.\n"); 297: xprintf("Null key not allowed\n"); 298: return (-1); 299: } 300: *sp = s; 301: return (-2); 302: } 303: 304: if (s[1] != 0) { /* if symbolic name */ 305: char *ts; 306: 307: ts = short2str(s); 308: if (!str7cmp(ts, "space") || !str7cmp(ts, "Spc")) 309: c = ' '; 310: else if (!str7cmp(ts, "return") || !str7cmp(ts, "Ret")) 311: c = '\r'; 312: else if (!str7cmp(ts, "newline") || !str7cmp(ts, "Lfd")) 313: c = '\n'; 314: else if (!str7cmp(ts, "linefeed")) 315: c = '\n'; 316: else if (!str7cmp(ts, "tab")) 317: c = '\t'; 318: else if (!str7cmp(ts, "escape") || !str7cmp(ts, "Esc")) 319: c = '\033'; 320: else if (!str7cmp(ts, "backspace")) 321: c = '\b'; 322: else if (!str7cmp(ts, "delete")) 323: c = '\177'; 324: else { 325: xprintf("bad key specification -- unknown name \"%s\"\n", s); 326: return -1; /* error */ 327: } 328: } 329: else 330: c = *s; /* just a single char */ 331: 332: if (control) 333: c = tocontrol(c); 334: if (meta) 335: c |= META; 336: if (ctrlx) 337: c |= 0400; 338: } 339: return (c & 0777); 340: } 341: 342: 343: void 344: dobindkey(v) 345: Char **v; 346: { 347: KEYCMD *map; 348: int string, no, remove; 349: Char *par; 350: Char p; 351: Char inbuf[200]; 352: Char outbuf[200]; 353: Char *in; 354: Char *out; 355: KEYCMD cmd; 356: 357: if (!MapsAreInited) 358: ed_IMaps(); 359: 360: map = CcKeyMap; 361: string = 0; 362: remove = 0; 363: for (no = 1, par = v[no]; 364: par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) { 365: if ((p = (*par & CHAR)) == '-') { 366: break; 367: } 368: else if (p == 'a') { 369: map = CcAltMap; 370: } 371: else if (p == 's') { 372: string = 1; 373: } 374: else if (p == 'r') { 375: remove = 1; 376: } 377: else if (p == 'v') { 378: ed_IVIMaps(); 379: return; 380: } 381: else if (p == 'e') { 382: ed_IEmacsMaps(); 383: return; 384: } 385: else if (p == 'd') { 386: #ifdef VIDEFAULT 387: ed_IVIMaps(); 388: #else 389: ed_IEmacsMaps(); 390: #endif 391: return; 392: } 393: else if (p == 'l') { 394: list_functions(); 395: return; 396: } 397: else { 398: bindkey_usage(); 399: return; 400: } 401: } 402: 403: if (!v[no]) { 404: print_all_keys(); 405: return; 406: } 407: 408: if ((in = parsestring(v[no++], inbuf)) == NULL) 409: return; 410: if (remove) { 411: if (in[1]) { 412: (void) DeleteXkey(in); 413: } 414: else if (map[(unsigned char) *in] == F_XKEY) { 415: (void) DeleteXkey(in); 416: map[(unsigned char) *in] = F_UNASSIGNED; 417: } 418: else { 419: map[(unsigned char) *in] = F_UNASSIGNED; 420: } 421: return; 422: } 423: if (!v[no]) { 424: prntky(map, in); 425: return; 426: } 427: if (v[no + 1]) { 428: bindkey_usage(); 429: return; 430: } 431: if (string) { 432: if ((out = parsestring(v[no], outbuf)) == NULL) 433: return; 434: AddXkey(in, out); 435: map[(unsigned char) *in] = F_XKEY; 436: } 437: else { 438: if ((cmd = parsecmd(v[no])) == 0) 439: return; 440: if (in[1]) { 441: AddXKeyCmd(in, (Char) cmd); 442: map[(unsigned char) *in] = F_XKEY; 443: } 444: else { 445: (void) ClearXkey(map, in); 446: map[(unsigned char) *in] = cmd; 447: } 448: } 449: } 450: 451: static void 452: prntky(map, in) 453: KEYCMD *map; 454: Char *in; 455: { 456: unsigned char outbuf[100]; 457: register struct KeyFuncs *fp; 458: 459: if (in[0] == 0 || in[1] == 0) { 460: (void) u_p_string(in, outbuf); 461: for (fp = FuncNames; fp->name; fp++) { 462: if (fp->func == map[(unsigned char) *in]) { 463: xprintf("%s\t->\t%s\n", outbuf, fp->name); 464: } 465: } 466: } 467: else { 468: (void) PrintXkey(in); 469: } 470: } 471: 472: static KEYCMD 473: parsecmd(str) 474: Char *str; 475: { 476: register struct KeyFuncs *fp; 477: 478: for (fp = FuncNames; fp->name; fp++) { 479: if (str7cmp(short2str(str), fp->name) == 0) { 480: return fp->func; 481: } 482: } 483: xprintf("Bad command name: %s\n", short2str(str)); 484: return 0; 485: } 486: 487: int 488: parseescape(ptr) 489: Char **ptr; 490: { 491: Char *p, c; 492: 493: p = *ptr; 494: 495: if ((p[1] & CHAR) == 0) { 496: xprintf("Something must follow: %c\\n", *p); 497: return 0; 498: } 499: if ((*p & CHAR) == '\\') { 500: p++; 501: switch (*p & CHAR) { 502: case 'a': 503: c = '\007'; /* Bell */ 504: break; 505: case 'b': 506: c = '\010'; /* Backspace */ 507: break; 508: case 't': 509: c = '\011'; /* Horizontal Tab */ 510: break; 511: case 'n': 512: c = '\012'; /* New Line */ 513: break; 514: case 'v': 515: c = '\013'; /* Vertical Tab */ 516: break; 517: case 'f': 518: c = '\014'; /* Form Feed */ 519: break; 520: case 'r': 521: c = '\015'; /* Carriage Return */ 522: break; 523: case 'e': 524: c = '\033'; /* Escape */ 525: break; 526: case '0': 527: case '1': 528: case '2': 529: case '3': 530: case '4': 531: case '5': 532: case '6': 533: case '7': 534: { 535: register int cnt, val, ch; 536: 537: for (cnt = 0, val = 0; cnt < 3; cnt++) { 538: ch = *p++ & CHAR; 539: if (ch < '0' || ch > '7') { 540: p--; 541: break; 542: } 543: val = (val << 3) | (ch - '0'); 544: } 545: if ((val & 0xffffff00) != 0) { 546: xprintf("Octal constant does not fit in a char.\n"); 547: return 0; 548: } 549: c = val; 550: --p; 551: } 552: break; 553: default: 554: c = *p; 555: break; 556: } 557: } 558: else if ((*p & CHAR) == '^') { 559: p++; 560: c = (*p == '?') ? '\177' : ((*p & CHAR) & 0237); 561: } 562: else 563: c = *p; 564: *ptr = p; 565: return (c); 566: } 567: 568: static Char * 569: parsestring(str, buf) 570: Char *str; 571: Char *buf; 572: { 573: Char *b; 574: Char *p; 575: 576: b = buf; 577: if (*str == 0) { 578: xprintf("Null string specification\n"); 579: return 0; 580: } 581: 582: for (p = str; *p != 0; p++) { 583: if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') { 584: if ((*b++ = parseescape(&p)) == 0) 585: return 0; 586: } 587: else { 588: *b++ = *p & CHAR; 589: } 590: } 591: *b = 0; 592: return buf; 593: } 594: 595: unsigned char * 596: u_p_string(str, buf) 597: Char *str; 598: unsigned char *buf; 599: { 600: unsigned char *b; 601: Char *p; 602: 603: b = buf; 604: *b++ = '"'; 605: if (*str == 0) { 606: *b++ = '^'; 607: *b++ = '@'; 608: *b++ = '"'; 609: *b++ = 0; 610: return buf; 611: } 612: 613: for (p = str; *p != 0; p++) { 614: if (Iscntrl(*p)) { 615: *b++ = '^'; 616: if (*p == '\177') 617: *b++ = '?'; 618: else 619: *b++ = *p | 0100; 620: } 621: else if (*p == '^' || *p == '\\') { 622: *b++ = '\\'; 623: *b++ = *p; 624: } 625: else if (*p == ' ' || (Isprint(*p) && !Isspace(*p))) { 626: *b++ = *p; 627: } 628: else { 629: *b++ = '\\'; 630: *b++ = ((*p >> 6) & 7) + '0'; 631: *b++ = ((*p >> 3) & 7) + '0'; 632: *b++ = (*p & 7) + '0'; 633: } 634: } 635: *b++ = '"'; 636: *b++ = 0; 637: return buf; /* should check for overflow */ 638: } 639: 640: static void 641: print_all_keys() 642: { 643: int prev, i; 644: 645: xprintf("Standard key bindings\n"); 646: prev = 0; 647: for (i = 0; i < 256; i++) { 648: if (CcKeyMap[prev] == CcKeyMap[i]) 649: continue; 650: prntkys(CcKeyMap, prev, i - 1); 651: prev = i; 652: } 653: prntkys(CcKeyMap, prev, i - 1); 654: 655: xprintf("Alternative key bindings\n"); 656: prev = 0; 657: for (i = 0; i < 256; i++) { 658: if (CcAltMap[prev] == CcAltMap[i]) 659: continue; 660: prntkys(CcAltMap, prev, i - 1); 661: prev = i; 662: } 663: prntkys(CcAltMap, prev, i - 1); 664: xprintf("Multi-character bindings\n"); 665: (void) PrintXkey(STRNULL); /* print all Xkey bindings */ 666: } 667: 668: static void 669: prntkys(map, first, last) 670: KEYCMD *map; 671: int first, last; 672: { 673: register struct KeyFuncs *fp; 674: Char firstbuf[2], lastbuf[2]; 675: unsigned char unparsbuf[10], extrabuf[10]; 676: 677: firstbuf[0] = first; 678: firstbuf[1] = 0; 679: lastbuf[0] = last; 680: lastbuf[1] = 0; 681: if (map[first] == F_UNASSIGNED) { 682: if (first == last) 683: xprintf("%-15s-> is undefined\n", 684: u_p_string(firstbuf, unparsbuf)); 685: return; 686: } 687: 688: for (fp = FuncNames; fp->name; fp++) { 689: if (fp->func == map[first]) { 690: if (first == last) { 691: xprintf("%-15s-> %s\n", 692: u_p_string(firstbuf, unparsbuf), fp->name); 693: } 694: else { 695: xprintf("%-4s to %-7s-> %s\n", 696: u_p_string(firstbuf, unparsbuf), 697: u_p_string(lastbuf, extrabuf), fp->name); 698: } 699: return; 700: } 701: } 702: if (map == CcKeyMap) { 703: xprintf("BUG!!! %s isn't bound to anything.\n", 704: u_p_string(firstbuf, unparsbuf)); 705: xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]); 706: } 707: else { 708: xprintf("BUG!!! %s isn't bound to anything.\n", 709: u_p_string(firstbuf, unparsbuf)); 710: xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]); 711: } 712: } 713: 714: static void 715: bindkey_usage() 716: { 717: xprintf( 718: "Usage: bindkey [options] [--] [in-string [out-string | command]]\n"); 719: xprintf(" -a bind key in alternative key binding\n"); 720: xprintf(" -s bind an out-string instad of a command\n"); 721: xprintf(" -v initialized maps to default vi bindings\n"); 722: xprintf(" -e initialized maps to default emacs bindings\n"); 723: xprintf(" -d initialized maps to default bindings\n"); 724: #ifdef LONGFUNCS 725: xprintf(" -l list available functions with descriptions\n"); 726: #else 727: xprintf(" -l list available functions\n"); 728: #endif /* LONGFUNCS */ 729: xprintf(" -r remove the binding of in-string\n"); 730: xprintf( 731: "\nIn no out-string or command is given, the binding for in-string\n"); 732: xprintf("is printed or all bindings if in-strings is not given.\n"); 733: } 734: 735: static void 736: list_functions() 737: { 738: register struct KeyFuncs *fp; 739: 740: for (fp = FuncNames; fp->name; fp++) { 741: #ifdef LONGFUNCS 742: xprintf("%s\n %s\n", fp->name, fp->description); 743: #else 744: xprintf("%s\n", fp->name); 745: #endif 746: } 747: } 748: 749: void 750: dobind(v) 751: register Char **v; 752: { 753: register int c; 754: register struct KeyFuncs *fp; 755: register int i, prev; 756: Char *p, *l; 757: Char buf[1000]; 758: 759: /* 760: * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name, 761: * and the key; or 'bind' key to print the func for that key. 762: */ 763: 764: if (!MapsAreInited) 765: ed_IMaps(); 766: 767: if (v[1] && v[2] && v[3]) { 768: xprintf( 769: "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n"); 770: return; 771: } 772: 773: if (v[1] && v[2]) { /* if bind FUNCTION KEY */ 774: for (fp = FuncNames; fp->name; fp++) { 775: if (str7cmp(short2str(v[1]), fp->name) == 0) { 776: Char *s = v[2]; 777: 778: if ((c = parsekey(&s)) == -1) 779: return; 780: if (c == -2) { /* extented key */ 781: for (i = 0; i < 256; i++) { 782: if (i != 033 && (CcKeyMap[i] == F_XKEY || 783: CcAltMap[i] == F_XKEY)) { 784: p = buf; 785: if (i > 0177) { 786: *p++ = 033; 787: *p++ = i & ASCII; 788: } 789: else { 790: *p++ = i; 791: } 792: for (l = s; *l != 0; l++) { 793: *p++ = *l; 794: } 795: *p = 0; 796: AddXKeyCmd(buf, fp->func); 797: } 798: } 799: return; 800: } 801: if (c & 0400) { 802: if (VImode) { 803: CcAltMap[c & 0377] = fp->func; 804: /* bind the vi cmd mode key */ 805: if (c & META) { 806: buf[0] = 033; 807: buf[1] = c & ASCII; 808: buf[2] = 0; 809: AddXKeyCmd(buf, fp->func); 810: } 811: } 812: else { 813: buf[0] = 030; /* ^X */ 814: buf[1] = c & 0377; 815: buf[2] = 0; 816: AddXKeyCmd(buf, fp->func); 817: CcKeyMap[030] = F_XKEY; 818: } 819: } 820: else { 821: CcKeyMap[c] = fp->func; /* bind the key */ 822: if (c & META) { 823: buf[0] = 033; 824: buf[1] = c & ASCII; 825: buf[2] = 0; 826: AddXKeyCmd(buf, fp->func); 827: } 828: } 829: return; 830: } 831: } 832: stderror(ERR_NAME | ERR_STRING, "Invalid function"); 833: } 834: else if (v[1]) { 835: char *cv = short2str(v[1]); 836: 837: if (str7cmp(cv, "list") == 0) { 838: for (fp = FuncNames; fp->name; fp++) { 839: xprintf("%s\n", fp->name); 840: } 841: return; 842: } 843: if ((str7cmp(cv, "emacs") == 0) || 844: #ifndef VIDEFAULT 845: (str7cmp(cv, "defaults") == 0) || 846: (str7cmp(cv, "default") == 0) || 847: #endif 848: (str7cmp(cv, "mg") == 0) || 849: (str7cmp(cv, "gnumacs") == 0)) { 850: /* reset keys to default */ 851: ed_IEmacsMaps(); 852: #ifdef VIDEFAULT 853: } 854: else if ((str7cmp(cv, "vi") == 0) 855: || (str7cmp(cv, "default") == 0) 856: || (str7cmp(cv, "defaults") == 0)) { 857: #else 858: } 859: else if (str7cmp(cv, "vi") == 0) { 860: #endif 861: ed_IVIMaps(); 862: } 863: else { /* want to know what this key does */ 864: Char *s = v[1]; 865: 866: if ((c = parsekey(&s)) == -1) 867: return; 868: if (c == -2) { /* extended key */ 869: (void) PrintXkey(s); 870: return; 871: } 872: pkeys(c, c); /* must be regular key */ 873: } 874: } 875: else { /* list all the bindings */ 876: prev = 0; 877: for (i = 0; i < 256; i++) { 878: if (CcKeyMap[prev] == CcKeyMap[i]) 879: continue; 880: pkeys(prev, i - 1); 881: prev = i; 882: } 883: pkeys(prev, i - 1); 884: prev = 0; 885: for (i = 256; i < 512; i++) { 886: if (CcAltMap[prev & 0377] == CcAltMap[i & 0377]) 887: continue; 888: pkeys(prev, i - 1); 889: prev = i; 890: } 891: pkeys(prev, i - 1); 892: (void) PrintXkey(STRNULL); /* print all Xkey bindings */ 893: } 894: return; 895: } 896: 897: static void 898: pkeys(first, last) 899: register int first, last; 900: { 901: register struct KeyFuncs *fp; 902: register KEYCMD *map; 903: char buf[8]; 904: 905: if (last & 0400) { 906: map = CcAltMap; 907: first &= 0377; 908: last &= 0377; 909: } 910: else { 911: map = CcKeyMap; 912: } 913: if (map[first] == F_UNASSIGNED) { 914: if (first == last) 915: #ifdef _SEQUENT_ 916: xprintf(" %s\t\tis undefined\n", 917: u_p_key(map == CcAltMap ? first | 0400 : first)); 918: #else /* _SEQUENT_ */ 919: xprintf(" %s\t\tis undefined\n", u_p_key(first)); 920: #endif /* _SEQUENT_ */ 921: return; 922: } 923: 924: for (fp = FuncNames; fp->name; fp++) { 925: if (fp->func == map[first]) { 926: if (first == last) { 927: xprintf(" %s\t\t%s\n", 928: u_p_key((first & 0377) | (map == CcAltMap ? 0400 : 0)), 929: fp->name); 930: } 931: else { 932: (void) strcpy(buf, u_p_key((first & 0377) | 933: (map == CcAltMap ? 0400 : 0))); 934: xprintf(" %s..%s\t\t%s\n", buf, 935: u_p_key((last & 0377) | (map == CcAltMap ? 0400 : 0)), 936: fp->name); 937: } 938: return; 939: } 940: } 941: if (map == CcKeyMap) { 942: xprintf("BUG!!! %s isn't bound to anything.\n", u_p_key(first)); 943: xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]); 944: } 945: else { 946: xprintf("BUG!!! %s isn't bound to anything.\n", 947: u_p_key(first & 0400)); 948: xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]); 949: } 950: }