Metropoli BBS
VIEWER: screen.c MODE: TEXT (CP437)
#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, &regs, &regs );
}

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, &regs, &regs );
}

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, &regs, &regs );
}

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, &regs, &regs );
}

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, &regs, &regs );
}

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, &regs, &regs );
}

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, &regs, &regs );
}

SCR_BlockCursor()
{
   union REGS regs;

   regs.h.ah = 0x01;
   regs.h.ch = 0;
   regs.h.cl = 11;
   int86( 0x10, &regs, &regs );
}

SCR_LineCursor()
{
   union REGS regs;

   regs.h.ah = 0x01;
   regs.h.ch = 10;
   regs.h.cl = 11;
   int86( 0x10, &regs, &regs );
}

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;
}

[ RETURN TO DIRECTORY ]