[comp.sources.misc] MicroGnu for MSDOS

jpn@teddy.UUCP (John P. Nelson) (08/20/87)

MicroGnu, I am giving up, and posting this to the world.  This is an
update to the MicroGnu 1.0 distribution that supports IBM/MSDOS
operation.  This is a shell archive, suitable for extraction under
UNIX.  It will extract tty/ibmbios and sys/msdos directories.  The
source is verified to work under Microsoft C 4.0

This version of MSDOS mg uses BIOS calls exclusively.  This makes it a
bit more portable, at the expense of speed.  Obvious areas for
enhancement:  support screen formats other than 80 x 25 (all it would
take is code to recognize a different screen size).  This code
implements timeout prompts, the ALT key as meta, function keys, display
of 8 bit data, entering 8 bit data (use ALT-DDD to enter a "funny"
character.)

Note that there is one assembly language file (since the MSC 4.0 library
is flawed), but I have included the uuencoded object file for those without
an assembler.


John P. Nelson
   decvax!genrad!teddy!jpn
   seismo!mit-eddie!genrad!teddy!jpn
   ARPA!talcott!panda!teddy!jpn

---------------------- cut here ----------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	sys
#	tty
# This archive created: Thu Jul 30 13:26:13 1987
export PATH; PATH=/bin:$PATH
if test ! -d 'sys'
then
	echo shar: creating directory "'sys'"
	mkdir 'sys'
fi
if test ! -d 'sys/msdos'
then
	echo shar: creating directory "'sys/msdos'"
	mkdir 'sys/msdos'
fi
echo shar: extracting "'sys/msdos/ttyio.c'" '(1664 characters)'
if test -f 'sys/msdos/ttyio.c'
then
	echo shar: will not over-write existing file "'sys/msdos/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/msdos/ttyio.c'
/*
 * Name:	MicroEMACS
 *		MSDOS terminal I/O (MSC 4.0)
 *
 * The functions in this file
 * negotiate with the operating system for
 * keyboard characters, and write characters to
 * the display
 *
 * This version goes along with tty/ibmbios/tty.c.
 * Terminal size is determined there, rather than here.
 */
#include	"def.h"

#include	<sys/types.h>
#include	<fcntl.h>
#include	<signal.h>

static int ttyactivep = FALSE;		/* terminal in editor mode?	*/

int	nrow;				/* Terminal size, rows.		*/
int	ncol;				/* Terminal size, columns.	*/

/*
 * This function gets called once, to set up
 * the terminal channel.  This is essentially a no-op
 * on msdos, since I/O will all be done via bios calls.
 */
ttopen()
{
	if (ttyactivep)
		return;

	signal(SIGINT, SIG_IGN);

	nrow = 25;			/* initial guess */
	ncol = 80;

	ttyactivep = TRUE;
}

/*
 * This function gets called just
 * before we go back home to the shell. Another
 * MSDOS no_op.
 */
ttclose()
{
	if(!ttyactivep)
		return;
	ttyactivep = FALSE;
}

/********************************************************************/
/* ttputc, ttgetc & typeahead have been deleted from this file, and */
/* moved into the tty specific code.  There is no operating-system  */
/* generic way to do these                                          */
/********************************************************************/

/*
 * Flush output.  This function is a no-op
 */
ttflush()
{
}

/*
 * panic:  print error and die, leaving core file.
 */
panic(s)
char *s;
{
	fprintf(stderr, "%s\r\n", s);
	exit(1);
}


/*
** This should check the size of the window, and reset if needed.
*/

setttysize()
{
	nrow = 25;
	ncol = 80;
}

SHAR_EOF
if test 1664 -ne "`wc -c < 'sys/msdos/ttyio.c'`"
then
	echo shar: error transmitting "'sys/msdos/ttyio.c'" '(should have been 1664 characters)'
fi
fi
echo shar: extracting "'sys/msdos/fileio.c'" '(4544 characters)'
if test -f 'sys/msdos/fileio.c'
then
	echo shar: will not over-write existing file "'sys/msdos/fileio.c'"
else
cat << \SHAR_EOF > 'sys/msdos/fileio.c'
/*
 * Name:	MicroEMACS
 * 		MSDOS file I/O (MSC4.0)
 */
#include	"def.h"

#ifndef F_OK
#define F_OK	0
#define X_OK	1
#define W_OK	2
#define R_OK	4
#endif

/*
 * Move bytes, overlaps OK (daveb).
 *
 * MS/C 1.0 provides "memcpy", rather than bcopy.
 */
bcopy( from, to, cnt )
char *from;
char *to;
int cnt;
{
	memcpy(to, from, cnt);
}


static	FILE	*ffp;

/*
 * Open a file for reading.
 */
ffropen(fn)
char	*fn;
{
	if ((ffp=fopen(fn, "rb")) == NULL)
		return (FIOFNF);
	return (FIOSUC);
}

/*
 * Open a file for writing.
 * Return TRUE if all is well, and
 * FALSE on error (cannot create).
 */
ffwopen(fn)
char	*fn;
{
	if ((ffp=fopen(fn, "wb")) == NULL) {
		ewprintf("Cannot open file for writing");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Close a file.
 * Should look at the status.
 */
ffclose()
{
	(VOID) fclose(ffp);
	return (FIOSUC);
}

/*
 * Write a line to the already
 * opened file. The "buf" points to the
 * buffer, and the "nbuf" is its length, less
 * the free newline. Return the status.
 * Check only at the newline.
 */
ffputline(buf, nbuf)
register char	buf[];
{
	register int	i;

	for (i=0; i<nbuf; ++i)
		putc(buf[i]&0xFF, ffp);
	putc('\r', ffp);	/* MSDOS wants \r\n line seperators */
	putc('\n', ffp);
	if (ferror(ffp) != FALSE) {
		ewprintf("Write I/O error");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Read a line from a file, and store the bytes
 * in the supplied buffer. Stop on end of file or end of
 * line. Don't get upset by files that don't have an end of
 * line on the last line; this seem to be common on CP/M-86 and
 * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
 * has not been confirmed. If this is sufficiently researched
 * it may be possible to pull this kludge). Delete any CR
 * followed by an LF. This is mainly for runoff documents,
 * both on VMS and on Ultrix (they get copied over from
 * VMS systems with DECnet).
 */
ffgetline(buf, nbuf)
register char	buf[];
{
	register int	c;
	register int	i;

	i = 0;
	for (;;) {
		c = getc(ffp);
		if (c == '\r') {		/* Delete any non-stray	*/
			c = getc(ffp);		/* carriage returns.	*/
			if (c != '\n') {
				if (i >= nbuf-1) {
					ewprintf("File has long line");
					return (FIOERR);
				}
				buf[i++] = '\r';
			}
		}
		if (c==EOF || c=='\n')		/* End of line.		*/
			break;
		if (i >= nbuf-1) {
			ewprintf("File has long line");
			return (FIOERR);
		}
		buf[i++] = c;
	}
	if (c == EOF) {				/* End of file.		*/
		if (ferror(ffp) != FALSE) {
			ewprintf("File read error");
			return (FIOERR);
		}
		if (i == 0)			/* Don't get upset if	*/
			return (FIOEOF);	/* no newline at EOF.	*/
	}
	buf[i] = 0;
	return (FIOSUC);
}

#ifdef	BACKUP
/*
 * Rename the file "fname" into a backup copy.
 * On Unix the backup has the same name as the
 * original file, with a "~" on the end - unfortunately
 * this does not map well to MS-DOS - the old .bak convention
 * is used.
 */
fbackupfile(fname)
char	*fname;
{
	register char	*nname, *ptr;
	char *strchr();

	if ((nname=malloc(strlen(fname)+3+1)) == NULL)
		return (ABORT);
	(void) strcpy(nname, fname);
	if (ptr = strchr(nname, '.'))
	    strcpy(ptr, ".bak")
	else
	    strcat(ptr, ".bak")

	if (strcmp(fname, nname) == 0) {
		free(nname);
		return FALSE;
	}

	(void) unlink(nname);		/* Ignore errors.	*/
	(void) rename(fname, nname);
	free(nname);
	return (TRUE);
}
#endif

/*
 * The string "fn" is a file name.
 * Perform any required case adjustments. All sustems
 * we deal with so far have case insensitive file systems.
 * We zap everything to lower case. The problem we are trying
 * to solve is getting 2 buffers holding the same file if
 * you visit one of them with the "caps lock" key down.
 * On UNIX file names are dual case, so we leave
 * everything alone.
 */
/*ARGSUSED*/
adjustcase(fn)
register char	*fn;
{
	register int	c;

	while ((c = *fn) != 0) {
		if (c>='A' && c<='Z')
			*fn = c + 'a' - 'A';
		++fn;
	}
}



#ifdef	STARTUP
#include <sys/types.h>
#define STARTUPNAME ".mg"
/*
 * find the users startup file, and return it's name. Check for
 * if MGSTARTUP is defined, then use that.   Otherwise, look
 * for .mg in the current directory, then in the root directory.
 */
char *
startupfile() 
{
	register char	*file;
	static char	temp[NFILEN];
	char		*getenv();

	if ((file = getenv("MGSTARTUP")) != NULL )
		{
		if (access(file, F_OK ) == 0)
		    return file;
		return NULL;
		}
	if (access (STARTUPNAME, F_OK) == 0)
		return STARTUPNAME;
	strcpy(temp, "/");
	strcat(temp, STARTUPNAME);
	if (access (temp, F_OK) == 0)
		return temp;
	return NULL;
}
#endif
SHAR_EOF
if test 4544 -ne "`wc -c < 'sys/msdos/fileio.c'`"
then
	echo shar: error transmitting "'sys/msdos/fileio.c'" '(should have been 4544 characters)'
fi
fi
echo shar: extracting "'sys/msdos/goodmake.mak'" '(1906 characters)'
if test -f 'sys/msdos/goodmake.mak'
then
	echo shar: will not over-write existing file "'sys/msdos/goodmake.mak'"
else
cat << \SHAR_EOF > 'sys/msdos/goodmake.mak'
# Makefile for MicroEMACS for MSDOS (Microsoft C 4.0).
# this makefile designed for a better "make" than microsofts!
# Anyway, this uses the "compact" model (small code, big data).

SYS	= msdos
TTY	= ibmbios

# CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
# get passed to lint.
CDEFS	= -DDPROMPT -DSTARTUP
#CFLAGS	= -Zi -Od -Mc $(CDEFS)
CFLAGS	= -Mc $(CDEFS)

OBJ1 =	basic.obj buffer.obj cinfo.obj display.obj echo.obj extend.obj
OBJ2 =	file.obj kbd.obj line.obj main.obj match.obj random.obj region.obj
OBJ3 =	search.obj symbol.obj version.obj window.obj paragrap.obj prefix.obj
OBJ4 =	word.obj fileio.obj spawn.obj ttyio.obj tty.obj ttykbd.obj pollkbd.obj
OBJ =	$(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4)

OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
SRCS =	basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
	line.c main.c match.o random.c region.c search.c symbol.c version.c \
	window.c word.c paragrap.c prefix.c
OINCS =	ttydef.h sysdef.h
INCS =	def.h

mg.exe:		$(OBJ)
#		$(CC) $(CFLAGS) -o mg $(OBJ) $(LIBS)
		@echo $(OBJ1)+ >  __link__.tmp
		@echo $(OBJ2)+ >> __link__.tmp
		@echo $(OBJ3)+ >> __link__.tmp
		@echo $(OBJ4)  >> __link__.tmp
		@echo $@/NOI/CO >> __link__.tmp
		@echo mg;      >> __link__.tmp
		link @__link__.tmp
		@del __link__.tmp


$(OBJ):		def.h sysdef.h ttydef.h

sysdef.h:	sys/$(SYS)/sysdef.h	# Update links, if needed.
		copy sys/$(SYS)/sysdef.h

ttydef.h:	tty/$(TTY)/ttydef.h
		copy tty/$(TTY)/ttydef.h

fileio.c:	sys/$(SYS)/fileio.c
		copy sys/$(SYS)/fileio.c

spawn.c:	sys/$(SYS)/spawn.c
		copy sys/$(SYS)/spawn.c

tty.c:		tty/$(TTY)/tty.c
		copy tty/$(TTY)/tty.c

ttyio.c:	sys/$(SYS)/ttyio.c
		copy sys/$(SYS)/ttyio.c

ttykbd.c:	tty/$(TTY)/ttykbd.c
		copy tty/$(TTY)/ttykbd.c

pollkbd.asm	tty/$(TTY)/pollkbd.asm
		copy tty/$(TTY)/pollkbd.asm

pollkbd.obj:	pollkbd.asm
		masm pollkbd,pollkbd/ml;

clean:;		-del $(OBJ) $(OSRCS) $(OINCS)
SHAR_EOF
if test 1906 -ne "`wc -c < 'sys/msdos/goodmake.mak'`"
then
	echo shar: error transmitting "'sys/msdos/goodmake.mak'" '(should have been 1906 characters)'
fi
fi
echo shar: extracting "'sys/msdos/makefile'" '(2258 characters)'
if test -f 'sys/msdos/makefile'
then
	echo shar: will not over-write existing file "'sys/msdos/makefile'"
else
cat << \SHAR_EOF > 'sys/msdos/makefile'
# Makefile for MicroEMACS for MSDOS (Microsoft C 4.0).
# This makefile designed for microsoft 4.0 make, which is a stupid program.
# Anyway, this uses the "compact" model (small code, big data).

SYS=MSDOS
TTY=IBMBIOS

# CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
# get passed to lint.
CDEFS=-DDPROMPT -DSTARTUP
#CFLAGS=-Zi -Od -Mc $(CDEFS)
CFLAGS=-Mc $(CDEFS)

OBJ1=BASIC.OBJ BUFFER.OBJ CINFO.OBJ DISPLAY.OBJ ECHO.OBJ EXTEND.OBJ
OBJ2=FILE.OBJ KBD.OBJ LINE.OBJ MAIN.OBJ MATCH.OBJ RANDOM.OBJ REGION.OBJ
OBJ3=SEARCH.OBJ SYMBOL.OBJ VERSION.OBJ WINDOW.OBJ PARAGRAP.OBJ PREFIX.OBJ
OBJ4=WORD.OBJ FILEIO.OBJ SPAWN.OBJ TTYIO.OBJ TTY.OBJ TTYKBD.OBJ POLLKBD.OBJ
OBJ=$(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4)

OSRCS=FILEIO.C SPAWN.C TTYIO.C TTY.C TTYKBD.C
OINCS=TTYDEF.H SYSDEF.H
INCS=DEF.H

I=$(OINCS) $(INCS)

.C.OBJ:
	cl -c $(CFLAGS) $*.C

# Update links, if needed.

SYSDEF.H: SYS\$(SYS)\SYSDEF.H
		COPY SYS\$(SYS)\SYSDEF.H

TTYDEF.H:	TTY\$(TTY)\TTYDEF.H
		COPY TTY\$(TTY)\TTYDEF.H

FILEIO.C:	SYS\$(SYS)\FILEIO.C
		COPY SYS\$(SYS)\FILEIO.C

SPAWN.C:	SYS\$(SYS)\SPAWN.C
		COPY SYS\$(SYS)\SPAWN.C

TTY.C:		TTY\$(TTY)\TTY.C
		COPY TTY\$(TTY)\TTY.C

TTYIO.C:	SYS\$(SYS)\TTYIO.C
		COPY SYS\$(SYS)\TTYIO.C

TTYKBD.C:	TTY\$(TTY)\TTYKBD.C
		COPY TTY\$(TTY)\TTYKBD.C

POLLKBD.OBJ: POLLKBD.ASM
		MASM POLLKBD,POLLKBD/ml;

BASIC.OBJ: BASIC.C $(I)

BUFFER.OBJ: BUFFER.C $(I)

CINFO.OBJ: CINFO.C $(I)

DISPLAY.OBJ: DISPLAY.C $(I)

ECHO.OBJ: ECHO.C $(I)

EXTEND.OBJ: EXTEND.C $(I)

FILE.OBJ: FILE.C $(I)

KBD.OBJ: KBD.C $(I)

LINE.OBJ: LINE.C $(I)

MAIN.OBJ: MAIN.C $(I)

MATCH.OBJ: MATCH.C $(I)

RANDOM.OBJ: RANDOM.C $(I)

REGION.OBJ: REGION.C $(I)

SEARCH.OBJ: SEARCH.C $(I)

SYMBOL.OBJ: SYMBOL.C $(I)

VERSION.OBJ: VERSION.C $(I)

WINDOW.OBJ: WINDOW.C $(I)

PARAGRAP.OBJ: PARAGRAP.C $(I)

PREFIX.OBJ: PREFIX.C $(I)

WORD.OBJ: WORD.C $(I)

FILEIO.OBJ: FILEIO.C $(I)

SPAWN.OBJ: SPAWN.C $(I)

TTYIO.OBJ: TTYIO.C $(I)

TTY.OBJ: TTY.C $(I)

TTYKBD.OBJ: TTYKBD.C $(I)

MG.EXE:	$(OBJ)
		echo $(OBJ1)+ >  __link__.tmp
		echo $(OBJ2)+ >> __link__.tmp
		echo $(OBJ3)+ >> __link__.tmp
		echo $(OBJ4)  >> __link__.tmp
		echo $@/NOI/CO >> __link__.tmp
		echo mg;      >> __link__.tmp
		link @__link__.tmp
		del __link__.tmp

#CLEAN:
#		del $(OBJ) $(OSRCS) $(OINCS)
SHAR_EOF
if test 2258 -ne "`wc -c < 'sys/msdos/makefile'`"
then
	echo shar: error transmitting "'sys/msdos/makefile'" '(should have been 2258 characters)'
fi
fi
echo shar: extracting "'sys/msdos/sysdef.h'" '(665 characters)'
if test -f 'sys/msdos/sysdef.h'
then
	echo shar: will not over-write existing file "'sys/msdos/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/msdos/sysdef.h'
/*
 * Name:	MicroEMACS
 *		MSDOS system header file (MSC4.0)
 */

#define PCC				/* [] doesnt work 		*/
#define	KBLOCK	1024			/* Kill grow.			*/
#define	GOOD	0			/* Good exit status.		*/

typedef int	RSIZE;			/* Type for file/region sizes	*/
typedef short	KEY;			/* Type for internal keystrokes	*/

/*
 * Macros used by the buffer name making code.
 * Start at the end of the file name, scan to the left
 * until BDC1 (or BDC2, if defined) is reached. The buffer
 * name starts just to the right of that location, and
 * stops at end of string (or at the next BDC3 character,
 * if defined). BDC2 and BDC3 are mainly for VMS.
 */
#define	BDC1	'/'
#define	BDC2	'\\'
SHAR_EOF
if test 665 -ne "`wc -c < 'sys/msdos/sysdef.h'`"
then
	echo shar: error transmitting "'sys/msdos/sysdef.h'" '(should have been 665 characters)'
fi
fi
echo shar: done with directory "'sys/msdos'"
echo shar: done with directory "'sys'"
if test ! -d 'tty'
then
	echo shar: creating directory "'tty'"
	mkdir 'tty'
fi
if test ! -d 'tty/ibmbios'
then
	echo shar: creating directory "'tty/ibmbios'"
	mkdir 'tty/ibmbios'
fi
echo shar: extracting "'tty/ibmbios/tty.c'" '(6473 characters)'
if test -f 'tty/ibmbios/tty.c'
then
	echo shar: will not over-write existing file "'tty/ibmbios/tty.c'"
else
cat << \SHAR_EOF > 'tty/ibmbios/tty.c'
/*
 * MicroEMACS
 *   IBM-PC and compatible BIOS based display driver.
 *   - this will tend to be a bit slower than a driver that
 *     writes directly to the memory mapped screen, but with
 *     the large # of display adapters floating around, I'd
 *     rather let the bios do the work.
 * 
 *     I DO recommend FANSI-CONSOLE which significantly speeds
 *     up display bios calls, however.
 */
#include	"def.h"
#include	<dos.h>

#define	BEL	0x07			/* BEL character.		*/

extern	int	ttrow;
extern	int	ttcol;
extern	int	tttop;
extern	int	ttbot;
extern	int	tthue;

static int biocol = 0;

int	tceeol = 2;			/* Costs are set later */
int	tcinsl = 5;
int	tcdell = 5;

static	int insdel = TRUE;	/* Do we have both insert & delete line? */
static int rendition =0x07;

int	ttputc();

/*
 * Initialize the terminal when the editor
 * gets started up.
 */
ttinit() {
}

/*
 * Clean up the terminal, in anticipation of
 * a return to the command interpreter.
 */
tttidy() {
}

/*
 * Move the cursor to the specified
 * origin 0 row and column position.
 */
ttmove(row, col) {
    ttcol = col;
    ttrow = row;
    _move(row, col);
}

_move(row, col) {
    union REGS rg;

    biocol = col;
    rg.h.ah = 2;		/* set cursor position function code */
    rg.h.dl = col;
    rg.h.dh = row;
    rg.h.bh = 0;		/* set screen page number */
    int86(0x10, &rg, &rg);
}

/*
 * Erase to end of line.
 */
tteeol() {
    union REGS rg;

    rg.h.ah = 9;	/* write character/rendition */
    rg.h.bh = 0;
    rg.x.cx = ncol-biocol;
    rg.h.al = ' ';
    rg.h.bl = rendition;

    int86(0x10, &rg, &rg);
}

/*
 * Erase to end of page.
 */
tteeop() {
    ttdell(ttrow, nrow, nrow - ttrow);
}

/*
 * Make a noise.
 */
ttbeep() {
    union REGS rg;

    rg.h.ah = 14;	/* write tty */
    rg.h.al = BEL;

    int86(0x10, &rg, &rg);
}

/*
 * Insert nchunk blank line(s) onto the
 * screen, scrolling the last line on the
 * screen off the bottom.
 */
ttinsl(row, bot, nchunk) {
    union REGS rg;
    
    if (row == bot) {		/* Case of one line insert is 	*/
	ttmove(row, 0);		/*	special			*/
	tteeol();
	return;
    }

    rg.h.ah = 7;	/* scroll down */
    rg.h.bh = 0x07;
    rg.h.al = nchunk;
    rg.h.ch = row;
    rg.h.cl = 0;
    rg.h.dh = bot;
    rg.h.dl = ncol - 1;

    int86(0x10, &rg, &rg);
}

/*
 * Delete nchunk line(s) from "row", replacing the
 * bottom line on the screen with a blank line. 
 */

ttdell(row, bot, nchunk)
{
    union REGS rg;

    if (row == bot) {		/* One line special case	*/
	ttmove(row, 0);
	tteeol();
	return;
    }
    rg.h.ah = 6;	/* scroll up */
    rg.h.bh = 0x07;
    rg.h.al = nchunk;
    rg.h.ch = row;
    rg.h.cl = 0;
    rg.h.dh = bot;
    rg.h.dl = ncol - 1;

    int86(0x10, &rg, &rg);
}

/*
 * Switch to full screen scroll. This is
 * used by "spawn.c" just before is suspends the
 * editor, and by "display.c" when it is getting ready
 * to exit.
 */
ttnowindow()
{
}

/*
 * Set the current writing color to the
 * specified color. Watch for color changes that are
 * not going to do anything (the color is already right)
 * and don't send anything to the display.
 * The rainbow version does this in putline.s on a
 * line by line basis, so don't bother sending
 * out the color shift.
 */
ttcolor(color) register int color; {
    if (color != tthue) {
	if (color == CTEXT) {		/* Normal video.	*/
	    rendition = 0x07;
	} else if (color == CMODE) {	/* Reverse video.	*/
	    rendition = 0x70;
	}
	tthue = color;			/* Save the color.	*/
    }
}

/*
 * This routine is called by the
 * "refresh the screen" command to try and resize
 * the display. The new size, which must be deadstopped
 * to not exceed the NROW and NCOL limits, it stored
 * back into "nrow" and "ncol". Display can always deal
 * with a screen NROW by NCOL. Look in "window.c" to
 * see how the caller deals with a change.
 */
ttresize() {
	setttysize();
}

/* calculate the cost of doing string s */
charcost (s) char *s; {
    return strlen(s);
}

ttputc(c)
unsigned char c;
{
    union REGS rg;

    if (c == '\b') {
	if (biocol-1 > 0) {
	    _move(ttrow, biocol-1);
	}
	return;
    }
    rg.h.ah = 9;	/* write character/rendition */
    rg.h.bh = 0;
    rg.x.cx = 1;
    rg.h.al = c;
    rg.h.bl = rendition;

    int86(0x10, &rg, &rg);

    if (biocol+1 >= ncol)
	_move(ttrow + 1, 0);
    else
	_move(ttrow, biocol + 1);
}

struct nap
    {
    long napvalue;
    long basetime;
    };

ttwait()
    {
    struct nap timer;
    napstart(200, &timer);
    while (napchk(&timer) == 0)
	if (typeahead())
	    return 0;
    return 1;
    }

/***************************/
/* MSDOS time functions    */
/***************************/

#define gettime(_a) ((((long)(_a.x.cx)) << 16)+_a.x.dx)
sleep(amount)
    {
    while (amount--)
	nap(100);
    }

/* nap in units of 100ths of seconds via busy loops. */
nap(amount)
    {
    struct nap tim;
    napstart(amount, &tim);
    while(napchk(&tim) == 0)
	;
    }

napstart(amount,sav)
int amount;
register struct nap *sav;
    {
    union REGS inregs, outregs;
    int hunds, secs;

    inregs.h.ah = 0x2c;			/* get time */
    int86(0x21, &inregs, &outregs);

    /* glitch in hardware RTC (time warp) makes this necessary */
    inregs = outregs;
    inregs.h.dl = 0;		/* seconds counter may be slow to increment */
    if (inregs.h.dh > 0)
	--inregs.h.dh;		/* paranoia */
    if (inregs.h.cl > 0)
	--inregs.h.cl;		/* more paranoia */
    /* end of glitch handling */

    sav->basetime = gettime(inregs);	/* in case of wraparound */

    /* convert hundredths of seconds to future time structure */
    secs = outregs.h.dh;
    hunds = outregs.h.dl + amount;

    while (hunds >= 100) {
	hunds -= 100;
	++secs;
    }
    outregs.h.dl = hunds;
    while (secs >= 60) {
	secs -= 60;
	++outregs.h.cl;			/* increment minutes */
    }
    outregs.h.dh = secs;

    /* check for minute and hour wraparound */
    if (outregs.h.cl >= 60)
	{
	outregs.h.cl -= 60;
	++outregs.h.ch;			/* increment hours */
	}
    if (outregs.h.ch >= 24)
	{
	outregs.h.ch -= 24;
	}
    sav->napvalue = gettime(outregs);
    }

napchk(sav)
register struct nap *sav;
    {
    union REGS inregs, outregs;
    long current;

    inregs.h.ah = 0x2c;			/* get time */
    int86(0x21, &inregs, &outregs);

    current = gettime(outregs);

    if(sav->napvalue > sav->basetime)
	{
	if (current >= sav->napvalue || current < sav->basetime)
	    return 1;
	}
    else if (current >= sav->napvalue && current < sav->basetime)
	return 1;
    return 0;
    }

SHAR_EOF
if test 6473 -ne "`wc -c < 'tty/ibmbios/tty.c'`"
then
	echo shar: error transmitting "'tty/ibmbios/tty.c'" '(should have been 6473 characters)'
fi
fi
echo shar: extracting "'tty/ibmbios/README'" '(468 characters)'
if test -f 'tty/ibmbios/README'
then
	echo shar: will not over-write existing file "'tty/ibmbios/README'"
else
cat << \SHAR_EOF > 'tty/ibmbios/README'
pollkbd.asm is required because the Microsoft C compiler library has no
way to get the 'Z' flag back from the tty bios "poll" function.  This is
a real botch, since I reported this bug to Microsoft back in the MSC 3.0 days.

Anyway, if you don't own "masm", you can "uudecode" the file "pollkbd.uu",
which will generate the binary file POLLKBD.OBJ.

My next version of "mg" for MESSYDOS will probably use TurboC, where this
is trivial to do WITHOUT assembly language.
SHAR_EOF
if test 468 -ne "`wc -c < 'tty/ibmbios/README'`"
then
	echo shar: error transmitting "'tty/ibmbios/README'" '(should have been 468 characters)'
fi
fi
echo shar: extracting "'tty/ibmbios/pollkbd.asm'" '(519 characters)'
if test -f 'tty/ibmbios/pollkbd.asm'
then
	echo shar: will not over-write existing file "'tty/ibmbios/pollkbd.asm'"
else
cat << \SHAR_EOF > 'tty/ibmbios/pollkbd.asm'
	TITLE   pollkbd

_TEXT	SEGMENT  BYTE PUBLIC 'CODE'
_TEXT	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
DGROUP	GROUP	CONST,	_BSS,	_DATA
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP

PUBLIC  _pollkbd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_TEXT	SEGMENT  BYTE PUBLIC 'CODE'
_pollkbd	PROC NEAR
	mov	ah,1
	int	16H
	jz	zero
	mov	ax,1
	ret
zero:
	xor	ax,ax
	ret
_pollkbd	ENDP
_TEXT	ENDS
	END
SHAR_EOF
if test 519 -ne "`wc -c < 'tty/ibmbios/pollkbd.asm'`"
then
	echo shar: error transmitting "'tty/ibmbios/pollkbd.asm'" '(should have been 519 characters)'
fi
fi
echo shar: extracting "'tty/ibmbios/ttydef.h'" '(907 characters)'
if test -f 'tty/ibmbios/ttydef.h'
then
	echo shar: will not over-write existing file "'tty/ibmbios/ttydef.h'"
else
cat << \SHAR_EOF > 'tty/ibmbios/ttydef.h'
/*
 *	Termcap terminal file, nothing special, just make it big
 *	enough for windowing systems.
 */

#define	GOSLING			/* Compile in fancy display.	*/
/* #define	MEMMAP		*/	/* Not memory mapped video.	*/

#define	NROW	25    			/* Rows.			*/
#define	NCOL	80			/* Columns.			*/
#define	MOVE_STANDOUT			/* don't move in standout mode	*/
/* #define	STANDOUT_GLITCH		/* possible standout glitch	*/

#define KHOME	K01
#define KDOWN	K02
#define	KUP	K03
#define	KLEFT	K04
#define	KRIGHT	K05
#define	KPGUP	K06
#define	KPGDN	K07
#define	KEND	K08
#define	KDELETE	K09
#define	KINSERT	K0A
#define	KF1	K0B
#define KF2	K0C
#define KF3	K0D
#define KF4	K0E
#define KF5	K0F
#define KF6	K10
#define KF7	K11
#define KF8	K12
#define	KF9	K13
#define KF10	K14
#define	KF11	K15
#define	KF12	K16
#define	KF13	K17
#define	KF14	K18
#define	KF15	K19
#define	KF16	K1A
#define	KF17	K1B
#define	KF18	K1C
#define	KF19	K1D
#define	KF20	K1E
SHAR_EOF
if test 907 -ne "`wc -c < 'tty/ibmbios/ttydef.h'`"
then
	echo shar: error transmitting "'tty/ibmbios/ttydef.h'" '(should have been 907 characters)'
fi
fi
echo shar: extracting "'tty/ibmbios/pollkbd.uu'" '(244 characters)'
if test -f 'tty/ibmbios/pollkbd.uu'
then
	echo shar: will not over-write existing file "'tty/ibmbios/pollkbd.uu'"
else
cat << \SHAR_EOF > 'tty/ibmbios/pollkbd.uu'
begin 644 POLLKBD.OBJ
M@ D !W!O;&QK8F2(EBX   -"4U,$0T]$105#3TY35 1$051!!D1'4D]54 1?
M0E-3!5]$051!!5]415A4/Y@' "@-  D# 1^8!P!(   $! $0F < 2   !P(!
M#Y@' $@   @% 0N:"  &_P+_ _\$4J 1  $  +0!S19T!+@! ,,SP,,,D \ 
4  $(7W!O;&QK8F0    1B@(  '0$
 
end
SHAR_EOF
if test 244 -ne "`wc -c < 'tty/ibmbios/pollkbd.uu'`"
then
	echo shar: error transmitting "'tty/ibmbios/pollkbd.uu'" '(should have been 244 characters)'
fi
fi
echo shar: extracting "'tty/ibmbios/ttykbd.c'" '(3016 characters)'
if test -f 'tty/ibmbios/ttykbd.c'
then
	echo shar: will not over-write existing file "'tty/ibmbios/ttykbd.c'"
else
cat << \SHAR_EOF > 'tty/ibmbios/ttykbd.c'
/*
 * Name:	MicroEmacs
 *		IBM BIOS keyboard driver
 *
 */

#include	"def.h"
#include	<dos.h>

char	*keystrings[] = {
	NULL,		"Home",		"Down-Arrow",	"Up-Arrow",
	"Left-Arrow",	"Right-Arrow",	"Page-Up",	"Page-Down",
	"End",		"Delete",	"Insert",	"F1",
	"F2",		"F3",		"F4",		"F5",
	"F6",		"F7",		"F8",		"F9",
	"F10",		"F11",		"F12",		"F13",
	"F14",		"F15",		"F16",		"F17",
	"F18",		"F19",		"F20",		NULL,
};

/* convert IBM bios extended scan codes to appropriate function key values */
static KEY extended[] = {
	-1,		-1,		-1,		0,	  /* 0-3 */
	-1,		-1,		-1,		-1,	  /* 4-7 */
	-1,		-1,		-1,		-1,	  /* 8-11 */
	-1,		-1,		-1,		-1,	  /* 12-15 */
	KMETA|'Q',	KMETA|'W',	KMETA|'E',	KMETA|'R',/* 16-19 */
	KMETA|'T',	KMETA|'Y',	KMETA|'U',	KMETA|'I',/* 20-23 */
	KMETA|'O',	KMETA|'P',	-1,		-1,	  /* 24-27 */
	-1,		-1,		KMETA|'A',	KMETA|'S',/* 28-31 */
	KMETA|'D',	KMETA|'F',	KMETA|'G',	KMETA|'H',/* 32-35 */
	KMETA|'J',	KMETA|'K',	KMETA|'L',	-1,	  /* 36-39 */
	-1,		-1,		-1,		-1,	  /* 40-43 */
	KMETA|'Z',	KMETA|'X',	KMETA|'C',	KMETA|'V',/* 44-47 */
	KMETA|'B',	KMETA|'N',	KMETA|'M',	-1,	  /* 48-51 */
	-1,		-1,		/* oops - miscounted */	  /* 52-53 */
	-1,		-1,		-1,		-1,	  /* 54-57 */
	-1,		KF1,		KF2,		KF3,	  /* 58-61 */
	KF4,		KF5,		KF6,		KF7,	  /* 62-65 */
	KF8,		KF9,		KF10,		-1,	  /* 66-69 */
	-1,		KHOME,		KUP,		KPGUP,	  /* 70-73 */
	-1,		KLEFT,		-1,		KRIGHT,	  /* 74-77 */
	-1,		KEND,		KDOWN,		KPGDN,	  /* 78-81 */
	KINSERT,	KDELETE,	KF11,		KF12,	  /* 82-85 */
	KF13,		KF14,		KF15,		KF16,	  /* 86-89 */
	KF17,		KF18,		KF19,		KF20,	  /* 90-93 */
	KF11,		KF12,		KF13,		KF14,	  /* 94-97 */
	KF15,		KF16,		KF17,		KF18,	  /* 98-101 */
	KF19,		KF20,		KF11,		KF12,	  /* 102-105 */
	KF13,		KF14,		KF15,		KF16,	  /* 106-109 */
	KF17,		KF18,		KF19,		KF20,	  /* 110-113 */
};

#define NEXTENDED (sizeof(extended)-sizeof(KEY))

static KEY savedkey = -1;

getkbd() {
    return (ttgetc());
}

/*
 * Get keyboard character, and interpret
 * any special keys on the keyboard.
 */
ttgetc() {
    KEY temp;

    while (savedkey == -1)
	getakey();

    temp = savedkey;
    savedkey = -1;
    return temp;
}

getakey() {
    union REGS rg;

    rg.h.ah = 0;		/* read keyboard */
    int86(0x16, &rg, &rg);
    if (rg.h.al) {
	if (rg.h.al == '\b' && rg.h.ah == 0x0E)
	    rg.h.al = 0x7F;	/* transform backspace key into delete */
	savedkey = rg.h.al;	/* normal key value */
    }
    else {
	if (rg.h.ah >= NEXTENDED)
	    savedkey = -1;
	else
	    savedkey = extended[rg.h.ah];
    }
}

typeahead() {
    if (savedkey != -1)
	return 1;
    if (pollkbd())
	getakey();
    return (savedkey != -1);
}

ttykeymapinit() {
	/*
	 * Bind things to the movement keys
	 */
	keydup(KHOME,	"beginning-of-buffer");	/* for now */
	keydup(KUP,	"previous-line");
	keydup(KDOWN,	"next-line");
	keydup(KLEFT,	"backward-char");
	keydup(KRIGHT,	"forward-char");
	keydup(KEND,	"end-of-buffer");
	keydup(KPGUP,	"scroll-down");		/* Prev Screen	*/
	keydup(KPGDN,	"scroll-up");		/* Next Screen	*/
	keydup(KINSERT,	"open-line");
	keydup(KDELETE,	"delete-char");
}
SHAR_EOF
if test 3016 -ne "`wc -c < 'tty/ibmbios/ttykbd.c'`"
then
	echo shar: error transmitting "'tty/ibmbios/ttykbd.c'" '(should have been 3016 characters)'
fi
fi
echo shar: done with directory "'tty/ibmbios'"
echo shar: done with directory "'tty'"
exit 0
#	End of shell archive

jpn@teddy.UUCP (John P. Nelson) (08/22/87)

My face is a bit red.  My recent posting of MicroGnu for MSDOS was
missing a file, spawn.c (actually sys/msdos/spawn.c).  Here is spawn.c
(not shar format)

/*
 * Name:	MicroEMACS spawn.c
 *		Spawn CLI for MSDOS (MSC4.0)
 *
 */
#include	"def.h"
#include	<process.h>

extern	char	*getenv();

/*
 * On MSDOS, we got no job control like system V, so always
 * run a subshell. Bound to "C-C", and used
 * as a subcommand by "C-Z". (daveb)
 *
 * Returns 0 if the shell executed OK, something else if
 * we couldn't start shell or it exited badly.
 */
spawncli(f, n, k)
{
	char *comspec;
	int		errp = FALSE;

	ttcolor(CTEXT);
	ttnowindow();
	ttmove(nrow-1, 0);
	if (epresf != FALSE) {
		tteeol();
		epresf = FALSE;
	}
	ttclose();
	sgarbf = TRUE;				/* Force repaint.	*/
	if ((comspec = getenv("COMSPEC")) == NULL)
		errp = -1;
	else
		errp = spawnl(P_WAIT, comspec, "COMMAND.COM", (char *)NULL);

	ttopen();
	if(errp == -1)
		ewprintf("Failed to create process");

	return ( e thatansl