# ifdef GEMDOS
# include <stdio.h>
# include <osbind.h>
# include <xbios.h>
# include <types.h>
# include <stat.h>
# include "header.h"
#define O_RDWR 2
#define PATHSEP ','

init_keys()
{
	static char unshf[]={
	0, 27, '1', '2', '3', '4', '5', '6',
	'7', '8', '9', '0', '-', '=', 8, 9,
	'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
	'o', 'p', '[', ']', 13, 0, 'a', 's',
	'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
	39, '`', 0, '\\', 'z', 'x', 'c', 'v',
	'b', 'n', 'm', ',', '.', '/', 0, 0,
	0, ' ', 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	'k', 0, '-', 'h', 0, 'l', '+', 0,
	'j', 0, 'i', 127, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, '?', '(', ')', '/', '*', 'y',
	'k', 'u', 'h', ' ', 'l', 'b', 'j', 'n',
	'i', '.', 13, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0},

	shift[]={
	0, 27, '!', '@', '#', '$', '%', '^',
	'&', '*', '(', ')', '_', '+', 8, 9,
	'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
	'O', 'P', '{', '}', 13, 0, 'A', 'S',
	'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
	39, '~', 0, '|', 'Z', 'X', 'C', 'V',
	'B', 'N', 'M', '<', '>', '?', 0, 0,
	0, ' ', 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	'K', 0, '-', 'H', 0, 'L', '+', 0,
	'J', 0, 'I', 127, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, '?', '(', ')', '/', '*', 'Y',
	'K', 'U', 'H', ' ', 'L', 'B', 'J', 'N',
	'I', '.', 13, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0},
 
	caps[]={
	0, 27, '1', '2', '3', '4', '5', '6',
	'7', '8', '9', '0', '-', '=', 8, 9,
	'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
	'O', 'P', '[', ']', 13, 0, 'A', 'S',
	'D', 'F', 'G', 'H', 'J', 'K', 'L', ';',
	39, '`', 0, '\\', 'Z', 'X', 'C', 'V',
	'B', 'N', 'M', ',', '.', '/', 0, 0,
	0, ' ', 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	'k', 0, '-', 'h', 0, 'l', '+', 0,
	'j', 0, 'i', 127, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, '?', '(', ')', '/', '*', 'y',
	'k', 'u', 'h', ' ', 'l', 'b', 'j', 'n',
	'i', '.', 13, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0};

	Keytbl(unshf, shift, caps);
}

kgetch()
{
	return Crawcin();
}

getche()
{
	return Cconin();
}

doshell()
{
	char args[2];

	args[0]=0;
	clear();
	lflush();
	if (Pexec(0, cmdshell, args, "\0") < 0) {
		write(2, "$ ", 2);
		while (getche() != '\r')
			;
	}
}


/* Add a backslash to any name not ending in /, \ or :   There must
 * be room for the \
 */
void
append_slash(name)
char *name;
{
	char *ptr;

	if (!*name)
		return;
	ptr = name + (strlen(name) - 1);
	if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
		*++ptr = '\\';
		*++ptr = '\0';
	}
}


/* Pause for secs -- sounds good ...
 */
sleep(secs)
int secs;
{
	time_t time(), waittill;

	waittill = time((time_t *) NULL) + secs;
	while (waittill > time((time_t *) NULL))
		;
}


/* Lopen a file somewhere along the PATH
 */
plopen(name)
char	*name;
{
	char	buf[PATHLEN], *pathp, *bufp, *getenv(), lastch;
	int	fd;

	/* Try the default directory first.  Then look along PATH unless
	 * the name has path components.
	 */
	if ((fd = lopen(name)) >= 0)
		return fd;
	if ((index(name, '\\') == NULL) && (index(name, ':') == NULL)) {
		strcpy(buf,name);
		pathp=getenv("PATH");
		while (pathp && *pathp) {
			bufp = buf;
			while (*pathp && *pathp != PATHSEP)
				lastch = *bufp++ = *pathp++;
			if(lastch != '\\')
				*bufp++ = '\\';
			strcpy(bufp,name);
			if ((fd = lopen(buf)) >= 0)
				return fd;
			if (*pathp)
				pathp++;
		}
	}
	return -1;
}

/* Diagnostic information about the disposition of levels between ram
 * and disk.
 */
levelinfo()
{
	DISKBLOCK	*dp;
	RAMBLOCK	*rp;

	cursors();
	lflush();
	fprintf(stderr, "\nRAM:\n");
	for (rp = ramblks; rp; rp = rp->next)
		fprintf(stderr, "%4d  gt:%6ld\n", rp->level, rp->gtime);
	fprintf(stderr, "\nDISK:\n");
	for (dp = diskblks; dp; dp = dp->next)
		fprintf(stderr, "%4d  gt:%6ld  fpos:%ld\n",
		dp->level, dp->gtime, dp->fpos);
	nomove=1;
	return (yrepcount = 0);
}

int swapfd = 0;	/* file descriptor for the swap file */
int ramlevels = MAXLEVEL + MAXVLEVEL;	/* the maximum */


/* Allocate as many levels as possible, then check that the swap file
 * will have enough storage for the overflow.  You must be able to allocate
 * at least one level or there will be nowhere to swap to/from.  If a swap
 * file is opened it remains open for the whole game.
 */
allocate_memory()
{
	register int	i;
	DISKBLOCK	*dp, *dp2;
	RAMBLOCK	*rp;

	/* First allocate the maximum number of disk blocks, some of which
	 * may not be used, but must do the allocation now since we don't
	 * yet know how many levels will be allocatable.
	 */
	for (i = 0; i < MAXLEVEL + MAXVLEVEL; i++) {
		if ((dp = (DISKBLOCK *) malloc(sizeof(DISKBLOCK))) == NULL)
			died(-285);
		dp->next = diskblks;
		diskblks = dp;
	}
	dp = diskblks;		/* Move this along in the next loop */

	/* Now allocate ram storage, up to ramlevels in count.
	 */
	for (i = 0; i < MAXLEVEL + MAXVLEVEL; i++) {
		if (i < ramlevels)
			rp = (RAMBLOCK *) malloc(sizeof(RAMBLOCK));
		else
			rp = NULL;
		if (rp == NULL) {
			if (i == 0)
				died(-285);	/* have to have at least one */

			/* Open the swap file if not yet done so
			 */
			if (swapfd == 0) {
				swapfd = creat(swapfile, 0);
				if (swapfd < 0)
					error("Can't create swapfile `%s'\n",
					swapfile);
				close(swapfd);
				swapfd = open(swapfile, O_RDWR);
				if (swapfd < 0)
					error("Can't open swapfile `%s'\n",
					swapfile);

				/* First block is FREE and will be used to
				 * swap out the first level.  When another
				 * level gets swapped in, its block will be
				 * FREE.
				 */
				if (dp == NULL)
					error("NULL1 disk pointer?\n");
				dp->level = FREEBLOCK;
				dp->fpos = 0;
				dp->gtime = 0;
				lseek(swapfd, (long) sizeof rp->cell, 0);
			}

			/* And try to seek the size of this level
			 */
			dp = dp->next;
			if (dp == NULL)
			 	error("NULL2 disk pointer?\n");
			dp->level = FREEBLOCK;
			dp->gtime = 0;
			dp->fpos = lseek(swapfd, 0L, 1);
			if (write(swapfd, rp->cell, sizeof(struct cel)) < 0)
				error("Not enough disk space for swapfile `%s'\n",
				swapfile);
		} else {
			rp->next = ramblks;
			ramblks = rp;
			rp->level = FREEBLOCK;
			rp->gtime = 0;
		}
	}

	/* dp now points to the last diskblock used.  Truncate the diskblock
	 * list here and free up the other blocks (for what it's worth ...)
	 */
	dp2 = dp->next;
	dp->next = NULL;
	dp = dp2;
	while (dp) {
		dp2 = dp->next;
		free((char *) dp);
		dp = dp2;
	}
}


/* VARARGS1 */
warn(format, a1, a2, a3)
char *format;
long a1, a2, a3;
{
	fprintf(stderr, format, a1, a2, a3);
}

/* VARARGS1 */
error(format, a1, a2, a3, a4)
char *format;
long a1, a2, a3, a4;
{
	fputc('\n', stderr);
	fprintf(stderr, format, a1, a2, a3, a4);
	sleep(5);
	exit(1);
}
# endif	/* GEMDOS */
