~kevin8t8/mutt

f4ff768c2764502a974042e1fe9d861a7a92fbcf — Kevin McCarthy 3 days ago e0232be master
Enable nonl() mode for ncurses.  closes #362.

This patch is based on the patch from Mike Frysinger, archived from
the old trac system at:
https://gitlab.com/muttmua/trac-tickets/-/blob/master/attachments/3494/mutt-enter-return-hg-6658.patch

This version creates a new key symbol, <KeypadEnter> for the KEY_ENTER
value returned by getch().  According to Vincent Lefèvre's research,
that corresponds to the "key pad" Enter key.  If KEY_ENTER is not
defined, it binds the symbol to "\n".  It does this after the
KeyNames[] definitions of <Enter> and <Return> so they remain the
default shown by <what-key>.

Since Mutt already accepts KEY_ENTER at the y/n prompt, add it for all
the built-in operations too.

Bindings with "\r" and "\n" in the binding_t structures don't need
"<enter>" and "<return>" to be re-specified in km_init(), so remove
those.  Instead add the "<KeypadEnter>" bindings there.

Remove unnecessary Alias menu bindings for OP_GENERIC_SELECT_ENTRY in
km_init().

As a note: I don't believe non-extended key symbol bindings need to be
bound inside km_init().  I'm not clear why this was done, or what
purpose it serves.  I'll do a bit more research, but if I can't
uncover any issues, will move them inside the binding_t structures in
another commit.
6 files changed, 56 insertions(+), 31 deletions(-)

M doc/gen-map-doc
M doc/manual.xml.head
M functions.h
M keymap.c
M main.c
M mutt_curses.h
M doc/gen-map-doc => doc/gen-map-doc +2 -1
@@ 35,7 35,8 @@ while (<STDIN>) {
    $binding =~ s/^\\(0\d+)$/'^'.chr(64+oct($1))/e;
    $binding =~ s/^\\(0\d+)(.)/'^'.chr(64+oct($1)) ." $2"/e;
    $binding =~ s/\\t/&lt;Tab&gt;/;
    $binding =~ s/M_ENTER_S/&lt;Return&gt;/;
    $binding =~ s/\\r/&lt;Return&gt;/;
    $binding =~ s/\\n/&lt;Enter&gt;/;
    $binding =~ s/NULL//;
    die "unknown key $binding" if $binding =~ /\\[^\\]|<|>/;
    die "unknown OP $op" unless $OPS{$op};

M doc/manual.xml.head => doc/manual.xml.head +27 -0
@@ 2767,6 2767,7 @@ addition, <emphasis>key</emphasis> may be a symbolic name as shown in
<row><entry>&lt;insert&gt;</entry><entry>Insert</entry></row>
<row><entry>&lt;enter&gt;</entry><entry>Enter</entry></row>
<row><entry>&lt;return&gt;</entry><entry>Return</entry></row>
<row><entry>&lt;keypadenter&gt;</entry><entry>Enter key on numeric keypad</entry></row>
<row><entry>&lt;home&gt;</entry><entry>Home</entry></row>
<row><entry>&lt;end&gt;</entry><entry>End</entry></row>
<row><entry>&lt;space&gt;</entry><entry>Space bar</entry></row>


@@ 2834,6 2835,32 @@ specified key sequence.
  </para>
</sect2>

<sect2 id="crlf">
  <title>Enter versus Return</title>

  <para>
    Prior to version 2.2, Mutt used a default ncurses mode
    (<quote><literal>nl()</literal></quote>).  This mode maps keyboard
    input of either <literal>&lt;Enter&gt;</literal> or
    <literal>&lt;Return&gt;</literal> to the same value, which Mutt
    interpreted as <literal>&lt;Return&gt;</literal> internally.
  </para>
  <para>
    However, starting in version 2.2, this mode is turned off,
    allowing <literal>&lt;Return&gt;</literal> and
    <literal>&lt;Enter&gt;</literal> to be mapped separately, if
    desired.  The default keyboard mappings set both, but you can
    override this or create new bindings with one or the other (or
    both).
  </para>
  <para>
    Note that in terminal application, such as Mutt,
    <literal>&lt;Enter&gt;</literal> is the same as <quote>\n</quote>
    and <literal>^J</literal>; while <literal>&lt;Return&gt;</literal>
    is the same as <quote>\r</quote> and <literal>^M</literal>.
  </para>
</sect2>

</sect1>

<sect1 id="cd">

M functions.h => functions.h +15 -8
@@ 22,8 22,9 @@
 *
 * Notes:
 *
 * - If you want to bind \n or \r, use MUTT_ENTER_S so that it will work
 * correctly under both ncurses and S-Lang
 * - For "enter" bindings, add entries for "\n" and "\r" in the struct
 *   binding_t below, and ALSO add a km_bindkey() call with
 *   "<keypadenter>" inside km_init().
 *
 * - If you need to bind a control char, use the octal value because the \cX
 * construct does not work at this level.


@@ 70,7 71,8 @@ const struct binding_t OpGeneric[] = { /* map: generic */
  { "tag-prefix-cond",	OP_TAG_PREFIX_COND,	NULL },
  { "end-cond",		OP_END_COND,		NULL },
  { "shell-escape",	OP_SHELL_ESCAPE,	"!" },
  { "select-entry",	OP_GENERIC_SELECT_ENTRY,MUTT_ENTER_S },
  { "select-entry",	OP_GENERIC_SELECT_ENTRY,"\r" },
  { "select-entry",	OP_GENERIC_SELECT_ENTRY,"\n" },
  { "search",		OP_SEARCH,		"/" },
  { "search-reverse",	OP_SEARCH_REVERSE,	"\033/" },
  { "search-opposite",	OP_SEARCH_OPPOSITE,	NULL },


@@ 160,7 162,8 @@ const struct binding_t OpMain[] = { /* map: index */
  { "show-version",		OP_VERSION,			"V" },
  { "set-flag",			OP_MAIN_SET_FLAG,		"w" },
  { "clear-flag",		OP_MAIN_CLEAR_FLAG,		"W" },
  { "display-message",		OP_DISPLAY_MESSAGE,		MUTT_ENTER_S },
  { "display-message",		OP_DISPLAY_MESSAGE,		"\r" },
  { "display-message",		OP_DISPLAY_MESSAGE,	        "\n" },
  { "mark-message",		OP_MARK_MSG,			"~" },
  { "buffy-list",		OP_BUFFY_LIST,			"." },
  { "sync-mailbox",		OP_MAIN_SYNC_FOLDER,		"$" },


@@ 284,7 287,8 @@ const struct binding_t OpPager[] = { /* map: pager */
  { "search",		OP_SEARCH,			"/" },
  { "search-reverse",	OP_SEARCH_REVERSE,		"\033/" },
  { "search-opposite",	OP_SEARCH_OPPOSITE,		NULL },
  { "next-line",	OP_NEXT_LINE,			MUTT_ENTER_S },
  { "next-line",	OP_NEXT_LINE,			"\r" },
  { "next-line",	OP_NEXT_LINE,			"\n" },
  { "error-history",	OP_ERROR_HISTORY,		NULL },
  { "jump",		OP_JUMP,			NULL },
  { "next-unread",	OP_MAIN_NEXT_UNREAD,		NULL },


@@ 345,7 349,8 @@ const struct binding_t OpAttach[] = { /* map: attachment */
  { "list-reply",	OP_LIST_REPLY, "L" },
  { "forward-message",	OP_FORWARD_MESSAGE,		"f" },
  { "view-text",	OP_ATTACH_VIEW_TEXT,		"T" },
  { "view-attach",	OP_VIEW_ATTACH,			MUTT_ENTER_S },
  { "view-attach",	OP_VIEW_ATTACH,			"\r" },
  { "view-attach",	OP_VIEW_ATTACH,			"\n" },
  { "delete-entry",	OP_DELETE,			"d" },
  { "undelete-entry",	OP_UNDELETE,			"u" },
  { "collapse-parts",	OP_ATTACH_COLLAPSE,		"v" },


@@ 393,7 398,8 @@ const struct binding_t OpCompose[] = { /* map: compose */
  { "toggle-unlink",	OP_COMPOSE_TOGGLE_UNLINK,	"u" },
  { "toggle-recode",    OP_COMPOSE_TOGGLE_RECODE,	NULL },
  { "update-encoding",	OP_COMPOSE_UPDATE_ENCODING,	"U" },
  { "view-attach",	OP_VIEW_ATTACH,			MUTT_ENTER_S },
  { "view-attach",	OP_VIEW_ATTACH,			"\r" },
  { "view-attach",	OP_VIEW_ATTACH,			"\n" },
  { "view-mailcap",	OP_ATTACH_VIEW_MAILCAP,		NULL },
  { "view-pager",	OP_ATTACH_VIEW_PAGER,		NULL },
  { "view-text",	OP_ATTACH_VIEW_TEXT,		NULL },


@@ 528,7 534,8 @@ const struct binding_t OpSmime[] = { /* map: smime */

#ifdef MIXMASTER
const struct binding_t OpMix[] = { /* map: mixmaster */
  { "accept",		OP_MIX_USE,	MUTT_ENTER_S },
  { "accept",		OP_MIX_USE,	"\r" },
  { "accept",		OP_MIX_USE,	"\n" },
  { "append",		OP_MIX_APPEND,	"a"       },
  { "insert",		OP_MIX_INSERT,	"i"       },
  { "delete",		OP_MIX_DELETE,  "d"	  },

M keymap.c => keymap.c +11 -12
@@ 80,10 80,13 @@ static struct mapping_t KeyNames[] = {
  { "<Insert>",	KEY_IC },
  { "<Home>",	KEY_HOME },
  { "<End>",	KEY_END },
  { "<Enter>",	'\n' },
  { "<Return>",	'\r' },
#ifdef KEY_ENTER
  { "<Enter>",	KEY_ENTER },
  { "<KeypadEnter>",	KEY_ENTER },
#else
  { "<KeypadEnter>",	'\n' },
#endif
  { "<Return>",	MUTT_ENTER_C },
  { "<Esc>",	'\033' },
  { "<Tab>",	'\t' },
  { "<Space>",	' ' },


@@ 770,6 773,7 @@ void km_init (void)
  km_bindkey ("<space>", MENU_MIX, OP_GENERIC_SELECT_ENTRY);
  km_bindkey ("h", MENU_MIX, OP_MIX_CHAIN_PREV);
  km_bindkey ("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
  km_bindkey ("<keypadenter>", MENU_MIX, OP_MIX_USE);
#endif

#ifdef USE_AUTOCRYPT


@@ 809,8 813,7 @@ void km_init (void)
  km_bindkey ("7", MENU_GENERIC, OP_JUMP);
  km_bindkey ("8", MENU_GENERIC, OP_JUMP);
  km_bindkey ("9", MENU_GENERIC, OP_JUMP);

  km_bindkey ("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
  km_bindkey ("<keypadenter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);

  /* Miscellaneous extra bindings */



@@ 820,8 823,7 @@ void km_init (void)
  km_bindkey ("J", MENU_MAIN, OP_NEXT_ENTRY);
  km_bindkey ("K", MENU_MAIN, OP_PREV_ENTRY);
  km_bindkey ("x", MENU_MAIN, OP_EXIT);

  km_bindkey ("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
  km_bindkey ("<keypadenter>", MENU_MAIN, OP_DISPLAY_MESSAGE);

  km_bindkey ("x", MENU_PAGER, OP_EXIT);
  km_bindkey ("i", MENU_PAGER, OP_EXIT);


@@ 843,19 845,16 @@ void km_init (void)
  km_bindkey ("7", MENU_PAGER, OP_JUMP);
  km_bindkey ("8", MENU_PAGER, OP_JUMP);
  km_bindkey ("9", MENU_PAGER, OP_JUMP);
  km_bindkey ("<keypadenter>", MENU_PAGER, OP_NEXT_LINE);

  km_bindkey ("<enter>", MENU_PAGER, OP_NEXT_LINE);

  km_bindkey ("<return>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
  km_bindkey ("<enter>",  MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
  km_bindkey ("<space>", MENU_ALIAS, OP_TAG);

  km_bindkey ("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
  km_bindkey ("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
  km_bindkey ("<keypadenter>", MENU_ATTACH, OP_VIEW_ATTACH);

  /* edit-to (default "t") hides generic tag-entry in Compose menu
     This will bind tag-entry to  "T" in the Compose menu */
  km_bindkey ("T", MENU_COMPOSE, OP_TAG);
  km_bindkey ("<keypadenter>", MENU_COMPOSE, OP_VIEW_ATTACH);
}

void km_error_key (int menu)

M main.c => main.c +1 -0
@@ 604,6 604,7 @@ static void start_curses (void)
  keypad (stdscr, TRUE);
  cbreak ();
  noecho ();
  nonl ();
#if HAVE_TYPEAHEAD
  typeahead (-1);       /* simulate smooth scrolling */
#endif

M mutt_curses.h => mutt_curses.h +0 -10
@@ 33,13 33,6 @@
#define KEY_DC SL_KEY_DELETE
#define KEY_IC SL_KEY_IC

/*
 * ncurses and SLang seem to send different characters when the Enter key is
 * pressed, so define some macros to properly detect the Enter key.
 */
#define MUTT_ENTER_C '\r'
#define MUTT_ENTER_S "\r"

#else /* USE_SLANG_CURSES */

#if HAVE_NCURSESW_NCURSES_H


@@ 52,9 45,6 @@
# include <curses.h>
#endif

#define MUTT_ENTER_C '\n'
#define MUTT_ENTER_S "\n"

#endif /* USE_SLANG_CURSES */

/* AIX defines ``lines'' in <term.h>, but it's used as a var name in