home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / sort.c.orig < prev    next >
Text File  |  1990-10-21  |  9KB  |  315 lines

  1. /* sort.c 3.0    (c) copyright 1986,1990 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4. /* #define MYQSORT */
  5.  
  6. /* The size of this array should really be bounded by
  7.  * 2 spaces for each possible different sort criteria
  8.  * (one space for each key letter and one per for 'r'),
  9.  * but 16 leaves room to add to the current list.
  10.  */
  11. static char subsort[16];
  12.  
  13. static int depth, order, ignore_case;
  14. static jmp_buf sortbuf;
  15.  
  16. sort(argc, argv, list)
  17. register int argc;
  18. register char *argv[], list[];
  19. {
  20.     int msg_cmp();
  21.     SIGRET (*oldint)(), (*oldquit)();
  22.     int n, offset = -1, range = 0;
  23.     long curr_msg_off = msg[current_msg].m_offset;
  24.  
  25.     depth = 0, order = 1, ignore_case = FALSE;
  26.  
  27.     while (argc && *++argv) {
  28.     n = (argv[0][0] == '-' && argv[0][1] != 0);
  29.     while (argv[0][n]) {
  30.         if (depth > sizeof subsort - 2)
  31.         break;
  32.         switch(argv[0][n]) {
  33.         case '-': /* reverse order of next criteria (obsolete) */
  34.             argv[0][n] = 'r'; /* fix it and fall through */
  35.         case 'r': /* reverse order of next criteria */
  36.         case 'd': /* sort by date */
  37.         case 'a': /* sort by author (address) */
  38.         case 's': /* sort by subject (ignore Re:) */
  39.         case 'R': /* sort by subject including Re: */
  40.         case 'l': /* sort by length in bytes */
  41.         case 'S': /* sort by message status */
  42.         case 'p': /* sort by message priority */
  43.             /* skip consecutive repeats of the same flag */
  44.             if (depth < 1 || subsort[depth-1] != argv[0][n])
  45.             subsort[depth++] = argv[0][n];
  46.         when 'i': ignore_case = TRUE;
  47.         otherwise: return help(0, "sort", cmd_help);
  48.         }
  49.         n++;
  50.     }
  51.     }
  52.     if (depth == 0 || subsort[depth-1] == 'r')
  53.     subsort[depth++] = 'S'; /* status sort is the default */
  54.     subsort[depth] = 0;
  55.     depth = 0;    /* start at the beginning */
  56.     if (msg_cnt <= 1) {
  57.     print("Not enough messages to sort.\n");
  58.     return -1;
  59.     }
  60.     turnon(glob_flags, IGN_SIGS);
  61.     on_intr();
  62.  
  63.     if (list && ison(glob_flags, IS_PIPE)) {
  64.     int consec = 1;
  65.     for (n = 0; n < msg_cnt; n++)
  66.         if (msg_bit(list, n)) {
  67.         if (!consec) {
  68.             ok_box("Listed messages not consecutive\n");
  69.             turnoff(glob_flags, IGN_SIGS);
  70.             off_intr();
  71.             return -1;
  72.         }
  73.         if (offset < 0)
  74.             offset = n;
  75.         range++;
  76.         } else if (offset >= 0)
  77.         consec = 0;
  78.     } else
  79.     offset = 0, range = msg_cnt;
  80.  
  81.     if (range < 2)
  82.     print("Range not broad enough to sort anything\n");
  83.     else {
  84.     Debug("Sorting %d messages starting at message %d\n", range, offset+1);
  85.  
  86.     if (setjmp(sortbuf) == 0)
  87.         qsort((char *)&msg[offset], range, sizeof (struct msg), msg_cmp);
  88.     else
  89.         print("WARNING: Sorting interrupted: unpredictable order.\n");
  90.     turnon(glob_flags, DO_UPDATE);
  91.     }
  92.     for (n = 0; n < msg_cnt; n++)
  93.     if (msg[n].m_offset == curr_msg_off)
  94.         break;
  95.     current_msg = n;
  96.     turnoff(glob_flags, IGN_SIGS);
  97.     off_intr();
  98.     /* Break pipes because message lists are invalid */
  99.     return 0 - in_pipe();
  100. }
  101.  
  102. #ifdef MYQSORT
  103. qsort(base, len, siz, compar)
  104. register struct msg *base;
  105. int (*compar)();
  106. {
  107.      register int i, swapping;
  108.      struct msg temp;
  109.  
  110.      do  {
  111.      swapping = 0;
  112.      for (i = 0; i < len-1; ++i) {
  113.          if (compar(base+i, base+i+1) > 0) {
  114.          temp = base[i];
  115.          base[i] = base[i+1];
  116.          base[i+1] = temp;
  117.          swapping = 1;
  118.          }
  119.      }
  120.      } while (swapping);
  121. }
  122. #endif /* MYSORT */
  123.  
  124. status_cmp(msg1, msg2)
  125. register struct msg *msg1, *msg2;
  126. {
  127.     if (msg1->m_flags == msg2->m_flags)
  128.     return msg_cmp(msg1, msg2);
  129.     if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE))
  130.     return order;
  131.     if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE))
  132.     return -order;
  133.     if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD))
  134.     return -order;
  135.     if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD))
  136.     return order;
  137.     if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD))
  138.     return -order;
  139.     if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD))
  140.     return order;
  141.     if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE))
  142.     return -order;
  143.     if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE))
  144.     return order;
  145.     if (ison(msg1->m_flags,REPLIED) && isoff(msg2->m_flags,REPLIED))
  146.     return -order;
  147.     if (isoff(msg1->m_flags,REPLIED) && ison(msg2->m_flags,REPLIED))
  148.     return order;
  149.     if (ison(msg1->m_flags,SAVED) && isoff(msg2->m_flags,SAVED))
  150.     return -order;
  151.     if (isoff(msg1->m_flags,SAVED) && ison(msg2->m_flags,SAVED))
  152.     return order;
  153.     if (ison(msg1->m_flags,PRINTED) && isoff(msg2->m_flags,PRINTED))
  154.     return -order;
  155.     if (isoff(msg1->m_flags,PRINTED) && ison(msg2->m_flags,PRINTED))
  156.     return order;
  157.     if (ison(msg1->m_flags,FORWARD) && isoff(msg2->m_flags,FORWARD))
  158.     return -order;
  159.     if (isoff(msg1->m_flags,FORWARD) && ison(msg2->m_flags,FORWARD))
  160.     return order;
  161.  
  162.     return pri_cmp(msg1, msg2);
  163. }
  164.  
  165. author_cmp(msg1, msg2)
  166. register struct msg *msg1, *msg2;
  167. {
  168.     char buf1[HDRSIZ], buf2[HDRSIZ];
  169.     int retval;
  170.  
  171.     (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */
  172.     (void) reply_to(msg2 - msg, 0, buf2);
  173.     Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
  174.     if (ignore_case)
  175.     retval = lcase_strncmp(buf1, buf2, -1) * order;
  176.     else
  177.     retval = strcmp(buf1, buf2) * order;
  178.     return retval ? retval : msg_cmp(msg1, msg2);
  179. }
  180.  
  181. /* compare messages according to size (length) */
  182. size_cmp(msg1, msg2)
  183. register struct msg *msg1, *msg2;
  184. {
  185.     int retval;
  186.  
  187.     Debug("sizes: (%d): %d, (%d): %d\"\n",
  188.     msg1-msg, msg1->m_size, msg2-msg, msg2->m_size);
  189.     if (retval = (msg1->m_size - msg2->m_size) * order) /* assign and test */
  190.     return retval;
  191.     return msg_cmp(msg1, msg2);
  192. }
  193.  
  194. /*
  195.  * Subject comparison ignoring Re:  subject_to() appends an Re: if there is
  196.  * any subject whatsoever.
  197.  */
  198. subject_cmp(msg1, msg2)
  199. register struct msg *msg1, *msg2;
  200. {
  201.     char buf1[HDRSIZ], buf2[HDRSIZ];
  202.     register char *p1, *p2;
  203.     int retval;
  204.  
  205.     p1 = subject_to(msg1 - msg, buf1);
  206.     p2 = subject_to(msg2 - msg, buf2);
  207.     if (p1) {
  208.     p1 += 4;
  209.     while (isspace(*p1))
  210.         p1++;
  211.     } else
  212.     p1 = buf1; /* subject_to() makes it an empty string */
  213.     if (p2) {
  214.     p2 += 4;
  215.     while (isspace(*p2))
  216.         p2++;
  217.     } else
  218.     p2 = buf2; /* subject_to() makes it an empty string */
  219.     Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg, p1, msg2-msg, p2);
  220.     if (ignore_case)
  221.     retval = lcase_strncmp(p1, p2, -1) * order;
  222.     else
  223.     retval = strcmp(p1, p2) * order;
  224.     return retval ? retval : msg_cmp(msg1, msg2);
  225. }
  226.  
  227. /*
  228.  * compare subject strings from two messages.
  229.  * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag.
  230.  */
  231. subj_with_re(msg1, msg2)
  232. register struct msg *msg1, *msg2;
  233. {
  234.     char buf1[HDRSIZ], buf2[HDRSIZ], *p;
  235.     int retval;
  236.  
  237.     if (!(p = header_field(msg1 - msg, "subject")))
  238.     p = "";
  239.     (void) strcpy(buf1, p);
  240.     if (!(p = header_field(msg2 - msg, "subject")))
  241.     p = "";
  242.     (void) strcpy(buf2, p);
  243.     Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n",
  244.     msg1-msg, buf1, msg2-msg, buf2);
  245.     if (ignore_case)
  246.     retval = lcase_strncmp(buf1, buf2, -1) * order;
  247.     else
  248.     retval = strcmp(buf1, buf2) * order;
  249.     return retval ? retval : msg_cmp(msg1, msg2);
  250. }
  251.  
  252. date_cmp(msg1, msg2)
  253. register struct msg *msg1, *msg2;
  254. {
  255.     long tm1, tm2;
  256.  
  257.     if (ison(glob_flags, DATE_RECV)) {
  258.     (void) sscanf(msg1->m_date_recv, "%ld", &tm1);
  259.     (void) sscanf(msg2->m_date_recv, "%ld", &tm2);
  260.     } else {
  261.     (void) sscanf(msg1->m_date_sent, "%ld", &tm1);
  262.     (void) sscanf(msg2->m_date_sent, "%ld", &tm2);
  263.     }
  264.     return tm1 < tm2 ? -order : (tm1 > tm2) ? order : msg_cmp(msg1, msg2);
  265. }
  266.  
  267. pri_cmp(msg1, msg2)
  268. register struct msg *msg1, *msg2;
  269. {
  270.     int i;
  271.     u_long pr1 = 0, pr2 = 0;
  272.  
  273.     for (i = 0; pr1 == pr2 && i <= MAX_PRIORITY; i++) {
  274.     if (ison(msg1->m_flags, M_PRIORITY(i)))
  275.         turnon(pr1, ULBIT(i));
  276.     if (ison(msg2->m_flags, M_PRIORITY(i)))
  277.         turnon(pr2, ULBIT(i));
  278.     }
  279.     return pr1 > pr2 ? -order : (pr1 < pr2) ? order : msg_cmp(msg1, msg2);
  280. }
  281.  
  282. static
  283. msg_cmp(msg1, msg2)
  284. register struct msg *msg1, *msg2;
  285. {
  286.     int sv_order = order, sv_depth = depth, retval = 0;
  287.  
  288.     if (ison(glob_flags, WAS_INTR))
  289.     longjmp(sortbuf, 1);
  290.     if (msg1 < msg || msg2 < msg) {
  291.     wprint("sort botch trying to sort %d and %d using %s\n",
  292.         msg1-msg, msg2-msg, subsort);
  293.     return 0;
  294.     }
  295.  
  296.     if (subsort[depth] == 'r') {
  297.     order = -1;
  298.     depth++;
  299.     } else
  300.     order = 1;
  301.     switch(subsort[depth++]) {
  302.     case '\0': retval = 0;
  303.     when 'd': retval = date_cmp(msg1, msg2);
  304.     when 'a': retval = author_cmp(msg1, msg2);
  305.     when 's': retval = subject_cmp(msg1, msg2);
  306.     when 'R': retval = subj_with_re(msg1, msg2);
  307.     when 'l': retval = size_cmp(msg1, msg2); /* length compare */
  308.     when 'p': retval = pri_cmp(msg1, msg2);
  309.     otherwise: retval = status_cmp(msg1, msg2);
  310.     }
  311.     depth = sv_depth;
  312.     order = sv_order;
  313.     return retval;
  314. }
  315.