From 4651f49fcaa81708f3795b0fbeb203d5d5ef41b8 Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@justemail.net>
Date: Fri, 27 Jun 2014 16:14:52 +0000
Subject: [PATCH] Allowing only those menus where the bound function is
 actually present, when rebinding keys.

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@5022 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 ChangeLog    |  5 +++++
 src/rcfile.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 876d63af..10e5bd39 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,11 @@
 	* src/global.c (shortcut_init): Add default keybindings for Cut,
 	PrevWord and NextWord in the prompt input lines; the code for those
 	special operations already exists, just the shortcuts were missing.
+	* src/rcfile.c (parse_binding): When binding keys, only allow those
+	menus where the bound function is actually present.  This reduces
+	the meaning of 'all' to "all menus where the function exists".
+	* src/rcfile.c (is_universal): New function, returning TRUE for the
+	functions that are present in most menus but only listed in MMAIN.
 
 2014-06-25  Benno Schulenberg  <bensberg@justemail.net>
 	* src/browser.c (do_browser): Allow 'firstfile' and 'lastfile' to be
diff --git a/src/rcfile.c b/src/rcfile.c
index 4ffd7ed4..041c1cbc 100644
--- a/src/rcfile.c
+++ b/src/rcfile.c
@@ -397,6 +397,22 @@ int check_bad_binding(sc *s)
     return 0;
 }
 
+/* Check whether the given executable function is "universal" (meaning
+ * any horizontal movement or deletion) and thus is present in almost
+ * all menus. */
+bool is_universal(void (*func))
+{
+    if (func == do_left || func == do_right ||
+	func == do_home || func == do_end ||
+	func == do_prev_word_void || func == do_next_word_void ||
+	func == do_verbatim_input || func == do_cut_text_void ||
+	func == do_delete || func == do_backspace ||
+	func == do_tab || func == do_enter)
+	return TRUE;
+    else
+	return FALSE;
+}
+
 /* Bind or unbind a key combo, to or from a function. */
 void parse_binding(char *ptr, bool dobind)
 {
@@ -487,6 +503,26 @@ void parse_binding(char *ptr, bool dobind)
 #endif
 
     if (dobind) {
+	subnfunc *f;
+	int mask = 0;
+
+	/* Tally up the menus where the function exists. */
+	for (f = allfuncs; f != NULL; f = f->next)
+	    if (f->scfunc == newsc->scfunc)
+		mask = mask | f->menus;
+
+	/* Now limit the given menu to those where the function exists. */
+	if (is_universal(newsc->scfunc))
+	    menu = menu & MMOST;
+	else
+	    menu = menu & mask;
+
+	if (!menu) {
+	    rcfile_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr);
+	    free(newsc);
+	    return;
+	}
+
 	newsc->keystr = keycopy;
 	newsc->menu = menu;
 	newsc->type = strtokeytype(newsc->keystr);
-- 
GitLab