/* W5.C		Text character insert, overwrite		01 Nov 1987 */

#include <ws.h>


FLAG ins_mode()			/* toggles the insert mode flag		*/
				/* returns FALSE since no text change	*/
{
	extern FLAG	ins_flag;	/* TRUE iff in insert mode	*/

	ins_flag = !ins_flag;
	return FALSE;
}


FLAG text_char(ch)		/* puts character ch in text		*/
char ch;			/* returns TRUE since text changes	*/
{
	extern FLAG	ins_flag;	/* TRUE iff in insert mode	*/
	extern INDEX	index;		/* current text position	*/
	extern unsigned cx;		/* current cursor x position	*/

	FLAG		ins_char();	/* insert char in text		*/
	INDEX		rest_line();	/* displays rest of line	*/
	FLAG		char_right();	/* goes to the next char	*/
	unsigned	disp_index();	/* display char of index	*/
	unsigned	min();		/* minimum of two int's		*/

	static FLAG	tab_flag;

	if (ins_flag || !*index) return ins_char(ch);
	tab_flag = (*index=='\t') || (ch=='\t');
	*index = ch;
	if (tab_flag) {
		rest_line(index);	/* never mind the value		*/
		char_right();		/* ditto			*/
	} else
		cx = min( LINE_LENGTH, disp_index(index++,cx));
	return TRUE;
}


FLAG ins_char(ch)		/* inserts char ch into text		*/
char ch;			/* returns FALSE only if out of space	*/
{
	extern INDEX	index;		/* current text position	*/
	extern INDEX	pb_index;	/* page bottom index		*/
	extern INDEX	b_begin, b_end;	/* block begin, end		*/
	extern unsigned n_lines;	/* no. of text lines		*/
	extern FLAG	blk_flag;	/* TRUE iff block active	*/

	FLAG		move_up();	/* moves rest of text up	*/
	INDEX		rest_line();	/* displays rest of line	*/
	void		f_pbottom();	/* finds page bottom		*/
	void		rest_page();	/* displays rest of page	*/
	FLAG		char_right();	/* goes to next char		*/

	if (!move_up(1)) return FALSE;
	*index = ch;
	if (blk_flag) {
		if (index<b_begin) b_begin++;
		if (index<=b_end+1) b_end++;
	}
	if (ch) {
		if (index<pb_index) pb_index++;
		rest_line(index);	/* never mind the value		*/
	} else {
		n_lines++;
		f_pbottom();
		rest_page(index);
	}
	char_right();			/* ditto			*/
	return TRUE;
}


FLAG new_line()			/* either appends a new line code	*/
				/* or goes to the next line		*/
				/* returns TRUE iff text was changed	*/
{
	extern FLAG	ins_flag;	/* TRUE iff in insert mode	*/
	extern INDEX	index;		/* current text position	*/
	extern INDEX	t_end;		/* text end			*/

	FLAG		ins_char();	/* insert char in text		*/
	INDEX		eol_index();	/* index of end of line		*/
	FLAG		char_right();	/* goes to next char		*/

	if (ins_flag || index==t_end) return ins_char('\0');
	index = eol_index(index);
	char_right();			/* never mind the value		*/
	return FALSE;
}


FLAG ins_line()			/* inserts a new line code into text	*/
				/* return TRUE iff text was changed	*/
{
	FLAG		ins_char();	/* insert char in text		*/
	FLAG		char_left();	/* goes to previous char	*/

	static FLAG	flag;

	if ( (flag=ins_char('\0')) ) char_left();	/* never mind value */
	return flag;
}
 

FLAG move_up(n)			/* moves text up n chars in memory	*/
unsigned n;			/* (i.e., makes space for n new chars)	*/
				/* returns FALSE iff out of memory	*/
{
	extern INDEX	t_end, t_max;	/* text end, max text length	*/
	extern INDEX	index;		/* current text position	*/

	void		pmpt_ack();	/* prompt for acknowledge	*/

	static INDEX	ts, td;		/* source, destination pointer	*/

	if (t_end+n >t_max) {
		pmpt_ack("Cannot move text");
		return FALSE;
	}
	for (ts=t_end, td=ts+n; ts>=index; )
		*td-- = *ts--;
	t_end += n;
	return TRUE;
}
 

void move_down(n)		/* moves text down n chars in memory	*/
				/* (e.g., after deleting n chars)	*/
{
	extern INDEX	t_end;		/* text end			*/
	extern INDEX	index;		/* current text position	*/

	static INDEX	ts, td;		/* source, destination pointer	*/

	for (td=index, ts=td+n; ts<=t_end; )
		*td++ = *ts++;
	t_end -= n;
	return;
}
