#include #include #include #include #include #include "ztypes.h" #include "xio.h" #define NUMCOMMANDS (768) /* 3*256 */ cmdentry *keycmds[NUMCOMMANDS]; char *keycmdargs[NUMCOMMANDS]; static cmdentry mastertable[] = { {xted_insert, -1, 0, "insert-self"}, {xted_enter, op_Enter, 0, "enter"}, {xted_movecursor, op_ForeChar, 0, "forward-char"}, {xted_movecursor, op_BackChar, 0, "backward-char"}, {xted_movecursor, op_ForeWord, 0, "forward-word"}, {xted_movecursor, op_BackWord, 0, "backward-word"}, {xted_movecursor, op_ForeLine, 0, "forward-line"}, {xted_movecursor, op_BackLine, 0, "backward-line"}, {xted_movecursor, op_BeginLine, 0, "beginning-of-line"}, {xted_movecursor, op_EndLine, 0, "end-of-line"}, {xted_scroll, op_DownPage, 0, "scroll-down"}, {xted_scroll, op_UpPage, 0, "scroll-up"}, {xted_scroll, op_DownLine, 0, "scroll-down-line"}, {xted_scroll, op_UpLine, 0, "scroll-up-line"}, {xted_scroll, op_ToBottom, 0, "scroll-to-bottom"}, {xted_scroll, op_ToTop, 0, "scroll-to-top"}, {xted_delete, op_ForeChar, 0, "delete-next-char"}, {xted_delete, op_BackChar, 0, "delete-char"}, {xted_delete, op_ForeWord, 0, "delete-next-word"}, {xted_delete, op_BackWord, 0, "delete-word"}, {xted_cutbuf, op_Yank, 0, "yank"}, {xted_cutbuf, op_Wipe, 0, "kill-region"}, {xted_cutbuf, op_Copy, 0, "copy-region"}, {xted_cutbuf, op_YankReplace, 0, "yank-pop"}, {xted_cutbuf, op_Kill, 0, "kill-line"}, {xted_cutbuf, op_Untype, 0, "kill-input"}, {xted_history, op_BackLine, 0, "backward-history"}, {xted_history, op_ForeLine, 0, "forward-history"}, {xted_macro, -1, 0, "macro"}, {xtexted_meta, op_Cancel, 1, "cancel"}, {xtexted_meta, op_Escape, 1, "escape"}, {xtexted_meta, op_ExplainKey, 0, "explain-key"}, {xtexted_meta, op_DefineMacro, 0, "define-macro"}, {xtexted_redraw, op_Screen, 0, "redraw-screen"}, {xtexted_redraw, op_Status, 0, "redraw-status"}, {xtexted_redraw, op_AllWindows, 0, "redraw-all-windows"}, {xstat_reset_window_size, op_Zoom, 0, "zoom-status"}, {xstat_reset_window_size, op_Shrink, 0, "shrink-status"}, {xstat_reset_window_size, op_Clear, 0, "clear-status"}, {xted_noop, -1, 0, "no-op"}, {NULL, 0, 0, NULL} }; typedef struct binding_t { unsigned int key; /* or keysym */ int which; /* keytype_main, keytype_meta, keytype_sym */ char *name; } binding; static binding defaultbindings[] = { {XK_Left, keytype_sym, "backward-char"}, {XK_KP_Left, keytype_sym, "backward-char"}, {XK_Right, keytype_sym, "forward-char"}, {XK_KP_Right, keytype_sym, "forward-char"}, {XK_Up, keytype_sym, "backward-history"}, {XK_KP_Up, keytype_sym, "backward-history"}, {XK_Down, keytype_sym, "forward-history"}, {XK_KP_Down, keytype_sym, "forward-history"}, {XK_Begin, keytype_sym, "beginning-of-line"}, {XK_KP_Begin, keytype_sym, "beginning-of-line"}, {XK_End, keytype_sym, "end-of-line"}, {XK_KP_End, keytype_sym, "end-of-line"}, {XK_Prior, keytype_sym, "scroll-up"}, {XK_KP_Prior, keytype_sym, "scroll-up"}, {XK_Next, keytype_sym, "scroll-down"}, {XK_KP_Next, keytype_sym, "scroll-down"}, {XK_Delete, keytype_sym, "delete-char"}, {XK_KP_Delete, keytype_sym, "delete-char"}, {XK_Help, keytype_sym, "explain-key"}, {'w', keytype_meta, "copy-region"}, {'y', keytype_meta, "yank-pop"}, {'b', keytype_meta, "backward-word"}, {'f', keytype_meta, "forward-word"}, {'v', keytype_meta, "scroll-up"}, {'d', keytype_meta, "delete-next-word"}, {'`', keytype_meta, "forward-history"}, {'=', keytype_meta, "backward-history"}, {'z', keytype_meta, "zoom-status"}, {'s', keytype_meta, "shrink-status"}, {'c', keytype_meta, "clear-status"}, {'r', keytype_meta, "define-macro"}, {'0', keytype_meta, "macro"}, {'1', keytype_meta, "macro"}, {'2', keytype_meta, "macro"}, {'3', keytype_meta, "macro"}, {'4', keytype_meta, "macro"}, {'5', keytype_meta, "macro"}, {'6', keytype_meta, "macro"}, {'7', keytype_meta, "macro"}, {'8', keytype_meta, "macro"}, {'9', keytype_meta, "macro"}, {'\177', keytype_meta, "delete-word"}, {'\010', keytype_meta, "delete-word"}, {'\007' /* ctrl-G */, keytype_main, "cancel"}, {'\033' /* Escape */, keytype_main, "escape"}, {'\007' /* ctrl-G */, keytype_meta, "cancel"}, {'\037' /* ctrl-_ */, keytype_main, "explain-key"}, #ifdef TESTING {'\021' /* ctrl-Q */, keytype_main, "scroll-up-line"}, {'\032' /* ctrl-Z */, keytype_main, "scroll-down-line"}, #endif {'\001' /* ctrl-A */, keytype_main, "beginning-of-line"}, {'\005' /* ctrl-E */, keytype_main, "end-of-line"}, {'\002' /* ctrl-B */, keytype_main, "backward-char"}, {'\006' /* ctrl-F */, keytype_main, "forward-char"}, {'\014' /* ctrl-L */, keytype_main, "redraw-all-windows"}, {'\031' /* ctrl-Y */, keytype_main, "yank"}, {'\027' /* ctrl-W */, keytype_main, "kill-region"}, {'\013' /* ctrl-K */, keytype_main, "kill-line"}, {'\025' /* ctrl-U */, keytype_main, "kill-input"}, {'\026' /* ctrl-V */, keytype_main, "scroll-down"}, {'\016' /* ctrl-N */, keytype_main, "forward-line"}, {'\020' /* ctrl-P */, keytype_main, "backward-line"}, {'\177' /* del */, keytype_main, "delete-char"}, {'\010' /* del */, keytype_main, "delete-char"}, {'\004' /* ctrl-D */, keytype_main, "delete-next-char"}, {'\n' /* newline */, keytype_main, "enter"}, {'\r' /* return */, keytype_main, "enter"}, {0, 0, NULL} }; #ifdef __STDC__ static void parse_one_binding(char *key, char *proc, char *marg); #else static void parse_one_binding(); #endif /* initialize key tables */ #ifdef __STDC__ void xkey_init() #else void xkey_init() #endif { int ix, keynum; cmdentry *cmd; binding *bx; for (ix=0; ixname; bx++) { ix = (bx->key & 255); cmd = xkey_find_cmd_by_name(bx->name); if (!cmd) { fprintf(stderr, "%s: unknown function <%s> in default bindings\n", PROGRAMNAME, bx->name); } else { keynum = ix | bx->which; if (keycmds[keynum]) { fprintf(stderr, "%s: key <%s> (%d) defined twice in default bindings\n", PROGRAMNAME, xkey_get_key_name(keynum), ix); } keycmds[keynum] = cmd; } } } #ifdef __STDC__ char *xkey_get_key_name(int key) #else char *xkey_get_key_name(key) int key; #endif { static char buf[32]; char *prefix, *name; int which; which = key & keytype_Mask; key = key & (~keytype_Mask); if (which==keytype_sym) { KeySym ksym = (KeySym)((XK_Home & (~255)) | key); /* I bet this is a stupid thing to do */ name = XKeysymToString(ksym); if (!name) name = "Unknown key"; strcpy(buf, name); return buf; } if (which==keytype_meta) prefix = "meta-"; else prefix = ""; if (iscntrl(key)) { sprintf(buf, "%sctrl-%c", prefix, key+'A'-1); } else { sprintf(buf, "%s%c", prefix, key); } return buf; } /* parse stuff of the form key=proc-name;key=proc-name;... Spaces are optional, c-X and m-X are abbreviations, /123 codes are accepted, and I'm getting a headache. */ #ifdef __STDC__ void xkey_parse_bindings(char *str) #else void xkey_parse_bindings(str) char *str; #endif { char *cx, *cx2, *key, *proc, *marg; char buf[64], nbuf[256], margbuf[256]; int escaped; int keylen, proclen; int hasmarg; cx = str; for (; *cx && isspace(*cx); cx++); while (*cx) { key = cx; escaped = FALSE; for (; *cx && *cx != '=' && !isspace(*cx); cx++) { if (*cx == '\\' && *(cx+1) != '\0') { cx++; if (isdigit(*cx)) { cx++; if (isdigit(*cx)) { cx++; } } } } keylen = cx - key; if (keylen >= sizeof(buf)) { keylen = sizeof(buf)-1; } strncpy(buf, key, keylen); buf[keylen] = '\0'; if (*cx == '\0') { fprintf(stderr, "%s: binding for <%s> has no procedure\n", PROGRAMNAME, buf); break; } for (; *cx && isspace(*cx); cx++); if (*cx != '=') { fprintf(stderr, "%s: unexpected '%c' instead of '=' after <%s>\n", PROGRAMNAME, *cx, buf); break; } cx++; /* skip equals */ for (; *cx && isspace(*cx); cx++); proc = cx; for (; *cx && (*cx=='-' || isalnum(*cx)); cx++); proclen = cx - proc; if (proclen >= sizeof(nbuf)) { proclen = sizeof(nbuf)-1; } strncpy(nbuf, proc, proclen); nbuf[proclen] = '\0'; for (; *cx && isspace(*cx); cx++); hasmarg = FALSE; if (*cx == ',') { cx++; /* skip comma */ for (; *cx && isspace(*cx); cx++); if (*cx != '"') { fprintf(stderr, "%s: unexpected '%c' instead of '\"' after ','\n", PROGRAMNAME, *cx); break; } cx++; /* skip open-quote */ marg = cx; for (; *cx && *cx!='\"'; cx++); if (*cx == '\0') { fprintf(stderr, "%s: unexpected end of string after '\"'\n", PROGRAMNAME); break; } proclen = cx - marg; if (proclen >= sizeof(margbuf)) { proclen = sizeof(margbuf)-1; } strncpy(margbuf, marg, proclen); margbuf[proclen] = '\0'; hasmarg = TRUE; cx++; /* skip close-quote */ for (; *cx && isspace(*cx); cx++); } parse_one_binding(buf, nbuf, hasmarg ? margbuf : NULL); if (*cx == '\0') break; if (*cx != ';') { fprintf(stderr, "%s: unexpected '%c' instead of ';' after <%s>\n", PROGRAMNAME, *cx, nbuf); break; } cx++; /* skip semicolon */ for (; *cx && isspace(*cx); cx++); } } #ifdef __STDC__ static void parse_one_binding(char *key, char *proc, char *marg) #else static void parse_one_binding(key, proc, marg) char *key; char *proc; char *marg; #endif { cmdentry *cmd; int ismeta = FALSE; int isctrl = FALSE; int keynum; KeySym ksym; cmd = xkey_find_cmd_by_name(proc); if (!cmd) { fprintf(stderr, "%s: unknown procedure <%s>\n", PROGRAMNAME, proc); return; } while ((*key=='c' || *key=='C' || *key=='m' || *key=='M') && *(key+1)=='-') { if (*key=='c' || *key=='C') isctrl = TRUE; else ismeta = TRUE; key += 2; } if (strlen(key)==1) { keynum = (*key); if (isctrl) { if (islower(keynum)) keynum = toupper(keynum); if (keynum >= 'A'-1) keynum -= ('A'-1); } if (ismeta) keynum |= keytype_meta; } else { ksym = XStringToKeysym(key); if (ksym==NoSymbol) { fprintf(stderr, "%s: unknown key <%s>\n", PROGRAMNAME, key); return; } if ((ksym & (~255)) == (XK_Home & (~255))) { keynum = keytype_sym | (ksym & (255)); } else if ((ksym & (~255)) == (XK_A & (~255))) { keynum = keytype_main | (ksym & (255)); if (ismeta) keynum |= keytype_meta; } else { fprintf(stderr, "%s: unknown key <%s>\n", PROGRAMNAME, key); return; } } keycmds[keynum] = cmd; if (keycmdargs[keynum]) { free(keycmdargs[keynum]); keycmdargs[keynum] = NULL; } if (marg) { keycmdargs[keynum] = (char *)malloc(sizeof(char) * (1+strlen(marg))); strcpy(keycmdargs[keynum], marg); } } #ifdef __STDC__ cmdentry *xkey_find_cmd_by_name(char *str) #else cmdentry *xkey_find_cmd_by_name(str) char *str; #endif { cmdentry *retval; for (retval = mastertable; retval->func; retval++) { if (!strcmp(str, retval->name)) return retval; } return NULL; }