home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name utansi -- Detect, disable, or re-enable ANSI.SYS
- *
- * Synopsis old_state = utansi(option);
- *
- * int old_state The previous state of ANSI.SYS:
- * UT_ANS_ABSENT -- Not detected.
- * UT_ANS_ENABLE -- Detected and active.
- * UT_ANS_DISABLE -- Detected and
- * disabled by this program.
- * UT_ANS_HANDLES -- No more file handles.
- * UT_BAD_OPT -- option contains
- * unsupported value.
- *
- * int option Operation to perform:
- * UT_ANS_DETECT -- Report only.
- * UT_ANS_DISABLE -- Disable if active.
- * UT_ANS_ENABLE -- Re-enable if
- * present and disabled.
- *
- * Description This function detects whether ANSI.SYS is installed
- * and active and optionally disables or re-enables it.
- *
- * Limitations This function uses DOS, including DOS function 12.
- *
- * Do not allow the program to be removed from memory or
- * relocated while ANSI.SYS is disabled.
- *
- * This function does not work if the console has been set
- * to some other device via the CTTY command. It works
- * only if the current console is the standard IBM display
- * and keyboard, i.e., device CON.
- *
- * This function does not work if the standard error device
- * (i.e., handle 2) has been redirected.
- *
- * Method DOS console output passes via interrupt 0x29. ANSI.SYS
- * works by servicing interrupt 0x29. UTANSI disables
- * ANSI.SYS by installing a handler for interrupt 0x29 that
- * simply calls the BIOS write-TTY function.
- *
- * We check for the presence of ANSI.SYS by emitting the
- * command "ESC [6n". If ANSI.SYS is active, it will
- * report the cursor position as a series of keystrokes.
- * If no such keystrokes appear, then ANSI.SYS is inactive
- * and we must restore the screen contents that were
- * garbled by the command.
- *
- * We transmit the command "ESC [6n" to handle 2, which is
- * not normally redirected. We look for the response from
- * ANSI.SYS via low-level DOS functions that access
- * standard input. In case standard input has been
- * redirected, we temporarily duplicate handle 2 as
- * standard input.
- *
- * Returns old_state The previous state of ANSI.SYS:
- * UT_ANS_ABSENT -- Not detected.
- * UT_ANS_ENABLE -- Detected and active.
- * UT_ANS_DISABLE -- Detected and
- * disabled by this program.
- * UT_ANS_HANDLES -- No more file handles.
- * UT_BAD_OPT -- option contains
- * unsupported value.
- * b_ansdis Nonzero if ANSI.SYS is disabled by
- * this function.
- *
- * Version 6.00 (C)Copyright Blaise Computing Inc. 1989
- *
- **/
-
- #include <conio.h> /* For kbhit(). */
- #include <dos.h> /* For REGS, SREGS, intdos(), */
- /* intdosx(). */
- #include <io.h> /* For close(), dup(), dup2(), */
- /* write(). */
-
- #include <bintrupt.h>
- #include <bscreens.h>
- #include <butil.h>
-
- int b_ansdis = 0; /* Nonzero if we disabled */
- /* ANSI.SYS. */
-
- #define MSGSIZE (sizeof(return_cursor_position) - 1)
-
- static void dos_kb_flush(void);
-
- int utansi(option)
- int option;
- {
- int old_state;
- int new_stdin;
- int mode,act_page,columns;
- int save_page;
- int save_row,save_col,high,low;
- int fore,back,col;
- static char return_cursor_position[] = "\33[6n";
- char save_chars[MSGSIZE];
- static void far *psave_vec;
- static unsigned char replacement_code[] =
- { /* Replacement int 0x29 handler:*/
- 0x50, /* push ax */
- 0x56, /* push si */
- 0x57, /* push di */
- 0x55, /* push bp */
- 0xbb,0x07,0x00, /* mov bx,7h */
- 0xb4,0x0e, /* mov ah,0eh */
- 0xcd,0x10, /* int 10h */
- 0x5d, /* pop bp */
- 0x5f, /* pop di */
- 0x5e, /* pop si */
- 0x58, /* pop ax */
- 0xcf /* iret */
- };
-
- switch (option) /* Check validity of option. */
- {
- case UT_ANS_DETECT:
- case UT_ANS_ENABLE:
- case UT_ANS_DISABLE:
- break;
- default:
- return UT_BAD_OPT;
- }
-
- if (b_ansdis)
- old_state = UT_ANS_DISABLE;
- else /* Check presense of ANSI.SYS. */
- {
- if (-1 == (new_stdin = dup(0))) /* Save spare copy of stdin. */
- old_state = UT_ANS_HANDLES; /* Quit if failure. */
- else
- {
- dup2(2,0); /* Force handle 0 to refer to */
- /* current console. */
-
- /* Save cursor position and */
- /* initial screen data. */
- scmode(&mode,&columns,&act_page);
- save_page = b_curpage;
- scpage(act_page);
- sccurst(&save_row,&save_col,&high,&low);
- for (col = 0; col < MSGSIZE; col++)
- {
- sccurset(0,col);
- save_chars[col] = scread(&fore,&back);
- }
- sccurset(0,0);
-
- dos_kb_flush(); /* Clear keyboard input. */
-
- /* Write string to console. */
- write(2,return_cursor_position,MSGSIZE);
-
- if (kbhit()) /* Look for response from ANSI. */
- {
- dos_kb_flush(); /* Discard the response. */
- old_state = UT_ANS_ENABLE; /* ANSI.SYS is active. */
- }
- else
- { /* No response; restore screen. */
- for (col = 0; col < MSGSIZE; col++)
- {
- sccurset(0,col);
- scwrite(save_chars[col],1);
- }
- old_state = UT_ANS_ABSENT;
- }
- sccurset(save_row,save_col); /* Clean up. */
- scpage(save_page);
- dup2(new_stdin,0);
- close(new_stdin);
- }
- }
-
- /* Presence test is complete; */
- switch (option) /* now do any work. */
- {
- case UT_ANS_DISABLE:
- if (old_state == UT_ANS_ENABLE)
- { /* Save previous 0x29 handler. */
- psave_vec = isgetvec(0x29);
- /* Install our 0x29 handler. */
- isputvec(0x29,replacement_code);
- b_ansdis = 1;
- }
- break;
-
- case UT_ANS_ENABLE:
- if (b_ansdis)
- { /* Restore previous 0x29 handler*/
- isputvec(0x29,psave_vec);
- b_ansdis = 0;
- }
- break;
- }
-
- return(old_state);
- }
-
- static void dos_kb_flush() /* dos_kb_flush(): Flush */
- { /* standard input via DOS. */
- union REGS inregs,outregs;
-
- inregs.x.ax = 0x0c06;
- inregs.h.dl = 0xff;
- intdos(&inregs,&outregs);
- }