/*
	e screen editor

	(C) G. Nigel Gilbert, MICROLOGY, 1981
	licensed for private non-profitmaking use 1983
	
	August-December 1981

	FILE: e

	FUNCTIONS: main, initialise, edit, finish, seldisk

	PURPOSE: initialise; process commands;

*/

#include "e.h"

main(argc,argv)
int argc;
char **argv;
{
	int argn;
	char *dig;
	char *bdosbase;
	int i,*six,*errbase,err1(),err2(),err3(),err4();

/**************************Default option settings***************************/

	autoin=YES;	/*auto indent  [YES/NO]*/
	backup=NO;	/*make ".BAK" file [YES/NO]*/
	trail=NO;	/*don't strip trailing blanks [YES/NO]*/
	helpon=NO;	/*start with help menu on [YES/NO]*/
	tabwidth=8;	/*tab stops every n cols [number]*/
	displaypos=YES;	/*display line:column at top of screen*/
	blockscroll=NO;	/*don't scroll whole page, just current line*/
	pagingdisk=0;	/*create buffer file on this disk -
				set to either 0 (for currently logged-in disk)
				or to desired disk letter  (eg 'B') */
	wboot=NO;	/*do a warm boot at end of edit [YES/NO]*/

/***********************End of default option settings***********************/


	inbufp=0;
	if ((bdos(VERNO,0) & 0xf0)  != 0x20) {
		puts("Must use CP/M vers 2.x with 'e'"); 
		exit();
		}

	filename[0]=name[0]='\0';

	argn=0;	
	while (++argn < argc)
		if (*argv[argn] == '-') {
			dig=argv[argn]+1;
			switch(*dig) {
			case 'A' : 
				autoin=!autoin; 
				break;
			case 'B' : 
				backup=!backup; 
				break;
			case 'L' :
				displaypos=!displaypos;
				break;
			case 'H' :
				blockscroll=!blockscroll;
				break;
			case 'T' : 
				tabwidth=0;
				while (*++dig) tabwidth=tabwidth*10+*dig-'0';
				break;
			case 'S' :
				trail=!trail; 
				break;
			case 'V' : 
				helpon=!helpon; 
				break;
			case 'X' : 
				wboot=!wboot; 
				break;
			case 'D' : 
				pagingdisk=*(dig+1);
				if (pagingdisk >= 'A' && pagingdisk <= 'P') break;
			default  : 
				puts("Illegal option: "); 
				puts(argv[argn]);
				exit();
				}
			}
		else strcpy(filename[0] ? name : filename,argv[argn]);

	six=6;
	bdosbase=*six;
	errbase=bdosbase+3;
	for (i=0; i < 4; i++) errold[i]=*(errbase+i);
	*(errbase)=err1;
	*(errbase+1)=err2;
	*(errbase+2)=err3;
	*(errbase+3)=err4;

	ans[0]=patt[0]=changeto[0]=opts[0]='\0';
	
	keytranslate();
	do {
		initialise();
		edit();
		} 
	while (YES);
}

initialise()
{
	int warn;

	cursorx=charn=offset=lastoff=from=to=0;
	cursory=topline=lastread=lastl=findir=1;
	isdim=replace=repeat=blocking=warn=blankedmess=NO;
	pfirst=-100;
	goteof=YES;
	errmess=NULL;

	curdsk=bdos(CURDSK);

	initvm();

	text[0]='\0';
	cline=1;
	altered=YES;
	puttext();

	if (filename[0]) {
		putclr();
		gotoxy(8,11);
		puts("e  screen editor  version "); 
		puts(VERSION);
		puts("  MICROLOGY 1983");
		gotoxy(20,12); 
		terminal();
		while (opentext(filename) == FAIL) {
			askforfile();
			if (!filename[0]) goto newfile;
			}
		lastl=UNKNOWN;
		lastread=0;
		goteof=NO;
		if (name[0]) {
			strcpy(filename,name); 
			name[0]='\0';
			}
		format(filename);
		}
newfile: errmess=NULL;
	gettext(1);
	putclr();
	if (helpon) dohelp();
	putpage();
}

edit()		/*command processor*/
{
	char c;
	int to;

	setjmp(mainmenu);

	while (YES) {
		goodline=cline;
		unmess();
		putlineno(cline);
		resetcursor();
		c=getkey();
		if (errmess != NULL) {
			errmess=NULL;
			putstatusline(cline);
			}
		switch(c) {
		case DOWNKEY	: 
			moveline(1); 
			break;
		case UPKEY	: 
			moveline(-1); 
			break;
		case LEFTKEY	: 
			movechar(-1); 
			break;
		case RIGHTKEY	: 
			movechar(1); 
			break;
		case LEFTWKEY	: 
			moveword(-1); 
			break;
		case RIGHTWKEY	: 
			moveword(1);  
			break;
		case BOLKEY	: 
			sync(0); 
			break;
		case EOLKEY	: 
			sync(strlen(text)); 
			break;
		case UPPAGE	: 
			movepage(-1); 
			break;
		case DOWNPAGE	: 
			movepage(0); 
			break;
		case HOMEKEY	: 
			if (jumpline(lastl-cline)) sync(strlen(text));
			break;
		case BOFKEY	: 
			if (jumpline(1-cline)) sync(0);
			break;
		case DELLEFT	: 
			deletechar(-1); 
			break;
		case DELRIGHT	: 
			deletechar(0); 
			break;
		case DELLNKEY	: 
			text[0]='\0';
			crdelete((cline == lastl ? -1 : 0)); 
			break;
		case DELWDKEY	: 
			deleteword(); 
			break;
		case JUMPKEY	: 
			putmess("Jump to? ");  
			scans(ans,6);
			if ((to=atoi(ans))) jumpline(to-cline);
			break;
		case FINDKEY	: 
			replace=NO; 
			findorrep(); 
			break;
		case ALTERKEY	: 
			replace=YES; 
			findorrep(); 
			break;
		case REPKEY	: 
			repeat=YES; 
			dofindrep(1); 
			repeat=NO; 
			break;
		case BLOCKKEY	: 
			blockops(); 
			break;
		case RDFILEKEY	: 
			putmess("File to read? ");
			scans(name,15);
			if (strlen(name) > 0) {
				readfile(name); 
				putpage();
				} 
			break;
		case HELPKEY	: 
			if (helpon) {
				helpon=NO; 
				unmess();
				}
			else {
				helpon=YES; 
				dohelp();
				} 
			break;
		case CR		: 
			crinsert(0); 
			break;
		case CRSTILL	: 
			crinsert(-1); 
			break;
		case ENVIRKEY   :
			envir(); 
			break;
		case QUITKEY	: 
			if (finish()) return;
			break;
		case OOPSKEY	:
			oops();
			break;
		case TAB:
			insertchar('\t');
			break;
		case ESCKEY	:
			resetcursor(); 
			while (!(c=inkey()));
		default		:
			insertchar(c); 
			break;
			}
		}
}

finish()	/*return YES to edit another file; NO to return to current file
		  or don't return, but exit if finished altogther */
{
	int abandon;
	char c, tempname[FILELEN], namebak[FILELEN], *strcpy();

	putmess("W|rite edited text to file, |A|bandon all edits, or |R|eturn? ");
	while ( (c=getlow()) != 'w' && c != 'a' && c != 'r'); 
	putch(c);
	if (c == 'r') return NO;
	abandon= c == 'a';
	if (c == 'w') {
		if (!filename[0]) {
			putmess("File to write to? ");
			scans(filename,15);
			format(filename);
			if (filename[0] <= ' ' || (!backup && !exists(filename)))
			{
				filename[0]='\0'; 
				return NO; 
				}
			}
		if (backup) {	/*delete old bak file*/
			retag(strcpy(namebak,filename),"BAK");
			if (checkexists(namebak))
				if (funlink(namebak) == FAIL) return NO;
			}
		strcpy(tempname,filename); /*keep old name in 'filename'*/
		retag(tempname,"$$$"); /*new file called'.$$$'*/
		if (writefile(1,lastl,tempname,filename,YES) == FAIL) return NO;
		/*check original file still exists - may have been deleted or
		   renamed by user */
		if (checkexists(filename)) {
			if (backup) {
				/*orig. file becomes '.bak' */
				if (frename(filename,namebak) == FAIL) goto failed;
				}
			else {
				/*delete orig file*/
				if (funlink(filename) == FAIL) {
	failed: 			/*if can't delete/rename old file, change
						new name to '.$$$'*/
					strcpy(filename,tempname);
					goto nowrite;
					}
				}
			}
		frename(tempname,filename); /*new file goes from '$$$' to orig name*/
		}
nowrite:
	putmess("E|xit to CP/M, |R|eturn to this file, or edit |A|nother file? ");
	while ( (c=getlow()) != 'e' && c!='a' && c!='r');
	putch(c);
	switch(c) {
	case 'e' : 
		if (pagefd != NOFILE) {
			close(pagefd); 
			funlink(pagingfile);
			}
		xit();
	case 'a' : 
		fclose(textbuf);
		if (pagefd != NOFILE) {
			close(pagefd); 
			funlink(pagingfile);
			}
		askforfile();
		return YES;
		
	case 'r' : 
		if (!abandon) {
			gotoxy(WAITPOS,0);
			opentext(filename);
			lastl=UNKNOWN; 
			lastread=0; 
			goteof=NO;
			initvm();
			gettext(cline);
			errmess=NULL;
			putstatusline(cline);
			}
		return NO;
		}
}

xit()		/*leave the editor, either by returning to CCP or by
		warm booting, according to X option*/
{
	unsigned *cpm;
	char *bdosbase;
	int *six, *errbase,i;

	six=6;
	bdosbase=*six;
	errbase=bdosbase+3;
	for (i=0; i < 4; i++) *(errbase+i)=errold[i];
	deleteline(0,23);
	gotoxy(0,22);
	if (wboot) exit();
	else {
		cpm=6;
		call(*cpm-6-CCP+0x75f);
		}
}

askforfile()	/*get another file to edit into 'filename' */
{
	int drive;
	
	while(YES) {
		printdirectory(curdsk);
		puts("File to edit\n |([return] to create a new file\n");
		puts(" |A:-P: to change default disk, [escape] to exit)| ? ");
		if (scans(filename,FILELEN) == ESCKEY) xit();
		if (strlen(filename) == 2 && filename[1] == ':') {
			if ( (drive=toupper(filename[0])-'A') >= 0 && drive < 16) {
				if (seldisk(drive)) continue;
				bdos(RESETDRV,1 << drive);
				curdsk=drive;
				}
			}
		else {
			name[0]='\0';
			return YES;
			}
		}
}

seldisk(drive)
int drive;
{
	if (dskcheck(setjmp(dskerr))) return FAIL;
	bdos(SELDSK,drive);
	return 0;
}
oto failed;
				}
			else {
				/*delete orig file*/
				if (funlink(filename) == FAIL) {
	failed: 			