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: }

Defined functions

bindkey_usage defined in line 714; used 2 times
dobind defined in line 749; never used
dobindkey defined in line 343; never used
getkeycmd defined in line 152; used 7 times
list_functions defined in line 735; used 1 times
parsecmd defined in line 472; used 2 times
parseescape defined in line 487; used 2 times
parsekey defined in line 198; used 2 times
parsestring defined in line 568; used 2 times
pkeys defined in line 897; used 5 times
print_all_keys defined in line 640; used 1 times
prntky defined in line 451; used 1 times
prntkys defined in line 668; used 4 times
rcsid defined in line 39; never used
str7cmp defined in line 65; used 24 times
tocontrol defined in line 75; used 2 times
u_p_key defined in line 91; used 7 times
u_p_string defined in line 595; used 7 times
Last modified: 1991-08-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 19
Valid CSS Valid XHTML 1.0 Strict