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 - metrics - download
Index: T s

⟦6decd3e40⟧ TextFile

    Length: 19808 (0x4d60)
    Types: TextFile
    Names: »sequence.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« 
        └─⟦dcb95597f⟧ 
            └─⟦this⟧ »sequence.c« 

TextFile

#ifndef lint
static char rcsid[] =
	"$Header: sequence.c,v 2.10 88/01/13 19:17:03 deboor Exp $";

static char notice[] =
	"This program is in the public domain and is available for unlimited \
distribution as long as this notice is enclosed.";
#endif

/*
 * routines for handling sequences.
 *
 * $Source: /c/support/deboor/usr/src/old/vmh/RCS/sequence.c,v $
 * $Revision: 2.10 $
 * $Author: deboor $
 *
 * FUNCTIONS:
 *	add_to_sequence		add array of messages to a given sequence in
 *				a given folder.
 *	cmdMark			primitive 'mark' command: just prints out a
 *				sequence (DEBUG)
 *	del_from_sequence	remove array of messages from a given sequence
 *				in a given folder
 *	delete_sequence		delete an entire sequence from a folder
 *	dump_sequences		refresh sequences file of a folder
 *	free_sequences		free all the sequences of a folder (w/o refresh)
 *	init_sequences		read sequences file to create in-core list
 *				of sequences for a folder
 *	is_pre_def		returns one of the PD_ constants or 0 based on
 *				whether the passed sequence is a pre-defined one
 *	readsequence		"read" a sequence from a folder
 *	set_sequence		set the value of a sequence for a folder
 */

# include "vmh.h"

/* the structure for the sequences list. one structure kept per sequence */
struct seq {
	char		*se_name;	/* name of sequence */
	int		se_length;	/* length of " */
	int		*se_msgs;	/* the messages in " */
	struct seq	*se_next;	/* the next " */
};

/* number of bits in an int */
# define nbits		(sizeof(int)*8)

/* Functions for manipulating bit arrays for messages */
# define mark(num)	letters[num/nbits]|=(1<<(num%nbits))
# define unmark(num)	letters[num/nbits]&=~(1<<(num%nbits))
# define marked(num)	letters[num/nbits]&(1<<(num%nbits))

static	int	seq_length;	/* the length of the current sequence */

/*
** static
** sequence_ok (seq_name) register char *seq_name;
**	returns true if the passed name is a valid MH sequence name
**	(all alphanumeric characters), false otherwise.
*/
static
sequence_ok (seq_name)
	register char *seq_name;
{
	if (! isalpha (*seq_name++))
		return (0);
	while (*seq_name && isalnum (*seq_name++))
		;
	return ( ! *seq_name );
}

/*
** static int *
** form_sequence (seq, negate, m) int *seq, negate; struct msgs *m;
**	takes a sequence (seq) in the folder with the msgs struct m
**	and compacts it (removes duplicated message numbers) and copies
**	the sequence to a new location. If  negate  is true, it copies
**	the complement of the sequence (that's what 'm' is used for).
**	It is used for two things: to negate a sequence and to compact/copy
**	it, for obvious reasons.
*/
static int *
form_sequence (seq, negate, m)
	int	*seq,
		negate;
	struct msgs *m;
{
	u_char		letters[MAXFOLDER];
	Reg1	int	i;
	Reg2	int	j;	/* a counter for counting */
	Reg4	int	*cq;	/* the new sequence location */
	Reg3	int	nseq;	/* the number of messages in the sequence */
	


	/* initialize the array */
	Bzero ((char *)letters, sizeof(letters));

	/* mark the messages in the sequence in the letters[] */
	for (i = 0, nseq = 0; seq[i]; i++)
		if (letters[seq[i]-1] == 0) {
			letters[seq[i]-1] = 1;
			nseq++;
		}
		
	seq_length = nseq + 1;
	if ( ! negate) {
		/* no negation necessary, so make room for the sequence */
		cq = (int *) Calloc (seq_length + 1, sizeof (int));

		/* now go through letters[] looking for marked msgs */
		for (j = 0, i = m->m_lowmsg; i <= m->m_hghmsg; i++) {

			/* go until we have one which exists */
			while ( i <= m->m_hghmsg && ! Exists(i,m))
				i++;

			/* if it's marked, put it in the new sequence */
			if (letters [i-1])
				cq[j++] = i;
		}
		cq[j] = 0;
	} else {
		/*
		 * need negation. get space for all but the messages in
		 * the sequence. (plus the null word)
		 * seq_length is the number of words.
		 */

		cq = (int *) Calloc((m->m_nummsg - (seq_length-1)) + 1,sizeof(int));

		/* go through the array looking for unmarked messages */
		for (j = 0, i = m->m_lowmsg; i <= m->m_hghmsg; i++) {

			/* get to an existing message */
			while ( ! Exists(i,m) && i <= m->m_hghmsg)
				i++;

			/* if it's unmarked, put it in the sequence */
			if (! letters[i-1])
				cq[j++] = i;
		}
		cq[j] = 0;
		seq_length = j;
	}
	return (cq);
}

static char *pre_defs[] = {
	"all", "first", "last", "prev", "next", "cur", (char *)0
};

/*
** is_pre_def (name) register char *name;
**	checks to see if the given name is one of the standard MH pre-defined
**	sequences. If it is, it returns its number, otherwise it returns 0.
*/
is_pre_def (name)
	register char	*name;
{
	register	pre_def_num;

	for (pre_def_num = 0; pre_defs[pre_def_num]; pre_def_num++)
		if ( ! strcmp (name, pre_defs[pre_def_num]))
			return (pre_def_num + 1);
	return (0);
}

/*
** static int *
** get_pre_def (pre_def_num, negate, f) register pre_def_num; int negate;
**   register struct fldr *f;
**	Checks  name  for being a pre-defined sequence (one of all, first,
**	first, prev, next, or last) and, if it is, returns the appropriate
**	value, after sending it to form_sequence to be negated, if nec'y.
*/
static int *
get_pre_def (pre_def_num, negate, f)
	Reg5	int	pre_def_num;
	int		negate;
	Reg4	FLDR	*f;
{
	Reg3	int	*sequence;		/* the sequence value */
	int		*tsequence;
	Reg1	int	i;
	Reg2	int	msg;

	if (f->f_tail == (INFO *) NULL)
		return ((int *) NULL);
	switch (pre_def_num) {
	case PD_ALL:
		if (negate) {
			/* this is the NULL sequence */
			sequence = (int *) Malloc (sizeof(int));
			*sequence = 0;
			seq_length = 0;
			return (sequence);
		} else {
			if (f->f_msgs.m_lowmsg > f->f_msgs.m_hghmsg) {
				punt ("data space corrupted");
			}
			/* need room for everybody */
			sequence = (int *)Calloc(f->f_msgs.m_nummsg + 1, sizeof(int));

			/* put all the messages which exist into the sequence */
			for (i=0, msg=f->f_msgs.m_lowmsg; msg <= f->f_msgs.m_hghmsg; msg++)
				if (Exists (msg, &f->f_msgs))
					sequence[i++] = msg;
			seq_length = i;
			return (sequence);
		}
	case PD_FIRST:

		sequence = (int *)Calloc (2,sizeof(int));
		*sequence = f->f_msgs.m_lowmsg;
		seq_length = 1;
		if (! negate)
			return (sequence);
		break;
	case PD_LAST:
		sequence = (int *)Calloc(2,sizeof(int));
		*sequence = f->f_msgs.m_hghmsg;
		seq_length = 1;
		if (! negate)
			return (sequence);
		break;
	case PD_PREV:
		sequence = (int *)Calloc(2,sizeof(int));
		if (f->f_cur != f->f_head)
			*sequence = f->f_cur->i_prev->i_mnum;
		else
			return ((int *)NULL);
		seq_length = 1;
		if (! negate)
			return (sequence);
		break;
	case PD_NEXT:
		sequence = (int *)Calloc(2,sizeof(int));
		if (f->f_cur != f->f_tail)
			*sequence = f->f_cur->i_next->i_mnum;
		else
			return ((int *) NULL);
		seq_length = 1;
		if (!negate)
			return (sequence);
		break;
	case PD_CUR:
		sequence = (int *)Calloc(2,sizeof(int));
		*sequence = f->f_cur->i_mnum;
		seq_length = 1;
		if (!negate)
			return (sequence);
		break;
	default:
		prt_action (" pdn = %d. I don't know what's happening! ",
			pre_def_num);
		sleep(2);
		punt ("Dying in a big way");
	}
	/* have gotten a sequence and found it needs negation */
	tsequence = form_sequence (sequence, 1, &f->f_msgs);
	Free ((char *)sequence);
	sequence = tsequence;

	return (sequence);

}



/*
** int *
** readsequence (seq, f) char *seq; struct fldr *f;
**	reads the given sequence  seq  from the folder  f .
*/
int *
readsequence (seq, f)
	char		*seq;
	Reg3	FLDR	*f;
{
	
	int			do_negate = 0;
	Reg2	struct	seq	*s;
	Reg1	int		i;

	if ( ! *seq || f->f_cur == (INFO *) 0)	/* guard against null sequence names */
		return NULL;			/* and empty folders */

	if (strncmp (seq, SeqNegate, strlen(SeqNegate)))
		do_negate = 0;
	else {
		do_negate = 1;
		seq += strlen(SeqNegate);
	}

	/* see if it's pre-defined sequence */
	if (i = is_pre_def (seq))
		/* form the proper negation and return it */
		return (get_pre_def (i, do_negate, f));

	/* see if the sequence is there */
	for (s = f->f_sequences; s ; s = s->se_next)

		/* is this the one? */
		if (! strcmp (s->se_name, seq)) {
			/* yes. set seq_length from here */
			seq_length = s->se_length;

			/* and get the sequence from it, negating as nec'y */
			return (form_sequence(s->se_msgs, do_negate, &f->f_msgs));
		}

	/*
	 * neither existent nor pre-defined. bitch.
	 */

	 /* BITCH BITCH BITCH BITCH that good enough? */
	 return (NULL);

}
/*
** init_sequences (f) FLDR *f;
**	initializes the sequence list for the passed folder from the
**	.mh_sequences file.
*/
init_sequences (f)
	Reg8 FLDR *f;
{
	char		seq_file[PATHLENGTH];
	Reg7	 FILE	*sfile;
	char		line[256];
	char		moremsgs[256];
	int		letters[MAXFOLDER/nbits + 1];
	int		need_more;
	int		nseq = 0;
	Reg4	char	*cp;
	Reg5	char	*c2p;
	Reg1	int	seqStart;
	Reg2	int	seqEnd;
	Reg3	int	i;
	Reg6	int	*sequence;

	f->f_cur = (INFO *) 0;	/* so we know if we've done "cur" */
	/* get the file name */
	(void) sprintf (seq_file, "%s/%s", f->f_name, mh_seq);

	if ((sfile = fopen (seq_file, "r")) == NULL) {
#ifdef DEBUG
		DeBuG("Couldn't open sequences file %s\n", seq_file);
#endif
		f->f_cur = f->f_tail;
		return;
	}
	
	
	while (cp = fgets (line, sizeof (line), sfile)) {
		/* initialize the marked messages array */
		Bzero ((char *)letters, sizeof (letters));

		/* get the offset to the start of the sequence */
		if ((cp = index (line, ':')) == (char *) 0) {
			punt ("Badly formatted sequences file");
		}
		*cp++ = '\0';

		/*
		 * keep reading in lines and processing the message numbers
		 * until we get a line ending in '\n' or we hit EOF
		 */
		for (need_more = 1;cp && need_more;) {
			if (c2p = index (cp, '\n')) {
				*c2p = '\0';
				need_more = 0;
			} else
				need_more = 1;
			while (*cp) {
				/* skip leading spaces */
				while (isspace (*cp))
					cp++;
				/* get start of sequence */
				for (seqStart = 0; isdigit (*cp); cp++)
					seqStart = 10*seqStart + *cp - '0';

				if (seqStart > MAXFOLDER)
					punt ("Badly formatted sequences file");
				/* if the next char is a '-' => it's a range */
				if (*cp == '-') {

					/* get end of sequence */
					for (seqEnd =0, cp++; isdigit (*cp); cp++)
						seqEnd = 10*seqEnd + *cp - '0';

					if (seqEnd > MAXFOLDER)
						punt ("Badly formatted sequences file");
					/* now mark all the messages which exist */
					for (i = seqStart; i <= seqEnd; i++, nseq++)
						if (Exists (i, &f->f_msgs))
							mark(i);
					
				} else {
					/* it's a single message, so mark it */
					if (Exists (seqStart, &f->f_msgs)) {
						nseq++;
						mark(seqStart);
					}
				}
			}
			if(need_more)
				cp=fgets(moremsgs, sizeof(moremsgs), sfile);
		}
		/* if it's not "cur", form structure and set it in the list */
		if (strcmp (line, current)) {
			/* get room for the sequence numbers */
			sequence = (int *) Calloc (nseq + 1, sizeof (int));

			/* set in the actual numbers */
			for (i=0, seqStart=f->f_msgs.m_lowmsg;seqStart<= f->f_msgs.m_hghmsg; seqStart++)
				if (marked(seqStart))
					sequence[i++] = seqStart;
			sequence[i] = 0;
			seq_length = i;

			set_sequence (line, sequence, f);	/* install the value */
			Free ((char *) sequence);		/* free that memory */
		} else {
			/*
			 * if the sequence *is* "cur", we must treat it
			 * specially. go through the letters[] looking for the first
			 * marked letter. while doing this, keep track of the number
			 * of existent messages. this is the line number.
			 * once the first marked message is found, j will be the
			 * line number of that message.
			 * if no marked letter, default cur to m_hghmsg.
			 */

			for (i = f->f_msgs.m_lowmsg; i < f->f_msgs.m_hghmsg; i++) {
				if (marked(i)) 
					break;
			}
			f->f_cur = findinfo(i, f);
		}
	}
	if (! f->f_cur)			/* set it to eof */
		f->f_cur = f->f_tail;	/* if not set already */

	(void) fclose (sfile);
}

/*
** dump_sequences (fold) register FLDR *fold;
**	dumps all the sequences in structure fold into the .mh_sequences
**	file for that folder. Including 'cur'.
*/
dump_sequences (fold)
	Reg4	FLDR *fold;
{
	char			seq_file[PATHLENGTH];
	Reg3	FILE		*sfile;
	Reg1	int		i;
	Reg2	SEQ		*s;

	(void) sprintf (seq_file, "%s/%s", fold->f_name, mh_seq);

	/***** (void) (void) unlink (seq_file); just zero this thing with fopen *****/

	if ((sfile = fopen (seq_file, "w")) == NULL) {
		errormsg ("Cannot open sequence file?!", 1);
		return;
	}

	for (s = fold->f_sequences; s; s = s->se_next) {
		if (! sequence_ok (s->se_name))
			continue;
		fprintf (sfile, "%s: ", s->se_name);
		for (i = 0; s->se_msgs[i];) {
			if (s->se_msgs[i+1] - s->se_msgs[i] == 1) {
				fprintf (sfile, "%d-", s->se_msgs[i++]);
				while (s->se_msgs[i+1] - s->se_msgs[i] == 1)
					i++;
				fprintf (sfile, "%d ", s->se_msgs[i++]);
			} else
				fprintf (sfile, "%d ", s->se_msgs[i++]);
		}
		fprintf (sfile, "\n");
	}
	if (! FEmpty(fold))	/* if non-empty */
		fprintf (sfile, "%s: %d\n", current, fold->f_cur->i_mnum);
				/* output cur finally */

	(void) fclose (sfile);
}

/*
** set_sequence (seq, msgs, f) char *seq; register int *msgs; register FLDR *f;
**	Sets the given  msgs  to be the value of the sequence  seq  in the
**	folder  f .
*/
set_sequence (seq, msgs, f)
	char	*seq;
	Reg4	int *msgs;
	Reg5	FLDR *f;
{
	Reg3	SEQ	*s;
	Reg1	int	i;
	Reg2	int	j;

	for (i=0; msgs[i]; i++)	/* get the number of messages */
		;
	seq_length = i;		/* set it in seq_length */

	if (is_pre_def (seq)) {	/* this is a no-no */
		errormsg ("Cannot set the value of a pre-defined sequence",1);
		return;
	}
	/* look for the sequence in the current list */
	for (s = f->f_sequences; s; s = s->se_next)
		if ( ! strcmp (seq, s->se_name)) {	/* there it is */
			Free ((char *)s->se_msgs);	/* free old sequence */

			/* make room for new one */
			s->se_msgs = (int *) Calloc (i+1, sizeof (int));

			/* copy the new one in */
			for (j = 0; j < seq_length; j++)
				s->se_msgs[j] = msgs[j];
			s->se_msgs[j] = 0;
			s->se_length = seq_length;	/* set the length */
			break;
		}
	if (s == NULL) {	/* not there already */
		/* get room for the structure */
		s = (struct seq *) Malloc (sizeof (struct seq));

		/* install the name */
		s->se_name = (char *) Malloc (strlen (seq) + 1);
		(void) strcpy (s->se_name, seq);

		/* and the length */
		s->se_length = seq_length;

		/* then get room for and install the sequence itself */
		s->se_msgs = (int *) Calloc (seq_length+1, sizeof (int));
		for (j = 0; j < seq_length; j++)
			s->se_msgs[j] = msgs[j];
		s->se_msgs[j] = 0;
		/* link in the new structure */
		s->se_next = f->f_sequences;
		f->f_sequences = s;
	}
}

/*
** delete_sequence (seq, f) register char *seq; register FLDR *f;
**	removes the sequence  seq  from the sequence list of folder  f .
*/
delete_sequence (seq, f)
	Reg4	char *seq;
	Reg3	FLDR *f;
{
	Reg1	SEQ	*sc;	/* the current sequence */
	Reg2	SEQ	*sp;	/* the previous sequence */

	/*
	 * first find the sequence, keeping track of the previous
	 * structure. don't need to worry about pre-defs since they
	 * aren't on the list anyway.
	 */
	for (sc = f->f_sequences, sp = (struct seq *)0;
		sc && strcmp (sc->se_name, seq);
		sc = sc->se_next)
			sp = sc;
	if (sc) {
		/* re-link the sequence list */
		if (sp) {
			sp->se_next = sc->se_next;
		} else {
			f->f_sequences = sc->se_next;
		}
		Free (sc->se_name);		/* free the name */
		Free ((char *) sc->se_msgs);	/* and the sequence */
		Free ((char *) sc);		/* and the Sequence */
	} /* if not there, do nothing */
}

/*
** add_to_sequence (seq, msgs, f) register char *seq; register int *msgs;
**  register FLDR *f;
**	adds the passed  msgs  to the sequence  seq  in the folder  f .
*/
add_to_sequence (seq, msgs, f)
	Reg6	char	*seq;
	Reg4	int	*msgs;
	Reg5	FLDR	*f;
{
	int		*nmsgs;
	int		*tmsgs;
	Reg3	int	i;
	Reg2	int	j;
	Reg1	int	k;

	if (is_pre_def (seq)) {
		errormsg ("can't add to a predefined sequence, bub", 1);
		longjmp (CommandLevel, 1);
	}
	tmsgs = readsequence (seq, f);
	if (tmsgs == (int *) NULL) {
		tmsgs = (int *) Calloc (1, sizeof(int));
	}
	for (j = 0; msgs[j]; j++)
		;
	
#ifdef DEBUG
	if (Dbg) {
	DeBuG ("+2seq: j = %d len = %d\nmsgs: ", j, seq_length);
	for(i=0; i < j; i++)
		DeBuG (" %d", msgs[i]);
	if (msgs[i])
		DeBuG ("\nnon null at end of msgs\ntmsgs: ");
	else
		DeBuG ("\ntmsgs: ");
	for (i=0;i<seq_length;i++)
		DeBuG (" %d",tmsgs[i]);
	if(tmsgs[i])
		DeBuG("\nnonnull at end of tmsgs\n");
	else
		DeBuG("\n");
	}
#endif
	nmsgs = (int *) Calloc (j + seq_length + 1, sizeof (int));
	for (i = 0; tmsgs[i]; i++)
		nmsgs[i] = tmsgs[i];
	for (k = 0; msgs[k]; nmsgs[i++] = msgs[k++])
		;
	seq_length += j;
	tmsgs = form_sequence (nmsgs, 0, &f->f_msgs);
	
	Free ((char *)nmsgs);
	set_sequence (seq, tmsgs, f);
	Free ((char *)tmsgs);
}

#ifdef DEBUG
/*
 * comparison routine for qsort() call in del_from_sequence
 */
static int
icmp (i1, i2) int *i1, *i2;
{
	return (*i2 - *i1);
}
#endif DEBUG

/*
** del_from_sequence (seq, msgs, f) register char *seq;
** register int *msgs; register FLDR *f;
**	removes the messages in  msgs  from the sequence  seq
**	in the folder  f .
*/
del_from_sequence (seq, msgs, f)
	Reg7	char	*seq;
	Reg5	int	*msgs;
	Reg6	FLDR	*f;
{
	Reg4	int	*cseq;
	
	Reg3	int	i;
	Reg2	int	k;
	Reg1	int	j;
	int		icmp();
	
	if ((cseq = readsequence (seq, f)) == (int *) 0) {
		return;
	}
#ifdef DEBUG
	DeBuG ("seq: ");
	for (i = 0; cseq[i]; i++)
		DeBuG ("%d ", cseq[i]);
	DeBuG ("(%d items)\n", i);
#endif
	for (i = 0; msgs[i]; i++)
		;
	/*
	 * sort incoming messages. do 'i' rather than 'i+1' 'cause we
	 * don't want the thing to move the ending 0 word.
	 */
	
#ifdef DEBUG
	DeBuG ("bs: ");
	for (j = 0; j < i; j++)
		DeBuG ("%d ", msgs[j]);
	qsort ((char *) msgs, i, sizeof(int), icmp);
	DeBuG ("as: ");
	for (j = 0; j < i; j++)
		DeBuG ("%d ", msgs[j]);
#endif
	/*
	 * i travels through the list of messages to delete, j travels
	 * through the current sequence and always advances, k travels
	 * through the new version of the sequence and advances only
	 * when a message # is copied.
	 */
	for (i = k = j = 0; msgs[i] && cseq[j]; j++) {
		if (cseq[j] == msgs[i]) {	/* if this is to be nuked, advance i */
			i++;
			continue;
		} else if (msgs[i] < cseq[j]) {	/* if past current msg-to-delete, advance to next possible one */
			while (msgs[++i] && msgs[i] < cseq[j])	/* i.e. next which is greater than current message number */
				;
			if (msgs[i] == cseq[j]) {	/* hit one to delete */
				i++;			/* so advance to next and don't copy */
				continue;
			}
		}
		cseq[k++] = cseq[j];			/* copy to new position */
	}
	while (cseq[j])			/* copy the rest */
		cseq[k++] = cseq[j++];
	cseq[k] = 0;					/* null-terminate it */
	set_sequence (seq, cseq, f);			/* put in new value */
}

/*
** static
** print_sequence (seq, f, win) char *seq; FLDR *f; WINDOW *win;
**	prints the members of the specified sequence, seq, of the
**	given folder, f, to the passed window, win.
*/
static
print_sequence (seq, f, win)
	Reg4	char *seq;
	Reg3	FLDR *f;
	WINDOW		*win;
{
	Reg2	int	*q;
	Reg1	int	i;

	wprintw (win, "Sequence |%s|: ", seq);
	q = readsequence (seq, f);

	if (q) {
		for (i = 0; q[i]; i++)
			wprintw (win, "%d ", q[i]);
	} else {
		waddstr (win, "<<No such sequence>>");
	}
	waddch (win, '\n');
}

/*
** cmdMark (count, undo, argc, argv) int count, undo, argc; char **argv;
**	a debugging function for looking at sequence values.
*/
/*ARGSUSED*/
cmdMark(count, undo, argc, argv)
	int	count,
		undo,
		argc;
	char	**argv;
{
	char		seq[50];
	struct seq	*s;
	
	wclear (botWin);
	prt_action (" Enter a sequence name ");
	*seq = '\0';

	wclear (cmdWin);
	if (mywgetstr (cmdWin, seq, 0) == 0)
		return;
	if (strcmp (seq, "All"))
		print_sequence (seq, F, botWin);
	else {
		for (s = F->f_sequences; s; s = s->se_next)
			print_sequence (s->se_name, F, botWin);
	}
	wrefresh (botWin);
}

free_sequences (f)
	Reg3	FLDR	*f;
{
	Reg1	SEQ	*sp;
	Reg2	SEQ	*tsp;

	for (sp = f->f_sequences; sp;) {
		Free ((char *)sp->se_msgs);
		Free ((char *)sp->se_name);
		tsp = sp->se_next;
		Free ((char *)sp);
		sp = tsp;
	}
}