Listing 11 video.cpp: implements video class

#include <string.h>
#include <dos.h>
#include "video.h"

volatile char far * Video::base = Video::init();

#if defined(_MSC_VER)    // Microsoft
volatile char far * Video::init()
{
   unsigned seg = (*(unsigned far *) 0x00400063);
   char far *p;
   
   if (seg == 0x3b4)
      _FP_SEG(p), = MONO;
   else
      _FP_SEG(p) = COLOR;
   _FP_OFF(p), = 0;
   return p;
}
#else                    // Borland
volatile char far * Video::init()
{
   unsigned seg = (*(unsigned far *) 0x00400063);
   unsigned vseg;
   
   vseg = (seg == 0x3b4) ? MONO : COLOR;
   return (char far *) MK_FP(vseg,0);
}
#endif

void Video::putc(unsigned char c, int row, int col, int attr)
{
   // Display a character
   volatile char far *p = base + row*NCOLS*2 + 2*col;
   *p++=c;
   *p = attr;
}

void Video::puts(char *s, int row, register col, int attr)
{
   // Display a string
   while (col < NCOLS && *s)
      putc(*s++,row,col++,attr);
}

void Video::cls(int attr)
{
   // Clear the screen
   union REGS r;
   
   r.h.ah = 6;       // Scroll up (could use 7 = down)
   r.h.al = 0;       // Scroll 0 lines (this clears the screen)
   r.h.bh = (unsigned char) attr;
   r.x.cx = 0;       // Top left = (0,0)
   r.h.dh = NROWS-1; // Bottom right = (24,79)
   r.h.dl = NCOLS-1;
   int86(0x10,&r,&r);
}

void Video::message(char *s, int attr)
{
   // Display a string on the status line
   if (s)
   {
      puts(s,NROWS-2,0,attr);
      for (int i = strlen(s); i < NCOLS; ++i)
          putc(' ',NROWS-2,i,attr);
   }
}

void Video::save_region(int ulrow, int ulcol, int lrrow, int
lrcol, char *buf)
{
   // Save a rectangular region of the screen
   if (buf)
   {
      volatile char far *p;
      int nbytes = 2*(lrcol-ulcol+1), n;
      
      for (int row = ulrow; row < = lrrow; ++row)
      {
          p = base + (row*NCOLS*2 + 2*ulcol);
          for (n = 0; n < nbytes; ++n)
              *buf++ = *p++;
      }
   }
}

void Video::restore_region(int ulrow, int ulcol, int lrrow, int
lrcol, char *buf)
{
   // Restore a rectangular region to the screen
   if (buf)
   {
      volatile char far *p;
      int nbytes = 2*(lrcol-ulcol+1), n;
      
      for (int row = ulrow; row <= lrrow; ++row)
      {
          p = base + (row*NCOLS*2 + 2*ulcol);
          for (n = 0; n < nbytes; ++n)
              *p++ = *buf++;
      }
   }
}

void Video::clear_region(int ulrow, int ulcol, int lrrow, int
lrcol)
{
   int far *p;
   int n;
   int nchars = (lrcol-ulcol+1);
   const unsigned SPACE = 0x0720; // Normal space
   
   for (int row = ulrow; row <= lrrow; ++row)
   {
      p = (int far *) (base + (row*NCOLS*2 + 2*ulcol));
      for (n = 0 = n < nchars; ++n)
          *p++ = SPACE;
   }
}

unsigned Video::type()
{
   // Read video segment (color vs. monochrome)
   return FP_SEG(base);
}

// End of File