//+++keyword+++ "@(#)%v %n, %f, %w"
// "@(#)3 CMPERROR.S, 05-Oct-95,23:42:48, LDH"

macro_file CMPERROR;

#define _UseStdDlgs_

#ifdef _Debug_
	#include DBUG.SH
	#include SPRINTF.SH
#endif

#ifdef _UseStdDlgs_
	#include STDDLGS.SH
#endif

#include CMPERROR.SH
#include WINDOWS.SH
#include METOOLS.SH
#include REGEXP.SH
#include MEWLIB.SH

// Internal functions
prototype CMPERROR {
	void _ProcessXStr( str &FName, int &Line, str &ColStr, str &Msg );
	int  _ProcessError( int Backward );
}

void CmpError( int Backward = Parse_Int( "/B=", MParm_Str ) ) Trans2 {
/******************************************************************************
															 Multi-Edit Macro
															 23-Jun-95  12:15

	Function: Finds the next error in the MEERR.TMP window generated by the last
						compile.

							Copyright (C) 1992-95 by American Cybernectic, Inc.
********************************************************************( ldh )***/

	str MStr[ 128 ];
	str File_Str[ 128 ] = g_LastCompiledWindow;
	str Comp_Str[ 30] = g_LastComp;
	str ErrMac = g_LastErrMac;
	str ErrFndRE = g_LastFndRE;
	str ErrRepRE = g_LastRepRE;
	str	E_Word;
	str	L_Str[ 128 ];
	str	SvWord[ 128 ];
	str	Nxt[ 128 ];
	str	T_Str;  // note: last 3 for alsys

	int Temp_Window = Window_Id;
	int Jx;
	int ECol;
	int El;
	int Tc;
	int Tl;
	int Offset;
	int VRet;
	int SCol;
	int DCnt;  // note: last 3 for alsys

	int TRefresh = Refresh;
	int TIgnore_Case = Ignore_Case;
	int TReg_Exp_Stat = Reg_Exp_Stat;

	Refresh = False;
	Ignore_Case = True;
	Reg_Exp_Stat = True;

	Error_Level = 0;

	// Find the error window
	Jx = 0;
	while ( ( Jx < Window_Count ) &&
      ( Caps( Truncate_Path( File_Name ) ) != "MEERR.TMP" ) ) {
		++Jx;
		Switch_Window( Cur_Window + 1 );
	}
	// If not found then exit
  if ( Caps( Truncate_Path( File_Name ) ) != "MEERR.TMP" ) {
		MStr = "No error file loaded.";
		Switch_Win_Id( Temp_Window );
		goto Exit2;
	}
	if ( C_Line == 1 ) {
		g_LastErrDir = -1;
	}
	if ( Svl( ErrFndRE ) && Svl( ErrRepRE ) ) {
		// Run regular expression process macro
		_ProcessError( Backward );
	}
	else if ( Backward ) {
		Return_Str = "Find previous error not supported for this compiler type";
		Switch_Win_Id( Temp_Window );
	}
	else if ( Svl( ErrMac ) != 0 ) {
		// Run specified error macro
		if ( XPos( "<", ErrMac, 1 ) != 0 ) {
			ErrMac = TranslateCmdLine( ErrMac, File_Str );
		}
		Rm( ErrMac );
	}
	else {
		goto NNM;
	}
	switch ( Return_Int ) {
		case rc_NoMoreErrors :
				MStr = "No more errors.";
				Switch_Win_Id( Temp_Window );
				break;

		case rc_NoErrors :
				MStr = "No errors.";
				Switch_Win_Id( Temp_Window );
				break;

		case rc_DisplayError :
				Rm( "MEERROR^Beeps /C=1" );

		case rc_DENoBeep :
				MStr = Return_Str;
				break;

		case rc_ProblemParsing :
				MStr = "Problem parsing error file.";
				Rm( "MEERROR^Beeps /C=2" );
				break;

		case rc_CantFind :
				MStr = "Can't find " + Return_Str;
				Rm( "MEERROR^Beeps /C=2" );
				break;
	}
	goto Final_Exit;

NNM:
	MStr = "";
	ECol = 1;
	EL = 1;
	Offset = 0;  // This variable decides whether or not ECol is an absolute
							 //	column position, or an offset from the first word

	// SPECIAL PROCESSING FOR ALSYS ADA VERSION 4.X
	if ( (COMP_STR == 'ALSYS ADA 4.X') ) {
		File_Str = Global_Str('last_compiled_window'); //  in main file
		if ( SEARCH_FWD('[0-9]   *@*',0) )
		{
			L_STR = GET_LINE;
			L_STR = COPY(L_STR,1,2);
			NXT = REMOVE_SPACE(L_STR);
			DCNT = 0;
			UP;
			UP;
RETRY4:
			L_STR = GET_LINE;
			L_STR = COPY(L_STR,1,9);
			MStr =  REMOVE_SPACE(L_STR);
			VRET = VAL(EL,MStr);
			if ( VRET != 0 )
			{
				UP;
				DCNT = DCNT + 1;
				GOTO RETRY4;
			}
			DOWN;
			scol = 0;
			if ( search_fwd(nxt,1) )
			{
				up;
				svword = get_word(' :=()-+;');
				down;
				scol = 1;
			}
			DOWN;
			while(  DCNT > 0 )
			{
				DOWN;
				DCNT = DCNT - 1;
			}
			MStr = GET_LINE;
			GOTO_COL(80);
			GOTO DISPLAY_ERROR_ADA;
		}
		GOTO NO_MORE_ERRORS;
	}  																		// end alsys 4.x
	// SPECIAL PROCESSING FOR ALSYS ADA
	else if ( (COMP_STR == 'ALSYS ADA') ) {
		File_Str = Global_Str('last_compiled_window'); //  in main file
		if ( SEARCH_FWD('[0-9] : *@*',0) )
		{
			DCNT = 0;
			UP;
			UP;
			UP;
RETRY:
			L_STR = GET_LINE;
			L_STR = COPY(L_STR,1,7);
			MStr =  REMOVE_SPACE(L_STR);
			VRET = VAL(EL,MStr);
			if ( VRET != 0 )
			{
				 UP;
				 DCNT = DCNT + 1;
				 GOTO RETRY;
			}
			DOWN;
			scol = 0;
			if ( search_fwd('^',1) )
			{
				up;
				svword = get_word(' :=()-+;');
				down;
				scol = 1;
			}
			DOWN;
			DOWN;
			while(  DCNT > 0 )
			{
				DOWN;
				DCNT = DCNT - 1;
			}
			MStr = GET_LINE;
			GOTO_COL(80);
			GOTO DISPLAY_ERROR_ADA;
		}
			GOTO NO_MORE_ERRORS;
	}  																		//  end alsys
	// SPECIAL PROCESSING FOR CLARION
	else if ( (comp_str == 'CLARION') ) {
		File_Str = Global_Str('last_compiled_window'); //  in main file
		// WE SEE IF WE HAVE FINISHED
		if ( AT_EOF == 1 )
			GOTO NO_MORE_ERRORS;
		//  NEXT WE SEE IF THIS IS A NEW FILE
		if ( SEARCH_FWD('Compiled',1) )
		{
			DOWN;
			VRET = SEARCH_FWD('IN',1);
			RIGHT;
			RIGHT;
			RIGHT;
			MStr = GET_WORD('.'); //  THIS IS THE FILE THAT PRODUCED ERRORS
			L_STR = CAPS(GET_PATH(FILE_STR));
			File_Str = L_STR+ MStr + '.CLA';
			DOWN;
			FIRST_WORD;
		}
		//  NOW WE ARE AT AN ERROR LINE
		MStr = GET_WORD('@');
		RIGHT;
		MStr = GET_WORD('/');
		VRET = VAL(EL,MStr);
		RIGHT;
		MStr = GET_WORD(':');
		VRET = VAL( ECol, MStr );
		RIGHT;
		MStr = GET_WORD('~');  // TO END OF LINE
		DOWN;
		FIRST_WORD;   // PREPARE FOR NEXT ERROR
		GOTO DISPLAY_ERROR_ADA;
	}  																		// END CLARION
	else if ( (Comp_Str == 'LOGITECH MODULA-2') ) {
		File_Str = Global_Str('last_compiled_window'); //  in main file
		Tc = C_Col;
		Tl = C_Line;
		Tof;
		if ( Search_Fwd('---- error',0) )
		{
			Goto_Col(Tc);
			Goto_Line(Tl);
M2_LOGI_AGAIN:
			if ( Search_Fwd('^',0) )
			{
				Tc = C_Col;
				Tl = C_Line;
				ECol = Tc - 6;
				Goto_Col(2);
				MStr = Get_Word(' ');
				if ( Xpos('*****',MStr,1) != 0 )
				{
					Goto_Col(2);
					while(  (Cur_Char == '*') )
						Up;
					Left;
					while(  (Cur_Char == ' ') )
						Right;
					MStr = Get_Word(' ');
					Jx = Val(El,MStr);
					if ( Jx != 0 )
						Goto ERROR_EXIT;
					Goto_Line(Tl);
					Goto_Col(Tc);
					Right;
					Right;
					MStr = Get_Word(', ');
					if ( Search_Fwd(MStr,0) )
						MStr = Get_Line;
					else
						Goto ERROR_EXIT;
					Goto_Line(Tl);
					Eol;
					Goto DISPLAY_ERROR;
				}
				else
				{
					Down;
					Goto_Col(1);
					Goto M2_LOGI_AGAIN;
				}
			}
			else
				GOTO NO_MORE_ERRORS;
		}
		else
		{
			Ignore_Case = False;
			if ( Search_Fwd('{----}||{===>}',0) )
			{
				Ignore_Case = True;
				MStr = '';
				Tof;
				Goto DISPLAY_ER3;
			}
			else
			{
				Ignore_Case = True;
				Goto NO_ERRORS;
			}
		}
	}
	else if ( (Comp_Str == 'JPI MODULA-2') ) {
		Tc = C_Col;
		Tl = C_Line;
		Goto_Col(1);
		if ( Search_Fwd('No Errors',0) )
		{
			Goto_Line(Tl);
			Goto_Col(Tc);
			Goto NO_ERRORS;
		}
		else
		{
			Goto_Line(Tl);
			Goto_Col(Tc);
M2_JPI_AGAIN:
			if ( Search_Fwd('(',0) )
			{
				if ( C_Col != 1 )
				{
					Right;
					Goto M2_JPI_AGAIN;
				}
				Right;
				File_Str = Get_Word(' ');
				while(  Cur_Char == ' ' )
					Right;
				MStr = Get_Word(',');
				if ( Val(El,MStr) != 0 )
					Goto ERROR_EXIT;
				Right;
				MStr = Get_Word(')');
				if ( Val(ECol,MStr) != 0 )
					Goto ERROR_EXIT;
				Goto DISPLAY_ERROR;
			}
			else
				Goto NO_MORE_ERRORS;
		}
	}
	else if ( (Comp_Str=='ZORTECH C++')||('ZORTECH C++ 2.0'==Comp_Str) ) {
		if ( search_fwd('%"?+", line [0-9]', 0 ) ) {
			goto_col(1);
			right;
			file_str = Caps(get_word('"'));
			MStr = get_word('0123456789');
			MStr = remove_space( get_word(' ') );
			if ( Val(EL,MStr) != 0 ) {
				GOTO error_exit;
			}
			up;
			goto_col(1);
			if ( search_fwd('^',1) ) {
				ECol = c_col;
			}
			down;
			eol;
			goto display_error;
		}
	}
	else if( (COMP_STR == 'INTEL PLM-86') ||
			(COMP_STR == 'INTEL ASM-86') ||
			(COMP_STR == 'INTEL IC-86') ) {

		if ( Search_FWD('FATAL ',0) ) {
			RM('MEERROR^Beeps /C=2');
			MStr = "FATAL COMPILER ERROR";
			goto Exit2;
		}

		if ( Search_FWD('I/O ERROR',0) ) {
			RM('MEERROR^Beeps /C=2');
			MStr = "COMPILER I/O ERROR";
			goto Exit2;
		}

		if ( SEARCH_FWD('{@*@*@* ERROR}||{@*@*@* WARNING}',0) ) {
			goto_col(1);
			if ( (Comp_Str == 'INTEL PLM-86') ) {
				if ( Search_Fwd('{(}',1) ) {
					Right;
					MStr = Get_Word(',');
					if ( POS(')',MStr) == 0 ) {
						File_str = MStr;   //  error is in an include file
						if ( Search_Fwd('{LINE }',1) == 0 ) {
							goto error_no_line;
						}
					} else {
						if ( Search_Bwd('{LINE }',1) == 0 ) {
							goto error_no_line;
						}
						File_Str = Global_Str('last_compiled_window'); //  in main file
					}
					Word_Right;
					MStr = Get_Word(')');
					if ( Val(EL,MStr) != 0 ) {
						goto error_exit;
					}
				} else {
					goto error_no_line;
				}
			}

			if ( (Comp_Str == 'INTEL ASM-86') ) {
				File_Str = Global_Str('Last_Compiled_Window');
				if ( Search_Fwd('{IN }',1) ) {
					Word_Right;
					MStr = Get_Word(',');
					if ( Val(EL,MStr) != 0 ) {
						goto Error_Exit;
					}
				}
				else {
					goto Error_No_Line;
				}
			}

			if ( (Comp_Str == 'INTEL IC-86') ) {
				if ( Search_Fwd('{LINE }',1) ) {
					Word_Right;
					MStr = Get_Word(' ');
					if ( Val(EL,MStr) != 0 ) {
						goto Error_Exit;
					}
					Word_Right;
					Word_Right;
					File_Str = Get_Word(' ');
					File_Str = Str_Del(File_Str, Length(File_Str), 1);
				}
				else {
					goto Error_No_Line;
				}
			}

			//  it drops down to here when a true error
			goto Display_Error;
		}
		goto Display_Line;
	}
	// Intermetrics support added 02-14-90 10:42am
	else if ( COMP_STR == 'INTERMETRICS C' ) {
		if ( AT_EOF )
			goto no_more_errors;
		if ( cur_char != ':' )
			goto no_more_errors;
		GOTO_COL(2);
		jx = search_fwd(':',1);
		right;
		File_Str = Caps(Get_Word('.'));
		File_Str = File_Str + Caps(Get_word(':'));
		right;
		MStr = Caps(Get_Word(':'));

		if ( Val(EL,MStr) != 0 )
			Goto Error_Exit;

		word_right;
		t_Str = Get_Word('');
		MStr = file_str + ' ' + '(' + str(el) + ')' + ' ' + t_str;
		down;
		goto_col(1);   // for eof check to be reliable you must be at beg of line
		call find_file_window;
		goto_line(el);
		goto display_er3;
	}
	// TI370 ASSEMBLER support
	else if ( Comp_Str == "TI370 ASSEMBLER" ) {
		if ( at_eof == 1 ) {
			goto No_More_Errors;
		}
		if ( cur_char != '[' ) {
			goto No_More_Errors;
		}
		goto_col(2);
		File_Str = Caps(get_word(' ]'));
		MStr = get_word('0123456789');
		MStr = caps(get_word(' '));
		if ( val(EL, MStr) != 0 )
			goto error_exit;
		right;
		right;
		right;
		t_str = get_word('');
		MStr = file_str + ' ' + '(' + str(el) + ')' + ' ' + t_str;
		down;
		goto_col(1);
		call find_file_window;
		goto_line(el);
		goto display_er3;
	}

	//  all other compilers
	// Search for error or warning messages
Do_Again:
	if ( Search_FWD('{ERROR[~S]}||{WARNING[~S]}||{NOT ENOUGH MEMORY}||{ABORTED}||{TOO BIG}',0) )
	{
		tc = c_col;
		Goto_Col(1);

		if ( Search_FWD('[0-9] Warning Errors',1) ) {
			EOL;
			goto Do_AGAIN;
		}

		Goto_Col(1);
		if ( Caps(GET_WORD(' :(')) == 'LINK' ) {
			Goto_Col(1);
			MStr = Get_Word('');
			Goto DISPLAY_ER3;
		}
		Goto_Col(1);

		if ( (COMP_STR == 'LATTICE C 3.0') ) {
			File_Str = Caps(Remove_Space(Get_Word(' ')));
			Right;
			MStr = Remove_Space(Get_Word(' '));
			if ( Val(EL,MStr) != 0 )
				Goto Error_Exit;
		}
		else if ( (COMP_STR == 'AZTEC C') ) {
			goto_col(tC);
			if ( Search_BWD(':',1) ) {
				left;
				if ( Search_BWD(':',1) ) {
					ECol = C_Col;
					if ( Search_BWD('/',1) ) {
						File_Str = Copy(Get_Line,1,C_Col - 1) + '\' +
								Copy(Get_Line, C_Col + 1, ECol - c_col - 1);
					}
					else {
						File_Str = Copy(Get_Line,1,ECol - 1);

					}
					File_Str = Fexpand(File_Str);
					goto_col(ECol);
					right;
					MStr = get_word(':');
					if ( Val(EL,MStr) != 0 ) {
						Goto Error_Exit;
					}
					Up;
					goto_col(1);
					if ( search_fwd('^',1) ) {
						ECol = c_col;
					}
					down;
					goto display_error;
				}
			}
		}
		else if ( (COMP_STR == 'RBASE_5') ) {
			Goto_Col(1);
			File_Str = Caps(Remove_Space(Get_Word(' ')));
			Right; Right;
			MStr = Remove_Space(Get_Word(')'));
			Down;
			if ( Val(EL,MStr) != 0 )
				Goto Error_Exit;
		}

Display_Error:
		if ( Comp_Str != "LOGITECH MODULA-2" ) {
				Goto_Col( 1 );
				MStr = Get_Word( "" );
		}

Display_Er1:
		call Find_File_Window;

Display_Er2:
		while ( C_Row < ( ( Win_Y2 - Win_Y1 ) / 2 ) ) {
			Down;
		}
		Goto_Line( El - ( Format_Stat != 0 ) );

		if ( Offset ) {
			First_Word;
			ECol += C_Col;
		}
		else {
			Comp_Str = Get_Line( );
			Jx = 1;
			// need to figure out the actual column number with tab expansion included
			Crunch_Tabs( Comp_Str, Jx );
			Expand_Tabs( Comp_Str, ECol );
		}
		Goto_Col( ECol );

Display_Er3:
		Rm( "MEERROR^Beeps /C=1" );
		goto Exit2;
	}


Display_Line:
	Eof;
	Left;
	MStr = Get_Line( );
	Switch_Win_Id( Temp_Window );
	goto Exit2;

//  for alsys
Display_Error_Ada:
	CALL FIND_FILE_WINDOW;
	if ( VRET == 0 ) {
		GOTO_LINE(EL);
		if ( SCOL == 1 ) {
			FIRST_WORD;
		reg_exp_stat = false;
		SCOL = SEARCH_FWD(SVWORD,1);
		reg_exp_stat = true;
		}
	}
	goto Exit2;
 //  end alsys


No_More_Errors:
	MStr = "No more errors.";
	Switch_Win_Id( Temp_Window );
	goto Exit2;

No_Errors:
	MStr = "No Errors.";
	switch_win_id(Temp_Window);
	goto exit2;

Error_Exit:
	MStr = "Problem parsing error file.";
	goto Exit2;

Error_No_Line:
	MStr = "Error.";
	RM('MEERROR^Beeps /C=1');
	goto Exit2;

Exit2:
	goto Final_Exit;

//  ========================================================================
Find_File_Window:
	Jx = 0;
	while ( ( Jx <= Window_Count ) &&
			( Caps( Truncate_Path( File_Name ) ) != Caps( Truncate_Path( File_Str ) ) ) ) {
		++Jx;
		Switch_Window( Jx );
	}
	if ( ( Jx >= Window_Count ) &&
			( Caps( Truncate_Path( File_Name ) ) != Caps( Truncate_Path( File_Str ) ) ) ) {
		Switch_Window( Window_Count );
		Create_Window;
		Load_File( File_Str );
		Rm( "SetWindowNames" );
		Rm( "ExtSetup" );
	}
	Window_Attr = 0;
	ret;

Final_Exit:

 	AutoArrangErrSrc( MStr );
	Right;
	Left;
	Ignore_Case = TIgnore_Case;
	Reg_Exp_Stat = TReg_Exp_Stat;
	Refresh = TRefresh;
	Redraw;

}  // CmpError

int ErrFindError(
				str FName = Parse_Str( "/F=", MParm_Str ),
				int Line = Parse_Int( "/L=", MParm_Str ),
				int Col = Parse_Int( "/C=", MParm_Str ),
				int Offset = Parse_Int( "/OF=", MParm_Str ),
				int NoLoad = Parse_Int( "/NL=", MParm_Str )
		)
{
/******************************************************************************
															 Multi-Edit Macro
															 23-Jun-95  12:15

	Function: Brings up the specified file, and moves the cursor to the passed
						line and column.

  Entry   : str FName		-	Filename 		(/F=)
						int Line		- Line number (/L=)
						int Col			- Column position (/C=)
						int Offset	- When True use Col as an offset from the first word of
													the line instead of as an absolute position. (/OF=1)

						int NoLoad	- When True no load if the file is not already loaded
													don't try to load

	Exit		: int ( Return_Int )
 							rc_DisplayError		- Success, Error located and cursor positioned
							rc_CantFind 			- Failure, File could not be found

							Copyright (C) 1992-95 by American Cybernectic, Inc.
********************************************************************( ldh )***/

	int Jx;
	int WinCenter;;

	str TStr;

	Error_Level = 0;
	Return_Str = FName;
	// Remove quotes
	if ( Copy( Return_Str, 1, 1 ) == "\"" ) {
		Return_Str = Copy( Return_Str, 2, Length( Return_Str ) - 2 );
	}
	Return_Str = FExpand( Return_Str );
	if ( Switch_File( Return_Str ) ) {
		Rm( "Select_Window /BM=1/VIS=1" );
	}
	else {
		Error_Level = True;
		if ( Parse_Int( "/NL=", MParm_Str ) == 0 ) {
			Rm( "LdFiles /CW=1/NW=1" );
		}
		if ( Error_Level ) {
			Return_Int = rc_CantFind;
			goto Exit;
		}
	}
	if ( Line ) {
		// Center line in window
		WinCenter = Win_CHeight( ) / 2;
  	while ( C_Row > WinCenter ) {
    	Up;
		}
//		while ( !At_Eof && ( C_Row < WinCenter ) ) {
		while ( C_Row < WinCenter ) {
			Down;
		}
		Goto_Line( Line - ( Format_Stat != 0 ) );
	}
	if ( Offset )  {
		First_Word;
		Col += C_Col;
	}
//	else {
//		TStr = Get_Line( );
//		Jx = 1;
//		// we need to figure out the actual column number with tab expansion included
//		Crunch_Tabs( TStr, Jx );
//		Expand_Tabs( TStr, Col );
//	}
	Goto_Col( Col );
	Return_Int = rc_DisplayError;

Exit:
	return ( Return_Int );

}  // ErrFindError

#ifdef Windows
void AutoArrangErrSrc( str Msg ) Trans2 {
/******************************************************************************
															 Multi-Edit Macro
															 23-Jun-95  12:15

	Function: Supports the Auto-Arrange compiler error window feature

							Copyright (C) 1993-95 by American Cybernectic, Inc.
********************************************************************( ldh )***/


	int Jx;
  int Cur_Win_Id     = Window_Id;
	int Cur_Screen_Num = Screen_Num;
  int Err_Win_Id     = 0;
  int Save_Refresh   = Refresh;

	str T_CLine;

	struct TRECT Cur_Window_Rect,
							 Main_Client_Rect,
							 Cur_Client_Rect;

	int Cur_Window_Width;
	int Cur_Window_Height;
	int Cur_Window_Left;
	int Cur_Window_Top;
	int Y_Offset;
	int X_Offset;
	int Non_Client_Height;
	int Err_Window_Top;
	int Err_Height;
	int Num_Lines;
	int TFont;
	int Xdc;
	int Scroll_Bar_Height = GetSystemMetrics( SM_CYHSCROLL );
	int Was_Maximized = IsZoomed( Window_Handle );
  int DoRedraw = False;

	struct TTextMetric xTextMetrics;
	struct TWINDOWPLACEMENT twp;
	struct tpoint tp;

  Refresh = False;
	// *** Find the error window and resize others
	Jx = 0;
	while ( ( Jx < Window_Count ) &&
      ( Caps( Truncate_Path( File_Name ) ) != "MEERR.TMP" ) ) {
		++Jx;
		Switch_Window( Cur_Window + 1 );
	}
	// *** If not found then exit
  if ( Caps( Truncate_Path( File_Name ) ) != "MEERR.TMP" ) {
		goto Exit;
	}
	Make_Window_Visible( 1 );
	Screen_Num = Cur_Screen_Num;

	if ( ( 0 == Global_Int( "!AutoArrangErrSrc" ) ) || ( Window_Id == Cur_Win_Id ) ) {
		goto SkipAttach;
	}
	Err_Win_Id = Window_Id;                   //  Save error window ID

//  SendMessage( Client_Handle, WM_SETREDRAW, 0, 0 );
  DoRedraw = True;

	// check for out of range values of ~MEERR_HEIGHT
	if ( Global_int( "~MEERR_HEIGHT" ) < 2 ) {
		Set_Global_Int( "~MEERR_HEIGHT", 2 );
	}
	if (Global_int( "~MEERR_HEIGHT" ) > ( Max_Window_Row - Min_Window_Row - 4 ) ) {
		Set_Global_Int( "~MEERR_HEIGHT", Max_Window_Row - Min_Window_Row - 4 );
	}

	Num_Lines = Global_int( "~MEERR_HEIGHT" );

	New_Screen;
	// size error window at the bottom of the client area
	GetClientRect( Window_Handle, &Cur_Client_Rect );
	GetWindowRect( Window_Handle, &Cur_Window_Rect );
	Cur_Window_Width = Cur_Window_Rect.Right - Cur_Window_Rect.Left;
	Cur_Window_Height = Cur_Window_Rect.Bottom - Cur_Window_Rect.Top;

	cur_window_left = cur_window_rect.left;
	cur_window_top = cur_window_rect.top;

  Get_Window_Font_Handle( 0, TFont, XDc, XDc, XDc);

	xdc = GetDc( window_handle );
	SelectObject( xdc, tfont );
	GetTextMetrics(xDC, &xTextMetrics);
	ReleaseDC(window_handle, xDC);

	GetClientRect(client_handle,&main_client_rect);

	switch_win_id(err_win_id);
  // get the difference between client height and window height
  non_client_height = ( (cur_window_rect.bottom - cur_window_rect.top) -
      (cur_client_rect.bottom - cur_client_rect.top) );

	err_height = xTextMetrics.tmHeight * (num_lines);
  err_window_top = (main_client_rect.bottom - main_client_rect.top) -
      err_height - non_client_height - scroll_bar_height;
	Twp.Length = 22;
	if (GetWindowPlacement(window_handle, &twp)) {
		twp.rcNormPos_top    = err_window_top;
		twp.rcNormPos_bottom = main_client_rect.bottom;
		twp.rcNormPos_left = 0;
		twp.rcNormPos_right = main_client_rect.right;
		SetWindowPlacement(window_handle, &twp);
	}
	for ( Jx = 1; Jx <= Window_Count; ++Jx ) {
		Switch_Window( Jx );
		if ( Window_Id != Err_Win_Id ) {
			if ( ( !( Window_Attr & 0x81 ) ) && ( IsWindow( Window_Handle ) ))
				if ( !IsIconic( Window_Handle) )
				{
					if ( GetWindowPlacement( Window_Handle, &Twp ) ) {
						if ( Twp.rcNormPos_Bottom > Err_Window_Top ) {
							Twp.rcNormPos_Bottom = Err_Window_Top;
							SetWindowPlacement( Window_Handle, &Twp );
						}
					}
				}
		}
	}
//  Refresh = True;
//	Switch_Win_Id(Cur_Win_Id);

SkipAttach:
Exit:
	Switch_Win_Id( Cur_Win_Id );
	Refresh = Save_Refresh;
  if ( DoRedraw ) {
//    SendMessage( Client_Handle, WM_SETREDRAW, 1, 0 );
//    RedrawWindow( Client_Handle, 0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
//        RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
    RedrawWindow( Client_Handle, 0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
        RDW_FRAME );
  }
	if ( "" != Msg ) {
		Make_Message( Msg );
	}
}  // AutoArrangErrSrc
#else

void AutoArrangErrSrc( str Msg ) Trans2 {
/******************************************************************************
															 Multi-Edit Macro
															 23-Jun-95  12:15

	Function: Supports the Auto-Arrange compiler error window feature

							Copyright (C) 1993-95 by American Cybernectic, Inc.
********************************************************************( ldh )***/

	int Jx;
	int Cur_Win_Id = Window_Id;
	int Err_Win_Id;
	int Save_Refresh = Refresh;

	str T_CLine;

	Refresh = False;

	// *** Find the error window
	Jx = 0;
	while ( ( Jx < Window_Count ) &&
			( Caps( Truncate_Path( File_Name ) ) != ( User_Id + "MEERR.TMP" ) ) )
	{
		Jx = Jx + 1;
		Switch_Window( Cur_Window + 1 );
	}

	// *** If not found then exit
	if ( Caps( Truncate_Path( File_Name ) ) != ( User_Id + "MEERR.TMP" ) ) {
		goto Exit;
	}
	if ( ( 0 == Global_Int( "!AutoArrangErrSrc" ) ) || ( Window_Id == Cur_Win_Id ) ) {
		goto SkipAttach;
	}
/*
	if ( 0 == L_Color )
		L_Color=(((T_Color&0x7)<<4)|((T_Color&0x70)>>4));
*/
	Err_Win_Id = Window_Id;                   //  Save error window ID

	// *** Unattach error window from the current window it is attached to
	Jx = Global_Int( "~MEERR_SPLIT_ID" );
	Set_Global_Int( "~MEERR_SPLIT_ID", 0 );

//  RM('Window^DelWin /NODEL=1');
	DelWin( 1, 0, 0);

	Set_Global_Int( "~MEERR_SPLIT_ID", Jx );

	if ( Global_Str('!WINZOOM#' + Str(Window_Id)) != '' ) {
		Set_Global_Str('!WINZOOM#' + str(window_id), ''); //  Set zoom status manually
	}
	// *** Switch back to current source window and attach the error window to it
	Switch_Win_id(Cur_Win_Id);
	if ( Window_Attr & 0x40 ) {
		Rm( "WINDOW^Zoom");
	}
	Window_Attr = Window_Attr & 0xFFFE;
	Set_Global_Int( "~MEERR_SPLIT_ID", Cur_Win_Id );

	// check for out of range values of ~MEERR_HEIGHT
	if ( Global_int( "~MEERR_HEIGHT" ) < 2 ) {
		Set_Global_Int( "~MEERR_HEIGHT", 2 );
	}
	if ( Global_int( "~MEERR_HEIGHT" ) > ( Max_Window_Row - Min_Window_Row - 4 ) ) {
		Set_Global_Int( "~MEERR_HEIGHT", Max_Window_Row - Min_Window_Row - 4 );
	}

	Rm( "WINDOW^SplitWin /DIR=Down/LN#=" + str( Global_int( "~MEERR_HEIGHT" ) + 1 ) +
			"/ID=" + Str( Err_Win_Id ) );

	Refresh = True;
	Switch_Win_Id( Cur_Win_Id );
	New_Screen;
	Refresh = False;

SkipAttach:
Exit:
	Switch_Win_Id( Cur_Win_Id );
	Refresh = Save_Refresh;
	if ( "" != Msg ) {
		Make_Message( Msg );
	}

}  // AutoArrangErrSrc
#endif

void _ProcessXStr( str &FName, int &Line, str &ColStr, str &Msg ) Trans2 {
/******************************************************************************
															 Multi-Edit Macro
															 21-Jun-95  00:11

  Function: Search for additional error information based upon contents of Xtra
 						and update specified variables.

  Entry   : str FName		- Filename
						int Line		- Line number
						str ColStr	- Column number or position string
						str Msg			- Error Message

  Exit    : None.				- Variables updated

  Globals : str g_LastErrXtra	- Xtra string

 	Notes		: Xtra fields
							/X=					- Letter of string to search for
								F						- File Name
								L           - Line number
								C           - Column number or postion
								M           - Message
								M+					- Append to Message

							/xP=				- Direction of search ( x = one of the /X= letters )
								D#					- Search forward # lines staring line down
								U#          - Search backward # lines starting line up
								F#          - Search forward # lines
								B#          - Search backward # lines
															# = 0 or blank to search to top or bottom of file

							/xS=				- Search pattern ( x = one of the /X= letters )

							/xR=				- Replace pattern ( x = one of the /X= letters )
														Note: use //x= in this string

							 Copyright (C) 1995 by American Cybernectic, Inc.
********************************************************************( ldh )***/

	str Xtra = g_LastErrXtra;
	str XStr = Parse_Str( "/X=", Xtra );
	str FndStr;
	str RepStr;
	str Option;
	str TStr;

	int Update;
	int Jx;
	int Cnt;

	Mark_Pos;
	// Get filename
	Update = XPos( "F", XStr, 1 ) && ( Svl( FName ) == 0 );
	if ( Update ) {
		FndStr = Parse_Str( "/FS=", Xtra );
		RepStr = Parse_Str( "/FR=", Xtra );
		Option = Parse_Str( "/FP=", Xtra );
		call GetString;
		if ( Svl( TStr ) != 0 ) {
			FName = Parse_Str( "\xFE" + "F=", TStr );
		}
	}
	// Get line
	Update = XPos( "L", XStr, 1 ) && ( Line == 0 );
	if ( Update ) {
		if ( Jx = Parse_Int( "\xFE" + "L=", TStr ) ) {
			Line = Jx;
		}
		else {
			Goto_Mark;
			Mark_Pos;
			FndStr = Parse_Str( "/LS=", Xtra );
			RepStr = Parse_Str( "/LR=", Xtra );
			Option = Parse_Str( "/LP=", Xtra );
			call GetString;
			if ( Svl( TStr ) != 0 ) {
				Line = Parse_Int( "\xFE" + "L=", TStr );
			}
		}
	}
	// Get column
	Update = XPos( "C", XStr, 1 ) && ( Svl( ColStr ) == 0 );
	if ( Update ) {
		FndStr = Parse_Str( "\xFE" + "C=", TStr );
		if ( Svl( FndStr ) != 0 ) {
			ColStr = FndStr;
		}
		else {
			Goto_Mark;
			Mark_Pos;
			FndStr = Parse_Str( "/CS=", Xtra );
			RepStr = Parse_Str( "/CR=", Xtra );
			Option = Parse_Str( "/CP=", Xtra );
			call GetString;
			if ( Svl( TStr ) != 0 ) {
				ColStr = Parse_Str( "\xFE" + "C=", TStr );
			}
		}
	}
	// Get/append message
	Jx = XPos( "M+", XStr, 1 );
	Update = Jx || ( XPos( "M", XStr, 1 ) && ( Svl( Msg ) == 0 ) );
	if ( Update ) {
		FndStr = Parse_Str( "\xFE" + "M=", TStr );
		if ( Svl( FndStr ) != 0 ) {
			Msg = FndStr;
		}
		else {
			Goto_Mark;
			Mark_Pos;
			FndStr = Parse_Str( "/MS=", Xtra );
			RepStr = Parse_Str( "/MR=", Xtra );
			Option = Parse_Str( "/MP=", Xtra );
			call GetString;
			if ( Svl( TStr ) != 0 ) {
				Msg += Parse_Str( "\xFE" + "M=", TStr );
			}
		}
	}
	Goto_Mark;
	return ( );

GetString:
	TStr = "";
	if ( Svl( FndStr ) && Svl( RepStr ) ) {
		if ( ( Jx = Svl( Option ) ) > 1 ) {
			Val( Cnt, Copy( Option, 2, Jx - 1 ) );
			Option = Copy( Option, 1, 1 );
		}
		else {
			Cnt = 0;
		}
		if ( Jx = XPos( Option, "DFUB", 1 ) ) {
			FndStr = ReTranslate( FndStr, 1 );
			Update = _RegExp;
			switch ( Jx ) {
				case 1 :
					Down;
					Goto_Col( 1 );

				case 2 :
					break;

				case 3 :
					Up;
					Eol;

				case 4 :
					Update |= _Backward;
					break;
			}
			if ( Find_Text( FndStr, Cnt, Update ) ) {
				Jx = 1;
				while ( Jx = XPos( "/", RepStr, Jx ) ) {
					RepStr = Str_Ins( "\xFE", Str_Del( RepStr, Jx, 1 ), Jx );
				}
				Replace( RepStr );
				TStr = Get_Line( );
				Undo;
			}
		}
	}
	ret;

}  // _ProcessXStr

int _ProcessError( int Backward ) Trans2 {
/******************************************************************************
															 Multi-Edit Macro
															 20-Jun-95  17:10

  Function: Search for an Error message as defined by FndStr, parse out the
						specified information in RepStr and load the file containing the
						error and position the cursor to the error.

  Entry   :

  Exit    : int ( Return_Int )
							rc_DisplayMsg
							rc_CantFind

  Globals : str g_LastFndRE		- The error search regular expression
						str g_LastRepRE   - The replace regular expression
						str g_LastXtra    - The extra information

  Macros  : void _ProcessXtra

							 Copyright (C) 1995 by American Cybernectic, Inc.
********************************************************************( ldh )***/

	str FndStr = g_LastFndRE;
	str RepStr = g_LastRepRE;
	str Xtra = g_LastErrXtra;
	str FName[ 128];
	str Msg;
	str TStr;
	str ColStr;

	int Line;
	int Col;
	int TRefresh = Refresh;
	int TMessages = Messages;
	int Jx;
	int TEvent_Mode = Event_Mode;
	int Flags = _RegExp;

	Refresh = False;
	Messages = False;
	Return_Int = rc_NoMoreErrors;
	FndStr = ReTranslate( FndStr, 1 );
	// Disable error sync event
	Event_Mode &= 0xFFFF ^ event_Mode_Enhanced;
	if ( Backward ) {
		Flags |= _Backward;
	}
	if ( ( g_LastErrDir != -1 ) && ( g_LastErrDir != Backward ) ) {
		if ( Backward ) {
			Up;
			Eol;
		}
		else {
			Down;
			Eol;
		}
	}
	if ( Find_Text( FndStr, 0, Flags ) ) {
		// Translate / to 0xFE character in RepStr
		Jx = 1;
		while ( Jx = XPos( "/", RepStr, Jx ) ) {
			RepStr = Str_Ins( "\xFE", Str_Del( RepStr, Jx, 1 ), Jx );
		}
		Replace( RepStr );
		TStr = Get_Line( );
		Undo;
		if ( Backward ) {
			Up;
		}
		Eol;
		FName = Parse_Str( "\xFE" + "F=", TStr );
		Line = Parse_Int( "\xFE" + "L=", TStr );
		ColStr = Parse_Str( "\xFE" + "C=", TStr );
		Msg = Parse_Str( "\xFE" + "M=", TStr );
		if ( Svl( Xtra ) != 0 ) {
			_ProcessXStr( FName, Line, ColStr, Msg );
		}
		if ( Val( Col, ColStr ) != 0 ) {
			Jx = 1;
			// Adjust for tabs
			Crunch_Tabs( ColStr, Jx );
			Expand_Tabs( ColStr, Jx );
			Col = Svl( ColStr );
		}
		if ( Svl( FName ) == 0 ) {
			FName = g_LastCompiledWindow;
		}
		// Convert / to \ in FName
		Jx = 1;
		while ( Jx = XPos( "/", FName, Jx ) ) {
			FName = Str_Ins( "\\", Str_Del( FName, Jx, 1 ), Jx );
		}
		// Enable error sync event
		Event_Mode |= event_Mode_Enhanced;
		Return_Int = ErrFindError( FName, Line, Col, 0, 0 );
		if ( Return_Int == rc_CantFind ) {
			Return_Str = FName;
		}
		else {
			Return_Str = Msg;
		}
		g_LastErrDir = Backward;
	}
	else {
		Event_Mode = TEvent_Mode;
		g_LastErrDir = -1;
	}
	Messages = TMessages;
	Refresh = TRefresh;
	return ( Return_Int );

}  // _ProcessError

int _ErrFileEvent( int Message ) {
/******************************************************************************
															 Multi-Edit Macro
															 08-Aug-95  16:47

  Function:
  Entry   :
  Exit    :
  Globals :
  Macros  :

									Copyright (C) 1995 by Small Systems Support
********************************************************************( ldh )***/

	int Result = True;
	int TRefresh = Refresh;
	int OrgWin = Window_Id;
	int TMaxWin;

	str FndStr = g_LastFndRE;
	str MStr;

	switch ( Message & 0xFFFF ) {
		case event_Cursor_Line :
			Refresh = False;
			FndStr = ReTranslate( FndStr, 1 );
			Goto_Col( 1 );
			if ( Find_Text( FndStr, 1, _RegExp ) ) {
				TMaxWin = Global_Int( "@Maximize_Windows" );
				Set_Global_Int( "@Maximize_Windows", False );
				_ProcessError( False );
				switch ( Return_Int ) {
					case rc_NoMoreErrors :
						MStr = "No more errors.";
						break;

					case rc_NoErrors :
						MStr = "No errors.";
						break;

					case rc_DisplayError :
//						Rm( "MEERROR^Beeps /C=1" );

					case rc_DENoBeep :
						MStr = Return_Str;
						break;

					case rc_ProblemParsing :
						MStr = "Problem parsing error file.";
						Rm( "MEERROR^Beeps /C=2" );
						break;

					case rc_CantFind :
						MStr = "Can't find " + Return_Str;
						Rm( "MEERROR^Beeps /C=2" );
						break;
				}
 				AutoArrangErrSrc( MStr );
				Refresh = TRefresh;
				Right;
				Left;
				Switch_Win_Id( OrgWin );
//				Refresh = TRefresh;
				Set_Global_Int( "@Maximize_Windows", TMaxWin );
			}
			break;
	}
	return ( Result );

}  // ErrFileEvent
