DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T l

⟦ae2d603d2⟧ TextFile

    Length: 6658 (0x1a02)
    Types: TextFile
    Names: »limit.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/limit.c« 

TextFile

/**			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);
}