#include <dos.h>
#include "keyboard.h"
#include "colors.h"
#include "screen.h"
#define ATEQU Attribute = (Bold + Blink + Fore + (Back << 4))
#define COLOR Attribute
static char far* Video;
static char far* Next;
static int Row;
static int Col;
static int WinTop;
static int WinBottom;
static int Attribute;
static int Fore = LIGHTGRAY;
static int Back = BLACK;
static int Scroll = -1;
static int UpdateCursor = 1;
static unsigned Blink = 0;
static unsigned Bold = 0;
static int Wrap = 0;
static int BW = 0;
static int LastRow = 24;
static int LastCol = 79;
void SCR_Init()
{
union REGS r;
int i;
r.h.ah = 0x0f;
int86( 0x10, &r, &r );
if( r.h.al == 0 || r.h.al == 2 || r.h.al == 7 )
BW = 1;
int86( 0x11, &r, &r );
if( (r.h.al & 0x30) == 0x30 )
Video = (char far *) 0xB0000000L;
else
Video = (char far *) 0xB8000000L;
LastRow = 24;
LastCol = 79;
WinTop = 0;
WinBottom = LastRow;
Bold = 0;
Blink = 0;
Fore = LIGHTGRAY;
Back = BLACK;
ATEQU;
Scroll = -1;
SCR_LineCursor();
SCR_Clear( 0 );
SCR_GotoRowCol( 0, 0, 0 );
}
SCR_Term()
{
}
SCR_SetScreenHeight( int h )
{
if( h < 2 )
h = 2;
else if( h > 25 )
h = 25;
LastRow = h - 1;
}
SCR_SetScreenWidth( int w )
{
if( w < 2 )
w = 2;
else if( w > 80 )
w = 80;
LastCol = w - 1;
}
int SCR_IsColor()
{
return !BW;
}
void SCR_ScrollColor( int c )
{
Scroll = c;
}
void SCR_ClearArea( int l, int t, int r, int b )
{
union REGS regs;
regs.h.ah = 0x06;
regs.h.al = b - t + 1;
regs.h.bh = Scroll == -1 ? COLOR : Scroll;
regs.x.cx = (t << 8) + l;
regs.x.dx = (b << 8) + r;
int86( 0x10, ®s, ®s );
}
void SCR_Fill( int l, int t, int r, int b, int ch, int co )
{
register j, i;
char far* v = Video;
for( i = t; i <= b; i++ )
{
v = Video + (l << 1) + i * 160;
for( j = l; j <= r; j++ )
{
*v++ = ch;
*v++ = co;
}
}
}
void SCR_FillArea( int l, int t, int r, int b )
{
union REGS regs;
regs.h.ah = 0x06;
regs.h.al = b - t + 1;
regs.h.bh = COLOR;
regs.x.cx = (t << 8) + l;
regs.x.dx = (b << 8) + r;
int86( 0x10, ®s, ®s );
}
void SCR_Clear( int w )
{
union REGS regs;
regs.h.ah = 0x06;
regs.h.al = (w ? (WinBottom - WinTop + 1) : (LastRow + 1));
regs.h.bh = Scroll == -1 ? COLOR : Scroll;
regs.x.cx = (w ? (WinTop << 8) : 0);
regs.x.dx = (w ? (WinBottom << 8) : ((LastRow << 8) + LastCol) );
int86( 0x10, ®s, ®s );
}
void SCR_ClearEOL()
{
register i;
char far* v;
v = Video + Row * 160 + (Col << 1);
for( i = Col; i <= LastCol; i++ )
{
*v++ = ' ';
*v++ = Scroll == -1 ? COLOR : Scroll;
}
}
void SCR_ClearBOL()
{
register i;
char far* v;
v = Video + Row * 160;
for( i = 0; i <= Col; i++ )
{
*v++ = ' ';
*v++ = Scroll == -1 ? COLOR : Scroll;
}
}
void SCR_ClearBOD( int w )
{
SCR_ClearBOL( w );
if( w )
SCR_ClearArea( 0, WinTop, LastCol, Row - 1 );
else
SCR_ClearArea( 0, 0, LastCol, Row - 1 );
}
void SCR_ClearEOD( int w )
{
SCR_ClearEOL( w );
if( w )
SCR_ClearArea( 0, Row + 1, LastCol, WinBottom );
else
SCR_ClearArea( 0, Row + 1, LastCol, LastRow );
}
SCR_InsertChar( int n, int c )
{
char far* v;
int l;
if( n < 1 )
n = 1;
else if( n > 80 )
n = 80;
while( n-- )
{
v = Video + Row * 160 + 159;
for( l = Col; l < 79; l++ )
{
*v = *(v - 2);
v--;
*v = *(v - 2);
v--;
}
*v-- = Scroll == -1 ? COLOR : Scroll;
*v-- = c;
}
}
SCR_DeleteChar( int n )
{
char far* v;
int l;
if( n < 1 )
n = 1;
else if( n > 80 )
n = 80;
while( n-- )
{
v = Video + Row * 160 + (Col << 1);
for( l = Col; l < 79; l++ )
{
*v = *(v + 2);
v++;
*v = *(v + 2);
v++;
}
*v++ = ' ';
*v++ = Scroll == -1 ? COLOR : Scroll;
}
}
void SCR_EraseChars( int n )
{
char far* v;
if( n < 1 )
n = 1;
v = Video + Row * 160 + (Col << 1);
while( n-- )
{
*v++ = ' ';
*v++ = Scroll == -1 ? COLOR : Scroll;
}
}
void SCR_InsertLine( int w, int n )
{
if( n < 1 )
n = 1;
if( w )
SCR_ScrollArea( SCROLL_DOWN, 0, Row, 79, WinBottom, n );
else
SCR_ScrollArea( SCROLL_DOWN, 0, Row, LastCol, LastRow, n );
}
void SCR_DeleteLine( int w, int n )
{
if( n < 1 )
n = 1;
if( w )
SCR_ScrollArea( SCROLL_UP, 0, Row, 79, WinBottom, n );
else
SCR_ScrollArea( SCROLL_UP, 0, Row, LastCol, LastRow, n );
}
void SCR_ScrollArea( int dir, int l, int t, int r, int b, int n )
{
union REGS regs;
if( n < 1 )
n = 1;
else if( n > 1 + b - t )
n = 1 + b - t;
regs.h.ah = dir;
regs.h.al = n;
regs.h.bh = ((Scroll == -1) ? COLOR : Scroll);
regs.x.cx = (t << 8) + l;
regs.x.dx = (b << 8) + r;
int86( 0x10, ®s, ®s );
}
void SCR_Scroll( int w, int dir, int n )
{
union REGS regs;
regs.h.ah = dir;
regs.h.al = n;
regs.h.bh = ((Scroll == -1) ? COLOR : Scroll);
regs.x.cx = (w ? (WinTop << 8) : 0);
regs.x.dx = (w ? ((WinBottom << 8) + 79) : 0x194f);
int86( 0x10, ®s, ®s );
}
void SCR_DefineRegion( int t, int b )
{
if( t < 0 )
t = 0;
if( t > LastRow - 1 )
t = LastRow - 1;
if( b <= t )
b = t + 1;
if( b > LastRow )
b = LastRow;
WinTop = t;
WinBottom = b;
}
int SCR_GetTop()
{
return WinTop;
}
int SCR_GetBottom()
{
return WinBottom;
}
void SCR_PutCursor( int w, int r, int c )
{
union REGS regs;
if( r < 0 )
r = 0;
else if( r > (w ? (WinBottom - WinTop) : LastRow) )
r = (w ? (WinBottom - WinTop) : LastRow);
if( c < 0 )
c = 0;
else if( c > 79 )
c = 79;
regs.h.ah = 0x02;
regs.h.bh = 0x00;
regs.h.dh = r;
regs.h.dl = c;
int86( 0x10, ®s, ®s );
}
void SCR_GotoRowCol( int w, int r, int c )
{
if( r < 0 )
r = 0;
else if( r > (w ? (WinBottom - WinTop) : LastRow) )
r = (w ? (WinBottom - WinTop) : LastRow);
if( c < 0 )
c = 0;
else if( c > 79 )
c = 79;
Row = (w ? (WinTop + r) : r);
Col = c;
Next = (Video + Row * 160 + (Col << 1));
if( UpdateCursor )
SCR_PutCursor( w, r, c );
}
int SCR_MoveLeft( int n )
{
if( Col == 0 )
return 0;
if( n < 1 )
n = 1;
Col -= n;
if( Col < 0 )
Col = 0;
SCR_GotoRowCol( 0, Row, Col );
return 1;
}
int SCR_MoveRight( int n )
{
if( Col == 79 )
return 0;
if( n < 1 )
n = 1;
Col += n;
if( Col > 79 )
Col = 79;
SCR_GotoRowCol( 0, Row, Col );
return 1;
}
int SCR_MoveUp( int n )
{
if( Row == WinTop || Row == 0 )
return 0;
if( n < 1 )
n = 1;
while( n-- && Row != WinTop && Row != 0 )
Row--;
SCR_GotoRowCol( 0, Row, Col );
return 1;
}
int SCR_MoveDown( int n )
{
if( Row == WinBottom || Row == LastRow )
return 0;
if( n < 1 )
n = 1;
while( n-- && Row != WinBottom && Row != LastRow )
Row++;
SCR_GotoRowCol( 0, Row, Col );
return 1;
}
int SCR_GetRow( int w )
{
return (w ? (Row - WinTop) : Row);
}
int SCR_GetCol()
{
return Col;
}
void SCR_Wrap( int o )
{
if( o )
Wrap = 1;
else
Wrap = 0;
}
void SCR_SetBlink( int o )
{
if( o )
Blink = 128;
else
Blink = 0;
ATEQU;
}
int SCR_GetBlink()
{
return Blink > 0;
}
void SCR_SetBold( int o )
{
if( o )
Bold = 8;
else
Bold = 0;
ATEQU;
}
int SCR_GetBold()
{
return Bold > 0;
}
void SCR_SetFore( int c )
{
if( c < 0 )
c = 0;
else if( c > 7 )
{
if( c > 15 )
c = 15;
c -= 8;
}
Fore = c;
ATEQU;
}
int SCR_GetFore()
{
return Fore;
}
void SCR_SetBack( int c )
{
if( c < 0 )
c = 0;
else if( c > 7 )
{
if( c > 15 )
c = 15;
c -= 8;
}
Back = c;
ATEQU;
}
int SCR_GetBack()
{
return Back;
}
void SCR_SetColor( int c )
{
Blink = (c & 128);
Bold = (c & 8);
Fore = (c & 7);
Back = (c & 112) >> 4;
ATEQU;
}
int SCR_GetColor()
{
return COLOR;
}
void SCR_PutChar( int w, unsigned char c )
{
if( Col > 79 )
{
if( Wrap )
{
Col = 0;
Row++;
if( Row == (w ? WinBottom : LastRow) + 1 )
{
Row = (w ? WinBottom : LastRow);
SCR_Scroll( w, SCROLL_UP, 1 );
}
}
else
Col = 79;
Next = (Video + Row * 160 + (Col << 1));
}
if( c < 32 ) switch( c )
{
case 0 : return;
case 7 : sound( 700 );
delay( 100 );
nosound();
delay( 10 );
return;
case 8 : if( Col > 0 )
SCR_GotoRowCol( 0, Row, Col - 1 );
return;
case 9 : SCR_PutString( 0, " " );
return;
case 10 :
case 11 :
case 12 : if( Row == (w ? WinBottom : LastRow) )
SCR_Scroll( w, SCROLL_UP, 1 );
else
SCR_GotoRowCol( 0, Row + 1, Col );
return;
case 13 : SCR_GotoRowCol( 0, Row, 0 );
return;
}
*Next++ = c;
*Next++ = COLOR;
Col++;
if( UpdateCursor )
SCR_PutCursor( 0, Row, Col );
}
void SCR_PutString( int w, char* s )
{
UpdateCursor = 0;
while( *s )
SCR_PutChar( w, *s++ );
UpdateCursor = 1;
SCR_GotoRowCol( 0, Row, Col );
}
SCR_PutStringPad( int w, char* s, int p )
{
UpdateCursor = 0;
while( *s && p )
{
SCR_PutChar( w, *s++ );
p--;
}
while( p-- )
SCR_PutChar( w, ' ' );
UpdateCursor = 1;
SCR_GotoRowCol( 0, Row, Col );
}
void SCR_DrawBorder( int l, int t, int r, int b, int bc, char* title, int tc )
{
char far* v;
int i;
v = Video + t * 160 + (l << 1);
*v++ = '┌'; *v++ = bc;
i = l + 1;
if( title )
{
*v++ = '┤'; *v++ = bc;
*v++ = ' '; *v++ = tc;
i += 2;
while( *title )
{
*v++ = *title++;
*v++ = tc;
i++;
}
*v++ = ' '; *v++ = tc;
*v++ = '├'; *v++ = bc;
i += 2;
}
while( i++ < r )
{
*v++ = '─';
*v++ = bc;
}
*v++ = '┐';
*v++ = bc;
v = Video + t * 160 + (l << 1) + 160;
for( i = t + 1; i < b; i++ )
{
*v = '│';
*(v + 1) = bc;
*(v + ((r - l) << 1)) = '│';
*(v + ((r - l) << 1) + 1) = bc;
v += 160;
}
*v++ = '└'; *v++ = bc;
for( i = l + 1; i < r; i++ )
{
*v++ = '─';
*v++ = bc;
}
*v++ = '┘';
*v = bc;
}
SCR_SaveArea( int l, int t, int b, int r, char* buf )
{
char far* v;
int x, y;
for( y = t; y <= b; y++ )
{
v = Video + y * 160 + (l << 1);
for( x = l; x <= r; x++ )
{
*buf++ = *v++;
*buf++ = *v++;
}
}
}
SCR_RestoreArea( int l, int t, int b, int r, char* buf )
{
char far* v;
int x, y;
for( y = t; y <= b; y++ )
{
v = Video + y * 160 + (l << 1);
for( x = l; x <= r; x++ )
{
*v++ = *buf++;
*v++ = *buf++;
}
}
}
SCR_SaveScreen( SCRSAV* s )
{
register i;
char far* v = Video;
s->row = Row;
s->col = Col;
s->scroll = Scroll;
s->fore = Fore;
s->back = Back;
s->blink = Blink;
s->bold = Bold;
s->wrap = Wrap;
s->top = WinTop;
s->bottom = WinBottom;
for( i = 0; i < 4000; i++ )
s->buffer[i] = *v++;
}
SCR_RestoreScreen( SCRSAV* s )
{
register i;
char far* v = Video;
Row = s->row;
Col = s->col;
Scroll = s->scroll;
Fore = s->fore;
Back = s->back;
Blink = s->blink;
Bold = s->bold;
Wrap = s->wrap;
WinTop = s->top;
WinBottom = s->bottom;
for( i = 0; i < 4000; i++ )
*v++ = s->buffer[i];
SCR_GotoRowCol( 0, Row, Col );
ATEQU;
}
SCR_NoCursor()
{
union REGS regs;
regs.h.ah = 0x01;
regs.h.ch = 0x20;
int86( 0x10, ®s, ®s );
}
SCR_BlockCursor()
{
union REGS regs;
regs.h.ah = 0x01;
regs.h.ch = 0;
regs.h.cl = 11;
int86( 0x10, ®s, ®s );
}
SCR_LineCursor()
{
union REGS regs;
regs.h.ah = 0x01;
regs.h.ch = 10;
regs.h.cl = 11;
int86( 0x10, ®s, ®s );
}
SCR_GetString( char* s, int l )
{
int done, k, i, c, ins = 1;
c = Col;
i = strlen( s );
while( i < l )
s[i++] = ' ';
s[i] = 0;
i = 0;
SCR_PutString( 0, s );
SCR_GotoRowCol( 0, Row, c + i );
done = 0;
SCR_LineCursor();
while( !done )
{
SCR_GotoRowCol( 0, Row, c + i );
k = KEY_GetKey( 0 );
switch( k )
{
case ESCAPE : done = -1;
break;
case ENTER : done = 1;
break;
case INSERT : ins = 1 - ins;
if( ins )
SCR_LineCursor();
else
SCR_BlockCursor();
break;
case BACKSPACE : if( i == 0 )
break;
i--;
Col--;
Next -= 2;
case DELETE : memmove( &s[i], &s[i + 1], l - i - 1 );
s[l - 1] = ' ';
SCR_PutString( 0, &s[i] );
break;
case LEFT : if( i )
i--;
break;
case RIGHT : if( i < l )
i++;
break;
case HOME : i = 0;
break;
case END : i = l - 1;
while( i && s[i] == ' ' )
i--;
if( s[i] != ' ' )
i++;
if( i > l )
i = l;
break;
default : if( k && k < 256 && i < l )
{
if( ins )
memmove( &s[i + 1], &s[i], l - i - 1 );
s[i] = k;
SCR_PutString( 0, &s[i] );
i++;
}
break;
}
}
i = l - 1;
while( i >= 0 && s[i] == ' ' )
s[i--] = 0;
SCR_LineCursor();
return done;
}