home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c005 / 4.ddi / C / SCNEWDEV.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-13  |  13.2 KB  |  412 lines

  1. /**
  2. *
  3. * Name        scnewdev -- Select and reset video display device and
  4. *                choose the number of text lines on screen
  5. *
  6. * Synopsis    new_mode = scnewdev(mode,num_rows);
  7. *
  8. *        int new_mode    Error code returned:
  9. *                -1 if requested mode or font are not
  10. *                      supported;
  11. *                actual mode set if no error.
  12. *        int mode    New mode value,
  13. *                or -1 to use existing mode and device.
  14. *        int num_rows    New maximum number of rows on current
  15. *                display device (25 or 43).
  16. *
  17. * Description    This function selects and resets a video adapter and
  18. *        selects the 25-line or (if possible) the 43-line
  19. *        built-in font.    It also selects the proper print-screen
  20. *        routine.
  21. *
  22. *        The permitted values for mode are
  23. *
  24. *        Mode  Device  Description
  25. *        ----  ------  ------------------------------------------
  26. *          0   COLOR   40 x 25 Black and White (Power on default)
  27. *          1   COLOR   40 x 25 Color burst enabled
  28. *          2   COLOR   80 x 25 Black and White
  29. *          3   COLOR   80 x 25 Color burst enabled
  30. *          4   COLOR   320 x 200 Color burst enabled (Medium res)
  31. *          5   COLOR   320 x 200 Black and White     (Medium res)
  32. *          6   COLOR   640 x 200 Black and White     (High   res)
  33. *          7   MONO    Monochrome Adapter or EGA + Mono Display
  34. *          8   COLOR   160 x 200 Color    (PCjr only) (Low    res)
  35. *          9   COLOR   320 x 200 Color    (PCjr only) (Medium res)
  36. *         10   COLOR   640 x 200 Color    (PCjr only) (High   res)
  37. *         13   COLOR   320 x 200 Color     (EGA only) (Medium res)
  38. *         14   COLOR   640 x 200 Color     (EGA only) (High   res)
  39. *         15   MONO    640 x 350 Mono     (EGA only) (High   res)
  40. *         16   COLOR   640 x 350 Color (EGA + Enhanced Color
  41. *                               Display only)
  42. *
  43. *        An error occurs if the mode is not supported by the
  44. *        installed hardware or if the requested font is not
  45. *        supported by the requested device.  In this case no
  46. *        action occurs and -1 is returned as the value of the
  47. *        function.
  48. *
  49. *        Use SCCHGDEV to switch video devices without clearing
  50. *        screens or resetting adapters.
  51. *
  52. * Method    This routine first checks for the presence of the
  53. *        required device and validates the mode and font
  54. *        requested.  If the device is present and the mode and
  55. *        font are supportable, SCNEWDEV then saves the state of
  56. *        the BIOS video state internal variables for the former
  57. *        device and sets the BIOS equipment word to select the
  58. *        new device.  If the new device is an Enhanced Graphics
  59. *        Adapter, the BIOS cursor compensation bit is set
  60. *        according to the font.    Then the new device is reset,
  61. *        clearing the screen.  Page 0 is selected as active
  62. *        (currently displayed) and current (selected for output
  63. *        via C TOOLS PLUS screen I/O routines).    The standard
  64. *        underline cursor is left at the upper left corner of
  65. *        each page.  If 43 lines are requested, the proper font
  66. *        is selected.
  67. *
  68. * Returns    new_mode       Error code returned:
  69. *                -1 if requested mode or font are not
  70. *                      supported;
  71. *                actual mode set if no error.
  72. *
  73. * Version    3.0 (C)Copyright Blaise Computing Inc. 1986
  74. *
  75. * Version    3.02 March 23, 1987
  76. *        Corrected handling of mode -1.
  77. *
  78. **/
  79.  
  80. #include <bquery.h>
  81. #include <bscreen.h>
  82.  
  83. int b_device = DONT_KNOW;          /* Current adapter:  DONT_KNOW, */
  84.                       /*   MONO, or COLOR          */
  85.  
  86. int b_vidcpy(int,int);              /* Internal (see below)          */
  87.  
  88. #define  FROM_BIOS    0          /* Direction flags for copying  */
  89. #define  TO_BIOS    1          /* BIOS video state variables.  */
  90.  
  91. #define  VIDEO_FIELD  0x0030          /* The bits to be modified in   */
  92.                       /* the BIOS equipment word.     */
  93. #define  MONO_FLAG    0x0030
  94. #define  COLOR_80     0x0020
  95. #define  COLOR_40     0x0010
  96.  
  97. int scnewdev(mode,num_rows)
  98. int mode,num_rows;
  99. {
  100.     int old_dev,old_mode,old_cols,old_act_page;
  101.     int device;
  102.     int ax,bx,cx,dx,flags;
  103.     int row,col,high,low;
  104.  
  105.                       /* Address of BIOS equipment    */
  106.     static ADS equip_word_ads = {0x0010,0x0040};    /* word.      */
  107.  
  108. #define our_word    ax              /* Our copy of equipment word.  */
  109.     ADS  our_ads;              /* Address of our_word.          */
  110.     int  old_flag,new_flag;          /* Old and new values of video  */
  111.                       /* device bit field.          */
  112.  
  113.                       /* Address of BIOS INFO byte    */
  114.     static ADS INFO_ads = {0x0087,0x0040};
  115.  
  116.     char old_info;              /* Our copy of former INFO byte */
  117.     ADS  old_ads;              /* Address of old_info          */
  118.     char new_info;
  119.  
  120.     if (num_rows != 25 && num_rows != 43)
  121.     return -1;              /* Unknown font.              */
  122.  
  123.     /* Note current state of BIOS.                      */
  124.  
  125.     old_dev = scmode(&old_mode,&old_cols,&old_act_page);
  126.  
  127.     /* Check validity of mode and font requested              */
  128.  
  129.     scequip();                  /* Sense hardware settings.     */
  130.  
  131.     if (mode == -1)
  132.     mode = old_mode;          /* Use existing mode          */
  133.  
  134.     switch (mode)
  135.     {                      /* Determine requested device.  */
  136.  
  137.                       /* Non-EGA color modes:          */
  138.     case 8:
  139.     case 9:
  140.     case 10:
  141.         if (b_pcmodel != IBM_JR)
  142.         return -1;
  143.     case 4:
  144.     case 5:
  145.     case 6:
  146.         if (num_rows != 25)
  147.         return -1;
  148.     case 0:
  149.     case 1:
  150.     case 2:
  151.     case 3:
  152.                       /* This is a color mode,          */
  153.                       /* so check for color device.   */
  154.         if (   b_cga != COLOR && b_pcmodel != IBM_JR
  155.         && b_ega != COLOR && b_pgc     != COLOR)
  156.         return -1;          /* Color/Graphics Adapter       */
  157.                       /* functions are not available, */
  158.  
  159.         device   = COLOR;          /* Color device is present.     */
  160.         new_flag = COLOR_80;
  161.         break;
  162.  
  163.                       /* EGA-only color modes:          */
  164.     case 13:
  165.     case 14:
  166.         if (num_rows != 25)
  167.         return -1;
  168.     case 16:
  169.         if (b_ega != COLOR)
  170.         return -1;
  171.         device   = COLOR;          /* Color device is present.     */
  172.         new_flag = COLOR_80;
  173.         break;
  174.  
  175.                       /* Monochrome modes:          */
  176.     case 15:
  177.         if (b_ega != MONO)
  178.         return -1;
  179.     case 7:
  180.                       /* This is a monochrome mode,   */
  181.                       /* so check for mono device.    */
  182.         if (b_mdpa != MONO && b_ega != MONO)
  183.         return -1;          /* Monochrome Adapter functions */
  184.                       /* are not available,          */
  185.  
  186.         new_flag = MONO_FLAG;     /* Monochrome functions found.  */
  187.         device   = MONO;
  188.         break;
  189.  
  190.     default:
  191.         return -1;              /* Unknown mode.              */
  192.     }
  193.  
  194.     if (num_rows == 43)           /* If requesting 43 lines       */
  195.     if (   device != b_ega          /* but not on EGA           */
  196.         || (   device == COLOR    /* or if color              */
  197.         && b_sw_ega != 0x9    /* and not on ECD in high-res   */
  198.         && b_sw_ega != 0x3))  /* mode                  */
  199.         return -1;              /* then quit.              */
  200.  
  201.     /* Validation complete:  now switch devices if necessary          */
  202.  
  203.     /* Record current BIOS variables in case we ever need to change   */
  204.     /* back to the old device.                          */
  205.  
  206.     if (b_vidcpy(FROM_BIOS,old_dev))
  207.     return -1;
  208.  
  209.     /* The BIOS keeps track of the color vs. monochrome distinction   */
  210.     /* by two bits in the equipment word, so we must poke those bits  */
  211.     /* to signal the change in device.                      */
  212.  
  213.     bios(17,&ax,&bx,&cx,&dx,&flags);  /* Retrieve equipment word.     */
  214.  
  215.     old_flag = (our_word & VIDEO_FIELD);
  216.     if (new_flag != old_flag          /* There is a change.          */
  217.         && (old_flag != COLOR_40 || new_flag != COLOR_80))
  218.                       /* (Skip the change if 40-col   */
  219.                       /*   mode is set and we're      */
  220.                       /*   setting color.)          */
  221.     {
  222.     our_word = (our_word & ~VIDEO_FIELD) | new_flag;
  223.  
  224.                       /* Install modified equipment   */
  225.                       /* word.                  */
  226.     utabsptr((char *) &our_word,&our_ads);
  227.     utslmove(&our_ads,&equip_word_ads,1);       /* Lower byte only */
  228.     }
  229.     b_device = device;
  230.  
  231.     /* Handle cursor compensation bit:                      */
  232.     /* The EGA BIOS adjusts the cursor type based on the lower bit of */
  233.     /* the variable called INFO.  When the bit is 0, cursor types are */
  234.     /* automatically adjusted to fit in 14 scan lines; when the bit   */
  235.     /* is 1, cursor types are used as requested.  The BIOS does not   */
  236.     /* maintain this bit.  Therefore we set this bit when in 43-line  */
  237.     /* mode and clear it for 25-line mode.                  */
  238.  
  239.     if (b_ega == device)
  240.     {
  241.     utabsptr(&old_info,&old_ads);
  242.     utslmove(&INFO_ads,&old_ads,1);      /* Fetch INFO byte.  */
  243.  
  244.     new_info = old_info;
  245.     if (num_rows == 43)
  246.         new_info |= 1;          /* Set compensation bit          */
  247.                       /* (turn compensation off).     */
  248.     else
  249.         new_info &= (~1);          /* Clear compensation bit       */
  250.                       /* (turn compensation on).      */
  251.  
  252.     if (new_info != old_info)     /* If there is a change,          */
  253.     {
  254.         old_info = new_info;      /* install the new INFO byte.   */
  255.         utslmove(&old_ads,&INFO_ads,1);
  256.     }
  257.     }
  258.  
  259.     /* Reset new device                           */
  260.  
  261.     ax = utbyword(0,mode);
  262.     bios(16,&ax,&bx,&cx,&dx,&flags);
  263.  
  264.     if (num_rows == 43)
  265.     {
  266.     if (mode > 3 && mode != 7)
  267.     {                  /* Graphics mode              */
  268.         ax = 0x1123;          /* Install 43-line font          */
  269.         bx = 0x0003;
  270.         bios(16,&ax,&bx,&cx,&dx,&flags);
  271.     }
  272.     else
  273.     {                  /* Text mode              */
  274.         ax = 0x1112;          /* Install 43-line font          */
  275.         bx = 0;
  276.         bios(16,&ax,&bx,&cx,&dx,&flags);
  277.     }
  278.  
  279.     ax = 0x1200;              /* Select 43-line print screen  */
  280.     bx = 0x0020;              /* routine.              */
  281.     bios(16,&ax,&bx,&cx,&dx,&flags);
  282.     }
  283.  
  284.     scpage(0);
  285.  
  286.     b_curknown[device] = 0;          /* Forget former cursor types.  */
  287.     sccurst(&row,&col,&high,&low);    /* Retrieve & record cursor type*/
  288.                       /* for all pages.           */
  289.  
  290.     /* Record new BIOS variables in case SCCHGDEV ever wants to       */
  291.     /* change to the new device.                      */
  292.  
  293.     b_vidcpy(FROM_BIOS,device);
  294.  
  295.     return mode;
  296. }
  297.  
  298. /**
  299. *
  300. * Name        b_vidcpy -- Copy BIOS video state variables.
  301. *
  302. * Synopsis    ercode = b_vidcpy(dir,device);
  303. *        int ercode      Result code:
  304. *                   1 if dir or device invalid or if
  305. *                     table information is unavailable;
  306. *                   0 if ok.
  307. *        int dir       Direction:
  308. *                   FROM_BIOS means from BIOS to table,
  309. *                   TO_BIOS   means from table to BIOS.
  310. *        int device      MONO or COLOR to denote which entry of
  311. *                  the b_adap_state table to use.
  312. *
  313. * Description    This function copies the five blocks of BIOS video state
  314. *        variables to or from the table called b_adap_state
  315. *        (defined above).
  316. *
  317. *        If dir is TO_BIOS, the b_adap_state table entry is
  318. *        checked for valid data; if it is marked as invalid, then
  319. *        1 is returned as an error code.
  320. *
  321. *        An error is also reported if dir or device is invalid.
  322. *
  323. * Returns    ercode          Result code:
  324. *                   1 if dir or device invalid or if
  325. *                     table information is unavailable;
  326. *                   0 if ok.
  327. *
  328. **/
  329.  
  330.     /* Internal structure for preserving BIOS video variables          */
  331.  
  332. VIDEO_STATE b_adap_state[2] = {0};    /* One entry for MONO, one for  */
  333.                       /* COLOR.               */
  334.  
  335. int b_vidcpy(dir,device)
  336. int dir,device;
  337. {
  338.     int i;
  339.     int were_on;          /* Flag indicating whether interrupts   */
  340.                   /* were on before we turned them off.   */
  341.  
  342.     /* There are five blocks of BIOS variables that describe the      */
  343.     /* state of an adapter.  Here are tables to help us copy them     */
  344.     /* into the b_adap_state array:                      */
  345.  
  346.     ADS save_ads;
  347.     static char *save_area[2][5] =    /* Pointers to the sections of  */
  348.     {                      /* the VIDEO_STATE structures   */
  349.                       /* in the b_adap_state table    */
  350.     {       b_adap_state[0].pc_area,
  351.      (char *) &b_adap_state[0].reset_flag,
  352.            b_adap_state[0].ega_area,
  353.      (char *) &b_adap_state[0].save_ptr,
  354.           &b_adap_state[0].ega_status},
  355.  
  356.     {       b_adap_state[1].pc_area,
  357.      (char *) &b_adap_state[1].reset_flag,
  358.            b_adap_state[1].ega_area,
  359.      (char *) &b_adap_state[1].save_ptr,
  360.           &b_adap_state[1].ega_status}
  361.     };
  362.     static int save_size[5] =          /* Sizes of the five sections   */
  363.     {                      /* of a VIDEO_STATE structure   */
  364.     sizeof(b_adap_state[0].pc_area),
  365.     sizeof(b_adap_state[0].reset_flag),
  366.     sizeof(b_adap_state[0].ega_area),
  367.     sizeof(b_adap_state[0].save_ptr),
  368.     sizeof(b_adap_state[0].ega_status)
  369.     };
  370.     static ADS bios_ads[5] =          /* Addresses of the five blocks */
  371.     {                      /* of BIOS variables          */
  372.     {0x0049,0x0040},
  373.     {0x0072,0x0040},
  374.     {0x0084,0x0040},
  375.     {0x00a8,0x0040},
  376.     {0x0100,0x0040}
  377.     };
  378.  
  379.     if (   (dir    != FROM_BIOS && dir      != TO_BIOS)
  380.     || (device != COLOR    && device != MONO))
  381.     return 1;              /* Invalid code.              */
  382.  
  383.     if (dir == TO_BIOS && !b_adap_state[device].known)
  384.     return 1;              /* Requested table info isn't   */
  385.                       /* valid.               */
  386.  
  387.     were_on = utintoff();          /* Turn interrupts off.          */
  388.  
  389.     for (i = 0; i < 5; i++)          /* For each of the five blocks, */
  390.     {
  391.                       /* Compute address of the area  */
  392.                       /* where it is to be saved.     */
  393.     utabsptr((char *) save_area[device][i],&save_ads);
  394.  
  395.     if (dir == FROM_BIOS)          /* Copy the block of data       */
  396.         utslmove(&bios_ads[i],&save_ads,save_size[i]);/* from BIOS*/
  397.     else
  398.         utslmove(&save_ads,&bios_ads[i],save_size[i]); /* to BIOS */
  399.     }
  400.  
  401.     if (were_on)
  402.     utinton();              /* Turn interrupts back on.     */
  403.  
  404.     if (dir == FROM_BIOS)
  405.     {
  406.     b_adap_state[device].curpage = b_curpage;
  407.     b_adap_state[device].known   = 1;/* Flag table info as valid. */
  408.     }
  409.  
  410.     return 0;                  /* Success.              */
  411. }
  412.