home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast2.iso
/
modem
/
cvt100.zip
/
VIDIO.C
< prev
next >
Wrap
Text File
|
1988-08-03
|
47KB
|
1,101 lines
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <alloc.h>
#define NORMAL 0x7 /* Normal video attribute */
#define BOLD 0x8 /* Bold video attribute */
#define UNDERLINED 0xA /* Underlined video attribute */
#define REVERSE 0x70 /* Reverse video attribute */
#define SCREEN 0x10 /* BIOS video interrupt number */
#define RETRACE 0x3da /* Video Retrace port address for CGA */
#define ASCII 0 /* ASCII character set */
#define UK 1 /* UK character set */
#define SPECIAL 2 /* Special character set, graphics chars */
/****************************************************************************/
/* Function prototypes */
void VidInit( void ); /* Initialize the video system */
void SetVattr( unsigned char ); /* Set the video attribute */
void AddVattr( unsigned char ); /* Add attribute to current video attribute*/
void SubVattr( unsigned char ); /* Sub attribute from current vid attribute*/
void BrkAtt( unsigned char ); /* Break attribute into extra and base */
unsigned char AddAtt( void ); /* Add extra and base attributes to get */
/* a resulting displayable video attribute*/
void ChrWrite( unsigned char ); /* Write character to the screen */
void SetScroll(int , int ); /* Set the scrolling region */
void ScrollDown( void ); /* Move down a row scrolling if necessary */
void ScrollUp( void ); /* Move up a row scrolling if necessary */
void IndexDown( void ); /* Scroll the screen down */
void IndexUp( void ); /* Scroll the screen up */
void SetCurs(int , int ); /* Set the cursor to absolute coordinates */
void SetRelCurs(int , int ); /* Set the cursor to relative coordinates */
void PosCurs( void ); /* Position the cursor to cursx,cursy */
void ModeLine( void ); /* Display the Mode line */
void ClearScreen( void ); /* Clear the terminal screen */
void ClearEOS( void ); /* Clear from cursor to end of screen */
void ClearBOS( void ); /* Clear from cursor to top of screen */
void ClearEOL( void ); /* Clear from cursor to end of line */
void ClearBOL( void ); /* Clear from cursor to start of line */
void ClearBox( unsigned char, /* Clear a box on the video screen */
unsigned char, unsigned char,
unsigned char, unsigned char);
void MarCharSet( int ); /* Map a character set */
void SetCharSet( int, unsigned char ); /* Set a character set */
void SaveCursor( void ); /* Save the cursor description */
void RestoreCursor( void ); /* Restore the cursor description */
void SetCursorVisibility( int ); /* Set the cursor visibility mode */
void SetBackGround( int ); /* Set background video attribute */
void SetColor( void ); /* Set the screen colors */
void InitTabs( void ); /* Initialize the tab settings */
void DoTab( void ); /* Perform a tab */
void SetTabStop( void ); /* Set a tab stop at cursor position */
void ClearTabStop( void ); /* Clear a tab stop at the cursor position*/
void ClearAllTabs( void ); /* Clear all the defined tab stops */
void SetScreenWidth( int ); /* Set the logical width of the screen */
void StartScreen( int, int ); /* Start a screen access */
void EndScreen( void ); /* End a screen access */
void WriteOneChar( unsigned char, /* Write one character to the screen */
int, int );
int VTprintf( int, int, int, /* Printf for Emulator to row and column */
char *, ... ); /* in regular or reverse video */
void SaveScreen( void ); /* Save contents of video memory */
void RestoreScreen( void ); /* Restore contents of video memory */
static void interrupt10( unsigned,/* Issue a BIOS video interrupt */
unsigned , unsigned , unsigned );
/****************************************************************************/
/* Global Data */
unsigned char retracemode = 0; /* Flag indicating No Video refresh wait */
unsigned char forecolor; /* Foreground color */
unsigned char backcolor; /* Background color */
unsigned char vidmode; /* Screen video mode */
/****************************************************************************/
/* External variables */
extern unsigned originmode; /* Origin mode, relative or absolute */
extern unsigned insertmode; /* Insert mode, off or on */
extern unsigned autowrap; /* Automatic wrap mode, off or on */
extern unsigned newline; /* Newline mode, off or on, GLOBAL data!*/
extern unsigned cursorvisible; /* Cursor visibility, on or hidden */
extern unsigned reversebackground;/* Reverse background attribute, on or off*/
extern unsigned screenwid; /* Absolute screen width */
extern char modeline[]; /* Text of mode line */
/***************************************************************************/
/* Local static data */
static unsigned char screentop; /* Absolute top of screen */
static unsigned char screenbot; /* Absolute bottom of screen */
static unsigned char scrolltop; /* Top row of scrolling region */
static unsigned char scrollbot; /* Bottom row of scrolling region */
static int cursx; /* X cursor position */
static int cursy; /* Y cursor position */
static unsigned scroff; /* Screen memory offset */
static unsigned scrseg; /* Screen memory segment */
static unsigned scrchars; /* Number of chars written to video memory */
static unsigned char tvmode; /* Flag to indicate control program present*/
char far *screen; /* Pointer to video screen */
static unsigned savebp; /* Static storage for BP through int 0x10 */
static unsigned char video_state; /* State of video, reversed or normal */
static unsigned char scbattr; /* Video attribute of empty video cell */
static unsigned char curattr; /* Video attribute of displayable chars */
static unsigned char baseattr; /* Base attribute for video attributes */
static unsigned char extrattr; /* Extra attribute for video attributes */
static unsigned char att_reverse; /* Reverse attribute bits */
static unsigned char att_normal; /* Normal attribute bits */
static unsigned char att_low_mask = 0x6; /* Low attribute mask */
static unsigned char att_underline = 0x1; /* Underlined attribute bit */
static unsigned char att_intensity = 0x8; /* Bold attribute bit */
static unsigned char att_blink = 0x80; /* Blinking attribute bit */
static unsigned columns; /* Columns on logical terminal screen */
static unsigned lines; /* Lines on logical terminal screen */
static char tabs[132]; /* active tab stops */
static char deftabs[132]; /* default tab stops, 9,17,26 .... */
static int G0 = ASCII; /* Character set G0 */
static int G1 = ASCII; /* Character set G1 */
static int *GL = &G0; /* Pointer to current mapped character set*/
static char special_chars[32] = { /* Special characters */
32,4,176,9,12,13,10,248,241,18,11,217,191,218,192,197,
196,196,196,196,196,195,180,193,194,179,243,242,227,216,156,7
} ;
static struct SaveCursorStruct { /* Structure to save cursor description */
int cursx; /* X cursor position, column */
int cursy; /* Y cursor position, row */
int *GL; /* pointer to mapped character set */
int G0; /* character set G0 */
int G1; /* character set G1 */
int mode; /* origin mode */
} save = { 1, 1, &G0, ASCII, ASCII , 0 } ;
/* Pointer to memory allocated to hold */
static char far *screen_save = NULL; /* the contents of video memory */
/****************************************************************************/
/****************************************************************************/
/* V I D I N I T -- Initialize the video system */
void VidInit( ) {
char far *bptr;
/* Obtain video information from BIOS */
_AH = 0x0F; /* Use function F of interrupt 10 */
savebp = _BP; /* Precautionary save of register BP */
geninterrupt( 0x10 ); /* Issue BIOS video interrupt */
_BP = savebp; /* Restore saved BP register */
vidmode = _AL; /* Save the video mode */
columns = _AH; /* Save the number of columns */
lines = 25; /* Lines = 25, (sorry no 43,50 lines */
screenbot = lines - 1; /* Bottom of screen is 24 */
screentop = 1; /* Top of screen is line 1 */
tvmode = 0; /* Assume no control program present */
if (GetVidSetup() == 0) { /* If no video parameters are saved */
/* then determine default values */
/* First determine if snow is a problem */
if (vidmode != 7) /* Assume video adapter is snowy if */
retracemode = 1; /* it is not a MonoChrome */
/* First query Video BIOS to see if */
_AX = 0x1A00; /* VGA is present, no "snow" problem on VGA*/
savebp = _BP; /* Precautionary save of register BP */
geninterrupt( 0x10 ); /* Issue BIOS video interrupt */
_BP = savebp; /* Restore saved BP register */
if (_AL == 0x1A) /* If VGA is detected */
retracemode = 0; /* No snow protection needed */
else { /* Else look for an EGA */
_CL = 0xC; /* Test the Video BIOS to see if */
_BX = 0xFF10; /* an EGA can be detected */
_AX = 0x1200; /* EGA's don't have "snow" problem either*/
savebp = _BP; /* Precautionary save of register BP */
geninterrupt( 0x10 ); /* Issue BIOS video interrupt */
_BP = savebp; /* Restore saved BP register */
if (_CL < 0xC) { /* If EGA is detected */
bptr = MK_FP(0x40,0x87);/* Check BIOS data to see if the */
if ( (*bptr & 0x8) == 0)/* EGA is the active adapter */
retracemode = 0; /* No snow protection required */
}
}
/* Determine the default screen attributes*/
_AH = 0x8; /* Issue function 8 or interrupt 10 */
_BH = 0x0; /* for page 0 */
savebp = _BP; /* Precautionary save of register BP */
geninterrupt( 0x10 ); /* Get video attribute at cursor pos */
_BP = savebp; /* Restore saved BP register */
scbattr = _AH; /* Save this attribute */
forecolor = scbattr & 0xf;/* Save values for determined colors */
backcolor = scbattr >> 4;
}
else { /* If saved values were available */
/* Set the screen color to saved value */
scbattr = ( backcolor << 4 ) | forecolor;
if (vidmode == 7) /* Do not let retracemode be set on */
retracemode = 0; /* if video is a MonoChrome */
}
att_normal = scbattr;
BrkAtt(scbattr); /* Break the attribute into base,extra */
/* Reverse the foreground and background*/
baseattr = ( baseattr >> 4 | baseattr << 4);
att_reverse = AddAtt(); /* Put the attributes back together */
/* in order to get reverse attribute */
/* Clear screen to established attribute*/
interrupt10( 0x0600,scbattr << 8,
0 ,(lines << 8) | (columns - 1 ));
/* Clear the top line setting it to reverse*/
interrupt10( 0x0600,att_reverse << 8 ,0,columns - 1);
vtprintf(0,0,1,modeline); /* Display the mode line in reverse */
if (screen_save == NULL) { /* If first time to be initialized */
/* Attempt to allocate screen mem */
if ( (screen_save = farmalloc( lines * columns * 2 )) == NULL)
badexit("No memory available for video screen save buffer");
}
}
/* S E T V A T T R -- Set the video attribute */
void SetVattr(unsigned char attr) {
video_state = 0; /* Reset the video state */
BrkAtt(scbattr); /* Break apart the default screen attribute*/
switch (attr) { /* See what video attribute is requested */
case BLINK: /* Blinking characters */
extrattr = att_blink;
break;
case REVERSE: /* Reversed video characters */
video_state = 1;
baseattr = ( baseattr >> 4 | baseattr << 4);
break;
case UNDERLINED: /* Underlined characters */
if (vidmode == 0x7) /* Monochrome can underline */
extrattr = att_underline;
else { /* others can't use reverse video */
video_state = 1;
baseattr = ( baseattr >> 4 | baseattr << 4);
}
break;
case BOLD: /* High intensity, bold, characters */
extrattr = att_intensity;
break;
case NORMAL: /* Normal characters */
default:
extrattr = 0;
break;
}
curattr = AddAtt(); /* Put the video attributes back together */
}
/* A D D V A T T R -- Add an attribute bit to the current video attribute */
void AddVattr(unsigned char attr) {
BrkAtt(curattr); /* Break apart the current video attribute*/
switch (attr) { /* See what attribute wants to be added */
case BLINK: /* Blinking attribute */
extrattr |= att_blink;
break;
case BOLD: /* High intensity, bold, attribute */
extrattr |= att_intensity;
break;
case REVERSE: /* Reversed attribute */
if (video_state == 0) {
video_state = 1;
baseattr = ( baseattr >> 4 | baseattr << 4);
}
break;
case UNDERLINED: /* Underlined characters */
if (vidmode == 0x7) /* Monochrom can underline */
extrattr = att_underline;
/* others cant use reversed video */
else if (video_state == 0) {
video_state = 1;
baseattr = ( baseattr >> 4 | baseattr << 4);
}
break;
default:
break;
}
curattr = AddAtt(); /* Put the video attributes back together */
}
/* S U B V A T T R -- Remove attribute bit to the current video attribute */
void SubVattr(unsigned char attr) {
BrkAtt(curattr); /* Break apart the current video attribute*/
switch (attr) { /* See what video attribute to remove */
case BLINK: /* Remove the blinking attribute */
extrattr &= ~att_blink;
break;
case BOLD: /* Remove the high intensity, bold */
extrattr &= ~att_intensity;
break;
case REVERSE: /* Remove reversed attribute */
if (video_state == 1) {
video_state = 0;
baseattr = ( baseattr >> 4 | baseattr << 4);
}
break;
case UNDERLINED: /* Remove underlined attribute */
if (vidmode == 0x7) /* Monochrome could have underlined */
extrattr &= ~att_underline;
/* others couldn't remove reverse attribute*/
else if (video_state == 1) {
video_state = 0;
baseattr = ( baseattr >> 4 | baseattr << 4);
}
break;
default:
break;
}
curattr = AddAtt(); /* Put the video attributes back together */
}
/* B R K A T T R -- Break an attribute into its video components */
void BrkAtt(unsigned char attribute) {
extrattr = 0; /* Clear extra attributes */
baseattr = attribute; /* Start specified base attribute */
if (vidmode == 0x7) { /* If a Monochrome monitor */
if (attribute & att_low_mask){ /* Any Low mask attributes on? */
baseattr |= att_normal; /* if yes then set normal bits on */
}
else { /* else check other attributes */
if (attribute & att_underline){ /* Underline attribute ? */
extrattr |= att_underline; /* yes then set underline bit */
if (attribute & 0x70) /* Reverse video ? */
baseattr &= ~att_underline; /* If yes then clear underline */
else /* monochrome can't do both */
baseattr |= att_normal; /* Else set normal bits on */
}
}
}
if (baseattr & att_intensity) /* If bold attribute is on */
extrattr |= att_intensity; /* then set intensity bit */
if (baseattr & att_blink) /* If blink attribute is on */
extrattr |= att_blink; /* then set blink bit */
/* Turn off blink,bold in base attribute */
baseattr &= ~(att_intensity + att_blink);
}
/* A D D A T R -- Build video attribute from base and extra attributes */
unsigned char AddAtt() {
if (extrattr & att_underline) /* If underline is requested */
baseattr &= ~att_low_mask; /* Clear low mask */
return(baseattr | extrattr); /* return the or'ed attributes */
}
/* C H R W R I T E -- Write a character to a row and column of the screen */
void ChrWrite( unsigned char chr ) {
unsigned char c[2], attr[2];
int row, ws;
if (*GL == ASCII) /* Check character set being used */
; /* if regular ASCII then char is OK */
else if (*GL == SPECIAL) { /* if using the special character */
if (chr > 94 && chr < 128) /* then translate graphics characters */
chr = special_chars[ chr - 95];
}
else if (*GL == UK) { /* If using the UK character set */
if (chr == '#') /* then watch for the number sign */
chr = '£'; /* translating it to British pound */
}
/* NOTE: Inserting a character using this technique is *very* slow */
/* for snowy CGA systems */
if (insertmode) { /* If insert mode, scoot rest of line over */
StartScreen(cursy,cursx-1);/* Start direct video memory access */
c[0] = *screen; /* Save character at current position */
attr[0] = *(screen + 1); /* Save attribute at current position */
ws = 1;
for (row = cursx; row < columns; row ++) {
c[ws] = *(screen + 2); /* Save character at next position */
attr[ws] = *(screen + 3); /* Save attribute at next position */
ws ^= 1; /* Flop save char,attribute array index */
*(screen + 2) = c[ws]; /* Write saved character and attribute */
*(screen + 3) = attr[ws];
screen += 2; /* Increment to next character position */
scrchars++; /* Increment the number of chars written */
}
EndScreen(); /* Update screen in control programs */
}
if (cursx > screenwid) { /* If trying to go beyond the screen width */
if (autowrap) { /* when autowrap is on */
ScrollUp(); /* scroll the screen up */
SetCurs(1,0); /* set cursor to column 1 of next line */
}
else
cursx = screenwid; /* else put the cursor on right margin */
}
WriteOneChar(chr, cursy, cursx - 1);
++cursx; /* Increment the cursor X position */
PosCurs(); /* Move the cursor to the new position */
}
/* S E T S C R O L L -- Establish the scrolling boundaries */
void SetScroll( register int top, register int bottom) {
if (top == 0) /* If the top scroll boundary is 0 */
top = 1; /* interpret this as the top screen row */
if (bottom == 0) /* If the bottom scroll boundary is 0 */
bottom = screenbot; /* interpret this as bottom screen row */
/* Set scrolling region if valid coords */
if (top > 0 && top <= screenbot && bottom >= top && bottom <= screenbot){
scrolltop = top; /* save top boundary */
scrollbot = bottom; /* save bottom boundary */
SetCurs(1,1); /* this also homes the cursor */
}
}
/* S C R O L L D O W N -- Move up a row scrolling if necessary */
void ScrollDown( )
{
if (cursy == scrolltop) /* If on the top of the scrolling region */
IndexDown(); /* scroll the rest of the region down */
else { /* Else */
--cursy; /* just decrement cursor Y position */
PosCurs(); /* and request the reposition */
}
}
/* S C R O L L U P -- Move down a row scrolling if necessary */
void ScrollUp( )
{
if (cursy == scrollbot) /* If on the bottom of the scrolling region*/
IndexUp(); /* scroll the rest of the region down */
else { /* Else */
++cursy; /* just increment the cursor Y position */
PosCurs(); /* and request the reposition */
}
}
/* I N D E X D O W N -- Scroll the screen down */
void IndexDown( )
{
register unsigned attr;
attr = scbattr << 8; /* Get the attribute for new line */
/* Call the BIOS to scroll the region */
interrupt10( 0x0701,attr,scrolltop << 8,(scrollbot << 8) | (columns - 1) );
PosCurs(); /* Position the cursor */
}
/* I N D E X U P -- Scroll the screen up */
void IndexUp( )
{
register unsigned attr;
attr = scbattr << 8; /* Get the attribute for new line */
/* Call the BIOS to scroll the region */
interrupt10( 0x0601,attr,scrolltop << 8,(scrollbot << 8) | (columns - 1));
PosCurs(); /* Position the cursor */
}
/* S E T C U R S -- Set absolute cursor position on the logical screen */
void SetCurs(register int col, register int row)
{
if (col == 0) /* If called with X coordinate = zero */
col = cursx; /* then default to current coordinate */
if (row == 0) /* If called with Y coordinate = zero */
row = cursy; /* then default to current coordinate */
if (originmode) { /* If origin mode is relative */
row += (scrolltop - 1); /* adjust the row */
if (row < scrolltop || row > scrollbot)
return; /* Can not position cursor out of scroll */
/* region in relative cursor mode */
}
/* Can only position the cursor if it lies */
/* within the logical screen limits */
if (col <= screenwid && row <= screenbot ) {
cursx = col; /* Set the X cursor coordinate, column */
cursy = row; /* Set the Y cursor coordinate, row */
PosCurs(); /* Request the physical positioning */
}
}
/* S E T R E L C U R S -- Set relative curs pos on the logical screen */
void SetRelCurs(register int col, register int row)
{
if (col == 0) /* If called with X coordinate = zero */
col = cursx; /* then default to current X coordinate */
else /* Else */
col = cursx + col; /* add col value to X cursor position */
/* Note: col can be negative */
if (row == 0) /* If called with Y coordinate = zero */
row = cursy; /* then default to current Y coordinate */
else /* Else */
row = cursy + row; /* add row value to Y cursor position */
/* Note: row can be negative */
if (originmode) { /* If origin mode is relative */
row += (scrolltop - 1); /* adjust the row */
if (row < scrolltop || row > scrollbot)
return; /* Can not position cursor out of scroll */
} /* region in relative cursor mode */
/* Can only position the cursor if it lies */
/* within the logical screen limits */
if (col > 0 && col <= screenwid && row > 0 && row <= screenbot){
cursy = row; /* Set the X cursor coordinate, column */
cursx = col; /* Set the Y cursor coordinate, row */
PosCurs(); /* Request the physical positioning */
}
}
/* P O S C U R S -- Position the cursor on the physical screen */
void PosCurs()
{
register int col = cursx;
register int row = cursy;
if (col <= columns) /* Check validity of requested column */
; /* ok if column is within screen bounds */
else
col = columns; /* else put cursor on the right bound */
if (row <= lines) /* Check validity of requested row */
; /* ok if row is within screen bounds */
else
row = lines; /* else put cursor on the bottom */
if (cursorvisible) /* Only position the cursor if its visible */
interrupt10(0x0200,0,0,(row << 8) | --col );
}
/* C L E A R S C R E E N -- Clear the screen setting it to a normal attr */
void ClearScreen()
{
ClearBox(1, screentop, columns, screenbot, scbattr);
}
/* C L E A R E O S -- Clear from the cursor to the end of screen */
void ClearEOS()
{
ClearEOL(); /* First clear to the End of the Line */
if (cursy < screenbot) /* Then clear every line below it */
clearbox(1,cursy + 1,columns, screenbot, scbattr);
}
/* C L E A R B O S -- Clear from the cursor to the beggining of screen */
void ClearBOS()
{
ClearBOL(); /* First clear to the Beginning of the Line */
if (cursy > screentop) /* Then clear every line above it */
ClearBox(1,screentop,columns, cursy - 1, scbattr);
}
/* C L E A R E O L -- Clear to the end of the current line */
void ClearEOL()
{
ClearBox(cursx, cursy, columns, cursy, scbattr );
}
/* C L E A R B O L -- Clear to the beginning of the current line */
void ClearBOL()
{
ClearBOX(1, cursy, cursx, cursy, scbattr );
}
/* C L E A R B O X -- Clear a window on the screen with the specified attr */
void ClearBox( unsigned char left, unsigned char top,
unsigned char right, unsigned char bottom, unsigned char attr )
{
/* Use BIOS scroll window function to clear*/
interrupt10( 0x0600,attr << 8, /* a window to a specified attribute */
(top << 8) | (--left),(bottom << 8) | --right);
}
/* M A P C H A R S E T -- Map an established character set to current */
void MapCharSet( int charset ) {
if (charset == 0) /* If mapping G0 character set */
GL = &G0; /* Point the current char set,GL to G0 */
else if (charset == 1) /* If mapping G1 character set */
GL = &G1; /* Point the current char set,GL, to G1 */
}
/* S E T C H A R S E T -- Establish a character set */
void SetCharSet( int gset, unsigned char set) {
int *charset;
if (gset == 0) /* Check to see what character set is */
charset = &G0; /* going to be set */
else if (gset == 1)
charset = &G1;
else
return; /* If not valid set then return */
switch(set) {
case 'B': /* 'B' maps the character set to ASCII */
*charset = ASCII; /* this is the normal character set */
break;
case 'A': /* 'A' maps the character set to UK */
*charset = UK; /* only difference between UK and ASCII */
break; /* is the pound sign, # = £ */
case '0': /* '0' maps the character set to SPECIAL */
*charset = SPECIAL; /* this character set is the 'graphics' */
break; /* character set used for line drawing */
default:
}
}
/* S A V E C U R S O R -- Save the cursor description into memory */
void SaveCursor() {
save.cursx = cursx; /* Save the X cursor position */
save.cursy = cursy; /* Save the Y cursor position */
save.GL = GL; /* Save the current mapped character set */
save.G0 = G0; /* Save G0 character set */
save.G1 = G1; /* Save G1 character set */
save.mode = originmode; /* Also save the origin mode */
}
/* R E S T O R E C U R S O R -- Restore the cursor description from memory */
void RestoreCursor() {
cursx = save.cursx; /* Restore the saved X cursor position */
cursy = save.cursy; /* Restore the saved Y cursor position */
GL = save.GL; /* Restore the saved mapped character set */
G0 = save.G0; /* Restore the saved G0 character set */
G1 = save.G1; /* Restore the saved G1 character set */
originmode = save.mode; /* Also restore the saved origin mode */
PosCurs(); /* Then reposition the cursor */
}
/* S E T C U R S O R V I S I B I L I T Y -- Show/Hide the cursor */
void SetCursorVisibility( int mode ) {
if (mode) { /* If invisible cursor is specified, then */
cursorvisible = 1; /* the cursor will not appear on the */
SetCurs(0,0); /* terminal screen */
}
else { /* Else the cursor will be shown at the */
cursorvisible = 0; /* current cursor position */
interrupt10(0x0200,0,0,lines << 8 );
}
}
/* S E T B A C K G R O U N D -- Set the background attribute */
void SetBackGround( int mode ) {
int reverse_screen = 0; /* Flag to indicate screen is to be reversed*/
register int i;
if (mode) { /* If reversed background is specified, */
if (reversebackground != 1) { /* only reverse the screen if it is */
reverse_screen = 1; /* not already set to reverse */
reversebackground = 1;
}
}
else { /* Else if normal background is specified */
if (reversebackground != 0) { /* only reverse the screen if it is */
reverse_screen = 1; /* currently set to reverse */
reversebackground = 0;
}
}
if (reverse_screen) { /* If reverse screen flag is set */
/* first save the contents of screen */
StartScreen(0,0);
for (i = 0; i < lines * columns; i++){
screen++;
BrkAtt(*screen); /* Break attribute apart and reverse it */
baseattr = ( baseattr >> 4 | baseattr << 4);
*screen++ = AddAtt(); /* Put attribute together as displayable */
}
scrchars = i;
EndScreen();
BrkAtt(scbattr); /* reverse the default character attr */
baseattr = ( baseattr >> 4 | baseattr << 4);
scbattr = AddAtt();
BrkAtt(curattr); /* reverse the current character attr */
baseattr = ( baseattr >> 4 | baseattr << 4);
curattr = AddAtt();
}
}
/* S E T C O L O R -- Set the screen color */
void SetColor() {
register int i;
unsigned char attr;
BrkAtt(att_normal); /* Break apart the current screen color */
attr = baseattr; /* Save this attribute */
/* Create the new screen attribute */
att_normal = curattr = scbattr = ( (backcolor << 4) | forecolor);
BrkAtt(att_normal); /* and the new reverse attribute */
baseattr = ( baseattr >> 4 | baseattr << 4);
att_reverse = AddAtt();
StartScreen(0,0);
for (i = 0; i < lines * columns; i++){
screen++;
BrkAtt(*screen); /* Break attribute apart and reverse it */
if (baseattr == attr) { /* If this chars base attributes are the */
baseattr = att_normal; /* old screen color then this is a normal */
} /* character so set it to new normal attr */
else /* Else set this character to new reverse */
baseattr = att_reverse;
*screen++ = AddAtt(); /* Put attribute together as displayable */
}
scrchars = i;
EndScreen();
}
/* I N I T T A B S -- Initialize Tab stops to default settings */
void InitTabs() {
register int i;
for( i = 1; i < 131; i++) { /* Set tabs for mod 8 = 0 positions */
if ( i % 8 ) /* 9, 17, 26 .... */
deftabs[i+1] = tabs[i+1] = 0; /* Zero indicates no tab here */
else
deftabs[i+1] = tabs[i+1] = 1; /* One indicates a tab stop */
}
}
/* D O T A B -- Perform a tab */
void DoTab() {
register int i;
/* Look for next tab stop */
for (i = cursx + 1; i <= screenwid; i++) {
if ( tabs[i] == 1 ) { /* If a tab stop is found */
SetCurs(i,cursy); /* request cursor position here */
return; /* and finished */
}
}
}
/* S E T T A B S T O P -- set a tab stop at the current cursor position */
void SetTabStop() {
tabs[cursx] = 1; /* Mark current cursor position as tab stop*/
}
/* C L E A R T A B S T O P -- clear a tab stop at the current curs position */
void ClearTabStop() {
tabs[cursx] = 0; /* Clear current cursor position tab stop */
}
/* C L E A R A L L T A B S -- clear all tab stops */
void ClearAllTabs() {
/* Clear all of the tab stop marks */
memset(tabs,'\0',sizeof(tabs));
}
/* S E T S C R E E N W I D T H -- set the screen width */
void SetScreenWidth(int width) {
if (width == 132) /* When the screen is set to 132 columns */
screenwid = 132; /* set the logical right boundary */
else if (width == 80) /* Else if the screen width is 80 */
screenwid = 80; /* set the logical right boundary */
/* Setting the screen width also */
ClearScreen(); /* Clears the screen */
originmode = 0; /* Sets the origin mode to absolute */
SetScroll(0,0); /* Resets the scrolling region */
SetCurs(1,1); /* Sets the cursor to the home position */
}
/* S T A R T S C R E E N -- Start a direct screen addressing "transaction" */
void StartScreen( register int row, register int col ) {
unsigned vscroff, vscrseg;
if ( vidmode == 7 ) { /* If in Monochrome video mode */
scrseg = 0xb000; /* Assume video segment of B000 */
}
else { /* If other mode then assumme */
scrseg = 0xb800; /* video memory segment is B800 */
}
scroff =((row*columns)+col)*2;/* Calculate offset from beginning of */
/* screen memory */
scrchars = 0; /* Initialize count of characters written */
savebp = _BP; /* Save reg BP, in case old BIOS trashes it */
/* Query the address of video memory for */
_ES = scrseg; /* this process under Windows, DesQview, ... */
_DI = 0; /* ES:DI = assumed screen address */
_AH = 0xFE; /* Issue Video interrupt function FE */
geninterrupt(0x10); /* in order to check for control program */
vscroff = _DI; /* ES:DI now holds actual address of screen*/
vscrseg = _ES;
_BP = savebp; /* Restore register BP */
tvmode = 0; /* Assume no control program */
if (vscroff != 0 || vscrseg != scrseg) {
scrseg = vscrseg; /* If address of screen is different from*/
scroff += vscroff; /* assumed address then a control program*/
tvmode = 1; /* is present and has remapped the screen*/
}
else if (retracemode == 0)
; /* No refresh wait for these situations */
else {
/* Wait till screen is refreshing */
while( (inportb(RETRACE) & 0x8) != 0 )
; /* Wait till refresh is through */
while( (inportb(RETRACE) & 0x8) == 0 )
;
outportb(0x3d8,0x25); /* Turn off the screen refresh */
}
/* Construct a far pointer to video memory*/
(void far *)screen = MK_FP(scrseg,scroff);
}
/* E N D S C R E E N -- End a direct screen addressing "transaction" */
void EndScreen( ) {
/* Values to turn the screen back on */
static unsigned char modeset[] = /* after video refresh is turned off */
{ 0x2C,0x28,0x2D,0x29,0x2A,0x2E,0x1E,0x29,
} ;
/* If control program video update required*/
if (tvmode == 1 && scrchars > 0) {
_ES = scrseg; /* Point ES:DI to beginning of video memory*/
_DI = scroff; /* to update */
_CX = scrchars; /* CX holds the number of chars to update */
_AH = 0xFF; /* Use function FF of BIOS video interrupt */
geninterrupt(0x10); /* to copy video buffer to screen */
}
else if (retracemode == 0)
; /* Situations screen was not turned off */
else { /* Else if screen is off turn it back on */
outportb(0x3d8, modeset[vidmode]);
}
}
/* W R I T E O N E C H A R -- writes on character to video memory */
/* NOTE: this function does not shut down video refresh in order */
/* to avoid snow on CGA, so it is *much* faster than using StartScreen */
/* and an EndScreen transaction for one character screen writes. */
void WriteOneChar(unsigned char c, register int row, register int col ) {
unsigned vscroff, vscrseg;
int retrace_wait = 0;
if ( vidmode == 7 ) { /* If in Monochrome video mode */
scrseg = 0xb000; /* Assume video segment of B000 */
}
else { /* If other mode then assumme */
scrseg = 0xb800; /* video memory segment is B800 */
}
scroff =((row*columns)+col)*2;/* Calculate offset from beginning of */
/* screen memory */
savebp = _BP; /* Save reg BP, in case old BIOS trashes it */
/* Query the address of video memory for */
_ES = scrseg; /* this process under Windows, DesQview, ... */
_DI = 0; /* ES:DI = assumed screen address */
_AH = 0xFE; /* Issue Video interrupt function FE */
geninterrupt(0x10); /* in order to check for control program */
vscroff = _DI; /* ES:DI now holds actual address of screen*/
vscrseg = _ES;
_BP = savebp; /* Restore register BP */
tvmode = 0; /* Assume no control program */
if (vscroff != 0 || vscrseg != scrseg) {
scrseg = vscrseg; /* If address of screen is different from*/
scroff += vscroff; /* assumed address then a control program*/
tvmode = 1; /* is present and has remapped the screen*/
}
else if (retracemode == 0)
; /* No refresh wait for these situations */
else {
retrace_wait = 1; /* Else assume snowy CGA */
}
/* Construct a far pointer to video memory*/
(void far *)screen = MK_FP(scrseg,scroff);
if ( retrace_wait == 0 ) { /* If no snow then */
*screen++ = c; /* write character into screen memory */
*screen = curattr; /* write attribute into screen memory */
}
else { /* Else if snowy CGA then try and sneak */
if (inportb(RETRACE) & 0x8) { /* the character and attribute into */
*screen++ = c; /* video memory in between video */
*screen = curattr; /* refreshes */
}
else {
while (inportb(RETRACE) & 0x8)
;
while (inportb(RETRACE) & 0x1)
;
*screen++ = c;
*screen = curattr;
}
}
if (tvmode == 1) { /* If control program video update required*/
_ES = scrseg; /* Point ES:DI to beginning of video memory*/
_DI = scroff; /* to update */
_CX = 1; /* CX holds the number of chars to update */
_AH = 0xFF; /* Use function FF of BIOS video interrupt */
geninterrupt(0x10); /* to copy video buffer to screen */
}
}
/* S A V E S C R E E N -- Save the contents of the video screen */
void SaveScreen() {
StartScreen(0,0); /* Start the video direct access */
movedata(scrseg, scroff, /* Move the video memory to save buffer */
FP_SEG(screen_save), FP_OFF(screen_save),
lines * columns * 2 );
scrchars = 0; /* Zero characters were written to screen */
EndScreen(); /* End the screen access */
interrupt10(0x0200,0,0,lines << 8 ); /* Hide the cursor */
}
/* R E S T O R E S C R E E N -- Restore contents of the video screen */
void RestoreScreen() {
StartScreen(0,0); /* Start the video direct access */
/* Move the save buffer to video memory */
movedata(FP_SEG(screen_save), FP_OFF(screen_save),
scrseg, scroff,
lines * columns * 2 );
scrchars = lines * columns; /* Number of chars written to screen */
EndScreen(); /* End the screen access */
PosCurs(); /* Reposition the cursor */
}
/* V T P R I N T F -- print a formatted string to the video screen */
int vtprintf( int row, int col, int reverse, char *strformat, ... )
{
unsigned attr;
va_list argptr;
char str[132];
char *sptr = str;
int it;
if (reverse) { /* If reversed attribute specified */
attr = att_reverse;
}
else { /* Else use normal attribute */
attr = att_normal;
}
va_start( argptr, format ); /* Start variable length argument list */
StartScreen(row,col); /* Start a screen update */
scrchars = vsprintf( str, strformat, argptr ); /* Format the string */
while (*sptr != '\0') { /* Move the formatted string */
*screen++ = *sptr++; /* to video memory */
*screen++ = attr;
}
EndScreen(); /* End the screen update */
va_end(argptr); /* End the va_start */
return(scrchars); /* Return number of characters written */
}
/* I N T E R R U P T 1 0 -- Call on the BIOS video software interrupt */
void interrupt10(unsigned ax,unsigned bx,unsigned cx,unsigned dx){
register unsigned savesi; /* Force compiler to save contents of */
register unsigned savedi; /* SI and DI registers on the stack */
static unsigned savebp;
savebp = _BP; /* Save BP since some BIOS'es may destroy it*/
_CX = cx; /* Load contents of register parameters */
_DX = dx;
_BX = bx;
_AX = ax;
geninterrupt(0x10); /* Issue Video interrupt */
_BP = savebp; /* Restore BP register */
}