$MACRO_FILE Text;
{*******************************MULTI-EDIT MACRO******************************

Name:  CHNGCASE

Description:  Changes the case of a block of text.

Parameters:  /U=1			Uppercase
						 	 =0			Lowercase
						 /T=0			Line
							 =1			Word
							 =2			Block

               (C) Copyright 1988 by American Cybernetics, Inc.
******************************************************************************}
$macro chngcase trans;
	def_int( jx, tc, ti, casetype, blocktype, tb1, tbs, tb2, tbl1, tbl2, tbc1, tbc2 );
	def_str( tstr );

	push_undo;
	refresh := false;
	ti := insert_mode;
	insert_mode := true;
	casetype := parse_int('/U=', mparm_str);
	blocktype := parse_int('/T=', mparm_str);

	if blocktype = 0 then
		if casetype then
			put_line( caps(get_line));
		else
			put_line( lower(get_line));
		end;
	end;
	if blocktype = 1 then
		if not(at_eol) and (xpos(cur_char,word_delimits,1) <> 0) then
			word_right;
		else
			if c_col > 1 then
				left;
				if xpos(cur_char,word_delimits,1) then
					right;
				else
					right;
					word_left;
				end;
			end;
		end;
		tc := c_col;
		tstr := get_word(word_delimits);
		if casetype then
			tstr := caps(tstr);
		else
			tstr := lower(tstr);
		end;

	  goto_col(tc);
		del_chars( svl(tstr) );
		text( tstr );
	end;
	if (block_stat <> 0) and (blocktype = 2) then
		block_end;
		tbl1 := block_line1; tbl2 := block_line2;
		tbc1 := block_col1; tbc2 := block_col2;
		tbs := block_stat;
		mark_pos;
		jx := block_line1;
		while jx <= tbl2 do
			goto_line(jx);
			if tbs = 1 then
				if casetype then
					put_line( caps(get_line));
				else
					put_line( lower(get_line));
				end;
			end;
			if tbs = 2 then
				goto_col(tbc1);
				tstr := copy(get_line, tbc1, tbc2 - tbc1 + 1);
				del_chars( svl(tstr) );
				if casetype then
					tstr := caps(tstr);
				else
					tstr := lower(tstr);
				end;
				text( tstr );
			end;
			if tbs = 3 then
				goto_col(1);
				tb1 := 1;
				tstr := get_line;
				tb2 := svl( tstr );
				if jx = tbl1 then
					 goto_col(tbc1);
					 tb1 := tbc1;
				end;
				if jx = tbl2 then
					tb2 := tbc2;
				end;
				del_chars( tb2 - tb1 + 1);
				tstr := copy( tstr, tb1, tb2 - tb1 + 1);
				if casetype then
					tstr := caps(tstr);
				else
					tstr := lower(tstr);
				end;
				text(tstr);
			end;
			++jx;
			down;
		end;
		if tbs = 3 then
			goto_line(tbl1);
			goto_col(tbc1);
			str_block_begin;
			goto_line(tbl2);
			goto_col(tbc2 + 1);
			block_end;
		end;
		goto_mark;
	end;
	insert_mode := ti;
	pop_undo;
	redraw;
end_macro;


$MACRO TextSort trans;
{*******************************MULTI-EDIT MACRO******************************

Name:	TextSort

Description:	Sorts lines of text.

Parameters:		/C=nn			Starting column of sort field.
							/L=nn			# of characters in sort field.
							/CASE			Ignore case of field.
							/D				Sort in descending order.
							/B				Sort the marked line block.

               (C) Copyright 1988 by American Cybernetics, Inc.
******************************************************************************}

		Def_Int( IX, SX, SL, NC, C, L, Caps_On, Descending, jx, Sort_Mode, old_block_stat );
		Def_Str( DP1, DP2, DX1, DX2 );
		def_char( tc, dc );

		push_undo;
		refresh := false;
		working;
		old_block_stat := 0;
		goto_col(1);
		set_indent_level;
	  EOF;
		NC := C_Line;
		TOF;
		sx := 1;
		Descending := xpos( '/D', MParm_Str, 1 ) <> 0;
		Caps_On := Xpos( '/CASE', MParm_Str, 1 ) <> 0;
		c := parse_int( '/C=', MParm_Str );
		l := parse_int( '/L=', MParm_Str );
		if c = 0 then
			c := 1;
		end;
		if l = 0 then
			l := 254;
		end;

		if xpos( '/B', MParm_Str, 1 ) <> 0 then
			if Block_Stat <> 1 THEN
				Make_Message( 'No line block marked.');
				goto exit;
			end;
			old_block_stat := block_stat;
			sx := block_line1;
			nc := block_line2;
			block_off;
		end;
		sl := sx;

		sort_mode := ((nc - sx) > 100);

		Make_Message( 'Sorting...' );

		{ We're going to do this with 2 different loops, depending on the
			options, for speed's sake }


		if sort_mode then
			jx := 0;
			while jx < 254 do
				++jx;
				set_global_int( char(jx) + 'SORT', sx );
			end;
		end;

		If Descending then
			goto DESCEND;
		end;

ASCEND:
		while sx < nc do
			++sx;
			put_line_num(sx);
			GOTO_LINE(SX);
			dp1 := Get_Line;
			dx1 := (Copy( dp1, c, l ));
			If Caps_On then
				dx1 := caps(dx1);
			end;
			del_line;
			if sort_mode then
				dc := str_char(dx1,1);
				ix := global_int( dc + 'SORT' );
			else
				ix := sl;
			end;
			while ix < sx do
				goto_line(ix);
				dx2 := (Copy( get_line, c, l ));
				If Caps_On then
					dx2 := caps(dx2);
				end;
				If ( dx1 < dx2 ) then
	 do_insert2:
					goto_col(1);
					cr;
					up;
					put_line(dp1);
					if sort_mode then
						up;
						goto_col(c);
						tc := cur_char;
						if caps_on then
							tc := caps(tc);
						end;
						if tc < dc then
							set_global_int( dc + 'SORT', c_line );
						end;
					end;
					goto ascend;
				END;
				++ix;
			END;
			down;
			goto do_insert2;
	 loopb:
		END;
		goto done;

DESCEND:
		while sx < nc do
			++sx;
			put_line_num(sx);
			GOTO_LINE(SX);
			dp1 := Get_Line;
			dx1 := (Copy( dp1, c, l ));
			If Caps_On then
				dx1 := caps(dx1);
			end;
			del_line;
			if sort_mode then
				dc := str_char(dx1,1);
				ix := global_int( dc + 'SORT' );
			else
				ix := sl;
			end;
			while ix < sx do
				goto_line(ix);
				dx2 := (Copy( get_line, c, l ));
				If Caps_On then
					dx2 := caps(dx2);
				end;
				If ( dx2 < dx1 ) then
	 do_insert3:
					goto_col(1);
					cr;
					up;
					put_line(dp1);
					if sort_mode then
						up;
						tc := cur_char;
						if caps_on then
							tc := caps(tc);
						end;
						if tc > dc then
							set_global_int( dc + 'SORT', c_line );
						end;
					end;
					goto descend;
				END;
				++ix;
			END;
			down;
			goto do_insert3;
	 loopc:
		END;
		goto done;

done:
		Make_Message( 'Sorting complete.' );
exit:
		if sort_mode then
			jx := 0;
			while jx < 254 do
				++jx;
				set_global_int( char(jx) + 'SORT', 0 );
			end;
		end;
		if old_block_stat > 0 then
			goto_line(sl);
			block_begin;
			goto_line(nc);
			block_end;
		end;
		pop_undo;
		refresh := true;
		goto_line( sl );
		redraw;
END_MACRO;

$macro center trans;
{*******************************************************************************
                                MULTI-EDIT MACRO

Name: CENTER

Description: Centers the line the cursor is on between column 1 and the right
							margin.

               (C) Copyright 1988 by American Cybernetics, Inc.
*******************************************************************************}
  Def_Int(jx);
  Def_Str(tstr);
  refresh := false;
  Goto_Col(1);
  Push_Undo;
  Insert_Mode := True;
{Delete leading spaces}
  While NOT(At_EOL) and (XPOS(Cur_Char,'|255|9|32',1) <> 0) Do
    Del_Char;
  End;
{Store line into variable}
  Tstr := Get_Line;
  jx := length(Tstr);
  If jx > 0 THEN
    jx := (Right_Margin / 2) - (jx / 2);
{Blank out existing line}
    Put_line('');
    Goto_Col(jx);
{Put line at new position.  Works with tabs as spaces, or tabs.}
    Text(TStr);
  END;
  refresh := true;
  redraw;
  Pop_Undo;
end_macro;



{*******************************************************************************
                                MULTI-EDIT MACRO

Name: openln

Description: Opens a line below the current line, without moving the cursor.

               (C) Copyright 1988 by American Cybernetics, Inc.
*******************************************************************************}

$macro openln;
	def_int( temp_ins );
	push_undo;
	temp_ins := insert_mode;
	insert_mode := true;
	Mark_Pos;
	CR;
	Goto_Mark;
	Make_Message('Line opened.');
	insert_mode := temp_ins;
	pop_undo;
end_macro;

$macro reformat trans;
{******************************************************************************
                                MULTI-EDIT MACRO

Name:	REFORMAT

Description: Reformats the current paragraph from the current cursor position
						 down.
						 Parameters:
						 			/NR		Don't restore position

               (C) Copyright 1988 by American Cybernetics, Inc.
******************************************************************************}

	Def_Str( RStr );
	Def_Int( rp );  { set true if we are not to restore the position }

	rp := XPOS( '/NR', MParm_Str, 1 ) = 0;

	Push_Undo;
	word_wrap_line;
	if rp then
		mark_pos;
	end;
	down;
	REFORMAT_LOOP:
		RStr := Get_Line;
		If (length( RStr ) > 0) and (XPOS(Page_Str,RStr,1) = 0) THEN
			word_wrap_line;
			down;
			if hard_cr <> '' then
				if xpos(hard_cr, rstr, 1) then
					goto no_reform_loop;
				end;
			end;
			GOTO REFORMAT_LOOP;
		END;
no_reform_loop:
	if rp then
		Goto_Mark;
	end;
	Pop_Undo;
	Make_Message('Paragraph reformatted from current line.');
end_macro;

$macro justify trans;
{******************************************************************************
                                MULTI-EDIT MACRO

Name:	JUSTIFY

Description: Justifies the current paragraph from the current cursor position
						 down.

               (C) Copyright 1988 by American Cybernetics, Inc.
******************************************************************************}
	def_int( jx,jy,rr,jk, ti );

	push_undo;
	ti := insert_mode;
	insert_mode := true;
	refresh := false;
	mark_pos;
	IF Right_Margin > 132 then
		Goto_Mark;
		Make_Message('Right Margin too big.');
		Goto Exit2;
	END;
	Make_Message('Justifying paragraph...');
	Working;
MAIN_LOOP:
	down;
	goto_col(1);
	if AT_EOL then
		goto EXIT;
	end;
	if Xpos(page_str,get_line,1) then
		goto exit;
	end;
	up;
M2:
	first_word;
{remove trailing spaces}
  put_line( Shorten_Str(Get_Line) );
	jx := 0;

{Count existing spaces}
SPACE_LOOP:
	if cur_char = ' ' then
		jx := jx + 1;
	end;
	right;
	if NOT( AT_EOL ) then
		goto space_loop;
	end;
	eol;
	left;
	jy := Right_Margin - c_col;
	IF (jy <= 0) OR (jX <= 0) then
		goto NEXT_LINE;
	end;
	rr := jx / jy;
	first_word;
	jx := 0;
	jk := 0;
{Add in extra spaces until desired line length is reached}
	while NOT( AT_EOL ) do
		if cur_char = ' ' then
			jx := jx + 1;
			if jx >= rr then
				if jk < jy then
					jk := jk + 1;
					text(' ');
					right;
				end;
				jx := 0;
			end;
		end;
		right;
	end;

{Repeat until at end of paragraph}
	IF c_col > Right_Margin then
		goto NEXT_LINE;
	END;
	GOTO M2;
NEXT_LINE:
	down;
	eol;
	if c_col = 1 then
		goto EXIT;
	end;
	if hard_cr <> '' then
		if xpos(hard_cr, get_line, 1) then
			goto EXIT;
		end;
	end;

	GOTO MAIN_LOOP;

EXIT:
	goto_mark;
	Make_Message('Paragraph justified.');
EXIT2:
	refresh := true;
	pop_undo;
	redraw;
	insert_mode := ti;
end_macro;

$macro unjustif trans;
{******************************************************************************
                                MULTI-EDIT MACRO

Name:	UNJUSTIF

Description: Unjustifies the current paragraph from the current cursor position
						 down.

               (C) Copyright 1988 by American Cybernetics, Inc.
******************************************************************************}
	push_undo;
	mark_pos;
	refresh := false;

	Make_Message('Unjustifying paragraph...');
	Working;
main_loop:
	first_word;
{Check for end of paragraph}
	if AT_EOL then
		goto EXIT;
	END;
	if hard_cr <> '' then
		if xpos(hard_cr, get_line, 1) then
			goto EXIT;
		end;
	end;
	while NOT( AT_EOL ) do
{Skip over end of sentences, etc.}
		if pos(cur_char,'.!?:') then
			right;
			right;
		end;
{Otherwise, remove occurances of more than one space}
		if cur_char = ' ' then
			right;
			while cur_char = ' ' do
				del_char;
			end;
		end;
		right;
	end;
	down;
	goto Main_Loop;
EXIT:
	Make_Message('Paragraph Unjustified...');
	pop_undo;
	refresh := true;
	goto_mark;
	redraw;

end_macro;