/*
** seq_msgstats -- message and sequence manipulation and folder attributes
**
** (These functions had once been macros in h/mh.h)
*/

#include <sysexits.h>
#include <h/mh.h>

static void
assert_msg_range(struct msgs *mp, int msgnum)
{
	if (msgnum < mp->lowoff || msgnum > mp->hghoff) {
		adios(EX_SOFTWARE, NULL, "Bug: message out of bounds");
	}
}


void
add_sequence(struct msgs *mp, int seqnum, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] |= (1 << (FFATTRSLOT + seqnum));
}

void
clear_msg_flags(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] = 0;
}

void
clear_sequence(struct msgs *mp, int seqnum, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] &= ~(1 << (FFATTRSLOT + seqnum));
}

void
copy_msg_flags(struct msgs *mp, int dstmsg, int srcmsg)
{
	assert_msg_range(mp, srcmsg);
	assert_msg_range(mp, dstmsg);
	mp->msgstats[dstmsg - mp->lowoff] = mp->msgstats[srcmsg - mp->lowoff];
}

seqset_t
does_exist(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	return mp->msgstats[msgnum - mp->lowoff] & EXISTS;
}

void
get_msg_flags(struct msgs *mp, seqset_t *dst, int msgnum)
{
	assert_msg_range(mp, msgnum);
	*dst = mp->msgstats[msgnum - mp->lowoff];
}

seqset_t
in_sequence(struct msgs *mp, int seqnum, int msgnum)
{
	assert_msg_range(mp, msgnum);
	return mp->msgstats[msgnum - mp->lowoff] & (1 << (FFATTRSLOT + seqnum));
}

seqset_t
is_selected(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	return mp->msgstats[msgnum - mp->lowoff] & SELECTED;
}

seqset_t
is_unseen(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	return mp->msgstats[msgnum - mp->lowoff] & SELECT_UNSEEN;
}

void
set_exists(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] |= EXISTS;
}

void
set_msg_flags(struct msgs *mp, seqset_t *src, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] = *src;
}

void
set_selected(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);

	if (is_selected(mp, msgnum)) {
		return;
	}

	mp->msgstats[msgnum - mp->lowoff] |= SELECTED;
	if (mp->lowsel == 0 || msgnum < mp->lowsel) {
		mp->lowsel = msgnum;
	}
	if (msgnum > mp->hghsel) {
		mp->hghsel = msgnum;
	}
	mp->numsel++;
}

void
set_unseen(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] |= SELECT_UNSEEN;
}

void
unset_exists(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);
	mp->msgstats[msgnum - mp->lowoff] &= ~EXISTS;
}

void
unset_selected(struct msgs *mp, int msgnum)
{
	assert_msg_range(mp, msgnum);

	if (!is_selected(mp, msgnum)) {
		return;
	}

	mp->msgstats[msgnum - mp->lowoff] &= ~SELECTED;
	if (mp->numsel > 0) {
		mp->numsel--;
	}
}


/*
**  private/public sequences
*/

int
is_seq_private(struct msgs *mp, int seqnum)
{
	return mp->attrstats & (1 << (FFATTRSLOT + seqnum));
}

void
make_seq_public(struct msgs *mp, int seqnum)
{
	mp->attrstats &= ~(1 << (FFATTRSLOT + seqnum));
}
void
make_seq_private(struct msgs *mp, int seqnum)
{
	mp->attrstats |= (1 << (FFATTRSLOT + seqnum));
}
void
make_all_public(struct msgs *mp)
{
	mp->attrstats = 0;
}


/*
** folder attributes
*/

void
clear_folder_flags(struct msgs *mp)
{
	mp->msgflags = 0;
}

int
is_readonly(struct msgs *mp)
{
	return mp->msgflags & READONLY;
}
void
set_readonly(struct msgs *mp)
{
	mp->msgflags |= READONLY;
}

int
other_files(struct msgs *mp)
{
	return mp->msgflags & OTHERS;
}
void
set_other_files(struct msgs *mp)
{
	mp->msgflags |= OTHERS;
}
