Based on my previous dev.15 patch 1, patch 2, patch 3, patch 5. Reference to Ilya's patch is <http://www.flora.org/lynx-dev/html/month1199/msg00231.html>. This patch subsumes / replaces it. Note that (afai read the code) Ilya's patch didn't work with a normal slang compile (Unix, at least). This one should, even for the .lynx-keymap form, although that is untested. Everybody (who is able to edit lynx.cfg or their own copy of it) should now be able to map both functions of ^V away from ^V, for example (or map one of them away to avoid confusion). Documentation (updated lynx.cfg comments, UG updates) not yet done, but will follow later. Klaus * Allow KEYMAP directives in lynx.cfg of extended form KEYMAP:lynxkey:lynxaction:editaction[:sel], where lynxkey and lynxaction are as before, editaction is a line-editor action like FORW, BACK, ERASE etc. and sel selects the line-editor style to be affected (as a number, starting with 1 for the Default Binding; or 0 for all styles (the default); or a negative number -n meaning "all line-editor styles except n"). See Line Editor Help pages for keywords to use as editaction. This includes PASS (which was already implemented), for "passing" on the key when line-editing form fields so that the normal lynxaction will be invoked. (KEYMAP:lynxkey:lynxaction:DIRED is also still possible for defining a Dired mode binding). This is based on a patch from IZ which introduced combined definitions in a .lynx-keymaps file in the form: setkey "\200s" LAC:LEFT_LINK/BACKW # C-left setkey "\200t" LAC:RIGHT_LINK/FORWW # C-right Combined definitions in .lynx-keymaps are also supported in this patch, but the syntax was changed to use another ':' instead of '/' as separator. Note that there is no need to support .lynx-keymaps (i.e. compile with USE_KEYMAPS defined) for using the extended KEYMAP lynx.cfg directive with this patch. * Corrections to make LYEditmap.c compile for non-ASCII systems. [ Reference for the latter is <http://www.flora.org/lynx-dev/html/month1199/msg00409.html>, by gil <[EMAIL PROTECTED]> ] Index: 2.24/src/LYForms.c --- 2.24/src/LYForms.c Thu, 25 Nov 1999 06:54:09 -0600 +++ 2.24(w)/src/LYForms.c Sun, 28 Nov 1999 18:12:44 -0600 @@ -468,7 +468,7 @@ } #endif /* VMS */ # ifdef NCURSES_MOUSE_VERSION - if (ch != -1 && (ch & LKC_ISLAC)) /* already lynxactioncode? */ + if (ch != -1 && (ch & LKC_ISLAC) && !(ch & LKC_ISLECLAC)) /* already +lynxactioncode? */ break; /* @@@ maybe move these 2 lines outside ifdef -kw */ if (ch == MOUSE_KEY) { /* Need to process ourselves */ #if defined(WIN_EX) @@ -513,7 +513,8 @@ } else # endif /* defined NCURSES_MOUSE_VERSION */ { - ch |= MyEdit.current_modifiers; + if (!(ch & LKC_ISLECLAC)) + ch |= MyEdit.current_modifiers; MyEdit.current_modifiers = 0; if (last_xlkc != -1) { if (ch == last_xlkc) Index: 2.24/src/LYStrings.c --- 2.24/src/LYStrings.c Thu, 25 Nov 1999 11:29:56 -0600 +++ 2.24(w)/src/LYStrings.c Sun, 28 Nov 1999 17:34:28 -0600 @@ -949,6 +949,22 @@ *keysym = -1; if (strncasecomp(str, "LAC:", 4) == 0) { + char *other = strchr(str+4, ':'); + + if (other) { + int othersym = lecname_to_lec(other + 1); + char buf[BUFSIZ]; + + if (othersym >= 0 && other - str - 4 < BUFSIZ ) { + strncpy(buf, str + 4, other - str - 4); + buf[other - str - 4] = '\0'; + *keysym = lacname_to_lac(buf); + if (*keysym >= 0) { + *keysym = LACLEC_TO_LKC0(*keysym, othersym); + return (*keysym); + } + } + } *keysym = lacname_to_lac(str + 4); if (*keysym >= 0) { *keysym = LAC_TO_LKC0(*keysym); @@ -1415,7 +1431,7 @@ if (keysym < 0) return 0; - if (keysym&LKC_ISLAC) + if (keysym & (LKC_ISLECLAC|LKC_ISLAC)) return (keysym); current_sl_modifier = 0; @@ -1725,7 +1741,11 @@ } } #ifdef USE_KEYMAPS - if (c >= 0 && (c&LKC_ISLKC)) { + /* Extract a single code if two are merged: */ + if (c >= 0 && (c&LKC_ISLECLAC)) { + if (!(code == FOR_INPUT || code == FOR_PROMPT)) + c = LKC2_TO_LKC(c); + } else if (c >= 0 && (c&LKC_ISLKC)) { c &= ~LKC_ISLKC; done_esc = TRUE; /* already a lynxkeycode, skip keypad switches - kw */ } @@ -1733,7 +1753,7 @@ current_modifier = LKC_MOD2; c &= LKC_MASK; } - if (c >= 0 && (c&LKC_ISLAC)) { + if (c >= 0 && (c&(LKC_ISLECLAC|LKC_ISLAC))) { done_esc = TRUE; /* already a lynxactioncode, skip keypad switches - iz */ } #endif @@ -2238,7 +2258,7 @@ } #endif /* USE_SLANG && __DJGPP__ && !DJGPP_KEYHANDLER && !USE_KEYMAPS */ - if (c&LKC_ISLAC) + if (c&(LKC_ISLAC|LKC_ISLECLAC)) return(c); if ((c+1) >= KEYMAP_SIZE) { /* Index: 2.24/src/LYKeymap.c --- 2.24/src/LYKeymap.c Thu, 25 Nov 1999 13:27:27 -0600 +++ 2.24(w)/src/LYKeymap.c Sun, 28 Nov 1999 17:27:05 -0600 @@ -778,6 +778,65 @@ "mouse pseudo key", /* normally not mapped to keymap[] action */ }; + +struct emap { + CONST char *name; + CONST int code; + CONST char *descr; +}; + +PRIVATE struct emap ekmap[] = { + {"NOP", LYE_NOP, "Do Nothing"}, + {"CHAR", LYE_CHAR, "Insert printable char"}, + {"ENTER", LYE_ENTER, "Input complete, return char/lynxkeycode"}, + {"TAB", LYE_TAB, "Input complete, return TAB"}, + {"ABORT", LYE_ABORT, "Input cancelled"}, + + {"PASS", LYE_FORM_PASS, "In fields: input complete, or Do Nothing"}, + + {"DELN", LYE_DELN, "Delete next/curr char"}, + {"DELP", LYE_DELP, "Delete prev char"}, + {"DELNW", LYE_DELNW, "Delete next word"}, + {"DELPW", LYE_DELPW, "Delete prev word"}, + + {"ERASE", LYE_ERASE, "Erase the line"}, + + {"BOL", LYE_BOL, "Go to begin of line"}, + {"EOL", LYE_EOL, "Go to end of line"}, + {"FORW", LYE_FORW, "Cursor forwards"}, + {"BACK", LYE_BACK, "Cursor backwards"}, + {"FORWW", LYE_FORWW, "Word forward"}, + {"BACKW", LYE_BACKW, "Word back"}, + + {"LOWER", LYE_LOWER, "Lower case the line"}, + {"UPPER", LYE_UPPER, "Upper case the line"}, + + {"LKCMD", LYE_LKCMD, "Invoke command prompt"}, + + {"AIX", LYE_AIX, "Hex 97"}, + + {"DELBL", LYE_DELBL, "Delete back to BOL"}, + {"DELEL", LYE_DELEL, "Delete thru EOL"}, + + {"SWMAP", LYE_SWMAP, "Switch input keymap"}, + + {"TPOS", LYE_TPOS, "Transpose characters"}, + + {"SETM1", LYE_SETM1, "Set modifier 1 flag"}, + {"SETM2", LYE_SETM2, "Set modifier 2 flag"}, + {"UNMOD", LYE_UNMOD, "Fall back to no-modifier command"}, + + {"C1CHAR", LYE_C1CHAR, "Insert C1 char if printable"}, + + {"SETMARK", LYE_SETMARK, "emacs-like set-mark-command"}, + {"XPMARK", LYE_XPMARK, "emacs-like exchange-point-and-mark"}, + {"KILLREG", LYE_KILLREG, "emacs-like kill-region"}, + {"YANK", LYE_YANK, "emacs-like yank"} +#if defined(WIN_EX) +, {"PASTE", LYE_PASTE, "ClipBoard to Lynx"} +#endif +}; + PRIVATE char *pretty ARGS1 (int, c) { static char buf[30]; @@ -935,6 +994,27 @@ } /* + * Return editactioncode whose name is the string func. + * func must be present in the ekmap table. + * returns -1 if not found. - kw + */ +PUBLIC int lecname_to_lec ARGS1( + CONST char *, func) +{ + int i; + struct emap *mp; + + if (func == NULL || *func == '\0') + return (-1); + for (i = 0, mp = ekmap; (*mp).name != NULL; mp++, i++) { + if (strcmp((*mp).name, func) == 0) { + return (*mp).code; + } + } + return (-1); +} + +/* * Return lynxkeycode represented by string src. * returns -1 if not valid. * This is simpler than what map_string_to_keysym() does for @@ -1077,7 +1157,7 @@ * called for an invalid lynxkeycode, fail or silently ignore * modifiers. - kw */ - if (c & LKC_ISLAC) + if (c & (LKC_ISLECLAC|LKC_ISLAC)) return 0; if ((c & LKC_MASK) != c) c &= LKC_MASK; Index: 2.24/src/LYEditmap.c --- 2.24/src/LYEditmap.c Thu, 25 Nov 1999 13:27:27 -0600 +++ 2.24(w)/src/LYEditmap.c Sun, 28 Nov 1999 18:33:18 -0600 @@ -983,7 +983,9 @@ * If we have more than one modifier bits, the first currently * wins. - kw */ - if (xlkc & LKC_MOD1) { + if (xlkc & LKC_ISLECLAC) { + return LKC2_TO_LEC(xlkc); + } else if (xlkc & LKC_MOD1) { xleac = LKC_TO_LEC_M1(c); } else if (xlkc & LKC_MOD2) { xleac = LKC_TO_LEC_M2(c); @@ -1008,17 +1010,25 @@ /* * Install lec as the lynxeditaction for lynxkeycode xlkc. * func must be present in the revmap table. + * For normal (non-modifier) lynxkeycodes, select_edi selects which + * of the alternative line-editor binding tables is modified. If + * select_edi is positive, only the table given by it is modified + * (the DefaultEditBinding table is numbered 1). If select_edi is 0, + * all tables are modified. If select_edi is negative, all tables + * except the one given by abs(select_edi) are modified. * returns TRUE if the mapping was made, FALSE if not. * Note that this remapping cannot be undone (as might be desirable * as a result of re-parsing lynx.cfg), we don't remember the * original editaction from the Bindings tables anywhere. - kw */ -PUBLIC int LYRemapEditBinding ARGS2( +PUBLIC BOOL LYRemapEditBinding ARGS3( int, xlkc, - int, lec) + int, lec, + int, select_edi) { int j; int c = xlkc & LKC_MASK; + BOOLEAN success = FALSE; if (xlkc < 0 || (xlkc&LKC_ISLAC) || c >= KEYMAP_SIZE + 1) return FALSE; #ifdef EXP_ALT_BINDINGS @@ -1027,16 +1037,19 @@ return FALSE; else Mod1Binding[c] = (short) lec; + return TRUE; } else if (xlkc & LKC_MOD2) { if (c > LAST_MOD2_LKC) return FALSE; else Mod2Binding[c] = (short) lec; + return TRUE; } else if (xlkc & LKC_MOD3) { if (c > LAST_MOD3_LKC) return FALSE; else Mod3Binding[c] = (short) lec; + return TRUE; } else #endif /* EXP_ALT_BINDINGS */ { @@ -1045,11 +1058,21 @@ #endif if ((unsigned int)lec > UCHAR_MAX) return FALSE; /* cannot do, doesn't fit in a char - kw */ - for (j = 0; LYLineeditNames[j]; j++) { - LYLineEditors[j][c] = (char) lec; + if (select_edi > 0) { + if ((unsigned int)select_edi < TABLESIZE(LYLineEditors)) { + LYLineEditors[select_edi - 1][c] = (char) lec; + success = TRUE; + } + } else { + for (j = 0; LYLineeditNames[j]; j++) { + success = TRUE; + if (select_edi < 0 && j + 1 + select_edi == 0) + continue; + LYLineEditors[j][c] = (char) lec; + } } } - return TRUE; + return success; } /* @@ -1180,7 +1203,7 @@ if (pmodkey) { #ifdef NOT_ASCII if (mod1found < 256) { - pmodkey = FROMASCII(mod1found); + *pmodkey = FROMASCII(mod1found); } else #endif *pmodkey = mod1found; @@ -1219,7 +1242,7 @@ if (pmodkey) { #ifdef NOT_ASCII if (mod1found < 256) { - pmodkey = FROMASCII(mod1found); + *pmodkey = FROMASCII(mod1found); } else #endif *pmodkey = mod1found; Index: 2.24/src/LYKeymap.h --- 2.24/src/LYKeymap.h Thu, 25 Nov 1999 11:29:56 -0600 +++ 2.24(w)/src/LYKeymap.h Sun, 28 Nov 1999 18:44:58 -0600 @@ -12,6 +12,7 @@ extern int LYReverseKeymap PARAMS((int KeyName)); extern int lookup_keymap PARAMS((int code)); extern int lacname_to_lac PARAMS((CONST char *func)); +extern int lecname_to_lec PARAMS((CONST char *func)); extern int lkcstring_to_lkc PARAMS((CONST char *src)); extern int remap PARAMS((char *key, char *func, BOOLEAN for_dired)); extern void print_keymap PARAMS((char **newfile)); @@ -45,10 +46,13 @@ #endif /* * * LynxKeyCodes * * */ +#define LKC_ISLECLAC 0x8000 /* flag: contains lynxaction + editaction */ #define LKC_MOD1 0x4000 /* a modifier bit - currently for ^x-map */ #define LKC_MOD2 0x2000 /* another one - currently for esc-map */ #define LKC_MOD3 0x1000 /* another one - currently for double-map */ #define LKC_ISLAC 0x0800 /* flag: lynxkeycode already lynxactioncode */ + +/* Used to distinguish internal Lynx keycodes of (say) extended ncurses once. */ #define LKC_ISLKC 0x0400 /* flag: already lynxkeycode (not native) */ /* 0x0400 is MOUSE_KEYSYM for slang in LYStrings.c */ #define LKC_MASK 0x07FF /* mask for lynxkeycode proper */ @@ -56,27 +60,48 @@ #define LKC_DONE 0x07FE /* special value - operation done, not-a-key */ /* * * LynxActionCodes * * */ -#define LAC_MASK 0x00FF /* mask for lynxactioncode - must cover all +#define LAC_SHIFT 8 /* shift for lynxactioncode - must not + overwrite any assigned LYK_* values */ +#define LAC_MASK ((1<<LAC_SHIFT)-1) + /* mask for lynxactioncode - must cover all assigned LYK_* values */ +#if 0 +/* Substitute a single actioncode given a double one - NOT USED */ +#define LKC2_TO_LKC(c,n) (((c) == -1 || !((c) & LKC_ISLECLAC)) ? (c) : \ + ((n) == 1) ? (((c) & LAC_MASK) | LKC_ISLAC) : \ + (((((c)&~LKC_ISLECLAC)>>LAC_SHIFT) & LAC_MASK) | +LKC_ISLECLAC)) +#endif /* 0 */ + +/* Return lkc masking single actioncode, given an lkc masking a lac + lec */ +#define LKC2_TO_LKC(c) (((c) == -1 || !((c) & LKC_ISLECLAC)) ? (c) : \ + (((c) & LAC_MASK) | LKC_ISLAC)) + +/* Return lynxeditactioncode, given an lkc masking a lac + lec */ +#define LKC2_TO_LEC(c) (((c) == -1 || !((c) & LKC_ISLECLAC)) ? (c) : \ + ((((c)&~LKC_ISLECLAC)>>LAC_SHIFT) & LAC_MASK)) + /* Convert lynxkeycode to lynxactioncode. Modifiers are dropped. */ #define LKC_TO_LAC(ktab,c) (((c) == -1) ? ktab[0] : \ - ((c) & LKC_ISLAC) ? ((c) & LAC_MASK) : \ + ((c) & (LKC_ISLECLAC|LKC_ISLAC)) ? ((c) & LAC_MASK) : \ ktab[((c) & LKC_MASK) + 1]) /* Mask lynxactioncode as a lynxkeycode. */ #define LAC_TO_LKC0(a) ((a)|LKC_ISLAC) +/* Mask a lynxactioncode and an editactioncode as a lynxkeycode. */ +#define LACLEC_TO_LKC0(a,b) ((a)|((b)<<LAC_SHIFT)|LKC_ISLECLAC) + /* Convert lynxactioncode to a lynxkeycode, attempting reverse mapping. */ #define LAC_TO_LKC(a) ((LYReverseKeymap(a)>=0)?LYReverseKeymap(a):LAC_TO_LKC0(a)) /* Simplify a lynxkeycode: - attempt reverse mapping if a masked lynxactioncode, drop modifiers. */ -#define LKC_TO_C(c) ((c&LKC_ISLAC)? LAC_TO_LKC(c&LAC_MASK) : (c&LKC_MASK)) + attempt reverse mapping if a single masked lynxactioncode, drop modifiers. */ +#define LKC_TO_C(c) ((c&LKC_ISLECLAC)? c : (c&LKC_ISLAC)? LAC_TO_LKC(c&LAC_MASK) : +(c&LKC_MASK)) -#define LKC_HAS_ESC_MOD(c) (c >= 0 && (c&LKC_MOD2)) +#define LKC_HAS_ESC_MOD(c) (c >= 0 && !(c&LKC_ISLECLAC) && (c&LKC_MOD2)) /* * The defined LynxActionCodes * */ Index: 2.24/src/LYStrings.h --- 2.24/src/LYStrings.h Thu, 25 Nov 1999 06:54:09 -0600 +++ 2.24(w)/src/LYStrings.h Sun, 28 Nov 1999 17:38:26 -0600 @@ -277,7 +277,10 @@ extern void LYRefreshEdit PARAMS(( EditFieldData * edit)); extern int EditBinding PARAMS((int ch)); /* in LYEditmap.c */ -extern int LYRemapEditBinding PARAMS((int xlkc, int lec)); /* in LYEditmap.c */ +extern BOOL LYRemapEditBinding PARAMS(( + int xlkc, + int lec, + int select_edi)); /* in LYEditmap.c */ extern int LYKeyForEditAction PARAMS((int lec)); /* in LYEditmap.c */ extern int LYEditKeyForAction PARAMS((int lac, int *pmodkey));/* LYEditmap.c */ extern int LYEdit1 PARAMS(( Index: 2.24/src/LYReadCFG.c --- 2.24/src/LYReadCFG.c Thu, 25 Nov 1999 11:29:56 -0600 +++ 2.24(w)/src/LYReadCFG.c Sun, 28 Nov 1999 17:34:27 -0600 @@ -652,6 +652,8 @@ fprintf(stderr, gettext("key remapping of %s to %s for %s failed\n"), key, func, efunc + 1); + } else if (func && !strcmp("TOGGLE_HELP", func)) { + LYUseNoviceLineTwo = FALSE; } return 0; } else if (!remap(key, strtok(func, " \t\n:#"), FALSE)) { @@ -667,9 +669,19 @@ BOOLEAN success = FALSE; int lkc = lkcstring_to_lkc(key); int lec = -1; - if (!success && strncasecomp(efunc, "DIRED", 5) == 0) { - lec = LYE_FORM_PASS; - success = (BOOL) LYRemapEditBinding(lkc, lec); + int select_edi = 0; + char *sselect_edi = strtok(NULL, " \t\n:#"); + char **endp = &sselect_edi; + if (sselect_edi) { + if (*sselect_edi) + select_edi = strtol(sselect_edi, endp, 10); + if (**endp != '\0') { + fprintf(stderr, + gettext( + "invalid line-editor selection %s for key %s, selecting all\n"), + sselect_edi, key); + select_edi = 0; + } } /* * PASS! tries to enter the key into the LYLineEditors @@ -688,7 +700,7 @@ if (!success && strcasecomp(efunc, "PASS!") == 0) { if (func) { lec = LYE_FORM_LAC|lacname_to_lac(func); - success = (BOOL) LYRemapEditBinding(lkc, lec); + success = (BOOL) LYRemapEditBinding(lkc, lec, select_edi); } if (!success) fprintf(stderr, @@ -698,9 +710,9 @@ else return 0; } - if (!success && strncasecomp(efunc, "PASS", 4) == 0) { - lec = LYE_FORM_PASS; - success = (BOOL) LYRemapEditBinding(lkc, lec); + if (!success) { + lec = lecname_to_lec(efunc); + success = (BOOL) LYRemapEditBinding(lkc, lec, select_edi); } if (!success) { if (lec != -1) {
