mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-22 16:04:18 +00:00
323 lines
6.4 KiB
C
323 lines
6.4 KiB
C
|
|
/********************************************************
|
|
* *
|
|
* P-CP/M BDOS Character I/O Routines *
|
|
* *
|
|
* This module does BDOS functions 1 thru 11 *
|
|
* *
|
|
* It contains the following functions which *
|
|
* are called from the BDOS main routine: *
|
|
* constat(); *
|
|
* conin(); *
|
|
* cookdout(); *
|
|
* rawconio(); *
|
|
* prt_line(); *
|
|
* readline(); *
|
|
* *
|
|
* Copyright (c) 1982 Digital Research, Inc. *
|
|
* *
|
|
********************************************************/
|
|
|
|
#include "stdio.h"
|
|
|
|
#include "bdosdef.h"
|
|
|
|
#include "biosdef.h"
|
|
|
|
|
|
#define ctrlc 0x03
|
|
#define ctrle 0x05
|
|
#define ctrlp 0x10
|
|
#define ctrlq 0x11
|
|
#define ctrlr 0x12
|
|
#define ctrls 0x13
|
|
#define ctrlu 0x15
|
|
#define ctrlx 0x18
|
|
|
|
#define cr 0x0d
|
|
#define lf 0x0a
|
|
#define tab 0x09
|
|
#define rub 0x7f
|
|
#define bs 0x08
|
|
#define space 0x20
|
|
|
|
|
|
EXTERN warmboot(); /* External function definition */
|
|
EXTERN UBYTE cpy_bi(); /* copy byte in from user space */
|
|
|
|
|
|
/******************/
|
|
/* console status */
|
|
/******************/
|
|
|
|
BOOLEAN constat()
|
|
{
|
|
BSETUP
|
|
|
|
return( GBL.kbchar ? TRUE : bconstat() );
|
|
}
|
|
|
|
/********************/
|
|
/* check for ctrl/s */
|
|
/* used internally */
|
|
/********************/
|
|
conbrk()
|
|
{
|
|
REG UBYTE ch;
|
|
REG BOOLEAN stop;
|
|
BSETUP
|
|
|
|
stop = FALSE;
|
|
if ( bconstat() ) do
|
|
{
|
|
if ( (ch = bconin()) == ctrlc ) warmboot(1);
|
|
if ( ch == ctrls ) stop = TRUE;
|
|
else if (ch == ctrlq) stop = FALSE;
|
|
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
|
else GBL.kbchar = ch;
|
|
} while (stop);
|
|
}
|
|
|
|
|
|
/******************/
|
|
/* console output */
|
|
/* used internally*/
|
|
/******************/
|
|
|
|
conout(ch)
|
|
REG UBYTE ch;
|
|
{
|
|
BSETUP
|
|
|
|
conbrk(); /* check for control-s break */
|
|
bconout(ch); /* output character to console */
|
|
if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
|
|
if (ch >= ' ') GBL.column++; /* keep track of screen column */
|
|
else if (ch == cr) GBL.column = 0;
|
|
else if (ch == bs) GBL.column--;
|
|
}
|
|
|
|
|
|
/*************************************/
|
|
/* console output with tab expansion */
|
|
/*************************************/
|
|
|
|
cookdout(ch, ctlout)
|
|
REG UBYTE ch; /* character to output */
|
|
BOOLEAN ctlout; /* output ^<char> for control chars? */
|
|
{
|
|
BSETUP
|
|
|
|
if (ch == tab) do /* expand tabs */
|
|
conout( ' ' );
|
|
while (GBL.column & 7);
|
|
|
|
else
|
|
{
|
|
if ( ctlout && (ch < ' ') )
|
|
{
|
|
conout( '^' );
|
|
ch |= 0x40;
|
|
}
|
|
conout(ch); /* output the character */
|
|
}
|
|
}
|
|
|
|
|
|
/*****************/
|
|
/* console input */
|
|
/*****************/
|
|
|
|
UBYTE getch() /* Get char from buffer or bios */
|
|
/* For internal use only */
|
|
{
|
|
REG UBYTE temp;
|
|
BSETUP
|
|
|
|
temp = GBL.kbchar; /* get buffered char */
|
|
GBL.kbchar = 0; /* clear it */
|
|
return( temp ? temp : bconin() ); /* if non-zero, return it */
|
|
/* else get char from bios */
|
|
}
|
|
|
|
UBYTE conin() /* BDOS console input function */
|
|
{
|
|
REG UBYTE ch;
|
|
BSETUP
|
|
|
|
conout( ch = getch() );
|
|
if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
|
return(ch);
|
|
}
|
|
|
|
/******************
|
|
* raw console i/o *
|
|
******************/
|
|
|
|
UBYTE rawconio(parm) /* BDOS raw console I/O function */
|
|
|
|
REG UWORD parm;
|
|
{
|
|
BSETUP
|
|
|
|
if (parm == 0xff) return(getch());
|
|
else if (parm == 0xfe) return(constat());
|
|
else return(bconout(parm & 0xff)); /* add return to make lint happy */
|
|
}
|
|
|
|
|
|
/****************************************************/
|
|
/* print line up to delimiter($) with tab expansion */
|
|
/****************************************************/
|
|
|
|
prt_line(p)
|
|
REG UBYTE *p;
|
|
{
|
|
BSETUP
|
|
|
|
while( *p != GBL.delim ) cookdout( *(p++), FALSE);
|
|
}
|
|
|
|
|
|
/**********************************************/
|
|
/* read line with editing and bounds checking */
|
|
/**********************************************/
|
|
|
|
/* Two subroutines first */
|
|
|
|
newline(startcol)
|
|
REG UWORD startcol;
|
|
{
|
|
BSETUP
|
|
|
|
conout(cr); /* go to new line */
|
|
conout(lf);
|
|
while(startcol)
|
|
{
|
|
conout(' ');
|
|
startcol -= 1; /* start output at starting column */
|
|
}
|
|
}
|
|
|
|
|
|
backsp(p, stcol) /* backspace one character position */
|
|
REG struct conbuf *p; /* pointer to console buffer */
|
|
UWORD stcol;
|
|
{
|
|
REG WORD i;
|
|
REG WORD length;
|
|
REG UBYTE ch;
|
|
BSETUP
|
|
|
|
if (p->retlen) length = UBWORD(--(p->retlen));
|
|
/* if buffer non-empty, decrease it by 1 */
|
|
else length = 0;
|
|
i = stcol;
|
|
while (length--)
|
|
{
|
|
ch = p->cbuf[length]; /* get character from buffer */
|
|
if ( ch == tab )
|
|
{
|
|
i += 8; /* i is our column counter */
|
|
i &= ~7; /* for tab, go to multiple of 8 */
|
|
}
|
|
else if ( ch < ' ' ) i += 2;
|
|
/* control chars put out 2 printable chars */
|
|
else i += 1;
|
|
}
|
|
while (GBL.column > i)
|
|
{
|
|
conout(bs); /* backspace until we get to proper column */
|
|
conout(' ');
|
|
conout(bs);
|
|
}
|
|
}
|
|
|
|
|
|
readline(p) /* BDOS function 10 */
|
|
REG struct conbuf *p;
|
|
|
|
{
|
|
REG UBYTE ch;
|
|
REG UWORD i;
|
|
REG UWORD j;
|
|
REG UBYTE *q;
|
|
UWORD stcol;
|
|
|
|
BSETUP
|
|
|
|
stcol = GBL.column; /* set up starting column */
|
|
if (GBL.chainp != XNULL) /* chain to program code */
|
|
{
|
|
i = UBWORD(cpy_bi(GBL.chainp++)); /* cpy in from user space */
|
|
j = UBWORD(p->maxlen);
|
|
if (j < i) i = j; /* don't overflow console buffer! */
|
|
p->retlen = (UBYTE)i;
|
|
q = p->cbuf;
|
|
while (i)
|
|
{
|
|
cookdout( *q++ = cpy_bi(GBL.chainp++), TRUE);
|
|
i -= 1;
|
|
}
|
|
GBL.chainp = XNULL;
|
|
return;
|
|
}
|
|
|
|
p->retlen = 0; /* start out with empty buffer */
|
|
while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
|
|
{ /* main loop for read console buffer */
|
|
|
|
if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
|
|
{
|
|
cookdout(ctrlc, TRUE);
|
|
warmboot(1);
|
|
}
|
|
|
|
else if ( (ch == cr) || (ch == lf) )
|
|
{ /* if cr or lf, exit */
|
|
conout(cr);
|
|
break;
|
|
}
|
|
|
|
else if (ch == bs) backsp(p, stcol); /* backspace */
|
|
|
|
else if (ch == rub) /* delete character */
|
|
{
|
|
if (GBL.echodel)
|
|
{
|
|
if (p->retlen)
|
|
{
|
|
i = UBWORD(--(p->retlen));
|
|
conout( p->cbuf[i] );
|
|
}
|
|
}
|
|
else backsp(p, stcol);
|
|
}
|
|
|
|
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
|
/* control-p */
|
|
else if (ch == ctrlx) /* control-x */
|
|
do backsp(p,stcol); while (p->retlen);
|
|
|
|
else if (ch == ctrle) newline(stcol); /* control-e */
|
|
|
|
else if (ch == ctrlu) /* control-u */
|
|
{
|
|
conout('#');
|
|
newline(stcol);
|
|
p->retlen = 0;
|
|
}
|
|
|
|
else if (ch == ctrlr) /* control-r */
|
|
{
|
|
conout('#');
|
|
newline(stcol);
|
|
for (i=0; i < UBWORD(p->retlen); i++)
|
|
cookdout( p->cbuf[i], TRUE);
|
|
}
|
|
|
|
else /* normal character */
|
|
cookdout( (p->cbuf[UBWORD((p->retlen)++)] = ch), TRUE );
|
|
}
|
|
}
|