home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elm.lzh / ELM / SRC / SORT.C < prev    next >
Text File  |  1991-01-11  |  8KB  |  286 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: sort.c,v 4.1 90/04/28 22:44:12 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    sort.c,v $
  17.  * Revision 4.1  90/04/28  22:44:12  syd
  18.  * checkin of Elm 2.3 as of Release PL0
  19.  * 
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /** Sort folder header table by the field specified in the global
  24.     variable "sortby"...if we're sorting by something other than
  25.     the default SENT_DATE, also put some sort of indicator on the
  26.     screen.
  27.  
  28. **/
  29.  
  30. #include "headers.h"
  31.  
  32. char *sort_name(), *skip_re();
  33. void   qsort();
  34.  
  35. sort_mailbox(entries, visible)
  36. int entries, visible;
  37. {
  38.     /** Sort the header_table definitions... If 'visible', then
  39.         put the status lines etc **/
  40.     
  41.     int last_index = -1;
  42.     int compare_headers();    /* for sorting */
  43.  
  44.     dprint(2, (debugfile, "\n** sorting folder by %s **\n\n", 
  45.         sort_name(FULL)));
  46.  
  47.     /* Don't get last_index if no entries or no current. */
  48.     /* There would be no current if we are sorting a new mail file. */
  49.     if (entries > 0 && current > 0)
  50.       last_index = headers[current-1]->index_number;
  51.  
  52.     if (entries > 30 && visible)  
  53.       error1("Sorting messages by %s...", sort_name(FULL));
  54.     
  55.     if (entries > 1)
  56.       qsort(headers, (unsigned) entries, sizeof (struct header_rec *),
  57.           compare_headers);
  58.  
  59.     if (last_index > -1)
  60.       find_old_current(last_index);
  61.  
  62.     clear_error();
  63. }
  64.  
  65. int
  66. compare_headers(p1, p2)
  67. struct header_rec **p1, **p2;
  68. {
  69.     /** compare two headers according to the sortby value.
  70.  
  71.         Sent Date uses a routine to compare two dates,
  72.         Received date is keyed on the file offsets (think about it)
  73.         Sender uses the truncated from line, same as "build headers",
  74.         and size and subject are trivially obvious!!
  75.         (actually, subject has been modified to ignore any leading
  76.         patterns [rR][eE]*:[ \t] so that replies to messages are
  77.         sorted with the message (though a reply will always sort to
  78.         be 'greater' than the basenote)
  79.      **/
  80.  
  81.     char from1[SLEN], from2[SLEN];    /* sorting buffers... */
  82.     struct header_rec *first, *second;
  83.     int ret;
  84.     long diff;
  85.     
  86.     first = *p1;
  87.     second = *p2;
  88.  
  89.     switch (abs(sortby)) {
  90.     case SENT_DATE:
  91.          diff = first->time_sent - second->time_sent;
  92.          if ( diff < 0 )    ret = -1;
  93.          else if ( diff > 0 ) ret = 1;
  94.          else ret = 0;
  95.           break;
  96.  
  97.     case RECEIVED_DATE:
  98.         ret = compare_parsed_dates(first->received, second->received);
  99.         break;
  100.  
  101.     case SENDER:
  102.         tail_of(first->from, from1, first->to);
  103.         tail_of(second->from, from2, second->to);
  104.         ret = strcmp(from1, from2);
  105.         break;
  106.  
  107.     case SIZE:
  108.         ret = (first->lines - second->lines);
  109.         break;
  110.  
  111.     case MAILBOX_ORDER:
  112.         ret = (first->index_number - second->index_number);
  113.         break;
  114.  
  115.     case SUBJECT:
  116.         /* need some extra work 'cause of STATIC buffers */
  117.         strcpy(from1, skip_re(shift_lower(first->subject)));
  118.         ret = strcmp(from1, skip_re(shift_lower(second->subject)));
  119.         break;
  120.  
  121.     case STATUS:
  122.         ret = (first->status - second->status);
  123.         break;
  124.  
  125.     default:
  126.         /* never get this! */
  127.         ret = 0;
  128.         break;
  129.     }
  130.  
  131.     if (sortby < 0)
  132.       ret = -ret;
  133.  
  134.     return ret;
  135. }
  136.  
  137. char *sort_name(type)
  138. int type;
  139. {
  140.     /** return the name of the current sort option...
  141.         type can be "FULL", "SHORT" or "PAD"
  142.     **/
  143.     int pad, abr;
  144.     
  145.     pad = (type == PAD);
  146.     abr = (type == SHORT);
  147.  
  148.     if (sortby < 0) {
  149.       switch (- sortby) {
  150.         case SENT_DATE    : return( 
  151.                       pad?     "Reverse Date Mail Sent  " : 
  152.                   abr?     "Reverse-Sent" :
  153.                        "Reverse Date Mail Sent");
  154.         case RECEIVED_DATE: return(
  155.                   abr?     "Reverse-Received":
  156.                   "Reverse Date Mail Rec'vd" );
  157.  
  158.         case MAILBOX_ORDER: return(
  159.                   pad?     "Reverse Mailbox Order   " :
  160.                   abr?     "Reverse-Mailbox":
  161.                            "Reverse Mailbox Order");
  162.  
  163.         case SENDER       : return(
  164.                   pad?     "Reverse Message Sender  " : 
  165.                   abr?     "Reverse-From":
  166.                        "Reverse Message Sender");
  167.         case SIZE         : return(
  168.                   abr?     "Reverse-Lines" : 
  169.                        "Reverse Lines in Message");
  170.         case SUBJECT      : return(
  171.                   pad?     "Reverse Message Subject " : 
  172.                   abr?     "Reverse-Subject" : 
  173.                        "Reverse Message Subject");
  174.         case STATUS          : return(
  175.                   pad?     "Reverse Message Status  " :
  176.                   abr?     "Reverse-Status":
  177.                            "Reverse Message Status");
  178.       }
  179.     }
  180.     else {
  181.       switch (sortby) {
  182.         case SENT_DATE    : return( 
  183.                         pad?   "Date Mail Sent          " : 
  184.                         abr?   "Sent" : 
  185.                        "Date Mail Sent");
  186.         case RECEIVED_DATE: return(
  187.                             pad?   "Date Mail Rec'vd        " :
  188.                             abr?   "Received" :
  189.                        "Date Mail Rec'vd");
  190.         case MAILBOX_ORDER: return(
  191.                             pad?   "Mailbox Order           " :
  192.                             abr?   "Mailbox" :
  193.                                    "Mailbox Order");
  194.         case SENDER       : return(
  195.                     pad?   "Message Sender          " : 
  196.                     abr?   "From" : 
  197.                        "Message Sender");
  198.         case SIZE         : return(
  199.                     pad?   "Lines in Message        " :
  200.                     abr?   "Lines" :
  201.                            "Lines in Message");
  202.         case SUBJECT      : return(
  203.                     pad?   "Message Subject         " : 
  204.                     abr?   "Subject" : 
  205.                        "Message Subject");
  206.         case STATUS          : return(
  207.                     pad?   "Message Status          " :
  208.                     abr?   "Status" :
  209.                            "Message Status");
  210.       }
  211.     }
  212.  
  213.     return("*UNKNOWN-SORT-PARAMETER*");
  214. }
  215.  
  216. find_old_current(iindex)
  217. int iindex;
  218. {
  219.     /** Set current to the message that has "index" as it's 
  220.         index number.  This is to track the current message
  221.         when we resync... **/
  222.  
  223.     register int i;
  224.  
  225.     dprint(4, (debugfile, "find-old-current(%d)\n", iindex));
  226.  
  227.     for (i = 0; i < message_count; i++)
  228.       if (headers[i]->index_number == iindex) {
  229.         current = i+1;
  230.         dprint(4, (debugfile, "\tset current to %d!\n", current));
  231.         return;
  232.       }
  233.  
  234.     dprint(4, (debugfile, 
  235.         "\tcouldn't find current index.  Current left as %d\n",
  236.         current));
  237.     return;        /* can't be found.  Leave it alone, then */
  238. }
  239.  
  240. char *skip_re(string)
  241. char *string;
  242. {
  243.     /** this routine returns the given string minus any sort of
  244.         "re:" prefix.  specifically, it looks for, and will
  245.         remove, any of the pattern:
  246.  
  247.         ( [Rr][Ee][^:]:[ ] ) *
  248.  
  249.         If it doesn't find a ':' in the line it will return it
  250.         intact, just in case!
  251.     **/
  252.  
  253.     static char buffer[SLEN];
  254.     register int i=0;
  255.  
  256.     while (whitespace(string[i])) i++;
  257.  
  258.     do {
  259.       if (string[i] == '\0') return( (char *) string);    /* forget it */
  260.  
  261.       if (string[i] != 'r' || string[i+1] != 'e') 
  262.         return( (char *) string);                /*   ditto   */
  263.  
  264.       i += 2;    /* skip the "re" */
  265.  
  266.       while (string[i] != ':') 
  267.         if (string[i] == '\0')
  268.           return( (char *) string);              /* no colon in string! */
  269.         else
  270.           i++;
  271.  
  272.       /* now we've gotten to the colon, skip to the next non-whitespace  */
  273.  
  274.       i++;    /* past the colon */
  275.  
  276.       while (whitespace(string[i])) i++;
  277.  
  278.     } while (string[i] == 'r' && string[i+1] == 'e');
  279.  
  280.     /* and now copy it into the buffer and sent it along... */
  281.  
  282.     strcpy(buffer, (char *) string + i);
  283.  
  284.     return( (char *) buffer);
  285. }
  286.