Metropoli BBS
VIEWER: chario.c MODE: TEXT (ASCII)
/****************************************************************/
/*								*/
/*			    chario.c				*/
/*			     DOS-C				*/
/*								*/
/*    Character device functions and device driver interface	*/
/*								*/
/*			Copyright (c) 1994			*/
/*			Pasquale J. Villani			*/
/*			All Rights Reserved			*/
/*								*/
/* This file is part of DOS-C.					*/
/*								*/
/* DOS-C is free software; you can redistribute it and/or	*/
/* modify it under the terms of the GNU General Public License	*/
/* as published by the Free Software Foundation; either version	*/
/* 2, or (at your option) any later version.			*/
/*								*/
/* DOS-C is distributed in the hope that it will be useful, but	*/
/* WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	*/
/* the GNU General Public License for more details.		*/
/*								*/
/* You should have received a copy of the GNU General Public	*/
/* License along with DOS-C; see the file COPYING.  If not,	*/
/* write to the Free Software Foundation, 675 Mass Ave,		*/
/* Cambridge, MA 02139, USA.					*/
/*								*/
/****************************************************************/

#include "../../hdr/portab.h"

/* $Logfile:   D:/dos-c/src/fs/chario.c_v  $ */
#ifndef IPL
static BYTE *charioRcsId = "$Header:   D:/dos-c/src/fs/chario.c_v   1.3   29 May 1996 21:15:12   patv  $";
#endif

/*
 * $Log:   D:/dos-c/src/fs/chario.c_v  $
 * 
 *    Rev 1.3   29 May 1996 21:15:12   patv
 * bug fixes for v0.91a
 * 
 *    Rev 1.2   01 Sep 1995 17:48:42   patv
 * First GPL release.
 * 
 *    Rev 1.1   30 Jul 1995 20:50:26   patv
 * Eliminated version strings in ipl
 * 
 *    Rev 1.0   02 Jul 1995  8:05:44   patv
 * Initial revision.
 * 
 */

#include "globals.h"

static BYTE *con_name = "CON";

#if !defined(KERNEL) && !defined(IPL)
VOID INRPT FAR 
handle_break (void)
{
}
#endif

#ifdef PROTO
BOOL _sto(COUNT);
VOID kbfill(keyboard FAR *, UCOUNT, BOOL);
#else
BOOL _sto();
VOID kbfill();
#endif

static BOOL 
_sto (COUNT c)
{
	request rq;
	BYTE buf = c;

	if(con_break())
	{
		handle_break();
		return FALSE;
	}
	rq.r_length = sizeof(request);
	rq.r_command = C_OUTPUT;
	rq.r_count = 1;
	rq.r_trans = (BYTE FAR *)(&buf);
	rq.r_status = 0;
	execrh((request FAR *)&rq, (struct dhdr FAR *)&con_dev);
	if(rq.r_status & S_ERROR)
		return char_error(&rq, con_name);
	return TRUE;
}


VOID 
sto (COUNT c)
{
	/* Test for hold char					*/
	con_hold();
	
	/* Display a printable character			*/
	if(c != HT)
		_sto(c);
	if(c == CR)
		scr_pos = 0;
	else if(c == BS)
	{
		if(scr_pos > 0)
			--scr_pos;
	}
	else if(c == HT)
	{
		do
			_sto(' ');
		while(++scr_pos & 7);
	}
	else if(c != LF && c != BS)
		++scr_pos;
}


VOID 
mod_sto (REG UCOUNT c)
{
	if(c < ' ' && c != HT)
	{
		sto('^');
		sto(c + '@');
	}
	else
		sto(c);
}


VOID 
destr_bs (void)
{
	sto(BS);
	sto(' ');
	sto(BS);
}


UCOUNT 
_sti (void)
{
	UBYTE cb;
	request rq;

	rq.r_length = sizeof(request);
	rq.r_command = C_INPUT;
	rq.r_count = 1;
	rq.r_trans = (BYTE FAR *)&cb;
	rq.r_status = 0;
	execrh((request FAR *)&rq, (struct dhdr FAR *)&con_dev);
	if(rq.r_status & S_ERROR)
		return char_error(&rq, con_name);
	if(cb == CTL_C)
	{
		handle_break();
		return CTL_C;
	}
	else
		return cb;
}

VOID 
con_hold (void)
{
	request rq;

	rq.r_unit = 0;
	rq.r_status = 0;
	rq.r_command = C_NDREAD;
	rq.r_length = sizeof(request);
	execrh((request FAR *)&rq, (struct dhdr FAR *)&con_dev);
	if(rq.r_status & S_BUSY)
		return;
	if(rq.r_ndbyte == CTL_S)
	{
		_sti();
		while(_sti() != CTL_Q)
			/* just wait */;
	}
}


BOOL 
con_break (void)
{
	request rq;

	rq.r_unit = 0;
	rq.r_status = 0;
	rq.r_command = C_NDREAD;
	rq.r_length = sizeof(request);
	execrh((request FAR *)&rq, (struct dhdr FAR *)&con_dev);
	if(rq.r_status & S_BUSY)
		return FALSE;
	if(rq.r_ndbyte == CTL_C)
	{
		_sti();
		return TRUE;
	}
	else
		return FALSE;
}


BOOL 
KbdBusy (void)
{
	request rq;

	rq.r_unit = 0;
	rq.r_status = 0;
	rq.r_command = C_ISTAT;
	rq.r_length = sizeof(request);
	execrh((request FAR *)&rq, (struct dhdr FAR *)&con_dev);
	if(rq.r_status & S_BUSY)
		return TRUE;
	else
		return FALSE;
}


VOID 
KbdFlush (void)
{
	request rq;

	rq.r_unit = 0;
	rq.r_status = 0;
	rq.r_command = C_IFLUSH;
	rq.r_length = sizeof(request);
	execrh((request FAR *)&rq, (struct dhdr FAR *)&con_dev);
}


static VOID kbfill(kp, c, ctlf)
keyboard FAR *kp;
UCOUNT c;
BOOL ctlf;
{
	if(kp -> kb_count > kp -> kb_size)
	{
		sto(BELL);
		return;
	}
	kp -> kb_buf[kp -> kb_count++] = c;
	if(!ctlf)
		mod_sto(c);
	else
		sto(c);
}


VOID sti(kp)
keyboard FAR *kp;
{
	REG UWORD c, cu_pos = scr_pos;
	WORD init_count = kp -> kb_count;
#ifndef NOSPCL
	static BYTE local_buffer[LINESIZE];
#endif

	if(kp -> kb_size == 0)
		return;
	if(kp -> kb_size <= kp -> kb_count || kp -> kb_buf[kp -> kb_count] != CR)
		kp -> kb_count = 0;
	FOREVER
	{
		switch(c = _sti())
		{
		case CTL_F:
			continue;

#ifndef NOSPCL
		case SPCL:
			switch(c = _sti())
			{
			case LEFT:
				goto backspace;

			case F3:
			{
				REG COUNT i;

				for(i = kp -> kb_count; local_buffer[i] != '\0'; i++)
				{
					c = local_buffer[kp -> kb_count];
					if(c == '\r' || c == '\n')
						break;
					kbfill(kp, c, FALSE);
				}
				break;
			}

			case RIGHT:
				c = local_buffer[kp -> kb_count];
				if(c == '\r' || c == '\n')
					break;
				kbfill(kp, c, FALSE);
				break;
			}
			break;
#endif

		case CTL_BS:
		case BS:
		backspace:
			if(kp -> kb_count > 0)
			{
				if(kp -> kb_buf[kp -> kb_count - 1] >= ' ')
				{
					destr_bs();
				}
				else if((kp -> kb_buf[kp -> kb_count - 1] < ' ')
				 && (kp -> kb_buf[kp -> kb_count - 1] != HT))
				{
					destr_bs();
					destr_bs();
				}
				else if(kp -> kb_buf[kp -> kb_count - 1] == HT)
				{
					do
					{
						destr_bs();
					}
					while((scr_pos > cu_pos) && (scr_pos & 7));
				}
				--kp -> kb_count;
			}
			break;

		case CR:
			kbfill(kp, CR, TRUE);
			kbfill(kp, LF, TRUE);
#ifndef NOSPCL
			fbcopy((BYTE FAR *)kp -> kb_buf,
			 (BYTE FAR *)local_buffer, (COUNT)kp -> kb_count);
			local_buffer[kp -> kb_count] = '\0';
#endif
			return;

		case LF:
			sto(CR);
			sto(LF);
			break;

		case ESC:
			sto('\\');
			sto(CR);
			sto(LF);
			for(c = 0; c < cu_pos; c++)
				sto(' ');
			kp -> kb_count = init_count;
			break;

		default:
			kbfill(kp, c, FALSE);
			break;
		}
	}
}



[ RETURN TO DIRECTORY ]