972 lines
21 KiB
C
972 lines
21 KiB
C
/* $Header: /proj/irix6.5.7m/isms/eoe/cmd/tcsh/RCS/tc.bind.c,v 1.2 1993/07/15 17:54:51 pdc 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. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. 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 1.2 1993/07/15 17:54:51 pdc Exp $")
|
|
|
|
#include "ed.h"
|
|
#include "ed.defns.h"
|
|
|
|
static int tocontrol __P((int));
|
|
static char *unparsekey __P((int));
|
|
static KEYCMD getkeycmd __P((Char **));
|
|
static int parsekey __P((Char **));
|
|
static void printkey __P((KEYCMD *, Char *));
|
|
static KEYCMD parsecmd __P((Char *));
|
|
static Char *parsestring __P((Char *, Char *));
|
|
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));
|
|
static void pkeys __P((int, int));
|
|
|
|
extern int MapsAreInited;
|
|
|
|
/*
|
|
* 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 = 0177;
|
|
else
|
|
c &= 037;
|
|
return (c);
|
|
}
|
|
|
|
static char *
|
|
unparsekey(c) /* 'c' -> "c", '^C' -> "^" + "C" */
|
|
register int c;
|
|
{
|
|
register 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);
|
|
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);
|
|
}
|
|
}
|
|
|
|
static KEYCMD
|
|
getkeycmd(sp)
|
|
Char **sp;
|
|
{
|
|
register Char *s = *sp;
|
|
register char c;
|
|
register 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) */
|
|
{
|
|
register int c, meta = 0, control = 0, ctrlx = 0;
|
|
Char *s = *sp;
|
|
KEYCMD keycmd;
|
|
|
|
if (s == NULL) {
|
|
xprintf("bad key specification -- null string\n");
|
|
return -1;
|
|
}
|
|
if (*s == 0) {
|
|
xprintf("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("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("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("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("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("Bad function-key specification.\n");
|
|
xprintf("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 = '\033';
|
|
else if (!strcmp(ts, "backspace"))
|
|
c = '\b';
|
|
else if (!strcmp(ts, "delete"))
|
|
c = '\177';
|
|
else {
|
|
xprintf("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
|
|
dobindkey(v, c)
|
|
Char **v;
|
|
struct command *c;
|
|
{
|
|
KEYCMD *map;
|
|
int ntype, no, remove, key;
|
|
Char *par;
|
|
Char p;
|
|
Char inbuf[200];
|
|
Char outbuf[200];
|
|
Char *in;
|
|
Char *out;
|
|
KEYCMD cmd;
|
|
|
|
USE(c);
|
|
if (!MapsAreInited)
|
|
ed_InitMaps();
|
|
|
|
map = CcKeyMap;
|
|
ntype = XK_CMD;
|
|
key = remove = 0;
|
|
for (no = 1, par = v[no];
|
|
par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
|
|
if ((p = (*par & CHAR)) == '-')
|
|
break;
|
|
else
|
|
switch (p) {
|
|
case 'k':
|
|
key = 1;
|
|
break;
|
|
case 'a':
|
|
map = CcAltMap;
|
|
break;
|
|
case 's':
|
|
ntype = XK_STR;
|
|
break;
|
|
case 'c':
|
|
ntype = XK_EXE;
|
|
break;
|
|
case 'r':
|
|
remove = 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)
|
|
in = v[no++];
|
|
else
|
|
if ((in = parsestring(v[no++], inbuf)) == NULL)
|
|
return;
|
|
|
|
if (remove) {
|
|
if (key) {
|
|
(void) ClearArrowKeys(in);
|
|
return;
|
|
}
|
|
if (in[1]) {
|
|
(void) DeleteXkey(in);
|
|
}
|
|
else if (map[(unsigned char) *in] == F_XKEY) {
|
|
(void) DeleteXkey(in);
|
|
map[(unsigned char) *in] = F_UNASSIGNED;
|
|
}
|
|
else {
|
|
map[(unsigned char) *in] = 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 ((out = parsestring(v[no], outbuf)) == NULL)
|
|
return;
|
|
if (key)
|
|
(void) SetArrowKeys(in, XmapStr(out), ntype);
|
|
else
|
|
AddXkey(in, XmapStr(out), ntype);
|
|
map[(unsigned char) *in] = 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[1]) {
|
|
AddXkey(in, XmapCmd((int) cmd), ntype);
|
|
map[(unsigned char) *in] = F_XKEY;
|
|
}
|
|
else {
|
|
ClearXkey(map, in);
|
|
map[(unsigned char) *in] = cmd;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
abort();
|
|
break;
|
|
}
|
|
if (key)
|
|
BindArrowKeys();
|
|
}
|
|
|
|
static void
|
|
printkey(map, in)
|
|
KEYCMD *map;
|
|
Char *in;
|
|
{
|
|
unsigned char outbuf[100];
|
|
register struct KeyFuncs *fp;
|
|
|
|
if (in[0] == 0 || in[1] == 0) {
|
|
(void) unparsestring(in, outbuf, STRQQ);
|
|
for (fp = FuncNames; fp->name; fp++) {
|
|
if (fp->func == map[(unsigned char) *in]) {
|
|
xprintf("%s\t->\t%s\n", outbuf, fp->name);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
PrintXkey(in);
|
|
}
|
|
|
|
static KEYCMD
|
|
parsecmd(str)
|
|
Char *str;
|
|
{
|
|
register struct KeyFuncs *fp;
|
|
|
|
for (fp = FuncNames; fp->name; fp++) {
|
|
if (strcmp(short2str(str), fp->name) == 0) {
|
|
return (KEYCMD) fp->func;
|
|
}
|
|
}
|
|
xprintf("Bad command name: %S\n", str);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
parseescape(ptr)
|
|
Char **ptr;
|
|
{
|
|
Char *p, c;
|
|
|
|
p = *ptr;
|
|
|
|
if ((p[1] & CHAR) == 0) {
|
|
xprintf("Something must follow: %c\n", *p);
|
|
return -1;
|
|
}
|
|
if ((*p & CHAR) == '\\') {
|
|
p++;
|
|
switch (*p & CHAR) {
|
|
case 'a':
|
|
c = '\007'; /* Bell */
|
|
break;
|
|
case 'b':
|
|
c = '\010'; /* Backspace */
|
|
break;
|
|
case 't':
|
|
c = '\011'; /* Horizontal Tab */
|
|
break;
|
|
case 'n':
|
|
c = '\012'; /* New Line */
|
|
break;
|
|
case 'v':
|
|
c = '\013'; /* Vertical Tab */
|
|
break;
|
|
case 'f':
|
|
c = '\014'; /* Form Feed */
|
|
break;
|
|
case 'r':
|
|
c = '\015'; /* Carriage Return */
|
|
break;
|
|
case 'e':
|
|
c = '\033'; /* Escape */
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
{
|
|
register int cnt, val, ch;
|
|
|
|
for (cnt = 0, val = 0; cnt < 3; cnt++) {
|
|
ch = *p++ & CHAR;
|
|
if (ch < '0' || ch > '7') {
|
|
p--;
|
|
break;
|
|
}
|
|
val = (val << 3) | (ch - '0');
|
|
}
|
|
if ((val & 0xffffff00) != 0) {
|
|
xprintf("Octal constant does not fit in a char.\n");
|
|
return 0;
|
|
}
|
|
c = (Char) val;
|
|
--p;
|
|
}
|
|
break;
|
|
default:
|
|
c = *p;
|
|
break;
|
|
}
|
|
}
|
|
else if ((*p & CHAR) == '^' && (Isalpha(p[1] & CHAR) ||
|
|
strchr("@^_?\\|[{]}", p[1] & CHAR))) {
|
|
p++;
|
|
c = (*p == '?') ? '\177' : ((*p & CHAR) & 0237);
|
|
}
|
|
else
|
|
c = *p;
|
|
*ptr = p;
|
|
return (c);
|
|
}
|
|
|
|
static Char *
|
|
parsestring(str, buf)
|
|
Char *str;
|
|
Char *buf;
|
|
{
|
|
Char *b;
|
|
Char *p;
|
|
int es;
|
|
|
|
b = buf;
|
|
if (*str == 0) {
|
|
xprintf("Null string specification\n");
|
|
return 0;
|
|
}
|
|
|
|
for (p = str; *p != 0; p++) {
|
|
if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
|
|
if ((es = parseescape(&p)) == -1)
|
|
return 0;
|
|
else
|
|
*b++ = (Char) es;
|
|
}
|
|
else
|
|
*b++ = *p & CHAR;
|
|
}
|
|
*b = 0;
|
|
return buf;
|
|
}
|
|
|
|
unsigned char *
|
|
unparsestring(str, buf, sep)
|
|
Char *str;
|
|
unsigned char *buf;
|
|
Char *sep;
|
|
{
|
|
unsigned char *b;
|
|
Char *p;
|
|
|
|
b = buf;
|
|
*b++ = sep[0];
|
|
if (*str == 0) {
|
|
*b++ = '^';
|
|
*b++ = '@';
|
|
*b++ = sep[1];
|
|
*b++ = 0;
|
|
return buf;
|
|
}
|
|
|
|
for (p = str; *p != 0; p++) {
|
|
if (Iscntrl(*p)) {
|
|
*b++ = '^';
|
|
if (*p == '\177')
|
|
*b++ = '?';
|
|
else
|
|
*b++ = *p | 0100;
|
|
}
|
|
else if (*p == '^' || *p == '\\') {
|
|
*b++ = '\\';
|
|
*b++ = *p;
|
|
}
|
|
else if (*p == ' ' || (Isprint(*p) && !Isspace(*p))) {
|
|
*b++ = *p;
|
|
}
|
|
else {
|
|
*b++ = '\\';
|
|
*b++ = ((*p >> 6) & 7) + '0';
|
|
*b++ = ((*p >> 3) & 7) + '0';
|
|
*b++ = (*p & 7) + '0';
|
|
}
|
|
}
|
|
*b++ = sep[1];
|
|
*b++ = 0;
|
|
return buf; /* should check for overflow */
|
|
}
|
|
|
|
static void
|
|
print_all_keys()
|
|
{
|
|
int prev, i;
|
|
|
|
xprintf("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("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("Multi-character bindings\n");
|
|
PrintXkey(STRNULL); /* print all Xkey bindings */
|
|
xprintf("Arrow key bindings\n");
|
|
PrintArrowKeys(STRNULL);
|
|
}
|
|
|
|
static void
|
|
printkeys(map, first, last)
|
|
KEYCMD *map;
|
|
int first, last;
|
|
{
|
|
register struct KeyFuncs *fp;
|
|
Char firstbuf[2], lastbuf[2];
|
|
unsigned char unparsbuf[10], extrabuf[10];
|
|
|
|
firstbuf[0] = (Char) first;
|
|
firstbuf[1] = 0;
|
|
lastbuf[0] = (Char) last;
|
|
lastbuf[1] = 0;
|
|
if (map[first] == F_UNASSIGNED) {
|
|
if (first == last)
|
|
xprintf("%-15s-> is undefined\n",
|
|
unparsestring(firstbuf, unparsbuf, STRQQ));
|
|
return;
|
|
}
|
|
|
|
for (fp = FuncNames; fp->name; fp++) {
|
|
if (fp->func == map[first]) {
|
|
if (first == last) {
|
|
xprintf("%-15s-> %s\n",
|
|
unparsestring(firstbuf, unparsbuf, STRQQ), fp->name);
|
|
}
|
|
else {
|
|
xprintf("%-4s to %-7s-> %s\n",
|
|
unparsestring(firstbuf, unparsbuf, STRQQ),
|
|
unparsestring(lastbuf, extrabuf, STRQQ), fp->name);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (map == CcKeyMap) {
|
|
xprintf("BUG!!! %s isn't bound to anything.\n",
|
|
unparsestring(firstbuf, unparsbuf, STRQQ));
|
|
xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
|
|
}
|
|
else {
|
|
xprintf("BUG!!! %s isn't bound to anything.\n",
|
|
unparsestring(firstbuf, unparsbuf, STRQQ));
|
|
xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
bindkey_usage()
|
|
{
|
|
xprintf(
|
|
"Usage: bindkey [options] [--] [in-string [out-string | command]]\n");
|
|
xprintf(" -a bind key in alternative key binding\n");
|
|
xprintf(" -s bind an out-string instead of a command\n");
|
|
xprintf(" -c bind a unix-command instead of a command\n");
|
|
xprintf(" -v initialized maps to default vi bindings\n");
|
|
xprintf(" -e initialized maps to default emacs bindings\n");
|
|
xprintf(" -d initialized maps to default bindings\n");
|
|
xprintf(" -l list available functions with descriptions\n");
|
|
xprintf(" -r remove the binding of in-string\n");
|
|
xprintf(" -k bind arrow key with name in in-string\n");
|
|
xprintf(
|
|
"\nIn no out-string or command is given, the binding for in-string\n");
|
|
xprintf("is printed or all bindings if in-strings is not given.\n");
|
|
}
|
|
|
|
static void
|
|
list_functions()
|
|
{
|
|
register struct KeyFuncs *fp;
|
|
|
|
for (fp = FuncNames; fp->name; fp++) {
|
|
xprintf("%s\n %s\n", fp->name, fp->description);
|
|
}
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
void
|
|
dobind(v, dummy)
|
|
register Char **v;
|
|
struct command *dummy;
|
|
{
|
|
register int c;
|
|
register struct KeyFuncs *fp;
|
|
register int i, prev;
|
|
Char *p, *l;
|
|
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(
|
|
"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) { /* extented key */
|
|
for (i = 0; i < 256; i++) {
|
|
if (i != 033 && (CcKeyMap[i] == F_XKEY ||
|
|
CcAltMap[i] == F_XKEY)) {
|
|
p = buf;
|
|
if (i > 0177) {
|
|
*p++ = 033;
|
|
*p++ = i & ASCII;
|
|
}
|
|
else {
|
|
*p++ = (Char) i;
|
|
}
|
|
for (l = s; *l != 0; l++) {
|
|
*p++ = *l;
|
|
}
|
|
*p = 0;
|
|
AddXkey(buf, 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] = 033;
|
|
buf[1] = c & ASCII;
|
|
buf[2] = 0;
|
|
AddXkey(buf, XmapCmd(fp->func), XK_CMD);
|
|
}
|
|
}
|
|
else {
|
|
buf[0] = 030; /* ^X */
|
|
buf[1] = c & APOLLO_0377;
|
|
buf[2] = 0;
|
|
AddXkey(buf, XmapCmd(fp->func), XK_CMD);
|
|
CcKeyMap[030] = F_XKEY;
|
|
}
|
|
}
|
|
else {
|
|
CcKeyMap[c] = fp->func; /* bind the key */
|
|
if (c & META) {
|
|
buf[0] = 033;
|
|
buf[1] = c & ASCII;
|
|
buf[2] = 0;
|
|
AddXkey(buf, XmapCmd(fp->func), XK_CMD);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
stderror(ERR_NAME | ERR_STRING, "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 */
|
|
PrintXkey(s);
|
|
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);
|
|
PrintXkey(STRNULL); /* print all Xkey bindings */
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void
|
|
pkeys(first, last)
|
|
register int first, last;
|
|
{
|
|
register struct KeyFuncs *fp;
|
|
register 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(" %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("BUG!!! %s isn't bound to anything.\n", unparsekey(first));
|
|
xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
|
|
}
|
|
else {
|
|
xprintf("BUG!!! %s isn't bound to anything.\n",
|
|
unparsekey(first & 0400));
|
|
xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
|
|
}
|
|
}
|