/********************************************************************
 *                                                                  *
 *      CRISP - Custom Reduced Instruction Set Programmers Editor   *
 *                                                                  *
 *      (C) Paul Fox, 1989                                          *
 *                                                                  *
 *                                                                  *
 *    Please See COPYLEFT notice.                                   *
 *                                                                  *
 ********************************************************************/
# include	"crisp.h"

# define	BLOCK_NOTHING	0	/* Do nothing with original text. */
# define	BLOCK_REPLACE	1 	/* Delete original text in block. */

string block_string; 		/* Buffer saved for column cut/copy.	    */

void
paste()
{	int	type;
	list	lines;
	int	len, col, line_no;
	int	i;
	int	old_msg_level;

	inq_scrap(NULL, type);
	if (type != MK_COLUMN) {
		old_msg_level = inq_msg_level();
		if (inq_called() == "")
			set_msg_level(0);
		paste();
		set_msg_level(old_msg_level);
		return;
		}
		
	/***********************************************/
	/*   Split  the  column  string into separate  */
	/*   lines.				       */
	/***********************************************/
	lines = split(block_string, "\n");
	
	/***********************************************/
	/*   Now paste them in, one at a time.	       */
	/***********************************************/
	len = length_of_list(lines);
	inq_position(line_no, col);
	for (i = 0; i < len; ) {
		message("%pPasting column: %d%% done", (i * 100) / len);
		insert(lines[i++]);
		move_abs(line_no + i, col);
		}
	message("Scrap inserted.");
}
void
copy()
{	int	old_msg_level;

	if (inq_called() != "") {
		copy();
		return;
		}
	if (inq_marked()) {
		old_msg_level = inq_msg_level();
		set_msg_level(0);
		if (inq_marked() == MK_COLUMN) {
			block_string = "";
			block("block_copy", 
				BLOCK_REPLACE, 
				"%pCopying column: %d%% done");
			set_scrap_info(NULL, MK_COLUMN);
			message("Column copied to scrap.");
			}
		else
			copy();
		set_msg_level(old_msg_level);
		return;
		}

	drop_anchor(MK_LINE);
	message("Line copied to scrap.");
	copy();
}
void
cut()
{	int	old_msg_level;

	if (inq_called() != "") {
		cut();
		return;
		}
	if (inq_marked()) {
		old_msg_level = inq_msg_level();
		set_msg_level(0);
		if (inq_marked() == MK_COLUMN) {
			block_string = "";
			block("block_cut", 
				BLOCK_REPLACE,
				"%pCutting column: %d%% done");
			set_scrap_info(NULL, MK_COLUMN);
			message("Column cut to scrap.");
			}
		else
			cut();
		set_msg_level(old_msg_level);
		return;
		}
	drop_anchor(MK_LINE);
	message("Line cut to scrap.");
	cut();
}

/**********************************************************************/
/*   Macro called on each line when we try and cut a column block.    */
/**********************************************************************/
int
block_cut(string block_line)
{
	block_string += block_line + "\n";
	return BLOCK_REPLACE;
}
/**********************************************************************/
/*   Macro called on each line when we try and copy a column block.    */
/**********************************************************************/
int
block_copy(string block_line, int width)
{
	string	s = trim(block_line, "\n");
	s += " " * (width - strlen(s));
	block_string += s + "\n";
	return BLOCK_NOTHING;
}
void
block_upper_case() 
{
	block("block_uc", NULL, "%pUpper case: %d%% done");
}
int
block_uc(string block_line)
{
	insert(upper(block_line));
	return BLOCK_REPLACE;
}
/**********************************************************************/
/*   Function to add up a column of numbers.			      */
/**********************************************************************/
void
sum()
{	float	sum = 0;
	int	buf = inq_buffer();
	string	s;

	block("block_sum1", NULL, "%pSumming column: %d%% done");
	
	/***********************************************/
	/*   Copy the number to the scrap buffer.      */
	/***********************************************/
	set_buffer(inq_scrap());
	clear_buffer();
	sprintf(s, "%g", sum);
	insert(s + "\n");
	set_buffer(buf);
	message("Result=%g - copied to scrap.", sum);
}
int
block_sum1(string line)
{	extern float sum;
	declare	x;
	
	x = cvt_to_object(line);
	switch (typeof(x)) {
	  case "float":
	  case "integer":
	  	sum += x;
		break;	
	  }
	return BLOCK_NOTHING;
}
void
block_lower_case() 
{
	block("block_lc", NULL, "%pLower case: %d%% done");
}
int
block_lc(string block_line)
{
	insert(lower(block_line));
	return BLOCK_REPLACE;
}
void
block_delete()
{
	block(NULL, BLOCK_REPLACE);
}
void
block(string macro_name, ~int, string msg)
{
	int	type,
		start_line,
		start_col,
		end_line,
		end_col,
		col = 1,
		result,
		width,
		size, s, cnt, total;
	string block_line;

	/***********************************************/
	/*   If  no  message  specified  then  use  a  */
	/*   default one which is time dependent.      */
	/***********************************************/
	if (msg == "")
		msg = "%p%d%% done";
	type = inq_marked(start_line, start_col, end_line, end_col);
	if (type == 0) {
		error("No marked region.");
		return;
		}
 
	if (type == MK_COLUMN)
		col = start_col;
	raise_anchor();

	move_abs(start_line, start_col);
	cnt = 0;
	total = end_line - start_line;
	width = end_col - start_col;
	while (start_line <= end_line) {
		message(msg, (cnt++ * 100) / total);
		drop_anchor(MK_NORMAL);
		save_position();
		if (type == MK_COLUMN || start_line == end_line)
			move_abs(0, end_col);
		else {
			end_of_line();
			prev_char();
			}
		size = inq_mark_size();
		raise_anchor();
		restore_position();
		block_line = read(size);
		if (macro_name != "")
		 	result = execute_macro(macro_name, block_line, width);
	       	else
			get_parm(1, result);
		switch (result) {
		  case BLOCK_REPLACE:
		  	s = strlen(trim(block_line, "\n"));
			delete_char(s);
			break;
		  }
		++ start_line;
		move_abs(start_line, col);
		}
	move_abs(end_line, end_col);
}

