macro_file MODULA_2;
/*******************************************************************************
														MULTI-EDIT MACRO FILE

Name: MODULA_2

Description:	Language support for Modula-2

MOD_IND - Smart indent
MODTEMP - Template editing
MODMTCH - Construct matching

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/

macro MOD_IND {
/*******************************************************************************
																MULTI-EDIT MACRO

Name: MOD_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 1991 by American Cybernetics, Inc.
*******************************************************************************/

	str C_STR;          /* Word to check for indent */
	int T_COL,T_COL2;   /* Temp column positions */
	int sig_char_found,ind_count,jx;
	char found_char;

	MARK_POS;
	Reg_Exp_Stat = True;
	Refresh = False;
	LEFT;
	/* Check to see if we are inside a comment */
	/* Don't go back farther than 20 lines in order to improve speed */
	if(  Search_Bwd('{(@*}||{@*)}',20)  ) {
		if(  (Cur_Char == '(')  ) {
			RIGHT;
			RIGHT;
			Set_Indent_Level; /*  this stuff below needed to be moved inside this loop  */
			GOTO_MARK;        /*  you might check the PAS_IND because I think it has the same problem  */
			Refresh = True;
			CR;
			GOTO MAC_EXIT;
		}
	}

	GOTO_MARK;
	MARK_POS;

	CALL skip_mod_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  ) {   /* If this position is greater than the original */
		T_COL = T_COL2;       /*   then store the original */
		GOTO_COL(T_COL);       /*   and go there */
	}
	if(  NOT (At_Eol)  ) {     /* If we are not beyond the end of the line then */
		SET_INDENT_LEVEL;      /*   set the indent level */
	}

	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) & (LENGTH(C_STR) != 0) &
		(POS(C_STR,
	 ' PROCEDURE BEGIN CASE '
	 ) != 0)  ) {
			INDENT;
	} else {
		if(  (Found_Char != ';') & (T_COL != T_COL2) & (LENGTH(C_STR) != 0)
			& (POS(C_STR,
		' VAR TYPE CONST PROCEDURE BEGIN IF WHILE REPEAT LOOP WITH FOR ELSE ELSIF '
		) != 0)  ) {
			INDENT;
		} else {
	/***********************************************************************/
	/****>>> IF YOU DON'T WANT AN UNDENT AFTER 'END' THEN COMMENT OUT THE  */
	/****>>> FOLLOWING THREE LINES                                         */
			IF (C_STR == ' END ')
				UNDENT;
		}
	}
	GOTO MAC_EXIT;

skip_mod_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('[~ ]', 1))  ) {
		if(  (CUR_CHAR == ')')  ) {
			LEFT;
			if(  (CUR_CHAR == '*')  ) {
				JX = SEARCH_BWD('(@*', 0);
				LEFT;
				GOTO skip_mod_noise1;
			}
			RIGHT;
			SIG_CHAR_FOUND = TRUE;
			GOTO EXIT_skip_mod;
		}

		SIG_CHAR_FOUND = TRUE;
		GOTO EXIT_skip_mod;
	}

/*  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)  ) {
		SIG_CHAR_FOUND = FALSE;
		GOTO EXIT_skip_mod;
	}
	UP;
	EOL;
	GOTO skip_mod_noise1;

EXIT_skip_mod:
	REFRESH = TRUE;
	RET;

MAC_EXIT:

}

macro MODTEMP {
/*******************************************************************************
																MULTI-EDIT MACRO

Name: MODTEMP

Description: Creates modula 2 language constructs based on a single character
	to the left of the current cursor position.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/

	int Temp_Col,Temp_Insert,Temp_Indent_Col;
	str Key_Chars, Tstr ;
	char Temp_Char;
	Key_Chars = 'BIWFPMCRLE';
	Temp_Insert = Insert_Mode;
	if(  NOT (At_Eol)  ) { /*  if we ain't at the eol of the line  */
		RM('MEERROR^Beeps /C=1'); /*  let the user know he's got stuff to the right on the line  */
		Make_Message('Not at the end of the line.'); /*  you can take this out if you would like  */
		GOTO END_OF_MAC;
	}
	Insert_Mode = True;
	Temp_Col = C_COL;
	if(  (C_Col > 1)  ) {
		Left;
		if(  (Pos(Caps(Cur_Char),Key_Chars) == 0)  ) {
			Goto_Col(Temp_Col);
			Goto END_OF_MAC;
		}
	} else {
		Goto END_OF_MAC;
	}
	Temp_Col = C_COL;

	if(  (Caps(Cur_Char) == 'B')  ) {
		Insert_Mode = False;
		Indent;
		Temp_Indent_Col = C_Col; /*  save current indent column position away as to be  */
		Goto_Col(Temp_Col);       /*  indent level sensitive  */
		Text('BEGIN');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);
		Text('END ;');
		Up;
		Goto_Col(Temp_Indent_Col);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'I')  ) {
		Insert_Mode = False;
		Indent;
		Goto_Col(Temp_Col);
		Text('IF () THEN');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);
		Text('END;');
		Up;
		Up;
		Goto_Col(Temp_Col + 4);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'E')  ) {
		Insert_Mode = False;
		Indent;
		Temp_Indent_Col = C_Col;
		Goto_Col(Temp_Col);
		Text('ELSE');
		Insert_Mode = True;
		Cr;
		Cr;
		Up;
		Goto_Col(Temp_Indent_Col);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'W')  ) {
		Insert_Mode = False;
		Indent;
		Goto_Col(Temp_Col);
		Text('WHILE () DO');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);
		Text('END;');
		Up;
		Up;
		Goto_Col(Temp_Col + 7);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'F')  ) {
		Insert_Mode = False;
		Indent;
		Goto_Col(Temp_Col);
		Text('FOR  :=  TO  DO');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);
		Text('END;');
		Up;
		Up;
		Goto_Col(Temp_Col + 4);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'P')  ) {
		Return_Str = '';
    RM('USERIN^QUERYBOX /T=Procedure Name?/W=40');
		if(  return_int < 1  ) {
			goto END_OF_MAC;
		}
		Insert_Mode = False;
		Indent;
		Temp_Indent_Col = C_Col;
		Goto_Col(Temp_Col);
		Text('PROCEDURE ' + return_str + '(  );');
		Insert_Mode = True;
		Cr;
		Goto_Col(Temp_Indent_Col);
		Text('BEGIN');
		Cr;
		Cr;
		Goto_Col(Temp_Indent_Col);
		Text('END ' + return_str + ';');
		Up;
		Up;
		Up;
		Goto_Col(Temp_Col + 12 + length(return_str));
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'M')  ) {
		Return_Str = '';
    RM('USERIN^QUERYBOX /T=Module Name?/W=40');
		if(  return_int < 1  ) {
			goto END_OF_MAC;
		}
		RM('USERIN^XMENU /T=1/B=1/M=Implementation module()Definition module()Module()');
		tstr = '';
		if(  return_int < 1  ) {
			goto END_OF_MAC;
		}
		if(  return_int == 1  ) {
			tstr = 'IMPLEMENTATION ';
		}
		if(  return_int == 2  ) {
			tstr = 'DEFINITION ';
		}

		Insert_Mode = False;
		Indent;
		Goto_Col(Temp_Col);
		Text(tstr + 'MODULE ' + return_str + ';');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);

		if(  return_int != 2  ) {
			Text('BEGIN');
			Cr;
			Cr;
			Goto_Col(Temp_Col);
		}
		Text('END ' + return_str + '.');
		Up;
		Goto_Col(1);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'C')  ) {
		Insert_Mode = False;
		Indent;
		Goto_Col(Temp_Col);
		Text('CASE  OF');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);
		Text('END;');
		Up;
		Up;
		Goto_Col(Temp_Col + 5);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'R')  ) {
		Insert_Mode = False;
		Indent;
		Goto_Col(Temp_Col);
		Text('REPEAT');
		Insert_Mode = True;
		Cr;
		Cr;
		Goto_Col(Temp_Col);
		Text('UNTIL ();');
		Goto_Col(Temp_Col + 7);
		Goto END_OF_MAC;
	}

	if(  (Caps(Cur_Char) == 'L')  ) {
		Insert_Mode = False;
		Indent;
		Temp_Indent_Col = C_Col;
		Goto_Col(Temp_Col);
		if(  C_Col != 1  ) {
			Left;
		}
		if(  Caps(Cur_Char) == 'E'  ) {
			Text('ELSIF');
			Insert_Mode = True;
			Cr;
			Goto_Col(Temp_Indent_Col);
		} else {
			Goto_Col(Temp_Col);
			Text('LOOP');
			Insert_Mode = True;
			Cr;
			Goto_Col(Temp_Indent_Col);
			Text('IF () THEN');
			Cr;
			Indent;
			Text('EXIT;');
			Cr;
			Undent;
			Goto_Col(Temp_Indent_Col);
			Text('END;');
			Cr;
			Goto_Col(Temp_Col);
			Text('END;');
			Up;
			Up;
			Up;
			Goto_Col(Temp_Col + 6);
		}
		Goto END_OF_MAC;
	}

END_OF_MAC:
	Insert_Mode = Temp_Insert;
}

macro MODMTCH TRANS {
/*******************************************************************************
																MULTI-EDIT MACRO

Name: MODMTCH

Description: Construct matching for Modula-2

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/

	str  Str1,     /* Match strings */
					 EStr1,
					 T_Str, S_Str, FStr ;

	int  Direction,   /* 1 = search forward, 0 = backward */
					 B_Count,     /* Match count.  0 = match found */
					 S_Res,       /* Search results */
					 Second_Time ;


	Second_Time = False;
	Refresh = False;     /* Turn screen refresh off */
	Str1 = '';
	EStr1 = '';

Find_Match_Str:

	if(  (Cur_Char == '(')  ) {   /* Setup match for '(' */
		Right;
		if(  cur_char == '*'  ) {
			Str1 = '(*';
			EStr1 = '*)';
			S_Str = '{(@*}||{@*)}';
		} else {
			Left;
			Str1 = '(';
			EStr1 = ')';
			S_Str = '[()'']';
		}
		Direction = 1;
		GOTO Start_Match;
	}

	if(  (Cur_Char == ')')  ) {   /* Setup match for ')' */
		if(  (C_Col != 1)  ) {
			Left;
		}
		if(  cur_char == '*'  ) {
			Str1 = '*)';
			EStr1 = '(*';
			S_Str = '{(@*}||{@*)}';
		} else {
			Right;
			Str1 = ')';
			EStr1 = '(';
			S_Str = '[()'']';
		}
		Direction = 0;
		GOTO Start_Match;
	}

	if(  At_EOL  ) {     /* If we are at the end of a line the go to the first word */
		First_Word;
	}

	if(  (Cur_Char == ' ') |
		 (Cur_Char == '|9') |
		 (Cur_Char == '|255')  ) {      /* If we are on a blank space then find a word */
		Word_Right;
	}

	S_Str = '['']||{%||[|9 ;)]{END}||{IF}||{WHILE}||{FOR}||{CASE}||{LOOP}||{WITH}||{BEGIN}$||[|9 ;.(]}||{(@*}||{@*)}';

	T_Str = Caps( Get_Word(';. |9|255') );  /* Get the current word */

	if(  (T_Str == 'IF') | (T_Str == 'WHILE') | (T_Str == 'FOR') | (T_Str == 'CASE') |
		 (T_STR == 'LOOP') | (T_Str == 'WITH') | (T_Str == 'BEGIN') |
		 (T_Str == 'ELSE') | (T_Str == 'ELSIF')  ) {
		Str1 = 'IF WHILE FOR CASE LOOP WITH BEGIN';
		EStr1 = 'END';
		Direction = 1;
		GOTO Start_Match;
	}

	if(  T_Str == 'END'  ) {
		Str1 = 'END';
		Estr1 = 'IF WHILE FOR CASE LOOP WITH BEGIN';
		Direction = 0;
		Word_Left;
		Left;
		GOTO Start_Match;
	}

	S_Str = '['']||{%||[|9 ;)]{REPEAT}||{UNTIL}$||[|9 ;.(]}||{(@*}||{@*)}';

	if(  T_Str == 'REPEAT'  ) {
		Str1 = 'REPEAT';
		Estr1 = 'UNTIL';
		Direction = 1;
		GOTO Start_Match;
	}

	if(  T_Str == 'UNTIL'  ) {
		Str1 = 'UNTIL';
		Estr1 = 'REPEAT';
		Direction = 0;
		Word_Left;
		Left;
		GOTO Start_Match;
	}


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

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

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

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

	if(  S_Res == 0  ) {   /* If last search result was false then exit */
		GOTO Error_Exit;
	}

	if(  B_Count == 0  ) { /* If match count is 0 then success */
		GOTO Found_Exit;
	}

	if(  Direction == 1  ) { /* Perform search based on direction */
		Right;
		while(  NOT( At_EOL) & (Cur_CHar == '|255')  ) {
			Right;
		}
		S_Res = Search_Fwd(S_Str,0);
	} else {
		Left;
		while(  (Cur_CHar == '|255') |
					(Cur_Char == '|9')  ) {
			Left;
		}
		S_Res = Search_Bwd(S_Str,0);
	}

	if(  S_Res == 0  ) {   /* If search failed then exit */
		GOTO Macro_Exit;
	}

	FStr = Found_Str;

	if(  Length(FStr) > 2  ) {
		if(  XPOS(Copy(FStr,1,1),'|9 ;()',1)   ) {  /* If the first char is a space or a ; */
			FStr = Copy(FStr,2,20);         /*   then eliminate it */
		}
																			/* If it ended in a space, ; or . then */
		if(  XPOS(Copy(FStr,Length(FStr),1),'|9 ;.()',1)  ) {
			FStr = Copy(FStr,1,Length(FStr) - 1);  /* eliminate that char */
		}
	}

															/* If we found the first match string then */
	if(  XPOS(FStr,STR1,1)  ) {
		++B_Count;   /* Inc the match count */
		GOTO Match_Loop;
	}

	if(  XPOS(FStr,ESTR1,1)  ) {          /* If we found the second match string then */
		--B_Count;    /*   decrement the match count */
		GOTO Match_Loop;
	}

	if(  Fstr == '(*'  ) {
		if(  Direction == 1  ) {
			S_Res = Search_Fwd('@*)',0);
			RIGHT;
		}
		Goto Match_Loop;
	}

	if(  Fstr == '*)'  ) {
		if(  Direction == 0  ) {
			S_Res = Search_Bwd('(@*',0);
		} else {
			RIGHT;
		}
		Goto Match_Loop;
	}

	if(  FStr == ''''''  ) {        /* If we found two single quotes the skip it */
		if(  Direction == 1  ) {
			RIGHT;
		} else {
			LEFT;
		}
		GOTO Match_Loop;
	}

															/* If we found a single quote then match it */
	if(  FStr == ''''  ) {

		Quote_Loop:

			if(  Direction == 1  ) {
				RIGHT;
			} else {
				LEFT;
			}
			if(  Direction == 1  ) {
				S_Res = Search_Fwd('''',0);
			} else {
				S_Res = Search_Bwd('''',0);
			}
			if(  S_Res == 0  ) {
				GOTO Macro_Exit;
			}
			FStr = Found_Str;
			if(  FStr == ''''''  ) {
				GOTO Quote_Loop;
			}
			GOTO Match_Loop;

	}

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

Found_Exit:     /* Go here for successfull match */
	if(  EStr1 == '*)'  ) {
		right;
	}
	Make_Message('Match Found');
Macro_Exit:
	Refresh = True;
	Redraw;
}
