This is limit.c in view mode; [Download] [Up]
static char rcsid[] = "@(#)$Id: limit.c,v 5.1 1992/10/03 22:58:40 syd Exp $";
/*******************************************************************************
* The Elm Mail System - $Revision: 5.1 $ $State: Exp $
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* Syd Weinstein, Elm Coordinator
* elm@DSI.COM dsinc!elm
*
*******************************************************************************
* $Log: limit.c,v $
* Revision 5.1 1992/10/03 22:58:40 syd
* Initial checkin as of 2.4 Release at 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"
#include "s_elm.h"
#include "s_aliases.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 = NULL;
int last_selected, all;
last_selected = selected;
all = 0;
if (prompt == NULL) {
prompt = catgets(elm_msg_cat, ElmSet, ElmLimitEnterCriteria,
"Enter criteria or '?' for help: ");
}
if (selected) {
MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmLimitAlreadyHave,
"Already have selection criteria - add more? (%c/%c) %c%c"),
*def_ans_yes, *def_ans_no, *def_ans_no, BACKSPACE);
PutLine0(LINES-2, 0, msg);
criteria[0] = ReadCh();
if (tolower(criteria[0]) == *def_ans_yes) {
Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmLimitYes, "Yes."), 0);
PutLine0(LINES-3, COLUMNS-30, catgets(elm_msg_cat, ElmSet, ElmLimitAdding,
"Adding criteria..."));
} else {
Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmLimitNo, "No."), 0);
selected = 0;
PutLine0(LINES-3, COLUMNS-30, catgets(elm_msg_cat, ElmSet, ElmLimitChanging,
"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 (inalias) {
if (equal(first, "?")) {
if (last_selected)
error(catgets(elm_msg_cat, AliasesSet, AliasesEnterLastSelected,
"Enter:{\"name\",\"alias\"} [pattern] OR {\"person\",\"group\",\"user\",\"system\"} OR \"all\""));
else
error(catgets(elm_msg_cat, AliasesSet, AliasesEnterSelected,
"Enter: {\"name\",\"alias\"} [pattern] OR {\"person\",\"group\",\"user\",\"system\"}"));
continue;
}
else if (equal(first, "all")) {
all++;
selected = 0;
}
else if (equal(first, "name"))
selected = limit_alias_selection(BY_NAME, rest, selected);
else if (equal(first, "alias"))
selected = limit_alias_selection(BY_ALIAS, rest, selected);
else if (equal(first, "person"))
selected = limit_alias_selection(PERSON, rest, selected);
else if (equal(first, "group"))
selected = limit_alias_selection(GROUP, rest, selected);
else if (equal(first, "user"))
selected = limit_alias_selection(USER, rest, selected);
else if (equal(first, "system"))
selected = limit_alias_selection(SYSTEM, rest, selected);
else {
error1(catgets(elm_msg_cat, ElmSet, ElmLimitNotValidCriterion,
"\"%s\" not a valid criterion."), first);
continue;
}
break;
}
else {
if (equal(first, "?")) {
if (last_selected)
error(catgets(elm_msg_cat, ElmSet, ElmEnterLastSelected,
"Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"all\""));
else
error(catgets(elm_msg_cat, ElmSet, ElmEnterSelected,
"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(catgets(elm_msg_cat, ElmSet, ElmLimitNotValidCriterion,
"\"%s\" not a valid criterion."), first);
continue;
}
break;
}
}
if (all && last_selected)
strcpy(msg, catgets(elm_msg_cat, ElmSet, ElmLimitReturnToUnlimited,
"Returned to unlimited display."));
else {
if (inalias) {
if (selected > 1)
sprintf(msg, catgets(elm_msg_cat, AliasesSet,
AliasesLimitMessagesSelected, "%d aliases selected."),
selected);
else if (selected == 1)
strcpy(msg, catgets(elm_msg_cat, AliasesSet,
AliasesLimitMessageSelected, "1 alias selected."));
else
strcpy(msg, catgets(elm_msg_cat, AliasesSet,
AliasesLimitNoMessagesSelected, "No aliases selected."));
}
else {
if (selected > 1)
sprintf(msg, catgets(elm_msg_cat, ElmSet,
ElmLimitMessagesSelected, "%d messages selected."), selected);
else if (selected == 1)
strcpy(msg, catgets(elm_msg_cat, ElmSet, ElmLimitMessageSelected,
"1 message selected."));
else
strcpy(msg, catgets(elm_msg_cat, ElmSet,
ElmLimitNoMessagesSelected, "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 && !(ifmain(headers[current-1]->status,
aliases[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
limit_alias_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 aliases 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 == BY_NAME) {
for (iindex = 0; iindex < message_count; iindex++)
if (! in_string(shift_lower(aliases[iindex]->name), pattern))
clearit(aliases[iindex]->status, VISIBLE);
else if (additional_criteria &&
!(aliases[iindex]->status & VISIBLE))
clearit(aliases[iindex]->status, VISIBLE); /* shut down! */
else { /* mark it as readable */
setit(aliases[iindex]->status, VISIBLE);
count++;
dprint(5, (debugfile,
" Alias %d (%s, %s) marked as visible\n",
iindex, aliases[iindex]->alias,
aliases[iindex]->name));
}
}
else if (based_on == BY_ALIAS) {
for (iindex = 0; iindex < message_count; iindex++)
if (! in_string(shift_lower(aliases[iindex]->alias), pattern))
clearit(aliases[iindex]->status, VISIBLE);
else if (additional_criteria &&
!(aliases[iindex]->status & VISIBLE))
clearit(aliases[iindex]->status, VISIBLE); /* shut down! */
else { /* mark it as readable */
setit(aliases[iindex]->status, VISIBLE);
count++;
dprint(5, (debugfile,
" Alias %d (%s, %s) marked as visible\n",
iindex, aliases[iindex]->alias,
aliases[iindex]->name));
}
}
else {
for (iindex = 0; iindex < message_count; iindex++)
if (! (based_on & aliases[iindex]->type))
clearit(aliases[iindex]->status, VISIBLE);
else if (additional_criteria &&
!(aliases[iindex]->status & VISIBLE))
clearit(aliases[iindex]->status, VISIBLE); /* shut down! */
else { /* mark it as readable */
setit(aliases[iindex]->status, VISIBLE);
count++;
dprint(5, (debugfile,
" Alias %d (%s, %s) marked as visible\n",
iindex, aliases[iindex]->alias,
aliases[iindex]->name));
}
}
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, stat;
if (iindex < 0) return(-1); /* invalid argument value! */
remember_for_debug = iindex;
for(iindex++;iindex < message_count; iindex++) {
stat = ifmain(headers[iindex]->status, aliases[iindex]->status);
if (((stat & VISIBLE) || (!selected))
&& (!(stat & 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, stat;
if (iindex >= message_count) return(-1); /* invalid argument value! */
remember_for_debug = iindex;
for(iindex--; iindex >= 0; iindex--) {
stat = ifmain(headers[iindex]->status, aliases[iindex]->status);
if (((stat & VISIBLE) || (!selected))
&& (!(stat & 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 (ifmain(headers[iindex]->status,
aliases[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 (ifmain(headers[iindex]->status,
aliases[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);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.