]> git.wh0rd.org Git - nano.git/commitdiff
New keybindings code and backend. New structs subnfunc for menu functions
authorChris Allegretta <chrisa@asty.org>
Wed, 5 Mar 2008 07:34:01 +0000 (07:34 +0000)
committerChris Allegretta <chrisa@asty.org>
Wed, 5 Mar 2008 07:34:01 +0000 (07:34 +0000)
and toggles and sc for shortcut keys, old 'shortcut' and 'toggles' structs are
gone.  The current implementation has a bunch of broken stuff (some of which is
documented in BUGS).  Updated nanorc.5 with some mostly complete documentation
on configuring.

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4215 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

12 files changed:
src/browser.c
src/files.c
src/global.c
src/help.c
src/nano.c
src/nano.h
src/prompt.c
src/proto.h
src/rcfile.c
src/search.c
src/text.c
src/winio.c

index d7be9744b85bcaba4ffbcdf5ba804c9b5212ccab..37d904c49089466031caeda84e0499e427b52aa7 100644 (file)
@@ -64,9 +64,9 @@ char *do_browser(char *path, DIR *dir)
     curs_set(0);
     blank_statusbar();
 #if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
-    currshortcut = browser_list;
+    currmenu = MBROWSER;
 #endif
-    bottombars(browser_list);
+    bottombars(MBROWSER);
     wnoutrefresh(bottomwin);
 
     UNSET(CONST_UPDATE);
@@ -213,17 +213,17 @@ char *do_browser(char *path, DIR *dir)
 #ifndef DISABLE_TABCOMP
                        FALSE,
 #endif
-                       gotodir_list, ans,
+                       MGOTODIR, ans,
 #ifndef NANO_TINY
                        NULL,
 #endif
-                       browser_refresh, _("Go To Directory"));
+                       browser_refresh, N_("Go To Directory"));
 
                curs_set(0);
 #if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
-               currshortcut = browser_list;
+               currmenu = MBROWSER;
 #endif
-               bottombars(browser_list);
+               bottombars(MBROWSER);
 
                /* If the directory begins with a newline (i.e. an
                 * encoded null), treat it as though it's blank. */
@@ -552,7 +552,7 @@ void browser_init(const char *path, DIR *dir)
  * shortcut keys. */
 void parse_browser_input(int *kbinput, bool *meta_key, bool *func_key)
 {
-    get_shortcut(browser_list, kbinput, meta_key, func_key);
+    get_shortcut(MBROWSER, kbinput, meta_key, func_key);
 
     /* Pico compatibility. */
     if (!*meta_key) {
@@ -796,7 +796,7 @@ int filesearch_init(void)
 #ifndef DISABLE_TABCOMP
        TRUE,
 #endif
-       whereis_file_list, backupstring,
+       MWHEREISFILE, backupstring,
 #ifndef NANO_TINY
        &search_history,
 #endif
@@ -955,8 +955,8 @@ void findnextfile_wrap_reset(void)
  * search, if any. */
 void filesearch_abort(void)
 {
-    currshortcut = browser_list;
-    bottombars(browser_list);
+    currmenu = MBROWSER;
+    bottombars(MBROWSER);
 #ifdef HAVE_REGEX_H
     regexp_cleanup();
 #endif
index a74054d23641ce358be180114f4eab49ee36c2ae..77973700e402225b36944a63d69681296c2080f2 100644 (file)
@@ -731,9 +731,9 @@ void do_insertfile(
                TRUE,
 #endif
 #ifndef NANO_TINY
-               execute ? extcmd_list :
+               execute ? MEXTCMD :
 #endif
-               insertfile_list, ans,
+               MINSERTFILE, ans,
 #ifndef NANO_TINY
                NULL,
 #endif
@@ -1814,7 +1814,7 @@ bool do_writeout(bool exiting)
 #endif
     bool retval = FALSE;
 
-    currshortcut = writefile_list;
+    currmenu = MWRITEFILE;
 
     if (exiting && openfile->filename[0] != '\0' && ISSET(TEMP_FILE)) {
        retval = write_file(openfile->filename, NULL, FALSE, OVERWRITE,
@@ -1865,7 +1865,7 @@ bool do_writeout(bool exiting)
 #ifndef DISABLE_TABCOMP
                TRUE,
 #endif
-               writefile_list, ans,
+               MWRITEFILE, ans,
 #ifndef NANO_TINY
                NULL,
 #endif
index f4c827760c4ff95765f6deb93b5d0243f98a3d1a..e33fde0d9bdc79e5991493e4427bd10382d00457 100644 (file)
@@ -1,4 +1,5 @@
-/* $Id$ */
+/* $Id$ 
+*/
 /**************************************************************************
  *   global.c                                                             *
  *                                                                        *
@@ -21,6 +22,9 @@
  *                                                                        *
  **************************************************************************/
 
+#include <ctype.h>
+#include <strings.h>
+#include "assert.h"
 #include "proto.h"
 
 /* Global variables. */
@@ -133,41 +137,6 @@ char *alt_speller = NULL;
        /* The command to use for the alternate spell checker. */
 #endif
 
-shortcut *main_list = NULL;
-       /* The main shortcut list. */
-shortcut *whereis_list = NULL;
-       /* The "Search" shortcut list. */
-shortcut *replace_list = NULL;
-       /* The "Search (to replace)" shortcut list. */
-shortcut *replace_list_2 = NULL;
-       /* The "Replace with" shortcut list. */
-shortcut *gotoline_list = NULL;
-       /* The "Enter line number, column number" shortcut list. */
-shortcut *writefile_list = NULL;
-       /* The "File Name to Write" shortcut list. */
-shortcut *insertfile_list = NULL;
-       /* The "File to insert" shortcut list. */
-#ifndef NANO_TINY
-shortcut *extcmd_list = NULL;
-       /* The "Command to execute" shortcut list. */
-#endif
-#ifndef DISABLE_HELP
-shortcut *help_list = NULL;
-       /* The help text shortcut list. */
-#endif
-#ifndef DISABLE_SPELLER
-shortcut *spell_list = NULL;
-       /* The internal spell checker shortcut list. */
-#endif
-#ifndef DISABLE_BROWSER
-shortcut *browser_list = NULL;
-       /* The file browser shortcut list. */
-shortcut *whereis_file_list = NULL;
-       /* The file browser "Search" shortcut list. */
-shortcut *gotodir_list = NULL;
-       /* The "Go To Directory" shortcut list. */
-#endif
-
 #ifdef ENABLE_COLOR
 syntaxtype *syntaxes = NULL;
        /* The global list of color syntaxes. */
@@ -177,11 +146,19 @@ char *syntaxstr = NULL;
 
 const shortcut *currshortcut;
        /* The current shortcut list we're using. */
+int currmenu;
+       /* The currently loaded menu */
+
 #ifndef NANO_TINY
 toggle *toggles = NULL;
        /* The global toggle list. */
 #endif
 
+sc *sclist = NULL;
+       /* New shortcut key struct */
+subnfunc *allfuncs = NULL;
+       /* New struct for the function list */
+
 #ifndef NANO_TINY
 filestruct *search_history = NULL;
        /* The search string history list. */
@@ -212,66 +189,255 @@ int reverse_attr = A_REVERSE;
 char *homedir = NULL;
        /* The user's home directory, from $HOME or /etc/passwd. */
 
-/* Return the number of entries in the shortcut list s. */
-size_t length_of_list(const shortcut *s)
+/* Return the number of entries in the shortcut list s for a given menu. */
+size_t length_of_list(int menu)
 {
+    subnfunc *f;
     size_t i = 0;
 
-    for (; s != NULL; s = s->next)
-       i++;
+    for (f = allfuncs; f != NULL; f = f->next)
+        if ((f->menus & menu) != 0) {
+           i++;
+       }
     return i;
 }
 
-/* Add a new shortcut to the end of the shortcut list. */
-void sc_init_one(shortcut **shortcutage, int ctrlval, const char *desc
-#ifndef DISABLE_HELP
-       , const char *help, bool blank_after
+/* Set type of function based on the string */
+function_type strtokeytype(char *str)
+{
+    if (str[0] ==  'M' || str[0] == 'm') {
+        return META;
+    } else if (str[0] == '^') {
+        return CONTROL;
+    } else if (str[0] ==  'M' || str[0] == 'm') {
+        return FKEY;
+    } else {
+       return RAW;
+    }
+}
+
+/* Add a string to the new function list strict.
+   Does not allow updates, yet anyway */
+void add_to_funcs(void *func, int menus, const char *desc, const char *help,
+    bool blank_after, bool viewok)
+{
+    subnfunc *f;
+
+    if (allfuncs == NULL) {
+       allfuncs = nmalloc(sizeof(subnfunc));
+       f = allfuncs;
+    } else {
+       for (f = allfuncs; f->next != NULL; f = f->next)
+               ;
+        f->next = (subnfunc *)nmalloc(sizeof(subnfunc));
+        f = f->next;
+    }
+    f->next = NULL;
+    f->scfunc = func;
+    f->menus = menus;
+    f->desc = desc;
+    f->viewok = viewok;
+#ifndef NANO_TINY
+    f->help = help;
+    f->blank_after = blank_after;
+#endif
+
+#ifdef DEBUG
+    fprintf(stderr, "Added func \"%s\"", f->desc);
 #endif
-       , int metaval, int funcval, int miscval, bool view,
-       void (*func)(void))
+}
+
+const sc *first_sc_for(int menu, void *func) {
+    const sc *s;
+
+    for (s = sclist; s != NULL; s = s->next) {
+       if ((s->menu & menu) && s->scfunc == func) {
+           return s;
+       }
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "Whoops, returning null given func %ld\n", (long) func);
+#endif
+    /* Otherwise... */
+    return NULL;
+}
+
+
+/* Add a string to the new shortcut list implementation
+   Allows updates to existing entries in the list */
+void add_to_sclist(int menu, char *scstring, void *func, int toggle, int execute)
 {
-    shortcut *s;
+    sc *s;
 
-    if (*shortcutage == NULL) {
-       *shortcutage = (shortcut *)nmalloc(sizeof(shortcut));
-       s = *shortcutage;
+    if (sclist == NULL) {
+       sclist = nmalloc(sizeof(sc));
+       s = sclist;
+        s->next = NULL;
     } else {
-       for (s = *shortcutage; s->next != NULL; s = s->next)
-           ;
-       s->next = (shortcut *)nmalloc(sizeof(shortcut));
-       s = s->next;
+       for (s = sclist; s->next != NULL; s = s->next)
+            if (s->menu == menu && s->keystr == scstring)
+               break;
+
+        if (s->menu != menu || s->keystr != scstring) { /* i.e. this is not a replace... */
+#ifdef DEBUG
+            fprintf(stderr, "No match found...\n");
+#endif
+           s->next = (sc *)nmalloc(sizeof(sc));
+           s = s->next;
+            s->next = NULL;
+        }
     }
 
-    s->ctrlval = ctrlval;
-    s->desc = (desc == NULL) ? "" : _(desc);
-#ifndef DISABLE_HELP
-    s->help = (help == NULL) ? "" : _(help);
-    s->blank_after = blank_after;
-#endif
-    s->metaval = metaval;
-    s->funcval = funcval;
-    s->miscval = miscval;
-    s->viewok = view;
-    s->func = func;
-    s->next = NULL;
+    s->type = strtokeytype(scstring);
+    s->menu = menu;
+    s->toggle = toggle;
+    s->keystr = scstring;
+    s->scfunc = func;
+    s->execute = execute;
+    assign_keyinfo(s);
+
+#ifdef DEBUG
+    fprintf(stderr, "list val = %d\n", (int) s->menu);
+    fprintf(stderr, "Hey, set sequence to %d for shortcut \"%s\"\n", s->seq, scstring);
+#endif
 }
 
+/* Assign the info to the shortcut struct 
+   Assumes keystr is already assigned, naturally */
+void assign_keyinfo(sc *s)
+{
+    if (s->type == CONTROL) {
+        assert(strlen(s->keystr) > 1);
+        s->seq = s->keystr[1] - 64;
+    } else if (s->type == META) {
+        assert(strlen(s->keystr) > 2);
+        s->seq = tolower((int) s->keystr[2]);
+    } else if (s->type == FKEY) {
+        assert(strlen(s->keystr) > 1);
+        s->seq = KEY_F0 + atoi(&s->keystr[1]);
+    } else /* raw */
+        s->seq = (int) s->keystr[0];
+}
+
+#ifdef DEBUG
+
+void print_sclist(void)
+{
+    sc *s;
+    const subnfunc *f;
+
+    for (s = sclist; s->next != NULL; s = s->next) {
+       f = sctofunc(s);
+        if (f)
+           fprintf(stderr, "Shortcut \"%s\", function: %s\n",  s->keystr, f->desc);
+       else
+           fprintf(stderr, "Hmm, didnt find a func for \"%s\"\n", s->keystr);
+    }
+
+}
+#endif
+
+
+/* Stuff we need to make at least static here so we can access it below */
+const char *cancel_msg = N_("Cancel");
+
+#ifndef NANO_TINY
+const char *case_sens_msg = N_("Case Sens");
+const char *backwards_msg = N_("Backwards");
+#endif
+
+#ifdef HAVE_REGEX_H
+const char *regexp_msg = N_("Regexp");
+#endif
+
+/* Stuff we want to just stun out if we're in TINY mode */
+#ifdef NANO_TINY
+const char *nano_cancel_msg = "";
+const char *nano_exit_msg = "";
+const char *nano_writeout_msg = "";
+const char *nano_insert_msg = "";
+const char *nano_whereis_msg = "";
+const char *nano_prevpage_msg = "";
+const char *nano_nextpage_msg = "";
+const char *nano_cut_msg = "";
+const char *nano_uncut_msg = "";
+const char *nano_cursorpos_msg = "";
+const char *nano_lastline_msg = "";
+const char *nano_gotoline_msg = "";
+const char *nano_replace_msg = "";
+const char *nano_forward_msg = "";
+const char *nano_back_msg = "";
+const char *nano_prevline_msg = "";
+const char *nano_nextline_msg = "";
+const char *nano_home_msg = "";
+const char *nano_end_msg = "";
+const char *nano_verbatim_msg = "";
+const char *nano_tab_msg = "";
+const char *nano_enter_msg = "";
+const char *nano_delete_msg = "";
+const char *nano_backspace_msg = "";
+const char *nano_regexp_msg = "";
+const char *gototext_msg = "";
+const char *do_para_begin_void = "";
+const char *do_para_end_void = "";
+const char *case_sens_msg = "";
+const char *backwards_msg = "";
+const char *do_cut_till_end = "";
+const char *dos_format_msg = "";
+const char *mac_format_msg = "";
+const char *append_msg = "";
+const char *prepend_msg = "";
+const char *backup_file_msg = "";
+const char *to_files_msg = "";
+#else /* NANO_TINY */
+const char *prev_history_msg = N_("PrevHstory");
+/* TRANSLATORS: Try to keep this and previous strings at most 10
+ * characters. */
+const char *next_history_msg = N_("NextHstory");
+const char *replace_msg = N_("Replace");
+const char *no_replace_msg = N_("No Replace");
+const char *go_to_line_msg = N_("Go To Line");
+const char *gototext_msg = N_("Go To Text");
+#ifndef DISABLE_BROWSER
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *to_files_msg = N_("To Files");
+/* TRANSLATORS: Try to keep this at most 12 characters. */
+const char *first_file_msg = N_("First File");
+/* TRANSLATORS: Try to keep this at most 12 characters. */
+const char *last_file_msg = N_("Last File");
+#endif
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *dos_format_msg = N_("DOS Format");
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *mac_format_msg = N_("Mac Format");
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *append_msg = N_("Append");
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *prepend_msg = N_("Prepend");
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *backup_file_msg = N_("Backup File");
+
+#ifdef ENABLE_MULTIBUFFER
+/* TRANSLATORS: Try to keep this at most 16 characters. */
+const char *new_buffer_msg = N_("New Buffer");
+#endif
+
+#endif
+
 /* Initialize all shortcut lists.  If unjustify is TRUE, replace the
  * Uncut shortcut in the main shortcut list with UnJustify. */
 void shortcut_init(bool unjustify)
 {
     /* TRANSLATORS: Try to keep this and following strings at most 10
      * characters. */
-    const char *cancel_msg = N_("Cancel");
     const char *get_help_msg = N_("Get Help");
     const char *exit_msg = N_("Exit");
     const char *whereis_msg = N_("Where Is");
     const char *prev_page_msg = N_("Prev Page");
     const char *next_page_msg = N_("Next Page");
-    const char *go_to_line_msg = N_("Go To Line");
-    /* TRANSLATORS: Try to keep this and previous strings at most 10
-     * characters. */
-    const char *replace_msg = N_("Replace");
+    /* TRANSLATORS: Try to keep this string at most 10 characters. */
+
 #ifndef NANO_TINY
     /* TRANSLATORS: Try to keep this at most 12 characters. */
     const char *whereis_next_msg = N_("WhereIs Next");
@@ -286,31 +452,10 @@ void shortcut_init(bool unjustify)
     const char *fulljstify_msg = N_("FullJstify");
 #endif
     const char *refresh_msg = N_("Refresh");
-#ifndef NANO_TINY
-    const char *case_sens_msg = N_("Case Sens");
-    const char *backwards_msg = N_("Backwards");
-#endif
-#ifdef HAVE_REGEX_H
-    const char *regexp_msg = N_("Regexp");
-#endif
-#ifndef NANO_TINY
-    const char *prev_history_msg = N_("PrevHstory");
-    /* TRANSLATORS: Try to keep this and previous strings at most 10
-     * characters. */
-    const char *next_history_msg = N_("NextHstory");
-#ifdef ENABLE_MULTIBUFFER
-    /* TRANSLATORS: Try to keep this at most 16 characters. */
-    const char *new_buffer_msg = N_("New Buffer");
-#endif
-#endif
-#ifndef DISABLE_BROWSER
-    /* TRANSLATORS: Try to keep this at most 16 characters. */
-    const char *to_files_msg = N_("To Files");
-    /* TRANSLATORS: Try to keep this at most 12 characters. */
-    const char *first_file_msg = N_("First File");
-    /* TRANSLATORS: Try to keep this at most 12 characters. */
-    const char *last_file_msg = N_("Last File");
-#endif
+    const char *insert_file_msg =  N_("Insert File");
+    const char *goto_dir_msg = N_("Go To Dir");
+    const char *ext_cmd_msg = N_("Execute Command");
+
 #ifndef DISABLE_HELP
     const char *nano_cancel_msg = N_("Cancel the current function");
     const char *nano_help_msg = N_("Display this help text");
@@ -338,9 +483,9 @@ void shortcut_init(bool unjustify)
        N_("Display the position of the cursor");
     const char *nano_spell_msg =
        N_("Invoke the spell checker, if available");
-    const char *nano_gotoline_msg = N_("Go to line and column number");
     const char *nano_replace_msg =
        N_("Replace a string or a regular expression");
+     const char *nano_gotoline_msg = N_("Go to line and column number");
 #ifndef NANO_TINY
     const char *nano_mark_msg = N_("Mark text at the cursor position");
     const char *nano_whereis_next_msg = N_("Repeat last search");
@@ -446,53 +591,49 @@ void shortcut_init(bool unjustify)
     const char *nano_lastfile_msg =
        N_("Go to the last file in the list");
     const char *nano_gotodir_msg = N_("Go to directory");
+
 #endif
 #endif /* !DISABLE_HELP */
 
-/* The following macro is to be used in calling sc_init_one().  The
- * point is that sc_init_one() takes 10 arguments, unless DISABLE_HELP
- * is defined, when the 4th and 5th ones should not be there. */
 #ifndef DISABLE_HELP
 #define IFSCHELP(help, blank, nextvar) help, blank, nextvar
 #else
 #define IFSCHELP(help, blank, nextvar) nextvar
 #endif
 
-    free_shortcutage(&main_list);
+    while (allfuncs != NULL) {
+        subnfunc *f = allfuncs;
+        allfuncs = (allfuncs)->next;
+        free(f);
+    }
 
-    sc_init_one(&main_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
 #ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
+    add_to_funcs(do_help_void, MALL, get_help_msg, nano_help_msg,
+       FALSE, VIEW);
 #endif
-       );
 
-    sc_init_one(&main_list, NANO_EXIT_KEY,
+    add_to_funcs((void *) cancel_msg,
+       (MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MWHEREISFILE|MGOTODIR),
+       cancel_msg, nano_cancel_msg, FALSE, VIEW);
+
+    add_to_funcs(do_exit, MMAIN,
 #ifdef ENABLE_MULTIBUFFER
        /* TRANSLATORS: Try to keep this at most 10 characters. */
        openfile != NULL && openfile != openfile->next ? N_("Close") :
 #endif
-       exit_msg, IFSCHELP(nano_exit_msg, FALSE, NANO_NO_KEY),
-       NANO_EXIT_FKEY, NANO_NO_KEY, VIEW, do_exit);
+       exit_msg, nano_exit_msg, FALSE, VIEW);
 
-    /* TRANSLATORS: Try to keep this at most 10 characters. */
-    sc_init_one(&main_list, NANO_WRITEOUT_KEY, N_("WriteOut"),
-       IFSCHELP(nano_writeout_msg, FALSE, NANO_NO_KEY),
-       NANO_WRITEOUT_FKEY, NANO_NO_KEY, NOVIEW, do_writeout_void);
+    add_to_funcs(do_exit, MBROWSER|MHELP, exit_msg, nano_exit_msg, FALSE, VIEW);
 
     /* TRANSLATORS: Try to keep this at most 10 characters. */
-    sc_init_one(&main_list, NANO_JUSTIFY_KEY, N_("Justify"),
-       IFSCHELP(nano_justify_msg, TRUE, NANO_NO_KEY),
-       NANO_JUSTIFY_FKEY, NANO_NO_KEY, NOVIEW,
+    add_to_funcs(do_writeout_void, MMAIN, N_("WriteOut"),
+       nano_writeout_msg, FALSE, NOVIEW);
+
 #ifndef DISABLE_JUSTIFY
-       do_justify_void
-#else
-       nano_disabled_msg
+    /* TRANSLATORS: Try to keep this at most 10 characters. */
+    add_to_funcs(do_justify_void, MMAIN, N_("Justify"),
+       nano_justify_msg, TRUE, NOVIEW);
 #endif
-       );
 
     /* We allow inserting files in view mode if multibuffers are
      * available, so that we can view multiple files.  If we're using
@@ -500,442 +641,222 @@ void shortcut_init(bool unjustify)
      * reading from or writing to files not specified on the command
      * line. */
     /* TRANSLATORS: Try to keep this at most 10 characters. */
-    sc_init_one(&main_list, NANO_INSERTFILE_KEY, N_("Read File"),
-       IFSCHELP(nano_insert_msg, FALSE, NANO_NO_KEY),
-       NANO_INSERTFILE_FKEY, NANO_NO_KEY,
+    add_to_funcs(!ISSET(RESTRICTED) ? do_insertfile_void : nano_disabled_msg,
+       MMAIN, N_("Read File"), nano_insert_msg, FALSE,
 #ifdef ENABLE_MULTIBUFFER
-       VIEW
+       VIEW);
 #else
-       NOVIEW
+       NOVIEW);
 #endif
-       , !ISSET(RESTRICTED) ? do_insertfile_void : nano_disabled_msg);
 
-    sc_init_one(&main_list, NANO_WHEREIS_KEY, whereis_msg,
-       IFSCHELP(nano_whereis_msg, FALSE, NANO_NO_KEY),
-       NANO_WHEREIS_FKEY, NANO_NO_KEY, VIEW, do_search);
+    add_to_funcs(do_search, MMAIN, whereis_msg,
+       nano_whereis_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_PREVPAGE_KEY, prev_page_msg,
-       IFSCHELP(nano_prevpage_msg, FALSE, NANO_NO_KEY),
-       NANO_PREVPAGE_FKEY, NANO_NO_KEY, VIEW, do_page_up);
-
-    sc_init_one(&main_list, NANO_NEXTPAGE_KEY, next_page_msg,
-       IFSCHELP(nano_nextpage_msg, TRUE, NANO_NO_KEY),
-       NANO_NEXTPAGE_FKEY, NANO_NO_KEY, VIEW, do_page_down);
+    add_to_funcs(do_page_up, (MMAIN|MHELP|MBROWSER),
+       prev_page_msg, nano_prevpage_msg, FALSE, VIEW);
+    add_to_funcs(do_page_down, (MMAIN|MHELP|MBROWSER),
+       next_page_msg, nano_nextpage_msg, TRUE, VIEW);
 
     /* TRANSLATORS: Try to keep this at most 10 characters. */
-    sc_init_one(&main_list, NANO_CUT_KEY, N_("Cut Text"),
-       IFSCHELP(nano_cut_msg, FALSE, NANO_NO_KEY), NANO_CUT_FKEY,
-       NANO_NO_KEY, NOVIEW, do_cut_text_void);
+    add_to_funcs(do_cut_text_void, MMAIN, N_("Cut Text"), nano_cut_msg,
+       FALSE, NOVIEW);
 
     if (unjustify)
        /* TRANSLATORS: Try to keep this at most 10 characters. */
-       sc_init_one(&main_list, NANO_UNJUSTIFY_KEY, N_("UnJustify"),
-               IFSCHELP(NULL, FALSE, NANO_NO_KEY), NANO_UNJUSTIFY_FKEY,
-               NANO_NO_KEY, NOVIEW, NULL);
+       add_to_funcs(do_uncut_text, MMAIN, N_("UnJustify"), "",
+           FALSE, NOVIEW);
+
     else
        /* TRANSLATORS: Try to keep this at most 10 characters. */
-       sc_init_one(&main_list, NANO_UNCUT_KEY, N_("UnCut Text"),
-               IFSCHELP(nano_uncut_msg, FALSE, NANO_NO_KEY),
-               NANO_UNCUT_FKEY, NANO_NO_KEY, NOVIEW, do_uncut_text);
+       add_to_funcs(do_uncut_text, MMAIN, N_("UnCut Text"), nano_uncut_msg,
+           FALSE, NOVIEW);
 
     /* TRANSLATORS: Try to keep this at most 10 characters. */
-    sc_init_one(&main_list, NANO_CURSORPOS_KEY, N_("Cur Pos"),
-       IFSCHELP(nano_cursorpos_msg, FALSE, NANO_NO_KEY),
-       NANO_CURSORPOS_FKEY, NANO_NO_KEY, VIEW, do_cursorpos_void);
+    add_to_funcs(do_cursorpos_void, MMAIN, N_("Cur Pos"), nano_cursorpos_msg,
+       FALSE, VIEW);
 
     /* If we're using restricted mode, spell checking is disabled
      * because it allows reading from or writing to files not specified
      * on the command line. */
     /* TRANSLATORS: Try to keep this at most 10 characters. */
-    sc_init_one(&main_list, NANO_SPELL_KEY, N_("To Spell"),
-       IFSCHELP(nano_spell_msg, TRUE, NANO_NO_KEY), NANO_SPELL_FKEY,
-       NANO_NO_KEY, NOVIEW,
 #ifndef DISABLE_SPELLER
-       !ISSET(RESTRICTED) ? do_spell :
+       if (!ISSET(RESTRICTED))
+           add_to_funcs(do_spell, MMAIN, N_("To Spell"), nano_spell_msg,
+               TRUE, NOVIEW);
 #endif
-       nano_disabled_msg);
 
-    sc_init_one(&main_list, NANO_GOTOLINE_KEY, go_to_line_msg,
-       IFSCHELP(nano_gotoline_msg, FALSE, NANO_GOTOLINE_METAKEY),
-       NANO_GOTOLINE_FKEY, NANO_NO_KEY, VIEW,
-       do_gotolinecolumn_void);
+    add_to_funcs(do_first_line,
+       (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MHELP),
+       first_line_msg, first_line_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_REPLACE_KEY, replace_msg
-#ifndef NANO_TINY
-       , IFSCHELP(nano_replace_msg, FALSE, NANO_REPLACE_METAKEY)
-#else
-       , IFSCHELP(nano_replace_msg, TRUE, NANO_REPLACE_METAKEY)
-#endif
-       , NANO_REPLACE_FKEY, NANO_NO_KEY, NOVIEW, do_replace);
+    add_to_funcs(do_last_line,
+       (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MHELP),
+       last_line_msg, nano_lastline_msg, TRUE, VIEW);
 
-#ifndef NANO_TINY
-    sc_init_one(&main_list, NANO_MARK_KEY, N_("Mark Text"),
-       IFSCHELP(nano_mark_msg, FALSE, NANO_MARK_METAKEY),
-       NANO_MARK_FKEY, NANO_NO_KEY, VIEW, do_mark);
-
-    sc_init_one(&main_list, NANO_NO_KEY, whereis_next_msg,
-       IFSCHELP(nano_whereis_next_msg, TRUE, NANO_WHEREIS_NEXT_KEY),
-       NANO_WHEREIS_NEXT_FKEY, NANO_NO_KEY, VIEW, do_research);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Copy Text"),
-       IFSCHELP(nano_copy_msg, FALSE, NANO_COPY_KEY), NANO_NO_KEY,
-       NANO_COPY_METAKEY, NOVIEW, do_copy_text);
+    add_to_funcs(do_gotolinecolumn_void, (MMAIN|MWHEREIS),
+       go_to_line_msg, nano_gotoline_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Indent Text"),
-       IFSCHELP(nano_indent_msg, FALSE, NANO_INDENT_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, NOVIEW, do_indent_void);
+    add_to_funcs(do_replace, (MMAIN|MWHEREIS), replace_msg, nano_replace_msg,
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Unindent Text"),
-       IFSCHELP(nano_unindent_msg, TRUE, NANO_UNINDENT_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_unindent);
+#ifndef NANO_TINY
+       FALSE,
+#else
+       TRUE,
 #endif
-
-    sc_init_one(&main_list, NANO_FORWARD_KEY, N_("Forward"),
-       IFSCHELP(nano_forward_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_right);
-
-    sc_init_one(&main_list, NANO_BACK_KEY, N_("Back"),
-       IFSCHELP(nano_back_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_left);
+       NOVIEW);
 
 #ifndef NANO_TINY
-    sc_init_one(&main_list, NANO_NEXTWORD_KEY, N_("Next Word"),
-       IFSCHELP(nano_nextword_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_next_word_void);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Prev Word"),
-       IFSCHELP(nano_prevword_msg, FALSE, NANO_PREVWORD_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, do_prev_word_void);
-#endif
+    add_to_funcs(do_mark, MMAIN, N_("Mark Text"), 
+       nano_mark_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_PREVLINE_KEY, N_("Prev Line"),
-       IFSCHELP(nano_prevline_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_up_void);
+    add_to_funcs(do_research, (MMAIN|MBROWSER), whereis_next_msg,
+       nano_whereis_next_msg, TRUE, VIEW);
 
-    sc_init_one(&main_list, NANO_NEXTLINE_KEY, N_("Next Line"),
-       IFSCHELP(nano_nextline_msg, TRUE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_down_void);
+    add_to_funcs(do_copy_text, MMAIN, N_("Copy Text"),
+       nano_copy_msg, FALSE, NOVIEW);
 
-    sc_init_one(&main_list, NANO_HOME_KEY, N_("Home"),
-       IFSCHELP(nano_home_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_home);
+    add_to_funcs(do_indent_void, MMAIN, N_("Indent Text"),
+       nano_indent_msg, FALSE, NOVIEW);
 
-    sc_init_one(&main_list, NANO_END_KEY, N_("End"),
-       IFSCHELP(nano_end_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, do_end);
+    add_to_funcs(do_unindent, MMAIN, N_("Unindent Text"),
+       nano_unindent_msg, TRUE, NOVIEW);
 
-#ifndef DISABLE_JUSTIFY
-    sc_init_one(&main_list, NANO_NO_KEY, beg_of_par_msg,
-       IFSCHELP(nano_parabegin_msg, FALSE, NANO_PARABEGIN_METAKEY),
-       NANO_NO_KEY, NANO_PARABEGIN_METAKEY2, VIEW, do_para_begin_void);
-
-    sc_init_one(&main_list, NANO_NO_KEY, end_of_par_msg,
-       IFSCHELP(nano_paraend_msg, FALSE, NANO_PARAEND_METAKEY),
-       NANO_NO_KEY, NANO_PARAEND_METAKEY2, VIEW, do_para_end_void);
 #endif
 
-    sc_init_one(&main_list, NANO_NO_KEY, first_line_msg,
-       IFSCHELP(nano_firstline_msg, FALSE, NANO_FIRSTLINE_METAKEY),
-       NANO_NO_KEY, NANO_FIRSTLINE_METAKEY2, VIEW, do_first_line);
 
-    sc_init_one(&main_list, NANO_NO_KEY, last_line_msg,
-       IFSCHELP(nano_lastline_msg, TRUE, NANO_LASTLINE_METAKEY),
-       NANO_NO_KEY, NANO_LASTLINE_METAKEY2, VIEW, do_last_line);
+    add_to_funcs(do_right, MMAIN, N_("Forward"), nano_forward_msg,
+       FALSE, VIEW);
 
-#ifndef NANO_TINY
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Find Other Bracket"),
-       IFSCHELP(nano_bracket_msg, FALSE, NANO_BRACKET_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, do_find_bracket);
+    add_to_funcs(do_left, MMAIN, N_("Back"), nano_back_msg,
+       FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Scroll Up"),
-       IFSCHELP(nano_scrollup_msg, FALSE, NANO_SCROLLUP_KEY),
-       NANO_NO_KEY, NANO_SCROLLUP_METAKEY, VIEW, do_scroll_up);
+#ifndef NANO_TINY
+    add_to_funcs(do_next_word_void, MMAIN, N_("Next Word"),
+       nano_nextword_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Scroll Down"),
-       IFSCHELP(nano_scrolldown_msg, TRUE, NANO_SCROLLDOWN_KEY),
-       NANO_NO_KEY, NANO_SCROLLDOWN_METAKEY, VIEW, do_scroll_down);
+    add_to_funcs(do_prev_word_void, MMAIN, N_("Prev Word"),
+       nano_prevword_msg, FALSE, VIEW);
 #endif
 
-#ifdef ENABLE_MULTIBUFFER
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Previous File"),
-       IFSCHELP(nano_prevfile_msg, FALSE, NANO_PREVFILE_KEY),
-       NANO_NO_KEY, NANO_PREVFILE_METAKEY, VIEW,
-       switch_to_prev_buffer_void);
+    add_to_funcs(do_up_void, (MMAIN|MHELP), N_("Prev Line"),
+       nano_prevline_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Next File"),
-       IFSCHELP(nano_nextfile_msg, TRUE, NANO_NEXTFILE_KEY),
-       NANO_NO_KEY, NANO_NEXTFILE_METAKEY, VIEW,
-       switch_to_next_buffer_void);
-#endif
+    add_to_funcs(do_down_void, (MMAIN|MHELP), N_("Next Line"),
+       nano_nextline_msg, TRUE, VIEW);
 
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Verbatim Input"),
-       IFSCHELP(nano_verbatim_msg, FALSE, NANO_VERBATIM_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_verbatim_input);
+    add_to_funcs(do_home, MMAIN, N_("Home"), nano_home_msg,
+       FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_TAB_KEY, N_("Tab"),
-       IFSCHELP(nano_tab_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, NOVIEW, do_tab);
+    add_to_funcs(do_end, MMAIN, N_("End"), nano_end_msg,
+       FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_ENTER_KEY, N_("Enter"),
-       IFSCHELP(nano_enter_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, NOVIEW, do_enter);
-
-    sc_init_one(&main_list, NANO_DELETE_KEY, N_("Delete"),
-       IFSCHELP(nano_delete_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, NOVIEW, do_delete);
+#ifndef DISABLE_JUSTIFY
+    add_to_funcs(do_para_begin_void, (MMAIN|MWHEREIS), beg_of_par_msg,
+       nano_parabegin_msg, FALSE, VIEW);
 
-    sc_init_one(&main_list, NANO_BACKSPACE_KEY, N_("Backspace")
-#ifndef NANO_TINY
-       , IFSCHELP(nano_backspace_msg, FALSE, NANO_NO_KEY)
-#else
-       , IFSCHELP(nano_backspace_msg, TRUE, NANO_NO_KEY)
+    add_to_funcs(do_para_end_void, (MMAIN|MWHEREIS), end_of_par_msg,
+       nano_paraend_msg, FALSE, VIEW);
 #endif
-       , NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_backspace);
 
 #ifndef NANO_TINY
-    sc_init_one(&main_list, NANO_NO_KEY, N_("CutTillEnd"),
-       IFSCHELP(nano_cut_till_end_msg, TRUE, NANO_CUTTILLEND_METAKEY),
-       NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_cut_till_end);
-#endif
+    add_to_funcs(do_find_bracket, MMAIN, _("Find Other Bracket"),
+       nano_bracket_msg, FALSE, VIEW);
 
-#ifndef DISABLE_JUSTIFY
-    sc_init_one(&main_list, NANO_NO_KEY, fulljstify_msg,
-       IFSCHELP(nano_fulljustify_msg, FALSE, NANO_FULLJUSTIFY_METAKEY),
-       NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_full_justify);
-#endif
+    add_to_funcs(do_scroll_up, MMAIN, N_("Scroll Up"),
+       nano_scrollup_msg, FALSE, VIEW);
 
-#ifndef NANO_TINY
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Word Count"),
-       IFSCHELP(nano_wordcount_msg, FALSE, NANO_WORDCOUNT_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, do_wordlinechar_count);
+    add_to_funcs(do_scroll_down, MMAIN, N_("Scroll Down"),
+       nano_scrolldown_msg, FALSE, VIEW);
 #endif
 
-    sc_init_one(&main_list, NANO_REFRESH_KEY, refresh_msg
+#ifdef ENABLE_MULTIBUFFER
+    add_to_funcs(switch_to_prev_buffer_void, MMAIN, _("Previous File"),
+       nano_prevfile_msg, FALSE, VIEW);
+    add_to_funcs(switch_to_next_buffer_void, MMAIN, N_("Next File"),
+       nano_nextfile_msg, TRUE, VIEW);
+#endif
+
+    add_to_funcs(do_verbatim_input, MMAIN, N_("Verbatim Input"),
+       nano_verbatim_msg, FALSE, NOVIEW);
+    add_to_funcs(do_tab, MMAIN, N_("Tab"), nano_tab_msg,
+       FALSE, NOVIEW);
+    add_to_funcs(do_enter, MMAIN, N_("Enter"), nano_enter_msg,
+       FALSE, NOVIEW);
+    add_to_funcs(do_delete, MMAIN, N_("Delete"), nano_delete_msg,
+       FALSE, NOVIEW);
+    add_to_funcs(do_backspace, MMAIN, N_("Backspace"), nano_backspace_msg,
 #ifndef NANO_TINY
-       , IFSCHELP(nano_refresh_msg, TRUE, NANO_NO_KEY)
+       FALSE,
 #else
-       , IFSCHELP(nano_refresh_msg, FALSE, NANO_NO_KEY)
+       TRUE,
 #endif
-       , NANO_NO_KEY, NANO_NO_KEY, VIEW, total_refresh);
+       VIEW);
 
-    free_shortcutage(&whereis_list);
-
-    sc_init_one(&whereis_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
+#ifndef NANO_TINY
+    add_to_funcs(do_cut_till_end, MMAIN, N_("CutTillEnd"),
+       nano_cut_till_end_msg, TRUE, NOVIEW);
 #endif
-       );
-
-    sc_init_one(&whereis_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&whereis_list, NANO_FIRSTLINE_KEY, first_line_msg,
-       IFSCHELP(nano_firstline_msg, FALSE, NANO_FIRSTLINE_METAKEY),
-       NANO_FIRSTLINE_FKEY, NANO_FIRSTLINE_METAKEY2, VIEW,
-       do_first_line);
-
-    sc_init_one(&whereis_list, NANO_LASTLINE_KEY, last_line_msg,
-       IFSCHELP(nano_lastline_msg, FALSE, NANO_LASTLINE_METAKEY),
-       NANO_LASTLINE_FKEY, NANO_LASTLINE_METAKEY2, VIEW, do_last_line);
 
-    sc_init_one(&whereis_list, NANO_TOOTHERSEARCH_KEY, replace_msg,
-       IFSCHELP(nano_replace_msg, FALSE, NANO_NO_KEY),
-       NANO_REPLACE_FKEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&whereis_list, NANO_TOGOTOLINE_KEY, go_to_line_msg,
-       IFSCHELP(nano_gotoline_msg, FALSE, NANO_NO_KEY),
-       NANO_GOTOLINE_FKEY, NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs(xon_complaint, MMAIN, "", "", FALSE, VIEW);
+    add_to_funcs(xoff_complaint, MMAIN, "", "", FALSE, VIEW);
 
 #ifndef DISABLE_JUSTIFY
-    sc_init_one(&whereis_list, NANO_PARABEGIN_KEY, beg_of_par_msg,
-       IFSCHELP(nano_parabegin_msg, FALSE, NANO_PARABEGIN_METAKEY),
-       NANO_NO_KEY, NANO_PARABEGIN_METAKEY2, VIEW, do_para_begin_void);
-
-    sc_init_one(&whereis_list, NANO_PARAEND_KEY, end_of_par_msg,
-       IFSCHELP(nano_paraend_msg, FALSE, NANO_PARAEND_METAKEY),
-       NANO_NO_KEY, NANO_PARAEND_METAKEY2, VIEW, do_para_end_void);
+    add_to_funcs(do_full_justify, (MMAIN|MWHEREIS), fulljstify_msg,
+       nano_fulljustify_msg, FALSE, NOVIEW);
 #endif
 
 #ifndef NANO_TINY
-    sc_init_one(&whereis_list, NANO_NO_KEY, case_sens_msg,
-       IFSCHELP(nano_case_msg, FALSE, TOGGLE_CASE_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&whereis_list, NANO_NO_KEY, backwards_msg,
-       IFSCHELP(nano_reverse_msg, FALSE, TOGGLE_BACKWARDS_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-#endif
-
-#ifdef HAVE_REGEX_H
-    sc_init_one(&whereis_list, NANO_NO_KEY, regexp_msg,
-       IFSCHELP(nano_regexp_msg, FALSE, NANO_REGEXP_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs(do_wordlinechar_count, MMAIN, N_("Word Count"),
+       nano_wordcount_msg, FALSE, VIEW);
 #endif
 
+    add_to_funcs(total_refresh, (MMAIN|MHELP), refresh_msg, refresh_msg,
 #ifndef NANO_TINY
-    sc_init_one(&whereis_list, NANO_PREVLINE_KEY, prev_history_msg,
-       IFSCHELP(nano_prev_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&whereis_list, NANO_NEXTLINE_KEY, next_history_msg,
-       IFSCHELP(nano_next_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-#endif
-
-#ifndef DISABLE_JUSTIFY
-    sc_init_one(&whereis_list, NANO_FULLJUSTIFY_KEY, fulljstify_msg,
-       IFSCHELP(nano_fulljustify_msg, FALSE, NANO_FULLJUSTIFY_METAKEY),
-       NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_full_justify);
-#endif
-
-    free_shortcutage(&replace_list);
-
-    sc_init_one(&replace_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
+       TRUE,
 #else
-       nano_disabled_msg
+       FALSE,
 #endif
-       );
-
-    sc_init_one(&replace_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&replace_list, NANO_FIRSTLINE_KEY, first_line_msg,
-       IFSCHELP(nano_firstline_msg, FALSE, NANO_FIRSTLINE_METAKEY),
-       NANO_FIRSTLINE_FKEY, NANO_FIRSTLINE_METAKEY2, VIEW,
-       do_first_line);
-
-    sc_init_one(&replace_list, NANO_LASTLINE_KEY, last_line_msg,
-       IFSCHELP(nano_lastline_msg, FALSE, NANO_LASTLINE_METAKEY),
-       NANO_LASTLINE_FKEY, NANO_LASTLINE_METAKEY2, VIEW, do_last_line);
-
-    /* TRANSLATORS: Try to keep this at most 12 characters. */
-    sc_init_one(&replace_list, NANO_TOOTHERSEARCH_KEY, N_("No Replace"),
-       IFSCHELP(nano_whereis_msg, FALSE, NANO_NO_KEY),
-       NANO_REPLACE_FKEY, NANO_NO_KEY, VIEW, NULL);
+       VIEW);
 
 #ifndef NANO_TINY
-    sc_init_one(&replace_list, NANO_NO_KEY, case_sens_msg,
-       IFSCHELP(nano_case_msg, FALSE, TOGGLE_CASE_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) case_sens_msg,
+       (MWHEREIS|MREPLACE|MWHEREISFILE),
+       case_sens_msg, nano_case_msg, FALSE, VIEW);
 
-    sc_init_one(&replace_list, NANO_NO_KEY, backwards_msg,
-       IFSCHELP(nano_reverse_msg, FALSE, TOGGLE_BACKWARDS_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) backwards_msg,
+       (MWHEREIS|MREPLACE|MWHEREISFILE),
+       backwards_msg, nano_reverse_msg, FALSE, VIEW);
 #endif
 
 #ifdef HAVE_REGEX_H
-    sc_init_one(&replace_list, NANO_NO_KEY, regexp_msg,
-       IFSCHELP(nano_regexp_msg, FALSE, NANO_REGEXP_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) regexp_msg,
+       (MWHEREIS|MREPLACE|MWHEREISFILE),
+       regexp_msg, nano_regexp_msg, FALSE, VIEW);
 #endif
 
 #ifndef NANO_TINY
-    sc_init_one(&replace_list, NANO_PREVLINE_KEY, prev_history_msg,
-       IFSCHELP(nano_prev_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) prev_history_msg,
+       (MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE),
+       prev_history_msg, nano_prev_history_msg, FALSE, VIEW);
 
-    sc_init_one(&replace_list, NANO_NEXTLINE_KEY, next_history_msg,
-       IFSCHELP(nano_next_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) next_history_msg,
+       (MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE),
+       next_history_msg, nano_next_history_msg, FALSE, VIEW);
 #endif
 
-    free_shortcutage(&replace_list_2);
+    add_to_funcs((void *) no_replace_msg, MREPLACE,
+       no_replace_msg, nano_whereis_msg, FALSE, VIEW);
 
-    sc_init_one(&replace_list_2, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
-#endif
-       );
-
-    sc_init_one(&replace_list_2, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&replace_list_2, NANO_FIRSTLINE_KEY, first_line_msg,
-       IFSCHELP(nano_firstline_msg, FALSE, NANO_FIRSTLINE_METAKEY),
-       NANO_FIRSTLINE_FKEY, NANO_FIRSTLINE_METAKEY2, VIEW,
-       do_first_line);
-
-    sc_init_one(&replace_list_2, NANO_LASTLINE_KEY, last_line_msg,
-       IFSCHELP(nano_lastline_msg, FALSE, NANO_LASTLINE_METAKEY),
-       NANO_LASTLINE_FKEY, NANO_LASTLINE_METAKEY2, VIEW, do_last_line);
-
-#ifndef NANO_TINY
-    sc_init_one(&replace_list_2, NANO_PREVLINE_KEY, prev_history_msg,
-       IFSCHELP(nano_prev_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&replace_list_2, NANO_NEXTLINE_KEY, next_history_msg,
-       IFSCHELP(nano_next_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-#endif
-
-    free_shortcutage(&gotoline_list);
-
-    sc_init_one(&gotoline_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
-#endif
-       );
-
-    sc_init_one(&gotoline_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&gotoline_list, NANO_FIRSTLINE_KEY, first_line_msg,
-       IFSCHELP(nano_firstline_msg, FALSE, NANO_FIRSTLINE_METAKEY),
-       NANO_FIRSTLINE_FKEY, NANO_FIRSTLINE_METAKEY2, VIEW,
-       do_first_line);
-
-    sc_init_one(&gotoline_list, NANO_LASTLINE_KEY, last_line_msg,
-       IFSCHELP(nano_lastline_msg, FALSE, NANO_LASTLINE_METAKEY),
-       NANO_LASTLINE_FKEY, NANO_LASTLINE_METAKEY2, VIEW, do_last_line);
-
-    sc_init_one(&gotoline_list, NANO_TOOTHERWHEREIS_KEY,
-       N_("Go To Text"), IFSCHELP(nano_whereis_msg, FALSE,
-       NANO_NO_KEY), NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-
-    free_shortcutage(&writefile_list);
-
-    sc_init_one(&writefile_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
-#endif
-       );
-
-    sc_init_one(&writefile_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) gototext_msg, MGOTOLINE,
+       gototext_msg, nano_whereis_msg, FALSE, VIEW);
 
 #ifndef DISABLE_BROWSER
-    /* If we're using restricted mode, the file browser is disabled.
-     * It's useless since inserting files is disabled. */
     if (!ISSET(RESTRICTED))
-       sc_init_one(&writefile_list, NANO_TOFILES_KEY, to_files_msg,
-               IFSCHELP(nano_tofiles_msg, FALSE, NANO_NO_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+       add_to_funcs((void *) to_files_msg,
+           (MGOTOLINE|MINSERTFILE),
+           to_files_msg, nano_tofiles_msg, FALSE, VIEW);
 #endif
 
 #ifndef NANO_TINY
@@ -946,279 +867,225 @@ void shortcut_init(bool unjustify)
      * specified on the command line, and the fifth is useless since
      * backups are disabled. */
     if (!ISSET(RESTRICTED))
-       /* TRANSLATORS: Try to keep this at most 16 characters. */
-       sc_init_one(&writefile_list, NANO_NO_KEY, N_("DOS Format"),
-               IFSCHELP(nano_dos_msg, FALSE, TOGGLE_DOS_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+        add_to_funcs((void *) dos_format_msg, MWRITEFILE,
+            dos_format_msg, nano_dos_msg, FALSE, NOVIEW);
 
     if (!ISSET(RESTRICTED))
-       /* TRANSLATORS: Try to keep this at most 16 characters. */
-       sc_init_one(&writefile_list, NANO_NO_KEY, N_("Mac Format"),
-               IFSCHELP(nano_mac_msg, FALSE, TOGGLE_MAC_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
-#endif
+        add_to_funcs((void *) mac_format_msg, MWRITEFILE,
+            mac_format_msg, nano_mac_msg, FALSE, NOVIEW);
 
     if (!ISSET(RESTRICTED))
-       /* TRANSLATORS: Try to keep this at most 16 characters. */
-       sc_init_one(&writefile_list, NANO_NO_KEY, N_("Append"),
-               IFSCHELP(nano_append_msg, FALSE, NANO_APPEND_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+        add_to_funcs((void *) append_msg, MWRITEFILE,
+            append_msg, nano_append_msg, FALSE, NOVIEW);
 
     if (!ISSET(RESTRICTED))
-       /* TRANSLATORS: Try to keep this at most 16 characters. */
-       sc_init_one(&writefile_list, NANO_NO_KEY, N_("Prepend"),
-               IFSCHELP(nano_prepend_msg, FALSE, NANO_PREPEND_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+        add_to_funcs((void *) prepend_msg, MWRITEFILE,
+            prepend_msg, nano_prepend_msg, FALSE, NOVIEW);
 
-#ifndef NANO_TINY
     if (!ISSET(RESTRICTED))
-       /* TRANSLATORS: Try to keep this at most 16 characters. */
-       sc_init_one(&writefile_list, NANO_NO_KEY, N_("Backup File"),
-               IFSCHELP(nano_backup_msg, FALSE, TOGGLE_BACKUP_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
-#endif
-
-    free_shortcutage(&insertfile_list);
-
-    sc_init_one(&insertfile_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
-#endif
-       );
-
-    sc_init_one(&insertfile_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-#ifndef DISABLE_BROWSER
-    /* If we're using restricted mode, the file browser is disabled.
-     * It's useless since inserting files is disabled. */
-    if (!ISSET(RESTRICTED))
-       sc_init_one(&insertfile_list, NANO_TOFILES_KEY, to_files_msg,
-               IFSCHELP(nano_tofiles_msg, FALSE, NANO_NO_KEY),
-               NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+        add_to_funcs((void *) backup_file_msg, MWRITEFILE,
+            backup_file_msg, nano_backup_msg, FALSE, NOVIEW);
 #endif
 
 #ifndef NANO_TINY
     /* If we're using restricted mode, command execution is disabled.
      * It's useless since inserting files is disabled. */
     if (!ISSET(RESTRICTED))
-       sc_init_one(&insertfile_list, NANO_TOOTHERINSERT_KEY,
-               /* TRANSLATORS: Try to keep this at most 22
-                * characters. */
-               N_("Execute Command"), IFSCHELP(nano_execute_msg, FALSE,
-               NANO_NO_KEY), NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+        add_to_funcs((void *) ext_cmd_msg, MINSERTFILE,
+           ext_cmd_msg, nano_execute_msg, FALSE, NOVIEW);
 
 #ifdef ENABLE_MULTIBUFFER
     /* If we're using restricted mode, the multibuffer toggle is
      * disabled.  It's useless since inserting files is disabled. */
     if (!ISSET(RESTRICTED))
-       sc_init_one(&insertfile_list, NANO_NO_KEY, new_buffer_msg,
-               IFSCHELP(nano_multibuffer_msg, FALSE,
-               TOGGLE_MULTIBUFFER_KEY), NANO_NO_KEY, NANO_NO_KEY,
-               NOVIEW, NULL);
-#endif
+       add_to_funcs((void *) new_buffer_msg, MWRITEFILE,
+       new_buffer_msg, nano_multibuffer_msg, FALSE, NOVIEW);
 #endif
 
-#ifndef NANO_TINY
-    free_shortcutage(&extcmd_list);
-
-    sc_init_one(&extcmd_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
-#endif
-       );
-
-    sc_init_one(&extcmd_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&extcmd_list, NANO_TOOTHERINSERT_KEY, N_("Insert File"),
-       IFSCHELP(nano_insert_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *)  insert_file_msg, MEXTCMD,
+       insert_file_msg, nano_insert_msg, FALSE, VIEW);
 
 #ifdef ENABLE_MULTIBUFFER
-    sc_init_one(&extcmd_list, NANO_NO_KEY, new_buffer_msg,
-       IFSCHELP(nano_multibuffer_msg, FALSE, TOGGLE_MULTIBUFFER_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, NOVIEW, NULL);
+     add_to_funcs((void *) new_buffer_msg, MEXTCMD,
+       new_buffer_msg, nano_multibuffer_msg, FALSE, NOVIEW);
 #endif
 #endif
 
 #ifndef DISABLE_HELP
-    free_shortcutage(&help_list);
-
-    sc_init_one(&help_list, NANO_REFRESH_KEY, refresh_msg,
-       IFSCHELP(nano_refresh_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_EXIT_KEY, exit_msg,
-       IFSCHELP(nano_exit_msg, FALSE, NANO_NO_KEY), NANO_EXIT_FKEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_PREVPAGE_KEY, prev_page_msg,
-       IFSCHELP(nano_prevpage_msg, FALSE, NANO_NO_KEY),
-       NANO_PREVPAGE_FKEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_NEXTPAGE_KEY, next_page_msg,
-       IFSCHELP(nano_nextpage_msg, FALSE, NANO_NO_KEY),
-       NANO_NEXTPAGE_FKEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_PREVLINE_KEY, N_("Prev Line"),
-       IFSCHELP(nano_prevline_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_NEXTLINE_KEY, N_("Next Line"),
-       IFSCHELP(nano_nextline_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_NO_KEY, first_line_msg,
-       IFSCHELP(nano_firstline_msg, FALSE, NANO_FIRSTLINE_METAKEY),
-       NANO_NO_KEY, NANO_FIRSTLINE_METAKEY2, VIEW, NULL);
-
-    sc_init_one(&help_list, NANO_NO_KEY, last_line_msg,
-       IFSCHELP(nano_lastline_msg, TRUE, NANO_LASTLINE_METAKEY),
-       NANO_NO_KEY, NANO_LASTLINE_METAKEY2, VIEW, NULL);
-#endif
-
-#ifndef DISABLE_SPELLER
-    free_shortcutage(&spell_list);
-
-    sc_init_one(&spell_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_help_void
-#else
-       nano_disabled_msg
-#endif
-       );
-
-    sc_init_one(&spell_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) refresh_msg, MHELP,
+       refresh_msg, nano_refresh_msg, FALSE, VIEW);
 #endif
 
 #ifndef DISABLE_BROWSER
-    free_shortcutage(&browser_list);
-
-    sc_init_one(&browser_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&browser_list, NANO_EXIT_KEY, exit_msg,
-       IFSCHELP(nano_exitbrowser_msg, FALSE, NANO_NO_KEY),
-       NANO_EXIT_FKEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&browser_list, NANO_WHEREIS_KEY, whereis_msg,
-       IFSCHELP(nano_whereis_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&browser_list, NANO_NO_KEY, whereis_next_msg,
-       IFSCHELP(nano_whereis_next_msg, FALSE, NANO_WHEREIS_NEXT_KEY),
-       NANO_WHEREIS_NEXT_FKEY, NANO_NO_KEY, VIEW, NULL);
 
-    sc_init_one(&browser_list, NANO_PREVPAGE_KEY, prev_page_msg,
-       IFSCHELP(nano_prevpage_msg, FALSE, NANO_NO_KEY),
-       NANO_PREVPAGE_FKEY, NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) first_file_msg,
+       (MBROWSER|MWHEREISFILE),
+       first_file_msg, nano_firstfile_msg, FALSE, VIEW);
 
-    sc_init_one(&browser_list, NANO_NEXTPAGE_KEY, next_page_msg,
-       IFSCHELP(nano_nextpage_msg, FALSE, NANO_NO_KEY),
-       NANO_NEXTPAGE_FKEY, NANO_NO_KEY, VIEW, NULL);
+    add_to_funcs((void *) last_file_msg,
+       (MBROWSER|MWHEREISFILE),
+       last_file_msg, nano_lastfile_msg, FALSE, VIEW);
 
-    sc_init_one(&browser_list, NANO_NO_KEY, first_file_msg,
-       IFSCHELP(nano_firstfile_msg, FALSE, NANO_FIRSTFILE_METAKEY),
-       NANO_NO_KEY, NANO_FIRSTFILE_METAKEY2, VIEW, NULL);
-
-    sc_init_one(&browser_list, NANO_NO_KEY, last_file_msg,
-       IFSCHELP(nano_lastfile_msg, FALSE, NANO_LASTFILE_METAKEY),
-       NANO_NO_KEY, NANO_LASTFILE_METAKEY2, VIEW, NULL);
-
-    /* TRANSLATORS: Try to keep this at most 12 characters. */
-    sc_init_one(&browser_list, NANO_GOTODIR_KEY, N_("Go To Dir"),
-       IFSCHELP(nano_gotodir_msg, FALSE, NANO_GOTODIR_METAKEY),
-       NANO_GOTODIR_FKEY, NANO_NO_KEY, VIEW, NULL);
-
-    free_shortcutage(&whereis_file_list);
-
-    sc_init_one(&whereis_file_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_browser_help
-#else
-       nano_disabled_msg
+    add_to_funcs((void *) goto_dir_msg, MBROWSER,
+       goto_dir_msg, nano_gotodir_msg, FALSE, VIEW);
 #endif
-       );
-
-    sc_init_one(&whereis_file_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&whereis_file_list, NANO_FIRSTFILE_KEY, first_file_msg,
-       IFSCHELP(nano_firstfile_msg, FALSE, NANO_FIRSTFILE_METAKEY),
-       NANO_FIRSTFILE_FKEY, NANO_FIRSTFILE_METAKEY2, VIEW,
-       do_first_file);
-
-    sc_init_one(&whereis_file_list, NANO_LASTFILE_KEY, last_file_msg,
-       IFSCHELP(nano_lastfile_msg, FALSE, NANO_LASTFILE_METAKEY),
-       NANO_LASTFILE_FKEY, NANO_LASTFILE_METAKEY2, VIEW, do_last_file);
 
-#ifndef NANO_SMALL
-    sc_init_one(&whereis_file_list, NANO_NO_KEY, case_sens_msg,
-       IFSCHELP(nano_case_msg, FALSE, TOGGLE_CASE_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+    currmenu = MMAIN;
 
-    sc_init_one(&whereis_file_list, NANO_NO_KEY, backwards_msg,
-       IFSCHELP(nano_reverse_msg, FALSE, TOGGLE_BACKWARDS_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-#endif
-
-#ifdef HAVE_REGEX_H
-    sc_init_one(&whereis_file_list, NANO_NO_KEY, regexp_msg,
-       IFSCHELP(nano_regexp_msg, FALSE, NANO_REGEXP_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
-#endif
-
-#ifndef NANO_SMALL
-    sc_init_one(&whereis_file_list, NANO_PREVLINE_KEY, prev_history_msg,
-       IFSCHELP(nano_prev_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
-
-    sc_init_one(&whereis_file_list, NANO_NEXTLINE_KEY, next_history_msg,
-       IFSCHELP(nano_next_history_msg, FALSE, NANO_NO_KEY),
-       NANO_NO_KEY, NANO_NO_KEY, VIEW, NULL);
+#ifndef NANO_TINY
+    add_to_sclist(MALL, "^G", do_help_void, 0, TRUE);
+    add_to_sclist(MALL, "F1", do_help_void, 0, TRUE);
+#endif
+    add_to_sclist(MMAIN, "^X", do_exit, 0, TRUE);
+    add_to_sclist(MMAIN, "F2", do_exit, 0, TRUE);
+    add_to_sclist(MHELP, "^X", do_exit, 0, TRUE);
+    add_to_sclist(MHELP, "F2", do_exit, 0, TRUE);
+    add_to_sclist(MMAIN, "^_", do_gotolinecolumn_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F13", do_gotolinecolumn_void, 0, TRUE);
+    add_to_sclist(MMAIN, "^O", do_writeout_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F3", do_writeout_void, 0, TRUE);
+#ifndef NANO_TINY
+    add_to_sclist(MMAIN, "^J", do_justify_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F4", do_justify_void, 0, TRUE);
+#endif
+    add_to_sclist(MMAIN, "^R", do_insertfile_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F5", do_insertfile_void, 0, TRUE);
+    add_to_sclist(MMAIN, "^W", do_search, 0, TRUE);
+    add_to_sclist(MMAIN, "F6", do_search, 0, TRUE);
+    add_to_sclist(MMAIN, "^Y", do_page_up, 0, TRUE);
+    add_to_sclist(MMAIN, "F7", do_page_up, 0, TRUE);
+    add_to_sclist(MMAIN, "^V", do_page_down, 0, TRUE);
+    add_to_sclist(MMAIN, "F8", do_page_down, 0, TRUE);
+    add_to_sclist(MMAIN, "^K", do_cut_text_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F9", do_cut_text_void, 0, TRUE);
+    add_to_sclist(MMAIN, "^U", do_uncut_text, 0, TRUE);
+    add_to_sclist(MMAIN, "F10", do_uncut_text, 0, TRUE);
+    add_to_sclist(MMAIN, "^C", do_cursorpos_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F11", do_cursorpos_void, 0, TRUE);
+#ifndef NANO_TINY
+    add_to_sclist(MMAIN, "^T", do_spell, 0, TRUE);
+    add_to_sclist(MMAIN, "F12", do_spell, 0, TRUE);
+#endif
+    add_to_sclist(MMAIN, "^_", do_gotolinecolumn_void, 0, TRUE);
+    add_to_sclist(MMAIN, "F13", do_gotolinecolumn_void, 0, TRUE);
+    add_to_sclist(MMAIN, "M-G", do_gotolinecolumn_void, 0, TRUE);
+    add_to_sclist(MMAIN, "^\\", do_replace, 0, TRUE);
+    add_to_sclist(MMAIN, "F14", do_replace, 0, TRUE);
+    add_to_sclist(MMAIN, "M-R", do_replace, 0, TRUE);
+    add_to_sclist(MWHEREIS, "^R", do_replace, 0, FALSE);
+    add_to_sclist(MREPLACE, "^R", (void *) no_replace_msg, 0, FALSE);
+    add_to_sclist(MWHEREIS, "^T", do_gotolinecolumn_void, 0, TRUE);
+#ifndef NANO_TINY
+    add_to_sclist(MMAIN, "^^", do_mark, 0, TRUE);
+    add_to_sclist(MMAIN, "F15", do_mark, 0, TRUE);
+    add_to_sclist(MMAIN, "M-A", do_mark, 0, TRUE);
+    add_to_sclist(MALL, "F16", do_research, 0, TRUE);
+    add_to_sclist(MALL, "M-W", do_research, 0, TRUE);
+    add_to_sclist(MMAIN, "M-^", do_copy_text, 0, TRUE);
+    add_to_sclist(MMAIN, "M-6", do_copy_text, 0, TRUE);
+    add_to_sclist(MMAIN, "M-}", do_indent_void, 0, TRUE);
+    add_to_sclist(MMAIN, "M-{", do_unindent, 0, TRUE);
+    add_to_sclist(MMAIN|MBROWSER|MHELP, "^F", do_right, 0, TRUE);
+    add_to_sclist(MMAIN|MBROWSER|MHELP, "^B", do_left, 0, TRUE);
+    add_to_sclist(MMAIN, "^Space", do_next_word_void, 0, TRUE);
+    add_to_sclist(MMAIN, "M-Space", do_prev_word_void, 0, TRUE);
+#endif
+    add_to_sclist(MALL, "^Q", xon_complaint, 0, TRUE);
+    add_to_sclist(MALL, "^X", xoff_complaint, 0, TRUE);
+    add_to_sclist(MALL, "^P", do_up_void, 0, TRUE);
+    add_to_sclist(MALL, "^N", do_down_void, 0, TRUE);
+    add_to_sclist(MALL, "^A", do_home, 0, TRUE);
+    add_to_sclist(MALL, "^E", do_end, 0, TRUE);
+    add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
+       "^W", do_para_begin_void, 0, TRUE);
+    add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
+       "^O", do_para_end_void, 0, TRUE);
+    add_to_sclist(MALL, "M-(", do_para_begin_void, 0, TRUE);
+    add_to_sclist(MALL, "M-9", do_para_begin_void, 0, TRUE);
+    add_to_sclist(MALL, "M-)", do_para_end_void, 0, TRUE);
+    add_to_sclist(MALL, "M-0", do_para_end_void, 0, TRUE);
+    add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
+       "^Y", do_first_line, 0, TRUE);
+    add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
+       "^V", do_last_line, 0, TRUE);
+
+    add_to_sclist(MWHEREIS,
+       "M-C", (void *) case_sens_msg, 0, FALSE);
+    add_to_sclist(MREPLACE,
+       "M-C", (void *) case_sens_msg, 0, FALSE);
+    add_to_sclist(MREPLACE2,
+       "M-C", (void *) case_sens_msg, 0, FALSE);
+    add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
+       "M-B", (void *) backwards_msg, 0, FALSE);
+    add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
+       "M-R", (void *) regexp_msg, 0, FALSE);
+
+    add_to_sclist(MMAIN, "M-\\", do_first_line, 0, TRUE);
+    add_to_sclist(MMAIN, "M-|", do_first_line, 0, TRUE);
+    add_to_sclist(MMAIN, "M-/", do_last_line, 0, TRUE);
+    add_to_sclist(MMAIN, "M-?", do_last_line, 0, TRUE);
+#ifndef NANO_TINY
+    add_to_sclist(MMAIN, "M-[", do_find_bracket, 0, TRUE);
+    add_to_sclist(MMAIN, "M--", do_scroll_up, 0, TRUE);
+    add_to_sclist(MMAIN, "M-_", do_scroll_up, 0, TRUE);
+    add_to_sclist(MMAIN, "M-+", do_scroll_down, 0, TRUE);
+    add_to_sclist(MMAIN, "M-=", do_scroll_down, 0, TRUE);
 #endif
 
-    free_shortcutage(&gotodir_list);
-
-    sc_init_one(&gotodir_list, NANO_HELP_KEY, get_help_msg,
-       IFSCHELP(nano_help_msg, FALSE, NANO_NO_KEY), NANO_HELP_FKEY,
-       NANO_NO_KEY, VIEW,
-#ifndef DISABLE_HELP
-       do_browser_help
-#else
-       nano_disabled_msg
-#endif
-       );
+#ifdef ENABLE_MULTIBUFFER
+    add_to_sclist(MMAIN, "M-<", switch_to_prev_buffer_void, 0, TRUE);
+    add_to_sclist(MMAIN, "M-,", switch_to_prev_buffer_void, 0, TRUE);
+    add_to_sclist(MMAIN, "M->", switch_to_next_buffer_void, 0, TRUE);
+    add_to_sclist(MMAIN, "M-.", switch_to_next_buffer_void, 0, TRUE);
+#endif
+    add_to_sclist(MMAIN, "M-V", do_verbatim_input, 0, TRUE);
+    add_to_sclist(MALL, "^I", do_tab, 0, TRUE);
+    add_to_sclist(MALL, "^M", do_enter, 0, TRUE);
+    add_to_sclist(MALL, "^D", do_delete, 0, TRUE);
+    add_to_sclist(MALL, "^H", do_backspace, 0, TRUE);
+    add_to_sclist(MALL, "M-T", do_cut_till_end, 0, TRUE);
+#ifndef NANO_TINY
+    add_to_sclist(MALL, "M-J", do_full_justify, 0, TRUE);
+    add_to_sclist(MALL, "M-D", do_wordlinechar_count, 0, TRUE);
+    add_to_sclist(MMAIN, "M-X", do_toggle, NO_HELP, TRUE);
+    add_to_sclist(MMAIN, "M-C", do_toggle, CONST_UPDATE, TRUE);
+    add_to_sclist(MMAIN, "M-O", do_toggle, MORE_SPACE, TRUE);
+    add_to_sclist(MMAIN, "M-S", do_toggle, SMOOTH_SCROLL, TRUE);
+    add_to_sclist(MMAIN, "M-P", do_toggle, WHITESPACE_DISPLAY, TRUE);
+    add_to_sclist(MMAIN, "M-Y", do_toggle, NO_COLOR_SYNTAX, TRUE);
+    add_to_sclist(MMAIN, "M-H", do_toggle, SMART_HOME, TRUE);
+    add_to_sclist(MMAIN, "M-I", do_toggle, AUTOINDENT, TRUE);
+    add_to_sclist(MMAIN, "M-K", do_toggle, CUT_TO_END, TRUE);
+    add_to_sclist(MMAIN, "M-L", do_toggle, NO_WRAP, TRUE);
+    add_to_sclist(MMAIN, "M-Q", do_toggle, TABS_TO_SPACES, TRUE);
+    add_to_sclist(MMAIN, "M-B", do_toggle, BACKUP_FILE, TRUE);
+    add_to_sclist(MMAIN, "M-F", do_toggle, MULTIBUFFER, TRUE);
+    add_to_sclist(MMAIN, "M-M", do_toggle, USE_MOUSE, TRUE);
+    add_to_sclist(MMAIN, "M-N", do_toggle, NO_CONVERT, TRUE);
+    add_to_sclist(MMAIN, "M-Z", do_toggle, SUSPEND, TRUE);
+#endif
+    add_to_sclist((MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MWHEREISFILE|MGOTODIR), 
+       "^C", (void *) cancel_msg, 0, FALSE);
+    add_to_sclist(MHELP, "^Y", do_page_up, 0, TRUE);
+    add_to_sclist(MHELP, "F7", do_page_up, 0, TRUE);
+    add_to_sclist(MHELP, "^V", do_page_down, 0, TRUE);
+    add_to_sclist(MHELP, "F8", do_page_down, 0, TRUE);
+    add_to_sclist(MHELP, "^X", do_exit, 0, TRUE);
+    add_to_sclist(MHELP, "F2", do_exit, 0, TRUE);
+    add_to_sclist(MWRITEFILE, "M-D", (void *) dos_format_msg, 0, FALSE);
+    add_to_sclist(MWRITEFILE, "M-M", (void *) mac_format_msg, 0, FALSE);
+    add_to_sclist(MWRITEFILE, "M-A", (void *) append_msg, 0, FALSE);
+    add_to_sclist(MWRITEFILE, "M-P", (void *) prepend_msg, 0, FALSE);
+    add_to_sclist(MWRITEFILE, "M-B", (void *) backup_file_msg, 0, FALSE);
+    add_to_sclist(MWRITEFILE, "^T", (void *) to_files_msg, 0, FALSE);
+    add_to_sclist(MINSERTFILE, "^T", (void *) to_files_msg, 0, FALSE);
+    add_to_sclist(MINSERTFILE, "^X", (void *) ext_cmd_msg, 0, FALSE);
+    add_to_sclist(MMAIN, "^L", total_refresh, 0, TRUE);
 
-    sc_init_one(&gotodir_list, NANO_CANCEL_KEY, cancel_msg,
-       IFSCHELP(nano_cancel_msg, FALSE, NANO_NO_KEY), NANO_NO_KEY,
-       NANO_NO_KEY, VIEW, NULL);
+#ifdef DEBUG
+    print_sclist();
 #endif
 
-    currshortcut = main_list;
-
-#ifndef NANO_TINY
-    toggle_init();
-#endif
 }
 
 /* Free the given shortcut. */
@@ -1233,146 +1100,326 @@ void free_shortcutage(shortcut **shortcutage)
     }
 }
 
-#ifndef NANO_TINY
-/* Add a new toggle to the end of the global toggle list. */
-void toggle_init_one(int val
-#ifndef DISABLE_HELP
-       , const char *desc, bool blank_after
-#endif
-       , long flag)
+const subnfunc *sctofunc(sc *s)
 {
-    toggle *u;
+    subnfunc *f;
 
-    if (toggles == NULL) {
-       toggles = (toggle *)nmalloc(sizeof(toggle));
-       u = toggles;
-    } else {
-       for (u = toggles; u->next != NULL; u = u->next)
-           ;
-       u->next = (toggle *)nmalloc(sizeof(toggle));
-       u = u->next;
-    }
+    for (f = allfuncs; f != NULL && s->scfunc != f->scfunc; f = f->next)
+       ;
 
-    u->val = val;
-#ifndef DISABLE_HELP
-    u->desc = (desc == NULL) ? "" : _(desc);
-    u->blank_after = blank_after;
-#endif
-    u->flag = flag;
-    u->next = NULL;
+    return f;
 }
 
-/* Initialize the global toggle list. */
-void toggle_init(void)
+#ifndef NANO_TINY
+/* Now lets come up with a single (hopefully)
+   function to get a string for each flag */
+char *flagtostr(int flag)
 {
-    /* There is no need to reinitialize the toggles.  They can't
-     * change. */
-    if (toggles != NULL)
-       return;
-
-/* The following macro is to be used in calling toggle_init_one().  The
- * point is that toggle_init_one() takes 4 arguments, unless
- * DISABLE_HELP is defined, when the 2nd and 3rd ones should not be
- * there. */
-#ifndef DISABLE_HELP
-#define IFTHELP(help, blank, nextvar) help, blank, nextvar
-#else
-#define IFTHELP(help, blank, nextvar) nextvar
-#endif
-
-    toggle_init_one(TOGGLE_NOHELP_KEY, IFTHELP(N_("Help mode"), FALSE,
-       NO_HELP));
-
-    toggle_init_one(TOGGLE_CONST_KEY,
-       IFTHELP(N_("Constant cursor position display"), FALSE,
-       CONST_UPDATE));
-
-    toggle_init_one(TOGGLE_MORESPACE_KEY,
-       IFTHELP(N_("Use of one more line for editing"), FALSE,
-       MORE_SPACE));
-
-    toggle_init_one(TOGGLE_SMOOTH_KEY,
-#ifdef ENABLE_NANORC
-       IFTHELP(N_("Smooth scrolling"), FALSE, SMOOTH_SCROLL)
-#else
-       IFTHELP(N_("Smooth scrolling"), TRUE, SMOOTH_SCROLL)
-#endif
-       );
-
-#ifdef ENABLE_NANORC
-    toggle_init_one(TOGGLE_WHITESPACE_KEY,
-#ifdef ENABLE_COLOR
-       IFTHELP(N_("Whitespace display"), FALSE, WHITESPACE_DISPLAY)
-#else
-       IFTHELP(N_("Whitespace display"), TRUE, WHITESPACE_DISPLAY)
-#endif
-       );
-#endif
-
-#ifdef ENABLE_COLOR
-    toggle_init_one(TOGGLE_SYNTAX_KEY,
-       IFTHELP(N_("Color syntax highlighting"), TRUE, NO_COLOR_SYNTAX));
-#endif
-
-    toggle_init_one(TOGGLE_SMARTHOME_KEY, IFTHELP(N_("Smart home key"),
-       FALSE, SMART_HOME));
-
-    toggle_init_one(TOGGLE_AUTOINDENT_KEY, IFTHELP(N_("Auto indent"),
-       FALSE, AUTOINDENT));
+   switch (flag) {
+        case NO_HELP:
+            return N_("Help mode");
+        case CONST_UPDATE:
+            return N_("Constant cursor position display");
+        case MORE_SPACE:
+            return N_("Use of one more line for editing");
+        case SMOOTH_SCROLL:
+            return N_("Smooth scrolling");
+        case WHITESPACE_DISPLAY:
+            return N_("Whitespace display");
+        case NO_COLOR_SYNTAX:
+            return N_("Color syntax highlighting");
+        case SMART_HOME:
+            return N_("Smart home key");
+        case AUTOINDENT:
+            return N_("Auto indent");
+        case CUT_TO_END:
+            return N_("Cut to end");
+        case NO_WRAP:
+            return N_("Long line wrapping");
+        case TABS_TO_SPACES:
+            return N_("Conversion of typed tabs to spaces");
+        case BACKUP_FILE:
+            return N_("Backup files");
+        case MULTIBUFFER:
+            return N_("Multiple file buffers");
+        case USE_MOUSE:
+            return N_("Mouse support");
+        case NO_CONVERT:
+            return N_("No conversion from DOS/Mac format");
+        case SUSPEND:
+            return N_("Suspension");
+        default:
+            return "?????";
+    }
+}
 
-    toggle_init_one(TOGGLE_CUTTOEND_KEY, IFTHELP(N_("Cut to end"),
-       FALSE, CUT_TO_END));
+/* Interpret the string given by the rc file and return a
+    shortcut struct, complete with proper value for execute */
+sc *strtosc(int menu, char *input)
+{
+     sc *s;
+
+    s = (sc *)nmalloc(sizeof(sc));
+    s->execute = TRUE; /* overridden as needed below */
+
+    if (!strcasecmp(input, "help"))
+       s->scfunc = do_help_void;
+    else if (!strcasecmp(input, "cancel")) {
+       s->scfunc = (void *) cancel_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "exit"))
+       s->scfunc = do_exit;
+    else if (!strcasecmp(input, "writeout"))
+       s->scfunc = do_writeout_void;
+    else if (!strcasecmp(input, "justify"))
+       s->scfunc = do_justify_void;
+    else if (!strcasecmp(input, "insert"))
+       s->scfunc = do_insertfile_void;
+    else if (!strcasecmp(input, "whereis"))
+       s->scfunc = do_search;
+    else if (!strcasecmp(input, "up"))
+       s->scfunc = do_page_up;
+    else if (!strcasecmp(input, "down"))
+       s->scfunc = do_page_down;
+    else if (!strcasecmp(input, "cut"))
+       s->scfunc = do_cut_text_void;
+    else if (!strcasecmp(input, "uncut"))
+       s->scfunc = do_uncut_text;
+    else if (!strcasecmp(input, "curpos") ||
+       !strcasecmp(input, "cursorpos"))
+       s->scfunc = do_cursorpos_void;
+    else if (!strcasecmp(input, "firstline"))
+       s->scfunc = do_first_line;
+    else if (!strcasecmp(input, "lastline"))
+       s->scfunc = do_last_line;
+    else if (!strcasecmp(input, "gotoline"))
+       s->scfunc = do_gotolinecolumn_void;
+    else if (!strcasecmp(input, "replace"))
+       s->scfunc = do_replace;
+    else if (!strcasecmp(input, "mark"))
+       s->scfunc = do_mark;
+    else if (!strcasecmp(input, "searchagain") ||
+               !strcasecmp(input, "research"))
+       s->scfunc = do_research;
+    else if (!strcasecmp(input, "copytext"))
+       s->scfunc = do_copy_text;
+    else if (!strcasecmp(input, "indent"))
+       s->scfunc = do_indent_void;
+    else if (!strcasecmp(input, "unindent"))
+       s->scfunc = do_unindent;
+    else if (!strcasecmp(input, "right") ||
+               !strcasecmp(input, "forward"))
+       s->scfunc = do_right;
+    else if (!strcasecmp(input, "left") ||
+               !strcasecmp(input, "back"))
+       s->scfunc = do_left;
+    else if (!strcasecmp(input, "nextword"))
+       s->scfunc = do_next_word_void;
+    else if (!strcasecmp(input, "prevword"))
+       s->scfunc = do_prev_word_void;
+    else if (!strcasecmp(input, "up") ||
+               !strcasecmp(input, "prevline"))
+       s->scfunc = do_up_void;
+    else if (!strcasecmp(input, "down") ||
+               !strcasecmp(input, "nextline"))
+       s->scfunc = do_down_void;
+    else if (!strcasecmp(input, "home"))
+       s->scfunc = do_home;
+    else if (!strcasecmp(input, "end"))
+       s->scfunc = do_end;
+    else if (!strcasecmp(input, "beginpara"))
+       s->scfunc = do_para_begin_void;
+    else if (!strcasecmp(input, "endpara"))
+       s->scfunc = do_para_end_void;
+    else if (!strcasecmp(input, "findbracket"))
+       s->scfunc = do_find_bracket;
+    else if (!strcasecmp(input, "scrollup"))
+       s->scfunc = do_scroll_up;
+    else if (!strcasecmp(input, "scrolldown"))
+       s->scfunc = do_scroll_down;
+#ifdef ENABLE_MULTIBUFFER
+    else if (!strcasecmp(input, "prevbuf"))
+       s->scfunc = switch_to_prev_buffer_void;
+    else if (!strcasecmp(input, "nextbuf"))
+       s->scfunc = switch_to_next_buffer_void;
+#endif
+    else if (!strcasecmp(input, "verbatim"))
+       s->scfunc = do_verbatim_input;
+    else if (!strcasecmp(input, "tab"))
+       s->scfunc = do_tab;
+    else if (!strcasecmp(input, "enter"))
+       s->scfunc = do_enter;
+    else if (!strcasecmp(input, "delete"))
+       s->scfunc = do_delete;
+    else if (!strcasecmp(input, "fulljustify"))
+       s->scfunc = do_full_justify;
+    else if (!strcasecmp(input, "wordcount"))
+       s->scfunc = do_wordlinechar_count;
+    else if (!strcasecmp(input, "refresh"))
+       s->scfunc = total_refresh;
+    else if (!strcasecmp(input, "casesens")) {
+       s->scfunc = (void *) case_sens_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "regexp") ||
+               !strcasecmp(input, "regex")) {
+       s->scfunc = (void *) regexp_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "prevhistory")) {
+       s->scfunc = (void *) prev_history_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "nexthistory")) {
+       s->scfunc = (void *) next_history_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "dontreplace")) {
+       s->scfunc = (void *) no_replace_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "gototext")) {
+       s->scfunc = (void *) gototext_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "browser") ||
+               !strcasecmp(input, "tofiles")) {
+       s->scfunc = (void *) to_files_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "dosformat")) {
+       s->scfunc = (void *) dos_format_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "macformat")) {
+       s->scfunc = (void *) mac_format_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "append")) {
+       s->scfunc = (void *) append_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "prepend")) {
+       s->scfunc = (void *) prepend_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "backup")) {
+       s->scfunc = (void *) backup_file_msg;
+       s->execute = FALSE;
+#ifdef ENABLE_MULTIBUFFER
+    } else if (!strcasecmp(input, "newbuffer")) {
+       s->scfunc = (void *) new_buffer_msg;
+       s->execute = FALSE;
+#endif
+    } else if (!strcasecmp(input, "firstfile")) {
+       s->scfunc = (void *) first_file_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "lastfile")) {
+       s->scfunc = (void *) last_file_msg;
+       s->execute = FALSE;
+    } else if (!strcasecmp(input, "nohelp") ||
+               !strcasecmp(input, "nohelp")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = NO_HELP;
+    } else if (!strcasecmp(input, "constupdate")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = CONST_UPDATE;
+    } else if (!strcasecmp(input, "morespace")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = MORE_SPACE;
+    } else if (!strcasecmp(input, "smoothscroll")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = SMOOTH_SCROLL;
+    } else if (!strcasecmp(input, "whitesplacedisplay")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = WHITESPACE_DISPLAY;
+    } else if (!strcasecmp(input, "nosyntax")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = NO_COLOR_SYNTAX;
+    } else if (!strcasecmp(input, "smarthome")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = SMART_HOME;
+    } else if (!strcasecmp(input, "autoindent")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = AUTOINDENT;
+    } else if (!strcasecmp(input, "cuttoend")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = CUT_TO_END;
+    } else if (!strcasecmp(input, "nowrap")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = NO_WRAP;
+    } else if (!strcasecmp(input, "tabstospaces")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = TABS_TO_SPACES;
+    } else if (!strcasecmp(input, "backupfile")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = BACKUP_FILE;
+    } else if (!strcasecmp(input, "mutlibuffer")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = MULTIBUFFER;
+    } else if (!strcasecmp(input, "mouse")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = USE_MOUSE;
+    } else if (!strcasecmp(input, "noconvert")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = NO_CONVERT;
+    } else if (!strcasecmp(input, "suspend")) {
+       s->scfunc = (void *) do_toggle;
+       s->execute = FALSE;
+       s->toggle = SUSPEND;
+    } else {
+       free(s);
+       return NULL;
+    }
 
-#ifndef DISABLE_WRAPPING
-    toggle_init_one(TOGGLE_WRAP_KEY, IFTHELP(N_("Long line wrapping"),
-       FALSE, NO_WRAP));
-#endif
+    return s;
 
-    toggle_init_one(TOGGLE_TABSTOSPACES_KEY,
-#ifndef DISABLE_MOUSE
-       IFTHELP(N_("Conversion of typed tabs to spaces"), TRUE,
-       TABS_TO_SPACES)
-#else
-       IFTHELP(N_("Conversion of typed tabs to spaces"),
-       !ISSET(RESTRICTED) ? TRUE : FALSE, TABS_TO_SPACES)
-#endif
-       );
+}
 
-    /* If we're using restricted mode, the backup toggle is disabled.
-     * It's useless since backups are disabled. */
-    if (!ISSET(RESTRICTED))
-       toggle_init_one(TOGGLE_BACKUP_KEY, IFTHELP(N_("Backup files"),
-               FALSE, BACKUP_FILE));
+/* Same thing as abnove but for the menu */
+int strtomenu(char *input)
+{
+    if (!strcasecmp(input, "all"))
+       return MALL;
+    else if (!strcasecmp(input, "main"))
+       return MMAIN;
+    else if (!strcasecmp(input, "search"))
+       return MWHEREIS;
+    else if (!strcasecmp(input, "replace"))
+       return MREPLACE;
+    else if (!strcasecmp(input, "replace2") ||
+               !strcasecmp(input, "replacewith"))
+       return MREPLACE2;
+    else if (!strcasecmp(input, "gotoline"))
+       return MGOTOLINE;
+    else if (!strcasecmp(input, "writeout"))
+       return MWRITEFILE;
+    else if (!strcasecmp(input, "insert"))
+       return MINSERTFILE;
+    else if (!strcasecmp(input, "externalcmd") ||
+               !strcasecmp(input, "extcmd"))
+       return MEXTCMD;
+    else if (!strcasecmp(input, "help"))
+       return MHELP;
+    else if (!strcasecmp(input, "spell"))
+       return MSPELL;
+    else if (!strcasecmp(input, "browser"))
+       return MBROWSER;
+    else if (!strcasecmp(input, "whereisfile"))
+       return MWHEREISFILE;
+    else if (!strcasecmp(input, "gotodir"))
+       return MGOTODIR;
+
+    return -1;
+}
 
-#ifdef ENABLE_MULTIBUFFER
-    /* If we're using restricted mode, the multibuffer toggle is
-     * disabled.  It's useless since inserting files is disabled. */
-    if (!ISSET(RESTRICTED))
-       toggle_init_one(TOGGLE_MULTIBUFFER_KEY,
-               IFTHELP(N_("Multiple file buffers"), FALSE,
-               MULTIBUFFER));
-#endif
 
-#ifndef DISABLE_MOUSE
-    toggle_init_one(TOGGLE_MOUSE_KEY, IFTHELP(N_("Mouse support"),
-       FALSE, USE_MOUSE));
 #endif
 
-    /* If we're using restricted mode, the DOS/Mac conversion toggle is
-     * disabled.  It's useless since inserting files is disabled. */
-    if (!ISSET(RESTRICTED))
-       toggle_init_one(TOGGLE_NOCONVERT_KEY,
-               IFTHELP(N_("No conversion from DOS/Mac format"), FALSE,
-               NO_CONVERT));
-
-    /* If we're using restricted mode, the suspend toggle is disabled.
-     * It's useless since suspending is disabled. */
-    if (!ISSET(RESTRICTED))
-       toggle_init_one(TOGGLE_SUSPEND_KEY, IFTHELP(N_("Suspension"),
-       FALSE, SUSPEND));
-}
-#endif /* !NANO_TINY */
-
 #ifdef DEBUG
 /* This function is used to gracefully return all the memory we've used.
  * It should be called just before calling exit().  Practically, the
@@ -1419,26 +1466,6 @@ void thanks_for_all_the_fish(void)
 #ifndef DISABLE_JUSTIFY
     if (jusbuffer != NULL)
        free_filestruct(jusbuffer);
-#endif
-    free_shortcutage(&main_list);
-    free_shortcutage(&whereis_list);
-    free_shortcutage(&replace_list);
-    free_shortcutage(&replace_list_2);
-    free_shortcutage(&gotoline_list);
-    free_shortcutage(&writefile_list);
-    free_shortcutage(&insertfile_list);
-#ifndef NANO_TINY
-    free_shortcutage(&extcmd_list);
-#endif
-#ifndef DISABLE_HELP
-    free_shortcutage(&help_list);
-#endif
-#ifndef DISABLE_SPELLER
-    free_shortcutage(&spell_list);
-#endif
-#ifndef DISABLE_BROWSER
-    free_shortcutage(&browser_list);
-    free_shortcutage(&gotodir_list);
 #endif
 #ifndef NANO_TINY
     /* Free the memory associated with each toggle. */
@@ -1504,3 +1531,4 @@ void thanks_for_all_the_fish(void)
 #endif
 }
 #endif /* DEBUG */
+
index 803cf1227bdd4d49cb7a6496ac5e95aaabfa804a..3e21e66f0144c149c62b7016f37990882662a394 100644 (file)
@@ -47,13 +47,15 @@ void do_help(void (*refresh_func)(void))
        /* The line number in help_text of the last help line.  This
         * variable is zero-based. */
 #ifndef DISABLE_MOUSE
-    const shortcut *oldshortcut = currshortcut;
        /* The current shortcut list. */
+    int oldmenu = currmenu;
 #endif
     const char *ptr;
        /* The current line of the help text. */
     size_t old_line = (size_t)-1;
        /* The line we were on before the current line. */
+    const sc *s;
+    const subnfunc *f;
 
     curs_set(0);
     blank_edit();
@@ -66,9 +68,9 @@ void do_help(void (*refresh_func)(void))
     assert(help_text != NULL);
 
 #ifndef DISABLE_MOUSE
-    /* Set currshortcut to allow clicking on the help screen's shortcut
+    /* Set currmenu to allow clicking on the help screen's shortcut
      * list, after help_init() is called. */
-    currshortcut = help_list;
+    currmenu = MHELP;
 #endif
 
     if (ISSET(NO_HELP)) {
@@ -78,7 +80,7 @@ void do_help(void (*refresh_func)(void))
        window_init();
     }
 
-    bottombars(help_list);
+    bottombars(MHELP);
     wnoutrefresh(bottomwin);
 
     /* Get the last line of the help text. */
@@ -127,57 +129,57 @@ void do_help(void (*refresh_func)(void))
        kbinput = get_kbinput(edit, &meta_key, &func_key);
        parse_help_input(&kbinput, &meta_key, &func_key);
 
-       switch (kbinput) {
+        s = get_shortcut(MMAIN, &kbinput, &meta_key, &func_key);
+       if (!s)
+           continue;
+        f = sctofunc(s);
+       if (!f)
+           continue;
+
+
+        if (f->scfunc == (void *) do_mouse) {
 #ifndef DISABLE_MOUSE
-           case KEY_MOUSE:
-               {
                    int mouse_x, mouse_y;
 
                    get_mouseinput(&mouse_x, &mouse_y, TRUE);
-               }
-               break;
 #endif
            /* Redraw the screen. */
-           case NANO_REFRESH_KEY:
+       } else if (f->scfunc == total_refresh) {
                total_redraw();
                break;
-           case NANO_PREVPAGE_KEY:
+       } else if (f->scfunc == do_page_up) {
                if (line > editwinrows - 2)
                    line -= editwinrows - 2;
                else
                    line = 0;
-               break;
-           case NANO_NEXTPAGE_KEY:
+       } else if (f->scfunc == do_page_down) {
                if (line + (editwinrows - 1) < last_line)
                    line += editwinrows - 2;
-               break;
-           case NANO_PREVLINE_KEY:
+       } else if (f->scfunc == do_up_void) {
                if (line > 0)
                    line--;
-               break;
-           case NANO_NEXTLINE_KEY:
+       } else if (f->scfunc == do_down_void) {
                if (line + (editwinrows - 1) < last_line)
                    line++;
-               break;
-           case NANO_FIRSTLINE_METAKEY:
+       } else if (f->scfunc == do_first_line) {
                if (meta_key)
                    line = 0;
                break;
-           case NANO_LASTLINE_METAKEY:
+       } else if (f->scfunc == do_last_line) {
                if (meta_key) {
                    if (line + (editwinrows - 1) < last_line)
                        line = last_line - (editwinrows - 1);
                }
                break;
            /* Abort the help browser. */
-           case NANO_EXIT_KEY:
+       } else if (f->scfunc == do_exit) {
                abort = TRUE;
                break;
        }
     }
 
 #ifndef DISABLE_MOUSE
-    currshortcut = oldshortcut;
+    currmenu = oldmenu;
 #endif
 
     if (old_no_help) {
@@ -186,7 +188,7 @@ void do_help(void (*refresh_func)(void))
        SET(NO_HELP);
        window_init();
     } else
-       bottombars(currshortcut);
+       bottombars(currmenu);
 
     curs_set(1);
     refresh_func();
@@ -222,9 +224,11 @@ void help_init(void)
                                 * full string is too long for the
                                 * compiler to handle. */
     char *ptr;
-    const shortcut *s;
+    const subnfunc *f;
+    const sc *s;
+    int scsfound = 0;
+
 #ifndef NANO_TINY
-    const toggle *t;
 #ifdef ENABLE_NANORC
     bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
 
@@ -233,8 +237,7 @@ void help_init(void)
 #endif
 
     /* First, set up the initial help text for the current function. */
-    if (currshortcut == whereis_list || currshortcut == replace_list ||
-       currshortcut == replace_list_2) {
+    if (currmenu == MWHEREIS || currmenu == MREPLACE || currmenu == MREPLACE2) {
        htx[0] = N_("Search Command Help Text\n\n "
                "Enter the words or characters you would like to "
                "search for, and then press Enter.  If there is a "
@@ -249,7 +252,7 @@ void help_init(void)
                "will be replaced.\n\n The following function keys are "
                "available in Search mode:\n\n");
        htx[2] = NULL;
-    } else if (currshortcut == gotoline_list) {
+    } else if (currmenu == MGOTOLINE) {
        htx[0] = N_("Go To Line Help Text\n\n "
                "Enter the line number that you wish to go to and hit "
                "Enter.  If there are fewer lines of text than the "
@@ -258,7 +261,7 @@ void help_init(void)
                "available in Go To Line mode:\n\n");
        htx[1] = NULL;
        htx[2] = NULL;
-    } else if (currshortcut == insertfile_list) {
+    } else if (currmenu == MINSERTFILE) {
        htx[0] = N_("Insert File Help Text\n\n "
                "Type in the name of a file to be inserted into the "
                "current file buffer at the current cursor "
@@ -273,7 +276,7 @@ void help_init(void)
                "the prompt and press Enter.\n\n The following "
                "function keys are available in Insert File mode:\n\n");
        htx[2] = NULL;
-    } else if (currshortcut == writefile_list) {
+    } else if (currmenu == MWRITEFILE) {
        htx[0] = N_("Write File Help Text\n\n "
                "Type the name that you wish to save the current file "
                "as and press Enter to save the file.\n\n If you have "
@@ -287,7 +290,7 @@ void help_init(void)
        htx[2] = NULL;
     }
 #ifndef DISABLE_BROWSER
-    else if (currshortcut == browser_list) {
+    else if (currmenu == MBROWSER) {
        htx[0] = N_("File Browser Help Text\n\n "
                "The file browser is used to visually browse the "
                "directory structure to select a file for reading "
@@ -300,7 +303,7 @@ void help_init(void)
                "in the file browser:\n\n");
        htx[1] = NULL;
        htx[2] = NULL;
-    } else if (currshortcut == whereis_file_list) {
+    } else if (currmenu == MWHEREISFILE) {
        htx[0] = N_("Browser Search Command Help Text\n\n "
                "Enter the words or characters you would like to "
                "search for, and then press Enter.  If there is a "
@@ -313,7 +316,7 @@ void help_init(void)
        htx[1] = N_(" The following function keys are available in "
                "Browser Search mode:\n\n");
        htx[2] = NULL;
-    } else if (currshortcut == gotodir_list) {
+    } else if (currmenu == MGOTODIR) {
        htx[0] = N_("Browser Go To Directory Help Text\n\n "
                "Enter the name of the directory you would like to "
                "browse to.\n\n If tab completion has not been "
@@ -326,7 +329,7 @@ void help_init(void)
     }
 #endif /* !DISABLE_BROWSER */
 #ifndef DISABLE_SPELLER
-    else if (currshortcut == spell_list) {
+    else if (currmenu == MSPELL) {
        htx[0] = N_("Spell Check Help Text\n\n "
                "The spell checker checks the spelling of all text in "
                "the current file.  When an unknown word is "
@@ -341,7 +344,7 @@ void help_init(void)
     }
 #endif /* !DISABLE_SPELLER */
 #ifndef NANO_TINY
-    else if (currshortcut == extcmd_list) {
+    else if (currmenu == MEXTCMD) {
        htx[0] = N_("Execute Command Help Text\n\n "
                "This mode allows you to insert the output of a "
                "command run by the shell into the current buffer (or "
@@ -397,18 +400,21 @@ void help_init(void)
     /* Count the shortcut help text.  Each entry has up to three keys,
      * which fill 24 columns, plus translated text, plus one or two
      * \n's. */
-       for (s = currshortcut; s != NULL; s = s->next)
-           allocsize += (24 * mb_cur_max()) + strlen(s->help) + 2;
+       for (f = allfuncs; f != NULL; f = f->next)
+            if (f->menus & currmenu)
+               allocsize += (24 * mb_cur_max()) + strlen(f->help) + 2;
 
 #ifndef NANO_TINY
     /* If we're on the main list, we also count the toggle help text.
      * Each entry has "M-%c\t\t\t", which fills 24 columns, plus a
      * space, plus translated text, plus one or two '\n's. */
-    if (currshortcut == main_list) {
+    if (currmenu == MMAIN) {
        size_t endis_len = strlen(_("enable/disable"));
 
-       for (t = toggles; t != NULL; t = t->next)
-           allocsize += strlen(t->desc) + endis_len + 9;
+       for (s = sclist; s != NULL; s = s->next)
+            if (s->scfunc == (void *) do_toggle)
+               allocsize += strlen(flagtostr(s->toggle)) + endis_len + 9;
+
     }
 #endif
 
@@ -429,131 +435,55 @@ void help_init(void)
 
     ptr = help_text + strlen(help_text);
 
-    /* Now add our shortcut info.  Assume that each shortcut has, at the
-     * very least, an equivalent control key, an equivalent primary meta
-     * key sequence, or both.  Also assume that the meta key values are
-     * not control characters.  We can display a maximum of three
-     * shortcut entries. */
-    for (s = currshortcut; s != NULL; s = s->next) {
-       int entries = 0;
-
-       /* Control key. */
-       if (s->ctrlval != NANO_NO_KEY) {
-           entries++;
-           /* Yucky sentinel values that we can't handle a better
-            * way. */
-           if (s->ctrlval == NANO_CONTROL_SPACE) {
-               char *space_ptr = display_string(_("Space"), 0, 14,
-                       FALSE);
-
-               if (s->funcval == NANO_NO_KEY && (s->metaval ==
-                       NANO_NO_KEY || s->miscval == NANO_NO_KEY)) {
-                   /* If we're here, we have at least two entries worth
-                    * of blank space.  If this entry takes up more than
-                    * one entry's worth of space, use two to display
-                    * it. */
-                   if (mbstrlen(space_ptr) > 6)
-                       entries++;
-               } else
-                   /* Otherwise, truncate it so that it takes up only
-                    * one entry's worth of space. */
-                   space_ptr[6] = '\0';
-
-               ptr += sprintf(ptr, "^%s", space_ptr);
-
-               free(space_ptr);
-           } else if (s->ctrlval == NANO_CONTROL_8)
-               ptr += sprintf(ptr, "^?");
-           /* Normal values. */
-           else
-               ptr += sprintf(ptr, "^%c", s->ctrlval + 64);
-           *(ptr++) = '\t';
-       }
+    /* Now add our shortcut info. */
+    for (f = allfuncs; f != NULL; f = f->next) {
 
-       /* Function key. */
-       if (s->funcval != NANO_NO_KEY) {
-           entries++;
-           /* If this is the first entry, put it in the middle. */
-           if (entries == 1) {
-               entries++;
-               *(ptr++) = '\t';
-           }
-           ptr += sprintf(ptr, "(F%d)", s->funcval - KEY_F0);
-           *(ptr++) = '\t';
-       }
+        if ((f->menus & currmenu) == 0)
+           continue;
 
-       /* Primary meta key sequence.  If it's the first entry, don't
-        * put parentheses around it. */
-       if (s->metaval != NANO_NO_KEY) {
-           entries++;
-           /* If this is the last entry, put it at the end. */
-           if (entries == 2 && s->miscval == NANO_NO_KEY) {
-               entries++;
-               *(ptr++) = '\t';
-           }
-           /* Yucky sentinel values that we can't handle a better
-            * way. */
-           if (s->metaval == NANO_META_SPACE && entries == 1) {
-               char *space_ptr = display_string(_("Space"), 0, 13,
-                       FALSE);
-
-               /* If we're here, we have at least two entries worth of
-                * blank space.  If this entry takes up more than one
-                * entry's worth of space, use two to display it. */
-               if (mbstrlen(space_ptr) > 5)
-                   entries++;
-
-               ptr += sprintf(ptr, "M-%s", space_ptr);
-
-               free(space_ptr);
-           } else
-               /* Normal values. */
-               ptr += sprintf(ptr, (entries == 1) ? "M-%c" : "(M-%c)",
-                       toupper(s->metaval));
-           *(ptr++) = '\t';
-       }
+        if (!f->desc || !strcmp(f->desc, ""))
+           continue;
 
-       /* Miscellaneous meta key sequence. */
-       if (entries < 3 && s->miscval != NANO_NO_KEY) {
-           entries++;
-           /* If this is the last entry, put it at the end. */
-           if (entries == 2) {
-               entries++;
-               *(ptr++) = '\t';
-           }
-           ptr += sprintf(ptr, "(M-%c)", toupper(s->miscval));
-           *(ptr++) = '\t';
-       }
+        /* Lets just try and use the first 3 shortcuts
+           from the new struct... */
+        for (s = sclist, scsfound = 0; s != NULL; s = s->next) {
 
-       /* If this entry isn't blank, make sure all the help text starts
-        * at the same place. */
-       if (s->ctrlval != NANO_NO_KEY || s->funcval != NANO_NO_KEY ||
-               s->metaval != NANO_NO_KEY || s->miscval !=
-               NANO_NO_KEY) {
-           while (entries < 3) {
-               entries++;
+            if (scsfound == 3)
+               continue;
+
+           if ((s->menu & currmenu) == 0)
+               continue;
+
+            if (s->scfunc == f->scfunc) {
+               scsfound++;
+
+               if (scsfound == 1)
+                   ptr += sprintf(ptr, "%s", s->keystr);
+               else
+                   ptr += sprintf(ptr, "(%s)", s->keystr);
                *(ptr++) = '\t';
            }
        }
+       /* Pad with tabs if we didnt find 3 */
+        for (; scsfound < 3; scsfound++) {
+           *(ptr++) = '\t';
+       }
 
        /* The shortcut's help text. */
-       ptr += sprintf(ptr, "%s\n", s->help);
+       ptr += sprintf(ptr, "%s\n", f->help);
 
-       if (s->blank_after)
+       if (f->blank_after)
            ptr += sprintf(ptr, "\n");
     }
 
 #ifndef NANO_TINY
     /* And the toggles... */
-    if (currshortcut == main_list) {
-       for (t = toggles; t != NULL; t = t->next) {
-           ptr += sprintf(ptr, "M-%c\t\t\t%s %s\n",
-               toupper(t->val), t->desc, _("enable/disable"));
+    if (currmenu == MMAIN)
+        for (s = sclist; s != NULL; s = s->next)
+            if (s->scfunc == (void *) do_toggle)
+               ptr += sprintf(ptr, "(%s)\t\t\t%s %s\n",
+                   s->keystr, flagtostr(s->toggle), _("enable/disable"));
 
-           if (t->blank_after)
-               ptr += sprintf(ptr, "\n");
-       }
-    }
 
 #ifdef ENABLE_NANORC
     if (old_whitespace)
@@ -573,7 +503,7 @@ void help_init(void)
  * shortcut keys. */
 void parse_help_input(int *kbinput, bool *meta_key, bool *func_key)
 {
-    get_shortcut(help_list, kbinput, meta_key, func_key);
+    get_shortcut(MHELP, kbinput, meta_key, func_key);
 
     if (!*meta_key) {
        switch (*kbinput) {
index b676fc93cc6d58ff5c0a280c5e1b7c2e61f87f77..38af9b2bd068abfc357e766911f217495e08a425 100644 (file)
@@ -1174,7 +1174,7 @@ RETSIGTYPE handle_sigwinch(int signal)
     /* Redraw the contents of the windows that need it. */
     blank_statusbar();
     wnoutrefresh(bottomwin);
-    currshortcut = main_list;
+    currmenu = MMAIN;
     total_refresh();
 
     /* Jump back to either main() or the unjustify routine in
@@ -1196,52 +1196,54 @@ void allow_pending_sigwinch(bool allow)
 
 #ifndef NANO_TINY
 /* Handle the global toggle specified in which. */
-void do_toggle(const toggle *which)
+void do_toggle(int flag)
 {
     bool enabled;
+    char *desc;
 
-    TOGGLE(which->flag);
+    TOGGLE(flag);
 
-    switch (which->val) {
+    switch (flag) {
 #ifndef DISABLE_MOUSE
-       case TOGGLE_MOUSE_KEY:
+       case USE_MOUSE:
            mouse_init();
            break;
 #endif
-       case TOGGLE_MORESPACE_KEY:
-       case TOGGLE_NOHELP_KEY:
+       case MORE_SPACE:
+       case NO_HELP:
            window_init();
            total_refresh();
            break;
-       case TOGGLE_SUSPEND_KEY:
+       case SUSPEND:
            signal_init();
            break;
 #ifdef ENABLE_NANORC
-       case TOGGLE_WHITESPACE_KEY:
+       case WHITESPACE_DISPLAY:
            titlebar(NULL);
            edit_refresh();
            break;
 #endif
 #ifdef ENABLE_COLOR
-       case TOGGLE_SYNTAX_KEY:
+       case NO_COLOR_SYNTAX:
            edit_refresh();
            break;
 #endif
     }
 
-    enabled = ISSET(which->flag);
+    enabled = ISSET(flag);
 
-    if (which->val == TOGGLE_NOHELP_KEY
+    if (flag ==  NO_HELP
 #ifndef DISABLE_WRAPPING
-       || which->val == TOGGLE_WRAP_KEY
+       || flag == NO_WRAP
 #endif
 #ifdef ENABLE_COLOR
-       || which->val == TOGGLE_SYNTAX_KEY
+       || flag == NO_COLOR_SYNTAX
 #endif
        )
        enabled = !enabled;
 
-    statusbar("%s %s", which->desc, enabled ? _("enabled") :
+    desc = flagtostr(flag);
+    statusbar("%s %s", desc, enabled ? _("enabled") :
        _("disabled"));
 }
 #endif /* !NANO_TINY */
@@ -1368,12 +1370,8 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
        /* The length of the input buffer. */
     bool cut_copy = FALSE;
        /* Are we cutting or copying text? */
-    const shortcut *s;
+    const sc *s;
     bool have_shortcut;
-#ifndef NANO_TINY
-    const toggle *t;
-    bool have_toggle;
-#endif
 
     *s_or_t = FALSE;
     *ran_func = FALSE;
@@ -1399,32 +1397,15 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
 #endif
 
     /* Check for a shortcut in the main list. */
-    s = get_shortcut(main_list, &input, meta_key, func_key);
+    s = get_shortcut(MMAIN, &input, meta_key, func_key);
 
     /* If we got a shortcut from the main list, or a "universal"
      * edit window shortcut, set have_shortcut to TRUE. */
-    have_shortcut = (s != NULL || input == NANO_XON_KEY ||
-       input == NANO_XOFF_KEY || input == NANO_SUSPEND_KEY);
-
-#ifndef NANO_TINY
-    /* Check for a toggle in the main list. */
-    t = get_toggle(input, *meta_key);
-
-    /* If we got a toggle from the main list, set have_toggle to
-     * TRUE. */
-    have_toggle = (t != NULL);
-#endif
-
-    /* Set s_or_t to TRUE if we got a shortcut or toggle. */
-    *s_or_t = (have_shortcut
-#ifndef NANO_TINY
-       || have_toggle
-#endif
-       );
+    have_shortcut = (s != NULL || input == NANO_SUSPEND_KEY);
 
     /* If we got a non-high-bit control key, a meta key sequence, or a
      * function key, and it's not a shortcut or toggle, throw it out. */
-    if (!*s_or_t) {
+    if (!have_shortcut) {
        if (is_ascii_cntrl_char(input) || *meta_key || *func_key) {
            statusbar(_("Unknown Command"));
            beep();
@@ -1439,7 +1420,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
         * it's a normal text character.  Display the warning if we're
         * in view mode, or add the character to the input buffer if
         * we're not. */
-       if (input != ERR && !*s_or_t) {
+       if (input != ERR && !have_shortcut) {
            if (ISSET(VIEW_MODE))
                print_view_warning();
            else {
@@ -1455,12 +1436,12 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
         * output all the characters in the input buffer if it isn't
         * empty.  Note that it should be empty if we're in view
         * mode. */
-        if (*s_or_t || get_key_buffer_len() == 0) {
+        if (have_shortcut || get_key_buffer_len() == 0) {
 #ifndef DISABLE_WRAPPING
            /* If we got a shortcut or toggle, and it's not the shortcut
             * for verbatim input, turn off prepending of wrapped
             * text. */
-           if (*s_or_t && (!have_shortcut || s == NULL || s->func !=
+           if (have_shortcut && (!have_shortcut || s == NULL || s->scfunc !=
                do_verbatim_input))
                wrap_reset();
 #endif
@@ -1489,12 +1470,6 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
        if (have_shortcut) {
            switch (input) {
                /* Handle the "universal" edit window shortcuts. */
-               case NANO_XON_KEY:
-                   statusbar(_("XON ignored, mumble mumble"));
-                   break;
-               case NANO_XOFF_KEY:
-                   statusbar(_("XOFF ignored, mumble mumble"));
-                   break;
                case NANO_SUSPEND_KEY:
                    if (ISSET(SUSPEND))
                        do_suspend(0);
@@ -1507,32 +1482,31 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
                default:
                    /* If the function associated with this shortcut is
                     * cutting or copying text, indicate this. */
-                   if (s->func == do_cut_text_void
+                   if (s->scfunc == do_cut_text_void
 #ifndef NANO_TINY
-                       || s->func == do_copy_text || s->func ==
+                       || s->scfunc == do_copy_text || s->scfunc ==
                        do_cut_till_end
 #endif
                        )
                        cut_copy = TRUE;
 
-                   if (s->func != NULL) {
+                   if (s->scfunc != NULL) {
+                       const subnfunc *f = sctofunc((sc *) s);
                        *ran_func = TRUE;
-                       if (ISSET(VIEW_MODE) && !s->viewok)
+                       if (ISSET(VIEW_MODE) && f && !f->viewok)
                            print_view_warning();
                        else
-                           s->func();
+#ifndef NANO_TINY
+                           if (s->scfunc == (void *) do_toggle)
+                               do_toggle(s->toggle);
+                           else
+#endif
+                               s->scfunc();
                    }
                    *finished = TRUE;
                    break;
            }
        }
-#ifndef NANO_TINY
-       else if (have_toggle) {
-           /* Toggle the flag associated with this shortcut. */
-           if (allow_funcs)
-               do_toggle(t);
-       }
-#endif
     }
 
     /* If we aren't cutting or copying text, blow away the text in the
@@ -1543,6 +1517,17 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
     return input;
 }
 
+void xon_complaint(void)
+{
+    statusbar(_("XON ignored, mumble mumble"));
+}
+
+void xoff_complaint(void)
+{
+    statusbar(_("XOFF ignored, mumble mumble"));
+}
+
+
 #ifndef DISABLE_MOUSE
 /* Handle a mouse click on the edit window or the shortcut list. */
 int do_mouse(void)
@@ -1991,6 +1976,11 @@ int main(int argc, char **argv)
 #endif
     }
 
+
+    /* Set up the shortcut lists.
+       Need to do this before the rcfile */
+    shortcut_init(FALSE);
+
 /* We've read through the command line options.  Now back up the flags
  * and values that are set, and read the rcfile(s).  If the values
  * haven't changed afterward, restore the backed-up values. */
@@ -2029,6 +2019,11 @@ int main(int argc, char **argv)
 
        do_rcfile();
 
+#ifdef DEBUG
+        fprintf(stderr, "After rebinding keys...\n");
+        print_sclist();
+#endif
+
 #ifndef DISABLE_OPERATINGDIR
        if (operating_dir_cpy != NULL) {
            free(operating_dir);
@@ -2191,9 +2186,6 @@ int main(int argc, char **argv)
     /* Set up the signal handlers. */
     signal_init();
 
-    /* Set up the shortcut lists. */
-    shortcut_init(FALSE);
-
 #ifndef DISABLE_MOUSE
     /* Initialize mouse support. */
     mouse_init();
@@ -2302,7 +2294,7 @@ int main(int argc, char **argv)
        if (ISSET(CONST_UPDATE) && get_key_buffer_len() == 0)
            do_cursorpos(TRUE);
 
-       currshortcut = main_list;
+        currmenu = MMAIN;
 
        /* Read in and interpret characters. */
        do_input(&meta_key, &func_key, &s_or_t, &ran_func, &finished,
index 370d6d33b94125783c2ea3fbed0b1c2a1fe41640..2688e9ba5a99e40fe16d1f6b6de1c80c9aa11b94 100644 (file)
@@ -165,6 +165,10 @@ typedef enum {
     CENTER, NONE
 } update_type;
 
+typedef enum {
+    CONTROL, META, FKEY, RAW
+}  function_type;
+
 /* Structure types. */
 typedef struct filestruct {
     char *data;
@@ -340,7 +344,51 @@ typedef struct rcoption {
    long flag;
        /* The flag associated with it, if any. */
 } rcoption;
+
+#endif
+
+typedef struct sc {
+    char *keystr;
+       /* The shortcut key for a function, ASCII version */
+    function_type type;
+        /* What kind of function key is it for convenience later */
+    int seq;
+        /* The actual sequence to check on the the type is determined */
+    int menu;
+        /* What list does this apply to */
+    void (*scfunc)(void);
+        /* The function we're going to run */
+    int toggle;
+        /* If a toggle, what we're toggling */
+    bool execute;
+       /* Whether to execute the function in question or just return
+          so the sequence can be caught by the calling code */
+    struct sc *next;
+        /* Next in the list */
+} sc;
+
+typedef struct subnfunc {
+   void (*scfunc)(void);
+       /* What function is this */
+    int menus;
+       /* In what menus does this function applu */
+    const char *desc;
+       /* The function's description, e.g. "Page Up". */
+#ifndef DISABLE_HELP
+    const char *help;
+       /* The help file entry text for this function. */
+    bool blank_after;
+       /* Whether there should be a blank line after the help entry
+        * text for this function. */
 #endif
+    bool viewok;
+        /* Is this function allowed when in view mode? */
+    long toggle;
+       /* If this is a toggle, if nonzero what toggle to set */
+    struct subnfunc *next;
+       /* next item in the list */
+} subnfunc;
+
 
 /* Bitwise flags so that we can save space (or, more correctly, not
  * waste it). */
@@ -376,6 +424,23 @@ typedef struct rcoption {
 #define NO_NEWLINES                    (1<<29)
 #define BOLD_TEXT                      (1<<30)
 
+/* Flags for which menus in which a given function should be present */
+#define MMAIN                          (1<<0)
+#define        MWHEREIS                        (1<<1)
+#define        MREPLACE                        (1<<2)
+#define        MREPLACE2                       (1<<3)
+#define        MGOTOLINE                       (1<<4)
+#define        MWRITEFILE                      (1<<5)
+#define        MINSERTFILE                     (1<<6)
+#define        MEXTCMD                         (1<<7)
+#define        MHELP                           (1<<8)
+#define        MSPELL                          (1<<9)
+#define        MBROWSER                        (1<<10)
+#define        MWHEREISFILE                    (1<<11)
+#define MGOTODIR                       (1<<12)
+/* This really isnt all but close enough */
+#define        MALL                            (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MBROWSER|MWHEREISFILE|MGOTODIR|MHELP)
+
 /* Control key sequences.  Changing these would be very, very bad. */
 #define NANO_CONTROL_SPACE 0
 #define NANO_CONTROL_A 1
index d32c7cb78d485b3f531b438faa2029f1c1618855..083174dce6e0605a403733cc352ac7173dbf912f 100644 (file)
@@ -61,7 +61,8 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
        /* The input buffer. */
     static size_t kbinput_len = 0;
        /* The length of the input buffer. */
-    const shortcut *s;
+    const sc *s;
+    const subnfunc *f;
     bool have_shortcut;
 
     *s_or_t = FALSE;
@@ -88,7 +89,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
 #endif
 
     /* Check for a shortcut in the current list. */
-    s = get_shortcut(currshortcut, &input, meta_key, func_key);
+    s = get_shortcut(currmenu, &input, meta_key, func_key);
 
     /* If we got a shortcut from the current list, or a "universal"
      * statusbar prompt shortcut, set have_shortcut to TRUE. */
@@ -131,7 +132,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
             * and we're at the "Write File" prompt, disable text
             * input. */
            if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
-               currshortcut != writefile_list) {
+               currmenu != MWRITEFILE) {
                kbinput_len++;
                kbinput = (int *)nrealloc(kbinput, kbinput_len *
                        sizeof(int));
@@ -181,7 +182,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
                     * isn't blank, and we're at the "Write File"
                     * prompt, disable Cut. */
                    if (!ISSET(RESTRICTED) || openfile->filename[0] ==
-                       '\0' || currshortcut != writefile_list)
+                       '\0' || currmenu != MWRITEFILE)
                        do_statusbar_cut_text();
                    break;
                case NANO_FORWARD_KEY:
@@ -218,7 +219,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
                         * prompt, disable verbatim input. */
                        if (!ISSET(RESTRICTED) ||
                                openfile->filename[0] == '\0' ||
-                               currshortcut != writefile_list) {
+                               currmenu != MWRITEFILE) {
                            bool got_enter;
                                /* Whether we got the Enter key. */
 
@@ -241,7 +242,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
                     * isn't blank, and we're at the "Write File"
                     * prompt, disable Delete. */
                    if (!ISSET(RESTRICTED) || openfile->filename[0] ==
-                       '\0' || currshortcut != writefile_list)
+                       '\0' || currmenu != MWRITEFILE)
                        do_statusbar_delete();
                    break;
                case NANO_BACKSPACE_KEY:
@@ -249,7 +250,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
                     * isn't blank, and we're at the "Write File"
                     * prompt, disable Backspace. */
                    if (!ISSET(RESTRICTED) || openfile->filename[0] ==
-                       '\0' || currshortcut != writefile_list)
+                       '\0' || currmenu != MWRITEFILE)
                        do_statusbar_backspace();
                    break;
                /* Handle the normal statusbar prompt shortcuts, setting
@@ -258,10 +259,11 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
                 * that we're done after running or trying to run their
                 * associated functions. */
                default:
-                   if (s->func != NULL) {
+                   f = sctofunc((sc *) s);
+                   if (s->scfunc != NULL &&  s->execute == TRUE) {
                        *ran_func = TRUE;
-                       if (!ISSET(VIEW_MODE) || s->viewok)
-                           s->func();
+                       if (!ISSET(VIEW_MODE) || f->viewok)
+                           f->scfunc();
                    }
                    *finished = TRUE;
            }
@@ -933,7 +935,7 @@ int get_prompt_string(bool allow_tabs,
 #ifndef NANO_TINY
        filestruct **history_list,
 #endif
-       void (*refresh_func)(void), const shortcut *s
+       void (*refresh_func)(void), int menu
 #ifndef DISABLE_TABCOMP
        , bool *list
 #endif
@@ -982,7 +984,11 @@ int get_prompt_string(bool allow_tabs,
        statusbar_pww = statusbar_xplustabs();
     }
 
-    currshortcut = s;
+    currmenu = menu;
+
+#ifdef DEBUG
+fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %d\n", answer, statusbar_x);
+#endif
 
     update_statusbar_line(answer, statusbar_x);
 
@@ -1118,6 +1124,7 @@ int get_prompt_string(bool allow_tabs,
        wnoutrefresh(bottomwin);
     }
 
+
 #ifndef NANO_TINY
     /* Set the current position in the history list to the bottom and
      * free magichistory, if we need to. */
@@ -1129,6 +1136,7 @@ int get_prompt_string(bool allow_tabs,
     }
 #endif
 
+
     /* We've finished putting in an answer or run a normal shortcut's
      * associated function, so reset statusbar_x and statusbar_pww.  If
      * we've finished putting in an answer, reset the statusbar cursor
@@ -1165,7 +1173,7 @@ int do_prompt(bool allow_tabs,
 #ifndef DISABLE_TABCOMP
        bool allow_files,
 #endif
-       const shortcut *s, const char *curranswer,
+       int menu, const char *curranswer,
 #ifndef NANO_TINY
        filestruct **history_list,
 #endif
@@ -1184,7 +1192,7 @@ int do_prompt(bool allow_tabs,
 
     prompt = charalloc(((COLS - 4) * mb_cur_max()) + 1);
 
-    bottombars(s);
+    bottombars(menu);
 
     va_start(ap, msg);
     vsnprintf(prompt, (COLS - 4) * mb_cur_max(), msg, ap);
@@ -1199,7 +1207,7 @@ int do_prompt(bool allow_tabs,
 #ifndef NANO_TINY
        history_list,
 #endif
-       refresh_func, s
+       refresh_func, menu
 #ifndef DISABLE_TABCOMP
        , &list
 #endif
@@ -1224,6 +1232,7 @@ int do_prompt(bool allow_tabs,
            break;
     }
 
+
     blank_statusbar();
     wnoutrefresh(bottomwin);
 
index 43b8746c6cdfcae188941937fc1532fc392f23cb..ab44188a4d80da1460fdf42bd59c04d50b733b45 100644 (file)
@@ -91,34 +91,15 @@ extern char *full_operating_dir;
 extern char *alt_speller;
 #endif
 
-extern shortcut *main_list;
-extern shortcut *whereis_list;
-extern shortcut *replace_list;
-extern shortcut *replace_list_2;
-extern shortcut *gotoline_list;
-extern shortcut *writefile_list;
-extern shortcut *insertfile_list;
-#ifndef NANO_TINY
-extern shortcut *extcmd_list;
-#endif
-#ifndef DISABLE_HELP
-extern shortcut *help_list;
-#endif
-#ifndef DISABLE_SPELLER
-extern shortcut *spell_list;
-#endif
-#ifndef DISABLE_BROWSER
-extern shortcut *browser_list;
-extern shortcut *whereis_file_list;
-extern shortcut *gotodir_list;
-#endif
-
+extern sc *sclist;
+extern subnfunc *allfuncs;
 #ifdef ENABLE_COLOR
 extern syntaxtype *syntaxes;
 extern char *syntaxstr;
 #endif
 
 extern const shortcut *currshortcut;
+extern int currmenu;
 #ifndef NANO_TINY
 extern toggle *toggles;
 #endif
@@ -341,7 +322,7 @@ void save_history(void);
 #endif
 
 /* All functions in global.c. */
-size_t length_of_list(const shortcut *s);
+size_t length_of_list(int menu);
 #ifndef NANO_TINY
 void toggle_init_one(int val
 #ifndef DISABLE_HELP
@@ -472,7 +453,7 @@ RETSIGTYPE handle_sigwinch(int signal);
 void allow_pending_sigwinch(bool allow);
 #endif
 #ifndef NANO_TINY
-void do_toggle(const toggle *which);
+void do_toggle(int flag);
 #endif
 void disable_extended_io(void);
 #ifdef USE_SLANG
@@ -531,7 +512,7 @@ int get_prompt_string(bool allow_tabs,
 #ifndef NANO_TINY
        filestruct **history_list,
 #endif
-       void (*refresh_func)(void), const shortcut *s
+       void (*refresh_func)(void), int menu
 #ifndef DISABLE_TABCOMP
        , bool *list
 #endif
@@ -540,7 +521,7 @@ int do_prompt(bool allow_tabs,
 #ifndef DISABLE_TABCOMP
        bool allow_files,
 #endif
-       const shortcut *s, const char *curranswer,
+       int menu, const char *curranswer,
 #ifndef NANO_TINY
        filestruct **history_list,
 #endif
@@ -753,8 +734,9 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
 #ifndef DISABLE_MOUSE
 int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
 #endif
-const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
+const sc *get_shortcut(int menu, int *kbinput, bool
        *meta_key, bool *func_key);
+const sc *first_sc_for(int menu, void *func);
 #ifndef NANO_TINY
 const toggle *get_toggle(int kbinput, bool meta_key);
 #endif
@@ -770,7 +752,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
 void titlebar(const char *path);
 void set_modified(void);
 void statusbar(const char *msg, ...);
-void bottombars(const shortcut *s);
+void bottombars(int menu);
 void onekey(const char *keystroke, const char *desc, size_t len);
 void reset_cursor(void);
 void edit_draw(const filestruct *fileptr, const char *converted, int
@@ -788,6 +770,30 @@ void display_main_list(void);
 void do_cursorpos(bool constant);
 void do_cursorpos_void(void);
 void do_replace_highlight(bool highlight, const char *word);
+char *flagtostr(int flag);
+const subnfunc *sctofunc(sc *s);
+void print_sclist(void);
+sc *strtosc(int menu, char *input);
+function_type strtokeytype(char *str);
+int strtomenu(char *input);
+void assign_keyinfo(sc *s);
+void xon_complaint(void);
+void xoff_complaint(void);
+
+
+const char *cancel_msg;
+#ifndef NANO_TINY
+const char *case_sens_msg;
+const char *backwards_msg;
+#endif
+const char *replace_msg;
+const char *no_replace_msg;
+const char *go_to_line_msg;
+
+#ifdef HAVE_REGEX_H
+const char *regexp_msg;
+#endif
+
 #ifdef NANO_EXTRA
 void do_credits(void);
 #endif
index 7a4bf26e89c025df3347fcf4cd860e2efb3488af..c88bc40af3e666a19f5bf526840e7d86c89b9413 100644 (file)
@@ -347,6 +347,95 @@ void parse_syntax(char *ptr)
     }
 }
 
+void parse_keybinding(char *ptr)
+{
+    char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
+    sc *s, *newsc;
+    int i, menu;
+
+    assert(ptr != NULL);
+
+    if (*ptr == '\0') {
+       rcfile_error(N_("Missing key name"));
+       return;
+    }
+
+    keyptr = ptr;
+    ptr = parse_next_word(ptr);
+    keycopy = mallocstrcpy(NULL, keyptr);
+    for (i = 0; i < strlen(keycopy); i++)
+       keycopy[i] = toupper(keycopy[i]);
+
+    if (keycopy[0] != 'M' && keycopy[0] != '^' && keycopy[0] != 'F') {
+       rcfile_error(
+               N_("keybindings must begin with \"^\", \"M\", or \"F\"\n"));
+       return;
+    }
+
+    funcptr = ptr;
+    ptr = parse_next_word(ptr);
+
+    if (funcptr == NULL) {
+       rcfile_error(
+               N_("Must specify function to bind key to\n"));
+       return;
+    }
+
+    menuptr = ptr;
+    ptr = parse_next_word(ptr);
+
+    if (menuptr == NULL) {
+       rcfile_error(
+               /* Note to translators, do not translate the word "all"
+                  in the sentence below, everything else is fine */
+               N_("Must specify menu bind key to (or \"all\")\n"));
+       return;
+    }
+
+    menu = strtomenu(menuptr);
+    if (menu < 1) {
+       rcfile_error(
+               N_("Could not map name \"%s\" to a menu\n"), menuptr);
+       return;
+    }
+
+    newsc = strtosc(menu, funcptr);
+#ifdef DEBUG
+    fprintf(stderr, "newsc now address %d, menu func assigned = %d, menu = %d\n",
+       (int) newsc, (int) newsc->scfunc, menu);
+#endif
+
+    if (newsc == NULL) {
+       rcfile_error(
+               N_("Could not map name \"%s\" to a function\n"), funcptr);
+       return;
+    }
+    newsc->keystr = keycopy;
+    newsc->menu = menu;
+    newsc->type = strtokeytype(newsc->keystr);
+    assign_keyinfo(newsc);
+#ifdef DEBUG
+    fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
+    fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
+#endif
+
+    /* now let's have some fun.  Try and delete the other entries
+       we found for the same menu, then make this new new
+       beginning */
+    for (s = sclist; s != NULL; s = s->next) {
+        if (((s->menu & newsc->menu) || newsc->menu == MALL) &&
+          (s->seq == newsc->seq)) {
+           s->menu &= ~newsc->menu;
+#ifdef DEBUG
+           fprintf(stderr, "replaced menu entry %d\n", s->menu);
+#endif
+       }
+    }
+    newsc->next = sclist;
+    sclist = newsc;
+}
+
+
 /* Read and parse additional syntax files. */
 void parse_include(char *ptr)
 {
@@ -674,6 +763,8 @@ void parse_rcfile(FILE *rcstream
            parse_colors(ptr, FALSE);
        else if (strcasecmp(keyword, "icolor") == 0)
            parse_colors(ptr, TRUE);
+       else if (strcasecmp(keyword, "bind") == 0)
+           parse_keybinding(ptr);
 #endif /* ENABLE_COLOR */
        else
            rcfile_error(N_("Command \"%s\" not understood"), keyword);
index e80d59a056a355e636a9ed9b6a4456b68a2b101b..29f3c68ce9ff0cbb2571628272fdf104229f15c0 100644 (file)
@@ -136,6 +136,8 @@ int search_init(bool replacing, bool use_answer)
 {
     int i = 0;
     char *buf;
+    sc *s;
+    void *func = NULL;
     static char *backupstring = NULL;
        /* The search string we'll be using. */
 
@@ -173,7 +175,7 @@ int search_init(bool replacing, bool use_answer)
 #ifndef DISABLE_TABCOMP
        TRUE,
 #endif
-       replacing ? replace_list : whereis_list, backupstring,
+       replacing ? MREPLACE : MWHEREIS, backupstring,
 #ifndef NANO_TINY
        &search_history,
 #endif
@@ -201,6 +203,8 @@ int search_init(bool replacing, bool use_answer)
 #endif
        _(" (to replace)") : "", buf);
 
+    fflush(stderr);
+
     /* Release buf now that we don't need it anymore. */
     free(buf);
 
@@ -213,9 +217,13 @@ int search_init(bool replacing, bool use_answer)
        statusbar(_("Cancelled"));
        return -1;
     } else {
-       switch (i) {
-           case -2:            /* It's an empty string. */
-           case 0:             /* It's a new string. */
+       for  (s = sclist; s != NULL; s = s->next)
+           if ((s->menu & currmenu) && i == s->seq) {
+               func = s->scfunc;
+               break;
+           }
+
+       if (i == -2 || i == 0 ) {
 #ifdef HAVE_REGEX_H
                /* Use last_search if answer is an empty string, or
                 * answer if it isn't. */
@@ -223,33 +231,34 @@ int search_init(bool replacing, bool use_answer)
                        last_search : answer))
                    return -1;
 #endif
-               break;
+               ;
 #ifndef NANO_TINY
-           case TOGGLE_CASE_KEY:
+       } else if (func == (void *) case_sens_msg) {
                TOGGLE(CASE_SENSITIVE);
                backupstring = mallocstrcpy(backupstring, answer);
                return 1;
-           case TOGGLE_BACKWARDS_KEY:
+       } else if (func == (void *) backwards_msg) {
                TOGGLE(BACKWARDS_SEARCH);
                backupstring = mallocstrcpy(backupstring, answer);
                return 1;
 #endif
 #ifdef HAVE_REGEX_H
-           case NANO_REGEXP_KEY:
+       } else if (func == (void *) regexp_msg) {
                TOGGLE(USE_REGEXP);
                backupstring = mallocstrcpy(backupstring, answer);
                return 1;
 #endif
-           case NANO_TOOTHERSEARCH_KEY:
+       } else if (func == (void *) do_replace || 
+         func == (void *) no_replace_msg) {
                backupstring = mallocstrcpy(backupstring, answer);
                return -2;      /* Call the opposite search function. */
-           case NANO_TOGOTOLINE_KEY:
+       } else if (func == (void *) go_to_line_msg) {
                do_gotolinecolumn(openfile->current->lineno,
                        openfile->placewewant + 1, TRUE, TRUE, FALSE,
                        TRUE);
                                /* Put answer up on the statusbar and
                                 * fall through. */
-           default:
+       } else {
                return -1;
        }
     }
@@ -915,7 +924,7 @@ void do_replace(void)
 #ifndef DISABLE_TABCOMP
        TRUE,
 #endif
-       replace_list_2, last_replace,
+       MREPLACE2, last_replace,
 #ifndef NANO_TINY
        &replace_history,
 #endif
@@ -983,7 +992,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
 #ifndef DISABLE_TABCOMP
                TRUE,
 #endif
-               gotoline_list, use_answer ? ans : "",
+               MGOTOLINE, use_answer ? ans : "",
 #ifndef NANO_TINY
                NULL,
 #endif
index 166c182e679c1c46e016c86aea2c2f41867a7ab1..d152a97fb006fbf706d9f9ff17f7ca07a3f3194f 100644 (file)
@@ -1854,7 +1854,7 @@ bool do_int_spell_fix(const char *word)
 #ifndef DISABLE_TABCOMP
                TRUE,
 #endif
-               spell_list, word,
+               MSPELL, word,
 #ifndef NANO_TINY
                NULL,
 #endif
@@ -2337,7 +2337,7 @@ void do_spell(void)
     unlink(temp);
     free(temp);
 
-    currshortcut = main_list;
+    currmenu = MMAIN;
 
     /* If the spell-checker printed any error messages onscreen, make
      * sure that they're cleared off. */
index b205b1df5c9232592c8ff29e3eac9213ea84f011..77e6172e8941d7fadef346d79ba910534c0c6765 100644 (file)
@@ -1,3 +1,4 @@
+
 /* $Id$ */
 /**************************************************************************
  *   winio.c                                                              *
@@ -328,6 +329,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
 
     *meta_key = FALSE;
     *func_key = FALSE;
+    const sc *s;
 
     /* Read in a character. */
     while ((kbinput = get_input(win, 1)) == NULL);
@@ -492,49 +494,100 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
                        NANO_BACKSPACE_KEY;
                break;
            case KEY_DOWN:
-               retval = NANO_NEXTLINE_KEY;
+#ifdef KEY_SDOWN
+           /* ncurses and Slang don't support KEY_SDOWN. */
+           case KEY_SDOWN:
+#endif
+               s = first_sc_for(currmenu, (void *) do_down_void);
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_UP:
-               retval = NANO_PREVLINE_KEY;
+#ifdef KEY_SUP
+           /* ncurses and Slang don't support KEY_SUP. */
+           case KEY_SUP:
+#endif
+               s = first_sc_for(currmenu, (void *) do_up_void);
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_LEFT:
-               retval = NANO_BACK_KEY;
+#ifdef KEY_SLEFT
+           /* Slang doesn't support KEY_SLEFT. */
+           case KEY_SLEFT:
+#endif
+               s = first_sc_for(currmenu, (void *) do_up_void);
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_RIGHT:
-               retval = NANO_FORWARD_KEY;
+#ifdef KEY_SRIGHT
+           /* Slang doesn't support KEY_SRIGHT. */
+           case KEY_SRIGHT:
+#endif
+               s = first_sc_for(currmenu, (void *) do_right);
+                if (s) 
+                    retval = s->seq;
                break;
 #ifdef KEY_HOME
            /* HP-UX 10-11 doesn't support KEY_HOME. */
            case KEY_HOME:
-               retval = NANO_HOME_KEY;
-               break;
 #endif
+#ifdef KEY_SHOME
+           /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
+           case KEY_SHOME:
+#endif
+           case KEY_A1:        /* Home (7) on numeric keypad with
+                                * NumLock off. */
+               s = first_sc_for(currmenu, (void *) do_home);
+                if (s) 
+                    retval = s->seq;
+               break;
            case KEY_BACKSPACE:
-               retval = NANO_BACKSPACE_KEY;
+               s = first_sc_for(currmenu, (void *) do_backspace);
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_DC:
-               retval = ISSET(REBIND_DELETE) ? NANO_BACKSPACE_KEY :
-                       NANO_DELETE_KEY;
+#ifdef KEY_SDC
+           /* Slang doesn't support KEY_SDC. */
+           case KEY_SDC:
+#endif
+               if (ISSET(REBIND_DELETE))
+                   s = first_sc_for(currmenu, (void *) do_delete);
+               else
+                   s = first_sc_for(currmenu, (void *) do_backspace);
+
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_IC:
-               retval = NANO_INSERTFILE_KEY;
+#ifdef KEY_SIC
+           /* Slang doesn't support KEY_SIC. */
+           case KEY_SIC:
+#endif
+               s = first_sc_for(currmenu, (void *) do_insertfile_void);
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_NPAGE:
-               retval = NANO_NEXTPAGE_KEY;
-               break;
-           case KEY_PPAGE:
-               retval = NANO_PREVPAGE_KEY;
-               break;
-           case KEY_ENTER:
-               retval = NANO_ENTER_KEY;
-               break;
-           case KEY_A1:        /* Home (7) on numeric keypad with
+           case KEY_C3:        /* PageDown (4) on numeric keypad with
                                 * NumLock off. */
-               retval = NANO_HOME_KEY;
+               s = first_sc_for(currmenu, (void *) do_page_down);
+                if (s) 
+                    retval = s->seq;
                break;
+           case KEY_PPAGE:
            case KEY_A3:        /* PageUp (9) on numeric keypad with
                                 * NumLock off. */
-               retval = NANO_PREVPAGE_KEY;
+               s = first_sc_for(currmenu, (void *) do_page_up);
+                if (s) 
+                    retval = s->seq;
+               break;
+           case KEY_ENTER:
+               s = first_sc_for(currmenu, (void *) do_enter);
+                if (s) 
+                    retval = s->seq;
                break;
            case KEY_B2:        /* Center (5) on numeric keypad with
                                 * NumLock off. */
@@ -542,11 +595,17 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
                break;
            case KEY_C1:        /* End (1) on numeric keypad with
                                 * NumLock off. */
-               retval = NANO_END_KEY;
-               break;
-           case KEY_C3:        /* PageDown (4) on numeric keypad with
-                                * NumLock off. */
-               retval = NANO_NEXTPAGE_KEY;
+#ifdef KEY_END
+           /* HP-UX 10-11 doesn't support KEY_END. */
+           case KEY_END:
+#endif
+#ifdef KEY_SEND
+           /* HP-UX 10-11 and Slang don't support KEY_SEND. */
+           case KEY_SEND:
+#endif
+               s = first_sc_for(currmenu, (void *) do_end);
+                if (s) 
+                    retval = s->seq;
                break;
 #ifdef KEY_BEG
            /* Slang doesn't support KEY_BEG. */
@@ -558,13 +617,11 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
 #ifdef KEY_CANCEL
            /* Slang doesn't support KEY_CANCEL. */
            case KEY_CANCEL:
-               retval = NANO_CANCEL_KEY;
-               break;
+#ifdef KEY_SCANCEL
+           /* Slang doesn't support KEY_SCANCEL. */
+           case KEY_SCANCEL:
 #endif
-#ifdef KEY_END
-           /* HP-UX 10-11 doesn't support KEY_END. */
-           case KEY_END:
-               retval = NANO_END_KEY;
+               retval = first_sc_for(currmenu, (void *) cancel_msg)->seq;
                break;
 #endif
 #ifdef KEY_SBEG
@@ -574,61 +631,6 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
                retval = ERR;
                break;
 #endif
-#ifdef KEY_SCANCEL
-           /* Slang doesn't support KEY_SCANCEL. */
-           case KEY_SCANCEL:
-               retval = NANO_CANCEL_KEY;
-               break;
-#endif
-#ifdef KEY_SDC
-           /* Slang doesn't support KEY_SDC. */
-           case KEY_SDC:
-               retval = ISSET(REBIND_DELETE) ? NANO_BACKSPACE_KEY :
-                       NANO_DELETE_KEY;
-               break;
-#endif
-#ifdef KEY_SEND
-           /* HP-UX 10-11 and Slang don't support KEY_SEND. */
-           case KEY_SEND:
-               retval = NANO_END_KEY;
-               break;
-#endif
-#ifdef KEY_SHOME
-           /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
-           case KEY_SHOME:
-               retval = NANO_HOME_KEY;
-               break;
-#endif
-#ifdef KEY_SIC
-           /* Slang doesn't support KEY_SIC. */
-           case KEY_SIC:
-               retval = NANO_INSERTFILE_KEY;
-               break;
-#endif
-#ifdef KEY_SDOWN
-           /* ncurses and Slang don't support KEY_SDOWN. */
-           case KEY_SDOWN:
-               retval = NANO_NEXTLINE_KEY;
-               break;
-#endif
-#ifdef KEY_SUP
-           /* ncurses and Slang don't support KEY_SUP. */
-           case KEY_SUP:
-               retval = NANO_PREVLINE_KEY;
-               break;
-#endif
-#ifdef KEY_SLEFT
-           /* Slang doesn't support KEY_SLEFT. */
-           case KEY_SLEFT:
-               retval = NANO_BACK_KEY;
-               break;
-#endif
-#ifdef KEY_SRIGHT
-           /* Slang doesn't support KEY_SRIGHT. */
-           case KEY_SRIGHT:
-               retval = NANO_FORWARD_KEY;
-               break;
-#endif
 #ifdef KEY_SSUSPEND
            /* Slang doesn't support KEY_SSUSPEND. */
            case KEY_SSUSPEND:
@@ -1639,6 +1641,7 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
 {
     MEVENT mevent;
     bool in_bottomwin;
+    subnfunc *f;
 
     *mouse_x = -1;
     *mouse_y = -1;
@@ -1670,9 +1673,6 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
            size_t currslen;
                /* The number of shortcuts in the current shortcut
                 * list. */
-           const shortcut *s;
-               /* The actual shortcut we released on, starting at the
-                * first one in the current shortcut list. */
 
            /* Translate the mouse event coordinates so that they're
             * relative to bottomwin. */
@@ -1694,10 +1694,10 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
            j = *mouse_y - 1;
 
            /* Get the shortcut lists' length. */
-           if (currshortcut == main_list)
+           if (currmenu == MMAIN)
                currslen = MAIN_VISIBLE;
            else {
-               currslen = length_of_list(currshortcut);
+               currslen = length_of_list(currmenu);
 
                /* We don't show any more shortcuts than the main list
                 * does. */
@@ -1730,20 +1730,16 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
 
            /* Go through the shortcut list to determine which shortcut
             * we released/clicked on. */
-           s = currshortcut;
+           f = allfuncs;
 
            for (; j > 0; j--)
-               s = s->next;
-
-           /* And put back the equivalent key.  Assume that each
-            * shortcut has, at the very least, an equivalent control
-            * key, an equivalent primary meta key sequence, or both. */
-           if (s->ctrlval != NANO_NO_KEY) {
-               unget_kbinput(s->ctrlval, FALSE, FALSE);
-               return 1;
-           } else if (s->metaval != NANO_NO_KEY) {
-               unget_kbinput(s->metaval, TRUE, FALSE);
-               return 1;
+                while (f != NULL && (f->menus & currmenu) != 0)
+                    f = f->next;
+
+           /* And put back the equivalent key. */
+           if (f != NULL) {
+                const sc *s = first_sc_for(currmenu, (void *) f->scfunc);
+               unget_kbinput(s->seq, s->type == META, FALSE);
            }
        } else
            /* Handle releases/clicks of the first mouse button that
@@ -1795,53 +1791,29 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
  * example, passing in a meta key sequence that corresponds to a
  * function with a control key, a function key, and a meta key sequence
  * will return the control key corresponding to that function. */
-const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
+const sc *get_shortcut(int menu, int *kbinput, bool
        *meta_key, bool *func_key)
 {
-    const shortcut *s = s_list;
-    size_t slen = length_of_list(s_list);
+    sc *s;
 
 #ifdef DEBUG
     fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s, func_key = %s\n", *kbinput, *meta_key ? "TRUE" : "FALSE", *func_key ? "TRUE" : "FALSE");
 #endif
 
     /* Check for shortcuts. */
-    for (; slen > 0; slen--) {
-       /* We've found a shortcut if:
-        *
-        * 1. The key exists.
-        * 2. The key is a control key in the shortcut list.
-        * 3. meta_key is TRUE and the key is the primary or
-        *    miscellaneous meta sequence in the shortcut list.
-        * 4. func_key is TRUE and the key is a function key in the
-        *    shortcut list. */
-
-       if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
-               (*meta_key && (*kbinput == s->metaval || *kbinput ==
-               s->miscval)) || (*func_key && *kbinput ==
-               s->funcval))) {
-           break;
-       }
-
-       s = s->next;
-    }
-
-    /* Translate the shortcut to either its control key or its meta key
-     * equivalent.  Assume that the shortcut has an equivalent control
-     * key, an equivalent primary meta key sequence, or both. */
-    if (slen > 0) {
-       if (s->ctrlval != NANO_NO_KEY) {
-           *meta_key = FALSE;
-           *func_key = FALSE;
-           *kbinput = s->ctrlval;
-           return s;
-       } else if (s->metaval != NANO_NO_KEY) {
-           *meta_key = TRUE;
-           *func_key = FALSE;
-           *kbinput = s->metaval;
+    for (s = sclist; s != NULL; s = s->next) {
+        if ((menu & s->menu)
+               && ((s->type == META && *meta_key == TRUE && *kbinput == s->seq)
+               || (s->type != META && *kbinput == s->seq))) {
+#ifdef DEBUG
+           fprintf (stderr, "matched seq \"%s\" and btw meta was %d (menus %d = %d)\n", s->keystr, *meta_key, menu, s->menu);
+#endif
            return s;
        }
     }
+#ifdef DEBUG
+    fprintf (stderr, "matched nothing btw meta was %d\n", *meta_key);
+#endif
 
     return NULL;
 }
@@ -2375,19 +2347,21 @@ void statusbar(const char *msg, ...)
 
 /* Display the shortcut list in s on the last two rows of the bottom
  * portion of the window. */
-void bottombars(const shortcut *s)
+void bottombars(int menu)
 {
     size_t i, colwidth, slen;
+    subnfunc *f;
+    const sc *s;
 
     if (ISSET(NO_HELP))
        return;
 
-    if (s == main_list) {
+    if (menu == MMAIN) {
        slen = MAIN_VISIBLE;
 
-       assert(slen <= length_of_list(s));
+       assert(slen <= length_of_list(menu));
     } else {
-       slen = length_of_list(s);
+       slen = length_of_list(menu);
 
        /* Don't show any more shortcuts than the main list does. */
        if (slen > MAIN_VISIBLE)
@@ -2402,26 +2376,34 @@ void bottombars(const shortcut *s)
 
     blank_bottombars();
 
-    for (i = 0; i < slen; i++, s = s->next) {
-       const char *keystr;
-       char foo[4] = "";
+#ifdef DEBUG
+    fprintf(stderr, "In bottombars, and slen == \"%d\"\n", (int) slen);
+#endif
 
-       /* Yucky sentinel values that we can't handle a better way. */
-       if (s->ctrlval == NANO_CONTROL_SPACE)
-           strcpy(foo, "^ ");
-       else if (s->ctrlval == NANO_CONTROL_8)
-           strcpy(foo, "^?");
-       /* Normal values.  Assume that the shortcut has an equivalent
-        * control key, meta key sequence, or both. */
-       else if (s->ctrlval != NANO_NO_KEY)
-           sprintf(foo, "^%c", s->ctrlval + 64);
-       else if (s->metaval != NANO_NO_KEY)
-           sprintf(foo, "M-%c", toupper(s->metaval));
+    for (f = allfuncs, i = 0; i < slen && f != NULL; f = f->next) {
 
-       keystr = foo;
+#ifdef DEBUG
+        fprintf(stderr, "Checking menu items....");
+#endif
+        if ((f->menus & menu) == 0)
+           continue;
 
+#ifdef DEBUG
+        fprintf(stderr, "found one! f->menus = %d\n", f->menus);
+#endif
+        s = first_sc_for(menu, f->scfunc);
+        if (s == NULL) {
+#ifdef DEBUG
+           fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
+#endif
+            continue;
+        }
        wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
-       onekey(keystr, s->desc, colwidth + (COLS % colwidth));
+#ifdef DEBUG
+        fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
+#endif
+       onekey(s->keystr, f->desc, colwidth + (COLS % colwidth));
+        i++;
     }
 
     wnoutrefresh(bottomwin);
@@ -3184,14 +3166,14 @@ void total_refresh(void)
     total_redraw();
     titlebar(NULL);
     edit_refresh();
-    bottombars(currshortcut);
+    bottombars(currmenu);
 }
 
 /* Display the main shortcut list on the last two rows of the bottom
  * portion of the window. */
 void display_main_list(void)
 {
-    bottombars(main_list);
+    bottombars(MMAIN);
 }
 
 /* If constant is TRUE, we display the current cursor position only if