/* --------------------
	vmail -- page.c

	Routines for paging between folders.

	Copyright (C) J. Zobel, University of Melbourne, October 1987.
-------------------- */

#include "defs.h"

/* --------------------
	Clear screen, show current page of mail items.
-------------------- */
void
display_page()
{
	int		i;
	item	mail;
	char	str[LEN];

	clear();
	add_page_header(str);
	for(i=FIRST, mail=curflr->mail ; mail != (item) NULL ; i++, mail=mail->next)
		show_title(str, i, mail);
	move(y, 0);
	refresh();
}


/* --------------------
	Find previous valid page of mail items (times count).
-------------------- */
void
prev_page(count, display)
	int		count;
	bool	display;
{
	bool	show = false;
	folder	f, p = curflr;

	for( ; count > 0 ; count--) {
		f = curflr->prev; PREV_VALID(f);
		if(f == (folder) NULL)
			break;
		else {
			show = true;
			y = FIRST;
			curflr = f;
			curmail = curflr->mail;
		}
	}
	if(p != curflr)
		alternate = p;
	if(display) {
		if(show)
			display_page();
		if(f == (folder) NULL)
			addstatus("first active page", true);
	}
}


/* --------------------
	Find next valid page of mail items (times count).
-------------------- */
void
next_page(count, display)
	int		count;
	bool	display;
{
	bool	show = false;
	folder	f, p = curflr;

	for( ; count > 0 ; count--) {
		f = curflr->next; NEXT_VALID(f);
		if(f == (folder) NULL)
			break;
		else {
			show = true;
			y = FIRST;
			curflr = f;
			curmail = curflr->mail;
		}
	}
	if(p != curflr)
		alternate = p;
	if(display) {
		if(show)
			display_page();
		if(f == (folder) NULL)
			addstatus("last active page", true);
	}
}


/* --------------------
	Move cursor up count lines.
-------------------- */
void
cursor_up(count)
	int count;
{
	bool	redraw = false;

	addstatus("", false);				/* clear status line */
	for( ; count > 0 ; count--)
		if(curmail->prev == (item) NULL) {
			if(curflr->prev == (folder) NULL ||
									curflr->name != curflr->prev->name) {
				addstatus("first page of folder", true);
				break;
			} else {
				redraw = true;
				prev_page(1, false);
					/* find last mail item on page */
				for( ; curmail->next != (item) NULL ; y++)
					curmail=curmail->next;
			}
		} else {
			y--;
			curmail = curmail->prev;
		}
	if(redraw)
		display_page();
	else {
		move(y, 0);
		refresh();
	}
}


/* --------------------
	Move cursor down count lines.
-------------------- */
void
cursor_down(count)
	int		count;
{
	bool	redraw = false;

	addstatus("", false);				/* clear status line */
	for( ; count > 0 ; count--)
		if(curmail->next == (item) NULL) {
			if(curflr->next == (folder) NULL ||
									curflr->name != curflr->next->name) {
				addstatus("last page of folder", true);
				break;
			} else {
				redraw = true;
				next_page(1, false);
			}
		} else {
			y++;
			curmail = curmail->next;
		}
	if(redraw)
		display_page();
	else {
		move(y, 0);
		refresh();
	}
}


/* --------------------
	Go to next folder, make active if not so already.
-------------------- */
void
goto_next_folder(count)
	int		count;
{
	bool	changed = false;
	folder	f, p = curflr;

	for( ; count > 0 ; count--) {
			/* skip other pages of current folder */
		for(f=p ; p->next && p->next->name == f->name ; p=p->next)
			;
		if(p->next == (folder) NULL) {
			addstatus("last folder", true);
			break;
		} else {
			changed = true;
			p = p->next;
		}
	}
	if(changed) {
		do {
			if(!p->valid) {
				p->valid = true;
				addstatus("reading mail headers ...", true);
				find_mail(p, false);
			}
			if(p->valid == EMPTY)
				p = p->next;
		} while(p != (folder) NULL && p->valid != true);
		if(p == (folder) NULL)
			addstatus("can't go forward that many folders", true);
		else {
			alternate = curflr;
			curflr = p;
			curmail = p->mail;
			y = FIRST;
			display_page();
		}
	}
}


/* --------------------
	Goto previous folder, make active if not so already.
-------------------- */
void
goto_prev_folder(count)
	int		count;
{
	bool	changed = false;
	folder	f, p = curflr;

	for( ; count > 0 ; count--) {
			/* skip other pages of current folder */
		for(f=p ; p->prev && p->prev->name == f->name ; p=p->prev)
			;
		if(p->prev == (folder) NULL) {
			addstatus("first folder", true);
			break;
		} else {
			changed = true;
			p = p->prev;
		}
	}
	if(changed) {
		do {
			if(!p->valid) {
				p->valid = true;
				addstatus("reading mail headers ...", true);
				find_mail(p, false);
			}
			if(p->valid == EMPTY)
				p = p->prev;
		} while(p != (folder) NULL && p->valid != true);
		if(p == (folder) NULL)
			addstatus("can't go back that many folders", true);
		else {
				/* skip other pages of current folder */
			for(f=p ; p->prev && p->prev->name == f->name ; p=p->prev)
				;
			alternate = curflr;
			curflr = p;
			curmail = p->mail;
			y = FIRST;
			display_page();
		}
	}
}


/* --------------------
	Make new folder current as specified - read from terminal (get_name =
	true) or use value in alternate (get_name = false).
-------------------- */
void
goto_folder(get_name)
	bool	get_name;
{
	char	buf[LEN], *str = buf;
	folder	f;
	int		i;

	if(get_name || alternate == (folder) NULL) {
			/* no alternate folder */
		get_string("folder? ", str);
		for(i=0 ; *str == ' ' ; i++, str++)
			;
		for(; i < LEN && buf[i] != ' ' && buf[i] != '\0' ; i++)
			;
		if(i < LEN)
			buf[i] = '\0';
		GOTO_NAME(f, str);
		if(f == (folder) NULL) {
			addstatus("no such folder", true);
			return;
		}
		if(!f->valid) {
			f->valid = true;
			addstatus("reading mail headers ...", true);
			find_mail(f, false);
			if(f->valid == EMPTY) {
				sprintf(str, "%s -- folder empty", f->name);
				addstatus(str, true);
				return;
			}
		}
	} else
		f = alternate;
	if(f == curflr)
		addstatus("already in that folder", true);
	else {
		alternate = curflr;
		curflr = f;
		curmail = f->mail;
		y = FIRST;
		display_page();
	}
}


/* --------------------
	Go to first line of page, as offset by count.
-------------------- */
void
cursor_first(count)
	int		count;
{
	item	m = curflr->mail;

	addstatus("", false);				/* clear status line */
	for(y=FIRST ; m != (item) NULL && count > 1 ; count--, y++, m=m->next)
		;
	if(m == (item) NULL)
		beep();
	else {
		curmail = m;
		move(y, 0);
		refresh();
	}
}


/* --------------------
	Go to middle line of page.
-------------------- */
void
cursor_middle()
{
	item	m, p;
	bool	tog = false;

	addstatus("", false);				/* clear status line */
		/* find middle of page - p traverses page at half speed */
	for(y=FIRST, m=p=curflr->mail ; m != (item) NULL ; m=m->next, tog= !tog)
		if(tog) {
			y++;
			p = p->next;
		}
	curmail = p;
	move(y, 0);
	refresh();
}


/* --------------------
	Go to last line of page, as offset by count.
-------------------- */
void
cursor_last(count)
	int		count;
{
	item	m = curflr->mail;

	addstatus("", false);				/* clear status line */
		/* find last item, including y-value */
	for(y=FIRST ; m->next != (item) NULL ; y++, m=m->next)
		;
	for(; m != (item) NULL && count > 1 ; count--, y--, m=m->prev)
		;
	if(m == (item) NULL)
		beep();
	else {
		curmail = m;
		move(y, 0);
		refresh();
	}
}


/* --------------------
	Go to first page.  ***should use count as offset*** 
-------------------- */
void
goto_first_page()
{
	folder	f;

	f = folders; NEXT_VALID(f);
	if(f == (folder) NULL) {
		/* no valid folders - bleah?! */
		addstatus("no valid folders, exiting", true);
		to_normal();
		exit(1);
	} else if(f != curflr) {
		alternate = curflr;
		curflr = f;
		curmail = f->mail;
		y = FIRST;
		display_page();
	}
}


/* --------------------
	Go to last page.  ***should use count as offset***
-------------------- */
void
goto_last_page()
{
	folder	f, p;

	for(f=folders ; f != (folder) NULL ; f=f->next)
		if(f->valid)
			p = f;
	if(p == (folder) NULL) {
		/* no valid folders - bleah?! */
		addstatus("no valid folders, exiting", true);
		to_normal();
		exit(1);
	} else if(p != curflr) {
		alternate = curflr;
		curflr = p;
		curmail = p->mail;
		y = FIRST;
		display_page();
	}
}
