-
-/*
- * repl.c -- reply to a message
+/* repl.c -- reply to a message
*
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
*/
#include <h/mh.h>
+#include <h/mime.h>
#include <h/utils.h>
-
-
-static struct swit switches[] = {
-#define GROUPSW 0
- { "group", 0 },
-#define NGROUPSW 1
- { "nogroup", 0 },
-#define ANNOSW 2
- { "annotate", 0 },
-#define NANNOSW 3
- { "noannotate", 0 },
-#define CCSW 4
- { "cc all|to|cc|me", 0 },
-#define NCCSW 5
- { "nocc type", 0 },
-#define DFOLDSW 6
- { "draftfolder +folder", 0 },
-#define DMSGSW 7
- { "draftmessage msg", 0 },
-#define NDFLDSW 8
- { "nodraftfolder", 0 },
-#define EDITRSW 9
- { "editor editor", 0 },
-#define NEDITSW 10
- { "noedit", 0 },
-#define FCCSW 11
- { "fcc folder", 0 },
-#define FILTSW 12
- { "filter filterfile", 0 },
-#define FORMSW 13
- { "form formfile", 0 },
-#define FRMTSW 14
- { "format", 5 },
-#define NFRMTSW 15
- { "noformat", 7 },
-#define INPLSW 16
- { "inplace", 0 },
-#define NINPLSW 17
- { "noinplace", 0 },
-#define MIMESW 18
- { "mime", 0 },
-#define NMIMESW 19
- { "nomime", 0 },
-#define QURYSW 20
- { "query", 0 },
-#define NQURYSW 21
- { "noquery", 0 },
-#define WHATSW 22
- { "whatnowproc program", 0 },
-#define NWHATSW 23
- { "nowhatnowproc", 0 },
-#define WIDTHSW 24
- { "width columns", 0 },
-#define VERSIONSW 25
- { "version", 0 },
-#define HELPSW 26
- { "help", 0 },
-#define FILESW 27
- { "file file", 4 }, /* interface from msh */
-#define BILDSW 28
- { "build", 5 }, /* interface from mhe */
-#define ATFILESW 29
- { "atfile", 0 },
-#define NOATFILESW 30
- { "noatfile", 0 },
-#define FMTPROCSW 31
- { "fmtproc program", 0 },
-#define NFMTPROCSW 32
- { "nofmtproc", 0 },
-
- { NULL, 0 }
-};
-
-static struct swit ccswitches[] = {
-#define CTOSW 0
- { "to", 0 },
-#define CCCSW 1
- { "cc", 0 },
-#define CMESW 2
- { "me", 0 },
-#define CALSW 3
- { "all", 0 },
- { NULL, 0 }
-};
-
-static struct swit aqrnl[] = {
-#define NOSW 0
- { "quit", 0 },
-#define YESW 1
- { "replace", 0 },
-#define LISTDSW 2
- { "list", 0 },
-#define REFILSW 3
- { "refile +folder", 0 },
-#define NEWSW 4
- { "new", 0 },
- { NULL, 0 }
-};
+#include "sbr/m_maildir.h"
+
+#define REPL_SWITCHES \
+ X("group", 0, GROUPSW) \
+ X("nogroup", 0, NGROUPSW) \
+ X("annotate", 0, ANNOSW) \
+ X("noannotate", 0, NANNOSW) \
+ X("cc all|to|cc|me", 0, CCSW) \
+ X("nocc all|to|cc|me", 0, NCCSW) \
+ X("draftfolder +folder", 0, DFOLDSW) \
+ X("draftmessage msg", 0, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("editor editor", 0, EDITRSW) \
+ X("noedit", 0, NEDITSW) \
+ X("convertargs type argstring", 0, CONVERTARGSW) \
+ X("fcc folder", 0, FCCSW) \
+ X("filter filterfile", 0, FILTSW) \
+ X("form formfile", 0, FORMSW) \
+ X("format", 5, FRMTSW) \
+ X("noformat", 7, NFRMTSW) \
+ X("inplace", 0, INPLSW) \
+ X("noinplace", 0, NINPLSW) \
+ X("mime", 0, MIMESW) \
+ X("nomime", 0, NMIMESW) \
+ X("query", 0, QURYSW) \
+ X("noquery", 0, NQURYSW) \
+ X("whatnowproc program", 0, WHATSW) \
+ X("nowhatnowproc", 0, NWHATSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("file file", 4, FILESW) \
+ X("build", 5, BILDSW) /* interface from mhe */ \
+ X("atfile", 0, ATFILESW) \
+ X("noatfile", 0, NOATFILESW) \
+ X("fmtproc program", 0, FMTPROCSW) \
+ X("nofmtproc", 0, NFMTPROCSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(REPL);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(REPL, switches);
+#undef X
+
+#define CC_SWITCHES \
+ X("to", 0, CTOSW) \
+ X("cc", 0, CCCSW) \
+ X("me", 0, CMESW) \
+ X("all", 0, CALSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(CC);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(CC, ccswitches);
+#undef X
+
+#define DISPO_SWITCHES \
+ X("quit", 0, NOSW) \
+ X("replace", 0, YESW) \
+ X("list", 0, LISTDSW) \
+ X("refile +folder", 0, REFILSW) \
+ X("new", 0, NEWSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DISPO);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DISPO, aqrnl);
+#undef X
static struct swit aqrl[] = {
- { "quit", 0 },
- { "replace", 0 },
- { "list", 0 },
- { "refile +folder", 0 },
- { NULL, 0 }
+ { "quit", 0, NOSW },
+ { "replace", 0, YESW },
+ { "list", 0, LISTDSW },
+ { "refile +folder", 0, REFILSW },
+ { NULL, 0, 0 }
};
short ccto = -1; /* global for replsbr */
short ccme = -1;
short querysw = 0;
-short outputlinelen = OUTPUTLINELEN;
-short groupreply = 0; /* Is this a group reply? */
+static short outputlinelen = OUTPUTLINELEN;
+static short groupreply = 0; /* Is this a group reply? */
-int mime = 0; /* include original as MIME part */
-char *form = NULL; /* form (components) file */
-char *filter = NULL; /* message filter file */
-char *fcc = NULL; /* folders to add to Fcc: header */
+static int mime = 0; /* include original as MIME part */
+static char *form = NULL; /* form (components) file */
+static char *filter = NULL; /* message filter file */
+static char *fcc = NULL; /* folders to add to Fcc: header */
/*
* prototypes
*/
-void docc (char *, int);
+static void docc (char *, int);
+static void add_convert_header (const char *, char *, char *, char *);
int
char *folder = NULL, *msg = NULL, *dfolder = NULL;
char *dmsg = NULL, *ed = NULL, drft[BUFSIZ], buf[BUFSIZ];
char **argp, **arguments;
+ svector_t convert_types = svector_create (10);
+ svector_t convert_args = svector_create (10);
+ size_t n;
struct msgs *mp = NULL;
struct stat st;
FILE *in;
int buildsw = 0;
-#ifdef LOCALE
- setlocale(LC_ALL, "");
-#endif
- invo_name = r1bindex (argv[0], '/');
-
- /* read user profile/context */
- context_read();
+ if (nmh_init(argv[0], 1)) { return 1; }
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
nedit++;
continue;
+ case CONVERTARGSW: {
+ char *type;
+ size_t i;
+
+ if (!(type = *argp++)) {
+ adios (NULL, "missing type argument to %s", argp[-2]);
+ }
+ if (!(cp = *argp++)) {
+ adios (NULL, "missing argstring argument to %s",
+ argp[-3]);
+ }
+
+ for (i = 0; i < svector_size (convert_types); ++i) {
+ if (! strcmp (svector_at (convert_types, i), type)) {
+ /* Already saw this type, so just update
+ its args. */
+ svector_strs (convert_args)[i] = cp;
+ break;
+ }
+ }
+
+ if (i == svector_size (convert_types)) {
+ svector_push_back (convert_types, type);
+ svector_push_back (convert_args, cp);
+ }
+ continue;
+ }
+
case WHATSW:
if (!(whatnowproc = *argp++) || *whatnowproc == '-')
adios (NULL, "missing argument to %s", argp[-2]);
nwhat = 0;
continue;
case BILDSW:
- buildsw++; /* fall... */
+ buildsw++;
+ /* FALLTHRU */
case NWHATSW:
nwhat++;
continue;
if (fcc)
fcc = add (", ", fcc);
fcc = add (cp, fcc);
- if (dp)
- free (dp);
+ free(dp);
continue;
case FILESW:
if (*cp == '+' || *cp == '@') {
if (folder)
adios (NULL, "only one folder at a time!");
- else
- folder = pluspath (cp);
+ folder = pluspath (cp);
} else {
if (msg)
adios (NULL, "only one message at a time!");
- else
- msg = cp;
+ msg = cp;
}
}
if (ccme == -1)
ccme = groupreply;
- cwd = getcpy (pwd ());
+ cwd = mh_xstrdup(pwd ());
if (!context_find ("path"))
free (path ("./", TFOLDER));
if (!buildsw && stat (drft, &st) != NOTOK) {
printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size);
for (i = LISTDSW; i != YESW;) {
- if (!(argp = getans ("\nDisposition? ", isdf ? aqrnl : aqrl)))
+ if (!(argp = read_switch_multiword ("\nDisposition? ",
+ isdf ? aqrnl : aqrl)))
done (1);
switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) {
case NOSW:
i = YESW;
break;
default:
- advise (NULL, "say what?");
+ inform("say what?");
break;
}
}
adios (maildir, "unable to change directory to");
/* read folder and create message structure */
- if (!(mp = folder_read (folder)))
+ if (!(mp = folder_read (folder, 1)))
adios (NULL, "unable to read folder %s", folder);
/* check for empty folder */
context_save (); /* save the context file */
}
- msg = file ? file : getcpy (m_name (mp->lowsel));
+ msg = file ? file : mh_xstrdup(m_name (mp->lowsel));
if ((in = fopen (msg, "r")) == NULL)
adios (msg, "unable to open");
fcc, fmtproc);
fclose (in);
+ {
+ char *filename = file ? file : concat (mp->foldpath, "/", msg, NULL);
+
+ for (n = 0; n < svector_size (convert_types); ++n) {
+ add_convert_header (svector_at (convert_types, n),
+ svector_at (convert_args, n),
+ filename, drft);
+ }
+ if (! file) {
+ free (filename);
+ }
+ }
+
if (nwhat)
done (0);
what_now (ed, nedit, NOUSE, drft, msg, 0, mp, anot ? "Replied" : NULL,
inplace, cwd, atfile);
+
+ svector_free (convert_args);
+ svector_free (convert_types);
+
done (1);
return 1;
}
break;
}
}
+
+/*
+ * Add pseudoheaders that will pass the convert arguments to
+ * mhbuild. They have the form:
+ * MHBUILD_FILE_PSEUDOHEADER-text/calendar: /home/user/Mail/inbox/7
+ * MHBUILD_ARGS_PSEUDOHEADER-text/calendar: reply -accept
+ * The ARGS pseudoheader is optional, but we always add it when
+ * -convertargs is used.
+ */
+void
+add_convert_header (const char *convert_type, char *convert_arg,
+ char *filename, char *drft) {
+ char *field_name;
+
+ field_name = concat (MHBUILD_FILE_PSEUDOHEADER, convert_type, NULL);
+ annotate (drft, field_name, filename, 1, 0, -2, 1);
+ free (field_name);
+
+ field_name = concat (MHBUILD_ARGS_PSEUDOHEADER, convert_type, NULL);
+ annotate (drft, field_name, convert_arg, 1, 0, -2, 1);
+ free (field_name);
+}