Logo Search packages:      
Sourcecode: tcsh version File versions  Download package

tc.bind.c

/* $Header: /src/pub/tcsh/tc.bind.c,v 3.39 2005/03/25 18:46:41 kim Exp $ */
/*
 * tc.bind.c: Key binding functions
 */
/*-
 * Copyright (c) 1980, 1991 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include "sh.h"

RCSID("$Id: tc.bind.c,v 3.39 2005/03/25 18:46:41 kim Exp $")

#include "ed.h"
#include "ed.defns.h"

#ifdef OBSOLETE
static      int    tocontrol  __P((int));
static      char  *unparsekey __P((int));
static      KEYCMD getkeycmd  __P((Char **));
static      int    parsekey         __P((Char **));
static      void   pkeys            __P((int, int));
#endif /* OBSOLETE */

static      void   printkey         __P((KEYCMD *, CStr *));
static      KEYCMD parsecmd         __P((Char *));
static  void   bad_spec       __P((Char *));
static      CStr  *parsestring      __P((Char *, CStr *));
static      CStr  *parsebind  __P((Char *, CStr *));
static      void   print_all_keys   __P((void));
static      void   printkeys  __P((KEYCMD *, int, int));
static      void   bindkey_usage    __P((void));
static      void   list_functions   __P((void));

extern int MapsAreInited;




/*ARGSUSED*/
void
dobindkey(v, c)
    Char  **v;
    struct command *c;
{
    KEYCMD *map;
    int     ntype, no, removeb, key, bindk;
    Char   *par;
    Char    p;
    KEYCMD  cmd;
    CStr    in;
    CStr    out;
    Char    inbuf[200];
    Char    outbuf[200];
    uChar   ch;
    in.buf = inbuf;
    out.buf = outbuf;
    in.len = 0;
    out.len = 0;

    USE(c);
    if (!MapsAreInited)
      ed_InitMaps();

    map = CcKeyMap;
    ntype = XK_CMD;
    key = removeb = bindk = 0;
    for (no = 1, par = v[no]; 
       par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
      if ((p = (*par & CHAR)) == '-') {
          no++;
          break;
      }
      else 
          switch (p) {
          case 'b':
            bindk = 1;
            break;
          case 'k':
            key = 1;
            break;
          case 'a':
            map = CcAltMap;
            break;
          case 's':
            ntype = XK_STR;
            break;
          case 'c':
            ntype = XK_EXE;
            break;
          case 'r':
            removeb = 1;
            break;
          case 'v':
            ed_InitVIMaps();
            return;
          case 'e':
            ed_InitEmacsMaps();
            return;
          case 'd':
#ifdef VIDEFAULT
            ed_InitVIMaps();
#else /* EMACSDEFAULT */
            ed_InitEmacsMaps();
#endif /* VIDEFAULT */
            return;
          case 'l':
            list_functions();
            return;
          default:
            bindkey_usage();
            return;
          }
    }

    if (!v[no]) {
      print_all_keys();
      return;
    }

    if (key) {
      if (!IsArrowKey(v[no]))
          xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]);
      in.buf = v[no++];
      in.len = Strlen(in.buf);
    }
    else {
      if (bindk) {
          if (parsebind(v[no++], &in) == NULL)
            return;
      }
      else {
          if (parsestring(v[no++], &in) == NULL)
            return;
      }
    }

#ifndef WINNT_NATIVE
    if (in.buf[0] > 0xFF) {
      bad_spec(in.buf);
      return;
    }
#endif
    ch = (uChar) in.buf[0];

    if (removeb) {
      if (key) {
          (void) ClearArrowKeys(&in);
          return;
      }
      if (in.len > 1) {
          (void) DeleteXkey(&in);
      }
      else if (map[ch] == F_XKEY) {
          (void) DeleteXkey(&in);
          map[ch] = F_UNASSIGNED;
      }
      else {
          map[ch] = F_UNASSIGNED;
      }
      return;
    }
    if (!v[no]) {
      if (key)
          PrintArrowKeys(&in);
      else
          printkey(map, &in);
      return;
    }
    if (v[no + 1]) {
      bindkey_usage();
      return;
    }
    switch (ntype) {
    case XK_STR:
    case XK_EXE:
      if (parsestring(v[no], &out) == NULL)
          return;
      if (key) {
          if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1)
            xprintf(CGETS(20, 2, "Bad key name: %S\n"), in.buf);
      }
      else
          AddXkey(&in, XmapStr(&out), ntype);
      map[ch] = F_XKEY;
      break;
    case XK_CMD:
      if ((cmd = parsecmd(v[no])) == 0)
          return;
      if (key)
          (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype);
      else {
          if (in.len > 1) {
            AddXkey(&in, XmapCmd((int) cmd), ntype);
            map[ch] = F_XKEY;
          }
          else {
            ClearXkey(map, &in);
            map[ch] = cmd;
          }
      }
      break;
    default:
      abort();
      break;
    }
    if (key)
      BindArrowKeys();
}

static void
printkey(map, in)
    KEYCMD *map;
    CStr   *in;
{
    unsigned char outbuf[100];
    struct KeyFuncs *fp;

    if (in->len < 2) {
      (void) unparsestring(in, outbuf, STRQQ);
      for (fp = FuncNames; fp->name; fp++) {
          if (fp->func == map[(uChar) *(in->buf)]) {
            xprintf("%s\t->\t%s\n", outbuf, fp->name);
          }
      }
    }
    else 
      PrintXkey(in);
}

static  KEYCMD
parsecmd(str)
    Char   *str;
{
    struct KeyFuncs *fp;

    for (fp = FuncNames; fp->name; fp++) {
      if (strcmp(short2str(str), fp->name) == 0) {
          return (KEYCMD) fp->func;
      }
    }
    xprintf(CGETS(20, 3, "Bad command name: %S\n"), str);
    return 0;
}


static void
bad_spec(str)
    Char *str;
{
    xprintf(CGETS(20, 4, "Bad key spec %S\n"), str);
}

static CStr *
parsebind(s, str)
    Char *s;
    CStr *str;
{
    Char *b = str->buf;

    if (Iscntrl(*s)) {
      *b++ = *s;
      *b = '\0';
      str->len = (int) (b - str->buf);
      return str;
    }

    switch (*s) {
    case '^':
      s++;
#ifdef IS_ASCII
      *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
#else
      *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
#endif
      *b = '\0';
      break;

    case 'F':
    case 'M':
    case 'X':
    case 'C':
#ifdef WINNT_NATIVE
    case 'N':
#endif /* WINNT_NATIVE */
      if (s[1] != '-' || s[2] == '\0') {
          bad_spec(s);
          return NULL;
      }
      s += 2;
      switch (s[-2]) {
      case 'F': case 'f':     /* Turn into ^[str */
          *b++ = CTL_ESC('\033');
          while ((*b++ = *s++) != '\0')
            continue;
          b--;
          break;

      case 'C': case 'c':     /* Turn into ^c */
#ifdef IS_ASCII
          *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
#else
          *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
#endif
          *b = '\0';
          break;

      case 'X' : case 'x':    /* Turn into ^Xc */
#ifdef IS_ASCII
          *b++ = 'X' & 0237;
#else
          *b++ = _toebcdic[_toascii['X'] & 0237];
#endif
          *b++ = *s;
          *b = '\0';
          break;

      case 'M' : case 'm':    /* Turn into 0x80|c */
          if (!NoNLSRebind) {
            *b++ = CTL_ESC('\033');
            *b++ = *s;
          } else {
#ifdef IS_ASCII
          *b++ = *s | 0x80;
#else
          *b++ = _toebcdic[_toascii[*s] | 0x80];
#endif
          }
          *b = '\0';
          break;
#ifdef WINNT_NATIVE
      case 'N' : case 'n':    /* NT */
            {
                  Char bnt;

                  bnt = nt_translate_bindkey(s);
                  if (bnt != 0)
                        *b++ = bnt;
                  else
                        bad_spec(s);
            }
          break;
#endif /* WINNT_NATIVE */

      default:
          abort();
          /*NOTREACHED*/
          return NULL;
      }
      break;

    default:
      bad_spec(s);
      return NULL;
    }

    str->len = (int) (b - str->buf);
    return str;
}


static CStr *
parsestring(str, buf)
    Char   *str;
    CStr   *buf;
{
    Char   *b;
    const Char   *p;
    eChar  es;

    b = buf->buf;
    if (*str == 0) {
      xprintf(CGETS(20, 5, "Null string specification\n"));
      return NULL;
    }

    for (p = str; *p != 0; p++) {
      if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
          if ((es = parseescape(&p)) == CHAR_ERR)
            return 0;
          else
            *b++ = (Char) es;
      }
      else
          *b++ = *p & CHAR;
    }
    *b = 0;
    buf->len = (int) (b - buf->buf);
    return buf;
}

static void
print_all_keys()
{
    int     prev, i;
    CStr nilstr;
    nilstr.buf = NULL;
    nilstr.len = 0;


    xprintf(CGETS(20, 6, "Standard key bindings\n"));
    prev = 0;
    for (i = 0; i < 256; i++) {
      if (CcKeyMap[prev] == CcKeyMap[i])
          continue;
      printkeys(CcKeyMap, prev, i - 1);
      prev = i;
    }
    printkeys(CcKeyMap, prev, i - 1);

    xprintf(CGETS(20, 7, "Alternative key bindings\n"));
    prev = 0;
    for (i = 0; i < 256; i++) {
      if (CcAltMap[prev] == CcAltMap[i])
          continue;
      printkeys(CcAltMap, prev, i - 1);
      prev = i;
    }
    printkeys(CcAltMap, prev, i - 1);
    xprintf(CGETS(20, 8, "Multi-character bindings\n"));
    PrintXkey(NULL);    /* print all Xkey bindings */
    xprintf(CGETS(20, 9, "Arrow key bindings\n"));
    PrintArrowKeys(&nilstr);
}

static void
printkeys(map, first, last)
    KEYCMD *map;
    int     first, last;
{
    struct KeyFuncs *fp;
    Char    firstbuf[2], lastbuf[2];
    CStr fb, lb;
    unsigned char unparsbuf[10], extrabuf[10];
    fb.buf = firstbuf;
    lb.buf = lastbuf;

    firstbuf[0] = (Char) first;
    firstbuf[1] = 0;
    lastbuf[0] = (Char) last;
    lastbuf[1] = 0;
    fb.len = 1;
    lb.len = 1;

    if (map[first] == F_UNASSIGNED) {
      if (first == last)
          xprintf(CGETS(20, 10, "%-15s->  is undefined\n"),
                unparsestring(&fb, unparsbuf, STRQQ));
      return;
    }

    for (fp = FuncNames; fp->name; fp++) {
      if (fp->func == map[first]) {
          if (first == last) {
            xprintf("%-15s->  %s\n",
                  unparsestring(&fb, unparsbuf, STRQQ), fp->name);
          }
          else {
            xprintf("%-4s to %-7s->  %s\n",
                  unparsestring(&fb, unparsbuf, STRQQ),
                  unparsestring(&lb, extrabuf, STRQQ), fp->name);
          }
          return;
      }
    }
    if (map == CcKeyMap) {
      xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
            unparsestring(&fb, unparsbuf, STRQQ));
      xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
    }
    else {
      xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
            unparsestring(&fb, unparsbuf, STRQQ));
      xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
    }
}

static void
bindkey_usage()
{
    xprintf(CGETS(20, 12,
          "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
    xprintf(CGETS(20, 13,
          "    -a   list or bind KEY in alternative key map\n"));
    xprintf(CGETS(20, 14,
          "    -b   interpret KEY as a C-, M-, F- or X- key name\n"));
    xprintf(CGETS(20, 15,
            "    -s   interpret COMMAND as a literal string to be output\n"));
    xprintf(CGETS(20, 16,
            "    -c   interpret COMMAND as a builtin or external command\n"));
    xprintf(CGETS(20, 17,
          "    -v   bind all keys to vi bindings\n"));
    xprintf(CGETS(20, 18,
          "    -e   bind all keys to emacs bindings\n"));
    xprintf(CGETS(20, 19,
          "    -d   bind all keys to default editor's bindings\n"));
    xprintf(CGETS(20, 20,
          "    -l   list editor commands with descriptions\n"));
    xprintf(CGETS(20, 21,
          "    -r   remove KEY's binding\n"));
    xprintf(CGETS(20, 22,
          "    -k   interpret KEY as a symbolic arrow-key name\n"));
    xprintf(CGETS(20, 23,
          "    --   force a break from option processing\n"));
    xprintf(CGETS(20, 24,
          "    -u   (or any invalid option) this message\n"));
    xprintf("\n");
    xprintf(CGETS(20, 25,
          "Without KEY or COMMAND, prints all bindings\n"));
    xprintf(CGETS(20, 26,
          "Without COMMAND, prints the binding for KEY.\n"));
}

static void
list_functions()
{
    struct KeyFuncs *fp;

    for (fp = FuncNames; fp->name; fp++) {
      xprintf("%s\n          %s\n", fp->name, fp->desc);
    }
}

#ifdef OBSOLETE

/*
 * Unfortunately the apollo optimizer does not like & operations
 * with 0377, and produces illegal instructions. So we make it
 * an unsigned char, and hope for the best.
 * Of-course the compiler is smart enough to produce bad assembly
 * language instructions, but dumb when it comes to fold the constant :-)
 */
#ifdef apollo
static unsigned char APOLLO_0377 = 0377;
#else /* sane */
# define APOLLO_0377    0377
#endif /* apollo */

static int
tocontrol(c)
    int    c;
{
    c &= CHAR;
    if (Islower(c))
      c = Toupper(c);
    else if (c == ' ')
      c = '@';
    if (c == '?')
      c = CTL_ESC('\177');
    else
#ifdef IS_ASCII
      c &= 037;
#else
      /* EBCDIC: simulate ASCII-behavior by transforming to ASCII and back */
      c  = _toebcdic[_toascii[c] & 037];
#endif
    return (c);
}

static char *
unparsekey(c)                 /* 'c' -> "c", '^C' -> "^" + "C" */
    int c;
{
    char *cp;
    static char tmp[10];

    cp = tmp;

    if (c & 0400) {
      *cp++ = 'A';
      *cp++ = '-';
      c &= APOLLO_0377;
    }
    if ((c & META) && !(Isprint(c) || (Iscntrl(c) && Isprint(c | 0100)))) {
      *cp++ = 'M';
      *cp++ = '-';
      c &= ASCII;
    }
    if (Isprint(c)) {
      *cp++ = (char) c;
      *cp = '\0';
      return (tmp);
    }
    switch (c) {
    case ' ':
      (void) strcpy(cp, "Spc");
      return (tmp);
    case '\n':
      (void) strcpy(cp, "Lfd");
      return (tmp);
    case '\r':
      (void) strcpy(cp, "Ret");
      return (tmp);
    case '\t':
      (void) strcpy(cp, "Tab");
      return (tmp);
#ifdef IS_ASCII
    case '\033':
      (void) strcpy(cp, "Esc");
      return (tmp);
    case '\177':
      (void) strcpy(cp, "Del");
      return (tmp);
    default:
      *cp++ = '^';
      if (c == '\177') {
          *cp++ = '?';
      }
      else {
          *cp++ = c | 0100;
      }
      *cp = '\0';
      return (tmp);
#else /* IS_ASCII */
    default:
        if (*cp == CTL_ESC('\033')) {
          (void) strcpy(cp, "Esc");
          return (tmp);
      }
      else if (*cp == CTL_ESC('\177')) {
          (void) strcpy(cp, "Del");
          return (tmp);
      }
      else if (Isupper(_toebcdic[_toascii[c]|0100])
            || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL) {
          *cp++ = '^';
          *cp++ = _toebcdic[_toascii[c]|0100]
      }
      else {
          xsnprintf(cp, 3, "\\%3.3o", c);
          cp += 4;
      }
#endif /* IS_ASCII */
    }
}

static  KEYCMD
getkeycmd(sp)
    Char  **sp;
{
    Char *s = *sp;
    char c;
    KEYCMD keycmd = F_UNASSIGNED;
    KEYCMD *map;
    int     meta = 0;
    Char   *ret_sp = s;

    map = CcKeyMap;

    while (*s) {
      if (*s == '^' && s[1]) {
          s++;
          c = tocontrol(*s++);
      }
      else
          c = *s++;

      if (*s == '\0')
          break;

      switch (map[c | meta]) {
      case F_METANEXT:
          meta = META;
          keycmd = F_METANEXT;
          ret_sp = s;
          break;

      case F_XKEY:
          keycmd = F_XKEY;
          ret_sp = s;
          /* FALLTHROUGH */

      default:
          *sp = ret_sp;
          return (keycmd);

      }
    }
    *sp = ret_sp;
    return (keycmd);
}

static int
parsekey(sp)
    Char  **sp;               /* Return position of first unparsed character
                         * for return value -2 (xkeynext) */
{
    int c, meta = 0, control = 0, ctrlx = 0;
    Char   *s = *sp;
    KEYCMD  keycmd;

    if (s == NULL) {
      xprintf(CGETS(20, 27, "bad key specification -- null string\n"));
      return -1;
    }
    if (*s == 0) {
      xprintf(CGETS(20, 28, "bad key specification -- empty string\n"));
      return -1;
    }

    (void) strip(s);          /* trim to 7 bits. */

    if (s[1] == 0)            /* single char */
      return (s[0] & APOLLO_0377);

    if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') {
      if (s[2] == 0) {
          xprintf(CGETS(20, 29,
               "Bad function-key specification.  Null key not allowed\n"));
          return (-1);
      }
      *sp = s + 2;
      return (-2);
    }

    if (s[0] == '0' && s[1] == 'x') {     /* if 0xn, then assume number */
      c = 0;
      for (s += 2; *s; s++) { /* convert to hex; skip the first 0 */
          c *= 16;
          if (!Isxdigit(*s)) {
            xprintf(CGETS(20, 30,
                  "bad key specification -- malformed hex number\n"));
            return -1;  /* error */
          }
          if (Isdigit(*s))
            c += *s - '0';
          else if (*s >= 'a' && *s <= 'f')
            c += *s - 'a' + 0xA;
          else if (*s >= 'F' && *s <= 'F')
            c += *s - 'A' + 0xA;
      }
    }
    else if (s[0] == '0' && Isdigit(s[1])) {    /* if 0n, then assume number */
      c = 0;
      for (s++; *s; s++) {    /* convert to octal; skip the first 0 */
          if (!Isdigit(*s) || *s == '8' || *s == '9') {
            xprintf(CGETS(20, 31,
                  "bad key specification -- malformed octal number\n"));
            return -1;  /* error */
          }
          c = (c * 8) + *s - '0';
      }
    }
    else if (Isdigit(s[0]) && Isdigit(s[1])) {  /* decimal number */
      c = 0;
      for (; *s; s++) { /* convert to octal; skip the first 0 */
          if (!Isdigit(*s)) {
            xprintf(CGETS(20, 32,
                   "bad key specification -- malformed decimal number\n"));
            return -1;  /* error */
          }
          c = (c * 10) + *s - '0';
      }
    }
    else {
      keycmd = getkeycmd(&s);

      if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') {    /* X- */
          ctrlx++;
          s += 2;
          keycmd = getkeycmd(&s);
      }
      if ((*s == 'm' || *s == 'M') && s[1] == '-') {  /* meta */
          meta++;
          s += 2;
          keycmd = getkeycmd(&s);
      }
      else if (keycmd == F_METANEXT && *s) {    /* meta */
          meta++;
          keycmd = getkeycmd(&s);
      }
      if (*s == '^' && s[1]) {
          control++;
          s++;
          keycmd = getkeycmd(&s);
      }
      else if ((*s == 'c' || *s == 'C') && s[1] == '-') {   /* control */
          control++;
          s += 2;
          keycmd = getkeycmd(&s);
      }

      if (keycmd == F_XKEY) {
          if (*s == 0) {
            xprintf(CGETS(20, 33,
                        "Bad function-key specification.\n"));
            xprintf(CGETS(20, 34, "Null key not allowed\n"));
            return (-1);
          }
          *sp = s;
          return (-2);
      }

      if (s[1] != 0) {  /* if symbolic name */
          char   *ts;

          ts = short2str(s);
          if (!strcmp(ts, "space") || !strcmp(ts, "Spc"))
            c = ' ';
          else if (!strcmp(ts, "return") || !strcmp(ts, "Ret"))
            c = '\r';
          else if (!strcmp(ts, "newline") || !strcmp(ts, "Lfd"))
            c = '\n';
          else if (!strcmp(ts, "linefeed"))
            c = '\n';
          else if (!strcmp(ts, "tab"))
            c = '\t';
          else if (!strcmp(ts, "escape") || !strcmp(ts, "Esc"))
            c = CTL_ESC('\033');
          else if (!strcmp(ts, "backspace"))
            c = '\b';
          else if (!strcmp(ts, "delete"))
            c = CTL_ESC('\177');
          else {
            xprintf(CGETS(20, 35,
                  "bad key specification -- unknown name \"%S\"\n"), s);
            return -1;  /* error */
          }
      }
      else
          c = *s;       /* just a single char */

      if (control)
          c = tocontrol(c);
      if (meta)
          c |= META;
      if (ctrlx)
          c |= 0400;
    }
    return (c & 0777);
}


/*ARGSUSED*/
void
dobind(v, dummy)
    Char **v;
    struct command *dummy;
{
    int c;
    struct KeyFuncs *fp;
    int i, prev;
    Char   *p, *l;
    CStr    cstr;
    Char    buf[1000];

    USE(dummy);
    /*
     * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name,
     * and the key; or 'bind' key to print the func for that key.
     */

    if (!MapsAreInited)
      ed_InitMaps();

    if (v[1] && v[2] && v[3]) {
      xprintf(CGETS(20, 36,
       "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n"));
      return;
    }

    if (v[1] && v[2]) {       /* if bind FUNCTION KEY */
      for (fp = FuncNames; fp->name; fp++) {
          if (strcmp(short2str(v[1]), fp->name) == 0) {
            Char   *s = v[2];

            if ((c = parsekey(&s)) == -1)
                return;
            if (c == -2) {    /* extended key */
                for (i = 0; i < 256; i++) {
                  if (i != CTL_ESC('\033') && (CcKeyMap[i] == F_XKEY ||
                               CcAltMap[i] == F_XKEY)) {
                      p = buf;
#ifdef IS_ASCII
                      if (i > 0177) {
                        *p++ = 033;
                        *p++ = i & ASCII;
                      }
                      else {
                        *p++ = (Char) i;
                      }
#else
                      *p++ = (Char) i;
#endif
                      for (l = s; *l != 0; l++) {
                        *p++ = *l;
                      }
                      *p = 0;
                      cstr.buf = buf;
                      cstr.len = Strlen(buf);
                      AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
                  }
                }
                return;
            }
            if (c & 0400) {
                if (VImode) {
                  CcAltMap[c & APOLLO_0377] = fp->func;     
                  /* bind the vi cmd mode key */
                  if (c & META) {
                      buf[0] = CTL_ESC('\033');
                      buf[1] = c & ASCII;
                      buf[2] = 0;
                      cstr.buf = buf;
                      cstr.len = Strlen(buf);
                      AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
                  }
                }
                else {
                  buf[0] = CTL_ESC('\030');     /* ^X */
                  buf[1] = c & APOLLO_0377;
                  buf[2] = 0;
                  cstr.buf = buf;
                  cstr.len = Strlen(buf);
                  AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
                  CcKeyMap[CTL_ESC('\030')] = F_XKEY;
                }
            }
            else {
                CcKeyMap[c] = fp->func;   /* bind the key */
                if (c & META) {
                  buf[0] = CTL_ESC('\033');
                  buf[1] = c & ASCII;
                  buf[2] = 0;
                  cstr.buf = buf;
                  cstr.len = Strlen(buf);
                  AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
                }
            }
            return;
          }
      }
      stderror(ERR_NAME | ERR_STRING, CGETS(20, 37, "Invalid function"));
    }
    else if (v[1]) {
      char   *cv = short2str(v[1]);

      if (strcmp(cv, "list") == 0) {
          for (fp = FuncNames; fp->name; fp++) {
            xprintf("%s\n", fp->name);
          }
          return;
      }
      if ((strcmp(cv, "emacs") == 0) ||
#ifndef VIDEFAULT
          (strcmp(cv, "defaults") == 0) ||
          (strcmp(cv, "default") == 0) ||
#endif
          (strcmp(cv, "mg") == 0) ||
          (strcmp(cv, "gnumacs") == 0)) {
          /* reset keys to default */
          ed_InitEmacsMaps();
#ifdef VIDEFAULT
      }
      else if ((strcmp(cv, "vi") == 0)
             || (strcmp(cv, "default") == 0)
             || (strcmp(cv, "defaults") == 0)) {
#else
      }
      else if (strcmp(cv, "vi") == 0) {
#endif
          ed_InitVIMaps();
      }
      else {                  /* want to know what this key does */
          Char   *s = v[1];

          if ((c = parsekey(&s)) == -1)
            return;
          if (c == -2) {      /* extended key */
            cstr.buf = s;
            cstr.len = Strlen(s);
            PrintXkey(&cstr);
            return;
          }
          pkeys(c, c);  /* must be regular key */
      }
    }
    else {              /* list all the bindings */
      prev = 0;
      for (i = 0; i < 256; i++) {
          if (CcKeyMap[prev] == CcKeyMap[i])
            continue;
          pkeys(prev, i - 1);
          prev = i;
      }
      pkeys(prev, i - 1);
      prev = 0;
      for (i = 256; i < 512; i++) {
          if (CcAltMap[prev & APOLLO_0377] == CcAltMap[i & APOLLO_0377])
            continue;
          pkeys(prev, i - 1);
          prev = i;
      }
      pkeys(prev, i - 1);
      cstr.buf = NULL;
      cstr.len = 0;
      PrintXkey(&cstr); /* print all Xkey bindings */
    }
    return;
}

static void
pkeys(first, last)
    int first, last;
{
    struct KeyFuncs *fp;
    KEYCMD *map;
    int mask;
    char    buf[8];

    if (last & 0400) {
      map = CcAltMap;
      first &= APOLLO_0377;
      last &= APOLLO_0377;
      mask = 0400;
    }
    else {
      map = CcKeyMap;
      mask = 0;
    }
    if (map[first] == F_UNASSIGNED) {
      if (first == last)
          xprintf(CGETS(20, 38, " %s\t\tis undefined\n"),
                unparsekey(first | mask));
      return;
    }

    for (fp = FuncNames; fp->name; fp++) {
      if (fp->func == map[first]) {
          if (first == last) 
            xprintf(" %s\t\t%s\n", 
                  unparsekey((first & APOLLO_0377) | mask), fp->name);
          else {
            (void) strcpy(buf, unparsekey((first & APOLLO_0377) | mask));
            xprintf(" %s..%s\t\t%s\n", buf,
                    unparsekey((last & APOLLO_0377) | mask), fp->name);
          }
          return;
      }
    }
    if (map == CcKeyMap) {
      xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
            unparsekey(first));
      xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
    }
    else {
      xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
            unparsekey(first & 0400));
      xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
    }
}
#endif /* OBSOLETE */

Generated by  Doxygen 1.6.0   Back to index