[comp.mail.mh] Sortm context diffs

marvit%hplpm@HPLABS.HP.COM (Peter Marvit) (05/19/89)

Wow!  I got ten (!) requests within three hours of my original message.
Therefore, here is the context diffs.  Some of them are minor (changed
variable names, et al), and I've tried to omit purely stylistic ones.  Look
at the diffs carefully before applying, as you should always do. Note that
I've not rewritten the man page to reflect the new capabilities.  If someone
wants to do that, I'd be grateful (plus it shows that the changes are
understood).

First, here is what I've recorded in my CHANGELOG file:

 uip/sortm.c Started with the new Van Jacobson version with the -subject
 sort. Simplified code a bit.  Added -[no]pack for backwards compatibility
 with old sortm.  -pack is default but will not work with partial folders.
 Subject sort was recoded to actually be subject major, date minor rather
 than the date major, subject minor.  Eventually I may do a generalized field
 sort, but not yet. Also fixed a tiny bug which may have been HP-UX compiler
 specific but really looks like some bad programming (return of a function
 without returning a value).

Following are the context diffs.  Happy Hacking!

	-Peter "MH 'R ME" Marvit
	 marvit@hplabs.hp.com

------------------------------ CUT HERE -------------------------------
*** sortm.c.ORIG	Tue Jul  5 15:03:02 1988
--- sortm.c	Mon Apr 24 22:48:17 1989
***************
*** 1,3
  /* sortm.c - sort messages in a folder by date/time */
  
  #include "../h/mh.h"

--- 1,24 -----
+ /*
+  * revision 1.4
+  * date: 88/07/14 16:08:48; author marvit;
+  * Simplified code a bit.  Added -[no]pack for backwards compatibility with old
+  * sortm.  -pack is default but will not work with partial folders.  Subject
+  * sort recoded to actually be subject major, date minor.
+  *
+  * revision 1.3        
+  * date: 87/05/20 21:30:02; author: van; state: Exp; lines added/del: 122/82
+  * corrected sorting of subsets of folder.  Just permute original
+  * numbers.  Don't pack or renumber.
+  *
+  * revision 1.2        
+  * date: 87/05/19 05:33:38; author: van; state: Exp; lines added/del: 360/256
+  * added subject sorting (-subj flag)
+  *
+  * revision 1.1        
+  * date: 87/05/18 22:58:33; author: van; state: Exp;  
+  * Initial revision
+  */
+ 
  /* sortm.c - sort messages in a folder by date/time */
  
  #include "../h/mh.h"
***************
*** 3,8
  #include "../h/mh.h"
  #include "../zotnet/tws.h"
  #include <stdio.h>
  
  /*  */
  

--- 24,32 -----
  #include "../h/mh.h"
  #include "../zotnet/tws.h"
  #include <stdio.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <ctype.h>
  
  static struct swit switches[] = {
  #define	DATESW	0
***************
*** 4,11
  #include "../zotnet/tws.h"
  #include <stdio.h>
  
- /*  */
- 
  static struct swit switches[] = {
  #define	DATESW	0
      "datefield field", 0,

--- 28,33 -----
  #include <sys/stat.h>
  #include <ctype.h>
  
  static struct swit switches[] = {
  #define	DATESW	0
  	 "datefield field", 0,
***************
*** 15,21
  #define NVERBSW	2
      "noverbose", 0,
  
! #define	HELPSW	3
      "help", 4,
  
      NULL, NULL

--- 37,51 -----
  #define NVERBSW	2
  	 "noverbose", 0,
  
! #define SUBJSW 3
! 	 "subject", 0,
! 
! #define PACKSW 4
! 	 "pack", 0,
! #define NOPACKSW 5
! 	 "nopack", 0,
! 
! #define	HELPSW	6
  	 "help", 4,
  
  	 NULL, NULL
***************
*** 21,27
      NULL, NULL
  };
  
- /*  */
  
  struct smsg {
      int     s_msg;

--- 51,56 -----
  	 NULL, NULL
  };
  
  
  struct smsg {
  	int s_msg;
***************
*** 25,31
  
  struct smsg {
      int     s_msg;
!     struct tws  s_tws;
  };
  
  static struct smsg *smsgs;

--- 54,61 -----
  
  struct smsg {
  	int s_msg;
! 	unsigned long s_clock;
! 	char *s_subj;
  };
  
  static struct smsg *smsgs;
***************
*** 29,34
  };
  
  static struct smsg *smsgs;
  
  
  int     msgsort ();

--- 59,65 -----
  };
  
  static struct smsg *smsgs;
+ int nmsgs;
  
  int subjsort;			/* sort on subject if != 0 */
  int verbose;
***************
*** 30,35
  
  static struct smsg *smsgs;
  
  
  int     msgsort ();
  

--- 61,72 -----
  static struct smsg *smsgs;
  int nmsgs;
  
+ int subjsort;			/* sort on subject if != 0 */
+ int verbose;
+ int packsw = 1;			/* smush folder, eliminating holes */
+ int dsort ();
+ int subsort ();
+ struct msgs *tfold ();		/* for packing folder */
  
  /* ARGSUSED */
  main (argc, argv)
***************
*** 31,45
  static struct smsg *smsgs;
  
  
- int     msgsort ();
- 
- struct tws *getws ();
- 
- 
- long	time ();
- 
- /*  */
- 
  /* ARGSUSED */
  
  main (argc, argv)

--- 68,73 -----
  int subsort ();
  struct msgs *tfold ();		/* for packing folder */
  
  /* ARGSUSED */
  main (argc, argv)
  	int argc;
***************
*** 41,47
  /*  */
  
  /* ARGSUSED */
- 
  main (argc, argv)
  int     argc;
  char  **argv;

--- 69,74 -----
  struct msgs *tfold ();		/* for packing folder */
  
  /* ARGSUSED */
  main (argc, argv)
  	int argc;
  	char **argv;
***************
*** 43,50
  /* ARGSUSED */
  
  main (argc, argv)
! int     argc;
! char  **argv;
  {
      int     verbosw = 0,
              msgp = 0,

--- 70,77 -----
  
  /* ARGSUSED */
  main (argc, argv)
! 	int argc;
! 	char **argv;
  {
  	int msgp = 0;
  	int i;
***************
*** 46,64
  int     argc;
  char  **argv;
  {
!     int     verbosw = 0,
!             msgp = 0,
! 	    i,
!             msgnum;
!     char   *cp,
!            *maildir,
!            *datesw = NULL,
!            *folder = NULL,
!             buf[100],
!           **ap,
!           **argp,
!            *arguments[MAXARGS],
!            *msgs[MAXARGS];
      struct msgs *mp;
  
      invo_name = r1bindex (argv[0], '/');

--- 73,90 -----
  	int argc;
  	char **argv;
  {
! 	int msgp = 0;
! 	int i;
! 	int msgnum;
! 	char *cp;
! 	char *maildir;
! 	char *datesw = NULL;
! 	char *folder = NULL;
! 	char buf[100];
! 	char **ap;
! 	char **argp;
! 	char *arguments[MAXARGS];
! 	char *msgs[MAXARGS];
  	struct msgs *mp;
  	struct smsg **dlist;
  
***************
*** 60,65
             *arguments[MAXARGS],
             *msgs[MAXARGS];
      struct msgs *mp;
  
      invo_name = r1bindex (argv[0], '/');
      if ((cp = m_find (invo_name)) != NULL) {

--- 86,92 -----
  	char *arguments[MAXARGS];
  	char *msgs[MAXARGS];
  	struct msgs *mp;
+ 	struct smsg **dlist;
  
  	invo_name = r1bindex (argv[0], '/');
  	if ((cp = m_find (invo_name)) != NULL) {
***************
*** 65,72
      if ((cp = m_find (invo_name)) != NULL) {
  	ap = brkstring (cp = getcpy (cp), " ", "\n");
  	ap = copyip (ap, arguments);
!     }
!     else
  	ap = arguments;
      (void) copyip (argv + 1, ap);
      argp = arguments;

--- 92,98 -----
  	if ((cp = m_find (invo_name)) != NULL) {
  		ap = brkstring (cp = getcpy (cp), " ", "\n");
  		ap = copyip (ap, arguments);
! 	} else
  		ap = arguments;
  	(void) copyip (argv + 1, ap);
  	argp = arguments;
***************
*** 71,78
      (void) copyip (argv + 1, ap);
      argp = arguments;
  
- /*  */
- 
      while (cp = *argp++) {
  	if (*cp == '-')
  	    switch (smatch (++cp, switches)) {

--- 97,102 -----
  	(void) copyip (argv + 1, ap);
  	argp = arguments;
  
  	while (cp = *argp++) {
  		if (*cp == '-')
  			switch (smatch (++cp, switches)) {
***************
*** 82,88
  		case UNKWNSW: 
  		    adios (NULLCP, "-%s unknown", cp);
  		case HELPSW: 
! 		    (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
  			    invo_name);
  		    help (buf, switches);
  		    done (1);

--- 106,113 -----
  			case UNKWNSW:
  				adios (NULLCP, "-%s unknown", cp);
  			case HELPSW:
! 				(void) sprintf(buf,
! 					      "%s [+folder] [msgs] [switches]",
  					      invo_name);
  				help (buf, switches);
  				done (1);
***************
*** 89,95
  
  		case DATESW: 
  		    if (datesw)
! 			adios (NULLCP, "only one date field at a time!");
  		    if (!(datesw = *argp++) || *datesw == '-')
  			adios (NULLCP, "missing argument to %s", argp[-2]);
  		    continue;

--- 114,121 -----
  
  			case DATESW:
  				if (datesw)
! 					adios (NULLCP,
! 					       "only one date field at a time");
  				if (!(datesw = *argp++) || *datesw == '-')
  					adios (NULLCP, "missing argument to %s", argp[-2]);
  				continue;
***************
*** 94,99
  			adios (NULLCP, "missing argument to %s", argp[-2]);
  		    continue;
  
  		case VERBSW: 
  		    verbosw++;
  		    continue;

--- 120,129 -----
  					adios (NULLCP, "missing argument to %s", argp[-2]);
  				continue;
  
+ 			case SUBJSW:
+ 				subjsort = 1;
+ 				continue;
+ 
  			case VERBSW:
  				verbose++;
  				continue;
***************
*** 95,101
  		    continue;
  
  		case VERBSW: 
! 		    verbosw++;
  		    continue;
  		case NVERBSW: 
  		    verbosw = 0;

--- 125,131 -----
  				continue;
  
  			case VERBSW:
! 				verbose++;
  				continue;
  			case NVERBSW:
  				verbose = 0;
***************
*** 98,104
  		    verbosw++;
  		    continue;
  		case NVERBSW: 
! 		    verbosw = 0;
  		    continue;
  	    }
  	if (*cp == '+' || *cp == '@') {

--- 128,134 -----
  				verbose++;
  				continue;
  			case NVERBSW:
! 				verbose = 0;
  				continue;
  			case PACKSW:
  				packsw++;
***************
*** 100,105
  		case NVERBSW: 
  		    verbosw = 0;
  		    continue;
  	    }
  	if (*cp == '+' || *cp == '@') {
  	    if (folder)

--- 130,142 -----
  			case NVERBSW:
  				verbose = 0;
  				continue;
+ 			case PACKSW:
+ 				packsw++;
+ 				continue;
+ 			case NOPACKSW:
+ 				packsw = 0;
+ 				continue;
+ 				
  			}
  		if (*cp == '+' || *cp == '@') {
  			if (folder)
***************
*** 106,113
  		adios (NULLCP, "only one folder at a time!");
  	    else
  		folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
! 	}
! 	else
  	    msgs[msgp++] = cp;
      }
  

--- 143,149 -----
  				adios (NULLCP, "only one folder at a time!");
  			else
  				folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
! 		} else
  			msgs[msgp++] = cp;
  	}
  
***************
*** 111,117
  	    msgs[msgp++] = cp;
      }
  
- /*  */
  
      if (!m_find ("path"))
  	free (path ("./", TFOLDER));

--- 147,152 -----
  			msgs[msgp++] = cp;
  	}
  
  
  	if (msgp && packsw)
  		adios (NULLCP, "use -nopack if you specify selected messages!"); 
***************
*** 113,118
  
  /*  */
  
      if (!m_find ("path"))
  	free (path ("./", TFOLDER));
      if (!msgp)

--- 148,155 -----
  	}
  
  
+ 	if (msgp && packsw)
+ 		adios (NULLCP, "use -nopack if you specify selected messages!"); 
  	if (!m_find ("path"))
  		free (path ("./", TFOLDER));
  	if (!msgp)
***************
*** 118,124
      if (!msgp)
  	msgs[msgp++] = "all";
      if (!datesw)
! 	datesw = "Date";
      if (!folder)
  	folder = m_getfolder ();
      maildir = m_maildir (folder);

--- 155,161 -----
  	if (!msgp)
  		msgs[msgp++] = "all";
  	if (!datesw)
! 		datesw = "date";
  	if (!folder)
  		folder = m_getfolder ();
  	maildir = m_maildir (folder);
***************
*** 127,133
  	adios (maildir, "unable to change directory to");
      if (!(mp = m_gmsg (folder)))
  	adios (NULLCP, "unable to read folder %s", folder);
!     if (mp -> hghmsg == 0)
  	adios (NULLCP, "no messages in %s", folder);
  
      for (msgnum = 0; msgnum < msgp; msgnum++)

--- 164,170 -----
  		adios (maildir, "unable to change directory to");
  	if (!(mp = m_gmsg (folder)))
  		adios (NULLCP, "unable to read folder %s", folder);
! 	if (mp->hghmsg == 0)
  		adios (NULLCP, "no messages in %s", folder);
  
  	for (msgnum = 0; msgnum < msgp; msgnum++)
***************
*** 135,141
  	    done (1);
      m_setseq (mp);
  
!     if ((i = read_dates (mp, datesw)) <= 0)
  	adios (NULLCP, "no messages to sort");
      qsort ((char *) smsgs, i, sizeof *smsgs, msgsort);
      file_dates (mp, verbosw);

--- 172,178 -----
  			done (1);
  	m_setseq (mp);
  
! 	if ((nmsgs = read_hdrs (mp, datesw)) <= 0)
  		adios (NULLCP, "no messages to sort");
  
  	/*
***************
*** 137,144
  
      if ((i = read_dates (mp, datesw)) <= 0)
  	adios (NULLCP, "no messages to sort");
-     qsort ((char *) smsgs, i, sizeof *smsgs, msgsort);
-     file_dates (mp, verbosw);
  
      m_replace (pfolder, folder);
      m_sync (mp);

--- 174,179 -----
  
  	if ((nmsgs = read_hdrs (mp, datesw)) <= 0)
  		adios (NULLCP, "no messages to sort");
  
  	/*
  	 * sort a list of pointers to our "messages to be sorted".
***************
*** 140,145
      qsort ((char *) smsgs, i, sizeof *smsgs, msgsort);
      file_dates (mp, verbosw);
  
      m_replace (pfolder, folder);
      m_sync (mp);
      m_update ();

--- 175,202 -----
  	if ((nmsgs = read_hdrs (mp, datesw)) <= 0)
  		adios (NULLCP, "no messages to sort");
  
+ 	/*
+ 	 * sort a list of pointers to our "messages to be sorted".
+ 	 */
+ 	dlist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*dlist));
+ 	if (! dlist)
+ 		adios (NULLCP, "couldn't allocate sort memory");
+ 	for (i = 0; i < nmsgs; i++)
+ 		dlist[i] = &smsgs[i];
+ 	dlist[nmsgs] = 0;
+ 
+ 	if (!subjsort)
+ 		qsort ((char *) dlist, nmsgs, sizeof(*dlist), dsort);
+ 
+ 	if (subjsort) {
+ 		qsort ((char *)dlist, nmsgs, sizeof(*dlist), subsort);
+ 
+ 	}
+ 	rename_msgs (mp, dlist);
+ 
+ 	if (packsw)
+ 		mp = tfold(mp); 	/* Stolen from folder.c  */
+ 	
  	m_replace (pfolder, folder);
  	m_sync (mp);
  	m_update ();
***************
*** 147,153
      done (0);
  }
  
- /*  */
  
  static int  read_dates (mp, datesw)
  register struct  msgs *mp;

--- 204,209 -----
  	done (0);
  }
  
  
  static int 
  read_hdrs (mp, datesw)
***************
*** 149,157
  
  /*  */
  
! static int  read_dates (mp, datesw)
! register struct  msgs *mp;
! register char   *datesw;
  {
      int     msgnum;
      struct tws  tb;

--- 205,214 -----
  }
  
  
! static int 
! read_hdrs (mp, datesw)
! 	register struct msgs *mp;
! 	register char *datesw;
  {
  	int msgnum;
  	struct tws tb;
***************
*** 156,162
      int     msgnum;
      struct tws  tb;
      register struct smsg *s;
-     register struct tws *tw;
  
      twscopy (&tb, dtwstime ());
  

--- 213,218 -----
  	int msgnum;
  	struct tws tb;
  	register struct smsg *s;
  
  	twscopy (&tb, dtwstime ());
  
***************
*** 161,167
      twscopy (&tb, dtwstime ());
  
      smsgs = (struct smsg   *)
! 		calloc ((unsigned) (mp -> hghsel - mp -> lowsel + 2),
  			sizeof *smsgs);
      if (smsgs == NULL)
  	adios (NULLCP, "unable to allocate sort storage");

--- 217,223 -----
  	twscopy (&tb, dtwstime ());
  
  	smsgs = (struct smsg *)
! 		calloc ((unsigned) (mp->hghsel - mp->lowsel + 2),
  			sizeof *smsgs);
  	if (smsgs == NULL)
  		adios (NULLCP, "unable to allocate sort storage");
***************
*** 167,185
  	adios (NULLCP, "unable to allocate sort storage");
  
      s = smsgs;
!     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
! 	tw = NULL;
! 	if (mp -> msgstats[msgnum] & SELECTED) {
! 	    if ((tw = getws (datesw, msgnum)) == NULL)
! 		tw = msgnum != mp -> lowsel ? &((s - 1) -> s_tws) : &tb;
! 	}
! 	else
! 	    if (mp -> msgstats[msgnum] & EXISTS)
! 		tw = &tb;
! 
! 	if (tw) {
! 	    s -> s_msg = msgnum;
! 	    twscopy (&s -> s_tws, tw);
  	    s++;
  	}
      }

--- 223,232 -----
  		adios (NULLCP, "unable to allocate sort storage");
  
  	s = smsgs;
! 	for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
! 		if (mp->msgstats[msgnum] & SELECTED) {
! 			if (getws (datesw, msgnum, s)) {
! 				s->s_msg = msgnum;
  				s++;
  			}
  		}
***************
*** 183,188
  	    s++;
  	}
      }
  
      s -> s_msg = 0;
      return (s - smsgs);

--- 230,238 -----
  				s++;
  			}
  		}
+ 	}
+ 	s->s_msg = 0;
+ 	nmsgs = s - smsgs;
  
  	return nmsgs;
  }
***************
*** 184,191
  	}
      }
  
!     s -> s_msg = 0;
!     return (s - smsgs);
  }
  
  /*  */

--- 234,240 -----
  	s->s_msg = 0;
  	nmsgs = s - smsgs;
  
! 	return nmsgs;
  }
  
  
***************
*** 188,194
      return (s - smsgs);
  }
  
- /*  */
  
  static struct tws  *getws (datesw, msg)
  register char   *datesw;

--- 237,242 -----
  	return nmsgs;
  }
  
  
  static
  getws (datesw, msg, smsg)
***************
*** 190,198
  
  /*  */
  
! static struct tws  *getws (datesw, msg)
! register char   *datesw;
! int     msg;
  {
      int     compnum,
              state;

--- 238,248 -----
  }
  
  
! static
! getws (datesw, msg, smsg)
! 	register char *datesw;
! 	int msg;
! 	register struct smsg *smsg;
  {
  	int compnum;
  	register int state;
***************
*** 194,205
  register char   *datesw;
  int     msg;
  {
!     int     compnum,
!             state;
!     register char  *hp,
!                    *msgnam;
!     char    buf[BUFSIZ],
!             nam[NAMESZ];
      register struct tws *tw;
      register    FILE *in;
  

--- 244,253 -----
  	int msg;
  	register struct smsg *smsg;
  {
! 	int compnum;
! 	register int state;
! 	char *msgnam;
! 	char buf[BUFSIZ], nam[NAMESZ];
  	register struct tws *tw;
  	register char *datecomp = NULLCP;
  	register char *subjcomp = NULLCP;
***************
*** 201,206
      char    buf[BUFSIZ],
              nam[NAMESZ];
      register struct tws *tw;
      register    FILE *in;
  
      if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {

--- 249,256 -----
  	char *msgnam;
  	char buf[BUFSIZ], nam[NAMESZ];
  	register struct tws *tw;
+ 	register char *datecomp = NULLCP;
+ 	register char *subjcomp = NULLCP;
  	register FILE *in;
  
  	if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
***************
*** 205,211
  
      if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
  	admonish (msgnam, "unable to read message");
! 	return NULL;
      }
  
  /*  */

--- 255,261 -----
  
  	if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
  		admonish (msgnam, "unable to read message");
! 		return (0);
  	}
  	for (compnum = 1, state = FLD;;) {
  		switch (state = m_getfld (state, nam, buf, sizeof buf, in)) {
***************
*** 207,216
  	admonish (msgnam, "unable to read message");
  	return NULL;
      }
! 
! /*  */
! 
!     for (compnum = 1, state = FLD, hp = NULL;;) {
  	switch (state = m_getfld (state, nam, buf, sizeof buf, in)) {
  	    case FLD: 
  	    case FLDEOF: 

--- 257,263 -----
  		admonish (msgnam, "unable to read message");
  		return (0);
  	}
! 	for (compnum = 1, state = FLD;;) {
  		switch (state = m_getfld (state, nam, buf, sizeof buf, in)) {
  		case FLD:
  		case FLDEOF:
***************
*** 216,224
  	    case FLDEOF: 
  	    case FLDPLUS: 
  		compnum++;
! 		if (hp != NULL)
! 		    free (hp), hp = NULL;
! 		hp = add (buf, NULLCP);
  		while (state == FLDPLUS) {
  		    state = m_getfld (state, nam, buf, sizeof buf, in);
  		    hp = add (buf, hp);

--- 263,270 -----
  		case FLDEOF:
  		case FLDPLUS:
  			compnum++;
! 			if (uleq (nam, datesw)) {
! 				datecomp = add (buf, datecomp);
  				while (state == FLDPLUS) {
  					state = m_getfld (state, nam, buf, sizeof buf, in);
  					datecomp = add (buf, datecomp);
***************
*** 221,227
  		hp = add (buf, NULLCP);
  		while (state == FLDPLUS) {
  		    state = m_getfld (state, nam, buf, sizeof buf, in);
! 		    hp = add (buf, hp);
  		}
  		if (uleq (nam, datesw))
  		    break;

--- 267,273 -----
  				datecomp = add (buf, datecomp);
  				while (state == FLDPLUS) {
  					state = m_getfld (state, nam, buf, sizeof buf, in);
! 					datecomp = add (buf, datecomp);
  				}
  				if (!subjsort || subjcomp)
  					break;
***************
*** 223,229
  		    state = m_getfld (state, nam, buf, sizeof buf, in);
  		    hp = add (buf, hp);
  		}
! 		if (uleq (nam, datesw))
  		    break;
  		if (state != FLDEOF)
  		    continue;

--- 269,275 -----
  					state = m_getfld (state, nam, buf, sizeof buf, in);
  					datecomp = add (buf, datecomp);
  				}
! 				if (!subjsort || subjcomp)
  					break;
  			} else if (subjsort && uleq (nam, "subject")) {
  				subjcomp = add (buf, subjcomp);
***************
*** 225,231
  		}
  		if (uleq (nam, datesw))
  		    break;
! 		if (state != FLDEOF)
  		    continue;
  
  	    case BODY: 

--- 271,289 -----
  				}
  				if (!subjsort || subjcomp)
  					break;
! 			} else if (subjsort && uleq (nam, "subject")) {
! 				subjcomp = add (buf, subjcomp);
! 				while (state == FLDPLUS) {
! 					state = m_getfld (state, nam, buf, sizeof buf, in);
! 					subjcomp = add (buf, subjcomp);
! 				}
! 				if (datecomp)
! 					break;
! 			} else {
! 				/* just flush this guy */
! 				while (state == FLDPLUS)
! 					state = m_getfld (state, nam, buf, sizeof buf, in);
! 			}
  			continue;
  
  		case BODY:
***************
*** 231,237
  	    case BODY: 
  	    case BODYEOF: 
  	    case FILEEOF: 
! 		admonish (NULLCP, "no %s field in message %d", datesw, msg);
  
  	    case LENERR: 
  	    case FMTERR: 

--- 289,295 -----
  		case BODY:
  		case BODYEOF:
  		case FILEEOF:
! 			break;
  
  		case LENERR:
  		case FMTERR:
***************
*** 237,243
  	    case FMTERR: 
  		if (state == LENERR || state == FMTERR)
  		    admonish (NULLCP,
! 			    "format error in message %d(header #%d)",
  			    msg, compnum);
  		if (hp != NULL)
  		    free (hp);

--- 295,301 -----
  		case FMTERR:
  			if (state == LENERR || state == FMTERR)
  				admonish (NULLCP,
! 				   "format error in message %d (header #%d)",
  					  msg, compnum);
  			if (datecomp)
  				free (datecomp);
***************
*** 239,246
  		    admonish (NULLCP,
  			    "format error in message %d(header #%d)",
  			    msg, compnum);
! 		if (hp != NULL)
! 		    free (hp);
  		(void) fclose (in);
  		return NULL;
  

--- 297,306 -----
  				admonish (NULLCP,
  				   "format error in message %d (header #%d)",
  					  msg, compnum);
! 			if (datecomp)
! 				free (datecomp);
! 			if (subjcomp)
! 				free (subjcomp);
  			(void) fclose (in);
  			return (0);
  
***************
*** 242,248
  		if (hp != NULL)
  		    free (hp);
  		(void) fclose (in);
! 		return NULL;
  
  	    default: 
  		adios (NULLCP, "internal error -- you lose");

--- 302,308 -----
  			if (subjcomp)
  				free (subjcomp);
  			(void) fclose (in);
! 			return (0);
  
  		default:
  			adios (NULLCP, "internal error -- you lose");
***************
*** 250,257
  	break;
      }
  
!     if ((tw = dparsetime (hp)) == NULL)
! 	admonish (NULLCP, "unable to parse %s field in message %d",
  		datesw, msg);
  
      if (hp != NULL)

--- 310,319 -----
  		break;
  	}
  
! 	if (!datecomp || (tw = dparsetime (datecomp)) == NULL) {
! 		struct stat st;
! 
! 		admonish (NULLCP, "can't parse %s field in message %d",
  			  datesw, msg);
  
  		/* use the modify time of the file as its date */
***************
*** 254,261
  	admonish (NULLCP, "unable to parse %s field in message %d",
  		datesw, msg);
  
!     if (hp != NULL)
! 	free (hp);
      (void) fclose (in);
      return tw;
  }

--- 316,355 -----
  		admonish (NULLCP, "can't parse %s field in message %d",
  			  datesw, msg);
  
! 		/* use the modify time of the file as its date */
! 		(void) fstat (fileno (in), &st);
! 		smsg->s_clock = st.st_mtime;
! 	} else {
! 		smsg->s_clock = twclock (tw);
! 	}
! 
! 	if (subjsort) {
! 		register char *cp;
! 		register char *cp2;
! 		register char c;
! 
! 		if (!subjcomp)
! 			subjcomp = "";
! 
! 		/*
! 		 * try to make the subject "canonical": delete leading "re:",
! 		 * punctuation, white space & smash everything to lower case. 
! 		 */
! 		cp = subjcomp;
! 		cp2 = subjcomp;
! 		while (c = *cp++)
! 			if (isupper (c))
! 				*cp2++ = tolower (c);
! 			else if (isalnum (c) || c == ':')
! 				*cp2++ = c;
! 
! 		*cp2 = '\0';
! 		while (subjcomp[0] == 'r' && subjcomp[1] == 'e'
! 		       && subjcomp[2] == ':')
! 			subjcomp += 3;
! 
! 		smsg->s_subj = subjcomp;
! 	}
  	(void) fclose (in);
  	if (datecomp)
  		free (datecomp);
***************
*** 257,263
      if (hp != NULL)
  	free (hp);
      (void) fclose (in);
!     return tw;
  }
  
  /*  */

--- 351,360 -----
  		smsg->s_subj = subjcomp;
  	}
  	(void) fclose (in);
! 	if (datecomp)
! 		free (datecomp);
! 
! 	return (1);
  }
  
  /*
***************
*** 260,266
      return tw;
  }
  
! /*  */
  
  static int  msgsort (a, b)
  register struct smsg *a,

--- 357,378 -----
  	return (1);
  }
  
! /*
!  * sort on dates.
!  */
! static int 
! dsort (a, b)
! 	register struct smsg **a, **b;
! {
! 	if ((*a)->s_clock < (*b)->s_clock)
! 		return (-1);
! 	else if ((*a)->s_clock > (*b)->s_clock)
! 		return (1);
! 	else if ((*a)->s_msg < (*b)->s_msg)
! 		return (-1);
! 	else
! 		return (1);
! }
  
  
  /*
***************
*** 262,270
  
  /*  */
  
! static int  msgsort (a, b)
! register struct smsg *a,
! 		     *b;
  {
      return twsort (&a -> s_tws, &b -> s_tws);
  }

--- 374,386 -----
  		return (1);
  }
  
! 
! /*
!  * sort on subjects.
!  */
! static int 
! subsort (a, b)
! 	register struct smsg **a, **b;
  {
  	register int i;
  	if (i = strcmp ((*a)->s_subj, (*b)->s_subj))
***************
*** 266,272
  register struct smsg *a,
  		     *b;
  {
!     return twsort (&a -> s_tws, &b -> s_tws);
  }
  
  /*  */

--- 382,396 -----
  subsort (a, b)
  	register struct smsg **a, **b;
  {
! 	register int i;
! 	if (i = strcmp ((*a)->s_subj, (*b)->s_subj))
! 		return (i);
! 
! 	if ((*a)->s_clock < (*b)->s_clock)
! 		return (-1);
! 	else if ((*a)->s_clock > (*b)->s_clock)
! 		return (1);
! 	else return (0);
  }
  
  
***************
*** 269,275
      return twsort (&a -> s_tws, &b -> s_tws);
  }
  
- /*  */
  
  static  file_dates (mp, verbosw)
  register struct  msgs *mp;

--- 393,398 -----
  	else return (0);
  }
  
  
  static 
  rename_msgs (mp, mlist)
***************
*** 271,279
  
  /*  */
  
! static  file_dates (mp, verbosw)
! register struct  msgs *mp;
! int     verbosw;
  {
      register int    i,
                      j,

--- 394,403 -----
  }
  
  
! static 
! rename_msgs (mp, mlist)
! 	register struct msgs *mp;
! 	register struct smsg **mlist;
  {
  	register int i, j, old, new;
  	register struct smsg *sp;
***************
*** 275,283
  register struct  msgs *mp;
  int     verbosw;
  {
!     register int    i,
!                     j,
!                     k;
      short   stats;
      char    f1[BUFSIZ],
              f2[BUFSIZ],

--- 399,406 -----
  	register struct msgs *mp;
  	register struct smsg **mlist;
  {
! 	register int i, j, old, new;
! 	register struct smsg *sp;
  	short stats;
  	char f1[BUFSIZ], f2[BUFSIZ], tmpfil[BUFSIZ];
  
***************
*** 279,287
                      j,
                      k;
      short   stats;
!     char    f1[BUFSIZ],
!             f2[BUFSIZ],
!             tmpfil[BUFSIZ];
  
      (void) strcpy (tmpfil, m_scratch ("", invo_name));
  

--- 402,408 -----
  	register int i, j, old, new;
  	register struct smsg *sp;
  	short stats;
! 	char f1[BUFSIZ], f2[BUFSIZ], tmpfil[BUFSIZ];
  
  	(void) strcpy (tmpfil, m_scratch ("", invo_name));
  
***************
*** 285,297
  
      (void) strcpy (tmpfil, m_scratch ("", invo_name));
  
!     for (i = 0; j = smsgs[i++].s_msg;)
! 	if (i != j) {
! 	    (void) strcpy (f1, m_name (i));
! 	    (void) strcpy (f2, m_name (j));
! 	    if (mp -> msgstats[i] & EXISTS) {
! 		if (verbosw)
! 		    printf ("swap messages %s and %s\n", f2, f1);
  
  		if (rename (f1, tmpfil) == NOTOK) {
  		    admonish (tmpfil, "unable to rename %s to ", f1);

--- 406,414 -----
  
  	(void) strcpy (tmpfil, m_scratch ("", invo_name));
  
! 	for (i = 0; i < nmsgs; i++) {
! 		if (! (sp = mlist[i])) 
! 			continue;	/* did this one */
  
  		j = sp - smsgs;
  		if (j == i)
***************
*** 293,302
  		if (verbosw)
  		    printf ("swap messages %s and %s\n", f2, f1);
  
! 		if (rename (f1, tmpfil) == NOTOK) {
! 		    admonish (tmpfil, "unable to rename %s to ", f1);
! 		    continue;
! 		}
  
  		if (rename (f2, f1) == NOTOK) {
  		    admonish (f1, "unable to rename %s to", f2);

--- 410,418 -----
  		if (! (sp = mlist[i])) 
  			continue;	/* did this one */
  
! 		j = sp - smsgs;
! 		if (j == i)
! 			continue;	/* this one doesn't move */
  
  		/*
  		 * the guy that was msg j is about to become msg i.
***************
*** 298,307
  		    continue;
  		}
  
! 		if (rename (f2, f1) == NOTOK) {
! 		    admonish (f1, "unable to rename %s to", f2);
! 		    continue;
! 		}
  
  		if (rename (tmpfil, f2) == NOTOK) {
  		    admonish (f2, "unable to rename %s to", tmpfil);

--- 414,427 -----
  		if (j == i)
  			continue;	/* this one doesn't move */
  
! 		/*
! 		 * the guy that was msg j is about to become msg i.
! 		 * rename 'j' to make a hole, then recursively rename
! 		 * guys to fill up the hole.
! 		 */
! 		old = smsgs[j].s_msg;
! 		new = smsgs[i].s_msg;
! 		(void) strcpy (f1, m_name (old));
  
  		if (verbose)
  			printf ("renaming chain from %d to %d\n", old, new);
***************
*** 303,312
  		    continue;
  		}
  
! 		if (rename (tmpfil, f2) == NOTOK) {
! 		    admonish (f2, "unable to rename %s to", tmpfil);
! 		    continue;
! 		}
  
  		for (k = i; smsgs[k].s_msg; k++)
  		    if (smsgs[k].s_msg == i) {

--- 423,430 -----
  		new = smsgs[i].s_msg;
  		(void) strcpy (f1, m_name (old));
  
! 		if (verbose)
! 			printf ("renaming chain from %d to %d\n", old, new);
  
  		if (rename (f1, tmpfil) == NOTOK)
  			adios (tmpfil, "unable to rename %s to ", f1);
***************
*** 308,322
  		    continue;
  		}
  
! 		for (k = i; smsgs[k].s_msg; k++)
! 		    if (smsgs[k].s_msg == i) {
! 			smsgs[k].s_msg = j;
! 			break;
! 		    }
! 	    }
! 	    else {
! 		if (verbosw)
! 		    printf ("message %s becomes message %s\n", f2, f1);
  
  		if (rename (f2, f1) == NOTOK) {
  		    admonish (f1, "unable to rename %s to ", f2);

--- 426,434 -----
  		if (verbose)
  			printf ("renaming chain from %d to %d\n", old, new);
  
! 		if (rename (f1, tmpfil) == NOTOK)
! 			adios (tmpfil, "unable to rename %s to ", f1);
! 		stats = mp->msgstats[old];
  
  		rename_chain (mp, mlist, j, i);
  		if (rename (tmpfil, m_name(new)) == NOTOK)
***************
*** 318,326
  		if (verbosw)
  		    printf ("message %s becomes message %s\n", f2, f1);
  
! 		if (rename (f2, f1) == NOTOK) {
! 		    admonish (f1, "unable to rename %s to ", f2);
! 		    continue;
  		}
  	    }
  

--- 430,441 -----
  			adios (tmpfil, "unable to rename %s to ", f1);
  		stats = mp->msgstats[old];
  
! 		rename_chain (mp, mlist, j, i);
! 		if (rename (tmpfil, m_name(new)) == NOTOK)
! 			adios (m_name(new), "unable to rename %s to", tmpfil);
! 
! 		mp->msgstats[new] = stats;
! 		mp->msgflags |= SEQMOD;
  	}
  }
  
***************
*** 322,328
  		    admonish (f1, "unable to rename %s to ", f2);
  		    continue;
  		}
! 	    }
  
  	    smsgs[i - 1].s_msg = i;
  	    stats = mp -> msgstats[i];

--- 437,443 -----
  		mp->msgstats[new] = stats;
  		mp->msgflags |= SEQMOD;
  	}
! }
  
  rename_chain (mp, mlist, msg, endmsg)
  	register struct msgs *mp;
***************
*** 324,335
  		}
  	    }
  
! 	    smsgs[i - 1].s_msg = i;
! 	    stats = mp -> msgstats[i];
! 	    mp -> msgstats[i] = mp -> msgstats[j];
! 	    mp -> msgstats[j] = stats;
! 	    if (mp -> curmsg == j)
! 		m_setcur (mp, i);
  	    mp -> msgflags |= SEQMOD;
  	}
  }

--- 439,501 -----
  	}
  }
  
! rename_chain (mp, mlist, msg, endmsg)
! 	register struct msgs *mp;
! 	struct smsg **mlist;
! 	int msg, endmsg;
! {
! 	int nxt, old, new;
! 	char *newname;
! 	char oldname[BUFSIZ];
! 
! 	nxt = mlist[msg] - smsgs;
! 	mlist[msg] = 0;
! 	old = smsgs[nxt].s_msg;
! 	new = smsgs[msg].s_msg;
! 	(void) strcpy (oldname, m_name (old));
! 	newname = m_name (new);
! 	if (verbose)
! 		printf ("    %s becomes %s\n", oldname, newname);
! 
! 	if (rename (oldname, newname) == NOTOK)
! 		adios (newname, "unable to rename %s to", oldname);
! 
! 	mp->msgstats[new] = mp->msgstats[old];
! 	if (mp->curmsg == old)
! 		m_setcur (mp, new);
! 
! 	if (nxt != endmsg)
! 		rename_chain (mp, mlist, nxt, endmsg);
! }
! 
! /* This folder packing routine was shamelessly lifted from folder.c so sortm
!    wouldn't change behavior from the "old" way.
!  */
! 
! struct msgs *tfold (mp)
! register struct msgs   *mp;
! {
!     register int    hole,
!                     msgnum;
!     char    newmsg[BUFSIZ],
!             oldmsg[BUFSIZ];
! 
!     if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL)
! 	adios (NULLCP, "unable to allocate folder storage");
! 
!     if (verbose)
! 		printf ("....packing folder\n");
! 
!     for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++)
! 	if (mp -> msgstats[msgnum] & EXISTS) {
! 	    if (msgnum != hole) {
! 		(void) strcpy (newmsg, m_name (hole));
! 		(void) strcpy (oldmsg, m_name (msgnum));
! 		if (rename (oldmsg, newmsg) == NOTOK)
! 		    adios (newmsg, "unable to rename %s to", oldmsg);
! 		if (msgnum == mp -> curmsg)
! 		    m_setcur (mp, mp -> curmsg = hole);
! 		mp -> msgstats[hole] = mp -> msgstats[msgnum];
  		mp -> msgflags |= SEQMOD;
  		if (msgnum == mp -> lowsel)
  		    mp -> lowsel = hole;
***************
*** 331,335
  	    if (mp -> curmsg == j)
  		m_setcur (mp, i);
  	    mp -> msgflags |= SEQMOD;
  	}
  }

--- 497,506 -----
  		    m_setcur (mp, mp -> curmsg = hole);
  		mp -> msgstats[hole] = mp -> msgstats[msgnum];
  		mp -> msgflags |= SEQMOD;
+ 		if (msgnum == mp -> lowsel)
+ 		    mp -> lowsel = hole;
+ 		if (msgnum == mp -> hghsel)
+ 		    mp -> hghsel = hole;
  	    }
  	    hole++;
  	}
***************
*** 332,335
  		m_setcur (mp, i);
  	    mp -> msgflags |= SEQMOD;
  	}
  }

--- 502,514 -----
  		if (msgnum == mp -> hghsel)
  		    mp -> hghsel = hole;
  	    }
+ 	    hole++;
+ 	}
+     if (mp -> nummsg > 0) {
+ 	mp -> lowmsg = 1;
+ 	mp -> hghmsg = hole - 1;
+     }
+ 
+     return mp;
  }
  
***************
*** 333,335
  	    mp -> msgflags |= SEQMOD;
  	}
  }

--- 511,514 -----
  
      return mp;
  }
+