/*	Title	All-Pro Diagnostics Editor */
/******************************************************************************/
/*				     DiagEdit				      */
/*			       All-pro Diagnostic Editor		      */
/*									      */
/* Module ...................... DIAGEDIT				      */
/* Title ....................... All-pro Diagnostic Editor		      */
/* Developing Engineer ......... Steven T. Harr 			      */
/* Company ..................... Logical Devices			      */
/* Revision Level .............. 1.00					      */
/* Date of Last Revision ....... 02-19-87				      */
/* Last Revision by ............ STH					      */
/* Developing System .......... IBM PC or compatible			      */
/* Target System .............. IBM PC or compatible			      */
/* Language ................... C					      */
/* Compiler ................... Manx Aztec C v3.20e			      */
/* Compiler Command(s) ........ cc Diagedit				      */
/*									      */
/* Interpreter ................ none					      */
/*									      */
/* Synopsis ................... This module contains the Diagnostic Editor    */
/*				commands and the Program execution control.   */
/*									      */
/* Revision History:							      */
/*  v1.00   01-29-87		Original version - STH			      */
/*									      */
/*									      */
/******************************************************************************/
/*	Subttl	Includes*/
#include <stdio.h>
#include <ctype.h>
#include "cmdfile.h"
#include "keybrd.h"
#include "diag2.h"
#include "diagedit.h"
#include "diagpars.h"

/*     Subttl  Defines*/
#define TRUE				1
#define FALSE				0

#define END_LIST    -1
#define MAX_ROWS    10
#define MAX_PROG_ROWS 30
#define COMMAND     1
#define PARAMETER   2
#define ON	    1
#define OFF	    0
#define TOP_ROW     3

#define COMMAND_WINDOW_COL 69

#define TAG_NULL		0x00
#define TAG_EMPTY		0xff

#define MAX_HELP_LINES		10
#define MAX_EDIT_BUFFER_SIZE	3000
#define LINE_BUFFER_ROW 	23
#define MAX_LINE_SIZE		64
#define CRLF			0
#define STX			2
#define ETX			3

/*	Subttl	externals */
extern func_print ();
extern func_null ();
extern func_help ();
extern compile_program ();
extern execute_program ();

extern int file_byte_ctr;
extern int file_eof_flag;
extern char *file_buffer_ptr;
extern char file_buffer [];
extern FILE *fptr, *fopen ();
extern char object_buffer [];
extern long crt_get_cur_pos ();
extern char key_word_table [MAX_KEY_WORDS] [MAX_COMMAND_SIZE];


/*	Subttl	Globals */

int file_loaded = FALSE;
int file_compiled = FALSE;
int new_file_flag;
int top_line_displayed;
int last_line;
int last_char;
unsigned char edit_buffer [MAX_EDIT_BUFFER_SIZE];
unsigned char line_buffer [MAX_LINE_SIZE + 1];
unsigned char last_line_buffer [MAX_LINE_SIZE];
char user_file_name [64] = {'\0'};
char cr_lf [3] = {'\15','\12','\0'};
int tab_stop [] = { 5, 14, 23, 32, 41, 50, 59 };
char *help_menu [MAX_HELP_LINES] =
{
    "F1 = RECALL LAST LINE",
    "F2 = SAVE FILE",
    "F3 = SAVE AND EXIT",
    "F4 = QUIT",
    "F9 FOR HELP",
    "CTRL BS = DELETE LINE",
    "USE ARROW KEYS",
    "PAGE UP",
    "PAGE DOWN",
    ""
};



/*	Subttl	Modify User Program */
/******************************************************************************/
/* Modify user program is a built in editor for diagnostic programs.	      */
/*									      */
/* Enter:   user_file_name	(global) name of file to edit		      */
/*									      */
/* Call:    modify_program ()						      */
/*									      */
/* Return:  edited file 						      */
/*									      */
/******************************************************************************/

modify_program ()
{
    int i;
    int ctr;
    int line;
    int col;
    int break_flag;
    int key_char;
    unsigned char key;
    int screen_update_flag;
    int line_buffer_col;

    int insert_mode = FALSE;

    line = 1;
    top_line_displayed = 0;
    col = 0;

    new_file_flag = TRUE;
    if (get_edit_file ())
    {
	new_file_flag = FALSE;
    }
    print_edit_screen ();

    highlight_word (TOP_ROW + line, 0, 4, TRUE );

    break_flag = FALSE;
    while ( break_flag == FALSE )
    {
	print_main_window (top_line_displayed);

	crt_pos_cursor ( LINE_BUFFER_ROW, tab_stop [0], 0 );
	print_fill ("", LINE_BUFFER_ROW);
	highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
	crt_pos_cursor ( LINE_BUFFER_ROW, tab_stop [0], 0 );

	line_buffer_col = 0;
	screen_update_flag = FALSE;

	while ( screen_update_flag == FALSE && break_flag == FALSE )
	{
	    crt_pos_cursor (LINE_BUFFER_ROW, tab_stop [0] + line_buffer_col, 0);
	    key_char = keybrd_getc ();
	    switch ( key_char )
	    {

		case KEY_F9:
		{
		    print_help_screen ();
		    ctr = strlen (&line_buffer [0]);
		    line_buffer_col = ctr;
		    i = 0;
		    while (ctr)
		    {
			crt_pos_cursor (LINE_BUFFER_ROW, i + tab_stop [0], 0);
			crt_wr_char_att (0, 1, line_buffer [i], (char) 0x70);
			ctr--;
			i++;
		    }
		    highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
		    crt_pos_cursor (LINE_BUFFER_ROW, i + tab_stop [0], 0);
		    break;
		}
		case 20992: /* insert toggle */
		{
		    if (insert_mode)
		    {
			insert_mode = FALSE;
		    }
		    else
		    {
			insert_mode = TRUE;
		    }
		}
		break;

		case KEY_ESC:
		case KEY_F4:	/* quit without saving */
		{
		    print_error_message ("Quit (Y/N)?");
		    key_char = '\0';
		    while ((key_char != 'N') && (key_char != 'Y'))
		    {
			key_char = toupper (keybrd_getc ());
		    }
		    if (key_char == 'Y')
		    {
			break_flag = TRUE;
		    }
		    else
		    {
			print_error_message ("");
		    }
		}
		break;

		case KEY_F2:  /* save file */
		{
		    print_error_message ("Saving file");
		    save_edit_file ();
		    print_error_message ("");
		}
		break;

		case 127:  /* ctrl back space ... delete line */
		{
		    delete_line (line);
		    screen_update_flag = TRUE;
		}
		break;

		case KEY_PAGE_UP:
		{
		    if (top_line_displayed > 0)
		    {
			highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, FALSE );
			if ((line -= 8) < 1)
			{
			    line = 1;
			}
			if ((top_line_displayed -= 8) < 0)
			{
			    top_line_displayed = 0;
			}
			screen_update_flag = TRUE;
			highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
		    }
		}
		break;

		case KEY_PAGE_DOWN:
		{
		    if (top_line_displayed < (MAX_PROG_ROWS - MAX_ROWS))
		    {
			highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, FALSE );

			if ((line += 8) > last_line)
			{
			    line = last_line - 1;
			}

			if ((top_line_displayed += 8) > (MAX_PROG_ROWS - MAX_ROWS))
			{
			    top_line_displayed = MAX_PROG_ROWS - MAX_ROWS;
			}
			else if (top_line_displayed > line)
			{
			    top_line_displayed = line;
			}
			screen_update_flag = TRUE;
			highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
		    }
		}
		break;

		case KEY_CURSOR_UP:
		{
		    highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, FALSE );
		    if (top_line_displayed == line)
		    {
			top_line_displayed--;
			screen_update_flag = TRUE;
		    }
		    if (line > 1)
		    {
			line--;
		    }

		    else if (top_line_displayed > 0)
		    {
			top_line_displayed--;
			if (top_line_displayed > 0)
			{
			    line--;
			}
			screen_update_flag = TRUE;
		    }
		    highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
		}
		break;

		case KEY_CURSOR_DOWN:
		{
		    highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, FALSE );
		    if (line < last_line)
		    {
			line++;
		    }
		    if ((line - top_line_displayed) >= MAX_ROWS )
		    {
			top_line_displayed++;
			screen_update_flag = TRUE;
		    }
		    highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
		}
		break;

		case KEY_CURSOR_LEFT:
		{
		    if ( line_buffer_col > 0 )
		    {
			line_buffer_col--;
		    }
		}
		break;

		case KEY_CURSOR_RIGHT:
		{
		    if (line_buffer_col < strlen (line_buffer))
		    {
			line_buffer_col++;
		    }
		}
		break;

		case KEY_BS:
		{
		    if (line_buffer_col)
		    {
			line_buffer [--line_buffer_col] = CRLF;
			crt_pos_cursor (LINE_BUFFER_ROW, tab_stop [0] + line_buffer_col, 0);
			crt_wr_char_att (0, 1, ' ', (char) (crt_rd_char_att (0) / 256));
		    }
		}
		break;

		case KEY_F1:
		{
		    strcpy (line_buffer, last_line_buffer);
		    ctr = strlen (&line_buffer [0]);
		    line_buffer_col = ctr;
		    i = 0;
		    while (ctr)
		    {
			crt_pos_cursor (LINE_BUFFER_ROW, i + tab_stop [0], 0);
			crt_wr_char_att (0, 1, line_buffer [i], (char) 0x70);
			ctr--;
			i++;
		    }
		    crt_pos_cursor (LINE_BUFFER_ROW, i + tab_stop [0], 0);
		}
		break;


		case KEY_CR:
		{
		    strcpy (last_line_buffer, line_buffer);

			highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, FALSE );
			insert_line (line_buffer, line);
			line++;
			crt_pos_cursor (LINE_BUFFER_ROW, tab_stop [0], 0);
			crt_wr_char_att (0, MAX_LINE_SIZE, ' ', (char) 0x70);
			highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, TRUE );
			line_buffer_col = 0;
			line_buffer [0] = 0;
			screen_update_flag = TRUE;
			for (i = 0; i < MAX_LINE_SIZE; i++)
			{
			    line_buffer [i] = '\0';
			}
		}
		break;

		case KEY_F3:
		{
		    save_edit_file ();
		    break_flag = TRUE;
		}
		break;

		default :
		{
		    if ((key_char < 127) && (key_char >= 32) && line_buffer_col < MAX_LINE_SIZE - 1)
		    {
			if (insert_mode)
			{
			    int j;
			    int col_pos;

			    for (i = MAX_LINE_SIZE - 2; i >= line_buffer_col; i--)
			    {
				crt_pos_cursor (LINE_BUFFER_ROW, tab_stop [0] + i, 0);
				j = crt_rd_char_att (0);
				crt_pos_cursor (LINE_BUFFER_ROW, tab_stop [0] + i + 1, 0);
				crt_wr_char_att (0, 1, (char) j, (char) (j >> 8));
				line_buffer [i + 1] = line_buffer [i];
			    }
			}
			crt_pos_cursor (LINE_BUFFER_ROW, tab_stop [0] + line_buffer_col, 0);
			i = crt_rd_char_att (0);
			key = (unsigned char) key_char & 0x7f;
			crt_wr_char_att (0, 1, key, (char) (i / 256));
			line_buffer [line_buffer_col] = key;
			line_buffer_col++;
		    }
		}
		break;
	    }
	}
    }
}


print_error_message (message_ptr)
char *message_ptr;
{
    pos_printf (LINE_BUFFER_ROW + 1, tab_stop [0], "                        ");
    pos_printf (LINE_BUFFER_ROW + 1, tab_stop [0], message_ptr);
}



delete_line (line_num)
unsigned int line_num;
{
    unsigned char *bufr_ptr;
    int i;
    int j;

    if ((line_num < last_line) && (line_num > 0))
    {
	bufr_ptr = &edit_buffer [2];
	j = 1;
	for (i = 2; (i < last_char) && (j < line_num); i++)
	{
	    if (edit_buffer [i] == CRLF)
	    {
		bufr_ptr = &edit_buffer [i + 1];
		j++;
	    }
	}

	j = strlen (bufr_ptr) + 1;
	while (bufr_ptr <= &edit_buffer [last_char + j])
	{
	    bufr_ptr [0] = bufr_ptr [j];
	    bufr_ptr++;
	}
	last_line--;
	last_char -= j;
    }
}







/* insert a line into edit buffer */

insert_line (buffer_ptr, line)
unsigned char *buffer_ptr;
int line;
{
    int i;
    int j;
    int length;

    length = strlen (buffer_ptr) + 1;
    j = last_line;
    for (i = last_char; (j >= line) && (i >= 0); i--)
    {
	edit_buffer [i + length] = edit_buffer [i];
	if (edit_buffer [i] == CRLF)
	{
	    j--;
	}
    }
    i++;
    edit_buffer [i] = CRLF;
    strcpy (&edit_buffer [i + 1], buffer_ptr );
    last_line++;
    last_char += length;

    if ((line - top_line_displayed) < (MAX_ROWS - 1))
    {
	crt_scroll_down (1,
		    TOP_ROW + line - top_line_displayed,
		    0,
		    TOP_ROW + MAX_ROWS - 1,
		    MAX_LINE_SIZE - 1);
    }
    else
    {
	crt_scroll_up (1,
			TOP_ROW,
			0,
			TOP_ROW + MAX_ROWS - 1,
			MAX_LINE_SIZE - 1);
	top_line_displayed++;
    }
    crt_pos_cursor ( TOP_ROW + line - top_line_displayed, tab_stop [0], 0 );
    print_fill ( buffer_ptr, line - top_line_displayed);
    if (line < top_line_displayed + MAX_ROWS)
    {
	highlight_word (TOP_ROW + line - top_line_displayed, 0, 4, FALSE );
	highlight_word (TOP_ROW + 1 + line - top_line_displayed, 0, 4, TRUE );
    }
    crt_pos_cursor ( LINE_BUFFER_ROW, tab_stop [0], 0 );
}





print_edit_screen ()
{
    int i;
    int j;
    int char_ctr;


    video_clear_screen ();
    crt_pos_cursor ( 1, 28, 0 );
    printf ("ALLPRO DIAGNOSTIC EDITOR\n");
    for ( i = 0; i < 80; i++ )
    {
	printf ("-");
    }

    crt_pos_cursor ( TOP_ROW + MAX_ROWS, 0, 0 );
    for ( i = 0; i < 80; i++ )
    {
	printf ("-");
    }

    highlight_word (LINE_BUFFER_ROW, tab_stop [0], MAX_LINE_SIZE, TRUE );
    pos_printf (LINE_BUFFER_ROW + 1, tab_stop [5], "Command line entry");


    for (i = 0; i < MAX_HELP_LINES / 2; i++)
    {
	for (j = 0; j < 2; j++)
	{
	    pos_printf (TOP_ROW + MAX_ROWS + 2 + i, tab_stop [j * 3], help_menu [i + (MAX_HELP_LINES/2) * j]);
	}
    }


    if (new_file_flag)
    {
	edit_buffer [0] = STX;
	edit_buffer [1] = CRLF;
	edit_buffer [2] = ETX;
	last_line = 1;
	last_char = 2;
	pos_printf (LINE_BUFFER_ROW - 1, tab_stop [6], "New file");
    }
    pos_printf (LINE_BUFFER_ROW - 1, tab_stop [0], user_file_name);
}


print_main_window (line)
int line;
{
    int i;
    int top_line;
    unsigned char *p;

    top_line = line;
    for ( i = 0; i < MAX_ROWS; i++ )
    {
	crt_pos_cursor ( i + TOP_ROW, 0, 0 );
	if ((i + line) && ((i + line) < last_line))
	{
	    printf ( "%04d ", top_line );
	}
	else
	{
	    printf ("     ");
	}
	top_line++;
    }

    top_line = line;
    p = &edit_buffer [0];
    while ((top_line) && (*p != ETX))
    {
	if (*p == CRLF)
	{
	    top_line--;
	}
	p++;
    }

    i = 0;
    while (((i + line) <= last_line) && (i < MAX_ROWS))
    {
	print_fill (p, i);
	while ((*p != CRLF) && (*p != ETX))
	{
	    p++;
	}
	if (*p != ETX)
	{
	    p++;
	}
	i++;
    }
    while (i < MAX_ROWS)
    {
	print_fill ("", i);
	i++;
    }
}



print_fill (buffer_ptr, row)
unsigned char *buffer_ptr;
int row;
{
    crt_pos_cursor (row + TOP_ROW, tab_stop [0], 0);
    crt_wr_char_att (0, MAX_LINE_SIZE, ' ', (char) 0x07);
    crt_pos_cursor (row + TOP_ROW, tab_stop [0], 0);
    if (*buffer_ptr == ETX)
    {
	printf ("---End of text---");
    }
    else if (*buffer_ptr == STX)
    {
	printf ("---Start of text---");
    }
    else
    {
	printf ("%s", buffer_ptr);
    }
}





pos_printf (row, col, strng_ptr)
int row;
int col;
unsigned char *strng_ptr;
{
    crt_pos_cursor (row, col, 0);
    printf ("%s", strng_ptr);
}


highlight_word (row, col, length, on_flag)
int row;
int col;
int length;
int on_flag;
{
    int i;
    char att;
    unsigned int temp;

    att = 0x07;
    if (on_flag)
    {
	att = 0x70;
    }
    for (i = 0; i < length; i++)
    {
	crt_pos_cursor (row, col + i, 0);
	temp = crt_rd_char_att (0);
	crt_wr_char_att (0, 1, (char) temp & 0xff, att);
    }
}

save_edit_file ()
{
    int i;
    file_compiled = FALSE;

    if ((fptr = fopen (user_file_name, "w")) != NULL)
    {
	for (i = 2; i < last_char; i++)
	{
	    if (edit_buffer [i] == CRLF)
	    {
		fwrite (cr_lf, 1, 2, fptr);
	    }
	    else
	    {
		if (!fwrite (&edit_buffer [i], 1, 1, fptr))
		{
		    print_error_message ("File write error");
		    keybrd_getc ();
		}
	    }
	}
	if (fclose (fptr) != 0)
	{
	    print_error_message ("Error closing file");
	    keybrd_getc ();
	}
    }
    else
    {
	print_error_message ("Error opening file");
	keybrd_getc ();
    }
}




get_edit_file ()
{
    int i;


    if ((fptr = fopen (user_file_name, "r")) == NULL)
    {
	file_loaded = FALSE;
	return (0);
    }
    else
    {
	edit_buffer [0] = STX;
	edit_buffer [1] = CRLF;
	last_line = 1;
	file_eof_flag = FALSE;
	for (i = 2; (file_eof_flag == FALSE) && (i < MAX_EDIT_BUFFER_SIZE - 1); i++)
	{
	    edit_buffer [i] = get_file_char ();

	    if ((edit_buffer [i] == 0x0a) || (edit_buffer [i] == 0x0d))
	    {
		edit_buffer [i] = CRLF;
		get_file_char ();
		last_line++;
	    }
	    else if (edit_buffer [i] == 0x1a)
	    {
		file_eof_flag = TRUE;
	    }
	}
	last_char = --i;
	edit_buffer [i] = ETX;
	fclose (fptr);
    }
    file_loaded = TRUE;
    return (1);
}





/*	crt_get_cur_pos (page) ret row * 256 + col position			*/
/*	crt_rd_char_att (page) ret attr * 256 + character			*/
/*	crt_wr_char_att (page, char_cnt, char, att)				*/
/*	crt_pos_cursor (row, col, page) 					*/
/*										*/
/*										*/
/*										*/



struct menu_struc menu_edit [] =
{
    { '?',*func_help,  2, 'C', "ALLPRO DIAGNOSTIC EDITOR" },
    { '\0',*func_null, 0,  0, "" }
};


func_edit ()
{
    print_menu (menu_edit);
    get_file_name ();
    modify_program ();
}



func_diag ()
{
    strcpy (line_buffer, "diag1 ");
    strcat (line_buffer, user_file_name );
    system (line_buffer);
    pump ();
}

func_execute ()
{
    video_clear_screen ();
    if (file_compiled)
    {
	execute_program (&object_buffer [0]);
    }
    else
    {
	if (file_loaded)
	{
	    if (compile_program ())
	    {
		video_clear_screen ();
		execute_program (&object_buffer [0]);
	    }
	}
	else
	{
	    get_file_name ();
	    if (get_edit_file ())
	    {
		if (compile_program ())
		{
		    video_clear_screen ();
		    execute_program (&object_buffer [0]);
		}
	    }
	}
    }
}

func_compile ()
{
    video_clear_screen ();
    if (file_loaded)
    {
	compile_program ();
    }
    else
    {
	get_file_name ();
	if (get_edit_file ())
	{
	    compile_program ();
	}
    }
}


struct menu_struc menu_trblsht [] =
{
    { '?',*func_help,        4,   'C', "TROUBLE SHOOTING AID" },
    { '1',*func_edit,        9,   'L', "1. Edit" },
    { '2',*func_compile,    10,   'L', "2. Compile" },
    { '3',*func_execute,    11,   'L', "3. Run" },
    { '\0',*func_null,       0,     0, "" }
};


func_trblsht ()
{
    select_command ( menu_trblsht );
}

get_file_name ()
{
    char first_char;

    crt_pos_cursor (7, 0, 0);
    printf ("Enter filename: ");
    if (strlen (user_file_name))
    {
	printf ("%s", user_file_name );
	crt_pos_cursor (7, 16, 0);
	if ((first_char = keybrd_getc ()) != KEY_CR)
	{
	    user_file_name [0] = first_char;
	    printf ("%c                       ",first_char);
	    crt_pos_cursor (7, 17, 0);
	    keybrd_gets (user_file_name + 1, 63);
	}
    }
    else
    {
	keybrd_gets (user_file_name, 64);
    }
}

print_help_screen ()
{
    unsigned char i;
    int j;
    unsigned temp;

    j = 80 / MAX_COMMAND_SIZE;
    temp = (unsigned int) (crt_get_cur_pos (0) >> 16);
    video_clear_screen ();
    pos_printf (1, 30, "Key word Operation Codes");
    for (i = 1; i < MAX_COMMANDS; i++)
    {
	pos_printf (3 + (i - 1) / j, ((i - 1) % j) * MAX_COMMAND_SIZE, &key_word_table [i] [0]);
    }
    pos_printf (10, 35, "Key word Operands");
    for (i = MAX_COMMANDS; i < MAX_KEY_WORDS; i++)
    {
	pos_printf (12 + ((i - MAX_COMMANDS) / j), ((i - MAX_COMMANDS) % j) * MAX_COMMAND_SIZE, &key_word_table [i] [0]);
    }
    keybrd_getc ();
    print_edit_screen ();
    print_main_window (top_line_displayed);

    crt_pos_cursor (temp / 256, temp & 0xff, 0);
}

