|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T l
Length: 6658 (0x1a02)
Types: TextFile
Names: »limit.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/limit.c«
/** limit.c **/
/** 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.
(C) Copyright 1986, Dave Taylor
**/
#include "headers.h"
#define TO 1
#define FROM 2
char *shift_lower();
int
limit()
{
/** returns non-zero if we did enough to redraw the screen **/
char criteria[STRING], first[STRING], rest[STRING];
int last_current;
if (selected) {
PutLine1(LINES-2, 0,
"Already have selection criteria - add more? (y/n) n%c",
BACKSPACE);
ReadCh(criteria[0]);
if (tolower(criteria[0]) == 'y')
PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
else {
selected = 0;
PutLine0(LINES-3, COLUMNS-30, "Use '?' for help");
}
}
PutLine1(LINES-2, 0, "Enter criteria: ");
CleartoEOLN();
criteria[0] = '\0';
optionally_enter(criteria, LINES-2, 16, FALSE);
if (strlen(criteria) == 0) return(0);
split_word(criteria, first, rest);
if (equal(first, "all")) {
selected = 0;
return(TRUE);
}
last_current = current;
current = -1;
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 {
selected = 0;
error1("Don't understand \"%s\" as a selection criteria!", first);
sleep(2);
}
if (! selected)
current = last_current;
else
current = visible_to_index(1)+1; /* map it and shift up 1 */
if (! selected)
set_error("no items selected");
else {
sprintf(first, "%d items selected", selected);
set_error(first);
}
return(selected);
}
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 index, count = 0;
dprint3(2,"\n\n\n**limit on %d - '%s' - (%s) **\n\n",
based_on, pattern, additional_criteria?"add'tl":"base");
if (based_on == SUBJECT) {
for (index = 0; index < message_count; index++)
if (! in_string(shift_lower(header_table[index].subject), pattern))
header_table[index].status &= ~VISIBLE;
else if (additional_criteria &&
header_table[index].status | VISIBLE)
header_table[index].status &= ~VISIBLE; /* shut down! */
else { /* mark it as readable */
header_table[index].status |= VISIBLE;
count++;
dprint3(5," Message %d (%s from %s) marked as visible\n",
index, header_table[index].subject,
header_table[index].from);
}
}
else if (based_on == FROM) {
for (index = 0; index < message_count; index++)
if (! in_string(shift_lower(header_table[index].from), pattern))
header_table[index].status &= ~VISIBLE;
else if (additional_criteria &&
header_table[index].status | VISIBLE)
header_table[index].status &= ~VISIBLE; /* shut down! */
else { /* mark it as readable */
header_table[index].status |= VISIBLE;
count++;
dprint3(5," Message %d (%s from %s) marked as visible\n",
index, header_table[index].subject,
header_table[index].from);
}
}
else if (based_on == TO) {
for (index = 0; index < message_count; index++)
if (! in_string(shift_lower(header_table[index].to), pattern))
header_table[index].status &= ~VISIBLE;
else if (additional_criteria &&
header_table[index].status | VISIBLE)
header_table[index].status &= ~VISIBLE; /* shut down! */
else { /* mark it as readable */
header_table[index].status |= VISIBLE;
count++;
dprint3(5," Message %d (%s from %s) marked as visible\n",
index, header_table[index].subject,
header_table[index].from);
}
}
dprint1(4,"\n** returning %d selected **\n\n\n", count);
return(count);
}
int
next_visible(index)
int index;
{
/** Given 'index', this routine will return the actual index into the
array of the NEXT visible message, or '-1' if none are visible
**/
int remember_for_debug;
remember_for_debug = index;
index--; /* shift from 'current' to actual index */
index++; /* make sure we don't bump into ourself! */
while (index < message_count) {
if (header_table[index].status & VISIBLE) {
dprint2(9,"[Next visible: given %d returning %d]\n",
remember_for_debug, index+1);
return(index+1);
}
index++;
}
return(-1);
}
int
previous_visible(index)
int index;
{
/** Just like 'next-visible', but backwards FIRST... */
int remember_for_debug;
remember_for_debug = index;
index -= 2; /* shift from 'current' to actual index, and skip us! */
while (index > -1) {
if (header_table[index].status & VISIBLE) {
dprint2(9,"[previous visible: given %d returning %d]",
remember_for_debug, index+1);
return(index+1);
}
index--;
}
return(-1);
}
int
compute_visible(message)
int message;
{
/** return the 'virtual' index 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 index, count = 0;
if (! selected) return(message);
if (message < 0) message = 0; /* normalize */
for (index = 0; index <= message; index++)
if (header_table[index].status & VISIBLE)
count++;
dprint2(4, "[compute-visible: displayed message %d is actually %d]\n",
count, message);
return(count);
}
int
visible_to_index(message)
int message;
{
/** Given a 'virtual' index, return a real one. This is the
flip-side of the routine above, and returns (message_count+1)
if it cannot map the virtual index requested (too big)
**/
register int index = 0, count = 0;
for (index = 0; index < message_count; index++) {
if (header_table[index].status & VISIBLE)
count++;
if (count == message) {
dprint2(4,"visible-to-index: (up) index %d is displayed as %d\n",
message, index);
return(index);
}
}
dprint1(4, "index %d is NOT displayed!\n", message);
return(message_count+1);
}