home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / modem / cvt100.zip / VIDIO.C < prev    next >
Text File  |  1988-08-03  |  47KB  |  1,101 lines

  1. #include <stdio.h>
  2. #include <dos.h>
  3. #include <conio.h>
  4. #include <alloc.h>
  5.  
  6. #define NORMAL        0x7         /* Normal video attribute */
  7. #define BOLD          0x8         /* Bold video attribute */
  8. #define UNDERLINED    0xA         /* Underlined video attribute */
  9. #define REVERSE       0x70        /* Reverse video attribute */
  10. #define SCREEN        0x10        /* BIOS video interrupt number */
  11. #define RETRACE       0x3da       /* Video Retrace port address for CGA */
  12. #define ASCII         0           /* ASCII character set */
  13. #define UK            1           /* UK character set */
  14. #define SPECIAL       2           /* Special character set, graphics chars */
  15.  
  16. /****************************************************************************/
  17. /* Function prototypes                                                      */
  18.  
  19. void VidInit( void );             /* Initialize the video system */
  20. void SetVattr( unsigned char );   /* Set the video attribute */
  21. void AddVattr( unsigned char );   /* Add attribute to current video attribute*/
  22. void SubVattr( unsigned char );   /* Sub attribute from current vid attribute*/
  23. void BrkAtt( unsigned char );     /* Break attribute into extra and base */
  24. unsigned char AddAtt( void );     /* Add extra and base attributes to get */
  25.                                   /* a resulting displayable video attribute*/
  26. void ChrWrite( unsigned char );   /* Write character to the screen */
  27. void SetScroll(int , int );       /* Set the scrolling region */
  28. void ScrollDown( void );          /* Move down a row scrolling if necessary */
  29. void ScrollUp( void );            /* Move up a row scrolling if necessary */
  30. void IndexDown( void );           /* Scroll the screen down */
  31. void IndexUp( void );             /* Scroll the screen up */
  32. void SetCurs(int , int );         /* Set the cursor to absolute coordinates */
  33. void SetRelCurs(int , int );      /* Set the cursor to relative coordinates */
  34. void PosCurs( void );             /* Position the cursor to cursx,cursy */
  35. void ModeLine( void );            /* Display the Mode line */
  36. void ClearScreen( void );         /* Clear the terminal screen */
  37. void ClearEOS( void );            /* Clear from cursor to end of screen */
  38. void ClearBOS( void );            /* Clear from cursor to top of screen */
  39. void ClearEOL( void );            /* Clear from cursor to end of line */
  40. void ClearBOL( void );            /* Clear from cursor to start of line */
  41. void ClearBox( unsigned char,     /* Clear a box on the video screen */
  42.    unsigned char, unsigned char,
  43.    unsigned char, unsigned char);
  44. void MarCharSet( int );           /* Map a character set */
  45. void SetCharSet( int, unsigned char ); /* Set a character set */
  46. void SaveCursor( void );          /* Save the cursor description */
  47. void RestoreCursor( void );       /* Restore the cursor description */
  48. void SetCursorVisibility( int );  /* Set the cursor visibility mode */
  49. void SetBackGround( int );        /* Set background video attribute */
  50. void SetColor( void );            /* Set the screen colors */
  51. void InitTabs( void );            /* Initialize the tab settings */
  52. void DoTab( void );               /* Perform a tab */
  53. void SetTabStop( void );          /* Set a tab stop at cursor position */
  54. void ClearTabStop( void );        /* Clear a tab stop at the cursor position*/
  55. void ClearAllTabs( void );        /* Clear all the defined tab stops */
  56. void SetScreenWidth( int );       /* Set the logical width of the screen */
  57. void StartScreen( int, int );     /* Start a screen access */
  58. void EndScreen( void );           /* End a screen access */
  59. void WriteOneChar( unsigned char, /* Write one character to the screen */
  60.      int, int );
  61. int  VTprintf( int, int, int,     /* Printf for Emulator to row and column */
  62.      char *, ... );                  /* in regular or reverse video */
  63. void SaveScreen( void );          /* Save contents of video memory */
  64. void RestoreScreen( void );       /* Restore contents of video memory */
  65.  
  66. static void interrupt10( unsigned,/* Issue a BIOS video interrupt */
  67.   unsigned , unsigned , unsigned );
  68.  
  69.  
  70. /****************************************************************************/
  71. /* Global Data                                                              */
  72.  
  73. unsigned char retracemode = 0;    /* Flag indicating No Video refresh wait */
  74. unsigned char forecolor;          /* Foreground color */
  75. unsigned char backcolor;          /* Background color */
  76.  
  77. unsigned char vidmode;            /* Screen video mode */
  78.  
  79. /****************************************************************************/
  80. /* External variables                                                       */
  81.  
  82. extern unsigned originmode;       /* Origin mode, relative or absolute */
  83. extern unsigned insertmode;       /* Insert mode, off or on */
  84. extern unsigned autowrap;         /* Automatic wrap mode, off or on */
  85. extern unsigned newline;          /* Newline mode, off or on,  GLOBAL data!*/
  86. extern unsigned cursorvisible;    /* Cursor visibility, on or hidden */
  87. extern unsigned reversebackground;/* Reverse background attribute, on or off*/
  88. extern unsigned screenwid;        /* Absolute screen width */
  89.  
  90. extern char modeline[];           /* Text of mode line */
  91.  
  92. /***************************************************************************/
  93. /* Local static data                                                       */
  94.  
  95. static unsigned char screentop;   /* Absolute top of screen */
  96. static unsigned char screenbot;   /* Absolute bottom of screen */
  97. static unsigned char scrolltop;   /* Top row of scrolling region */
  98. static unsigned char scrollbot;   /* Bottom row of scrolling region */
  99.  
  100. static int cursx;                 /* X cursor position */
  101. static int cursy;                 /* Y cursor position */
  102.  
  103. static unsigned scroff;           /* Screen memory offset */
  104. static unsigned scrseg;           /* Screen memory segment */
  105. static unsigned scrchars;         /* Number of chars written to video memory */
  106. static unsigned char tvmode;      /* Flag to indicate control program present*/
  107. char far *screen;                 /* Pointer to video screen */
  108. static unsigned savebp;           /* Static storage for BP through int 0x10 */
  109.  
  110. static unsigned char video_state; /* State of video, reversed or normal */
  111. static unsigned char scbattr;     /* Video attribute of empty video cell */
  112. static unsigned char curattr;     /* Video attribute of displayable chars */
  113. static unsigned char baseattr;    /* Base attribute for video attributes */
  114. static unsigned char extrattr;    /* Extra attribute for video attributes */
  115.  
  116. static unsigned char att_reverse;          /* Reverse attribute bits */
  117. static unsigned char att_normal;           /* Normal attribute bits */
  118. static unsigned char att_low_mask  = 0x6;  /* Low attribute mask */
  119. static unsigned char att_underline = 0x1;  /* Underlined attribute bit */
  120. static unsigned char att_intensity = 0x8;  /* Bold attribute bit */
  121. static unsigned char att_blink     = 0x80; /* Blinking attribute bit */
  122.  
  123.  
  124. static unsigned columns;          /* Columns on logical terminal screen */
  125. static unsigned lines;            /* Lines on logical terminal screen */
  126.  
  127. static char tabs[132];            /* active tab stops */
  128. static char deftabs[132];         /* default tab stops, 9,17,26 .... */
  129.  
  130. static int G0 = ASCII;            /* Character set G0 */
  131. static int G1 = ASCII;            /* Character set G1 */
  132. static int *GL = &G0;             /* Pointer to current mapped character set*/
  133.  
  134. static char special_chars[32] = { /* Special characters */
  135.    32,4,176,9,12,13,10,248,241,18,11,217,191,218,192,197,
  136.    196,196,196,196,196,195,180,193,194,179,243,242,227,216,156,7
  137.    } ;
  138.  
  139. static struct SaveCursorStruct {  /* Structure to save cursor description */
  140.    int cursx;                        /* X cursor position, column */
  141.    int cursy;                        /* Y cursor position, row */
  142.    int *GL;                          /* pointer to mapped character set */
  143.    int G0;                           /* character set G0 */
  144.    int G1;                           /* character set G1 */
  145.    int mode;                         /* origin mode */
  146.    } save = { 1, 1, &G0, ASCII, ASCII , 0 } ;
  147.  
  148.                                   /* Pointer to memory allocated to hold */
  149. static char far *screen_save = NULL; /* the contents of video memory */
  150.  
  151. /****************************************************************************/
  152. /****************************************************************************/
  153.  
  154.  
  155. /* V I D I N I T  -- Initialize the video system */
  156.  
  157. void VidInit( ) {
  158.  
  159.     char far *bptr;
  160.                                   /* Obtain video information from BIOS */
  161.     _AH = 0x0F;                   /* Use function F of interrupt 10 */
  162.     savebp = _BP;                 /* Precautionary save of register BP */
  163.     geninterrupt( 0x10 );         /* Issue BIOS video interrupt */
  164.     _BP = savebp;                 /* Restore saved BP register */
  165.     vidmode = _AL;                /* Save the video mode */
  166.     columns = _AH;                /* Save the number of columns */
  167.     lines = 25;                   /* Lines = 25, (sorry no 43,50 lines */
  168.     screenbot = lines - 1;        /* Bottom of screen is 24 */
  169.     screentop = 1;                /* Top of screen is line 1 */
  170.  
  171.     tvmode = 0;                   /* Assume no control program present */
  172.  
  173.  
  174.  
  175.     if (GetVidSetup() == 0) {     /* If no video parameters are saved */
  176.                                   /* then determine default values */
  177.  
  178.                                   /* First determine if snow is a problem */
  179.        if (vidmode != 7)          /* Assume video adapter is snowy if */
  180.             retracemode = 1;      /* it is not a MonoChrome */
  181.  
  182.                                   /* First query Video BIOS to see if */
  183.         _AX = 0x1A00;             /* VGA is present, no "snow" problem on VGA*/
  184.         savebp = _BP;             /* Precautionary save of register BP */
  185.         geninterrupt( 0x10 );     /* Issue BIOS video interrupt */
  186.         _BP = savebp;             /* Restore saved BP register */
  187.         if (_AL == 0x1A)          /* If VGA is detected */
  188.             retracemode = 0;         /* No snow protection needed */
  189.         else {                    /* Else look for an EGA */
  190.             _CL = 0xC;               /* Test the Video BIOS to see if */
  191.             _BX = 0xFF10;            /*  an EGA can be detected */
  192.             _AX = 0x1200;            /*  EGA's don't have "snow" problem either*/
  193.             savebp = _BP;            /* Precautionary save of register BP */
  194.             geninterrupt( 0x10 );    /* Issue BIOS video interrupt */
  195.             _BP = savebp;            /* Restore saved BP register */
  196.             if (_CL < 0xC) {         /* If EGA is detected */
  197.                 bptr = MK_FP(0x40,0x87);/* Check BIOS data to see if the */
  198.                 if ( (*bptr & 0x8) == 0)/* EGA is the active adapter */
  199.                     retracemode = 0;    /* No snow protection required */
  200.             }
  201.         }
  202.  
  203.                                   /* Determine the default screen attributes*/
  204.         _AH = 0x8;                /* Issue function 8 or interrupt 10 */
  205.         _BH = 0x0;                /* for page 0 */
  206.         savebp = _BP;             /* Precautionary save of register BP */
  207.         geninterrupt( 0x10 );     /* Get video attribute at cursor pos */
  208.         _BP = savebp;             /* Restore saved BP register */
  209.         scbattr = _AH;            /* Save this attribute */
  210.  
  211.         forecolor = scbattr & 0xf;/* Save values for determined colors */
  212.         backcolor = scbattr >> 4;
  213.     }
  214.  
  215.  
  216.     else {                        /* If saved values were available */
  217.  
  218.                                   /* Set the screen color to saved value */
  219.         scbattr = ( backcolor << 4 ) | forecolor;
  220.  
  221.        if (vidmode == 7)          /* Do not let retracemode be set on */
  222.             retracemode = 0;      /* if video is a MonoChrome */
  223.     }
  224.  
  225.     att_normal = scbattr;
  226.     BrkAtt(scbattr);              /* Break the attribute into base,extra */
  227.                                   /* Reverse the foreground and background*/
  228.     baseattr = ( baseattr >> 4 | baseattr << 4);
  229.     att_reverse = AddAtt();       /* Put the attributes back together */
  230.                                   /* in order to get reverse attribute */
  231.  
  232.                                   /* Clear screen to established attribute*/
  233.     interrupt10( 0x0600,scbattr << 8,
  234.        0 ,(lines << 8) | (columns - 1 ));
  235.  
  236.                                   /* Clear the top line setting it to reverse*/
  237.     interrupt10( 0x0600,att_reverse << 8 ,0,columns - 1);
  238.     vtprintf(0,0,1,modeline);     /* Display the mode line in reverse */
  239.  
  240.  
  241.     if (screen_save == NULL) {    /* If first time to be initialized */
  242.                                   /* Attempt to allocate screen mem */
  243.        if ( (screen_save = farmalloc( lines * columns * 2 )) == NULL)
  244.           badexit("No memory available for video screen save buffer");
  245.     }
  246.  
  247. }
  248.  
  249.  
  250. /* S E T V A T T R  --  Set the video attribute */
  251.  
  252. void SetVattr(unsigned char attr) {
  253.  
  254.     video_state = 0;              /* Reset the video state */
  255.     BrkAtt(scbattr);              /* Break apart the default screen attribute*/
  256.  
  257.     switch (attr) {               /* See what video attribute is requested */
  258.         case BLINK:               /* Blinking characters */
  259.             extrattr = att_blink;
  260.             break;
  261.         case REVERSE:             /* Reversed video characters */
  262.             video_state = 1;
  263.             baseattr = ( baseattr >> 4 | baseattr << 4);
  264.             break;
  265.         case UNDERLINED:          /* Underlined characters */
  266.             if (vidmode == 0x7)   /* Monochrome can underline */
  267.                 extrattr = att_underline;
  268.             else {                /* others can't use reverse video */
  269.                 video_state = 1;
  270.                 baseattr = ( baseattr >> 4 | baseattr << 4);
  271.             }
  272.             break;
  273.         case BOLD:                /* High intensity, bold, characters */
  274.             extrattr = att_intensity;
  275.             break;
  276.         case NORMAL:              /* Normal characters */
  277.         default:
  278.             extrattr = 0;
  279.             break;
  280.     }
  281.     curattr = AddAtt();           /* Put the video attributes back together */
  282.  
  283. }
  284.  
  285.  
  286.  
  287. /* A D D V A T T R  --  Add an attribute bit to the current video attribute */
  288.  
  289. void AddVattr(unsigned char attr) {
  290.  
  291.     BrkAtt(curattr);              /* Break apart the current video attribute*/
  292.  
  293.     switch (attr) {               /* See what attribute wants to be added */
  294.         case BLINK:               /* Blinking attribute */
  295.             extrattr |= att_blink;
  296.             break;
  297.         case BOLD:                /* High intensity, bold, attribute */
  298.             extrattr |= att_intensity;
  299.             break;
  300.         case REVERSE:             /* Reversed attribute */
  301.             if (video_state == 0) {
  302.                 video_state = 1;
  303.                 baseattr = ( baseattr >> 4 | baseattr << 4);
  304.             }
  305.             break;
  306.         case UNDERLINED:          /* Underlined characters */
  307.             if (vidmode == 0x7)   /* Monochrom can underline */
  308.                 extrattr = att_underline;
  309.                                   /* others cant use reversed video */
  310.             else if (video_state == 0) {
  311.                 video_state = 1;
  312.                 baseattr = ( baseattr >> 4 | baseattr << 4);
  313.             }
  314.             break;
  315.         default:
  316.             break;
  317.     }
  318.     curattr = AddAtt();           /* Put the video attributes back together */
  319. }
  320.  
  321. /* S U B V A T T R  --  Remove attribute bit to the current video attribute */
  322.  
  323. void SubVattr(unsigned char attr) {
  324.  
  325.     BrkAtt(curattr);              /* Break apart the current video attribute*/
  326.  
  327.     switch (attr) {               /* See what video attribute to remove */
  328.         case BLINK:               /* Remove the blinking attribute */
  329.             extrattr &= ~att_blink;
  330.             break;
  331.         case BOLD:                /* Remove the high intensity, bold */
  332.             extrattr &= ~att_intensity;
  333.             break;
  334.         case REVERSE:             /* Remove reversed attribute */
  335.             if (video_state == 1) {
  336.                 video_state = 0;
  337.                 baseattr = ( baseattr >> 4 | baseattr << 4);
  338.             }
  339.             break;
  340.         case UNDERLINED:          /* Remove underlined attribute */
  341.             if (vidmode == 0x7)   /* Monochrome could have underlined */
  342.                 extrattr &= ~att_underline;
  343.                                   /* others couldn't remove reverse attribute*/
  344.             else if (video_state == 1) {
  345.                 video_state = 0;
  346.                 baseattr = ( baseattr >> 4 | baseattr << 4);
  347.             }
  348.             break;
  349.         default:
  350.             break;
  351.     }
  352.     curattr = AddAtt();           /* Put the video attributes back together */
  353. }
  354.  
  355.  
  356.  
  357. /* B R K A T T R -- Break an attribute into its video components */
  358.  
  359. void BrkAtt(unsigned char attribute) {
  360.  
  361.    extrattr = 0;                  /* Clear extra attributes */
  362.    baseattr = attribute;          /* Start specified base attribute */
  363.  
  364.    if (vidmode == 0x7) {          /* If a Monochrome monitor */
  365.       if (attribute & att_low_mask){ /* Any Low mask attributes on? */
  366.          baseattr |= att_normal;     /* if yes then set normal bits on */
  367.       }
  368.       else {                         /* else check other attributes */
  369.          if (attribute & att_underline){ /* Underline attribute ? */
  370.             extrattr |= att_underline;   /* yes then set underline bit */
  371.             if (attribute & 0x70)        /* Reverse video ? */
  372.                baseattr &= ~att_underline;  /* If yes then clear underline */
  373.             else                            /* monochrome can't do both */
  374.                baseattr |= att_normal;      /* Else set normal bits on */
  375.          }
  376.       }
  377.    }
  378.  
  379.    if (baseattr & att_intensity)  /* If bold attribute is on */
  380.       extrattr |= att_intensity;     /* then set intensity bit */
  381.  
  382.    if (baseattr & att_blink)      /* If blink attribute is on */
  383.       extrattr |= att_blink;         /* then set blink bit */
  384.  
  385.                                   /* Turn off blink,bold in base attribute */
  386.    baseattr &= ~(att_intensity + att_blink);
  387. }
  388.  
  389.  
  390. /* A D D A T R -- Build video attribute from base and extra attributes */
  391.  
  392. unsigned char AddAtt() {
  393.  
  394.    if (extrattr & att_underline)  /* If underline is requested */
  395.       baseattr &= ~att_low_mask;     /* Clear low mask */
  396.  
  397.    return(baseattr | extrattr);   /* return the or'ed attributes */
  398. }
  399.  
  400.  
  401. /* C H R W R I T E  -- Write a character to a row and column of the screen */
  402.  
  403. void ChrWrite( unsigned char chr ) {
  404.     unsigned char c[2], attr[2];
  405.     int row, ws;
  406.  
  407.     if (*GL == ASCII)             /* Check character set being used */
  408.        ;                             /* if regular ASCII then char is OK */
  409.     else if (*GL == SPECIAL) {       /* if using the special character */
  410.        if (chr > 94 && chr < 128)    /* then translate graphics characters */
  411.            chr = special_chars[ chr - 95];
  412.     }
  413.     else if (*GL == UK) {         /* If using the UK character set */
  414.        if (chr == '#')               /* then watch for the number sign */
  415.           chr = '£';                 /* translating it to British pound */
  416.     }
  417.  
  418.  
  419.     /* NOTE:  Inserting a character using this technique is *very* slow      */
  420.     /* for snowy CGA systems                                                 */
  421.     if (insertmode) {             /* If insert mode, scoot rest of line over */
  422.        StartScreen(cursy,cursx-1);/* Start direct video memory access        */
  423.  
  424.        c[0] = *screen;            /* Save character at current position      */
  425.        attr[0] = *(screen + 1);   /* Save attribute at current position      */
  426.        ws = 1;
  427.        for (row = cursx; row < columns; row ++) {
  428.  
  429.            c[ws] = *(screen + 2); /* Save character at next position        */
  430.            attr[ws] = *(screen + 3); /* Save attribute at next position     */
  431.            ws ^= 1;               /* Flop save char,attribute array index   */
  432.            *(screen + 2) = c[ws];  /* Write saved character and attribute   */
  433.            *(screen + 3) = attr[ws];
  434.            screen += 2;           /* Increment to next character position   */
  435.            scrchars++;            /* Increment the number of chars written  */
  436.        }
  437.        EndScreen();               /* Update screen in control programs      */
  438.     }
  439.  
  440.  
  441.     if (cursx > screenwid) {      /* If trying to go beyond the screen width */
  442.        if (autowrap) {               /* when autowrap is on */
  443.           ScrollUp();                /* scroll the screen up */
  444.           SetCurs(1,0);              /* set cursor to column 1 of next line */
  445.        }
  446.        else
  447.           cursx = screenwid;         /* else put the cursor on right margin */
  448.     }
  449.  
  450.     WriteOneChar(chr, cursy, cursx - 1);
  451.  
  452.     ++cursx;                      /* Increment the cursor X position */
  453.     PosCurs();                    /* Move the cursor to the new position */
  454.  
  455. }
  456.  
  457.  
  458. /* S E T S C R O L L  -- Establish the scrolling boundaries */
  459.  
  460. void SetScroll( register int top, register int bottom) {
  461.  
  462.     if (top == 0)                 /* If the top scroll boundary is 0 */
  463.        top = 1;                     /* interpret this as the top screen row */
  464.     if (bottom == 0)              /* If the bottom scroll boundary is 0 */
  465.        bottom = screenbot;          /* interpret this as bottom screen row */
  466.  
  467.                                   /* Set scrolling region if valid coords */
  468.     if (top > 0 && top <= screenbot && bottom >= top && bottom <= screenbot){
  469.         scrolltop = top;            /* save top boundary */
  470.         scrollbot = bottom;         /* save bottom boundary */
  471.         SetCurs(1,1);               /* this also homes the cursor */
  472.     }
  473. }
  474.  
  475.  
  476.  
  477.  
  478. /* S C R O L L D O W N  -- Move up a row scrolling if necessary */
  479.  
  480. void ScrollDown( )
  481. {
  482.  
  483.    if (cursy == scrolltop)        /* If on the top of the scrolling region */
  484.       IndexDown();                  /* scroll the rest of the region down */
  485.    else {                         /* Else */
  486.       --cursy;                      /* just decrement cursor Y position */
  487.       PosCurs();                    /* and request the reposition */
  488.    }
  489. }
  490.  
  491.  
  492. /* S C R O L L U P  -- Move down a row scrolling if necessary */
  493.  
  494. void ScrollUp( )
  495. {
  496.  
  497.    if (cursy == scrollbot)        /* If on the bottom of the scrolling region*/
  498.       IndexUp();                    /* scroll the rest of the region down */
  499.    else {                         /* Else */
  500.       ++cursy;                      /* just increment the cursor Y position */
  501.       PosCurs();                    /* and request the reposition */
  502.    }
  503. }
  504.  
  505.  
  506. /* I N D E X D O W N  -- Scroll the screen down */
  507.  
  508. void IndexDown( )
  509. {
  510.   register unsigned attr;
  511.  
  512.   attr = scbattr << 8;            /* Get the attribute for new line */
  513.                                   /* Call the BIOS to scroll the region */
  514.   interrupt10( 0x0701,attr,scrolltop << 8,(scrollbot << 8) | (columns - 1) );
  515.   PosCurs();                      /* Position the cursor */
  516. }
  517.  
  518. /* I N D E X U P  -- Scroll the screen up */
  519.  
  520. void IndexUp( )
  521. {
  522.   register unsigned attr;
  523.  
  524.   attr = scbattr << 8;            /* Get the attribute for new line */
  525.                                   /* Call the BIOS to scroll the region */
  526.   interrupt10( 0x0601,attr,scrolltop << 8,(scrollbot << 8) | (columns - 1));
  527.   PosCurs();                      /* Position the cursor */
  528. }
  529.  
  530.  
  531. /* S E T C U R S -- Set absolute cursor position on the logical screen */
  532.  
  533. void SetCurs(register int col, register int row)
  534. {
  535.    if (col == 0)                  /* If called with X coordinate = zero */
  536.       col = cursx;                  /* then default to current coordinate */
  537.    if (row == 0)                  /* If called with Y coordinate = zero */
  538.       row = cursy;                  /* then default to current coordinate */
  539.  
  540.    if (originmode) {              /* If origin mode is relative */
  541.       row += (scrolltop - 1);     /* adjust the row */
  542.      if (row < scrolltop || row > scrollbot)
  543.           return;                 /* Can not position cursor out of scroll */
  544.                                   /* region in relative cursor mode */
  545.    }
  546.                                   /* Can only position the cursor if it lies */
  547.                                   /* within the logical screen limits */
  548.    if (col <= screenwid && row <= screenbot ) {
  549.        cursx = col;               /* Set the X cursor coordinate, column */
  550.        cursy = row;               /* Set the Y cursor coordinate, row */
  551.        PosCurs();                 /* Request the physical positioning */
  552.    }
  553. }
  554.  
  555.  
  556. /* S E T R E L C U R S -- Set relative curs pos on the logical screen */
  557.  
  558. void SetRelCurs(register int col, register int row)
  559. {
  560.  
  561.    if (col == 0)                  /* If called with X coordinate = zero */
  562.       col = cursx;                  /* then default to current X coordinate */
  563.    else                           /* Else */
  564.       col = cursx + col;            /* add col value to X cursor position */
  565.                                     /* Note:  col can be negative */
  566.  
  567.    if (row == 0)                  /* If called with Y coordinate = zero */
  568.       row = cursy;                  /* then default to current Y coordinate */
  569.    else                           /* Else */
  570.       row = cursy + row;            /* add row value to Y cursor position */
  571.                                     /* Note:  row can be negative */
  572.  
  573.    if (originmode) {               /* If origin mode is relative */
  574.       row += (scrolltop - 1);      /* adjust the row */
  575.       if (row < scrolltop || row > scrollbot)
  576.           return;                  /* Can not position cursor out of scroll */
  577.    }                               /* region in relative cursor mode */
  578.  
  579.                                    /* Can only position the cursor if it lies */
  580.                                    /* within the logical screen limits */
  581.    if (col > 0 && col <= screenwid && row > 0 && row <= screenbot){
  582.        cursy = row;                /* Set the X cursor coordinate, column */
  583.        cursx = col;                /* Set the Y cursor coordinate, row */
  584.        PosCurs();                  /* Request the physical positioning */
  585.    }
  586. }
  587.  
  588. /* P O S C U R S -- Position the cursor on the physical screen */
  589.  
  590. void PosCurs()
  591. {
  592.    register int col = cursx;
  593.    register int row = cursy;
  594.  
  595.    if (col <= columns)            /* Check validity of requested column */
  596.       ;                             /* ok if column is within screen bounds */
  597.    else
  598.       col = columns;                /* else put cursor on the right bound */
  599.  
  600.    if (row <= lines)              /* Check validity of requested row */
  601.       ;                             /* ok if row is within screen bounds */
  602.    else
  603.       row = lines;                  /* else put cursor on the bottom */
  604.  
  605.     if (cursorvisible)            /* Only position the cursor if its visible */
  606.        interrupt10(0x0200,0,0,(row << 8) | --col );
  607. }
  608.  
  609.  
  610.  
  611. /* C L E A R S C R E E N -- Clear the screen setting it to a normal attr */
  612.  
  613. void ClearScreen()
  614. {
  615.     ClearBox(1, screentop, columns, screenbot, scbattr);
  616. }
  617.  
  618. /* C L E A R E O S -- Clear from the cursor to the end of screen */
  619.  
  620. void ClearEOS()
  621. {
  622.     ClearEOL();                   /* First clear to the End of the Line */
  623.     if (cursy < screenbot)        /* Then clear every line below it */
  624.        clearbox(1,cursy + 1,columns, screenbot, scbattr);
  625. }
  626.  
  627. /* C L E A R B O S -- Clear from the cursor to the beggining of screen */
  628.  
  629. void ClearBOS()
  630. {
  631.     ClearBOL();                   /* First clear to the Beginning of the Line */
  632.     if (cursy > screentop)        /* Then clear every line above it */
  633.        ClearBox(1,screentop,columns, cursy - 1, scbattr);
  634. }
  635.  
  636. /* C L E A R E O L -- Clear to the end of the current line */
  637.  
  638. void ClearEOL()
  639. {
  640.    ClearBox(cursx, cursy, columns, cursy, scbattr );
  641. }
  642.  
  643.  
  644. /* C L E A R B O L -- Clear to the beginning of the current line */
  645.  
  646. void ClearBOL()
  647. {
  648.    ClearBOX(1, cursy, cursx, cursy, scbattr );
  649. }
  650.  
  651.  
  652. /* C L E A R B O X -- Clear a window on the screen with the specified attr */
  653.  
  654. void ClearBox( unsigned char left, unsigned char top,
  655. unsigned char right, unsigned char bottom, unsigned char attr )
  656. {
  657.                                   /* Use BIOS scroll window function to clear*/
  658.     interrupt10( 0x0600,attr << 8,  /* a window to a specified attribute */
  659.        (top << 8) | (--left),(bottom << 8) | --right);
  660. }
  661.  
  662.  
  663. /* M A P C H A R S E T -- Map an established character set to current */
  664.  
  665. void MapCharSet( int charset ) {
  666.  
  667.    if (charset == 0)              /* If mapping G0 character set */
  668.       GL = &G0;                     /* Point the current char set,GL to G0 */
  669.    else if (charset == 1)         /* If mapping G1 character set */
  670.       GL = &G1;                     /* Point the current char set,GL, to G1 */
  671. }
  672.  
  673.  
  674. /* S E T C H A R S E T -- Establish a character set */
  675.  
  676. void SetCharSet( int gset, unsigned char set) {
  677.    int *charset;
  678.  
  679.    if (gset == 0)                 /* Check to see what character set is */
  680.       charset = &G0;                /* going to be set */
  681.    else if (gset == 1)
  682.       charset = &G1;
  683.    else
  684.       return;                     /* If not valid set then return */
  685.  
  686.    switch(set) {
  687.       case 'B':                   /* 'B' maps the character set to ASCII */
  688.          *charset = ASCII;          /* this is the normal character set */
  689.          break;
  690.       case 'A':                   /* 'A' maps the character set to UK */
  691.          *charset = UK;             /* only difference between UK and ASCII */
  692.          break;                     /* is the pound sign,  # = £ */
  693.       case '0':                   /* '0' maps the character set to SPECIAL */
  694.          *charset = SPECIAL;        /* this character set is the 'graphics' */
  695.          break;                     /* character set used for line drawing */
  696.       default:
  697.    }
  698. }
  699.  
  700. /* S A V E C U R S O R  --  Save the cursor description into memory */
  701.  
  702. void SaveCursor() {
  703.  
  704.    save.cursx = cursx;              /* Save the X cursor position */
  705.    save.cursy = cursy;              /* Save the Y cursor position */
  706.    save.GL = GL;                    /* Save the current mapped character set */
  707.    save.G0 = G0;                    /* Save G0 character set */
  708.    save.G1 = G1;                    /* Save G1 character set */
  709.    save.mode = originmode;          /* Also save the origin mode */
  710. }
  711.  
  712.  
  713. /* R E S T O R E C U R S O R  --  Restore the cursor description from memory */
  714.  
  715. void RestoreCursor() {
  716.  
  717.    cursx = save.cursx;              /* Restore the saved X cursor position */
  718.    cursy = save.cursy;              /* Restore the saved Y cursor position */
  719.    GL = save.GL;                    /* Restore the saved mapped character set */
  720.    G0 = save.G0;                    /* Restore the saved G0 character set */
  721.    G1 = save.G1;                    /* Restore the saved G1 character set */
  722.    originmode = save.mode;          /* Also restore the saved origin mode */
  723.    PosCurs();                       /* Then reposition the cursor */
  724. }
  725.  
  726.  
  727. /* S E T C U R S O R V I S I B I L I T Y -- Show/Hide the cursor */
  728.  
  729. void SetCursorVisibility( int mode ) {
  730.  
  731.    if (mode) {                    /* If invisible cursor is specified, then */
  732.       cursorvisible = 1;            /* the cursor will not appear on the */
  733.       SetCurs(0,0);                 /* terminal screen */
  734.    }
  735.    else {                         /* Else the cursor will be shown at the */
  736.       cursorvisible = 0;            /* current cursor position */
  737.       interrupt10(0x0200,0,0,lines << 8 );
  738.    }
  739. }
  740.  
  741.  
  742. /* S E T B A C K G R O U N D -- Set the background attribute */
  743.  
  744. void SetBackGround( int mode ) {
  745.    int reverse_screen = 0;        /* Flag to indicate screen is to be reversed*/
  746.    register int i;
  747.  
  748.  
  749.    if (mode) {                    /* If reversed background is specified, */
  750.       if (reversebackground != 1) { /* only reverse the screen if it is */
  751.          reverse_screen = 1;        /* not already set to reverse */
  752.          reversebackground = 1;
  753.       }
  754.    }
  755.    else {                         /* Else if normal background is specified */
  756.       if (reversebackground != 0) { /* only reverse the screen if it is */
  757.          reverse_screen = 1;        /* currently set to reverse */
  758.          reversebackground = 0;
  759.       }
  760.    }
  761.  
  762.    if (reverse_screen) {          /* If reverse screen flag is set */
  763.                                     /* first save the contents of screen */
  764.  
  765.       StartScreen(0,0);
  766.  
  767.       for (i = 0; i < lines * columns; i++){
  768.          screen++;
  769.          BrkAtt(*screen);           /* Break attribute apart and reverse it */
  770.          baseattr = ( baseattr >> 4 | baseattr << 4);
  771.          *screen++ = AddAtt();      /* Put attribute together as displayable */
  772.       }
  773.       scrchars = i;
  774.       EndScreen();
  775.  
  776.       BrkAtt(scbattr);              /* reverse the default character attr */
  777.       baseattr = ( baseattr >> 4 | baseattr << 4);
  778.       scbattr = AddAtt();
  779.       BrkAtt(curattr);              /* reverse the current character attr */
  780.       baseattr = ( baseattr >> 4 | baseattr << 4);
  781.       curattr = AddAtt();
  782.    }
  783. }
  784.  
  785.  
  786.  
  787. /* S E T C O L O R -- Set the screen color */
  788.  
  789. void SetColor() {
  790.    register int i;
  791.    unsigned char attr;
  792.  
  793.    BrkAtt(att_normal);            /* Break apart the current screen color */
  794.    attr = baseattr;               /* Save this attribute */
  795.  
  796.                                   /* Create the new screen attribute */
  797.    att_normal = curattr = scbattr = ( (backcolor << 4) | forecolor);
  798.    BrkAtt(att_normal);            /* and the new reverse attribute */
  799.    baseattr = ( baseattr >> 4 | baseattr << 4);
  800.    att_reverse = AddAtt();
  801.  
  802.    StartScreen(0,0);
  803.  
  804.    for (i = 0; i < lines * columns; i++){
  805.        screen++;
  806.        BrkAtt(*screen);           /* Break attribute apart and reverse it */
  807.        if (baseattr == attr) {    /* If this chars base attributes are the */
  808.            baseattr = att_normal; /* old screen color then this is a normal */
  809.        }                          /* character so set it to new normal attr */
  810.        else                       /* Else set this character to new reverse */
  811.            baseattr = att_reverse;
  812.        *screen++ = AddAtt();      /* Put attribute together as displayable */
  813.    }
  814.    scrchars = i;
  815.    EndScreen();
  816. }
  817.  
  818.  
  819. /* I N I T T A B S -- Initialize Tab stops to default settings */
  820.  
  821. void InitTabs() {
  822.    register int i;
  823.  
  824.    for( i = 1; i < 131; i++) {    /* Set tabs for mod 8 = 0 positions */
  825.       if ( i % 8 )                /* 9, 17, 26 .... */
  826.          deftabs[i+1] = tabs[i+1] = 0; /* Zero indicates no tab here */
  827.       else
  828.          deftabs[i+1] = tabs[i+1] = 1; /* One indicates a tab stop */
  829.    }
  830. }
  831.  
  832.  
  833. /* D O T A B -- Perform a tab */
  834.  
  835. void DoTab() {
  836.    register int i;
  837.                                   /* Look for next tab stop */
  838.    for (i = cursx + 1; i <= screenwid; i++) {
  839.       if ( tabs[i] == 1 ) {       /* If a tab stop is found */
  840.          SetCurs(i,cursy);          /* request cursor position here */
  841.          return;                    /* and finished */
  842.       }
  843.    }
  844. }
  845.  
  846. /* S E T T A B S T O P  -- set a tab stop at the current cursor position */
  847.  
  848. void SetTabStop() {
  849.  
  850.     tabs[cursx] = 1;              /* Mark current cursor position as tab stop*/
  851. }
  852.  
  853. /* C L E A R T A B S T O P  -- clear a tab stop at the current curs position */
  854.  
  855. void ClearTabStop() {
  856.  
  857.     tabs[cursx] = 0;              /* Clear current cursor position tab stop */
  858. }
  859.  
  860. /* C L E A R A L L T A B S  -- clear all tab stops */
  861.  
  862. void ClearAllTabs() {
  863.                                   /* Clear all of the tab stop marks */
  864.     memset(tabs,'\0',sizeof(tabs));
  865. }
  866.  
  867.  
  868. /* S E T S C R E E N W I D T H -- set the screen width */
  869.  
  870. void SetScreenWidth(int width) {
  871.  
  872.    if (width == 132)              /* When the screen is set to 132 columns */
  873.       screenwid = 132;              /* set the logical right boundary */
  874.    else if (width == 80)          /* Else if the screen width is 80 */
  875.       screenwid = 80;               /* set the logical right boundary */
  876.  
  877.                                   /* Setting the screen width also */
  878.    ClearScreen();                 /* Clears the screen */
  879.    originmode = 0;                /* Sets the origin mode to absolute */
  880.    SetScroll(0,0);                /* Resets the scrolling region */
  881.    SetCurs(1,1);                  /* Sets the cursor to the home position */
  882. }
  883.  
  884.  
  885. /* S T A R T S C R E E N -- Start a direct screen addressing "transaction" */
  886.  
  887. void StartScreen( register int row, register int col ) {
  888.     unsigned vscroff, vscrseg;
  889.  
  890.     if ( vidmode == 7 ) {         /* If in Monochrome video mode     */
  891.         scrseg = 0xb000;            /* Assume video segment of B000 */
  892.     }
  893.     else {                        /* If other mode then assumme */
  894.         scrseg = 0xb800;            /* video memory segment is B800 */
  895.     }
  896.  
  897.     scroff =((row*columns)+col)*2;/* Calculate offset from beginning of */
  898.                                     /* screen memory */
  899.     scrchars = 0;                 /* Initialize count of characters written */
  900.  
  901.     savebp = _BP;                 /* Save reg BP, in case old BIOS trashes it */
  902.                                   /* Query the address of video memory for */
  903.     _ES = scrseg;                 /* this process under Windows, DesQview, ... */
  904.     _DI = 0;                      /* ES:DI = assumed screen address */
  905.     _AH = 0xFE;                   /* Issue Video interrupt function FE */
  906.     geninterrupt(0x10);           /*  in order to check for control program */
  907.     vscroff = _DI;                /* ES:DI now holds actual address of screen*/
  908.     vscrseg = _ES;
  909.     _BP = savebp;                 /* Restore register BP */
  910.  
  911.     tvmode = 0;                   /* Assume no control program */
  912.     if (vscroff != 0 || vscrseg != scrseg) {
  913.         scrseg = vscrseg;           /* If address of screen is different from*/
  914.         scroff += vscroff;          /* assumed address then a control program*/
  915.         tvmode = 1;                 /* is present and has remapped the screen*/
  916.     }
  917.     else if (retracemode == 0)
  918.         ;                         /* No refresh wait for these situations */
  919.     else {
  920.                                   /* Wait till screen is refreshing */
  921.         while( (inportb(RETRACE) & 0x8) != 0 )
  922.             ;                     /* Wait till refresh is through */
  923.         while( (inportb(RETRACE) & 0x8) == 0 )
  924.             ;
  925.         outportb(0x3d8,0x25);     /* Turn off the screen refresh */
  926.     }
  927.                                   /* Construct a far pointer to video memory*/
  928.     (void far *)screen = MK_FP(scrseg,scroff);
  929.  
  930. }
  931.  
  932.  
  933. /* E N D S C R E E N -- End a direct screen addressing "transaction" */
  934.  
  935. void EndScreen( ) {
  936.                                   /* Values to turn the screen back on */
  937.     static unsigned char modeset[] = /* after video refresh is turned off */
  938.         { 0x2C,0x28,0x2D,0x29,0x2A,0x2E,0x1E,0x29,
  939.     } ;
  940.                                   /* If control program video update required*/
  941.     if (tvmode == 1 && scrchars > 0) {
  942.         _ES = scrseg;             /* Point ES:DI to beginning of video memory*/
  943.         _DI = scroff;             /*  to update */
  944.         _CX = scrchars;           /* CX holds the number of chars to update */
  945.         _AH = 0xFF;               /* Use function FF of BIOS video interrupt */
  946.         geninterrupt(0x10);       /*  to copy video buffer to screen */
  947.     }
  948.     else if (retracemode == 0)
  949.         ;                         /* Situations screen was not turned off */
  950.     else {                        /* Else if screen is off turn it back on */
  951.         outportb(0x3d8, modeset[vidmode]);
  952.     }
  953. }
  954.  
  955.  
  956. /* W R I T E O N E C H A R -- writes on character to video memory      */
  957. /* NOTE: this function does not shut down video refresh in order       */
  958. /* to avoid snow on CGA, so it is *much* faster than using StartScreen */
  959. /* and an EndScreen transaction for one character screen writes.       */
  960.  
  961. void WriteOneChar(unsigned char c, register int row, register int col ) {
  962.     unsigned vscroff, vscrseg;
  963.     int retrace_wait = 0;
  964.  
  965.     if ( vidmode == 7 ) {         /* If in Monochrome video mode     */
  966.         scrseg = 0xb000;            /* Assume video segment of B000 */
  967.     }
  968.     else {                        /* If other mode then assumme */
  969.         scrseg = 0xb800;            /* video memory segment is B800 */
  970.     }
  971.  
  972.     scroff =((row*columns)+col)*2;/* Calculate offset from beginning of */
  973.                                     /* screen memory */
  974.     savebp = _BP;                 /* Save reg BP, in case old BIOS trashes it */
  975.                                   /* Query the address of video memory for */
  976.     _ES = scrseg;                 /* this process under Windows, DesQview, ... */
  977.     _DI = 0;                      /* ES:DI = assumed screen address */
  978.     _AH = 0xFE;                   /* Issue Video interrupt function FE */
  979.     geninterrupt(0x10);           /*  in order to check for control program */
  980.     vscroff = _DI;                /* ES:DI now holds actual address of screen*/
  981.     vscrseg = _ES;
  982.     _BP = savebp;                 /* Restore register BP */
  983.  
  984.     tvmode = 0;                   /* Assume no control program */
  985.     if (vscroff != 0 || vscrseg != scrseg) {
  986.         scrseg = vscrseg;           /* If address of screen is different from*/
  987.         scroff += vscroff;          /* assumed address then a control program*/
  988.         tvmode = 1;                 /* is present and has remapped the screen*/
  989.     }
  990.     else if (retracemode == 0)
  991.         ;                         /* No refresh wait for these situations */
  992.     else {
  993.          retrace_wait = 1;         /* Else assume snowy CGA */
  994.     }
  995.                                   /* Construct a far pointer to video memory*/
  996.     (void far *)screen = MK_FP(scrseg,scroff);
  997.  
  998.     if ( retrace_wait == 0 ) {    /* If no snow then */
  999.         *screen++ = c;                /* write character into screen memory */
  1000.         *screen = curattr;            /* write attribute into screen memory */
  1001.     }
  1002.     else {                        /* Else if snowy CGA then try and sneak */
  1003.         if (inportb(RETRACE) & 0x8) { /* the character and attribute into */
  1004.             *screen++ = c;            /* video memory in between video */
  1005.             *screen = curattr;        /* refreshes */
  1006.         }
  1007.         else {
  1008.             while (inportb(RETRACE) & 0x8)
  1009.                 ;
  1010.             while (inportb(RETRACE) & 0x1)
  1011.                 ;
  1012.             *screen++ = c;
  1013.             *screen = curattr;
  1014.         }
  1015.     }
  1016.  
  1017.     if (tvmode == 1) {            /* If control program video update required*/
  1018.         _ES = scrseg;             /* Point ES:DI to beginning of video memory*/
  1019.         _DI = scroff;             /*  to update */
  1020.         _CX = 1;                  /* CX holds the number of chars to update */
  1021.         _AH = 0xFF;               /* Use function FF of BIOS video interrupt */
  1022.         geninterrupt(0x10);       /*  to copy video buffer to screen */
  1023.     }
  1024. }
  1025.  
  1026.  
  1027. /* S A V E S C R E E N -- Save the contents of the video screen */
  1028.  
  1029. void SaveScreen() {
  1030.  
  1031.     StartScreen(0,0);             /* Start the video direct access */
  1032.     movedata(scrseg, scroff,      /* Move the video memory to save buffer */
  1033.        FP_SEG(screen_save), FP_OFF(screen_save),
  1034.        lines * columns * 2 );
  1035.     scrchars = 0;                 /* Zero characters were written to screen */
  1036.     EndScreen();                  /* End the screen access */
  1037.     interrupt10(0x0200,0,0,lines << 8 ); /* Hide the cursor */
  1038. }
  1039.  
  1040. /* R E S T O R E S C R E E N -- Restore contents of the video screen */
  1041.  
  1042. void RestoreScreen() {
  1043.  
  1044.     StartScreen(0,0);             /* Start the video direct access */
  1045.                                   /* Move the save buffer to video memory */
  1046.     movedata(FP_SEG(screen_save), FP_OFF(screen_save),
  1047.        scrseg, scroff,
  1048.        lines * columns * 2 );
  1049.     scrchars = lines * columns;   /* Number of chars written to screen */
  1050.     EndScreen();                  /* End the screen access */
  1051.     PosCurs();                    /* Reposition the cursor */
  1052. }
  1053.  
  1054.  
  1055. /* V T P R I N T F -- print a formatted string to the video screen */
  1056.  
  1057. int vtprintf( int row, int col, int reverse, char *strformat, ... )
  1058. {
  1059.     unsigned attr;
  1060.     va_list argptr;
  1061.     char str[132];
  1062.     char *sptr = str;
  1063.     int it;
  1064.  
  1065.     if (reverse) {                /* If reversed attribute specified */
  1066.         attr = att_reverse;
  1067.     }
  1068.     else {                        /* Else use normal attribute */
  1069.         attr = att_normal;
  1070.     }
  1071.  
  1072.     va_start( argptr, format );   /* Start variable length argument list */
  1073.     StartScreen(row,col);         /* Start a screen update */
  1074.     scrchars = vsprintf( str, strformat, argptr ); /* Format the string */
  1075.     while (*sptr != '\0') {       /* Move the formatted string */
  1076.         *screen++ = *sptr++;         /* to video memory */
  1077.         *screen++ = attr;
  1078.     }
  1079.     EndScreen();                  /* End the screen update */
  1080.     va_end(argptr);               /* End the va_start */
  1081.     return(scrchars);             /* Return number of characters written */
  1082. }
  1083.  
  1084.  
  1085.  
  1086. /* I N T E R R U P T 1 0  -- Call on the BIOS video software interrupt */
  1087.  
  1088. void interrupt10(unsigned ax,unsigned bx,unsigned cx,unsigned dx){
  1089.    register unsigned savesi;      /* Force compiler to save contents of */
  1090.    register unsigned savedi;      /* SI and DI registers on the stack */
  1091.    static unsigned savebp;
  1092.  
  1093.    savebp = _BP;                  /* Save BP since some BIOS'es may destroy it*/
  1094.    _CX = cx;                      /* Load contents of register parameters */
  1095.    _DX = dx;
  1096.    _BX = bx;
  1097.    _AX = ax;
  1098.    geninterrupt(0x10);            /* Issue Video interrupt */
  1099.    _BP = savebp;                  /* Restore BP register */
  1100. }
  1101.