www.pudn.com > ·ÂÕæÖÕ¶Ëvt100.zip > VIDIO.C


#include  
#include  
#include  
#include  
 
#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 */ 
}