{****************************************************************************}
{                ---  Mult-Edit macros for Pascal ---                        }
{****************************************************************************}

$MACRO_FILE PASCAL;

{******************************************************************************}
{                                MULTI-EDIT MACRO                              }
{                                                                              }
{Name: PASMTCH                                                                 }
{                                                                              }
{Description:  This macro will match occurances of BEGIN/END, (), CASE/END     }
{  and handles problems withc statements embedded in quotes or comments.       }
{                                                                              }
{               (C) Copyright 1988 by American Cybernetics, Inc.               }
{******************************************************************************}

$MACRO PASMTCH TRANS;

	DEF_STR( Str1, Str2, Str3,     {Match strings}
					 T_Str,S_str, FStr );

	DEF_INT( Direction,   {1 = search forward, 0 = backward}
					 B_Count,     {Match count.  0 = match found}
					 S_Res,       {Search result}
					 Second_Time );


	Second_Time := False;
	Refresh := False;     {Turn screen refresh off}
	Str3 := '';           {Some matchs only require 2 match strings so init the 3rd}

Find_Match_Str:

	IF (Cur_Char = '(') THEN   {Setup match for '('}
		Str1 := '(';
		Str2 := ')';
		Direction := 1;
		S_Str := Str1+'||'+Str2+'||[''{}]||{(@*}||{@*)}';
		GOTO Start_Match;
	END;

	IF (Cur_Char = ')') THEN   {Setup match for ')'}
		Str1 := ')';
		Str2 := '(';
		Direction := 0;
		S_Str := Str1+'||'+Str2+'||[''{}]||{(@*}||{@*)}';
		GOTO Start_Match;
	END;


	IF At_EOL THEN     {If we are at the end of a line the go to the first word}
		First_Word;
	END;

	IF (Cur_Char = ' ') or
		 (Cur_Char = '|9') or
		 (Cur_Char = '|255') THEN      {If we are on a blank space then find a word}
		Word_Right;
	END;

	T_Str := Caps( Get_Word(';. |9|255') );  {Get the current word}

	IF (T_Str = 'BEGIN') OR (T_Str = 'CASE') THEN
		Str1 := 'BEGIN';
		Str2 := 'END';
		Str3 := 'CASE';
		Direction := 1;
		S_Str := '{%||[|9 ;}]{'+Str1+'}||{'+Str2+'}||{'+Str3+'}$||[ |9;.{]}||[''{}]||{(@*}||{@*)}';
		GOTO Start_Match;
	END;

	IF T_Str = 'END' THEN
		Str1 := 'END';
		Str2 := 'BEGIN';
		Str3 := 'CASE';
		Direction := 0;
		Word_Left;
		Left;
		S_Str := '{%||[|9 ;}]{'+Str1+'}||{'+Str2+'}||{'+Str3+'}$||[|9 ;.{]}||[''{}]||{(@*}||{@*)}';
		GOTO Start_Match;
	END;

	{If we didn't find a word to match the first time then try again}
	If NOT( Second_Time ) THEN
		Second_Time := True;
		First_Word;
		GOTO Find_Match_Str;
	END;

	Make_Message('NOTHING to Match');
	GOTO Macro_Exit;

Start_Match:
	Reg_Exp_Stat := True;
	Ignore_Case := True;
	B_Count := 1;
	S_Res := 1;
	Make_Message('Matching...  Hit <ESC> to Stop.');
	Working;

MATCH_LOOP:   {Main loop}

					{If the <ESC> key is pressed while matching then abort the search}
	if check_key then
		if key1 = 27 then
			Make_Message('Match Aborted.');
			goto macro_exit;
		end;
	end;

	If S_Res = 0 THEN   {If last search result was false then exit}
		GOTO Error_Exit;
	END;

	If B_Count = 0 THEN {If match count is 0 then success}
		GOTO Found_Exit;
	END;

	If Direction = 1 THEN {Perform search based on direction}
		Right;
		While NOT( At_EOL) and (Cur_CHar = '|255') DO
			Right;
		END;
		S_Res := Search_Fwd(S_Str,0);
	END ELSE
		Left;
		While (Cur_CHar = '|255') or
					(Cur_Char = '|9') DO
			Left;
		END;
		S_Res := Search_Bwd(S_Str,0);
	END;

	If S_Res = 0 THEN   {If search failed then exit}
		GOTO Macro_Exit;
	END;


	FStr := Caps(Found_Str); {Get the found string and capatilize it}
	IF XPOS(Copy(FStr,1,1),'|9 ;',1)  THEN  {If the first char is a space or a ;}
		FStr := Copy(FStr,2,20);         {  then eliminate it}
	END;
																		 {If it ended in a space, ; or . then}
	IF XPOS(Copy(FStr,Length(FStr),1),'|9 ;.',1) THEN
		FStr := Copy(FStr,1,Length(FStr) - 1);  {eliminate that char}
	END;
 {	Make_Message(FStr);
	read_key; }

															{If we found the first match string then}
	IF FStr = STR1 THEN
		B_Count := B_Count + 1;   {Inc the match count}
		GOTO Match_Loop;
	END;

	IF FStr = STR2 THEN          {If we found the second match string then}
		B_Count := B_Count - 1;    {  decrement the match count}
		GOTO Match_Loop;
	END;

	If FStr = '''''' THEN        {If we found two single quotes the skip it}
		If Direction = 1 THEN
			RIGHT;
		END ELSE
			LEFT;
		END;
		GOTO Match_Loop;
	END;


															{If we found a single quote then match it}
	IF FStr = '''' THEN

		Quote_Loop:

			If Direction = 1 THEN
				RIGHT;
			END ELSE
				LEFT;
			END;
			IF Direction = 1 THEN
				S_Res := Search_Fwd('''',0);
			END ELSE
				S_Res := Search_Bwd('''',0);
			END;
			If S_Res = 0 THEN
				GOTO Macro_Exit;
			END;
			FStr := Found_Str;
			If FStr = '''''' THEN
				GOTO Quote_Loop;
			END;
			GOTO Match_Loop;

	END;

														{If we found a comment then match it}
	IF (Direction = 1) AND (FStr = '{') THEN
			S_Res := Search_Fwd('@}',0);
			GOTO Match_Loop;
	END;
														{If we found a comment then match it}
	IF (Direction = 0) AND (FStr = '}') THEN
			S_Res := Search_Bwd('@{',0);
			GOTO Match_Loop;
	END;
														{If we found a comment then match it}
	IF (Direction = 1) AND (FStr = '(*') THEN
			S_Res := Search_Fwd('@*)',0);
			GOTO Match_Loop;
	END;
														{If we found a comment then match it}
	IF (Direction = 0) AND (FStr = '*)') THEN
			S_Res := Search_Bwd('(@*',0);
			GOTO Match_Loop;
	END;
														{If we found the third string then}
														{  if forward search then}
	IF (Direction = 0) and (FStr = Str3) THEN
		B_Count := B_Count - 1; {  decrement the match count}
		GOTO Match_Loop;
	END;                      {  if backward search then}
	If (Direction = 1) and (FStr = Str3) THEN
		B_Count := B_Count + 1; {  increment the match count}
		GOTO Match_Loop;
	END;

Error_Exit:     {Go here for unsucessfull match}
	Make_Message('Match NOT Found');
	GOTO Macro_Exit;

Found_Exit:     {Go here for successfull match}
	Make_Message('Match Found');
Macro_Exit:
	Refresh := True;
	Redraw;
END_MACRO;


{}
{******************************************************************************}
{                                MULTI-EDIT MACRO                              }
{                                                                              }
{Name: PAS_IND                                                                 }
{                                                                              }
{Description:  This macro will perform a smart indent when the <ENTER> key is  }
{  pressed.  This macro is called by the macro CR.                             }
{                                                                              }
{               (C) Copyright 1988 by American Cybernetics, Inc.               }
{******************************************************************************}

$MACRO PAS_IND;

	DEF_STR(C_STR);          {Word to check for indent}
	DEF_INT(T_COL,T_COL2);   {Temp column positions}
	DEF_INT(sig_char_found,ind_count,jx);
	DEF_CHAR(found_char);
	Messages := False;

	MARK_POS;
	Reg_Exp_Stat := True;
	Down;
	Refresh := False;
	Up;
	LEFT;
	{Check to see if we are inside a comment}
	{Don't go back farther than 5 lines in order to improve speed}

	IF Search_Bwd('@{||@}||{(@*}||{@*)}',5) THEN
		IF (Cur_Char = '{') or (Cur_Char = '(') THEN
			IF (Cur_Char = '{') THEN
				RIGHT;
			ELSE
				RIGHT;
				RIGHT;
			END;
			Set_Indent_Level;
			GOTO_MARK;
		{	Refresh := True; }
			CR;
			GOTO MAC_EXIT;
		END;
	END;


	GOTO_MARK;

	MARK_POS;

	CALL SKIP_PAS_NOISE1;
	FOUND_CHAR := CUR_CHAR;
	GOTO_MARK;
 {REFRESH := TRUE;}

	T_COL2 := C_COL;         {Store current position}
	FIRST_WORD;              {Go to the first word on the line}
	T_COL := C_COL;          {Store this position}

	IF T_COL2 < T_COL THEN   {If this position is greater than the original}
		T_COL := T_COL2;       {  then store the original}
		GOTO_COL(T_COL);       {  and go there}
	END;
	IF At_Eol = False THEN {If we are beyond the end of the line then}
		SET_INDENT_LEVEL;      {  set the indent level}
	END;

	T_COL := C_COL;          {Store the current position}
													 {Get the current word, removing any extra space}
	C_STR := ' ' + REMOVE_SPACE(CAPS( GET_WORD('; (,{') )) + ' ';
	GOTO_COL(T_COL2);        {Put cursor on original position}
	CR;                      {Perform a carriage return}

													 {If the word is in this list, and the original
															position was not on the first word then
															indent}
	IF (T_COL <> T_COL2) AND (LENGTH(C_STR) <> 0) AND
		(POS(C_STR,
	 ' PROCEDURE FUNCTION BEGIN '
	 ) <> 0) THEN
			INDENT;
	END ELSE
		IF (Found_Char <> ';') and (T_COL <> T_COL2) and (LENGTH(C_STR) <> 0)
			AND (POS(C_STR,
		' VAR TYPE CONST PROCEDURE FUNCTION BEGIN IF WHILE REPEAT WITH FOR ELSE '
		) <> 0) THEN
			INDENT;
		END
		ELSE
	{*********************************************************************}
	{***>>> IF YOU DON'T WANT AN UNDENT AFTER 'END' THEN COMMENT OUT THE  }
	{***>>> FOLLOWING THREE LINES                                         }
			IF (C_STR = ' END ') THEN
				UNDENT;
			END;
		END;
	END;
	GOTO MAC_EXIT;

SKIP_PAS_NOISE1:

{ Here we look for the nearest preceding nonblank character.  If it is a
	closing comment then we find the  nearest opening comment.
}

	IF (SEARCH_BWD('[~ |9]', 1)) THEN
		IF (CUR_CHAR = ')') THEN
			LEFT;
			IF (CUR_CHAR = '*') THEN
				JX := SEARCH_BWD('(@*', 0);
				LEFT;
				GOTO SKIP_PAS_NOISE1;
			END;
			RIGHT;
			SIG_CHAR_FOUND := TRUE;
			GOTO EXIT_SKIP_PAS;
		ELSE
			IF (CUR_CHAR = '}') THEN
				JX := SEARCH_BWD('@{', 0);
				LEFT;
				GOTO SKIP_PAS_NOISE1;
			END;
		END;

		SIG_CHAR_FOUND := TRUE;
		GOTO EXIT_SKIP_PAS;
	END;

{ If we failed to find a nonblank character on the current line, and the
	cursor is on line 1, we failed to find a significant character; otherwise,
	we back up a line and try again. }

	IF (C_LINE = 1) THEN
		SIG_CHAR_FOUND := FALSE;
		GOTO EXIT_SKIP_PAS;
	END;
	UP;
	EOL;
	GOTO SKIP_PAS_NOISE1;

EXIT_SKIP_PAS:
 {REFRESH := TRUE;}
	RET;



MAC_EXIT:
	REFRESH := True;
	Messages := True;
END_MACRO;



{}
{******************************************************************************}
{                                MULTI-EDIT MACRO                              }
{                                                                              }
{Name: PASTEMP                                                                 }
{                                                                              }
{Description: Creates pascal language constructs based on a single character   }
{  to the left of the current cursor position.                                 }
{                                                                              }
{               (C) Copyright 1988 by American Cybernetics, Inc.               }
{******************************************************************************}

$MACRO PASTEMP TRANS;

	DEF_INT(Temp_Col,Temp_Insert,Choice, UC);
	DEF_STR(XStr);

	Temp_Insert := Insert_Mode;
	If (At_Eol = False) Then
		GOTO END_OF_MAC;
	End;

	Insert_Mode := True;
	Temp_Col := C_COL;

	Left;

	If (C_Col > 1) Then
		Left;
		If (Pos(Cur_Char,' ;})Ff|255|9') = 0) Then
			Goto_Col(Temp_Col);
			Goto END_OF_MAC;
		End
		Else
			Right;
		End;
	End;

	UC := true;

	If (Cur_Char = 'B') Then
		GOTO MAKEBEGIN;
	End;

	If (Cur_Char = 'I') Then
		GOTO MAKEIF;
	End;

	If (Cur_Char = 'W') Then
		GOTO MAKEWHILE;
	End;

	If (Cur_Char = 'R') Then
		GOTO MAKEREPEAT;
	End;

	If (Cur_Char = 'O') Then
		Del_Char;
		Temp_Col := Temp_Col - 1;
		GOTO MAKEFOR;
	End;

	If (Cur_Char = 'U') Then
		Temp_Col := Temp_Col - 1;
		Del_Char;
		GOTO MAKEFUNCTION;
	End;

	If (Cur_Char = 'F') Then

		Make_Message('Select:');
		run_macro('userin^xmenu /X=10/Y=2/M=For-Next(TE) Function(TE)');
		choice := return_int;
		Make_Message('');
		If (Choice = 2) Then
			GOTO MAKEFUNCTION;
		End
		Else
			GOTO MAKEFOR;
		End;
	End;

	If (Cur_Char = 'P') Then
		GOTO MAKEPROCEDURE;
	End;

	If (Cur_Char = 'C') Then
		GOTO MAKECASE;
	End;


	UC := false;
	If (Cur_Char = 'b') Then
		GOTO MAKEBEGIN;
	End;

	If (Cur_Char = 'i') Then
		GOTO MAKEIF;
	End;

	If (Cur_Char = 'w') Then
		GOTO MAKEWHILE;
	End;

	If (Cur_Char = 'r') Then
		GOTO MAKEREPEAT;
	End;

	If (Cur_Char = 'o') Then
		Del_Char;
		Temp_Col := Temp_Col - 1;
		GOTO MAKEFOR;
	End;

	If (Cur_Char = 'u') Then
		Temp_Col := Temp_Col - 1;
		Del_Char;
		GOTO MAKEFUNCTION;
	End;

	If (Cur_Char = 'f') Then

		Make_Message('Select:');
		run_macro('userin^xmenu /X=10/Y=2/M=For-Next(TE) Function(TE)');
		Choice :=  return_int;

		make_message('');
		If (Choice = 2) Then
			GOTO MAKEFUNCTION;
		End
		Else
			GOTO MAKEFOR;
		End;
	End;

	If (Cur_Char = 'p') Then
		GOTO MAKEPROCEDURE;
	End;

	If (Cur_Char = 'c') Then
		GOTO MAKECASE;
	End;

	Goto_Col(Temp_Col);
	GOTO END_OF_MAC;

MAKEIF:
	Goto_Col(Temp_Col);
	XStr := 'f () then';
	CALL XTEXT;
	Cr;
	Goto_Col(Temp_Col);
	Indent;
	Up;
	Goto_Col(Temp_Col + 3);
	GOTO END_OF_MAC;

MAKEWHILE:
	Goto_Col(Temp_Col);
	XSTR := 'hile () Do';
	CALL XTEXT;
	Cr;
	Goto_Col(Temp_Col);
	Indent;
	Up;
	Goto_Col(Temp_Col + 6);
	GOTO END_OF_MAC;

MAKEBEGIN:
	Goto_Col(Temp_Col);
	XStr := 'egin';
	CALL XTEXT;
	First_Word;
	Temp_Col := C_Col;
	Eol;
	Cr;
	Cr;
	Goto_Col(Temp_Col);
	XStr := 'end;';
	CALL XTEXT;
	Up;
	Goto_Col(Temp_Col);
	Indent;
	GOTO END_OF_MAC;

MAKEFOR:
	Goto_Col(Temp_Col);
	XStr := 'or  :=  to  do';
	CALL XTEXT;
	Cr;
	Goto_Col(Temp_Col);
	Indent;
	Up;
	Goto_Col(Temp_Col + 4);
	GOTO END_OF_MAC;

MAKEREPEAT:
	Goto_Col(Temp_Col);
	XStr := 'epeat';
	CALL XTEXT;
	Cr;
	Goto_Col(Temp_Col - 1);
	Indent;
	Cr;
	Goto_Col(Temp_Col - 1);
	XStr := 'until ();';
	CALL XTEXT;
	Goto_Col(Temp_Col + 6);
	GOTO END_OF_MAC;

MAKEPROCEDURE:
	Goto_Col(Temp_Col);
	XStr := 'rocedure  ;';
	CALL XTEXT;
	Cr;
	Goto_Col(Temp_Col - 1);
	Indent;
	XStr := 'begin';
	CALL XTEXT;
	Cr;
	Cr;
	XStr := 'end;';
	CALL XTEXT;
	Up;
	Goto_Col(Temp_Col);
	Indent;
	Up;
	Up;
	Goto_Col(Temp_Col + 9);
	GOTO END_OF_MAC;

MAKEFUNCTION:
	Goto_Col(Temp_Col);
	XStr := 'unction  ;';
	CALL XTEXT;
	Cr;
	Goto_Col(Temp_Col - 1);
	Indent;
	XStr := 'begin';
	CALL XTEXT;
	Cr;
	Cr;
	XStr := 'end;';
	CALL XTEXT;
	Up;
	Goto_Col(Temp_Col);
	Indent;
	Up;
	Up;
	Goto_Col(Temp_Col + 8);
	GOTO END_OF_MAC;

MAKECASE:
	Goto_Col(Temp_Col);
	XStr := 'ase () of';
	CALL XTEXT;
	Cr;
	Cr;
	Goto_Col(Temp_Col - 1);
	XStr := 'end;';
	CALL XTEXT;
	Up;
	Goto_Col(Temp_Col - 1);
	Indent;
	Up;
	Goto_Col(Temp_Col + 5);
	GOTO END_OF_MAC;

XTEXT:
	IF UC THEN
		XSTR := CAPS(XSTR);
	END;
	TEXT( XSTR );
	RET;

END_OF_MAC:
	Insert_Mode := Temp_Insert;

END_MACRO;


