home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_09_08 / 9n08035a < prev    next >
Text File  |  1991-04-23  |  9KB  |  397 lines

  1.  
  2. /* IBM bios screen control package
  3.    Copyright Dave Newman 1991 
  4.    Permission to use these routines for any reason
  5.    is granted as long as this copyright notice is
  6.    included.
  7.    This should compile on any DOS C compiler
  8.    that supports int86() */
  9.  
  10. /* declarations for these functions */
  11. #include <bios.h>
  12. /* needed for REGS union */
  13. #include <dos.h>
  14.  
  15.  
  16. /* these variables are global */
  17. /* these vars hold information about the system.
  18.    They are valid after the call to bios_open().
  19.    If the information in them is not relevant,        
  20.    the call to bios_open() is not necessary. */
  21. int cur_mode;         /* current display mode */
  22. int cur_page;         /* current display page */
  23. int num_cols;         /* number of cols on screen */
  24.  
  25. /* adapter types */
  26. char    cga,         /* color graphics adapter */
  27.    ega,          /* Enhanced graphics adapter */
  28.    vga,          /* video graphics array */
  29.    mcga,         /* PS/2 mcga display */
  30.    mono,         /* just black and white */
  31.    herc,         /* hercules graphics adapter */
  32.    none;         /* no monitor at all */
  33.  
  34. char   color,    /* is using a color monitor */
  35.    b_w;          /* or black+white? */
  36.  
  37. /* these vars hold info about the cursor position
  38.    and the current color/attribute being used.
  39.    (no bios_open call necessary) */
  40.  
  41. /* display attribute (use to change colors) */
  42. unsigned char cur_attr;
  43. int cur_row;         /* current row of cursor */
  44. int cur_col;         /* current column of cursor */
  45. /* end global values */
  46.  
  47. /* bios open function.
  48.    Set up the initial values in all of the variables
  49.    above. */
  50. void bios_open()
  51.    {
  52.    union REGS regs;
  53.    void vtest(void);
  54.  
  55.    /* determine the current display mode */
  56.    regs.x.ax = 0x0f00;
  57.    int86(0x10,®s,®s);
  58.    cur_mode = regs.h.al;
  59.    cur_page = regs.h.bh;
  60.    num_cols = regs.h.ah;
  61.  
  62.    /* determine the type of display in the system
  63.       and set it's type value to 1
  64.       on return the proper video adapter variable
  65.       will be set as will the color or b_w value */
  66.    none=mono=herc=cga=ega=vga=mcga=color=b_w=0;
  67.    vtest();
  68.    }
  69.  
  70. /* and a bios_close function just for the sake of
  71.    consistency. Please use this function. It may do
  72.    something one day (like restore the screen
  73.    to the previous state) */
  74. void bios_close()
  75.    {}
  76.  
  77. /* change value of cursor.
  78.    range 0x0000 to 0xFFFF (FFFF == OFF) */
  79. void bios_cursor(int state)
  80.    {
  81.    union REGS regs;
  82.    regs.h.ah = 1;
  83.    /* ch == start line. cl == end line */
  84.    regs.x.cx = state;
  85.    int86(0x10,®s,®s);
  86.    }
  87.  
  88. /* move cursor to row,col */
  89. void bios_move(int row,int col)
  90.    {
  91.    union REGS regs;
  92.  
  93.    regs.h.dh = row;
  94.    regs.h.dl = col;
  95.    regs.h.ah = 2;
  96.    regs.h.bh = cur_page;
  97.    int86(0x10,®s,®s);
  98.    cur_row = row;
  99.    cur_col = col;
  100.    }
  101.  
  102.  
  103. /* scroll active page up.
  104.    use to clear boxes on screen */
  105. void bios_scroll_up(
  106.              int count,int sr,int sc,int er,int ec)
  107.    {
  108.    union REGS regs;
  109.  
  110.    regs.h.al = count;
  111.    regs.h.ch = sr;
  112.    regs.h.cl = sc;
  113.    regs.h.dh = er;
  114.    regs.h.dl = ec;
  115.    regs.h.bh = cur_attr;
  116.    regs.h.ah = 6;
  117.    int86(0x10,®s,®s);
  118.    }
  119.  
  120. /* scroll active page down.
  121.    good for clearing entire screen */
  122. void bios_scroll_dn(
  123.              int count,int sr,int sc,int er,int ec)
  124.    {
  125.    union REGS regs;
  126.  
  127.    regs.h.al = count;
  128.    regs.h.ch = sr;
  129.    regs.h.cl = sc;
  130.    regs.h.dh = er;
  131.    regs.h.dl = ec;
  132.    regs.h.bh = cur_attr;
  133.    regs.h.ah = 7;
  134.    int86(0x10,®s,®s);
  135.    }
  136.  
  137. /* return current video state */
  138. int bios_mode()
  139.    {
  140.    union REGS regs;
  141.  
  142.    regs.h.ah = 15;
  143.    int86(0x10,®s,®s);
  144.    cur_mode = regs.h.al;
  145.    return(regs.h.al);
  146.    }
  147.  
  148. /* return current cursor position
  149.    into global values */
  150. void bios_rc()
  151.    {
  152.    union REGS regs;
  153.  
  154.    regs.h.bh = cur_page;
  155.    regs.h.ah = 3;
  156.    int86(0x10,®s,®s);
  157.    cur_row = regs.h.dh;
  158.    cur_col = regs.h.dl;
  159.    }
  160.  
  161.  
  162. /* print char (attribute at r/c unchanged)
  163.    at current cursor position */
  164. void bios_putchar(char ch)
  165.    {
  166.    union REGS regs;
  167.  
  168.    regs.h.bh = cur_page;
  169.    regs.x.cx =1;
  170.    regs.h.al = ch;
  171.    regs.h.ah = 0x0a;
  172.    int86(0x10,®s,®s);
  173.    }
  174.  
  175. /* print char & attribute at cusor position */
  176. void bios_pchatt(char ch)
  177.    {
  178.    union REGS regs;
  179.  
  180.    regs.h.bh = cur_page;
  181.    regs.h.bl = cur_attr;
  182.    regs.x.cx = 1;
  183.    regs.h.al = ch;
  184.    regs.h.ah = 0x09;
  185.    int86(0x10,®s,®s);
  186.    }
  187.  
  188. /* this function replaces puts()
  189.    (but no linefeed on end) 
  190.    recognises LF,CR,BS and TAB 
  191.    Use sprintf() with this to simulate printf()
  192.    (need large buffer too) */
  193. void bios_puts(char *str)
  194.    {
  195.    int i;
  196.    bios_rc();
  197.    while(*str)
  198.       {
  199.       if(*str == 10) /* do LF */
  200.          {
  201.          cur_col = 0;
  202.          cur_row++;
  203.          bios_move(cur_row,cur_col);
  204.          str++;
  205.          if(!*str)
  206.             break;
  207.          }
  208.       if(*str == 8)   /* do BS */
  209.          {
  210.          if(cur_col == 0)
  211.             cur_row--;
  212.          else
  213.             cur_col--;
  214.          bios_move(cur_row,cur_col);
  215.          str++;
  216.          if(!*str)
  217.             break;
  218.          }
  219.       if(*str == 13)   /* do CR */
  220.          {
  221.          cur_col = 0;
  222.          bios_move(cur_row,cur_col);
  223.          str++;
  224.          if(!*str)
  225.             break;
  226.          }
  227.       if(*str == 9)   /* do TAB */
  228.          {
  229.          i = (1+(cur_col / 8)) *8;
  230.          while(cur_col < i)
  231.             {
  232.             bios_pchatt(' ');
  233.             cur_col++;
  234.             bios_move(cur_row,cur_col);
  235.             }      
  236.          str++;
  237.          if(!*str)
  238.             break;
  239.          }
  240.  
  241.       bios_pchatt(*str);
  242.       str++;
  243.       cur_col++;
  244.       bios_move(cur_row,cur_col);
  245.       }
  246.    }
  247.  
  248. /* returns the char under the cursor */
  249. char bios_rdchar()
  250.    {
  251.    union REGS regs;
  252.  
  253.    regs.h.bh = cur_page;
  254.    regs.h.ah = 8;
  255.    int86(0x10,®s,®s);
  256.    return((char)regs.h.al);
  257.    }
  258.  
  259. /* returns char AND attribute under cursor */
  260. int bios_rdchatt()
  261.    {
  262.    union REGS regs;
  263.  
  264.    regs.h.bh = cur_page;
  265.    regs.h.ah = 8;
  266.    int86(0x10,®s,®s);
  267.    /* char is in AL, attribute is in AH */
  268.    return((int)regs.x.ax);
  269.    }
  270.  
  271. /* this function was written by Andrew Binstock.
  272.    The text of the function
  273.    and the supporting artical can be found in 
  274.    the magazine: C Gazette, Summer 1989 issue.
  275.    (v4 #1) p27.
  276.    Only minor modifications have been made by me.
  277. */
  278. /* test to determine type of
  279.    video adapter in the system */
  280. void vtest()
  281.    {
  282.    union REGS regs;
  283.    unsigned char hold_a_byte;
  284.    int i;
  285.  
  286.    /* identify VGA/MCGA/EGA */
  287.    regs.h.ah = 0x1a;
  288.    regs.h.al = 0;
  289.    int86(0x10,®s,®s);
  290.  
  291.    /* true only for VGA, MCGA */
  292.    if(regs.h.al == 0x1a)
  293.       {
  294.       if(regs.h.bl < 0x0a)
  295.          vga =1;
  296.       else
  297.          mcga =1;
  298.       color = 1;
  299.       return;
  300.       }
  301.  
  302.    /* next test for EGA */
  303.    regs.h.ah = 0x12;
  304.    regs.h.bl = 0x10;
  305.    int86(0x10,®s,®s);
  306.    if(regs.h.bl != 0x10)   /* it's an EGA */
  307.       {
  308.       ega = 1;
  309.  
  310.       /* EGA can be color or B+W */
  311.       if(regs.h.bh ==0)
  312.          color = 1;
  313.       else
  314.          b_w = 1;
  315.       return;
  316.       }
  317.  
  318.    /* not any of the above,
  319.       so it must be CGA or MONO (or HERC) */
  320.  
  321.    /* test for MONO by looking at the current mode */
  322.    bios_mode();
  323.  
  324.    /* go to MONO test. CGA can't use mode 7 */
  325.    if(cur_mode != 7)
  326.       {
  327.       /* test CGA by looking at the CGA registers */
  328.       outp(0x3d4,0x0f);      /* get value of reg 15 */
  329.       hold_a_byte = inp(0x3d5);   /* save it */
  330.       outp(0x3d5,0x63);  /* write an unlikely value */
  331.       for(i=0;i< 100;i++)      /* wait a bit */
  332.          ;
  333.       if(inp(0x3d5) == 0x63)      /* read it back */
  334.          {
  335.          outp(0x3d5,hold_a_byte); /* restore value */
  336.          cga = 1;
  337.          color = 1;
  338.          return;
  339.          }
  340.       else
  341.          {
  342.          outp(0x3d5,hold_a_byte);
  343.          none = 1;
  344.          color =1;
  345.          return;
  346.          }
  347.       }
  348.    /* not CGA, Test for MDA and HERC.
  349.       Same test as CGA but to mono ports */
  350.    outp(0x3b4,0xf);
  351.    hold_a_byte = inp(0x3b5);
  352.    outp(0x3b5,0x63);
  353.    for(i=0;i<100;i++)
  354.       ;
  355.    if(inp(0x3b5) != 0x63)
  356.       {
  357.       outp(0x3b5,hold_a_byte);
  358.       none = 1;
  359.       b_w = 1;
  360.       return;
  361.       }
  362.    outp(0x3b5,hold_a_byte);
  363.    /* must be a MONO but is it a HERCULES????? */
  364.    hold_a_byte = inp(0x3ba);   /* check status port */
  365.    hold_a_byte &= 0x80;      /* isolate bit 7 */
  366.    for(i=0; i< 1000; i++)
  367.       {
  368.       if(inp(0x3ba) & 0x80 != hold_a_byte)
  369.          {
  370.       /* if value changes, hercules is present */
  371.          herc = 1;
  372.          break;
  373.          }
  374.       }
  375.    if(!herc)
  376.       {
  377.       /* must be just MDA */
  378.       mono = 1;
  379.       b_w = 1;
  380.       return;
  381.       }
  382.  
  383.    /* determine if the card is herc mono or color */
  384.    hold_a_byte = inp(0x3ba);
  385.    switch(hold_a_byte)
  386.       {
  387.       case   0x50:   color = 1;
  388.             break;
  389.       case   0x00:   b_w = 1;
  390.             break;
  391.    /*   case   0x10:    graphics plus card found */
  392.       }
  393.    }
  394.  
  395.  
  396.  
  397.