;**
;**		BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;**		Written by Dave Nanian and Michael Strickman.
;**
;**		Revision history:
;**		-----------------
;**		6 October 1985			Added col_mark routine.
;**

;**
;**		col_copy.m
;**
;**		This file contains a set of macros that let you copy and paste
;**	columns of text.  The syntax of the macros is identical to that of
;**	"copy" and "paste", with two differences: it uses its own scrap buffer,
;**	and the col_paste command overlays vertically, instead of inserting new
;**	lines as normal "cut and paste" does.
;**
;**		Note that the highlighting while marking is deceptive, because
;**	it highlights as if a normal mark operation were occurring (i.e. all
;**	the characters on the lines in the block are highlighted, not just the
;**	ones in the block).  This can be avoided by dropping an anchor with
;**	(drop_anchor 1) rather than (drop_anchor) or (mark).  The col_mark
;**	function is an example of this.  You can assign it to a key if
;**	desired.
;**


;**
;**		col_copy:
;**
;**		This macro copies a marked area to another buffer.  It loops through
;**	the marked lines, reading the text between the starting and ending
;**	columns on each line, accumulating that text in another buffer.
;**

(macro col_copy
	(
		(int		start_line 
			  		start_col
					end_line
					end_col
					temp_int
		)
		(int		_col_buf_id
					save_buf_id
		)
		(global	_col_buf_id)

		(if (inq_marked)
			(
				(save_position)
				(inq_position end_line end_col)
				(swap_anchor)
				(inq_position start_line start_col)
				(raise_anchor)

				;**
				;**		If the starting line is after the ending line, swap
				;**	the variables.
				;**

				(if (above start_line end_line)
					(
						(= temp_int start_line)
						(= start_line end_line)
						(= end_line temp_int)
					)
				)

				;**
				;**		Move to the upper left corner of the block (assuming
				;**	that the ending column is greater than the starting column.
				;**

				(if (> start_col end_col)
					(
						;**
						;**	If the starting column is greater then the ending col,
						;**	swap the two.
						;**

						(= temp_int start_col)
						(= start_col end_col)
						(= end_col temp_int)
					)
				)

				(move_abs start_line start_col)

				;**
				;**		If a buffer already existed, get rid of it, then create
				;**	the scrap buffer.
				;**

				(if (!= _col_buf_id 0)
					(delete_buffer _col_buf_id)
				)
				(= _col_buf_id (create_buffer "Column Copy" NULL 1))
				(= save_buf_id (inq_buffer))

				(while (below_eq start_line end_line)
					(
						(end_of_line)
						(inq_position NULL temp_int)

						(set_buffer _col_buf_id)
						(transfer save_buf_id start_line start_col start_line end_col)

						;**		If line isn't terminated with a newline, move to
						;**	the next line.

						(if (> temp_int end_col)
							(
								(move_rel 1 0)
								(move_abs 0 1)
							)
						)

						(set_buffer save_buf_id)
						(move_rel 1 0)
						(++ start_line)
					)
				)
				(restore_position)
			)
		;else
			(error "No marked area.")
		)
	)
)

;**
;**		col_paste:
;**
;**		This macro pastes the contents of the current column buffer, by
;**	inserting it at the current point in the current buffer.  Like the
;**	macro above, it loops through the text, inserting one line at a time
;**	into the current buffer.
;**

(macro col_paste
	(
		(if (== _col_buf_id 0)
			(error "Nothing to insert.")
		;else
			(
				(int		line_len
							save_buf_id
				)
				(string	temp_str)

				(= save_buf_id (inq_buffer))
				(set_buffer _col_buf_id)
				(move_abs 1 1)

				(while (! (inq_position))
					(
						(= temp_str (read))

						;**
						;**		The last character of the read string is a newline
						;**	that should not be inserted.  We parse it off, then
						;**	insert the remaining string into the buffer.
						;**

						(= temp_str (substr temp_str 1 (- (strlen temp_str) 1)))

						(set_buffer save_buf_id)
						(save_position)
						(insert temp_str)
						(restore_position)
						(move_rel 1 0)
						(set_buffer _col_buf_id)
						(move_rel 1 0)
					)
				)
				(set_buffer save_buf_id)
			)
		)
	)
)

;**
;**		col_mark:
;**
;**		This routine implements the standard mark function, but uses the
;**	type of mark that displays correctly for columnar blocks.
;**

(macro col_mark
	(
		(if (inq_marked)
			(raise_anchor)
		;else
			(drop_anchor 1)
		)
	)
)
