]> diplodocus.org Git - nmh/blobdiff - uip/repl.c
read_switch.c: Move interface declaration to own file.
[nmh] / uip / repl.c
index d1c8ebfa6ee44d7cc0aa8585655ed539c70de94e..8ee26b8621479059f3cf103349dc648faf6454bc 100644 (file)
@@ -1,15 +1,35 @@
-
-/*
- * 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
  * complete copyright information.
  */
 
-#include <h/mh.h>
-#include <h/utils.h>
-
+#include "h/mh.h"
+#include "sbr/concat.h"
+#include "sbr/seq_setprev.h"
+#include "sbr/seq_setcur.h"
+#include "sbr/seq_save.h"
+#include "sbr/showfile.h"
+#include "sbr/smatch.h"
+#include "sbr/refile.h"
+#include "sbr/m_draft.h"
+#include "sbr/m_convert.h"
+#include "sbr/getfolder.h"
+#include "sbr/folder_read.h"
+#include "sbr/context_save.h"
+#include "sbr/context_replace.h"
+#include "sbr/context_find.h"
+#include "sbr/ambigsw.h"
+#include "sbr/path.h"
+#include "sbr/print_version.h"
+#include "sbr/print_help.h"
+#include "sbr/error.h"
+#include "h/mime.h"
+#include "h/done.h"
+#include "h/utils.h"
+#include "sbr/m_maildir.h"
+#include "replsbr.h"
 
 #define REPL_SWITCHES \
     X("group", 0, GROUPSW) \
     X("annotate", 0, ANNOSW) \
     X("noannotate", 0, NANNOSW) \
     X("cc all|to|cc|me", 0, CCSW) \
-    X("nocc type", 0, NCCSW) \
+    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) \
@@ -39,7 +60,7 @@
     X("width columns", 0, WIDTHSW) \
     X("version", 0, VERSIONSW) \
     X("help", 0, HELPSW) \
-    X("file file", 4, FILESW) /* interface from msh */ \
+    X("file file", 4, FILESW) \
     X("build", 5, BILDSW) /* interface from mhe */ \
     X("atfile", 0, ATFILESW) \
     X("noatfile", 0, NOATFILESW) \
@@ -91,15 +112,10 @@ static struct swit aqrl[] = {
     { NULL, 0, 0 }
 };
 
-short ccto = -1;               /* global for replsbr */
-short cccc = -1;
-short ccme = -1;
-short querysw = 0;
-
 static short outputlinelen = OUTPUTLINELEN;
-static short groupreply = 0;           /* Is this a group reply?        */
+static bool groupreply;                        /* Is this a group reply?        */
 
-static int mime = 0;                   /* include original as MIME part */
+static bool mime;                      /* 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 */
@@ -108,32 +124,33 @@ 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
 main (int argc, char **argv)
 {
     int        i, isdf = 0;
-    int anot = 0, inplace = 1;
-    int nedit = 0, nwhat = 0;
-    int atfile = 0;
+    bool anot = false;
+    bool inplace = true;
+    bool nedit = false;
+    bool nwhat = false;
+    bool atfile = false;
     int fmtproc = -1;
     char *cp, *cwd, *dp, *maildir, *file = NULL;
     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;
+    bool buildsw = false;
 
-    int buildsw = 0;
-
-    setlocale(LC_ALL, "");
-    invo_name = r1bindex (argv[0], '/');
-
-    /* read user profile/context */
-    context_read();
+    if (nmh_init(argv[0], true, true)) { return 1; }
 
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
@@ -145,7 +162,7 @@ main (int argc, char **argv)
                    ambigsw (cp, switches);
                    done (1);
                case UNKWNSW: 
-                   adios (NULL, "-%s unknown", cp);
+                   die("-%s unknown", cp);
 
                case HELPSW: 
                    snprintf (buf, sizeof(buf), "%s: [+folder] [msg] [switches]",
@@ -157,102 +174,130 @@ main (int argc, char **argv)
                    done (0);
 
                case GROUPSW:
-                   groupreply++;
+                   groupreply = true;
                    continue;
                case NGROUPSW:
-                   groupreply = 0;
+                   groupreply = false;
                    continue;
 
                case ANNOSW: 
-                   anot++;
+                   anot = true;
                    continue;
                case NANNOSW: 
-                   anot = 0;
+                   anot = false;
                    continue;
 
                case CCSW: 
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    docc (cp, 1);
                    continue;
                case NCCSW: 
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    docc (cp, 0);
                    continue;
 
                case EDITRSW: 
                    if (!(ed = *argp++) || *ed == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
-                   nedit = 0;
+                       die("missing argument to %s", argp[-2]);
+                   nedit = false;
                    continue;
                case NEDITSW:
-                   nedit++;
+                   nedit = true;
                    continue;
                    
+               case CONVERTARGSW: {
+                    char *type;
+                    size_t i;
+
+                   if (!(type = *argp++)) {
+                       die("missing type argument to %s", argp[-2]);
+                    }
+                   if (!(cp = *argp++)) {
+                       die("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;
+                       die("missing argument to %s", argp[-2]);
+                   nwhat = false;
                    continue;
                case BILDSW: 
-                   buildsw++;  /* fall... */
+                   buildsw = true;
+                   /* FALLTHRU */
                case NWHATSW: 
-                   nwhat++;
+                   nwhat = true;
                    continue;
 
                case FCCSW: 
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    dp = NULL;
                    if (*cp == '@')
                        cp = dp = path (cp + 1, TSUBCWF);
                    if (fcc)
                        fcc = add (", ", fcc);
                    fcc = add (cp, fcc);
-                   if (dp)
-                       free (dp);
+                    free(dp);
                    continue;
 
                case FILESW: 
                    if (file)
-                       adios (NULL, "only one file at a time!");
+                       die("only one file at a time!");
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    file = path (cp, TFILE);
                    continue;
                case FILTSW:
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
-                   filter = getcpy (etcpath (cp));
-                   mime = 0;
+                       die("missing argument to %s", argp[-2]);
+                   filter = mh_xstrdup(etcpath(cp));
+                   mime = false;
                    continue;
                case FORMSW: 
                    if (!(form = *argp++) || *form == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    continue;
 
                case FRMTSW: 
-                   filter = getcpy (etcpath (mhlreply));
-                   mime = 0;
+                   filter = mh_xstrdup(etcpath(mhlreply));
+                   mime = false;
                    continue;
                case NFRMTSW: 
                    filter = NULL;
                    continue;
 
                case INPLSW: 
-                   inplace++;
+                   inplace = true;
                    continue;
                case NINPLSW: 
-                   inplace = 0;
+                   inplace = false;
                    continue;
 
                case MIMESW:
-                   mime++;
+                   mime = true;
                    filter = NULL;
                    continue;
                case NMIMESW:
-                   mime = 0;
+                   mime = false;
                    continue;
 
                case QURYSW: 
@@ -264,24 +309,24 @@ main (int argc, char **argv)
 
                case WIDTHSW: 
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    if ((outputlinelen = atoi (cp)) < 10)
-                       adios (NULL, "impossible width %d", outputlinelen);
+                       die("impossible width %d", outputlinelen);
                    continue;
 
                case DFOLDSW: 
                    if (dfolder)
-                       adios (NULL, "only one draft folder at a time!");
+                       die("only one draft folder at a time!");
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
                                    *cp != '@' ? TFOLDER : TSUBCWF);
                    continue;
                case DMSGSW:
                    if (dmsg)
-                       adios (NULL, "only one draft message at a time!");
+                       die("only one draft message at a time!");
                    if (!(dmsg = *argp++) || *dmsg == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    continue;
                case NDFLDSW: 
                    dfolder = NULL;
@@ -289,15 +334,15 @@ main (int argc, char **argv)
                    continue;
 
                case ATFILESW:
-                   atfile++;
+                   atfile = true;
                    continue;
                case NOATFILESW:
-                   atfile = 0;
+                   atfile = false;
                    continue;
 
                case FMTPROCSW:
                    if (!(formatproc = *argp++) || *formatproc == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       die("missing argument to %s", argp[-2]);
                    fmtproc = 1;
                    continue;
                case NFMTPROCSW:
@@ -307,14 +352,12 @@ main (int argc, char **argv)
        }
        if (*cp == '+' || *cp == '@') {
            if (folder)
-               adios (NULL, "only one folder at a time!");
-           else
-               folder = pluspath (cp);
+               die("only one folder at a time!");
+            folder = pluspath (cp);
        } else {
            if (msg)
-               adios (NULL, "only one message at a time!");
-           else
-               msg = cp;
+               die("only one message at a time!");
+            msg = cp;
        }
     }
 
@@ -325,12 +368,12 @@ main (int argc, char **argv)
     if (ccme == -1)
        ccme = groupreply;
 
-    cwd = getcpy (pwd ());
+    cwd = mh_xstrdup(pwd ());
 
     if (!context_find ("path"))
        free (path ("./", TFOLDER));
     if (file && (msg || folder))
-       adios (NULL, "can't mix files and folders/msgs");
+       die("can't mix files and folders/msgs");
 
 try_it_again:
 
@@ -341,7 +384,8 @@ try_it_again:
     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: 
@@ -359,7 +403,7 @@ try_it_again:
                        i = YESW;
                    break;
                default: 
-                   advise (NULL, "say what?");
+                   inform("say what?");
                    break;
            }
        }
@@ -369,7 +413,7 @@ try_it_again:
        /*
         * We are replying to a file.
         */
-       anot = 0;       /* we don't want to annotate a file */
+       anot = false;   /* we don't want to annotate a file */
     } else {
        /*
         * We are replying to a message.
@@ -385,11 +429,11 @@ try_it_again:
 
        /* read folder and create message structure */
        if (!(mp = folder_read (folder, 1)))
-           adios (NULL, "unable to read folder %s", folder);
+           die("unable to read folder %s", folder);
 
        /* check for empty folder */
        if (mp->nummsg == 0)
-           adios (NULL, "no messages in %s", folder);
+           die("no messages in %s", folder);
 
        /* parse the message range/sequence/name and set SELECTED */
        if (!m_convert (mp, msg))
@@ -397,7 +441,7 @@ try_it_again:
        seq_setprev (mp);       /* set the previous-sequence */
 
        if (mp->numsel > 1)
-           adios (NULL, "only one message at a time!");
+           die("only one message at a time!");
 
        context_replace (pfolder, folder);      /* update current folder   */
        seq_setcur (mp, mp->lowsel);    /* update current message  */
@@ -405,7 +449,7 @@ try_it_again:
        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");
@@ -422,15 +466,32 @@ try_it_again:
             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;
 }
 
-void
+static void
 docc (char *cp, int ccflag)
 {
     switch (smatch (cp, ccswitches)) {
@@ -438,7 +499,7 @@ docc (char *cp, int ccflag)
            ambigsw (cp, ccswitches);
            done (1);
        case UNKWNSW: 
-           adios (NULL, "-%scc %s unknown", ccflag ? "" : "no", cp);
+           die("-%scc %s unknown", ccflag ? "" : "no", cp);
 
        case CTOSW: 
            ccto = ccflag;
@@ -457,3 +518,26 @@ docc (char *cp, int ccflag)
            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.
+ */
+static 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);
+}