mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
362 lines
10 KiB
C
362 lines
10 KiB
C
/********************************************************
|
||
* *
|
||
* CP/M-68K 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(); *
|
||
* tabout(); *
|
||
* rawconio(); *
|
||
* prt_line(); *
|
||
* readline(); *
|
||
* *
|
||
* Copyright (c) 1982 Digital Research, Inc. *
|
||
* *
|
||
* Modified 2/5/84 sw Allow typeahead *
|
||
* ^C warmboot modifications *
|
||
* Again 3/17/84 sw Chain hack *
|
||
* *
|
||
********************************************************/
|
||
|
||
#include "bdosinc.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 */
|
||
|
||
|
||
/******************/
|
||
/* 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(2); /*sw from (1) */
|
||
if ( ch == ctrls ) stop = TRUE;
|
||
else if (ch == ctrlq) stop = FALSE;
|
||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||
/*sw What Follows is new... */
|
||
else /* Insert character in ring buffer */
|
||
{ /* */
|
||
if(GBL.kbchar < TBUFSIZ) /* Room? */
|
||
{ /************************************/
|
||
*GBL.insptr++ = ch; /* Yes, insert the character in buff*/
|
||
GBL.kbchar++; /* Up count */
|
||
} /************************************/
|
||
} /* Note if no room, character is */
|
||
/* Ignomiously discarded (!) */
|
||
/*sw End of new stuff */
|
||
/************************************/
|
||
} 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 ((UWORD)ch >= (UWORD)' ')
|
||
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 */
|
||
/*************************************/
|
||
|
||
tabout(ch)
|
||
REG UBYTE ch; /* character to output to console */
|
||
{
|
||
BSETUP
|
||
|
||
if (ch == tab) do
|
||
conout(' ');
|
||
while (GBL.column & 7);
|
||
else conout(ch);
|
||
}
|
||
|
||
/*******************************/
|
||
/* console output with tab and */
|
||
/* control character expansion */
|
||
/*******************************/
|
||
|
||
cookdout(ch)
|
||
REG UBYTE ch; /* character to output to console */
|
||
{
|
||
if (ch == tab) tabout(ch); /* if tab, expand it */
|
||
else
|
||
{
|
||
if ( (UWORD)ch < (UWORD)' ' )
|
||
{
|
||
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
|
||
|
||
if(GBL.kbchar)
|
||
{
|
||
temp = *GBL.remptr++; /* Fetch the character */
|
||
GBL.kbchar--; /* Decrement the count */
|
||
if(!GBL.kbchar) /* Gone to zero? */
|
||
GBL.remptr = GBL.insptr = &(GBL.t_buff[0]);
|
||
return(temp);
|
||
}
|
||
return( bconin() ); /* 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 bconout(parm & 0xff);
|
||
}
|
||
|
||
|
||
/****************************************************/
|
||
/* print line up to delimiter($) with tab expansion */
|
||
/****************************************************/
|
||
|
||
prt_line(p)
|
||
REG UBYTE *p;
|
||
{
|
||
BSETUP
|
||
|
||
while( *p != GBL.delim ) tabout( *p++ );
|
||
}
|
||
|
||
|
||
/**********************************************/
|
||
/* 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(bufp, col)
|
||
/* backspace one character position */
|
||
REG struct conbuf *bufp; /* pointer to console buffer */
|
||
REG WORD col; /* starting console column */
|
||
{
|
||
REG UBYTE ch; /* current character */
|
||
REG WORD i;
|
||
REG UBYTE *p; /* character pointer */
|
||
BSETUP
|
||
|
||
if (bufp->retlen) --(bufp->retlen);
|
||
/* if buffer non-empty, decrease it by 1 */
|
||
i = UBWORD(bufp->retlen); /* get new character count */
|
||
p = &(bufp->cbuf[0]); /* point to character buffer */
|
||
while (i--) /* calculate column position */
|
||
{ /* across entire char buffer */
|
||
ch = *p++; /* get next char */
|
||
if ( ch == tab )
|
||
{
|
||
col += 8;
|
||
col &= ~7; /* for tab, go to multiple of 8 */
|
||
}
|
||
else if ( (UWORD)ch < (UWORD)' ' ) col += 2;
|
||
/* control chars put out 2 printable chars */
|
||
else col += 1;
|
||
}
|
||
while (GBL.column > col)
|
||
{
|
||
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 */
|
||
|
||
#ifdef NFG /*sw This didn't work for SUBMIT files...*/
|
||
if (GBL.chainp != NULL) /* chain to program code */
|
||
{
|
||
i = UBWORD(*(GBL.chainp++));
|
||
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++ = *(GBL.chainp++) );
|
||
i -= 1;
|
||
}
|
||
GBL.chainp = NULL;
|
||
return;
|
||
}
|
||
#endif /*sw NFG chain code */
|
||
|
||
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);
|
||
warmboot(2); /*sw From 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] );
|
||
}
|
||
|
||
else /* normal character */
|
||
cookdout( p->cbuf[UBWORD((p->retlen)++)] = ch );
|
||
}
|
||
}
|
||
|