/* W8.C		Delete, Undelete				01 Nov 1987 */

#include <ws.h>


FLAG del_str(n,disp)	/* deletes string of n chars at current index	*/
unsigned n;		/* possibly displays text changes on screen	*/
FLAG disp;		/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/
	extern INDEX	t_end;		/* text end			*/
	extern FLAG	blk_flag;	/* TRUE iff block active	*/
	extern INDEX	b_begin, b_end;	/* block begin, end		*/
	extern unsigned	n_lines;	/* no.of text lines		*/
	extern unsigned pb_index;	/* page bottom index		*/

	unsigned	min();		/* minimum of two int's		*/
	FLAG		save();		/* saves string in scratch buffer */
	FLAG		pmptYN();	/* prompts for Yes/No answer	*/
	unsigned	nl_count();	/* counts newlines in string	*/
	void		move_down();	/* moves rest of text down	*/
	void		f_pbottom();	/* finds page bottom		*/
	void		rest_page();	/* displays rest of page	*/
	INDEX		rest_line();	/* displays rest of line	*/

	static unsigned	nl;

	if ((n=min(n,t_end-index)) == 0) return FALSE;
	if (n>1 && !save(index,n) && 
	    !pmptYN("Cannot save string. Delete anyway",TRUE))
		return FALSE;

	nl = nl_count(index,n);
	move_down(n);
	if (blk_flag) {
		if (index<b_begin) b_begin -= n;
		if (index<=b_end) b_end -= n;
	}
	if (nl) {
		n_lines -= nl;
		f_pbottom();
		if (disp) rest_page(index);
	} else {
		if (index<pb_index) pb_index -= n;
		if (disp) rest_line(index);
	}
	return TRUE;
}


FLAG del_cc()		/* deletes the current character		*/
			/* returns TRUE iff text changes		*/
{
	FLAG	del_str();		/* deletes a string		*/

	return del_str(1,TRUE);		/* TRUE = display changes	*/
}


FLAG del_lc()		/* deletes char to the left of current char	*/
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/
	extern INDEX	t_begin;	/* text begin			*/

	FLAG		char_left();	/* goes to preceding char	*/
	FLAG		del_cc();	/* deletes current char		*/

	if (index<=t_begin) return FALSE;
	char_left();		
	return del_cc();
}

FLAG del_lw()		/* deletes word to the left of current char	*/
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/
	extern INDEX	t_begin;	/* text begin			*/

	void		find_page();	/* displays page for given index */
	void		set_xy();	/* sets cursor coordinates	*/
	FLAG		del_str();	/* deletes string		*/

	static INDEX	old;

	if (index<=t_begin) return FALSE;
	old = index;
	if (isalnum(*--index))
		while (--index>=t_begin && isalnum(*index)) ;
	else
		while (--index>=t_begin && (*index=='\t' || ispunct(*index))) ;
	find_page(++index);
	set_xy();
	return del_str(old-index,TRUE);
}


FLAG del_rw()		/* deletes word to the right of current char	*/
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/
	extern INDEX	t_end;		/* text end			*/

	FLAG		del_str();	/* deletes string		*/

	static INDEX	new;

	if (index>=t_end) return FALSE;
	new = index;
	if (isalnum(*new))
		while (++new<t_end && isalnum(*new)) ;
	else
		while (++new<t_end && (*new=='\t' || ispunct(*new))) ;
	return del_str(new-index,TRUE);
}


FLAG del_line()		/* deletes and removes the entire current text line */
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/

	INDEX		bol_index();	/* index at begin of line	*/
	void		set_x();	/* sets cursor x coordinate	*/
	INDEX		eol_index();	/* index at end of line		*/
	FLAG		del_str();	/* deletes text string		*/

	index = bol_index(index);
	set_x();
	return del_str(eol_index(index)-index+1,TRUE);
}


FLAG del_eol()		/* deletes to end of the current text line	*/
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/

	INDEX		eol_index();	/* index at end of line		*/
	FLAG		del_str();	/* deletes text string		*/

	return del_str(eol_index(index)-index,TRUE);
}


FLAG del_bol()		/* deletes to begin of the current text line	*/
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text position	*/

	INDEX		bol_index();	/* index at begin of line	*/
	void		set_x();	/* sets cursor x coordinate	*/
	FLAG		del_str();	/* deletes text string		*/

	static INDEX	old;

	old = index;
	index = bol_index(index);
	set_x();
	return del_str(old-index,TRUE);
}


#define NULL 0

INDEX	s_buffer;		/* pointer to scratch buffer		  */
INDEX	str_end = s_buffer;	/* pointer behind end of current contents */

FLAG save(ind,n)	/* copies n>1 chars from ind into undelete buffer */
INDEX ind;		/* returns FALSE iff not enough memory for buffer */
unsigned n;
{
	INDEX	*alloc();		/* allocates space in memory	*/
	void	free();			/* deallocates space in memory	*/
	INDEX	s_copy();		/* copies a number of chars	*/

	if (n<=1) return TRUE;
	if (s_buffer!=NULL)	free(s_buffer);
	s_buffer = alloc(n);
	if (s_buffer!=NULL) {
		str_end = s_copy(s_buffer,ind,n);
		return TRUE;
	}
	str_end=s_buffer;
	return FALSE;
}


FLAG undelete()		/* copies string last deleted back into text	*/
			/* returns TRUE iff text changes		*/
{
	extern INDEX	index;		/* current text postition	*/
	extern INDEX	t_end,t_max;	/* text end, max. text end	*/
	extern unsigned	n_lines;	/* no.of text lines		*/

	INDEX		s_copy();	/* copies a number of chars	*/
	unsigned	nl_count();	/* counts newlines in string	*/
	void		f_pbottom();	/* finds page bottom		*/
	void		rest_page();	/* displays rest of text page	*/
	INDEX		rest_line();	/* displays rest of text line	*/

	static unsigned	n;

	if ((n=str_end-s_buffer)<=0) return FALSE;	/* buffer empty? */
	if (!move_up(n)) {
		if (!pmptYN("Cannot undelete completely. Try anyway",TRUE))
			return FALSE;
		move_up(n = t_max-t_end);
	}
	s_copy(index,s_buffer,n);		/* never mind the value */
	n_lines +=  (n=nl_count(s_buffer,n));
	f_pbottom();
	if (n>0)
		rest_page(index);
	else
		rest_line(index);		/* ditto		*/
	return TRUE;
}
