home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_01_03 / 1n03073a < prev    next >
Text File  |  1990-07-09  |  16KB  |  675 lines

  1. /*
  2.     Screen
  3.         2.50
  4.         19-Jun-1990
  5.         ANSI C for MS-DOS w/monochrome or color text
  6.         display
  7.  
  8.         Provides a set of functions for manipulating a
  9.         text display. To drastically improve the speed
  10.         of this module, NO RANGE CHECKING is done!
  11.         Invalid line/column values may cause portions
  12.         of non-video memory to be corrupted!
  13.  
  14.         Written by Scott Robert Ladd. Released into
  15.         the public domain.
  16. */
  17.  
  18. #include "conio.h"
  19. #include "dos.h"
  20. #include "screen.h"
  21. #include "stdarg.h"
  22. #include "stdio.h"
  23. #include "stdlib.h"
  24. #include "string.h"
  25.  
  26. static ScrType      VideoType    = ST_UNKNOWN;
  27. static ScrMode      VideoMode    = SM_UNKNOWN;
  28. static ScrMode      OriginalMode = SM_UNKNOWN;
  29. static ScrAccess    AccessMode   = SA_DIRECT;
  30. static unsigned int Width        = 0;
  31. static unsigned int Length       = 0;
  32. static unsigned int BaseAdr      = 0;
  33. static unsigned int CursorShape  = 0;
  34. static int          CursorHidden = 0;
  35. static int *        SavedScreen  = NULL;
  36. static unsigned int SavedCursPos = 0;
  37. static int          SavedCursShp = 0;
  38. static union REGS   regs;
  39.  
  40. #if !defined(MK_FP)
  41.     #define MK_FP(seg,off) (void far *)(((long)/
  42.             (seg) << 16L) | (long)(off))
  43. #endif
  44.  
  45. ScrType ScrOpen(void)
  46.     {
  47.     int i, status_changed;
  48.     unsigned char orig_status;
  49.     int far * vmemptr;
  50.  
  51.     /* Attempt to identify the type of video adapter installed.
  52.        Call VGA "Identify Adapter Service" first */
  53.  
  54.     regs.h.ah = 0x1A;
  55.     regs.h.al = 0;
  56.     int86(0x10,®s,®s);
  57.  
  58.     if (regs.h.al == 0x1A)
  59.         {
  60.         switch (regs.h.bl)
  61.             {
  62.             case 1 :
  63.                 VideoType = ST_MDA;
  64.                 break;
  65.  
  66.             case 2 :
  67.                 VideoType = ST_CGA;
  68.                 break;
  69.  
  70.             case 4 :
  71.             case 5 :
  72.                 VideoType = ST_EGA;
  73.                 break;
  74.  
  75.             case 7 :
  76.             case 8 :
  77.                 VideoType = ST_VGA;
  78.                 break;
  79.  
  80.             case 10:
  81.             case 11:
  82.             case 12:
  83.                 VideoType = ST_MCGA;
  84.                 break;
  85.  
  86.             default:
  87.                 return 1;
  88.             }
  89.         }
  90.     else
  91.         {
  92.         /* VGA services not available -- maybe it's EGA */
  93.  
  94.         regs.h.ah = 0x12;
  95.         regs.x.bx = 0x0010;
  96.         int86(0x10,®s,®s);
  97.  
  98.         /* if BX is 0x10, we have an EGA */
  99.  
  100.         if (regs.x.bx != 0x10)
  101.             VideoType = ST_EGA;
  102.         else
  103.             {
  104.             /* check two-bit "monitor type" setting in equipment word */
  105.  
  106.             int86(0x11,®s,®s);
  107.  
  108.             switch ((regs.h.al & 0x30) >> 4)
  109.                 {
  110.                 case 0 :
  111.                     return 1;
  112.  
  113.                 case 1 :
  114.                 case 2 :
  115.                     VideoType = ST_CGA;
  116.                     break;
  117.  
  118.                 case 3 :
  119.                     /* if we have a mono adapter, a Hercules can be
  120.                        differentiated from an MDA by seeing if the high bit
  121.                        of the status register changes */
  122.  
  123.                     status_changed = 0;
  124.  
  125.                     orig_status = (unsigned char)(inp(0x03BA) & 0x80);
  126.  
  127.                     for (i=0; (i<30000) && (!status_changed); ++i)
  128.                         if (orig_status != (unsigned char)/
  129.                                            (inp(0x03BA) & 0x80))
  130.                             status_changed = 1;
  131.  
  132.                     if (status_changed)
  133.                         VideoType = ST_HGC;
  134.                     else
  135.                         VideoType = ST_MDA;
  136.                 }
  137.             }
  138.         }
  139.  
  140.     /* store the segment of video memory */
  141.  
  142.     if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
  143.         BaseAdr = 0xB000;
  144.     else
  145.         BaseAdr = 0xB800;
  146.  
  147.     /* save the original cursor shape */
  148.  
  149.     regs.h.ah = 3;
  150.     regs.h.bh = 0;
  151.  
  152.     int86(0x10,®s,®s);
  153.  
  154.     SavedCursShp = regs.x.cx;
  155.  
  156.     /* and the orihginal cursor position */
  157.  
  158.     regs.h.ah = 3;
  159.     regs.h.bh = 0;
  160.  
  161.     int86(0x10,®s,®s);
  162.  
  163.     SavedCursPos = regs.x.dx;
  164.  
  165.     /* find width of the orginal screen */
  166.  
  167.     regs.h.ah = 0x0F;
  168.     int86(0x10,®s,®s);
  169.  
  170.     Width = (int) regs.h.ah;
  171.  
  172.     /* find length of the original screen */
  173.  
  174.     regs.x.ax = 0x1130;
  175.     regs.h.bh = 0;
  176.     regs.x.dx = 0;
  177.  
  178.     int86(0x10,®s,®s);
  179.  
  180.     Length = regs.x.dx + 1;
  181.  
  182.     if (Length == 1)
  183.         Length = 25;
  184.  
  185.     /* now, allocate a buffer to hold the original
  186.        screen contents... */
  187.  
  188.     SavedScreen = malloc(Length * Width * 2);
  189.  
  190.     /* ...and save the original screen */
  191.  
  192.     if (SavedScreen != NULL)
  193.         for (i = 0; i < Length * Width; i++)
  194.             {
  195.             vmemptr = MK_FP(BaseAdr,i << 1);
  196.             SavedScreen[i] = *vmemptr;
  197.             }
  198.  
  199.     /* make note of the original screen mode */
  200.  
  201.     switch (Width)
  202.         {
  203.         case 40:
  204.             OriginalMode = SM_25x40;
  205.             break;
  206.  
  207.         case 80:
  208.             switch (Length)
  209.                 {
  210.                 case 25:
  211.                     OriginalMode = SM_25x80;
  212.                     break;
  213.                 case 30:
  214.                     OriginalMode = SM_30x80;
  215.                     break;
  216.                 case 43:
  217.                     OriginalMode = SM_43x80;
  218.                     break;
  219.                 case 50:
  220.                     OriginalMode = SM_50x80;
  221.                 }
  222.         }
  223.  
  224.     /* if we have an identifiable screen mode, make it
  225.        the current mode */
  226.  
  227.     if (OriginalMode != -1)
  228.         VideoMode = OriginalMode;
  229.  
  230.     /* mark the cursor as visible */
  231.  
  232.     CursorHidden = 0;
  233.  
  234.     /* get outa here */
  235.  
  236.     return VideoType;
  237.     }
  238.  
  239. void ScrClose()
  240.     {
  241.     int i;
  242.     int far * vmemptr;
  243.  
  244.     /* reset to orginal mode */
  245.  
  246.     if ((OriginalMode != VideoMode) &&/
  247.         (OriginalMode != SM_UNKNOWN))
  248.         ScrSetMode(OriginalMode);
  249.  
  250.     /* restore original screen contents */
  251.  
  252.     if (SavedScreen != NULL)
  253.         for (i = 0; i < Length * Width; i++)
  254.             {
  255.             vmemptr = MK_FP(BaseAdr,i << 1);
  256.             *vmemptr = SavedScreen[i];
  257.             }
  258.  
  259.     /* restore original cursor shape */
  260.  
  261.     regs.h.ah = 1;
  262.     regs.x.cx = SavedCursShp;
  263.  
  264.     int86(0x10,®s,®s);
  265.  
  266.     /* restore original cursor position */
  267.  
  268.     regs.h.ah = 2;
  269.     regs.h.bh = 0;
  270.     regs.x.dx = SavedCursPos;
  271.  
  272.     int86(0x10,®s,®s);
  273.     }
  274.  
  275. int ScrSetMode(ScrMode mode)
  276.     {
  277.     /* don't change to the current mode */
  278.  
  279.     if (VideoMode == mode)
  280.         return 1;
  281.  
  282.     /* if we don't know the type of screen we have,
  283.        don't change mode */
  284.  
  285.     if (OriginalMode == SM_UNKNOWN)
  286.         return 1;
  287.  
  288.     /* make sure the mode requested is valid */
  289.  
  290.     if ((mode < SM_25x40) || (mode > SM_50x80))
  291.         return 0;
  292.  
  293.     /* set modes */
  294.  
  295.     switch (mode)
  296.         {
  297.         case SM_25x40:
  298.             if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
  299.                 return 0;
  300.             else
  301.                 {
  302.                 regs.x.ax = 0x0001;
  303.                 int86(0x10,®s,®s);
  304.  
  305.                 Length = 25;
  306.                 Width  = 40;
  307.                 }
  308.  
  309.             break;
  310.  
  311.         case SM_25x80:
  312.             if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
  313.                 {
  314.                 regs.x.ax = 0x0007;
  315.                 int86(0x10,®s,®s);
  316.                 }
  317.             else /* color */
  318.                 {
  319.                 regs.x.ax = 0x0003;
  320.                 int86(0x10,®s,®s);
  321.  
  322.                 switch (VideoType)
  323.                     {
  324.                     case ST_CGA:
  325.                         regs.x.ax = 0x1112;
  326.                         int86(0x10,®s,®s);
  327.                         break;
  328.  
  329.                     case ST_EGA:
  330.                         regs.x.ax = 0x1111;
  331.                         int86(0x10,®s,®s);
  332.                         break;
  333.  
  334.                     case ST_VGA:
  335.                         regs.x.ax = 0x1114;
  336.                         int86(0x10,®s,®s);
  337.                         break;
  338.  
  339.                     default:
  340.                         return 0;
  341.                     }
  342.                 }
  343.  
  344.  
  345.             Length = 25;
  346.             Width  = 80;
  347.  
  348.             break;
  349.  
  350.         case SM_30x80:
  351.             if (VideoType == ST_VGA)
  352.                 {
  353.                 regs.x.ax = 0x0003;
  354.                 int86(0x10,®s,®s);
  355.  
  356.                 regs.x.ax = 0x1111;
  357.                 regs.h.bl = 0;
  358.                 int86(0x10,®s,®s);
  359.  
  360.                 Length = 30;
  361.                 Width  = 80;
  362.                 }
  363.             else
  364.                 return 0;
  365.  
  366.             break;
  367.  
  368.         case SM_43x80:
  369.         case SM_50x80:
  370.             if ((VideoType >= ST_EGA) || (VideoType <= ST_VGA))
  371.                 {
  372.                 regs.x.ax = 0x0003;
  373.                 int86(0x10,®s,®s);
  374.  
  375.                 regs.x.ax = 0x1112;
  376.                 regs.h.bl = 0;
  377.                 int86(0x10,®s,®s);
  378.  
  379.                 if (VideoType == ST_EGA)
  380.                     Length = 43;
  381.                 else
  382.                     Length = 50;
  383.  
  384.                 Width  = 80;
  385.                 }
  386.             else
  387.                 return 0;
  388.  
  389.             break;
  390.  
  391.         default:
  392.             return 0;
  393.         }
  394.  
  395.     VideoMode = mode;
  396.  
  397.     ScrClear();
  398.  
  399.     return 1;
  400.     }
  401.  
  402. ScrMode ScrGetMode(void)
  403.     {
  404.     return VideoMode;
  405.     }
  406.  
  407. void ScrSetAccess(ScrAccess access)
  408.     {
  409.     AccessMode = access;
  410.     }
  411.  
  412. ScrAccess ScrGetAccess(void)
  413.     {
  414.     return AccessMode;
  415.     }
  416.  
  417. void ScrDimensions(unsigned int * wid, unsigned int * len)
  418.     {
  419.     *wid = Width;
  420.     *len = Length;
  421.     }
  422.  
  423. void ScrCursorHide(void)
  424.     {
  425.  
  426.     if (CursorHidden)
  427.         return;
  428.  
  429.     /* save the current cursor shape */
  430.  
  431.     regs.h.ah = 3;
  432.     regs.h.bh = 0;
  433.  
  434.     int86(0x10,®s,®s);
  435.  
  436.     CursorShape = regs.x.cx;
  437.  
  438.     /* make the cursor invisible */
  439.  
  440.     regs.h.ah = 1;
  441.     regs.x.cx = 0x2000;
  442.  
  443.     int86(0x10,®s,®s);
  444.  
  445.     CursorHidden = 1;
  446.     }
  447.  
  448. void ScrCursorUnhide(void)
  449.     {
  450.     if (!CursorHidden)
  451.         return;
  452.  
  453.     /* restore the cursor shape */
  454.  
  455.     regs.h.ah = 1;
  456.     regs.x.cx = CursorShape;
  457.  
  458.     int86(0x10,®s,®s);
  459.  
  460.     CursorHidden = 0;
  461.     }
  462.  
  463. void ScrCursorSetPos(unsigned int line, unsigned int col)
  464.     {
  465.     regs.h.ah = 2;
  466.     regs.h.bh = 0;
  467.     regs.h.dh = (char)line;
  468.     regs.h.dl = (char)col;
  469.  
  470.     int86(0x10,®s,®s);
  471.     }
  472.  
  473. void ScrCursorGetPos(unsigned int * line, unsigned int * col)
  474.     {
  475.     regs.h.ah = 3;
  476.     regs.h.bh = 0;
  477.  
  478.     int86(0x10,®s,®s);
  479.  
  480.     *line = regs.h.dh;
  481.     *col  = regs.h.dl;
  482.     }
  483.  
  484. void ScrPutChar(unsigned int line, unsigned int col,
  485.                 unsigned char attr, char ch)
  486.     {
  487.     unsigned int far * vmemptr;
  488.  
  489.     if (AccessMode == SA_DIRECT)
  490.         {
  491.         vmemptr  = MK_FP(BaseAdr,((line * Width << 1) +
  492.                    (col << 1)));
  493.         *vmemptr = ((unsigned int)attr << 8) | (unsigned char)ch;
  494.         }
  495.     else
  496.         {
  497.         regs.h.ah = 2;
  498.         regs.h.bh = 0;
  499.         regs.h.dh = (char)line;
  500.         regs.h.dl = (char)col;
  501.  
  502.         int86(0x10,®s,®s);
  503.  
  504.         regs.h.ah = 9;
  505.         regs.h.al = ch;
  506.         regs.h.bh = 0;
  507.         regs.h.bl = attr;
  508.         regs.x.cx = 1;
  509.  
  510.         int86(0x10,®s,®s);
  511.         }
  512.     }
  513.  
  514. void ScrGetChar(unsigned int line, unsigned int col,
  515.                 unsigned char * attr, char * ch)
  516.     {
  517.     unsigned int far * vmemptr;
  518.  
  519.     if (AccessMode == SA_DIRECT)
  520.         {
  521.         vmemptr = MK_FP(BaseAdr,((line * Width << 1) +
  522.                   (col << 1)));
  523.  
  524.         *attr = (unsigned char)(*vmemptr >> 8);
  525.         *ch   = (char)(*vmemptr & 0xFF);
  526.         }
  527.     else
  528.         {
  529.         regs.h.ah = 2;
  530.         regs.h.bh = 0;
  531.         regs.h.dh = (char)line;
  532.         regs.h.dl = (char)col;
  533.  
  534.         int86(0x10,®s,®s);
  535.  
  536.         regs.h.ah = 8;
  537.         regs.h.bh = 0;
  538.  
  539.         int86(0x10,®s,®s);
  540.  
  541.         *attr = regs.h.ah;
  542.         *ch   = regs.h.al;
  543.         }
  544.     }
  545.  
  546. void ScrPrintf(unsigned int line, unsigned int col,
  547.                unsigned char attr, char * format, ...)
  548.     {
  549.     va_list args;
  550.     char * buffer;
  551.  
  552.     buffer = malloc(256);
  553.  
  554.     va_start(args, format);
  555.  
  556.     vsprintf(buffer,format,args);
  557.      
  558.     va_end(args);
  559.      
  560.     ScrPutStr(line, col, attr, buffer);
  561.  
  562.     free(buffer);
  563.     }
  564.  
  565. void ScrPutStr(unsigned int line, unsigned int col,
  566.                unsigned char attr, char * str)
  567.     {
  568.     unsigned int i;
  569.  
  570.     for (i = 0; (str[i] != '\000') && (i < Width); ++i)
  571.         ScrPutChar(line, col + i, attr, str[i]);
  572.     }
  573.  
  574. void ScrDrawBox(unsigned int topLine, unsigned int leftCol,
  575.                 unsigned int btmLine, unsigned int rightCol,
  576.                 unsigned char attr, BoxType typeBox)
  577.     {
  578.     char v = 0, h = 0;
  579.     unsigned int  c, l;
  580.  
  581.     if ((typeBox == BT_NONE)
  582.     || (leftCol >= rightCol)
  583.     || (topLine >= btmLine))
  584.         return;
  585.  
  586.     switch (typeBox)
  587.         {
  588.         case BT_SINGLE:
  589.             v = '\xB3';
  590.             h = '\xC4';
  591.             ScrPutChar(topLine, leftCol,  attr, '\xDA');
  592.             ScrPutChar(topLine, rightCol, attr, '\xBF');
  593.             ScrPutChar(btmLine, leftCol,  attr, '\xC0');
  594.             ScrPutChar(btmLine, rightCol, attr, '\xD9');
  595.             break;
  596.         case BT_DOUBLE:
  597.             v = '\xBA';
  598.             h = '\xCD';
  599.             ScrPutChar(topLine, leftCol,  attr, '\xC9');
  600.             ScrPutChar(topLine, rightCol, attr, '\xBB');
  601.             ScrPutChar(btmLine, leftCol,  attr, '\xC8');
  602.             ScrPutChar(btmLine, rightCol, attr, '\xBC');
  603.             break;
  604.         case BT_SOLID:
  605.             v = '\xDB';
  606.             h = '\xDB';
  607.             ScrPutChar(topLine, leftCol,  attr, '\xDB');
  608.             ScrPutChar(topLine, rightCol, attr, '\xDB');
  609.             ScrPutChar(btmLine, leftCol,  attr, '\xDB');
  610.             ScrPutChar(btmLine, rightCol, attr, '\xDB');
  611.         }
  612.  
  613.     for (c = leftCol + 1; c < rightCol; ++c)
  614.         {
  615.         ScrPutChar(topLine, c, attr, h);
  616.         ScrPutChar(btmLine, c, attr, h);
  617.         }
  618.  
  619.     for (l = topLine + 1; l < btmLine; ++l)
  620.         {
  621.         ScrPutChar(l, leftCol,  attr, v);
  622.         ScrPutChar(l, rightCol, attr, v);
  623.         }
  624.     }
  625.  
  626.  
  627. void ScrScrollUp(unsigned int topLine, unsigned int leftCol,
  628.                  unsigned int btmLine, unsigned int rightCol,
  629.                  unsigned char attr, unsigned int noOfLines)
  630.     {
  631.     regs.h.ah = 6;
  632.     regs.h.al = (unsigned char)noOfLines;
  633.     regs.h.bh = attr;
  634.     regs.h.ch = topLine;
  635.     regs.h.cl = leftCol;
  636.     regs.h.dh = btmLine;
  637.     regs.h.dl = rightCol;
  638.  
  639.     int86(0x10,®s,®s);
  640.     }
  641.  
  642. void ScrScrollDown(unsigned int topLine, unsigned int leftCol,
  643.                    unsigned int btmLine, unsigned int rightCol,
  644.                    unsigned char attr, unsigned int noOfLines)
  645.     {
  646.     regs.h.ah = 7;
  647.     regs.h.al = (unsigned char)noOfLines;
  648.     regs.h.bh = attr;
  649.     regs.h.ch = topLine;
  650.     regs.h.cl = leftCol;
  651.     regs.h.dh = btmLine;
  652.     regs.h.dl = rightCol;
  653.  
  654.     int86(0x10,®s,®s);
  655.     }
  656.  
  657. void ScrClear()
  658.     {
  659.     unsigned int l, c;
  660.  
  661.     for (l = 0; l < Length; ++l)
  662.         for (c = 0; c < Width; ++c)
  663.             ScrPutChar(l,c,7,' ');
  664.  
  665.     ScrCursorSetPos(0,0);
  666.     }
  667.  
  668. void ScrClearLine(unsigned int line, unsigned int col)
  669.     {
  670.     unsigned int c;
  671.  
  672.     for (c = col; c < Width; ++c)
  673.         ScrPutChar(line,c,7,' ');
  674.     }
  675.