about summary refs log tree commit diff stats
path: root/src/LYEditmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/LYEditmap.c')
-rw-r--r--src/LYEditmap.c300
1 files changed, 299 insertions, 1 deletions
diff --git a/src/LYEditmap.c b/src/LYEditmap.c
index e49475ca..8f94fce3 100644
--- a/src/LYEditmap.c
+++ b/src/LYEditmap.c
@@ -1,15 +1,20 @@
 /*
- * $LynxId: LYEditmap.c,v 1.54 2013/10/13 20:23:07 tom Exp $
+ * $LynxId: LYEditmap.c,v 1.68 2013/10/19 20:04:16 tom Exp $
  *
  * LYEditMap.c
  * Keybindings for line and form editing.
  */
 
 #include <HTUtils.h>
+#include <HTAlert.h>
+#include <HTFile.h>
 #include <LYGlobalDefs.h>
+#include <LYCharUtils.h>
 #include <LYStrings.h>
 #include <LYKeymap.h>		/* KEYMAP_SIZE, LKC_*, LYK_* - kw */
 
+#define PUTS(buf)    (*target->isa->put_string)(target, buf)
+
 /* * * * * LynxEditactionCodes * * * * */
 #ifdef USE_ALT_BINDINGS
 
@@ -35,6 +40,72 @@ int escape_bound = 0;		/* User wanted Escape to perform actions?  */
 /*
  * See LYStrings.h for the LYE definitions.
  */
+/* *INDENT-OFF* */
+struct emap {
+    const char *name;
+    const int   code;
+    const char *descr;
+};
+
+#define SEPARATOR {"", -1, ""}
+
+static struct emap ekmap[] = {
+  {"NOP",	LYE_NOP,	"Do Nothing"},
+  {"CHAR",	LYE_CHAR,	"Insert printable char"},
+  SEPARATOR,
+  {"ENTER",	LYE_ENTER,	"Input complete, return char"},
+  {"TAB",	LYE_TAB,	"Input complete, return TAB"},
+  {"STOP",	LYE_STOP,	"Input deactivated"},
+  {"ABORT",	LYE_ABORT,	"Input cancelled"},
+  SEPARATOR,
+  {"PASS",	LYE_FORM_PASS,  "Fields only: input complete"},
+  SEPARATOR,
+  {"DELBL",	LYE_DELBL,	"Delete back to BOL"},
+  {"DELEL",	LYE_DELEL,	"Delete thru EOL"},
+  {"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"},
+  SEPARATOR,
+
+  {"ERASE",	LYE_ERASE,	"Erase the line"},
+  SEPARATOR,
+  {"BOL",	LYE_BOL,	"Go to begin of line"},
+  {"EOL",	LYE_EOL,	"Go to end   of line"},
+  {"FORW",	LYE_FORW,	"Cursor forwards"},
+  {"FORW_RL",	LYE_FORW_RL,	"Cursor forwards or right link"},
+  {"BACK",	LYE_BACK,	"Cursor backwards"},
+  {"BACK_LL",	LYE_BACK_LL,	"Cursor backwards or left link"},
+  {"FORWW",	LYE_FORWW,	"Word forward"},
+  {"BACKW",	LYE_BACKW,	"Word back"},
+  SEPARATOR,
+  {"LOWER",	LYE_LOWER,	"Lower case the line"},
+  {"UPPER",	LYE_UPPER,	"Upper case the line"},
+  SEPARATOR,
+  {"LKCMD",	LYE_LKCMD,	"Invoke command prompt"},
+  {"SWMAP",	LYE_SWMAP,	"Switch input keymap"},
+  SEPARATOR,
+  {"C1CHAR",	LYE_C1CHAR,	"Insert C1 char if printable"},
+  {"SETM1",	LYE_SETM1,	"Set modifier 1 flag"},
+  {"SETM2",	LYE_SETM2,	"Set modifier 2 flag"},
+  {"UNMOD",	LYE_UNMOD,	"Fall back to no-modifier command"},
+  SEPARATOR,
+  {"TPOS",	LYE_TPOS,	"Transpose characters"},
+  {"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"},
+#ifdef CAN_CUT_AND_PASTE
+  SEPARATOR,
+  {"PASTE",	LYE_PASTE,	"ClipBoard to Lynx"},
+#endif
+  SEPARATOR,
+  {"AIX",	LYE_AIX,	"Hex 97"},
+  {0,           -1,             0},
+};
+#undef SEPARATOR
+/* *INDENT-ON* */
+
 static LYEditCode DefaultEditBinding[KEYMAP_SIZE - 1];
 
 #ifdef USE_ALT_BINDINGS
@@ -1170,6 +1241,62 @@ const char *LYLineeditHelpURLs[] =
     (char *) 0
 };
 
+static struct emap *name2emap(const char *name)
+{
+    struct emap *mp;
+    struct emap *result = 0;
+
+    if (non_empty(name)) {
+	for (mp = ekmap; mp->name != NULL; mp++) {
+	    if (strcmp(mp->name, name) == 0) {
+		result = mp;
+		break;
+	    }
+	}
+    }
+    return result;
+}
+
+static struct emap *code2emap(int code)
+{
+    struct emap *mp;
+    struct emap *result = 0;
+
+    for (mp = ekmap; mp->name != NULL; mp++) {
+	if (mp->code == code) {
+	    result = mp;
+	    break;
+	}
+    }
+    return result;
+}
+
+/*
+ * Return editactioncode whose name is the string func.  func must be present
+ * in the ekmap table.  returns -1 if not found.  - kw
+ */
+int lecname_to_lec(const char *func)
+{
+    struct emap *mp;
+    int result = -1;
+
+    if ((mp = name2emap(func)) != 0) {
+	result = mp->code;
+    }
+    return result;
+}
+
+const char *lec_to_lecname(int code)
+{
+    struct emap *mp;
+    const char *result = 0;
+
+    if ((mp = code2emap(code)) != 0) {
+	result = mp->name;
+    }
+    return result;
+}
+
 int EditBinding(int xlkc)
 {
     int editaction, xleac = LYE_UNMOD;
@@ -1639,3 +1766,174 @@ void LYinitEditmap(void)
 	initLineEditor(&LYModifierBindings[j]);
     }
 }
+
+static char *showRanges(int *state)
+{
+    char *result = 0;
+    int range[2];
+    int i;
+
+    range[0] = range[1] = -1;
+    for (i = 0; i < KEYMAP_SIZE - 1; ++i) {
+	if (!state[i]) {
+	    int code = CurrentLineEditor()[i];
+
+	    if (code == LYE_CHAR) {
+		if (range[0] < 0)
+		    range[0] = i;
+		range[1] = i;
+		state[i] = 3;
+	    } else if (range[0] >= 0) {
+		if (non_empty(result))
+		    StrAllocCat(result, ", ");
+		HTSprintf(&result, "%d-%d", range[0], range[1]);
+		range[0] = range[1] = -1;
+	    }
+	}
+    }
+    return result;
+}
+
+static int LYLoadEditmap(const char *arg GCC_UNUSED,
+			 HTParentAnchor *anAnchor,
+			 HTFormat format_out,
+			 HTStream *sink)
+{
+#define FORMAT "  %-*s  %-*s  -  %s\n"
+    HTFormat format_in = WWW_HTML;
+    HTStream *target;
+    int state[KEYMAP_SIZE - 1];
+    int width[2];
+    char *buf = 0;
+    char *ranges = 0;
+    struct emap *mp;
+    int i;
+    int hanging;
+    int wrapped;
+    int had_output = FALSE;
+    int result;
+
+    if ((target = HTStreamStack(format_in, format_out, sink, anAnchor)) != 0) {
+	anAnchor->no_cache = TRUE;
+
+	HTSprintf0(&buf,
+		   "<html>\n<head>\n<title>%s</title>\n</head>\n<body>\n",
+		   CURRENT_EDITMAP_TITLE);
+	PUTS(buf);
+	HTSprintf0(&buf, "<pre>\n");
+	PUTS(buf);
+
+	/* determine the column-widths we will use for showing bindings */
+	width[0] = 0;
+	width[1] = 0;
+	for (i = 0; i < KEYMAP_SIZE - 1; ++i) {
+	    int code = CurrentLineEditor()[i];
+
+	    if (code == LYE_NOP) {
+		state[i] = 1;
+	    } else {
+		int need;
+
+		if ((mp = code2emap(code)) != 0) {
+		    state[i] = 0;
+		    if ((need = (int) strlen(mp->name)) > width[0])
+			width[0] = need;
+		    if ((need = (int) strlen(mp->descr)) > width[1])
+			width[1] = need;
+		} else {
+		    state[i] = 2;
+		}
+	    }
+	}
+	hanging = 2 + width[0] + 2 + width[1] + 5;
+	wrapped = hanging;
+
+	/*
+	 * Tell which set of bindings we are showing, and link to the
+	 * handcrafted page, which adds explanations.
+	 */
+	PUTS(gettext("These are the current edit-bindings:"));
+	HTSprintf0(&buf,
+		   " <a href=\"%s\">%s</a>\n\n",
+		   LYLineeditHelpURL(),
+		   LYEditorNames[current_lineedit]);
+	PUTS(buf);
+
+	/* Show by groups to match the arrangement in the handmade files. */
+	for (mp = ekmap; mp->name != 0; ++mp) {
+	    if (isEmpty(mp->name)) {
+		if (had_output) {
+		    PUTS("\n");
+		    had_output = FALSE;
+		}
+	    } else if (mp->code == LYE_CHAR) {
+		ranges = showRanges(state);
+		HTSprintf0(&buf, FORMAT,
+			   width[0], mp->name,
+			   width[1], mp->descr,
+			   ranges);
+		FREE(ranges);
+		PUTS(buf);
+		had_output = TRUE;
+	    } else {
+		for (i = 0; i < KEYMAP_SIZE - 1; ++i) {
+		    int code = CurrentLineEditor()[i];
+
+		    if ((code == mp->code) && !state[i]) {
+			char *value = LYKeycodeToString(i, (i >= 160 &&
+							    i <= 255));
+			int before = wrapped + (ranges ? ((int)
+							  strlen(ranges)) : 0);
+			int after = before;
+
+			if (non_empty(ranges)) {
+			    StrAllocCat(ranges, ", ");
+			    after += 2;
+			}
+			after += (int) strlen(value) + 2;
+			if ((before / LYcols) != (after / LYcols)) {
+			    wrapped += (LYcols - (before % LYcols));
+			    HTSprintf(&ranges, "\n%-*s", hanging, " ");
+			}
+			StrAllocCat(ranges, value);
+		    }
+		}
+		if (non_empty(ranges)) {
+		    LYEntify(&ranges, TRUE);
+		    HTSprintf0(&buf, FORMAT,
+			       width[0], mp->name,
+			       width[1], mp->descr,
+			       ranges);
+		    PUTS(buf);
+		    FREE(ranges);
+		    had_output = TRUE;
+		}
+	    }
+	}
+
+	HTSprintf0(&buf, "</pre>\n</body>\n</html>\n");
+	PUTS(buf);
+
+	(*target->isa->_free) (target);
+	result = HT_LOADED;
+    } else {
+	HTSprintf0(&buf, CANNOT_CONVERT_I_TO_O,
+		   HTAtom_name(format_in), HTAtom_name(format_out));
+	HTAlert(buf);
+	result = HT_NOT_LOADED;
+    }
+    FREE(ranges);
+    FREE(buf);
+    return result;
+#undef FORMAT
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _LYEDITMAP_C_GLOBALDEF_1_INIT { "LYNXEDITMAP", LYLoadEditmap, 0}
+GLOBALDEF(HTProtocol, LYLynxEditmap, _LYEDITMAP_C_GLOBALDEF_1_INIT);
+#else
+GLOBALDEF HTProtocol LYLynxEditmap =
+{
+    "LYNXEDITMAP", LYLoadEditmap, 0
+};
+#endif /* GLOBALDEF_IS_MACRO */