home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / UTANSI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-31  |  6.3 KB  |  210 lines

  1. /**
  2. *
  3. * Name        utansi -- Detect, disable, or re-enable ANSI.SYS
  4. *
  5. * Synopsis    old_state = utansi(option);
  6. *
  7. *        int old_state      The previous state of ANSI.SYS:
  8. *                  UT_ANS_ABSENT -- Not detected.
  9. *                  UT_ANS_ENABLE -- Detected and active.
  10. *                  UT_ANS_DISABLE -- Detected and
  11. *                    disabled by this program.
  12. *                  UT_ANS_HANDLES -- No more file handles.
  13. *                  UT_BAD_OPT -- option contains
  14. *                    unsupported value.
  15. *
  16. *        int option      Operation to perform:
  17. *                  UT_ANS_DETECT -- Report only.
  18. *                  UT_ANS_DISABLE -- Disable if active.
  19. *                  UT_ANS_ENABLE -- Re-enable if
  20. *                    present and disabled.
  21. *
  22. * Description    This function detects whether ANSI.SYS is installed
  23. *        and active and optionally disables or re-enables it.
  24. *
  25. * Limitations    This function uses DOS, including DOS function 12.
  26. *
  27. *        Do not allow the program to be removed from memory or
  28. *        relocated while ANSI.SYS is disabled.
  29. *
  30. *        This function does not work if the console has been set
  31. *        to some other device via the CTTY command.  It works
  32. *        only if the current console is the standard IBM display
  33. *        and keyboard, i.e., device CON.
  34. *
  35. *        This function does not work if the standard error device
  36. *        (i.e., handle 2) has been redirected.
  37. *
  38. * Method    DOS console output passes via interrupt 0x29.  ANSI.SYS
  39. *        works by servicing interrupt 0x29.  UTANSI disables
  40. *        ANSI.SYS by installing a handler for interrupt 0x29 that
  41. *        simply calls the BIOS write-TTY function.
  42. *
  43. *        We check for the presence of ANSI.SYS by emitting the
  44. *        command "ESC [6n".  If ANSI.SYS is active, it will
  45. *        report the cursor position as a series of keystrokes.
  46. *        If no such keystrokes appear, then ANSI.SYS is inactive
  47. *        and we must restore the screen contents that were
  48. *        garbled by the command.
  49. *
  50. *        We transmit the command "ESC [6n" to handle 2, which is
  51. *        not normally redirected.  We look for the response from
  52. *        ANSI.SYS via low-level DOS functions that access
  53. *        standard input.  In case standard input has been
  54. *        redirected, we temporarily duplicate handle 2 as
  55. *        standard input.
  56. *
  57. * Returns    old_state      The previous state of ANSI.SYS:
  58. *                  UT_ANS_ABSENT -- Not detected.
  59. *                  UT_ANS_ENABLE -- Detected and active.
  60. *                  UT_ANS_DISABLE -- Detected and
  61. *                    disabled by this program.
  62. *                  UT_ANS_HANDLES -- No more file handles.
  63. *                  UT_BAD_OPT -- option contains
  64. *                    unsupported value.
  65. *        b_ansdis      Nonzero if ANSI.SYS is disabled by
  66. *                  this function.
  67. *
  68. * Version    6.00 (C)Copyright Blaise Computing Inc.  1989
  69. *
  70. **/
  71.  
  72. #include <conio.h>              /* For kbhit().              */
  73. #include <dos.h>              /* For REGS, SREGS, intdos(),   */
  74.                       /*   intdosx().              */
  75. #include <io.h>               /* For close(), dup(), dup2(),  */
  76.                       /*   write().              */
  77.  
  78. #include <bintrupt.h>
  79. #include <bscreens.h>
  80. #include <butil.h>
  81.  
  82. int b_ansdis = 0;              /* Nonzero if we disabled       */
  83.                       /* ANSI.SYS.              */
  84.  
  85. #define  MSGSIZE  (sizeof(return_cursor_position) - 1)
  86.  
  87. static void dos_kb_flush(void);
  88.  
  89. int utansi(option)
  90. int option;
  91. {
  92.     int      old_state;
  93.     int      new_stdin;
  94.     int      mode,act_page,columns;
  95.     int      save_page;
  96.     int      save_row,save_col,high,low;
  97.     int      fore,back,col;
  98.     static char  return_cursor_position[] = "\33[6n";
  99.     char     save_chars[MSGSIZE];
  100.     static void far *psave_vec;
  101.     static unsigned char replacement_code[] =
  102.     {                      /* Replacement int 0x29 handler:*/
  103.     0x50,                  /* push ax              */
  104.     0x56,                  /* push si              */
  105.     0x57,                  /* push di              */
  106.     0x55,                  /* push bp              */
  107.     0xbb,0x07,0x00,           /* mov  bx,7h              */
  108.     0xb4,0x0e,              /* mov  ah,0eh              */
  109.     0xcd,0x10,              /* int  10h              */
  110.     0x5d,                  /* pop  bp              */
  111.     0x5f,                  /* pop  di              */
  112.     0x5e,                  /* pop  si              */
  113.     0x58,                  /* pop  ax              */
  114.     0xcf                  /* iret                  */
  115.     };
  116.  
  117.     switch (option)              /* Check validity of option.    */
  118.     {
  119.     case UT_ANS_DETECT:
  120.     case UT_ANS_ENABLE:
  121.     case UT_ANS_DISABLE:
  122.         break;
  123.     default:
  124.         return UT_BAD_OPT;
  125.     }
  126.  
  127.     if (b_ansdis)
  128.     old_state = UT_ANS_DISABLE;
  129.     else                  /* Check presense of ANSI.SYS.  */
  130.     {
  131.     if (-1 == (new_stdin = dup(0)))  /* Save spare copy of stdin. */
  132.         old_state = UT_ANS_HANDLES;  /* Quit if failure.          */
  133.     else
  134.     {
  135.         dup2(2,0);              /* Force handle 0 to refer to   */
  136.                       /* current console.          */
  137.  
  138.                       /* Save cursor position and     */
  139.                       /* initial screen data.          */
  140.         scmode(&mode,&columns,&act_page);
  141.         save_page = b_curpage;
  142.         scpage(act_page);
  143.         sccurst(&save_row,&save_col,&high,&low);
  144.         for (col = 0; col < MSGSIZE; col++)
  145.         {
  146.         sccurset(0,col);
  147.         save_chars[col] = scread(&fore,&back);
  148.         }
  149.         sccurset(0,0);
  150.  
  151.         dos_kb_flush();          /* Clear keyboard input.          */
  152.  
  153.                       /* Write string to console.     */
  154.         write(2,return_cursor_position,MSGSIZE);
  155.  
  156.         if (kbhit())          /* Look for response from ANSI. */
  157.         {
  158.         dos_kb_flush();          /* Discard the response. */
  159.         old_state = UT_ANS_ENABLE;   /* ANSI.SYS is active.   */
  160.         }
  161.         else
  162.         {                  /* No response; restore screen. */
  163.         for (col = 0; col < MSGSIZE; col++)
  164.         {
  165.             sccurset(0,col);
  166.             scwrite(save_chars[col],1);
  167.         }
  168.         old_state = UT_ANS_ABSENT;
  169.         }
  170.         sccurset(save_row,save_col);    /* Clean up.          */
  171.         scpage(save_page);
  172.         dup2(new_stdin,0);
  173.         close(new_stdin);
  174.     }
  175.     }
  176.  
  177.                       /* Presence test is complete;   */
  178.     switch (option)              /* now do any work.          */
  179.     {
  180.     case UT_ANS_DISABLE:
  181.         if (old_state == UT_ANS_ENABLE)
  182.         {                  /* Save previous 0x29 handler.  */
  183.         psave_vec = isgetvec(0x29);
  184.                       /* Install our 0x29 handler.    */
  185.         isputvec(0x29,replacement_code);
  186.         b_ansdis = 1;
  187.         }
  188.         break;
  189.  
  190.     case UT_ANS_ENABLE:
  191.         if (b_ansdis)
  192.         {                  /* Restore previous 0x29 handler*/
  193.         isputvec(0x29,psave_vec);
  194.         b_ansdis = 0;
  195.         }
  196.         break;
  197.     }
  198.  
  199.     return(old_state);
  200. }
  201.  
  202. static void dos_kb_flush()          /* dos_kb_flush():  Flush       */
  203. {                      /* standard input via DOS.      */
  204.     union REGS inregs,outregs;
  205.  
  206.     inregs.x.ax = 0x0c06;
  207.     inregs.h.dl = 0xff;
  208.     intdos(&inregs,&outregs);
  209. }
  210.