#include	<stdio.h>
#include	<dos.h>
#include	<ctype.h>
#include	<string.h>
#define		PCBIOS
#include	"pcbios.h"
#undef		PCBIOS


int	pckey(int operate)
{
	union REGS	reg;

	if((operate < 0) || (2 < operate))
		return(0);

	reg.h.ah = (unsigned char)operate;
	int86(PC_KEYB,&reg,&reg);
	return(reg.x.ax);
}


int	pcgvmode()
{
	union REGS	reg;

	reg.h.ah = 0x0f;
	int86(PC_VIDEO,&reg,&reg);
	return(reg.h.al);
}


void	pcsvmode(int mode)
{
	union REGS	reg;

	reg.h.ah = 0x00;
	reg.h.al = (unsigned char)mode;
	int86(PC_VIDEO,&reg,&reg);
	return;
}


void	curstype(int type)
{
	union REGS	reg;

	reg.h.ah = 0x01;
	switch(type)
	{
	case CURSOFF:
		reg.x.cx = 0x2000;
		break;
	case CURSLIN:
		reg.x.cx = 0x0607;
		break;
	case CURSBOX:
		reg.x.cx = 0x0007;
		break;
	default:
		reg.x.cx = 0x0003;
		break;
	}
	int86(PC_VIDEO,&reg,&reg);
	return;
}


void	poscurso(int row,int col)
{
	union REGS	reg;

	reg.h.ah = 0x02;
	reg.h.bh = 0x00;
	reg.h.dh = (unsigned char)row;
	reg.h.dl = (unsigned char)col;
	int86(PC_VIDEO,&reg,&reg);
	return;
}


int	cursorow()
{
	union REGS	reg;

	reg.h.ah = 0x03;
	reg.h.bh = 0x00;
	int86(PC_VIDEO,&reg,&reg);
	return(reg.h.dh);
}


int	cursocol()
{
	union REGS	reg;

	reg.h.ah = 0x03;
	reg.h.bh = 0x00;
	int86(PC_VIDEO,&reg,&reg);
	return(reg.h.dl);
}


unsigned char	readchr()
{
	union REGS	reg;

	reg.h.ah = 0x08;
	reg.h.bh = 0x00;
	int86(PC_VIDEO,&reg,&reg);
	return(reg.h.al);
}


unsigned char	readatt()
{
	union REGS	reg;

	reg.h.ah = 0x08;
	reg.h.bh = 0x00;
	int86(PC_VIDEO,&reg,&reg);
	return(reg.h.ah);
}


void	writechr(int chr,int n)
{
	union REGS	reg;

	reg.h.ah = 0x0a;
	reg.h.bh = 0x00;
	reg.h.al = (unsigned char)chr;
	reg.x.cx = n;
	int86(PC_VIDEO,&reg,&reg);
	return;
}


void	writecha(int chr,int attr,int n)
{
	union REGS	reg;

	reg.h.ah = 0x09;
	reg.h.bh = 0x00;
	reg.h.al = (unsigned char)chr;
	reg.x.cx = n;
	reg.h.bl = (unsigned char)attr;
	int86(PC_VIDEO,&reg,&reg);
	return;
}


void	putstr(char *str,int length)
{
	int	row,col;

	row = cursorow();
	col = cursocol();

	if(length <= 0)
	{
		while(*str)
		{
			writechr(*str++,1);
			poscurso(row,++col);
		}
	}
	else
	{
		while(*str)
		{
			writechr(*str++,1);
			poscurso(row,++col);
			if(0 == (--length))
				break;
		}
		while(length--)
		{
			writechr(' ',1);
			poscurso(row,++col);
		}
	}

	return;
}


void	putbstr(char *str,int length)
{
	int	row,col;

	row = cursorow();
	col = cursocol();

	if(length <= 0)
		length = strlen(str);

	while(length--)
	{
		writechr(*str++,1);
		poscurso(row,++col);
	}

	return;
}


void	putsa(char *str,int attr,int length)
{
	int	row,col;

	row = cursorow();
	col = cursocol();

	if(length <= 0)
	{
		while(*str)
		{
			writecha(*str++,attr,1);
			poscurso(row,++col);
		}
	}
	else
	{
		while(*str)
		{
			writecha(*str++,attr,1);
			poscurso(row,++col);
			if(0 == (--length))
				break;
		}
		while(length--)
		{
			writecha(' ',attr,1);
			poscurso(row,++col);
		}
	}

	return;
}


unsigned long	strtounl(char *str,char **scanstop,int base)
{
	unsigned long	value;
	unsigned char	c;

	if((base < 0) || (base == 1) || (base > 36))
		return(0);

	if(base == 0)
	{
		if(str[0] == '0')
		{
			if((str[1] == 'x') || (str[1] == 'X'))
				base = 16;
			else
				base = 8;
		}
		else
			base = 10;
	}

	while(isspace(*str))
		str++;

	value = 0l;
	for(c = 0;*str;str++)
	{
		if(isdigit(*str))
			c = *str - '0';
		else if(('A' <= *str) && (*str <= 'Z'))
			c = *str - 'A' + 10;
		else if(('a' <= *str) && (*str <= 'z'))
			c = *str - 'a' + 10;
		else
			break;
		if(c >= (unsigned char)base)
			break;
		value *= base;
		value += (unsigned long)c;
	}

	if(NULL != scanstop)
		*scanstop = str;

	return(value);
}


int	getcdisk()
{
	union REGS	reg;

	reg.h.ah = 0x19;
	intdos(&reg,&reg);
	return(reg.h.al);
}


int	setcdisk(int drive)
{
	union REGS	reg;

	reg.h.ah = 0x0e;
	reg.h.dl = (unsigned char)drive;
	intdos(&reg,&reg);
	return(reg.h.al);
}


int	getcudir(int drive,char *dirname)
{
	union REGS	reg;
	struct SREGS	sreg;

	segread(&sreg);
	reg.h.ah = 0x47;
	if(sizeof(dirname) == 4)	/* if far */
	{
		sreg.ds = FP_SEG(dirname);
		reg.x.si = FP_OFF(dirname);
	}
	else
		reg.x.si = (unsigned int)dirname;
	reg.h.dl = (unsigned char)drive;
	intdosx(&reg,&reg,&sreg);
	return(0);
}


int	isdbcs()
{
	union REGS	reg;
	struct SREGS	sreg;
	char far	*fptr;

	segread(&sreg);

	reg.x.ax = 0x6300;		/* get DBCS vector */
	intdosx(&reg,&reg,&sreg);

	FP_SEG(fptr) = sreg.ds;
	FP_OFF(fptr) = reg.x.si;

	if( (*fptr == 0) && (*(fptr + 1) == 0) )
		return(0);		/* SBCS mode */

	return(1);		/* DBCS mode */
}


/*	comm port functions	*/

unsigned int	comminit(int comm,int paristop,int wordbps)
{
	union REGS	reg;

	if((comm < 0) || (3 < comm))
		return(0);

	reg.x.ax = 0x0400;
	reg.x.bx = (unsigned int)paristop;
	reg.x.cx = (unsigned int)wordbps;
	reg.x.dx = (unsigned int)comm;
	int86(PC_COMM,&reg,&reg);
	return(reg.x.ax);
}


unsigned int	commsend(int comm,int chr)
{
	union REGS	reg;

	if((comm < 0) || (3 < comm))
		return(0);

	reg.h.ah = 0x01;
	reg.h.al = (unsigned char)chr;
	reg.x.dx = (unsigned int)comm;
	int86(PC_COMM,&reg,&reg);
	return(reg.x.ax);
}


unsigned int	commrecv(int comm,int *chr)
{
	union REGS	reg;

	if((comm < 0) || (3 < comm))
		return(0);

	reg.x.ax = 0x0200;
	reg.x.dx = (unsigned int)comm;
	int86(PC_COMM,&reg,&reg);
	*chr = (int)reg.h.al;
	return(reg.x.ax);
}


unsigned int	commstat(int comm)
{
	union REGS	reg;

	if((comm < 0) || (3 < comm))
		return(0);

	reg.x.ax = 0x0300;
	reg.x.dx = (unsigned int)comm;
	int86(PC_COMM,&reg,&reg);
	return(reg.x.ax);
}


unsigned int	commcrrd(int comm,int *creg)
{
	union REGS	reg;

	if((comm < 0) || (3 < comm))
		return(0);

	reg.x.ax = 0x0500;
	reg.x.dx = (unsigned int)comm;
	int86(PC_COMM,&reg,&reg);
	*creg = (int)reg.h.bl;
	return(reg.x.ax);
}


unsigned int	commcrwr(int comm,int creg)
{
	union REGS	reg;

	if((comm < 0) || (3 < comm))
		return(0);

	reg.x.ax = 0x0501;
	reg.x.dx = (unsigned int)comm;
	reg.h.bl = (unsigned char)creg;
	int86(PC_COMM,&reg,&reg);
	return(reg.x.ax);
}

