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 / LIMIT.C < prev    next >
Text File  |  1991-01-11  |  9KB  |  299 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: limit.c,v 4.1 90/04/28 22:43:21 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:    limit.c,v $
  17.  * Revision 4.1  90/04/28  22:43:21  syd
  18.  * checkin of Elm 2.3 as of Release PL0
  19.  * 
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /** This stuff is inspired by MH and dmail and is used to 'select'
  24.     a subset of the existing mail in the folder based on one of a
  25.     number of criteria.  The basic tricks are pretty easy - we have
  26.     as status of VISIBLE associated with each header stored in the
  27.     (er) mind of the computer (!) and simply modify the commands to
  28.     check that flag...the global variable `selected' is set to the
  29.     number of messages currently selected, or ZERO if no select.
  30. **/
  31.  
  32. #include "headers.h"
  33.  
  34. #define TO        1
  35. #define FROM        2
  36.  
  37. char *shift_lower();
  38.  
  39. int
  40. limit()
  41. {
  42.     /** returns non-zero if we changed selection criteria = need redraw **/
  43.     
  44.     char criteria[STRING], first[STRING], rest[STRING], msg[STRING];
  45.     static char prompt[] = "Enter criteria or '?' for help: ";
  46.     int  last_selected, all;
  47.  
  48.     last_selected = selected;
  49.     all = 0;
  50.  
  51.     if (selected) {
  52.       PutLine1(LINES-2, 0, 
  53.         "Already have selection criteria - add more? (y/n) n%c",
  54.         BACKSPACE);
  55.       criteria[0] = ReadCh();
  56.       if (tolower(criteria[0]) == 'y') {
  57.         Write_to_screen("Yes.", 0);
  58.         PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
  59.       } else {
  60.         Write_to_screen("No.", 0);
  61.         selected = 0;
  62.         PutLine0(LINES-3, COLUMNS-30, "Change criteria...");
  63.       }
  64.     }
  65.  
  66.     while(1) {
  67.       PutLine1(LINES-2, 0, prompt);
  68.       CleartoEOLN();
  69.  
  70.       criteria[0] = '\0';
  71.       optionally_enter(criteria, LINES-2, strlen(prompt), FALSE, FALSE);
  72.       error("");
  73.       
  74.       if (strlen(criteria) == 0) {
  75.         /* no change */
  76.         selected = last_selected;
  77.         return(FALSE);    
  78.       }
  79.  
  80.       split_word(criteria, first, rest);
  81.  
  82.       if (equal(first, "?")) {
  83.          if(last_selected)
  84.            error(
  85.               "Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"all\"");
  86.          else
  87.            error("Enter: {\"subject\",\"to\",\"from\"} [pattern]");
  88.          continue;
  89.       } else if (equal(first, "all")) {
  90.         all++;
  91.         selected = 0;
  92.       }
  93.       else if (equal(first, "subj") || equal(first, "subject"))
  94.         selected = limit_selection(SUBJECT, rest, selected);
  95.       else if (equal(first, "to"))
  96.         selected = limit_selection(TO, rest, selected);
  97.       else if (equal(first, "from"))
  98.         selected = limit_selection(FROM, rest, selected);
  99.       else {
  100.         error1("\"%s\" not a valid criterion.", first);
  101.         continue;
  102.       }
  103.       break;
  104.     }
  105.  
  106.     if(all && last_selected)
  107.       strcpy(msg, "Returned to unlimited display.");
  108.     else if(selected)
  109.       sprintf(msg, "%d message%s selected.", selected, plural(selected));
  110.     else
  111.       strcpy(msg, "No messages selected.");
  112.     set_error(msg);
  113.  
  114.     /* we need a redraw if there had been a selection or there is now. */
  115.     if(last_selected || selected) {
  116.       /* if current message won't be on new display, go to first message */
  117.       if(selected && !(headers[current-1]->status & VISIBLE))
  118.         current = visible_to_index(1)+1;
  119.       return(TRUE);
  120.     } else {
  121.       return(FALSE);
  122.     }
  123. }
  124.  
  125. int
  126. limit_selection(based_on, pattern, additional_criteria)
  127. int based_on, additional_criteria;
  128. char *pattern;
  129. {
  130.     /** Given the type of criteria, and the pattern, mark all
  131.         non-matching headers as ! VISIBLE.  If additional_criteria,
  132.         don't mark as visible something that isn't currently!
  133.     **/
  134.  
  135.     register int iindex, count = 0;
  136.  
  137.     dprint(2, (debugfile, "\n\n\n**limit on %d - '%s' - (%s) **\n\n",
  138.            based_on, pattern, additional_criteria?"add'tl":"base"));
  139.  
  140.     if (based_on == SUBJECT) {
  141.       for (iindex = 0; iindex < message_count; iindex++)
  142.         if (! in_string(shift_lower(headers[iindex]->subject), pattern))
  143.           headers[iindex]->status &= ~VISIBLE;
  144.         else if (additional_criteria &&     
  145.              !(headers[iindex]->status & VISIBLE))
  146.           headers[iindex]->status &= ~VISIBLE;    /* shut down! */
  147.         else { /* mark it as readable */
  148.           headers[iindex]->status |= VISIBLE;
  149.           count++;
  150.           dprint(5, (debugfile,
  151.              "  Message %d (%s from %s) marked as visible\n",
  152.             iindex, headers[iindex]->subject,
  153.             headers[iindex]->from));
  154.         }
  155.     }
  156.     else if (based_on == FROM) {
  157.       for (iindex = 0; iindex < message_count; iindex++)
  158.         if (! in_string(shift_lower(headers[iindex]->from), pattern))
  159.           headers[iindex]->status &= ~VISIBLE;
  160.         else if (additional_criteria &&     
  161.              !(headers[iindex]->status & VISIBLE))
  162.           headers[iindex]->status &= ~VISIBLE;    /* shut down! */
  163.         else { /* mark it as readable */
  164.           headers[iindex]->status |= VISIBLE;
  165.           count++;
  166.           dprint(5, (debugfile, 
  167.             "  Message %d (%s from %s) marked as visible\n",
  168.             iindex, headers[iindex]->subject,
  169.             headers[iindex]->from));
  170.         }
  171.     }
  172.     else if (based_on == TO) {
  173.       for (iindex = 0; iindex < message_count; iindex++)
  174.         if (! in_string(shift_lower(headers[iindex]->to), pattern))
  175.           headers[iindex]->status &= ~VISIBLE;
  176.         else if (additional_criteria &&     
  177.              !(headers[iindex]->status & VISIBLE))
  178.           headers[iindex]->status &= ~VISIBLE;    /* shut down! */
  179.         else { /* mark it as readable */
  180.           headers[iindex]->status |= VISIBLE;
  181.           count++;
  182.           dprint(5, (debugfile,
  183.             "  Message %d (%s from %s) marked as visible\n",
  184.             iindex, headers[iindex]->subject,
  185.             headers[iindex]->from));
  186.         }
  187.     }
  188.  
  189.     dprint(4, (debugfile, "\n** returning %d selected **\n\n\n", count));
  190.  
  191.     return(count);
  192. }
  193.  
  194. int
  195. next_message(iindex, skipdel)
  196. register int iindex, skipdel;
  197. {
  198.     /** Given 'iindex', this routine will return the actual iindex into the
  199.         array of the NEXT message, or '-1' iindex is the last.
  200.         If skipdel, return the iindex for the NEXT undeleted message.
  201.         If selected, return the iindex for the NEXT message marked VISIBLE.
  202.     **/
  203.  
  204.     register int remember_for_debug;
  205.  
  206.     if(iindex < 0) return(-1);    /* invalid argument value! */
  207.  
  208.     remember_for_debug = iindex;
  209.  
  210.     for(iindex++;iindex < message_count; iindex++)
  211.       if (((headers[iindex]->status & VISIBLE) || (!selected))
  212.         && (!(headers[iindex]->status & DELETED) || (!skipdel))) {
  213.           dprint(9, (debugfile, "[Next%s%s: given %d returning %d]\n", 
  214.           (skipdel ? " undeleted" : ""),
  215.           (selected ? " visible" : ""),
  216.           remember_for_debug+1, iindex+1));
  217.           return(iindex);
  218.       }
  219.     return(-1);
  220. }
  221.  
  222. int
  223. prev_message(iindex, skipdel)
  224. register int iindex, skipdel;
  225. {
  226.     /** Like next_message, but the PREVIOUS message. **/
  227.  
  228.     register int remember_for_debug;
  229.  
  230.     if(iindex >= message_count) return(-1);    /* invalid argument value! */
  231.  
  232.     remember_for_debug = iindex;
  233.     for(iindex--; iindex >= 0; iindex--)
  234.       if (((headers[iindex]->status & VISIBLE) || (!selected))
  235.         && (!(headers[iindex]->status & DELETED) || (!skipdel))) {
  236.           dprint(9, (debugfile, "[Previous%s%s: given %d returning %d]\n", 
  237.           (skipdel ? " undeleted" : ""),
  238.           (selected ? " visible" : ""),
  239.           remember_for_debug+1, iindex+1));
  240.           return(iindex);
  241.       }
  242.     return(-1);
  243. }
  244.  
  245.  
  246. int
  247. compute_visible(message)
  248. int message;
  249. {
  250.     /** return the 'virtual' iindex of the specified message in the
  251.         set of messages - that is, if we have the 25th message as
  252.         the current one, but it's #2 based on our limit criteria,
  253.         this routine, given 25, will return 2.
  254.     **/
  255.  
  256.     register int iindex, count = 0;
  257.  
  258.     if (! selected) return(message);
  259.  
  260.     if (message < 1) message = 1;    /* normalize */
  261.  
  262.     for (iindex = 0; iindex < message; iindex++)
  263.        if (headers[iindex]->status & VISIBLE) 
  264.          count++;
  265.  
  266.     dprint(4, (debugfile,
  267.         "[compute-visible: displayed message %d is actually %d]\n",
  268.         count, message));
  269.  
  270.     return(count);
  271. }
  272.  
  273. int
  274. visible_to_index(message)
  275. int message;
  276. {
  277.     /** Given a 'virtual' iindex, return a real one.  This is the
  278.         flip-side of the routine above, and returns (message_count+1)
  279.         if it cannot map the virtual iindex requested (too big) 
  280.     **/
  281.  
  282.     register int iindex = 0, count = 0;
  283.  
  284.     for (iindex = 0; iindex < message_count; iindex++) {
  285.        if (headers[iindex]->status & VISIBLE) 
  286.          count++;
  287.        if (count == message) {
  288.          dprint(4, (debugfile,
  289.              "visible-to-index: (up) index %d is displayed as %d\n",
  290.              message, iindex));
  291.          return(iindex);
  292.        }
  293.     }
  294.  
  295.     dprint(4, (debugfile, "index %d is NOT displayed!\n", message));
  296.  
  297.     return(message_count+1);
  298. }
  299.