/****************************************************************************
*
* Console Output Library
*
* Copyright (C) 1996 SciTech Software
* All rights reserved.
*
* Filename: $Workfile: console.c $
* Version: $Revision: 1.0 $
*
* Language: ANSI C
* Environment: IBM PC 16/32 bit code
*
* Description: Main module for console manipulation module. This is a
* small module for fast, compiler independant console
* output routines. It has been modified to for use with
* 32 bit flat model compilers and the code is being made
* freely available for use in the POVRay Ray Tracer.
*
* Has also been completely re-written to only use direct
* video output code, since there is not longer any need to
* send any output via the BIOS these days, and to no longer
* use any assembler specific code.
*
* $Date: 05 Feb 1996 20:44:28 $ $Author: KendallB $
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "console.h"
#include "pmode.h"
/*---------------------------- Global variables ---------------------------*/
#define LINES_43 0x2000
#define LINES_50 0x4000
PRIVATE int _attr = 0x07; /* Current global attribute */
PRIVATE int _backAttr = 0x07; /* Background attribute */
PRIVATE int _backChar = ' '; /* Background character */
PRIVATE int _activePage; /* Active display page */
PRIVATE int _visualPage; /* Visual display page */
PRIVATE int _win_left; /* Left edge of window */
PRIVATE int _win_top; /* Top edge of window */
PRIVATE int _win_right; /* Right edge of window */
PRIVATE int _win_bottom; /* Bottom edge of window */
PRIVATE int _win_width; /* Width of window */
PRIVATE int _win_height; /* Height of window */
PRIVATE int _screenWidth; /* Width of entire screen */
PRIVATE int _screenHeight; /* Height of entire screen */
PRIVATE char *_screenPtrBase; /* Pointer to video buffer start*/
PRIVATE char *_screenPtr; /* Pointer to video display */
PRIVATE uint _biosSel; /* Selector to BIOS data area */
PRIVATE int _cnt_x = 0,_cnt_y = 0; /* Current cursor coordinates */
PRIVATE bool _lineWrap = true; /* Line wrap mode */
PRIVATE int _oldMode; /* Old BIOS mode */
/*---------------------------- Implementation -----------------------------*/
#define bufferAddr(x,y) (_screenPtr + (((_screenWidth * (y)) + (x)) * 2))
#define writeChar(x,y,ch,attr) \
{ \
char *p = bufferAddr((x),(y)); \
*p++ = (ch); \
*p = attr; \
}
#define writeStr(x,y,attr,str,len) \
{ \
char *p = bufferAddr(x,y); \
while ((len)--) { \
*p++ = *str++; \
*p++ = attr; \
} \
}
PRIVATE void moveText(int left,int top,int right,int bottom,int dstLeft,
int dstTop)
/****************************************************************************
*
* Function: moveText
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* destleft - Destination region left edge
* desttop - Destination region top edge
*
* Description: Moves a block of video memory to another location using
* calls to the direct video routine screentoscreen().
*
****************************************************************************/
{
int i,increment,len;
char *source,*dest;
increment = _screenWidth * 2;
len = (right - left + 1) * 2;
if (top > dstTop) {
source = bufferAddr(left,top);
dest = bufferAddr(dstLeft,dstTop);
for (i = top; i <= bottom; i++) {
memmove(dest,source,len);
source += increment;
dest += increment;
}
}
else {
source = bufferAddr(left,bottom);
dest = bufferAddr(dstLeft,(dstTop + bottom - top));
for (i = top; i <= bottom; i++) {
memmove(dest,source,len);
source -= increment;
dest -= increment;
}
}
}
PRIVATE void moveToScreen(int left,int top,int right,int bottom,
char *source)
/****************************************************************************
*
* Function: moveToScreen
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* source - Place to store the memory region
*
* Description: Moves a block of video memory from a buffer directly to
* the screen.
*
****************************************************************************/
{
int i,increment,len;
char *dest = bufferAddr(left,top);
increment = _screenWidth * 2;
len = (right - left + 1) * 2;
for (i = top; i <= bottom; i++) {
memcpy(dest,source,len);
source += len;
dest += increment;
}
}
PRIVATE void moveFromScreen(int left,int top,int right,int bottom,
char *dest)
/****************************************************************************
*
* Function: moveFromScreen
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* dest - Place to store the memory region
*
* Description: Moves a block of video memory from the screen into a buffer.
*
****************************************************************************/
{
int i,increment,len;
char *source = bufferAddr(left,top);
increment = _screenWidth * 2;
len = (right - left + 1) * 2;
for (i = top; i <= bottom; i++) {
memcpy(dest,source,len);
source += increment;
dest += len;
}
}
PRIVATE void fillText(int left,int top,int right,int bottom,int attr,int ch)
/****************************************************************************
*
* Function: fillText
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* attr - Attribute to fill with
* ch - Character to fill with
*
* Description: Fills a block of memory with the specified character and
* attribute.
*
****************************************************************************/
{
int i,j,increment,len;
char *dest = bufferAddr(left,top);
len = (right - left + 1);
increment = (_screenWidth - len) * 2;
for (i = top; i <= bottom; i++) {
for (j = 0; j < len; j++) {
*dest++ = ch;
*dest++ = attr;
}
dest += increment;
}
}
PRIVATE void fillAttr(int left,int top,int right,int bottom,int attr)
/****************************************************************************
*
* Function: fillAttr
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* attr - Attribute to fill with
*
* Description: Fills a block of memory with the specified attribute,
* leaving the characters unchanged.
*
****************************************************************************/
{
int i,j,increment,len;
char *dest = bufferAddr(left,top);
len = (right - left + 1);
increment = (_screenWidth - len) * 2;
for (i = top; i <= bottom; i++) {
for (j = 0; j < len; j++) {
dest++;
*dest++ = attr;
}
dest += increment;
}
}
void _PUBAPI CON_init(void)
/****************************************************************************
*
* Function: CON_init
*
* Description: Initialise the console subsystem. This should be called
* at program inception, and also after any changes to the
* current video mode (ie: change to 43 line mode, change to
* monochrome adapter etc).
*
****************************************************************************/
{
_biosSel = PM_getBIOSSelector();
if (CON_isMonoMode())
_screenPtrBase = PM_mapPhysicalAddr(0xB0000L, 0xFFFF);
else _screenPtrBase = PM_mapPhysicalAddr(0xB8000L, 0xFFFF);
_win_width = _screenWidth = PM_getByte(_biosSel,0x4A);
_win_height = _screenHeight = PM_getByte(_biosSel,0x84)+1;
_win_left = _win_top = 0;
_win_right = _win_width - 1;
_win_bottom = _win_height - 1;
CON_setVisualPage(0);
CON_setActivePage(0);
CON_setCursor(CON_CURSOR_NORMAL);
/* Save current video mode so we can restore it later */
_oldMode = PM_getByte(_biosSel, 0x49);
if (_screenHeight == 43)
_oldMode |= LINES_43;
if (_screenHeight == 50)
_oldMode |= LINES_50;
}
void _PUBAPI CON_restoreMode(void)
/****************************************************************************
*
* Function: CON_restoreMode
*
* Description: Restore the original text mode active when CON_init()
* was called. Will correctly restore 25, 43 and 50 line
* VGA video modes.
*
****************************************************************************/
{
PMREGS regs;
CON_set25LineMode(); /* Reset to 80x25 mode first */
regs.h.ah = 0x00; /* Set video mode service */
regs.h.al = (char)_oldMode; /* Mode into AL */
PM_int386(0x10,®s,®s);
if ((_oldMode & ~LINES_43) == 0x03 && (_oldMode & LINES_43))
CON_set43LineMode();
if ((_oldMode & ~LINES_50) == 0x03 && (_oldMode & LINES_50))
CON_set50LineMode();
}
void _PUBAPI CON_set25LineMode(void)
/****************************************************************************
*
* Function: CON_set25LineMode
*
* Description: Set the standard VGA 80x25 line video mode.
*
****************************************************************************/
{
PMREGS regs;
regs.x.ax = 0x1202; /* Set system into 400 line mode */
regs.x.bx = 0x30;
PM_int386(0x10,®s,®s);
regs.x.ax = 0x3; /* Set 80x25 text mode */
PM_int386(0x10,®s,®s);
}
bool _PUBAPI CON_set43LineMode(void)
/****************************************************************************
*
* Function: CON_set43LineMode
*
* Description: Set the standard VGA 80x43 line video mode.
*
****************************************************************************/
{
PMREGS regs;
if (CON_isMonoMode())
return false;
regs.x.ax = 0x1201; /* Set system into 350 line mode */
regs.x.bx = 0x30;
PM_int386(0x10,®s,®s);
regs.x.ax = 0x3;
PM_int386(0x10,®s,®s); /* Set 80x25 text mode */
regs.x.ax = 0x1112; /* Load 8x8 character font */
regs.x.bx = 0x0;
PM_int386(0x10,®s,®s);
return true;
}
bool _PUBAPI CON_set50LineMode(void)
/****************************************************************************
*
* Function: CON_set50LineMode
*
* Description: Set the standard VGA 80x50 line video mode.
*
****************************************************************************/
{
PMREGS regs;
if (CON_isMonoMode())
return false;
regs.x.ax = 0x1202; /* Set system into 400 line mode */
regs.x.bx = 0x30;
PM_int386(0x10,®s,®s);
regs.x.ax = 0x3; /* Set 80x25 text mode */
PM_int386(0x10,®s,®s);
regs.x.ax = 0x1112; /* Load 8x8 character font */
regs.x.bx = 0x0;
PM_int386(0x10,®s,®s);
return true;
}
void _PUBAPI CON_printf(char *format, ...)
/****************************************************************************
*
* Function: CON_printf
* Parameters: format - Format string
*
* Description: Printf function that sends its output via the CONSOLE
* routines, either through the BIOS or direct to video ram.
* Formatting information is handled correctly.
*
****************************************************************************/
{
va_list args;
static char buf[256];
va_start(args,format);
vsprintf(buf,format,args);
CON_puts(buf);
va_end(args);
}
PRIVATE void outputBuf(char *buf,int len)
{
writeStr(_cnt_x + _win_left,_cnt_y + _win_top,_attr,buf,len);
}
PRIVATE void syncCursor(void)
/****************************************************************************
*
* Function: syncCursor
*
* Description: Sync up the current cursor location and the BIOS cursor
* position in case we have intermixed normal console IO
* with out high speed IO routines.
*
****************************************************************************/
{
_cnt_x = PM_getByte(_biosSel, 0x50 + _activePage*2) - _win_left;
_cnt_y = PM_getByte(_biosSel, 0x51 + _activePage*2) - _win_top;
}
void _PUBAPI CON_puts(char *str)
/****************************************************************************
*
* Function: CON_puts
* Parameters: str - String to output
*
* Description: Outputs a string to the video display. Formatting info
* is handled correctly. The following formatting
* characters are handled:
*
* \f Clear window and home cursor
* \n Advance a line, scrolling window if necessary
* \r Move to left edge of window
* \b Move one character left (non-destructive)
*
* The screen will scroll up if you go past the bottom line
* of the window. Characters that go past the end of the
* current line wrap depending on the setting of wrapmode. If
* wrapmode is true (default), characters wrap to the beginning
* of the next line, otherwise they wrap to the beginning of
* the same line.
*
* To speed up the output of this function, we build a
* temporary buffer to store each contiguous section of the
* string to be output as a single entity.
*
****************************************************************************/
{
static char buf[256];
char *p;
int len;
/* Sync up with current BIOS cursor location */
syncCursor();
len = *(p = buf) = 0;
while (*str) {
switch (*str) {
case '\f':
CON_clrscr();
len = *(p = buf) = 0; /* Discard buffer contents */
break;
case '\n':
outputBuf(buf,len);
_cnt_x += len;
len = *(p = buf) = 0;
if (++_cnt_y >= _win_height) {
_cnt_y = _win_height-1;
CON_scroll(CON_SCROLL_UP,1);
}
CON_gotoxy(_cnt_x,_cnt_y);
break;
case '\r':
outputBuf(buf,len);
len = *(p = buf) = 0;
_cnt_x = 0;
CON_gotoxy(_cnt_x,_cnt_y);
break;
case '\b':
if (_cnt_x + --len < 0)
len = 0;
else
--p;
break;
default:
*p++ = *str;
len++;
if (_cnt_x + len >= _win_width) {
outputBuf(buf,len);
len = *(p = buf) = 0;
_cnt_x = 0;
if (_lineWrap) {
if (++_cnt_y >= _win_height) {
_cnt_y = _win_height-1;
CON_scroll(CON_SCROLL_UP,1);
}
}
CON_gotoxy(_cnt_x,_cnt_y);
}
break;
}
str++;
}
outputBuf(buf,len);
_cnt_x += len;
CON_gotoxy(_cnt_x,_cnt_y);
}
void _PUBAPI CON_putc(int c)
/****************************************************************************
*
* Function: CON_putc
* Parameters: c - Character to output
*
* Description: Displays a single character on the console. Formatting
* information is handled correctly. The following formatting
* characters are handled:
*
* \f Clear window and home cursor
* \n Advance a line, scrolling window if necessary
* \r Move to left edge of window
* \b Move one character left (non-destructive)
*
* The screen will scroll up if you go past the bottom line
* of the window. Characters that go past the end of the
* current line wrap depending on the setting of wrapmode. If
* wrapmode is true (default), characters wrap to the beginning
* of the next line, otherwise they wrap to the beginning of
* the same line.
*
****************************************************************************/
{
/* Sync up with current BIOS cursor location */
syncCursor();
switch (c) {
case 0:
break; /* Ignore ASCII NULL's */
case '\f':
CON_clrscr();
break;
case '\n':
if (++_cnt_y >= _win_height) {
_cnt_y = _win_height-1;
CON_scroll(CON_SCROLL_UP,1);
}
break;
case '\r':
_cnt_x = 0;
break;
case '\b':
if (--_cnt_x < 0)
_cnt_x = 0;
break;
default:
writeChar(_cnt_x + _win_left,_cnt_y + _win_top,c,_attr);
if (++_cnt_x >= _win_width) {
_cnt_x = 0;
if (_lineWrap) {
if (++_cnt_y >= _win_height) {
_cnt_y = _win_height-1;
CON_scroll(CON_SCROLL_UP,1);
}
}
}
break;
}
CON_gotoxy(_cnt_x,_cnt_y);
}
void _PUBAPI CON_clreol(void)
/****************************************************************************
*
* Function: CON_clreol
*
* Description: Clears from the current position to the end of the line.
*
****************************************************************************/
{
syncCursor();
CON_fillText(_cnt_x,_cnt_y,_win_width-1,_cnt_y,_backAttr,_backChar);
}
void _PUBAPI CON_clrscr(void)
/****************************************************************************
*
* Function: CON_clrscr
*
* Description: Clears the window and moves the cursor to the top left
* hand corner of the window (0,0). The window is cleared with
* the current background character and in the current
* background attribute.
*
****************************************************************************/
{
syncCursor();
CON_fillText(0,0,_win_width-1,_win_height-1,_backAttr,_backChar);
_cnt_x = _cnt_y = 0;
CON_gotoxy(0,0);
}
void _PUBAPI CON_delline(void)
/****************************************************************************
*
* Function: CON_delline
*
* Description: Deletes the current line and moves all text below it up
* one line.
*
****************************************************************************/
{
int top;
syncCursor();
top = _win_top;
_win_top += _cnt_y;
CON_scroll(CON_SCROLL_UP,1);
_win_top = top;
}
void _PUBAPI CON_insline(void)
/****************************************************************************
*
* Function: CON_insline
*
* Description: Inserts a new lines at the current cursor position. Lines
* below the line are moved down, and the bottom line is
* lost.
*
****************************************************************************/
{
int top;
syncCursor();
top = _win_top;
_win_top += _cnt_y;
CON_scroll(CON_SCROLL_DOWN,1);
_win_top = top;
}
void _PUBAPI CON_write(int x,int y,int attr,char *str)
/****************************************************************************
*
* Function: CON_write
* Parameters: x,y - Position to write string at
* _attr - Attribute to write string in.
* str - String to output
*
* Description: Outputs a string to the video display. Formatting info
* is NOT handled. The string is clipped at the window
* boundary. This function is a LOT faster than CON_printf()
* and CON_puts() since formatting information is not handled.
* The cursor is not moved.
*
****************************************************************************/
{
int len;
if (y < 0 || y >= _win_height || x < 0)
return;
len = strlen(str);
if (x + len - 1 >= _win_width)
len = _win_width - x;
if (len <= 0)
return;
writeStr(x + _win_left,y + _win_top,attr,str,len);
}
void _PUBAPI CON_writec(int x,int y,int attr,int c)
/****************************************************************************
*
* Function: CON_writec
* Parameters: x,y - Postion to write character at
* _attr - Attribute to write character in
* c - Character to output
*
* Description: Displays a single character on the console. Formatting
* info is NOT handled, and the character is clipped at the
* window boundary.
*
****************************************************************************/
{
if (y < 0 || y >= _win_height || x < 0)
return;
if (x >= _win_width)
return;
writeChar(x + _win_left,y + _win_top,c,attr);
}
void _PUBAPI CON_moveText(int left,int top,int right,int bottom,int destleft,
int desttop)
/****************************************************************************
*
* Function: CON_moveText
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* destleft - Destination region left edge
* desttop - Destination region top edge
*
* Description: Moves a block of video memory to another location.
*
****************************************************************************/
{
moveText(_win_left + left,_win_top + top,_win_left + right,
_win_top + bottom,_win_left + destleft,_win_top + desttop);
}
void _PUBAPI CON_saveText(int left,int top,int right,int bottom,void *dest)
/****************************************************************************
*
* Function: CON_saveText
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* destin - Buffer to hold data
*
* Description: Moves a block of text from the video display to a buffer
* in RAM.
*
****************************************************************************/
{
moveFromScreen(_win_left + left,_win_top + top,_win_left + right,
_win_top + bottom,dest);
}
void _PUBAPI CON_restoreText(int left,int top,int right,int bottom,
void *source)
/****************************************************************************
*
* Function: CON_restoreText
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* source - Buffer holding data to use
*
* Description: Moves a block of text from a buffer in RAM to the video
* display.
*
****************************************************************************/
{
moveToScreen(_win_left + left,_win_top + top,_win_left + right,
_win_top + bottom,source);
}
void _PUBAPI CON_fillText(int left,int top,int right,int bottom,int attr,
int ch)
/****************************************************************************
*
* Function: CON_fillText
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* _attr - Attribute to fill with
* ch - Character to fill with
*
* Description: Fills a region of the screen with the specified character
* and attribute by calling the video BIOS.
*
****************************************************************************/
{
fillText(_win_left + left,_win_top + top,_win_left + right,
_win_top + bottom,attr,ch);
}
void _PUBAPI CON_fillAttr(int left,int top,int right,int bottom,int attr)
/****************************************************************************
*
* Function: CON_fillAttr
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
* _attr - Attribute to fill with
*
* Description: Changes the attribute value for a block of text on the
* screen.
*
****************************************************************************/
{
fillAttr(_win_left + left,_win_top + top,_win_left + right,
_win_top + bottom,attr);
}
void _PUBAPI CON_scroll(int direction,int amt)
/****************************************************************************
*
* Function: CON_scroll
* Parameters: direction - Direction to scroll area in
* amt - Amount to scroll area by
*
* Description: Scrolls the current window in the indicated direction by
* the indicated amount, filling in the exposed area with
* the current background character and attribute.
*
* NOTE: Scrolling with the video BIOS routines will scroll
* text in the current visual page, not the page output is
* being sent to, so should only be used to scroll areas of
* text currently visible.
*
****************************************************************************/
{
switch (direction) {
case CON_SCROLL_UP:
if (amt <= 0 || amt >= _win_height) {
CON_clrscr();
return;
}
moveText(_win_left,_win_top + amt,_win_right,
_win_bottom,_win_left,_win_top);
fillText(_win_left,_win_bottom - (amt-1),_win_right,
_win_bottom,_backAttr,_backChar);
break;
case CON_SCROLL_DOWN:
if (amt <= 0 || amt >= _win_height) {
CON_clrscr();
return;
}
moveText(_win_left,_win_top,_win_right,_win_bottom - amt,
_win_left,_win_top + amt);
fillText(_win_left,_win_top,_win_right,_win_top+(amt-1),
_backAttr,_backChar);
break;
case CON_SCROLL_RIGHT:
if (amt <= 0 || amt > _win_width) {
CON_clrscr();
return;
}
moveText(_win_left,_win_top,_win_right - amt,_win_bottom,
_win_left + amt,_win_top);
fillText(_win_left,_win_top,_win_left + (amt-1),_win_bottom,
_backAttr,_backChar);
break;
case CON_SCROLL_LEFT:
if (amt <= 0 || amt > _win_width) {
CON_clrscr();
return;
}
moveText(_win_left + amt,_win_top,_win_right,_win_bottom,
_win_left,_win_top);
fillText(_win_right-(amt-1),_win_top,_win_right,_win_bottom,
_backAttr,_backChar);
break;
}
}
void _PUBAPI CON_setWindow(int left,int top,int right,int bottom)
/****************************************************************************
*
* Function: CON_setWindow
* Parameters: left - Left edge of screen region
* top - Top edge of screen region
* right - Right edge of screen region
* bottom - Bottom edge of screen region
*
* Description: Sets the current window, and moves the cursor to the top
* left hand corner.
*
****************************************************************************/
{
_win_left = MAX(left,0);
_win_right = MIN(right,_screenWidth-1);
_win_top = MAX(top,0);
_win_bottom = MIN(bottom,_screenHeight-1);
_win_width = _win_right - _win_left + 1;
_win_height = _win_bottom - _win_top + 1;
CON_gotoxy(0,0);
}
void _PUBAPI CON_getWindow(int *left,int *top,int *right,int *bottom)
/****************************************************************************
*
* Function: CON_getWindow
* Parameters: left - Place to store left edge of screen region
* top - Place to store top edge of screen region
* right - Place to store right edge of screen region
* bottom - Place to store bottom edge of screen region
*
* Description: Returns the dimensions of the current window
*
****************************************************************************/
{
*left = _win_left;
*top = _win_top;
*right = _win_right;
*bottom = _win_bottom;
}
int _PUBAPI CON_maxx(void)
/****************************************************************************
*
* Function: CON_maxx
* Returns: Maximum x coordinate for current window
*
****************************************************************************/
{
return _win_width - 1;
}
int _PUBAPI CON_maxy(void)
/****************************************************************************
*
* Function: CON_maxy
* Returns: Maximum y coordinate for current window
*
****************************************************************************/
{
return _win_height - 1;
}
void _PUBAPI CON_setBackground(int attr,int ch)
/****************************************************************************
*
* Function: CON_setBackground
* Parameters: _attr - New background attribute
* ch - New background character
*
* Description: Sets the current background character and attribute.
*
****************************************************************************/
{
_backAttr = attr;
_backChar = ch;
}
void _PUBAPI CON_getBackground(int *attr,int *ch)
/****************************************************************************
*
* Function: CON_getBackground
* Parameters: _attr - Place to store background attribute
* ch - Place to store background character
*
* Description: Returns the current background character and attribute.
*
****************************************************************************/
{
*attr = _backAttr;
*ch = _backChar;
}
void _PUBAPI CON_setAttr(int attr)
/****************************************************************************
*
* Function: CON_setAttr
* Parameters: _attr - New foreground attribute
*
* Description: Sets the current foreground attribute.
*
****************************************************************************/
{
_attr = attr;
}
int _PUBAPI CON_getAttr(void)
{
return _attr;
}
void _PUBAPI CON_setBackColor(int newcolor)
/****************************************************************************
*
* Function: CON_setBackColor
* Parameters: newcolor - New background color
*
* Description: Sets the background color for the current foreground
* text attribute.
*
****************************************************************************/
{
_attr = _attr & 0x0F | ((newcolor & 0x0F) << 4);
}
void _PUBAPI CON_setForeColor(int newcolor)
/****************************************************************************
*
* Function: CON_setForeColor
* Parameters: newcolor - New foreground color
*
* Description: Sets the foreground color for the current foreground
* text attribute.
*
****************************************************************************/
{
_attr = _attr & 0xF0 | (newcolor & 0x0F);
}
void _PUBAPI CON_gotoxy(int x,int y)
/****************************************************************************
*
* Function: CON_gotoxy
* Parameters: x,y - New cursor position
*
* Description: Moves the cursor location to (x,y) by calling the BIOS. If
* the location lies outside of the current window, the
* cursor is hidden by moving it off the entire screen.
*
****************************************************************************/
{
PMREGS regs;
if (x >= _win_width || y >= _win_height) {
x = _screenWidth;
y = _screenHeight;
}
regs.h.dl = _win_left + x;
regs.h.dh = _win_top + y;
regs.h.bh = _activePage;
regs.h.ah = 0x02;
PM_int386(0x10,®s,®s);
_cnt_x = x;
_cnt_y = y;
}
int _PUBAPI CON_wherex(void)
/****************************************************************************
*
* Function: CON_wherex
* Returns: Current cursor x coordinate
*
****************************************************************************/
{
syncCursor();
return _cnt_x;
}
int _PUBAPI CON_wherey(void)
/****************************************************************************
*
* Function: CON_wherey
* Returns: Current cursor y coordinate
*
****************************************************************************/
{
syncCursor();
return _cnt_y;
}
int CON_screenWidth(void)
/****************************************************************************
*
* Function: CON_screenWidth
* Returns: Current full screen width
*
****************************************************************************/
{
return _screenWidth;
}
int CON_screenHeight(void)
/****************************************************************************
*
* Function: CON_screenHeight
* Returns: Current full screen height
*
****************************************************************************/
{
return _screenHeight;
}
void _PUBAPI CON_setCursor(int type)
/****************************************************************************
*
* Function: CON_setCursor
* Parameters: type
*
* Description: Sets the text mode cursor to type. Note that if the
* video mode is monochrome text mode, we correctly handle
* the case of an EGA adapter with a monochrome monitor
* running in 43 line mode.
*
****************************************************************************/
{
int scans;
switch (type) {
case CON_CURSOR_NORMAL:
if (CON_isMonoMode())
scans = 0x0B0C;
else scans = 0x0607;
break;
case CON_CURSOR_FULL:
if (CON_isMonoMode())
scans = 0x000E;
else scans = 0x0007;
break;
}
CON_restoreCursor(scans);
}
void _PUBAPI CON_cursorOff(void)
/****************************************************************************
*
* Function: CON_cursorOff
*
* Description: Hides the cursor.
*
****************************************************************************/
{
PMREGS regs;
regs.h.ah = 0x01;
regs.x.cx = 0x2000;
PM_int386(0x10,®s,®s);
}
void _PUBAPI CON_restoreCursor(int scans)
/****************************************************************************
*
* Function: CON_restoreCursor
* Parameters: scans - Cursor scan lines
*
* Description: Restores a previously saved cursor value.
*
****************************************************************************/
{
PMREGS regs;
regs.h.ah = 0x01;
regs.x.cx = scans;
PM_int386(0x10,®s,®s);
}
int _PUBAPI CON_getCursor(void)
/****************************************************************************
*
* Function: CON_getCursor
* Returns: Current cursor size
*
****************************************************************************/
{
PMREGS regs;
regs.h.ah = 0x03;
PM_int386(0x10,®s,®s);
return regs.x.cx;
}
void _PUBAPI CON_setActivePage(int page)
/****************************************************************************
*
* Function: CON_setActivePage
* Parameters: page - New page number to use
*
* Description: Sets the currently active video page. The active video page
* is the page all output is currently sent to, but it not
* necessarily visible. Note that only one page is available
* on monochrome systems.
*
****************************************************************************/
{
int offset;
PMREGS regs;
if (CON_isMonoMode())
return;
_activePage = page;
regs.h.ah = 0x05;
regs.h.al = page;
PM_int386(0x10,®s,®s);
offset = PM_getWord(_biosSel, 0x4E);/* Get offset into video buffer */
regs.h.ah = 0x05;
regs.h.al = _visualPage;
PM_int386(0x10,®s,®s);
_screenPtr = _screenPtrBase + offset;
_cnt_x = PM_getByte(_biosSel, 0x50 + page*2) - _win_left;
_cnt_y = PM_getByte(_biosSel, 0x51 + page*2) - _win_top;
}
int _PUBAPI CON_getActivePage(void)
/****************************************************************************
*
* Function: CON_getActivePage
* Returns: Currently active video page
*
****************************************************************************/
{
return _activePage;
}
void _PUBAPI CON_setVisualPage(int page)
/****************************************************************************
*
* Function: CON_setVisualPage
* Parameters: page - New page number to use
*
* Description: Sets the currently visible video page to 'page'. This page
* is the one containing currenlty visible data, but may not
* be the one currently active for writing. Note that only
* one page is available on monochrome systems.
*
****************************************************************************/
{
PMREGS regs;
if (CON_isMonoMode())
return;
_visualPage = page;
regs.h.ah = 0x05;
regs.h.al = page;
PM_int386(0x10,®s,®s);
}
int _PUBAPI CON_getVisualPage(void)
/****************************************************************************
*
* Function: CON_getVisualPage
* Returns: Currently visible video page.
*
****************************************************************************/
{
return _visualPage;
}
bool CON_isMonoMode(void)
{
return (PM_getByte(_biosSel, 0x49) == 0x7);
}