399 lines
7.7 KiB
C
399 lines
7.7 KiB
C
/**
|
||
* KSvt100
|
||
*
|
||
* This library offers a common interface for keyboard and screen devices
|
||
* using VT100 control codes
|
||
*
|
||
* This is a stripped down version of KS to only support VT100, but includes
|
||
* color codes
|
||
*/
|
||
|
||
/* ks.h
|
||
|
||
Keyboard & screen functions library for CP/M & MESCC - Mike's Enhanced Small C Compiler.
|
||
|
||
Stripped down version for VT100+color by Anna Christina Naß <acn@acn.wtf>
|
||
|
||
Copyright (c) 2016, 2017 Miguel I. Garcia Lopez / FloppySoftware, Spain
|
||
|
||
This program 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 3, or (at your option) any
|
||
later version.
|
||
|
||
This program 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 this program; if not, write to the Free Software
|
||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
*/
|
||
|
||
int xks_rows = 25; // Screen rows
|
||
int xks_cols = 80; // Screen columns
|
||
BYTE *xks_clrscr = "\e[H\e[J"; // Clear screen
|
||
BYTE *xks_poscur = "\e[%r;%cH"; // Position cursor
|
||
BYTE *xks_shwcur = "\e[?25h"; // Show cursor
|
||
BYTE *xks_hidcur = "\e[?25l"; // Hide cursor
|
||
BYTE *xks_yrever = "\e[7m"; // Reverse on
|
||
BYTE *xks_nrever = "\e[m"; // Reverse off
|
||
BYTE *xks_yuline = "\e[4m"; // Underline on
|
||
BYTE *xks_nuline = "\e[m"; // Underline off
|
||
|
||
#define RESET "\e[0m" // reset all attributes
|
||
#define FGBLK "\e[30m" // black
|
||
#define FGRED "\e[31m" // red
|
||
#define FGGRN "\e[32m" // green
|
||
#define FGYEL "\e[33m" // yellow
|
||
#define FGBLU "\e[34m" // blue
|
||
#define FGMAG "\e[35m" // magenta
|
||
#define FGCYN "\e[36m" // cyan
|
||
#define FGWHT "\e[37m" // white/gray
|
||
#define FGBGRY "\e[30;1m" // gray ("bright black")
|
||
#define FGBRED "\e[31;1m" // bright red
|
||
#define FGBGRN "\e[32;1m" // bright green
|
||
#define FGBYEL "\e[33;1m" // bright yellow
|
||
#define FGBBLU "\e[34;1m" // bright blue
|
||
#define FGBMAG "\e[35;1m" // bright magenta
|
||
#define FGBCYN "\e[36;1m" // bright cyan
|
||
#define FGBWHT "\e[37;1m" // bright white
|
||
#define BGBLK "\e[40m" // black
|
||
#define BGRED "\e[41m" // red
|
||
#define BGGRN "\e[42m" // green
|
||
#define BGYEL "\e[43m" // yellow
|
||
#define BGBLU "\e[44m" // blue
|
||
#define BGMAG "\e[45m" // magenta
|
||
#define BGCYN "\e[46m" // cyan
|
||
#define BGWHT "\e[47m" // white
|
||
|
||
|
||
/**
|
||
* @fn int KsHello(char *tty_name)
|
||
* @brief Initialize the KS library.
|
||
* Call this function before any other function (with a few exceptions).
|
||
* @param code - TTY code
|
||
* @return 0 on success, -1 on failure
|
||
*/
|
||
KsHello(code)
|
||
int code;
|
||
{
|
||
// Setup BIOS jumps, etc.
|
||
xKsInit();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @fn void KsBye(void)
|
||
* @brief Reset the KS library.
|
||
* Call this function before you stop your program, in order to reset the TTY.
|
||
*/
|
||
KsBye()
|
||
{
|
||
// Nothing yet
|
||
}
|
||
|
||
/**
|
||
* @fn int KsGetCode(char *name)
|
||
* @brief Get the code for a TTY name.
|
||
* This function can be called before KsHello().
|
||
* @param name - TTY name
|
||
* @return TTY code if found, or -1 on unknown name
|
||
*/
|
||
KsGetCode(name)
|
||
char *name;
|
||
{
|
||
if(strcmp(name, "VT100")) {
|
||
return 0;
|
||
}
|
||
else {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn int KsGetName(int code)
|
||
* @brief Get the name for a TTY code.
|
||
* This function can be called before KsHello().
|
||
* @param code - TTY code
|
||
* @return TTY name, or NULL on unknown code
|
||
*/
|
||
KsGetName(code)
|
||
int code;
|
||
{
|
||
if(code==0) {
|
||
return "VT100";
|
||
}
|
||
else {
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn char **KsGetNames(void)
|
||
* @brief Get all supported TTY names.
|
||
* This function can be called before KsHello().
|
||
* @return Pointer to an array of pointers to char
|
||
*/
|
||
KsGetNames()
|
||
{
|
||
WORD xks_names[1];
|
||
xks_names[0] = "VT100";
|
||
return xks_names;
|
||
}
|
||
|
||
/**
|
||
* @fn int KsGetHowMany(void)
|
||
* @brief Get the number of supported TTYs.
|
||
* This function can be called before KsHello().
|
||
* @return Number of supported TTYs
|
||
*/
|
||
KsGetHowMany()
|
||
{
|
||
return 1;
|
||
}
|
||
|
||
/**
|
||
* @fn void KsClear(void)
|
||
* @brief Clear the screen and move the cursor to 0,0.
|
||
*/
|
||
KsClear()
|
||
{
|
||
KsPutRawStr(xks_clrscr);
|
||
}
|
||
|
||
/**
|
||
* @fn void KsPosCursor(int row, int col)
|
||
* @brief Move the cursor on screen.
|
||
* @param row - screen row from 0
|
||
* @param col - screen column from 0
|
||
*/
|
||
KsPosCursor(row, col)
|
||
int row, col;
|
||
{
|
||
char *p; int v;
|
||
|
||
for(p = xks_poscur; *p; ++p) {
|
||
if(*p != '%') {
|
||
KsPutRawCh(*p);
|
||
}
|
||
else {
|
||
v = (*(++p) == 'r' ? row : col);
|
||
xKsPutDec(1 + v);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn void KsSetCursor(int toggle)
|
||
* @brief Show or hide the cursor on screen.
|
||
* @param toggle - 0 to hide, other to show
|
||
*/
|
||
KsSetCursor(toggle)
|
||
int toggle;
|
||
{
|
||
if(xks_shwcur) {
|
||
KsPutRawStr(toggle ? xks_shwcur : xks_hidcur);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn void KsUnderline(int toggle)
|
||
* @brief Set or reset underline text.
|
||
* If the TTY does not have this capability, does nothing.
|
||
* @param toggle - 0 to reset, other to set
|
||
*/
|
||
KsUnderline(toggle)
|
||
int toggle;
|
||
{
|
||
if(xks_yuline) {
|
||
KsPutRawStr(toggle ? xks_yuline : xks_nuline);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn void KsReverse(int toggle)
|
||
* @brief Set or reset reverse text.
|
||
* If the TTY does not have this capability, does nothing.
|
||
* @param toggle - 0 to reset, other to set
|
||
*/
|
||
KsReverse(toggle)
|
||
int toggle;
|
||
{
|
||
if(xks_yrever) {
|
||
KsPutRawStr(toggle ? xks_yrever : xks_nrever);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn int KsGetRows(void)
|
||
* @brief Get TTY rows.
|
||
* @return TTY rows.
|
||
*/
|
||
KsGetRows()
|
||
{
|
||
return xks_rows;
|
||
}
|
||
|
||
/**
|
||
* @fn int KsGetCols(void)
|
||
* @brief Get TTY columns.
|
||
* @return TTY columns.
|
||
*/
|
||
KsGetCols()
|
||
{
|
||
return xks_cols;
|
||
}
|
||
|
||
/**
|
||
* @fn void KsCenterStr(int row, char *s)
|
||
* @brief Print a string centered on screen.
|
||
* @param row - screen row
|
||
* @param s - string
|
||
*/
|
||
KsCenterStr(row, s)
|
||
int row; char *s;
|
||
{
|
||
KsPosCursor(row, (KsGetCols() - strlen(s)) / 2);
|
||
KsPutStr(s);
|
||
}
|
||
|
||
/**
|
||
* @fn void KsPutRawCh(int ch)
|
||
* @brief Send a character to the TTY.
|
||
* @param ch - character
|
||
*/
|
||
#asm
|
||
KsPutRawCh
|
||
ld c,l
|
||
jp xKsConOut
|
||
#endasm
|
||
|
||
/**
|
||
* @fn void KsPutRawStr(char *s)
|
||
* @brief Send a string to the TTY using KsPutRawCh().
|
||
* @param s - string
|
||
*/
|
||
KsPutRawStr(s)
|
||
char *s;
|
||
{
|
||
while(*s) {
|
||
KsPutRawCh(*s++);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn void KsPutCh(int ch)
|
||
* @brief Send a character to the TTY.
|
||
* This functions performs the following translations:
|
||
* - '\n' to '\r' + '\n'
|
||
* @param ch - character
|
||
*/
|
||
#asm
|
||
KsPutCh
|
||
ld a,l
|
||
cp 10
|
||
jp nz,KsPutRawCh
|
||
ld l,13
|
||
call KsPutRawCh
|
||
ld l,10
|
||
jp KsPutRawCh
|
||
#endasm
|
||
|
||
/**
|
||
* @fn void KsPutStr(char *s)
|
||
* @brief Send a string to the TTY using KsPutCh().
|
||
* @param s - string
|
||
*/
|
||
KsPutStr(s)
|
||
char *s;
|
||
{
|
||
while(*s) {
|
||
KsPutCh(*s++);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @fn int KsGetKb(void)
|
||
* @brief Check if there is an input character from the keyboard.
|
||
* @return 0 for NO, other for YES
|
||
*/
|
||
#asm
|
||
KsGetKb:
|
||
call xKsConInSt
|
||
ld h,a
|
||
ld l,a
|
||
ret
|
||
#endasm
|
||
|
||
/**
|
||
* @fn int KsGetCh(void)
|
||
* @brief Get character from the keyboard, waiting for one if necessary.
|
||
* @return character
|
||
*/
|
||
#asm
|
||
KsGetCh
|
||
call xKsConIn
|
||
ld h,0
|
||
ld l,a
|
||
ret
|
||
#endasm
|
||
|
||
/* Private functions
|
||
-----------------
|
||
*/
|
||
|
||
// void xKsInit(void) : Set BIOS JUMPs.
|
||
#asm
|
||
xKsInit
|
||
ld hl,(1)
|
||
inc hl
|
||
inc hl
|
||
inc hl
|
||
ld de,xKsConInSt
|
||
ld bc,9
|
||
ldir
|
||
ret
|
||
|
||
xKsConInSt
|
||
jp 0 ; BIOS ConSt
|
||
xKsConIn
|
||
jp 0 ; BIOS ConIn
|
||
xKsConOut
|
||
jp 0 ; BIOS ConOut
|
||
#endasm
|
||
|
||
// void xKsPutDec(int num) : Send positive decimal number to TTY.
|
||
xKsPutDec(num)
|
||
int num;
|
||
{
|
||
#ifdef SPRINTF_H
|
||
char buf[6];
|
||
|
||
sprintf(buf, "%d", num);
|
||
|
||
KsPutRawStr(buf);
|
||
#else
|
||
char buf[6];
|
||
int i;
|
||
|
||
for(i = 0; i < 6; ++i) {
|
||
if(num > 9) {
|
||
buf[i] = num % 10;
|
||
num /= 10;
|
||
}
|
||
else {
|
||
buf[i++] = num;
|
||
break;
|
||
}
|
||
}
|
||
|
||
do {
|
||
KsPutRawCh('0' + buf[--i]);
|
||
} while(i);
|
||
#endif
|
||
}
|
||
|
||
|