Category : C Source Code
Archive   : ELM23SRC.ZIP
Filename : LIMIT.C

 
Output of file : LIMIT.C contained in archive : ELM23SRC.ZIP

static char rcsid[] = "@(#)$Id: limit.c,v 4.1 90/04/28 22:43:21 syd Exp $";

/*******************************************************************************
* The Elm Mail System - $Revision: 4.1 $ $State: Exp $
*
* Copyright (c) 1986, 1987 Dave Taylor
* Copyright (c) 1988, 1989, 1990 USENET Community Trust
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* Syd Weinstein, Elm Coordinator
* [email protected] dsinc!elm
*
*******************************************************************************
* $Log: limit.c,v $
* Revision 4.1 90/04/28 22:43:21 syd
* checkin of Elm 2.3 as of Release PL0
*
*
******************************************************************************/

/** This stuff is inspired by MH and dmail and is used to 'select'
a subset of the existing mail in the folder based on one of a
number of criteria. The basic tricks are pretty easy - we have
as status of VISIBLE associated with each header stored in the
(er) mind of the computer (!) and simply modify the commands to
check that flag...the global variable `selected' is set to the
number of messages currently selected, or ZERO if no select.
**/

#include "headers.h"

#define TO 1
#define FROM 2

char *shift_lower();

int
limit()
{
/** returns non-zero if we changed selection criteria = need redraw **/

char criteria[STRING], first[STRING], rest[STRING], msg[STRING];
static char prompt[] = "Enter criteria or '?' for help: ";
int last_selected, all;

last_selected = selected;
all = 0;

if (selected) {
PutLine1(LINES-2, 0,
"Already have selection criteria - add more? (y/n) n%c",
BACKSPACE);
criteria[0] = ReadCh();
if (tolower(criteria[0]) == 'y') {
Write_to_screen("Yes.", 0);
PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
} else {
Write_to_screen("No.", 0);
selected = 0;
PutLine0(LINES-3, COLUMNS-30, "Change criteria...");
}
}

while(1) {
PutLine1(LINES-2, 0, prompt);
CleartoEOLN();

criteria[0] = '\0';
optionally_enter(criteria, LINES-2, strlen(prompt), FALSE, FALSE);
error("");

if (strlen(criteria) == 0) {
/* no change */
selected = last_selected;
return(FALSE);
}

split_word(criteria, first, rest);

if (equal(first, "?")) {
if(last_selected)
error(
"Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"all\"");
else
error("Enter: {\"subject\",\"to\",\"from\"} [pattern]");
continue;
} else if (equal(first, "all")) {
all++;
selected = 0;
}
else if (equal(first, "subj") || equal(first, "subject"))
selected = limit_selection(SUBJECT, rest, selected);
else if (equal(first, "to"))
selected = limit_selection(TO, rest, selected);
else if (equal(first, "from"))
selected = limit_selection(FROM, rest, selected);
else {
error1("\"%s\" not a valid criterion.", first);
continue;
}
break;
}

if(all && last_selected)
strcpy(msg, "Returned to unlimited display.");
else if(selected)
sprintf(msg, "%d message%s selected.", selected, plural(selected));
else
strcpy(msg, "No messages selected.");
set_error(msg);

/* we need a redraw if there had been a selection or there is now. */
if(last_selected || selected) {
/* if current message won't be on new display, go to first message */
if(selected && !(headers[current-1]->status & VISIBLE))
current = visible_to_index(1)+1;
return(TRUE);
} else {
return(FALSE);
}
}

int
limit_selection(based_on, pattern, additional_criteria)
int based_on, additional_criteria;
char *pattern;
{
/** Given the type of criteria, and the pattern, mark all
non-matching headers as ! VISIBLE. If additional_criteria,
don't mark as visible something that isn't currently!
**/

register int iindex, count = 0;

dprint(2, (debugfile, "\n\n\n**limit on %d - '%s' - (%s) **\n\n",
based_on, pattern, additional_criteria?"add'tl":"base"));

if (based_on == SUBJECT) {
for (iindex = 0; iindex < message_count; iindex++)
if (! in_string(shift_lower(headers[iindex]->subject), pattern))
headers[iindex]->status &= ~VISIBLE;
else if (additional_criteria &&
!(headers[iindex]->status & VISIBLE))
headers[iindex]->status &= ~VISIBLE; /* shut down! */
else { /* mark it as readable */
headers[iindex]->status |= VISIBLE;
count++;
dprint(5, (debugfile,
" Message %d (%s from %s) marked as visible\n",
iindex, headers[iindex]->subject,
headers[iindex]->from));
}
}
else if (based_on == FROM) {
for (iindex = 0; iindex < message_count; iindex++)
if (! in_string(shift_lower(headers[iindex]->from), pattern))
headers[iindex]->status &= ~VISIBLE;
else if (additional_criteria &&
!(headers[iindex]->status & VISIBLE))
headers[iindex]->status &= ~VISIBLE; /* shut down! */
else { /* mark it as readable */
headers[iindex]->status |= VISIBLE;
count++;
dprint(5, (debugfile,
" Message %d (%s from %s) marked as visible\n",
iindex, headers[iindex]->subject,
headers[iindex]->from));
}
}
else if (based_on == TO) {
for (iindex = 0; iindex < message_count; iindex++)
if (! in_string(shift_lower(headers[iindex]->to), pattern))
headers[iindex]->status &= ~VISIBLE;
else if (additional_criteria &&
!(headers[iindex]->status & VISIBLE))
headers[iindex]->status &= ~VISIBLE; /* shut down! */
else { /* mark it as readable */
headers[iindex]->status |= VISIBLE;
count++;
dprint(5, (debugfile,
" Message %d (%s from %s) marked as visible\n",
iindex, headers[iindex]->subject,
headers[iindex]->from));
}
}

dprint(4, (debugfile, "\n** returning %d selected **\n\n\n", count));

return(count);
}

int
next_message(iindex, skipdel)
register int iindex, skipdel;
{
/** Given 'iindex', this routine will return the actual iindex into the
array of the NEXT message, or '-1' iindex is the last.
If skipdel, return the iindex for the NEXT undeleted message.
If selected, return the iindex for the NEXT message marked VISIBLE.
**/

register int remember_for_debug;

if(iindex < 0) return(-1); /* invalid argument value! */

remember_for_debug = iindex;

for(iindex++;iindex < message_count; iindex++)
if (((headers[iindex]->status & VISIBLE) || (!selected))
&& (!(headers[iindex]->status & DELETED) || (!skipdel))) {
dprint(9, (debugfile, "[Next%s%s: given %d returning %d]\n",
(skipdel ? " undeleted" : ""),
(selected ? " visible" : ""),
remember_for_debug+1, iindex+1));
return(iindex);
}
return(-1);
}

int
prev_message(iindex, skipdel)
register int iindex, skipdel;
{
/** Like next_message, but the PREVIOUS message. **/

register int remember_for_debug;

if(iindex >= message_count) return(-1); /* invalid argument value! */

remember_for_debug = iindex;
for(iindex--; iindex >= 0; iindex--)
if (((headers[iindex]->status & VISIBLE) || (!selected))
&& (!(headers[iindex]->status & DELETED) || (!skipdel))) {
dprint(9, (debugfile, "[Previous%s%s: given %d returning %d]\n",
(skipdel ? " undeleted" : ""),
(selected ? " visible" : ""),
remember_for_debug+1, iindex+1));
return(iindex);
}
return(-1);
}


int
compute_visible(message)
int message;
{
/** return the 'virtual' iindex of the specified message in the
set of messages - that is, if we have the 25th message as
the current one, but it's #2 based on our limit criteria,
this routine, given 25, will return 2.
**/

register int iindex, count = 0;

if (! selected) return(message);

if (message < 1) message = 1; /* normalize */

for (iindex = 0; iindex < message; iindex++)
if (headers[iindex]->status & VISIBLE)
count++;

dprint(4, (debugfile,
"[compute-visible: displayed message %d is actually %d]\n",
count, message));

return(count);
}

int
visible_to_index(message)
int message;
{
/** Given a 'virtual' iindex, return a real one. This is the
flip-side of the routine above, and returns (message_count+1)
if it cannot map the virtual iindex requested (too big)
**/

register int iindex = 0, count = 0;

for (iindex = 0; iindex < message_count; iindex++) {
if (headers[iindex]->status & VISIBLE)
count++;
if (count == message) {
dprint(4, (debugfile,
"visible-to-index: (up) index %d is displayed as %d\n",
message, iindex));
return(iindex);
}
}

dprint(4, (debugfile, "index %d is NOT displayed!\n", message));

return(message_count+1);
}


  3 Responses to “Category : C Source Code
Archive   : ELM23SRC.ZIP
Filename : LIMIT.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/