/* W9.C		Assorted functions				01 Nov 1987 */

#include <ws.h>

unsigned min(a,b)		/* returns minimum of a,b		*/
unsigned a,b;
{
	return (a<b) ? a : b;
}


unsigned max(a,b)		/* returns maximum of a,b		*/
unsigned a,b;
{
	return (a>b) ? a : b;
}


void f_pb_line()		/* finds page bottom line		*/
{
	extern unsigned	pt_line, pb_line;	/* page top,bottom line	*/
	extern unsigned	n_lines;		/* no of text lines	*/
	extern INDEX	t_begin, t_end;		/* text begin, end	*/

	unsigned	min();			/* minimum of two int's */

	if ((pb_line=pt_line + PAGE_LENGTH - 1) > n_lines) {
		pb_line = n_lines;
		if (t_end>t_begin && *(t_end-1)=='\0')
			pb_line++;
	}
	return;
}


void f_pb_index()		/* finds page bottom index		*/
{
	extern INDEX	pb_index;		/* page bottom index	*/
	extern unsigned	pb_line;		/* page bottom line	*/

	INDEX		l_index();		/* index of line	*/

	pb_index = l_index(pb_line);		/* pretty expensive	*/
	return;
}


void f_pbottom()		/* finds page bottom (line and index)	*/
{
	void		f_pb_line();	/* finds page bottom line	*/
	void		f_pb_index();	/* finds page bottom index	*/

	f_pb_line();		/* order of calls is significant!	*/
	f_pb_index();
	return;
}


unsigned dx_bol(ind)		/* returns cursor dist to begin of line */
INDEX ind;
{
	extern INDEX	t_begin;		/* text begin		*/

	unsigned	ch_exp();		/* expanded char width	*/

	static unsigned	c, x;

	c = 0;
	while (--ind>=t_begin && *ind) 
		c++;
	x = 0;
	while (c-->0)
		if (*(++ind)=='\t')
			while (++x % TAB_POS != 0);
		else 
			x += ch_exp(*ind);
	return x;
}


unsigned dy_top(ind)		/* returns cursor dist to top of page	*/
INDEX ind;
{
	extern INDEX	pt_index;		/* page top index	*/

	INDEX		bol_index();		/* index at begin of line */

	static unsigned	dy;

	dy = 0;
	while ( (ind=bol_index(ind)-1) >= pt_index)
		dy++;
	return dy;
}


INDEX bol_index(ind)		/* returns index of char at begin of line */
INDEX ind;
{
	extern INDEX	t_begin;		/* text begin		*/

	while (--ind>=t_begin && *ind) ;
	return ind+1;
}


INDEX eol_index(ind)		/* returns index of NULL char at end of line */
INDEX ind;
{
	extern INDEX	t_end;			/* text end		*/

	while (ind<=t_end && *ind++) ;
	return ind-1;
}


unsigned dx(ind)	/* returns cursor increment for char with index ind */
INDEX ind;
{
	unsigned	dx_bol();	/* cursor dist. to begin of line*/
	unsigned	ch_exp();	/* expanded character width	*/

	static unsigned	x, xx;

	if (*ind=='\t') {
		xx = x = dx_bol(ind);
		while (++x % TAB_POS != 0) ;
		return x-xx;
	}
	return ch_exp(*ind);
}


unsigned ch_exp(ch)	/* returns expanded display width of char ch	*/
char ch;		/* Note: Tabs are NOT treated here.		*/
{
	return (ch<' ') ? 0 : 1;	/* simple version (no Ctrl-chars) */
}


unsigned line(ind)		/* returns line of char with index ind	*/
INDEX ind;
{
	extern INDEX	t_begin;	/* text begin			*/

	INDEX		bol_index();	/* index at begin of line	*/

	static unsigned	l;

	l=1;
	while ((ind=bol_index(ind)-1) >= t_begin)
		l++;
	return l;
}

INDEX l_index(line)		/* returns index at begin of line	*/
unsigned line;
{
	extern INDEX	t_begin;		/* text begin		*/

	INDEX		eol_index();		/* index at end of line	*/

	static INDEX	i;

	i = t_begin;
	while (--line)
		i=eol_index(i)+1;
	return i;
}


void get_xy(ind,x,y)	/* stores cursor coords for index in x,y */
INDEX ind;
unsigned *x,*y;
{
	unsigned	dx_bol();	/* cursor dist to begin of line	*/
	unsigned	dy_top();	/* cursor dist to top of page	*/

	*x = LEFT_SCREEN + dx_bol(ind);
	*y = TOP_SCREEN + dy_top(ind);
	return;
}

void set_xy()		/* stores cursor coords for index in globals cx,cy */
{
	void		set_x();	/* sets cursor x position	*/
	void		set_y();	/* sets cursor y position	*/

	set_x();
	set_y();
	return;
}

void set_x()		/* stores cursor x coord for index in global cx */
{
	extern INDEX	index;		/* current text position	*/
	extern unsigned	cx;		/* current cursor x position	*/

	unsigned	dx_bol();	/* cursor dist to begin of line	*/

	cx = LEFT_SCREEN + dx_bol(index);
	return;
}


void set_y()		/* stores cursor y coord for index in global cy */
{
	extern INDEX	index;		/* current text position	*/
	extern unsigned	cy;		/* current cursor y position	*/

	unsigned	dy_top();	/* cursor dist to top of page	*/

	cy = TOP_SCREEN + dy_top(index);
	return;
}


void to_xy()		/* positions cursor on screen at cx,cy		*/
{
	extern unsigned	cx,cy;		/* current cursor position	*/

	void		CursorTo();	/* positions cursor on screen	*/

	CursorTo(cx,cy);
	return;
}


INDEX s_copy(dest,src,n)	/* copies n chars from src to dest	*/
INDEX dest,src;			/* (does not stop at newlines!)		*/
unsigned n;			/* returns pointer behind dest end	*/
{
	while (n--)
		*dest++ = *src++;
	return dest;
}


unsigned nl_count(ind,n)	/* returns no. of newline codes in	*/
INDEX ind;			/* string at index ind of length n	*/
unsigned n;
{
	static INDEX	indend;
	static unsigned	nl;

	for (indend=ind+n, nl=0; ind<indend; ind++)
		if (!*ind) nl++;
	return nl;
}
