* uip/mhlistsbr.c, uip/mhlsbr.c, uip/picksbr.c: cast
[mmh] / uip / sortm.c
index 398045b..212b441 100644 (file)
@@ -3,17 +3,15 @@
  * sortm.c -- sort messages in a folder by date/time
  *
  * $Id$
+ *
+ * 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 <zotnet/tws/tws.h>
-
-/*
- * We allocate space for messages (msgs array)
- * this number of elements at a time.
- */
-#define MAXMSGS  256
-
+#include <h/tws.h>
+#include <h/utils.h>
 
 static struct swit switches[] = {
 #define DATESW                 0
@@ -35,7 +33,7 @@ static struct swit switches[] = {
 #define VERSIONSW              8
      { "version", 0 },
 #define HELPSW                 9
-     { "help", 4 },
+     { "help", 0 },
      { NULL, 0 }
 };
 
@@ -71,10 +69,12 @@ static void rename_msgs (struct msgs *, struct smsg **);
 int
 main (int argc, char **argv)
 {
-    int        nummsgs, maxmsgs, i, msgnum;
-    char *cp, *maildir, *datesw = NULL;
+    int        i, msgnum;
+    unsigned char *cp;
+    char *maildir, *datesw = NULL;
     char *folder = NULL, buf[BUFSIZ], **argp;
-    char **arguments, **msgs;
+    char **arguments;
+    struct msgs_array msgs = { 0, 0, NULL };
     struct msgs *mp;
     struct smsg **dlist;
 
@@ -90,15 +90,6 @@ main (int argc, char **argv)
     argp = arguments;
 
     /*
-     * Allocate the initial space to record message
-     * names and ranges.
-     */
-    nummsgs = 0;
-    maxmsgs = MAXMSGS;
-    if (!(msgs = (char **) malloc ((size_t) (maxmsgs * sizeof(*msgs)))))
-       adios (NULL, "unable to allocate storage");
-
-    /*
      * Parse arguments
      */
     while ((cp = *argp++)) {
@@ -170,26 +161,15 @@ main (int argc, char **argv)
            if (folder)
                adios (NULL, "only one folder at a time!");
            else
-               folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
-       } else {
-           /*
-            * Check if we need to allocate more space
-            * for message names/ranges.
-            */
-           if (nummsgs >= maxmsgs) {
-               maxmsgs += MAXMSGS;
-               if (!(msgs = (char **) realloc (msgs,
-                       (size_t) (maxmsgs * sizeof(*msgs)))))
-                   adios (NULL, "unable to reallocate msgs storage");
-           }
-           msgs[nummsgs++] = cp;
-       }
+               folder = pluspath (cp);
+       } else
+               app_msgarg(&msgs, cp);
     }
 
     if (!context_find ("path"))
        free (path ("./", TFOLDER));
-    if (!nummsgs)
-       msgs[nummsgs++] = "all";
+    if (!msgs.size)
+       app_msgarg(&msgs, "all");
     if (!datesw)
        datesw = "date";
     if (!folder)
@@ -208,8 +188,8 @@ main (int argc, char **argv)
        adios (NULL, "no messages in %s", folder);
 
     /* parse all the message ranges/sequences and set SELECTED */
-    for (msgnum = 0; msgnum < nummsgs; msgnum++)
-       if (!m_convert (mp, msgs[msgnum]))
+    for (msgnum = 0; msgnum < msgs.size; msgnum++)
+       if (!m_convert (mp, msgs.msgs[msgnum]))
            done (1);
     seq_setprev (mp);  /* set the previous sequence */
 
@@ -219,23 +199,22 @@ main (int argc, char **argv)
     /*
      * sort a list of pointers to our "messages to be sorted".
      */
-    dlist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*dlist));
-    if (! dlist)
-       adios (NULL, "couldn't allocate sort memory");
+    dlist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*dlist));
     for (i = 0; i < nmsgs; i++)
        dlist[i] = &smsgs[i];
     dlist[nmsgs] = 0;
 
-    if (verbose)       /* announce what we're doing */
+    if (verbose) {     /* announce what we're doing */
        if (subjsort)
-           printf ("sorting by %s-major %s-minor\n", 
+           printf ("sorting by %s-major %s-minor\n",
                submajor ? subjsort : datesw,
                submajor ? datesw : subjsort);
        else
            printf ("sorting by datefield %s\n", datesw);
+    }
 
     /* first sort by date, or by subject-major, date-minor */
-    qsort ((char *) dlist, nmsgs, sizeof(*dlist), 
+    qsort ((char *) dlist, nmsgs, sizeof(*dlist),
            (qsort_comp) (submajor && subjsort ? txtsort : dsort));
 
     /*
@@ -247,9 +226,7 @@ main (int argc, char **argv)
        struct smsg **slist, **flist;
        register struct smsg ***il, **fp, **dp;
 
-       slist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*slist));
-       if (! slist)
-           adios (NULL, "couldn't allocate sort memory");
+       slist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*slist));
        memcpy((char *)slist, (char *)dlist, (nmsgs+1)*sizeof(*slist));
        qsort((char *)slist, nmsgs, sizeof(*slist), (qsort_comp) subsort);
 
@@ -267,9 +244,7 @@ main (int argc, char **argv)
         * make up the final list, chronological but with
         * all the same subjects grouped together.
         */
-       flist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*flist));
-       if (! flist)
-           adios (NULL, "couldn't allocate msg list");
+       flist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*flist));
        fp = flist;
        for (dp = dlist; *dp;) {
            register struct smsg **s = il[(*dp++)->s_msg];
@@ -287,7 +262,7 @@ main (int argc, char **argv)
             */
            while (*s && (*s)->s_subj[0] &&
                   strcmp((*s)->s_subj, s[-1]->s_subj) == 0 &&
-                  (datelimit == 0 || 
+                  (datelimit == 0 ||
                   (*s)->s_clock - s[-1]->s_clock <= datelimit)) {
                il[(*s)->s_msg] = 0;
                *fp++ = *s++;
@@ -298,6 +273,12 @@ main (int argc, char **argv)
        free (dlist);
        dlist = flist;
     }
+
+    /*
+     * At this point, dlist is a sorted array of pointers to smsg structures,
+     * each of which contains a message number.
+     */
+
     rename_msgs (mp, dlist);
 
     context_replace (pfolder, folder); /* update current folder         */
@@ -305,9 +286,10 @@ main (int argc, char **argv)
     context_save ();                   /* save the context file         */
     folder_free (mp);                  /* free folder/message structure */
     done (0);
+    return 1;
 }
 
-static int 
+static int
 read_hdrs (struct msgs *mp, char *datesw)
 {
     int msgnum;
@@ -361,7 +343,7 @@ get_fields (char *datesw, int msg, struct smsg *smsg)
        case FLDEOF:
        case FLDPLUS:
            compnum++;
-           if (!strcasecmp (nam, datesw)) {
+           if (!mh_strcasecmp (nam, datesw)) {
                datecomp = add (buf, datecomp);
                while (state == FLDPLUS) {
                    state = m_getfld (state, nam, buf, sizeof(buf), in);
@@ -369,7 +351,7 @@ get_fields (char *datesw, int msg, struct smsg *smsg)
                }
                if (!subjsort || subjcomp)
                    break;
-           } else if (subjsort && !strcasecmp (nam, subjsort)) {
+           } else if (subjsort && !mh_strcasecmp (nam, subjsort)) {
                subjcomp = add (buf, subjcomp);
                while (state == FLDPLUS) {
                    state = m_getfld (state, nam, buf, sizeof(buf), in);
@@ -426,30 +408,30 @@ get_fields (char *datesw, int msg, struct smsg *smsg)
            /*
             * try to make the subject "canonical": delete
             * leading "re:", everything but letters & smash
-            * letters to lower case. 
+            * letters to lower case.
             */
-           register char  *cp, *cp2, c;
+           register char  *cp, *cp2;
+           register unsigned char c;
 
            cp = subjcomp;
            cp2 = subjcomp;
-           if (strcmp (subjsort, "subject") == 0)
+           if (strcmp (subjsort, "subject") == 0) {
                while ((c = *cp)) {
                    if (! isspace(c)) {
                        if(uprf(cp, "re:"))
                            cp += 2;
-                       else {
-                           if (isalnum(c))
-                               *cp2++ = isupper(c) ? tolower(c) : c;
+                       else
                            break;
-                       }
                    }
                    cp++;
                }
+           }
+
            while ((c = *cp++)) {
                if (isalnum(c))
                    *cp2++ = isupper(c) ? tolower(c) : c;
-
            }
+
            *cp2 = '\0';
        }
        else
@@ -467,7 +449,7 @@ get_fields (char *datesw, int msg, struct smsg *smsg)
 /*
  * sort on dates.
  */
-static int 
+static int
 dsort (struct smsg **a, struct smsg **b)
 {
     if ((*a)->s_clock < (*b)->s_clock)
@@ -483,7 +465,7 @@ dsort (struct smsg **a, struct smsg **b)
 /*
  * sort on subjects.
  */
-static int 
+static int
 subsort (struct smsg **a, struct smsg **b)
 {
     register int i;
@@ -494,7 +476,7 @@ subsort (struct smsg **a, struct smsg **b)
     return (dsort (a, b));
 }
 
-static int 
+static int
 txtsort (struct smsg **a, struct smsg **b)
 {
     register int i;
@@ -512,6 +494,7 @@ rename_chain (struct msgs *mp, struct smsg **mlist, int msg, int endmsg)
 {
     int nxt, old, new;
     char *newname, oldname[BUFSIZ];
+    char newbuf[MAXPATHLEN + 1];
 
     for (;;) {
        nxt = mlist[msg] - smsgs;       /* mlist[msg] is a ptr into smsgs */
@@ -523,6 +506,10 @@ rename_chain (struct msgs *mp, struct smsg **mlist, int msg, int endmsg)
        if (verbose)
            printf ("message %d becomes message %d\n", old, new);
 
+       (void)snprintf(oldname, sizeof (oldname), "%s/%d", mp->foldpath, old);
+       (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, new);
+       ext_hook("ref-hook", oldname, newbuf);
+
        if (rename (oldname, newname) == NOTOK)
            adios (newname, "unable to rename %s to", oldname);
 
@@ -530,7 +517,7 @@ rename_chain (struct msgs *mp, struct smsg **mlist, int msg, int endmsg)
        if (mp->curmsg == old)
            seq_setcur (mp, new);
 
-       if (nxt == endmsg) 
+       if (nxt == endmsg)
            break;
 
        msg = nxt;
@@ -545,12 +532,13 @@ rename_msgs (struct msgs *mp, struct smsg **mlist)
     int i, j, old, new;
     seqset_t tmpset;
     char f1[BUFSIZ], tmpfil[BUFSIZ];
+    char newbuf[MAXPATHLEN + 1];
     struct smsg *sp;
 
     strncpy (tmpfil, m_name (mp->hghmsg + 1), sizeof(tmpfil));
 
     for (i = 0; i < nmsgs; i++) {
-       if (! (sp = mlist[i])) 
+       if (! (sp = mlist[i]))
            continue;   /* did this one */
 
        j = sp - smsgs;
@@ -569,11 +557,31 @@ rename_msgs (struct msgs *mp, struct smsg **mlist)
        if (verbose)
            printf ("renaming message chain from %d to %d\n", old, new);
 
+       /*
+        *      Run the external hook to refile the old message as the
+        *      temporary message number that is off of the end of the
+        *      messages in the folder.
+        */
+
+       (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, old);
+       (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, mp->hghmsg + 1);
+       ext_hook("ref-hook", f1, newbuf);
+
        if (rename (f1, tmpfil) == NOTOK)
            adios (tmpfil, "unable to rename %s to ", f1);
+
        get_msg_flags (mp, &tmpset, old);
 
        rename_chain (mp, mlist, j, i);
+
+       /*
+        *      Run the external hook to refile the temorary message number
+        *      to the real place.
+        */
+
+       (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, new);
+       ext_hook("ref-hook", newbuf, f1);
+
        if (rename (tmpfil, m_name(new)) == NOTOK)
            adios (m_name(new), "unable to rename %s to", tmpfil);