#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 11 (of 13)."
# Contents:  stevie/dos.c
# Wrapped by thor@surt on Fri Oct 16 09:43:47 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'stevie/dos.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/dos.c'\"
else
echo shar: Extracting \"'stevie/dos.c'\" \(23301 characters\)
sed "s/^X//" >'stevie/dos.c' <<'END_OF_FILE'
X/* $Header:
X *
X * MSDOS support for Stevie.
X * Many of the functions in this file have two versions:
X *   -	The original version, using ANSI escape sequences
X *	(by Tim Thompson and/or Tony Andrews).
X *	It requires a non-IBM ANSI driver, such as the shareware NANSI.SYS.
X *   -	The BIOS-function version (by Larry A. Shurr).  The BIOS version
X *	doesn't require an enhanced console driver such as NANSI.SYS.
X *	Invoke it by #defining BIOS in ENV.H.
X * Dave Tutelman has incorporated many features of Larry Shurr's BIOS
X * version (such as colors and 43-line mode) into the ANSI version.
X */
X
X#include "stevie.h"
X#include <stdio.h>
X#include <dos.h>
X#include <signal.h>
X
Xchar	*getenv();
X
Xstatic	char	getswitch();
Xstatic	void	setswitch();
X
X#ifdef BIOS
Xvoid bios_t_ed();
Xvoid bios_t_el();
X#endif
X
Xenum hostval_e {hIBMPC, hTIPRO};
Xtypedef enum hostval_e hostval;
Xstatic	hostval	host_type   = 0;	/* Gets host computer type */
X
Xstatic	char	bgn_color   = 0x7;	/* For saving orig color */
Xstatic	char	quitting_now= 0;	/* Set for windexit() */
Xstatic	int	crt_int     = 0;	/* Gets CRT BIOS interrupt */
Xstatic	char	bgn_page    = 0;	/* For saving current page (IBM PC) */
Xstatic	char	bgn_mode    = 0;	/* For saving video mode (IBM PC) */
X
X#ifdef BIOS
Xstatic	int	sav_curattr = 0;	/* For saving cursor attributes */
Xstatic	int	sav_curpos  = 0;	/* For saving cursor position */
X#endif
X
X/*
X * inchar() - get a character from the keyboard
X */
Xint
Xinchar()
X{
X	int	c;
X
X	got_int = FALSE;
X
X	for (;;beep()) {	/* loop until we get a valid character */
X
X		flushbuf();	/* flush any pending output */
X
X		switch (c = getch()) {
X		case 0x1e:
X			return K_CCIRCM;
X		case 0:				/* special key */
X			if (State != NORMAL) {
X				c = getch();	/* throw away next char */
X				continue;	/* and loop for another char */
X			}
X			switch (c = getch()) {
X			case 0x50:
X				return K_DARROW;
X			case 0x48:
X				return K_UARROW;
X			case 0x4b:
X				return K_LARROW;
X			case 0x4d:
X				return K_RARROW;
X			case 0x47:		/* Home key */
X				stuffin("1G");
X				return -1;
X			case 0x4f:		/* End key */
X				stuffin("G");
X				return -1;
X			case 0x51:		/* PgDn key */
X				stuffin(mkstr(CTRL('F')));
X				return -1;
X			case 0x49:		/* PgUp key */
X				stuffin(mkstr(CTRL('B')));
X				return -1;
X			case 0x52:		/* insert key */
X				return K_INSERT;
X			case 0x53:		/* delete key */
X				stuffin("x");
X				return -1;
X			/*
X			 * Hard-code some useful function key macros.
X			 */
X			case 0x3b: /* F1 */
X				stuffin(":help\n");
X				return -1;
X			case 0x3c: /* F2 */
X				stuffin(":n\n");
X				return -1;
X			case 0x55: /* SF2 */
X				stuffin(":n!\n");
X				return -1;
X			case 0x3d: /* F3 */
X				stuffin(":N\n");
X				return -1;
X			case 0x56: /* SF3 */
X				stuffin(":N!\n");
X				return -1;
X			case 0x3e: /* F4 */
X				stuffin(":e #\n");
X				return -1;
X			case 0x57: /* SF4 */
X				stuffin(":e! #\n");
X				return -1;
X			case 0x3f: /* F5 */
X				stuffin(":rew\n");
X				return -1;
X			case 0x58: /* SF5 */
X				stuffin(":rew!\n");
X				return -1;
X			case 0x40: /* F6 */
X				stuffin("]]");
X				return -1;
X			case 0x59: /* SF6 */
X				stuffin("[[");
X				return -1;
X			case 0x42: /* F8 - Set up global substitute */
X				stuffin(":1,$s/");
X				return -1;
X			case 0x43: /* F9 - declare C variable */
X				stuffin("yyp!!cdecl\n");
X				return -1;
X			case 0x5C: /* SF9 - explain C declaration */
X				stuffin("yyp^iexplain \033!!cdecl\n");
X				return -1;
X			case 0x44: /* F10 - save & quit */
X				stuffin(":x\n");
X				return -1;
X			case 0x5D: /* F10 - quit without saving */
X				stuffin(":q!\n");
X				return -1;
X			default:
X				break;
X			}
X			break;
X
X		default:
X			return c;
X		}
X	}
X}
X
X
Xstatic	int	bpos = 0;
X#ifdef BIOS
X
X#define	BSIZE	256
Xstatic	char	outbuf[BSIZE];
X
X/* Flushbuf() is used a little differently here in the BIOS-only interface
X * than in the case of other systems.  In general, the other systems buffer
X * large amounts of text and screen management data (escape sequences).
X * Here, only text is buffered, screen management is performed using BIOS
X * calls.  Hence, the buffer is much smaller since no more than one line of
X * text is buffered.  Also, screen management calls must assure that the
X * buffered text is output before performing the requested function.
X *
X * O.K.  Now I had better explain the tricky code sequences for IBM PC and
X * TI Pro.  In both cases, the tricks involve: 1) getting the text written
X * to the display as quickly as possible in the desired color and 2) assur-
X * ing that the cursor is positioned immediately following the latest text
X * output.
X *
X * On the IBM PC, we output the first character using the "write character
X * with attribute" function followed by code which outputs the buffer, a
X * character at a time, using the "write tty" function.  The first write
X * sets the display attributes, which are then reused by the "write tty"
X * function.  The "write tty" is then used to quickly write the data while
X * advancing the cursor.  The "write character with attribute" function
X * does not advance the cursor and so cannot be used to write the entire
X * buffer without additional code to advance the cursor in a separate oper-
X * ation.  Even though the first character in each buffer gets written
X * twice, the result is still substantially faster than it would be using a
X * "write character with attribute" - "[re]position cursor" sequence.
X *
X * On the TI Pro, we output the entire buffer using the "write character
X * string with attribute" function which is fast and convenient.  Unfortun-
X * ately, it does not advance the cursor.  Therefore, we include code which
X * determines the current location of the cursor, writes the buffer, then
X * positions the cursor at the end of the new data.
X *
X * I admit it, this is tricky, but it makes display updates much faster
X * than the would be using a more straightforward approach.
X */
X
X
Xvoid
Xflushbuf()				/* Flush buffered output to display */
X{
X	union	REGS	inregs, curregs, outregs;
X
X	if (bpos != 0) {
X		char	*bptr = outbuf;
X
X		switch (host_type) {
X		case hIBMPC:
X			inregs.h.ah = 0x09;
X			inregs.h.al = *bptr;
X			inregs.h.bh = bgn_page;
X			inregs.h.bl = P(P_CO);
X			inregs.x.cx = 1;
X			int86(crt_int, &inregs, &outregs);
X			inregs.h.ah = 0x0E;
X			while (bpos-- > 0) {
X				inregs.h.al = *bptr++;
X				int86(crt_int, &inregs, &outregs);
X			}
X			break;
X		case hTIPRO:
X			curregs.h.ah = 0x03;
X			int86(crt_int, &curregs, &curregs);
X			inregs.h.ah = 0x10;
X			inregs.h.al = P(P_CO);
X			inregs.x.bx = FP_OFF(outbuf);
X			inregs.x.cx = bpos;
X			inregs.x.dx = FP_SEG(outbuf);
X			int86(crt_int, &inregs, &outregs);
X			curregs.h.ah = 0x02;
X			curregs.h.dh += bpos;
X			int86(crt_int, &curregs, &outregs);
X			break;
X		}
X	}
X	bpos = 0;
X}
X
Xvoid
Xwrite_tty(c)				/* Used to execute control chars */
Xchar	c;
X{
X	int	curcol;
X
X	union	REGS	inregs, curregs, outregs;
X
X	flushbuf(); \
X
X	switch (c) {
X	case '\t':
X		inregs.h.ah = 0x09;
X		inregs.h.al = ' ';
X		inregs.h.bh = bgn_page;
X		inregs.h.bl = P(P_CO);
X		inregs.x.cx = 1;
X		int86(crt_int, &inregs, &outregs);
X		inregs.h.ah = 0x0E;
X		int86(crt_int, &inregs, &outregs);
X		curregs.h.ah = 0x03;
X		curregs.h.bh = bgn_page;
X		int86(crt_int, &curregs, &outregs);
X		curcol = host_type == hIBMPC ? outregs.h.dl : outregs.h.dh;
X		while (curcol++ % P(P_TS)) int86(crt_int, &inregs, &outregs);
X		break;
X	case '\n':
X		if (host_type == hTIPRO) bios_t_el();
X		/* No break, fall through to default action. */
X	default:
X		inregs.h.ah = 0x0E;
X		inregs.h.bh = bgn_page;
X		inregs.h.al = c;
X		int86(crt_int, &inregs, &outregs);
X		break;
X	}
X}
X
X#else		/* Not BIOS */
X
X#define	BSIZE	2048
Xstatic	char	outbuf[BSIZE];
X
Xvoid
Xflushbuf()
X{
X	if (bpos != 0)
X		write(1, outbuf, bpos);
X	bpos = 0;
X}
X
X#endif
X
X
X/*
X * Macro to output a character. Used within this file for speed.
X *
X * This macro had to be upgraded for the BIOS-only version because we
X * cannot count on flushbuf() to execute control characters such as
X * end-of-line or tab.  Therefore, when we encounter one, we flush
X * the buffer and call a routine which executes the character.
X */
X
X#ifdef BIOS
X
X#define	outone(cc) {                 \
X  register char ch = cc;             \
X  if (ch >= ' ') {                   \
X    outbuf[bpos++] = ch;             \
X    if (bpos >= BSIZE) flushbuf();   \
X  } else write_tty(ch);              \
X}
X
X#else
X
X#define	outone(c)	outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
X
X#endif
X
X/*
X * Function version for use outside this file.
X */
X
Xvoid
Xoutchar(c)
Xchar	c;
X{
X	outone(c);
X}
X
X/*
X * outstr(s) - write a string to the console
X */
X
Xvoid
Xoutstr(s)
Xchar	*s;
X{
X	while (*s) {
X		outone(*s++);
X	}
X}
X
Xvoid
Xbeep()
X{
X	if ( P(P_VB) )
X		vbeep();
X	else
X		outchar('\007');
X}
X
Xvbeep()		/* "Visual Bell" - reverse color flash */
X{
X	unsigned char oldcolor, revcolor, temp;
X
X	oldcolor = P(P_CO);
X
X	/* put reverse color in revcolor */
X	revcolor = (P(P_CO) & 0x07) << 4;	/* foregnd -> bkgnd */
X	temp     = (P(P_CO) & 0x70) >> 4;	/* bkgnd -> foregnd */
X	revcolor  |= temp;
X
X	/* Flash revcolor, then back */
X	setcolor (revcolor);
X	flushbuf();
X#ifdef TURBOC
X	delay (100);
X#endif
X	setcolor (oldcolor);
X	windgoto (Cursrow, Curscol);
X	flushbuf();
X}
X
X
X#ifndef TURBOC
Xsleep(n)
Xint	n;
X{
X	/*
X	 * Should do something reasonable here.
X	 */
X}
X#endif
X
Xvoid
Xpause()
X{
X	long	l;
X
X	flushbuf();
X
X#ifdef TURBOC
X	delay (600);	/* "stop" for a fraction of a second */
X#else
X	/*
X	 * Should do something better here...
X	 */
X	for (l=0; l < 5000 ;l++)
X		;
X#endif
X}
X
Xvoid
Xsig()
X{
X	signal(SIGINT, sig);
X
X	got_int = TRUE;
X}
X
Xstatic	char	schar;		/* save original switch character */
X
X/*	While Larry Shurr's addition of color and mode support was
X *	dependent on #define BIOS, there's no reason it needs to be.
X *	The BIOS is always there, even if NANSI.SYS isn't.  We'll
X *	use the BIOS where appropriate, and extend support to
X *	all cases of #define DOS.  This is especially true of the
X *	setup in windinit() and the termination in windexit().
X */
X
Xvoid
Xwindinit()
X{
X	union	REGS	regs;
X	struct	SREGS	sregs;
X
X	/* The "SYSROM..." string is a signature in the TI Pro's ROM which
X	 * which we can look for to determine whether or not we're running
X	 * on a TI Pro.  If we don't find it at F400:800D,
X	 * we assume we're running on an IBM PC or clone.
X	 * Unfortunately, the signature is actually
X	 * the system ROM's copyright notice though you will note that the
X	 * year is omitted.  Still, placing it in this program might
X	 * inadvertantly make it appear to be an official copyright notice
X	 * for THIS program.  Hence, I have surrounded the signature
X	 * string with disclaimers.
X	 */
X
X        static	char far *disclaimer1 =
X	  "The following is *NOT* a copyright notice for this program: ";
X
X	static	char far *ti_sig =
X          "SYSROM (c) Copyright Texas Instruments Inc.";
X
X	static	char far *disclaimer2[] = {
X	  "\nInstead, it is a signature string we look for ",
X	  "to distinguish the TI Pro computer.\n",
X	  "Actually, this program is in the public domain."
X	};
X
X	static char far	*ti_sig_addr = (char far *)0xF400800D;
X	static int ti_sig_len = sizeof(ti_sig) - 1;
X
X	/* Identify the host type.  Look for signature in TI Pro ROM.  If */
X	/* found, set host type to TI Pro, else assume host is an IBM PC. */
X
X	host_type = strncmp(ti_sig, ti_sig_addr, ti_sig_len) ? hIBMPC : hTIPRO;
X
X	/* Next, perform host-dependent initialization. */
X
X	switch (host_type) {
X	case hIBMPC:
X		/* Get the video mode info */
X		crt_int = 0x10;
X		regs.h.ah = 0x0F;
X		int86(crt_int, &regs, &regs);
X		bgn_page = regs.h.bh;
X		bgn_mode = regs.h.al;
X		Columns = regs.h.ah;
X		/*  Find the starting color, and save to restore later */
X		regs.h.ah = 8;		/* Read char/attr BIOS fn */
X		regs.h.bh = bgn_page;
X		int86(crt_int, &regs, &regs);
X		bgn_color = (int) regs.h.ah;
X		P(P_CO) = bgn_color;
X		break;
X	case hTIPRO:
X		Columns = 80;
X		crt_int = 0x49;
X		P(P_CO) = 0x0F;
X		break;
X
X	default:
X		Columns = 80;
X		break;
X	}
X
X	P(P_LI) = Rows = 25;
X
X	schar = getswitch();
X	setswitch('/');
X
X	signal(SIGINT, sig);
X#ifndef BIOS
X	setraw (1);
X#endif
X}
X
Xvoid
Xwindexit(r)
Xint r;
X{
X
X	union	REGS	regs;
X
X	quitting_now = 1;
X
X	/* Restore original color */
X	setcolor (bgn_color);
X
X	if (host_type == hIBMPC) {
X		/* If we've changed any of the setup, reset the mode.
X		 * Otherwise, leave stuff on the screen.
X		 */
X		regs.h.ah = 0x0F;	/* "Get-mode" BIOS fn */
X		int86(0x10, &regs, &regs);
X		if (bgn_mode != regs.h.al)
X			set_mode (bgn_mode);
X	}
X
X	flushbuf();
X	setswitch(schar);
X#ifndef BIOS
X	setraw(0);
X#endif
X	exit(r);
X}
X
X
X#ifndef BIOS
X/*	Setraw sets the console driver into raw mode, which makes it run
X *	somewhat faster.  Details of the function:
X *	If r=1, remember current mode, and set into raw mode.
X *	   r=0, return to the original mode.
X */
X
Xsetraw (r)
X  int	r;
X{
X	static int origr=0;	/* save the original r */
X	union REGS rr;
X
X	/* Do IOCTL call to get current control info */
X	rr.x.ax = 0x4400;	/* Read IOCTL info - DOS fn */
X	rr.x.bx = 1;		/* Handle for stdout */
X	intdos (&rr, &rr);
X
X	/* Save relevant info, and modify for "set" call */
X	if (r) {
X		origr = rr.h.dl & 0x20;		/* save current "raw" bit */
X		rr.h.dl = rr.h.dl | 0x20;	/* set "raw" bit */
X	}
X	else
X		rr.h.dl = (rr.h.dl & (~0x20)) | (origr & 0x20);
X
X	/* Do IOCTL call to set control info */
X	rr.x.ax = 0x4401;	/* Set IOCTL function call */
X	rr.x.bx = 1;		/* Handle for stdout */
X	rr.h.dh = 0;		/* DL already set up */
X	intdos (&rr, &rr);
X}
X#endif
X
X
Xvoid
Xwindgoto(r, c)				/* Move cursor to r'ow & c'olumn */
Xregister int	r, c;
X{
X#ifdef BIOS
X	union	REGS	inregs, outregs;
X
X	if (bpos > 0) flushbuf();
X
X	inregs.h.ah = 0x02;
X
X	switch (host_type) {
X	case hIBMPC :
X		inregs.h.bh = bgn_page;
X		inregs.h.dh = r;
X		inregs.h.dl = c;
X		break;
X	case hTIPRO:
X		inregs.h.dh = c;
X		inregs.h.dl = r;
X		break;
X	}
X
X	int86(crt_int, &inregs, &outregs);
X
X#else		/* Not BIOS */
X
X	r += 1;
X	c += 1;
X
X	/*
X	 * Check for overflow once, to save time.
X	 */
X	if (bpos + 8 >= BSIZE)
X		flushbuf();
X
X	outbuf[bpos++] = '\033';
X	outbuf[bpos++] = '[';
X	if (r >= 10)
X		outbuf[bpos++] = r/10 + '0';
X	outbuf[bpos++] = r%10 + '0';
X	outbuf[bpos++] = ';';
X	if (c >= 10)
X		outbuf[bpos++] = c/10 + '0';
X	outbuf[bpos++] = c%10 + '0';
X	outbuf[bpos++] = 'H';
X
X#endif
X}
X
XFILE *
Xfopenb(fname, mode)
Xchar	*fname;
Xchar	*mode;
X{
X	FILE	*fopen();
X	char	modestr[16];
X
X	sprintf(modestr, "%sb", mode);
X	return fopen(fname, modestr);
X}
X
Xstatic	char
Xgetswitch()
X{
X	union	REGS	inregs, outregs;
X
X	inregs.h.ah = 0x37;
X	inregs.h.al = 0;
X
X	intdos(&inregs, &outregs);
X
X	return outregs.h.dl;
X}
X
Xstatic	void
Xsetswitch(c)
Xchar	c;
X{
X	union	REGS	inregs, outregs;
X
X	inregs.h.ah = 0x37;
X	inregs.h.al = 1;
X	inregs.h.dl = c;
X
X	intdos(&inregs, &outregs);
X}
X
X#define	PSIZE	128
X
X/*
X * fixname(s) - fix up a dos name
X *
X * Takes a name like:
X *
X *	\x\y\z\base.ext
X *
X * and trims 'base' to 8 characters, and 'ext' to 3.
X */
Xchar *
Xfixname(s)
Xchar	*s;
X{
X	char	*strchr(), *strrchr();
X	static	char	f[PSIZE];
X	char	base[32];
X	char	ext[32];
X	char	*p;
X	int	i;
X
X	strcpy(f, s);
X
X	for (i=0; i < PSIZE ;i++)
X		if (f[i] == '/')
X			f[i] = '\\';
X
X	/*
X	 * Split the name into directory, base, extension.
X	 */
X	if ((p = strrchr(f, '\\')) != NULL) {
X		strcpy(base, p+1);
X		p[1] = '\0';
X	} else {
X		strcpy(base, f);
X		f[0] = '\0';
X	}
X
X	if ((p = strchr(base, '.')) != NULL) {
X		strcpy(ext, p+1);
X		*p = '\0';
X	} else
X		ext[0] = '\0';
X
X	/*
X	 * Trim the base name if necessary.
X	 */
X	if (strlen(base) > 8)
X		base[8] = '\0';
X
X	if (strlen(ext) > 3)
X		ext[3] = '\0';
X
X	/*
X	 * Paste it all back together
X	 */
X	strcat(f, base);
X	strcat(f, ".");
X	strcat(f, ext);
X
X	return f;
X}
X
Xvoid
Xdoshell(cmd)
Xchar	*cmd;
X{
X	if (cmd == NULL)
X		if ((cmd = getenv ("COMSPEC")) == NULL)
X			cmd = "command.com";
X
X	system(cmd);
X	wait_return();
X}
X
X
X/*
X *	setcolor (color)
X *	Set the screen attributes (basically, color) to value co.
X *	The color attributes for a DOS machine are the BIOS colors
X *	for text.  Where BIOS is not defined, we map the Escape
X *	sequences to the NANSI.SYS equivalents of the BIOS colors.
X */
X
Xsetcolor (color)
X  int	color;
X{
X#ifdef BIOS
X	P(P_CO) = host_type == hIBMPC ? color : ((color & 0x17) | 0x08);
X#else
X	unsigned char work;
X
X	/* Send the ANSI define-attribute sequence */
X	outone('\033');
X	outone('[');
X	outone('0');		/* Normal color */
X	outone(';');
X	/* BIOS-to-NANSI color conversion may look a little bizarre.
X	 * They have different bit orderings to represent the
X	 * color (BIOS=RGB, NANSI=BGR).
X	 *
X	 * First put the foreground color.
X	 */
X	work = 0;
X	if (color & 1)		work += 4;	/* Blue */
X	if (color & 2)		work += 2;	/* Green */
X	if (color & 4)		work += 1;	/* Red */
X	outone('3');		/* NANSI foreground starts at 30 */
X	outone(work + '0');
X	outone(';');
X	/*  Now the background color */
X	work = 0;
X	if (color & 0x10)	work += 4;	/* Blue */
X	if (color & 0x20)	work += 2;	/* Green */
X	if (color & 0x40)	work += 1;	/* Red */
X	outone('4');		/* NANSI background starts at 40 */
X	outone(work + '0');
X	/*  Do the intensity and blinking, if any  */
X	if (color & 8) {	/* intensity */
X		outone(';');
X		outone('1');
X	}
X	if (color & 0x80) {	/* blink */
X		outone(';');
X		outone('5');
X	}
X	/*  The 'm' suffix means "set graphic rendition"  */
X	outone('m');
X	P(P_CO) = color;
X
X#endif		/* Not BIOS */
X
X	if (!quitting_now) {
X		screenclear();
X		updatescreen();
X	}
X}
X
X
X/*	setrows (r)
X *	Sets the screen to "r" rows, or lines, where "r" is a feasible
X *	value for the IBM PC with some common display.  In this function:
X *   -	We set the mode to 25-line or 43-line mode, assuming the display
X *	supports the requested mode.
X *   -	We set the logical number of lines that Stevie uses to "r",
X *	so that the screen USED may not be the same as the physical screen.
X *
X *	The function returns the number of rows set.
X */
Xsetrows (r)
X  int r;
X{
X	int	rphys, rlog;	/* physical and logical "r" */
X
X	rphys = (r <= 25) ? 25 : 43 ;
X	rlog  = (r <= 50) ? r : 50;
X
X	/* Set the mode to correspond to the number of lines */
X	set_mode (rphys);
X
X	return (rlog);
X}
X
X
Xset_mode (m)
X  int m;
X{
X	set_25 ();
X	if (m == 43)
X		set_43 ();
X}
X
X#ifdef BIOS
X
Xint
Xset_25(lines)			/* Set display to 25 line mode */
Xint	lines;
X{
X	union	REGS	inregs, outregs;
X
X	switch (host_type) {
X	case hIBMPC:
X		inregs.h.ah = 0x00;
X		inregs.h.al = bgn_mode;
X		int86(crt_int, &inregs, &outregs);
X		break;
X	case hTIPRO:
X		windgoto(0, 0);
X		inregs.h.ah = 0x09;
X		inregs.h.al = ' ';
X		inregs.h.bl = P(P_CO);
X		inregs.x.cx = 80 * 25;
X		int86(crt_int, &inregs, &outregs);
X		if (lines > 25) lines = 25;
X		break;
X	}
X
X	return(lines);
X}
X
Xint
Xset_43(lines)			/* Set display to 43/50 line mode */
Xint	lines;
X{
X	union	REGS	inregs, outregs;
X
X	switch (host_type) {
X	case hIBMPC:
X		inregs.x.ax = 0x1112;
X		inregs.h.bl = 0;
X		int86(crt_int, &inregs, &outregs);
X		inregs.x.ax = 0x1200;
X		inregs.h.bl = 0x20;
X		int86(crt_int, &inregs, &outregs);
X		inregs.h.ah = 0x01;
X		inregs.x.cx = 0x0707;
X		int86(crt_int, &inregs, &outregs);
X		break;
X	case hTIPRO:
X		if (lines > 25) lines = 25;
X		break;
X	}
X
X	return(lines);
X}
X
X#else		/* Not BIOS */
X
Xset_25 ()
X{
X	send_setmode (bgn_mode);
X}
X
Xset_43 ()
X{
X	send_setmode (43);
X}
X
Xsend_setmode (m)
X{
X	outone('\033');
X	outone('[');
X
X	/* Convert 2-digit decimal to ASCII */
X	if (m >= 10)
X		outone( m/10 + '0' );
X	outone( m%10 + '0' );
X	outone ('h');
X}
X
X#endif		/* Not BIOS */
X
X#ifdef BIOS
X/*
X *	The rest of the file is BIOS-specific
X */
X
Xvoid
Xbios_t_ci()				/* Make cursor invisible */
X{
X	union	REGS	inregs, outregs;
X
X	if (sav_curattr == 0) {
X		inregs.h.ah = 0x03;
X		inregs.h.bh = bgn_page;
X		int86(crt_int, &inregs, &outregs);
X		sav_curattr = outregs.x.cx;
X		inregs.h.ah = 0x01;
X		inregs.x.cx = 0x2000;
X		int86(crt_int, &inregs, &outregs);
X	}
X}
X
Xvoid
Xbios_t_cv()				/* Make cursor visible */
X{
X	union	REGS	inregs, outregs;
X
X	if (sav_curattr != 0) {
X		inregs.h.ah = 0x01;
X		inregs.h.bh = bgn_page;
X		inregs.x.cx = sav_curattr;
X		int86(crt_int, &inregs, &outregs);
X		sav_curattr = 0;
X	}
X}
X
X/*
X * O.K., I have tried to keep bios.c as "pure" as possible. I.e., I have used
X * BIOS calls for everything instead of going for all-out speed by using
X * direct-video access for updating the display - after all, I named it this
X * module bios.c.  There is one area, however, where using the BIOS is just
X * too much of a compromise... the TI Pro's "scroll display" functions are so
X * slow and ugly that I hate them.  True, they are very flexible, but their
X * poor on-screen appearance and low performance are a liability - you prob-
X * ably think I'm exaggerating, but you're wrong - it is truly bad.  There-
X * fore, I am bypassing them and scrolling the screen myself; something I
X * nearly always do.  From a purist like me, that really says something.
X */
X
Xvoid
Xbios_t_dl(r,l)				/* Delete lines */
Xint r, l;
X{
X	char	far	*end;		/* End ptr for TI Pro screen */
X	char	far	*dst;		/* Dest ptr for scrolling TI Pro scrn */
X	char	far	*src;		/* Src  ptr for scrolling TI Pro scrn */
X
X	union	REGS	inregs, outregs;
X
X	switch (host_type) {
X	case hIBMPC:
X		inregs.h.ah = 0x06;
X		inregs.h.al = l;
X		inregs.h.bh = P(P_CO);
X		inregs.h.ch = r;
X		inregs.h.cl = 0;
X		inregs.h.dh = Rows - 1;
X		inregs.h.dl = Columns - 1;
X		int86(crt_int, &inregs, &outregs);
X		break;
X	case hTIPRO:
X		inregs.h.ah = 0x17;
X		int86(crt_int, &inregs, &outregs);
X		dst = MK_FP(0xDE00, outregs.x.dx + (r * Columns));
X		src = dst + (l * Columns);
X		end = MK_FP(0xDE00, outregs.x.dx + ((Rows - 1) * Columns));
X		while (src < end) *dst++ = *src++;
X		while (dst < end) *dst++ = ' ';
X		break;
X	}
X}
X
Xvoid
Xbios_t_ed()				/* Home cursor, erase display */
X{
X	union	REGS	inregs, outregs;
X
X	windgoto(0, 0);
X
X	inregs.h.ah = 0x09;
X	inregs.h.al = ' ';
X	inregs.h.bh = bgn_page;
X	inregs.h.bl = P(P_CO);
X	inregs.x.cx = Columns * Rows;
X	int86(crt_int, &inregs, &outregs);
X}
X
Xvoid
Xbios_t_el()				/* Erase to end-of-line */
X{
X	short	ccol;
X
X	union	REGS	inregs, outregs;
X
X	inregs.h.ah = 0x03;
X	inregs.h.bh = bgn_page;
X	int86(crt_int, &inregs, &outregs);
X
X	inregs.h.ah = 0x09;
X	inregs.h.al = ' ';
X	inregs.h.bl = P(P_CO);
X
X	ccol = host_type == hIBMPC ? outregs.h.dl : outregs.h.dh;
X
X	inregs.x.cx = Columns - ccol;
X	int86(crt_int, &inregs, &outregs);
X}
X
X/* As in the delete-line function, we scroll the TI display ourselves
X * rather than the use the slow-and-ugly software scroll in the BIOS.  See
X * the remarks for bios_t_dl() additional information.
X */
X
Xvoid
Xbios_t_il(r,l)				/* Insert lines */
Xint r, l;
X{
X	char	far	*end;		/* End ptr for TI Pro screen */
X	char	far	*dst;		/* For scrolling TI Pro screen */
X	char	far	*src;		/* For scrolling TI Pro screen */
X
X	union	REGS	inregs, outregs;
X
X	switch (host_type) {
X	case hIBMPC:
X		inregs.h.ah = 0x07;
X		inregs.h.al = l;
X		inregs.h.bh = P(P_CO);
X		inregs.h.ch = r;
X		inregs.h.cl = 0;
X		inregs.h.dh = Rows - 1;
X		inregs.h.dl = Columns - 1;
X		int86(crt_int, &inregs, &outregs);
X		break;
X	case hTIPRO:
X		inregs.h.ah = 0x17;
X		int86(crt_int, &inregs, &outregs);
X		dst = MK_FP(0xDE00, outregs.x.dx + (Columns * (Rows - 1)) - 1);
X		src = dst - (Columns * l);
X		end = MK_FP(0xDE00, outregs.x.dx + (Columns * r));
X		while (src >= end) *dst-- = *src--;
X		src = MK_FP(0xDE00, outregs.x.dx + (r * Columns));
X		end = src + (l * Columns);
X		while (src < end) *src++ = ' ';
X		break;
X	}
X}
X
Xvoid
Xbios_t_rc()				/* Restore saved cursor position */
X{
X	union	REGS	inregs, outregs;
X
X	inregs.h.ah = 0x02;
X	inregs.h.bh = bgn_page;
X	inregs.x.dx = sav_curpos;
X	int86(crt_int, &inregs, &outregs);
X}
X
Xvoid
Xbios_t_sc()				/* Save cursor position */
X{
X	union	REGS	inregs, outregs;
X
X	inregs.h.ah = 0x03;
X	inregs.h.bh = bgn_page;
X	int86(crt_int, &inregs, &outregs);
X	sav_curpos = outregs.x.dx;
X}
X
X#endif
X
END_OF_FILE
if test 23301 -ne `wc -c <'stevie/dos.c'`; then
    echo shar: \"'stevie/dos.c'\" unpacked with wrong size!
fi
# end of 'stevie/dos.c'
fi
echo shar: End of archive 11 \(of 13\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 13 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
