/* Screen editor:  operating system module
 *		   C/80 version
 *
 * Source:  ed8.c
 * Version: June 19, 1981.
 */

/* define globals */

#include ed1.h


/* all calls to the operating system are made here.
 * only this module will have to be
 * rewritten for a new operating system.
 */

/* CP/M 2.2 versions of syscstat(), syscin(), syscout() */

/* return -1 if no character is ready from the console. 
 * otherwise, return the character.
 */

syscstat()
{
	return(bdos(6,-1));
}

/* wait for next character from the console.
 * do not echo it.
 */

syscin()
{
int c;
	while ((c=bdos(6,-1))==0) {
		;
	}
	return(c);
}

/* print character on the console */

syscout(c) char c;
{
	bdos(6,c);
	return(c);
}


/* print character on the printer */

syslout(c) char c;
{
	bdos(5,c);
	return(c);
}

/* open a file */

sysopen(name,mode) char *name, *mode;
{
int file;
int m;
	m=tolower(mode[0]);
	if (m=='r' || m=='w') {
		if ((file=fopen(name,mode))==0) {
			iormode='c';
			return(ERR);
		}
		else {
			iormode=m;
			return(file);
		}
	}
	else {
		iormode='c';
		syserr("fopen: bad mode");
		return(ERR);
	}
}

/* close a file */

sysclose(file) int file;
{
	if (iormode=='w') {
		/* write end of file byte */
		putc(0x1a,file);
	}
	iormode='c';
	fclose(file);
	return(OK);
}

/* read next char from file */

sysrdch(file) int file;
{
int c;
	if (iormode!='r') {
		error ("sysrdch:  read in w mode");
		return(ERR);
	}
	if ((c=getc(file))==-1) {
		return(EOF);
	}
	else if (c==0x1a) {
		return(EOF);
	}
	else if (c=='\n') {
		return (CR);
	}
	else {
		return(c);
	}
}

/* write next char to file */

syspshch(c,file) char c; int file;
{
char ch;
	if (iormode!='w') {
		error("syspshch:  write in r mode");
		return(ERR);
	}
	if (c==CR) {
		ch='\n';
	}
	else {
		ch=c;
	}
	if (putc(ch,file)==-1) {
		error("disk write failed");
		return(ERR);
	}
	else {
		return(c);
	}
}

/* read one char from END of file */

syspopch(file) int file;
{
	error("syspopch() not implemented");
	return(ERR);
}

/* check file name for syntax */

syschkfn(args) char *args;
{
	return(OK);
}

/* copy file name from args to buffer */

syscopfn(args,buffer) char *args, *buffer;
{
int n;
	n=0;
	while (n<(SYSFNMAX-1)) {
		if (args[n]==EOS) {
			break;
		}
		else {
			buffer[n]=args[n];
			n++;
		}
	}
	buffer[n]=EOS;
}

/* move a block of n bytes down (towards HIGH addresses).
 * block starts at source and the first byte goes to dest.
 *	src:[<--n-->]   dest:[       ]
 */

sysmovdn(n,dest,source) int n; char *dest, *source;
{
	if (n>0) {
#asm
	DB 0DDH,0E1H	;POP IX = return address in IX
	POP H		;source in HL
	POP D		;dest in DE
	POP B		;count in BC
	PUSH B		;restore args
	PUSH D
	PUSH H
	DB 0DDH,0E5H	;PUSH IX
	XCHG
	DAD B
	XCHG		;dest+count in DE
	DAD B		;source+count in HL
	INX B		;count+1 in BC
	DB 0EDH,0B8H	;LDDR
#endasm
	}
}

/* move a block of n bytes up (towards LOW addresses).
 * the block starts at source and the first byte goes to dest.
 *	dest:[       ]   src:[<--n-->]
 */

sysmovup(n,dest,source) int n; char *dest, *source;
{
	if (n>0) {
#asm
	DB 0DDH,0E1H	;POP IX = return address in IX
	POP H		;source in HL
	POP D		;dest in DE
	POP B		;count in BC
	PUSH B		;restore args
	PUSH D
	PUSH H
	DB 0DDH,0E5H	;PUSH IX
	DB 0EDH,0B0H	;LDIR
#endasm
	}
}

/*
Interfaces with operating system functions
*/

bdos(c,d) int c,d;
{
#asm
	POP H
	POP D
	POP B
	PUSH B
	PUSH D
	PUSH H
	CALL 5
#endasm
}
