uip_comp_SOURCES = uip/comp.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c
-uip_comp_LDADD = $(LDADD) $(ICONVLIB)
+uip_comp_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
uip_dist_SOURCES = uip/dist.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c uip/forwsbr.c
-uip_dist_LDADD = $(LDADD) $(ICONVLIB)
+uip_dist_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
uip_flist_SOURCES = uip/flist.c
uip_forw_SOURCES = uip/forw.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c uip/forwsbr.c
-uip_forw_LDADD = $(LDADD) $(ICONVLIB)
+uip_forw_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
uip_inc_SOURCES = uip/inc.c uip/scansbr.c uip/dropsbr.c uip/termsbr.c \
uip/popsbr.c
uip_repl_SOURCES = uip/repl.c uip/replsbr.c uip/whatnowproc.c \
uip/whatnowsbr.c uip/sendsbr.c uip/annosbr.c uip/distsbr.c
-uip_repl_LDADD = $(LDADD) $(ICONVLIB)
+uip_repl_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
uip_rmf_SOURCES = uip/rmf.c
uip_whatnow_SOURCES = uip/whatnow.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c
+uip_whatnow_LDADD = $(LDADD) $(READLINELIB)
uip_whom_SOURCES = uip/whom.c uip/distsbr.c
sbr/snprintb.c sbr/ssequal.c sbr/strcasecmp.c \
sbr/strindex.c sbr/trimcpy.c sbr/uprf.c sbr/vfgets.c \
sbr/fmt_def.c sbr/m_msgdef.c sbr/mf.c sbr/utils.c \
- sbr/m_mktemp.c config/config.c config/version.c
+ sbr/m_mktemp.c sbr/getansreadline.c config/config.c \
+ config/version.c
sbr_libmh_a_CPPFLAGS = -I./sbr -DNMHETCDIR='"$(sysconfdir)"' \
-DMAILSPOOL='"$(mailspool)"' \
--- /dev/null
+dnl
+dnl Our readline heuristic. If we haven't been asked about readline, then
+dnl try to compile with it. If we've been asked for it, then we fail
+dnl if we cannot use it. If we were explicitly NOT asked for it, then
+dnl don't even try to use it.
+dnl
+
+AC_DEFUN([NMH_READLINE],
+[AC_ARG_WITH([readline],
+ AS_HELP_STRING([--with-readline],
+ [enable readline editing for whatnow (default=maybe)]),
+ [], [with_readline=maybe])
+AS_IF([test x"$with_readline" = xyes -o x"$with_readline" = xmaybe],
+ [save_LIBS="$LIBS"
+ LIBS=
+ AC_SEARCH_LIBS([readline], [readline editline],
+ [READLINELIB="$LIBS"
+ AC_DEFINE([READLINE_SUPPORT], [1],
+ [Support for using readline() in whatnow])],
+ [AS_IF([test x"$with_readline" = xyes],
+ [AC_MSG_ERROR([Unable to find a readline library])])])
+ LIBS="$save_LIBS"])
+])
+
+AC_SUBST([READLINELIB])
--- /dev/null
+
+/*
+ * getansreadline.c -- get an answer from the user, with readline
+ *
+ * This code is Copyright (c) 2012, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/signals.h>
+#include <h/m_setjmp.h>
+#include <signal.h>
+#include <errno.h>
+
+#ifdef READLINE_SUPPORT
+#include <readline/readline.h>
+#include <readline/history.h>
+
+static struct swit *rl_cmds;
+
+static char *nmh_command_generator(const char *, int);
+static char **nmh_completion(const char *, int, int);
+static void initialize_readline(void);
+
+static char ansbuf[BUFSIZ];
+static sigjmp_buf sigenv;
+
+#if 0
+/*
+ * static prototypes
+ */
+static void intrser (int);
+
+
+char **
+getans (char *prompt, struct swit *ansp)
+{
+ int i;
+ SIGNAL_HANDLER istat = NULL;
+ char *cp, **cpp;
+
+ if (!(sigsetjmp(sigenv, 1))) {
+ istat = SIGNAL (SIGINT, intrser);
+ } else {
+ SIGNAL (SIGINT, istat);
+ return NULL;
+ }
+
+ for (;;) {
+ printf ("%s", prompt);
+ fflush (stdout);
+ cp = ansbuf;
+ while ((i = getchar ()) != '\n') {
+ if (i == EOF) {
+ /*
+ * If we get an EOF, return
+ */
+ if (feof(stdin))
+ siglongjmp (sigenv, 1);
+
+ /*
+ * For errors, if we get an EINTR that means that we got
+ * a signal and we should retry. If we get another error,
+ * then just return.
+ */
+
+ else if (ferror(stdin)) {
+ if (errno == EINTR) {
+ clearerr(stdin);
+ continue;
+ }
+ fprintf(stderr, "\nError %s during read\n",
+ strerror(errno));
+ siglongjmp (sigenv, 1);
+ } else {
+ /*
+ * Just for completeness's sake ...
+ */
+
+ fprintf(stderr, "\nUnknown problem in getchar()\n");
+ siglongjmp (sigenv, 1);
+ }
+ }
+ if (cp < &ansbuf[sizeof ansbuf - 1])
+ *cp++ = i;
+ }
+ *cp = '\0';
+ if (ansbuf[0] == '?' || cp == ansbuf) {
+ printf ("Options are:\n");
+ print_sw (ALL, ansp, "", stdout);
+ continue;
+ }
+ cpp = brkstring (ansbuf, " ", NULL);
+ switch (smatch (*cpp, ansp)) {
+ case AMBIGSW:
+ ambigsw (*cpp, ansp);
+ continue;
+ case UNKWNSW:
+ printf (" -%s unknown. Hit <CR> for help.\n", *cpp);
+ continue;
+ default:
+ SIGNAL (SIGINT, istat);
+ return cpp;
+ }
+ }
+}
+
+
+static void
+intrser (int i)
+{
+ NMH_UNUSED (i);
+
+ /*
+ * should this be siglongjmp?
+ */
+ siglongjmp (sigenv, 1);
+}
+#endif
+
+/*
+ * getans, but with readline support
+ */
+
+char **
+getans_via_readline(char *prompt, struct swit *ansp)
+{
+ char *ans, **cpp;
+
+ initialize_readline();
+ rl_cmds = ansp;
+
+ for (;;) {
+ ans = readline(prompt);
+ /*
+ * If we get an EOF, return
+ */
+
+ if (ans == NULL)
+ return NULL;
+
+ if (ans[0] == '?' || ans[0] == '\0') {
+ printf("Options are:\n");
+ print_sw(ALL, ansp, "", stdout);
+ free(ans);
+ continue;
+ }
+ add_history(ans);
+ strncpy(ansbuf, ans, sizeof(ansbuf));
+ ansbuf[sizeof(ansbuf) - 1] = '\0';
+ cpp = brkstring(ansbuf, " ", NULL);
+ switch (smatch(*cpp, ansp)) {
+ case AMBIGSW:
+ ambigsw(*cpp, ansp);
+ continue;
+ case UNKWNSW:
+ printf(" -%s unknown. Hit <CR> for help.\n", *cpp);
+ continue;
+ default:
+ free(ans);
+ return cpp;
+ }
+ free(ans);
+ }
+}
+
+static void
+initialize_readline(void)
+{
+ rl_readline_name = "Nmh";
+ rl_attempted_completion_function = nmh_completion;
+}
+
+static char **
+nmh_completion(const char *text, int start, int end)
+{
+ char **matches;
+
+ matches = (char **) NULL;
+
+ if (start == 0)
+ matches = rl_completion_matches(text, nmh_command_generator);
+
+ return matches;
+}
+
+static char *
+nmh_command_generator(const char *text, int state)
+{
+ static int list_index, len;
+ char *name, *p;
+ char buf[256];
+
+ if (!state) {
+ list_index = 0;
+ len = strlen(text);
+ }
+
+ while (name = rl_cmds[list_index].sw) {
+ list_index++;
+ strncpy(buf, name, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ p = *brkstring(buf, " ", NULL);
+ if (strncmp(p, text, len) == 0)
+ return strdup(p);
+ }
+
+ return NULL;
+}
+#endif /* READLINE_SUPPORT */
+