Category : C Source Code
Archive   : WIN.ZIP
Filename : SCRIO.C

 
Output of file : SCRIO.C contained in archive : WIN.ZIP


/***************************************************************************/
/* SCRIO - Routines which directly access the video screen */
/* */
/* */
/* */
/***************************************************************************/
/* Modification Log */
/***************************************************************************/
/* Version Date Programmer ----------- Description --------------- */
/* */
/* V01.00 112787 Bob Withers Program intially complete. */
/* */
/* */
/***************************************************************************/

#include
#include
#include
#include
#include "win.h"

#define MAXDIM(array) (sizeof(array) / sizeof(array[0]))

#define SCR_BYTES_PER_ROW 160
#define CGA_MODE_SEL 0x3d8
#define CGA_ENABLE 0x29
#define CGA_DISABLE 0x21

#define BIOS_VID_INT 0x10
#define BIOS_VID_SET_CRTMODE 0
#define BIOS_VID_SET_CURSORTYPE 1
#define BIOS_VID_SET_CURSORPOS 2
#define BIOS_VID_GET_CURSORPOS 3
#define BIOS_VID_SCROLL_UP 6
#define BIOS_VID_SCROLL_DOWN 7
#define BIOS_VID_WRITE_CHATTR 9
#define BIOS_VID_GET_CRTMODE 15


struct sBoxType
{
BYTE cUpperLeft;
BYTE cLowerLeft;
BYTE cUpperRight;
BYTE cLowerRight;
BYTE cLeft;
BYTE cRight;
BYTE cTop;
BYTE cBottom;
};
typedef struct sBoxType BOXTYPE;


unsigned uScrSeg = 0xb800;
unsigned uCsrType = 0x0107;
short nCurrActivePage = 0;
short nVideoCard = VIDEO_CGA;
short nScrCols = 80;


/***************************************************************************/
/* ScrCvtAttr - Test for a monochrome video card and convert the */
/* requested attribute to black & white as best we can */
/* and still honor the callers request. */
/* Parms: */
/* nAttr - The passed color attribute. */
/* */
/* Return Value: A converted black & white attribute if the current */
/* video mode is monochrome. */
/***************************************************************************/

static short near pascal ScrCvtAttr(nAttr)
register short nAttr;
{
short nRev, nClr, nBlink, nIntensity;

if (VIDEO_MONO != nVideoCard)
return(nAttr);
nIntensity = nAttr & 0x40;
nBlink = nAttr & 0x80;
nRev = nAttr & 0x70;
nClr = nAttr & 0x07;
if (REV_BLACK == nRev)
nClr = WHITE;
else
{
nRev = REV_WHITE;
nClr = BLACK;
}
return(nRev | nClr | nBlink | nIntensity);
}


/***************************************************************************/
/* ScrEnableVideoCGA - Test the current video equipment for a snowy CGA */
/* card. If running on a CGA enable/disable the */
/* video signal based on the passed parameter which */
/* MUST be one of the predefined constants CGA_ENABLE */
/* or CGA_DISABLE. If the current video equipment is */
/* not a CGA, the routine returns without taking any */
/* action. */
/* Parms: */
/* nStatus - Enable or disable the CGA video signal */
/* CGA_ENABLE or CGA_DISABLE */
/* */
/* Return Value: None */
/***************************************************************************/

static void pascal ScrEnableVideoCGA(nStatus)
short nStatus;
{
if (VIDEO_CGA == nVideoCard)
outp(CGA_MODE_SEL, nStatus);
return;
}


/***************************************************************************/
/* ScrGetRectSize - This routine will calculate and return the number of */
/* bytes required to store a screen image which is nWidth*/
/* columns by nHeight rows. */
/* Parms: */
/* nWidth - Column width of the screen rectangle */
/* nHeight - Number of rows in the screen rectangle */
/* */
/* Return Value: Size in bytes required to store the screen rectangle */
/***************************************************************************/

short pascal ScrGetRectSize(nWidth, nHeight)
short nWidth, nHeight;
{
return(nWidth * nHeight * 2);
}


/***************************************************************************/
/* ScrClearRect - This routine will clear a screen rectangle to the */
/* color attribute passed. */
/* Parms: */
/* nRow - Row of the screen rectangle */
/* nCol - Column of the screen rectangle */
/* nWidth - Width in columns of the screen rectangle */
/* nHeight - Number of rows in the screen rectangle */
/* nAttr - Color attribute used to clear screen rectangle */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrClearRect(nRow, nCol, nWidth, nHeight, nAttr)
short nRow, nCol, nWidth, nHeight, nAttr;
{
auto union REGS r;

nAttr = ScrCvtAttr(nAttr);
r.h.ah = (BYTE) BIOS_VID_SCROLL_UP;
r.h.al = 0;
r.h.bh = (BYTE) nAttr;
r.h.ch = (BYTE) (nRow - 1);
r.h.cl = (BYTE) (nCol - 1);
r.h.dh = (BYTE) (nRow + nHeight - 2);
r.h.dl = (BYTE) (nCol + nWidth - 2);
int86(BIOS_VID_INT, &r, &r);
return;
}


/***************************************************************************/
/* ScrSaveRect - This routine will save a screen rectangle in a caller */
/* supplied buffer area. nRow, nCol define the row and */
/* column of the upper left corner of the rectangle. */
/* Parms: */
/* nRow - Row of the screen rectangle */
/* nCol - Column of the screen rectangle */
/* nWidth - Width in columns of the screen rectangle */
/* nHeight - Number of rows in the screen rectangle */
/* pBuf - Buffer used to store the saved screen rectangle */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrSaveRect(nRow, nCol, nWidth, nHeight, pBuf)
short nRow, nCol, nWidth, nHeight;
char *pBuf;
{
register unsigned uNumRows;
register unsigned uColLen;
auto unsigned uScrOfs;
auto unsigned uBufSeg, uBufOfs;
auto char far *fpBuf;

uColLen = nWidth * 2;
uScrOfs = ((nRow - 1) * SCR_BYTES_PER_ROW) + (nCol - 1) * 2;
fpBuf = (char far *) pBuf;
uBufSeg = FP_SEG(fpBuf);
uBufOfs = FP_OFF(fpBuf);
ScrEnableVideoCGA(CGA_DISABLE);
for (uNumRows = nHeight; uNumRows > 0; --uNumRows)
{
movedata(uScrSeg, uScrOfs, uBufSeg, uBufOfs, uColLen);
uScrOfs += SCR_BYTES_PER_ROW;
uBufOfs += uColLen;
}
ScrEnableVideoCGA(CGA_ENABLE);
return;
}


/***************************************************************************/
/* ScrRestoreRect - This routine will restore a screen rectangle from */
/* a previously saved caller buffer. nRow and nCol */
/* define the upper left corner of the rectangle on */
/* the screen and are not required to be the same */
/* coordinates used in the save call. nWidth and */
/* nHeight should remain unchanged from the save call */
/* but are not required to do so. */
/* Parms: */
/* nRow - Row of the screen rectangle */
/* nCol - Column of the screen rectangle */
/* nWidth - Width in columns of the screen rectangle */
/* nHeight - Number of rows in the screen rectangle */
/* pBuf - Buffer used to restore the saved screen rectangle */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrRestoreRect(nRow, nCol, nWidth, nHeight, pBuf)
short nRow, nCol, nWidth, nHeight;
char *pBuf;
{
register unsigned uNumRows;
register unsigned uColLen;
auto unsigned uScrOfs;
auto unsigned uBufSeg, uBufOfs;
auto char far *fpBuf;

uColLen = nWidth * 2;
uScrOfs = ((nRow - 1) * SCR_BYTES_PER_ROW) + (nCol - 1) * 2;
fpBuf = (char far *) pBuf;
uBufSeg = FP_SEG(fpBuf);
uBufOfs = FP_OFF(fpBuf);
ScrEnableVideoCGA(CGA_DISABLE);
for (uNumRows = nHeight; uNumRows > 0; --uNumRows)
{
movedata(uBufSeg, uBufOfs, uScrSeg, uScrOfs, uColLen);
uScrOfs += SCR_BYTES_PER_ROW;
uBufOfs += uColLen;
}
ScrEnableVideoCGA(CGA_ENABLE);
return;
}


/***************************************************************************/
/* ScrScrollRectUp - Scrolls a screen rectangle up the requested number */
/* of lines. */
/* Parms: */
/* nRow - Row of the screen rectangle */
/* nCol - Column of the screen rectangle */
/* nWidth - Width in columns of the screen rectangle */
/* nHeight - Number of rows in the screen rectangle */
/* nNoRows - Number of rows to scroll */
/* nAttr - Color attribute to fill blank line on bottom */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrScrollRectUp(nRow, nCol, nWidth, nHeight, nNoRows, nAttr)
short nRow, nCol, nWidth, nHeight, nNoRows, nAttr;
{
auto union REGS r;

nAttr = ScrCvtAttr(nAttr);
r.h.ah = BIOS_VID_SCROLL_UP;
r.h.al = (BYTE) nNoRows;
r.h.bh = (BYTE) nAttr;
r.h.ch = (BYTE) (nRow - 1);
r.h.cl = (BYTE) (nCol - 1);
r.h.dh = (BYTE) (nRow + nHeight - 2);
r.h.dl = (BYTE) (nCol + nWidth - 2);
int86(BIOS_VID_INT, &r, &r);
return;
}


/***************************************************************************/
/* ScrScrollRectDown - Scrolls a screen rectangle up the requested number */
/* of lines. */
/* Parms: */
/* nRow - Row of the screen rectangle */
/* nCol - Column of the screen rectangle */
/* nWidth - Width in columns of the screen rectangle */
/* nHeight - Number of rows in the screen rectangle */
/* nNoRows - Number of rows to scroll */
/* nAttr - Color attribute to fill blank lines on top */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrScrollRectDown(nRow, nCol, nWidth, nHeight, nNoRows, nAttr)
short nRow, nCol, nWidth, nHeight, nNoRows, nAttr;
{
auto union REGS r;

nAttr = ScrCvtAttr(nAttr);
r.h.ah = BIOS_VID_SCROLL_DOWN;
r.h.al = (BYTE) nNoRows;
r.h.bh = (BYTE) nAttr;
r.h.ch = (BYTE) (nRow - 1);
r.h.cl = (BYTE) (nCol - 1);
r.h.dh = (BYTE) (nRow + nHeight - 2);
r.h.dl = (BYTE) (nCol + nWidth - 2);
int86(BIOS_VID_INT, &r, &r);
return;
}


/***************************************************************************/
/* ScrSetCursorPos - This routine will position the cursor to an absolute */
/* screen coordinate using the BIOS video services. */
/* Parms: */
/* nRow - Absolute screen row */
/* nCol - Absolute screen column */
/* */
/* Return Value None */
/***************************************************************************/

void pascal ScrSetCursorPos(nRow, nCol)
short nRow, nCol;
{
auto union REGS r;

r.h.ah = BIOS_VID_SET_CURSORPOS;
r.h.dh = (BYTE) (nRow - 1);
r.h.dl = (BYTE) (nCol - 1);
r.h.bh = (BYTE) nCurrActivePage;
int86(BIOS_VID_INT, &r, &r);
return;
}


/***************************************************************************/
/* ScrGetCursorPos - This routine will return the current absolute */
/* cursor position. */
/* Parms: */
/* nRow - Pointer to location to save current row */
/* nCol - Pointer to location to save current column */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrGetCursorPos(nRow, nCol)
short *nRow, *nCol;
{
auto union REGS r;

r.h.ah = BIOS_VID_GET_CURSORPOS;
r.h.bh = (BYTE) nCurrActivePage;
int86(BIOS_VID_INT, &r, &r);
*nRow = r.h.dh + 1;
*nCol = r.h.dl + 1;
return;
}


/***************************************************************************/
/* ScrCusrosOn - Enables the screen cursor. */
/* */
/* Parms: None */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrCursorOn()
{
auto union REGS r;

r.h.ah = BIOS_VID_SET_CURSORTYPE;
r.x.cx = uCsrType;
int86(BIOS_VID_INT, &r, &r);
return;
}


/***************************************************************************/
/* ScrCusrosOff - Disables the screen cursor. */
/* */
/* Parms: None */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrCursorOff()
{
auto union REGS r;

r.h.ah = BIOS_VID_SET_CURSORTYPE;
r.x.cx = 0x0f00;
int86(BIOS_VID_INT, &r, &r);
return;
}


/***************************************************************************/
/* ScrTextOut - This function uses the BIOS write character and attribute */
/* service routine to display a string within a window. The */
/* passed nCount is used to limit a string from overflowing */
/* a window boundry. */
/* Parms: */
/* pStr - Pointer to the string to be displayed */
/* nAttr - Color attribute used to display string */
/* nCount - Maximum number of characters to dispalay */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrTextOut(pStr, nAttr, nCount)
register char *pStr;
short nAttr, nCount;
{
register short i;
auto short nRow, nCol;
auto union REGS r, r1;

ScrGetCursorPos(&nRow, &nCol);
nAttr = ScrCvtAttr(nAttr);
r.h.ah = BIOS_VID_WRITE_CHATTR;
r.h.bh = (BYTE) nCurrActivePage;
r.h.bl = (BYTE) nAttr;
r.x.cx = 1;
while (*pStr && nCount-- > 0)
{
ScrSetCursorPos(nRow, nCol++);
r.h.al = *pStr++;
int86(BIOS_VID_INT, &r, &r1);
}
return;
}


/***************************************************************************/
/* ScrDrawRect - This routine is used to draw borders around a screen */
/* window. The passed parameters define the rectangle */
/* being used by the window as well as the border color */
/* and type. */
/* Parms: */
/* nRow - Top row of screen border */
/* nCol - Left column of screen border */
/* nWidth - Column width of the window */
/* nHeight - Number of rows in the window */
/* nColor - Color attribute for the window border */
/* nType - Type of border to be displayed */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrDrawRect(nRow, nCol, nWidth, nHeight, nColor, nType)
short nRow, nCol, nWidth, nHeight, nColor, nType;
{
register short i;
auto union REGS r, r1;
static BOXTYPE BoxTypes[] =
{
{ 32, 32, 32, 32, 32, 32, 32, 32 }, /* NO_BOX */
{ 213, 212, 184, 190, 179, 179, 205, 205 }, /* DBL_LINE_TOP_BOTTOM */
{ 214, 211, 183, 189, 186, 186, 196, 196 }, /* DBL_LINE_SIDES */
{ 201, 200, 187, 188, 186, 186, 205, 205 }, /* DBL_LINE_ALL_SIDES */
{ 218, 192, 191, 217, 179, 179, 196, 196 }, /* SNGL_LINE_ALL_SIDES */
{ 219, 219, 219, 219, 219, 219, 223, 220 } /* GRAPHIC BOX */
};

if (nType < 0 || nType >= MAXDIM(BoxTypes))
return;
if (nWidth < 2 || nHeight < 2)
return;
nColor = ScrCvtAttr(nColor);

/* Draw upper left corner */
ScrSetCursorPos(nRow, nCol);
r.h.ah = (BYTE) BIOS_VID_WRITE_CHATTR;
r.h.al = (BYTE) BoxTypes[nType].cUpperLeft;
r.h.bh = (BYTE) nCurrActivePage;
r.h.bl = (BYTE) nColor;
r.x.cx = 1;
int86(BIOS_VID_INT, &r, &r1);

/* Draw upper right corner */
ScrSetCursorPos(nRow, nCol + nWidth - 1);
r.h.al = (BYTE) BoxTypes[nType].cUpperRight;
int86(BIOS_VID_INT, &r, &r1);

/* Draw lower left corner */
ScrSetCursorPos(nRow + nHeight - 1, nCol);
r.h.al = (BYTE) BoxTypes[nType].cLowerLeft;
int86(BIOS_VID_INT, &r, &r1);

/* Draw lower right corner */
ScrSetCursorPos(nRow + nHeight - 1, nCol + nWidth - 1);
r.h.al = (BYTE) BoxTypes[nType].cLowerRight;
int86(BIOS_VID_INT, &r, &r1);

if (nHeight > 2)
{
/* Draw left side line */
r.h.al = (BYTE) BoxTypes[nType].cLeft;
for (i = 1; i <= nHeight - 2; ++i)
{
ScrSetCursorPos(nRow + i, nCol);
int86(BIOS_VID_INT, &r, &r1);
}

/* Draw right side line */
r.h.al = (BYTE) BoxTypes[nType].cRight;
for (i = 1; i <= nHeight - 2; ++i)
{
ScrSetCursorPos(nRow + i, nCol + nWidth - 1);
int86(BIOS_VID_INT, &r, &r1);
}
}

if (nWidth > 2)
{
/* Draw top line */
ScrSetCursorPos(nRow, nCol + 1);
r.h.al = (BYTE) BoxTypes[nType].cTop;
r.x.cx = nWidth - 2;
int86(BIOS_VID_INT, &r, &r1);

/* Draw bottom line */
ScrSetCursorPos(nRow + nHeight - 1, nCol + 1);
r.h.al = BoxTypes[nType].cBottom;
int86(BIOS_VID_INT, &r, &r1);
}

return;
}


/***************************************************************************/
/* ScrInitialize - Determine type of video card and init global data. */
/* */
/* Parms: None */
/* */
/* Return Value: None */
/***************************************************************************/

void pascal ScrInitialize()
{
auto union REGS r;

r.h.ah = BIOS_VID_GET_CURSORPOS;
r.h.bh = (BYTE) nCurrActivePage;
int86(BIOS_VID_INT, &r, &r);
uCsrType = r.x.cx;

r.h.ah = BIOS_VID_GET_CRTMODE;
int86(BIOS_VID_INT, &r, &r);
nScrCols = r.h.ah;
nCurrActivePage = r.h.bh;
if (7 == r.h.al)
{
uScrSeg = 0xb000;
nVideoCard = VIDEO_MONO;
return;
}
r.h.ah = BIOS_VID_SET_CRTMODE;
r.h.al = 3;
int86(BIOS_VID_INT, &r, &r);
uScrSeg = 0xb800;
nVideoCard = VIDEO_CGA;
return;
}