/* 	(c) Marietta Systems, Inc. 1987
*	All rights reserved
*/
#include "mtest.h"
/*
*
*	Program to demonstrate use of ascii files
*	A simple text editor
*
*/
unsigned maxsize = 20000;
unsigned maxrecs = 253;
void delline(int*, int, int);
void editfile(char*, int*, int*);
int  getfile(char*, char*, int*, int*);
void insline(int*, int, int);
void linedisp(char*, int*, int, int);
void putfile(int, char*, char*, int*, int); 
void scrndisp(char*, int*, int, int*, int);
void show_nbr(int, int);
/*
*
*	Function to obtain file and read it in
*
*/
int getfile(fname, text, lineptr, len)
char *fname, *text;
int *lineptr;
int *len;{
	long rec_nbr;
	int z, slen, fh, ret;
	byte out[20], *ptr;
  /* setup */
	strcpy(fname, "textfile.dat");
	top_spot(1);
	for (z = 0 ; z < 8 ; KEYMATCH[z++] = 0); /* blank out function keys */
	disp_err("",1); /* display new function key settings */
	for (z = 0, slen = 0 ; z < maxrecs; z++, slen += 79)
	     {lineptr[z] = slen; text[slen] = 0;}/* initialize out line ptr */
  /*	*/
	for(;;){
	    display("Text file to edit -  ", 19, 1, low);
	    if (accept(fname, left, alt_reverse, 51, 0) && INCHAR == QUIT)
		goodbye(0);
	    if ((fh = fileopen(fname, ascii, readonly)) < 0)
	        {disp_err("File name or access error",1); continue;}
	    disp_err(fname, 1);
	    if (!fh) if (!disp_qry("File not found, Create")) continue;
	        else {*len = 0; ptr = fname; 
		    for (z = 0 ; z < strlen(fname) && fname[z] != '.' ; z++)
		        if (fname[z] == '\\') ptr = &fname[z+1];
		    display(ptr, 1, 50, reverse); 
		    return 0;}
	    display((byte*)FN[fh].fname, 1, 50, reverse);
	    fileseek(fh, -1L); /* position to end of file */
	    if (FN[fh].location >= (long)maxsize)
	        {disp_err("File is too big for editor", 1); 
	        fileclos(fh); continue;}
	    fileinit(fh, 0, 81, 0L);  /* Max record width is set to 80 */
	    *len = 0; text[0] = 0; 
	    if (!fh) return 0; /* new text file */
	  /* read in the text and set up line pointers */
	    rec_nbr = 0L;
	    if (fileread(fh, firstrec, &rec_nbr) <= 0) goodbye(10);
	    ptr = text;
	    display ("Loading text file ", 21, 1, high); 
	    for (; rec_nbr < (long)maxrecs;){
	        slen = strlen(FN[fh].record);
	        FN[fh].record[slen-1] = 0;  /* replace the '\n' with 0 */
	        strncpy(ptr, FN[fh].record, 78); ptr = &ptr[79];
	        if ((ret = fileread(fh, nextrec, &rec_nbr)) < 0) 
	            goodbye(11);
	        if (!ret) {*len = (int)rec_nbr - 2; 
	            fileclos(fh); return fh;} /* EOF */
	        if (!(rec_nbr & 0X3F)) /* print rec_nbr every 48 */
	            {sprintf(out, "%lu", rec_nbr);
	            display(out, 21, 20, reverse);}
	        }
	    disp_err("File contains too many records", (int)rec_nbr);
	    fileclos(fh); 
	    continue;
	    } /* end of main for loop */
	} /* end of function getedit*/
/*
*
*	Function editfile
*
*/
void editfile(text, lineptr, len)
char *text;
int *lineptr;
int *len;{
	int h, top = 0, x = 1, bottom;
  /*	setup */	
	display("\030 \031 Ctrl+Home Ctrl+End PgUp PgDn", 1, 2, low);
	if (mk_wndw(TOP_LINE+2, 1, SCRN_LEN - 1, 80,
"  5    10   15   20   25   30   35   40   45   50   55   60   65   70   75")
    	    < 0) goodbye(20);
	KEYMATCH[0] = 0XA38;  /* PgDn, Crs-up, Crs-rt, Tab, Shift-Tab */
	KEYMATCH[1] = 0X10C;  /* PgUp, Crs-dn, Crs-lt */
	KEYMATCH[4] = 0X3000;  /* F5, F6 */
	KEYMATCH[7] = 0X1400; /* Ctrl+end, Ctrl+home */
	KEYMATCH[2] = KEYMATCH[3] = KEYMATCH[5] = KEYMATCH[6] = 0;
	disp_err("",1); /* force display of control keys */	
	h = WINDOW[W_NUM].H - 1; /* lines in screen */
	scrndisp(text, lineptr, top, &bottom, *len); /* initial display */  
	A_TRACK = 0; INCHAR = ENTER; x = 0;
  /* 	main for loop */
	for (;;){
	switch((int)INCHAR){
	    case CRS_LT:
	    case SFT_TAB: A_TRACK = 78 - 1;
	    case CRS_UP: if (!(--x)) 
	            if (!top) {x = 1; A_TRACK = 0;} /* at TOF */
	            else {scroll(-1, 0); 
	                linedisp(text, lineptr, --top, (x = 1));
	                if (top + h <= bottom) bottom--;}    
	        break;
	    case ENTER: 
	    case CRS_RT:
	    case TAB: A_TRACK = 0;
	    case CRS_DN: if ((++x) > h) 
	            if (bottom >= *len) {x = h; A_TRACK = 78 - 1;}
	            else {scroll(1, 0); top++; 
	                linedisp(text, lineptr, ++bottom, (x = h));}
	        if (INCHAR != ENTER) 
	            {if (top + x > *len) {x--; A_TRACK = 78 - 1;} 
	            break;}
	        if (top + x <= bottom) break;
        case INSERT: if (*len == maxrecs) break;
	        insline(lineptr, top + x, *len);
	        scroll(-1, x - 1);
	        A_TRACK = 0;
	        text[lineptr[top + x - 1]] = 0;
	        *len += 1; 
	        break;
	    case DELETE: if (!*len) break;
	        delline(lineptr, top + x, *len);
	        scroll(1, x - 1);
            if (*len > bottom) linedisp(text, lineptr, bottom, h);
                else {bottom--; if (x > bottom - top) x--;}
	        *len -= 1;
	        break;
	    case PGUP: top -= h; if (top < 0) top = 0;
	        scrndisp(text, lineptr, top, &bottom, *len);
	        break;
	    case PGDN: if (bottom >= *len) break;
		    top += h; 
	        scrndisp(text, lineptr, top, &bottom, *len);
	        if (x > bottom - top) x = bottom - top;
	        break;
	    case CTL_HOME: top = 0; x = 1;
	        scrndisp(text, lineptr, top, &bottom, *len);
	        break;
	    case CTL_END: top = *len - h; 
            if (top < 0) top = 0; 
	        scrndisp(text, lineptr, top, &bottom, *len);
	        x = bottom - top;
            break;
	    case QUIT: if (disp_qry("Have you finished editing")) return;
	        break;
	    default: disp_err("Invalid function key", 1); break;
	    } /* end switch */
	    set_crsr(x, 1);
	    show_nbr(top + x, *len);
	    if (accept(&text[lineptr[top+x-1]], as_typed, alt_reverse, 78, 0)
	        < 0) goodbye(10);
	    }  /* end for loop */
	} /* end function editfile */
/*
*
*	Function to display a line on screen
*
*/
void linedisp(text, lineptr, nbr, x)
char *text;
int *lineptr;
int nbr, x;{
	byte line[81];
	justify(as_typed, line, &text[lineptr[nbr]], 78, 0);
	display(line, x, 1, ACC_DISP);
	}    
/*
*
*	Function to re_display screen on edit
*
*/
void scrndisp(text, lineptr, top, bottom, len)
char *text;
int *lineptr, top, *bottom, len;{
	int h = WINDOW[W_NUM].H - 1, k, x;
	byte line[81];
	*bottom = top + h ;
	if (*bottom >= len) *bottom = len; 
	for (x = 1, k = top ; x <= h  && k < *bottom ; x++, k++)
	    linedisp(text, lineptr, k, x);
	if (x > h) return;
	memset(line, 32, 78); line[78] = 0; /* blank bottom of screen */
	for (; x <= h ; display(line, x++, 1, ACC_DISP));
	}  /* end of function scrndisp */
/*
*
*	Function to insert pointer in lineptr
*
*/
void insline(lineptr, k, len)
int *lineptr, k, len;{
	int z = len - k, save = lineptr[len];	
	if (z <= 0) return; /* pointer already at EOT */
	memcpy ((char*)&lineptr[k], (char*)&lineptr[k - 1], ++z * sizeof(int));
        lineptr[k - 1] = save;
	}
/*
*
*	Function to delete pointer from lineptr
*
*/
void delline(lineptr, k, len)
int *lineptr, k, len;{
	int z = len - k, save = lineptr[k - 1];
	if (!z) return; /* pointer at EOT */
	memcpy((char*)&lineptr[k - 1], (char*)&lineptr[k], ++z * sizeof(int));
	lineptr[len] = save;
	}
/*
*
*       Function to show current record location on screen
*
*/
void show_nbr(loc, len)
int loc;
int len;{
	char text[16];
	set_clr(99, low); /* use error status color */
	sprintf(text, "%3u of %-3u", loc, len);
	scrn_map(text, TOP_LINE + 1, 69); /* hairy technique */
	set_clr(98, low); /* reset color */
	}
/*
*
*	Function to store new file to disc
*
*/
void putfile(fh, fname, text, lineptr, len)
char *fname, *text;
int fh, *lineptr, len;{
	long rec_nbr = 0L;
	int z;
	if (fh && fileback(fname) < 1) goodbye(30);
	fh = fileopen(fname, ascii, recreate);
	fileinit(fh, 0, 81, 0L);
	if (fh <= 0) goodbye(31);
	for (z = 0 ; z < len ; z++){
	    strcpy(FN[fh].record, &text[lineptr[z]]); /* copy to record area */
	    concat(FN[fh].record, 0); /* strip trailing spaces */
	    strcat(FN[fh].record, "\n"); /* Add the '\n' char */
	    if (filewrit(fh, &rec_nbr)) goodbye(32);
	    if (!(rec_nbr & 0XF)) 
	        disp_msg("Writing to disc - record",(int)rec_nbr);
	    }
	disp_msg("",0);
	fileclos(fh);
	rm_wndw();
	}
/*
*
*	Main program
*
*/
void main(){
int len = 0;
int fh, *lineptr;
char *text, fname[66];
/*  setup */
clr_scrn("Text Editor");
text = malloc(maxsize); /* assign workarea */
lineptr = (int*) malloc(sizeof(int) * maxrecs);
if (text == NULL || lineptr == NULL) goodbye(1);
/*	edit */
if ((fh = getfile(fname, text, lineptr, &len)) < 0) goodbye(2);
editfile(text, lineptr, &len);
putfile(fh, fname, text, lineptr, len);
disp_err("ready for goodbye", 11); idleloop(18);
goodbye(0);
}