/* * The functions in this file negotiate with the operating system for * characters, and write characters in a barely buffered fashion on the display. * All operating systems. */ #include /* 1.13 */ #ifdef UNIX /* System V */ #if defined(__GLIBC__) || \ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #define TERMIOS 1 #endif #include #include #include #include #if defined(BSD) && !defined(TERMIOS) #include #else #ifdef OS2 #ifndef __EMX__ #define INCL_NOPM #define INCL_DOS #define INCL_KBD #include #endif #include #else #ifdef MINIX #include #define O_NDELAY O_NONBLOCK #else #ifdef TERMIOS #include #include #else #include #endif /* __GLIBC__ */ #endif /* MINIX */ #endif /* OS2 */ #endif /* BSD */ #include #include #include "def.h" int kbdflgs; /* saved keyboard fd flags */ int kbdpoll; /* in O_NDELAY mode */ int kbdqp; /* there is a char in kbdq */ char kbdq; /* char we've already read */ #if defined(BSD) && !defined(TERMIOS) struct sgttyb otermb; struct sgttyb ntermb; #else #ifdef OS2 #ifndef __EMX__ KBDINFO kbst, kbst_std; #endif #else #ifdef MINIX struct sgttyb otermio; /* original terminal characteristics */ struct sgttyb ntermio; /* charactoristics to use inside */ struct tchars tchars, tcharsorig; #else #ifdef TERMIOS #include struct termios otermio; struct termios ntermio; #else struct termio otermio; /* original terminal characteristics */ struct termio ntermio; /* charactoristics to use inside */ #endif /* __GLIBC__ */ #endif /* MINIX */ #endif /* OS2 */ #endif /* BSD */ #ifndef OS2 //extern errno; /* System error number -- Necessary when compiling in BSD 1.13 */ #endif int nrow; /* Terminal size, rows. */ int ncol; /* Terminal size, columns. */ /* * This function is called once to set up the terminal device streams. * On VMS, it translates TT until it finds the terminal, then assigns * a channel to it and sets it raw. On CPM it is a no-op. */ void ttopen () { #if defined(BSD) && !defined(TERMIOS) #ifdef TIOCGWINSZ struct winsize ttysize; #else struct ttysize ttysize; #endif ioctl (0, TIOCGETP, &otermb); /* save settings */ ntermb = otermb; /* setup new settings */ ntermb.sg_flags &= ~ECHO; ntermb.sg_flags |= RAW; ioctl (0, TIOCSETP, &ntermb); /* and activate them */ kbdpoll = FALSE; /* on all screens we are not sure of the initial position of the cursor */ ttrow = 999; ttcol = 999; #ifdef TIOCGWINSZ if (ioctl (0, TIOCGWINSZ, &ttysize) == 0) { nrow = ttysize.ws_row; ncol = ttysize.ws_col; #else if (ioctl (0, TIOCGSIZE, &ttysize) == 0) { nrow = ttysize.ts_lines; ncol = ttysize.ts_cols; #endif /* ULTRIX */ } else { nrow = NROW; ncol = NCOL; } #else #ifdef OS2 setmode (1, O_BINARY); #else #ifdef MINIX ioctl (0, TIOCGETP, &otermio); ntermio = otermio; ntermio.sg_flags &= ~ECHO; ntermio.sg_flags |= RAW; ioctl (0, TIOCSETP, &ntermio); ioctl (0, TIOCGETC, &tcharsorig); tchars = tcharsorig; tchars.t_intrc = tchars.t_quitc = tchars.t_startc = tchars.t_stopc = tchars.t_eofc = tchars.t_brkc = -1; ioctl (0, TIOCSETC, &tchars); #else #ifdef TERMIOS #ifdef TIOCGWINSZ struct winsize ttysize; #endif tcgetattr(0,&otermio); ntermio.c_ispeed = otermio.c_ispeed; ntermio.c_ospeed = otermio.c_ospeed; #else ioctl (0, TCGETA, &otermio);/* save old settings */ ntermio.c_line = otermio.c_line; #endif ntermio.c_iflag = 0; /* setup new settings */ ntermio.c_oflag = 0; ntermio.c_cflag = otermio.c_cflag; ntermio.c_lflag = 0; ntermio.c_cc[VMIN] = 1; ntermio.c_cc[VTIME] = 0; #ifdef TERMIOS tcsetattr(0,TCSANOW,&ntermio); #else ioctl (0, TCSETAW, &ntermio); /* and activate them */ #endif #endif /* MINIX */ kbdflgs = fcntl (0, F_GETFL, 0); kbdpoll = FALSE; #endif /* OS2 */ /* on all screens we are not sure of the initial position of the cursor */ ttrow = 999; ttcol = 999; #if defined(TERMIOS) && defined(TIOCGWINSZ) if (ioctl (0, TIOCGWINSZ, &ttysize) == 0) { nrow = ttysize.ws_row; ncol = ttysize.ws_col; } else #endif { nrow = NROW; ncol = NCOL; } #endif /* BSD */ } /* * This function gets called just before we go back home to the command * interpreter. On VMS it puts the terminal back in a reasonable state. * Another no-operation on CPM. */ void ttclose () { #if defined(BSD) && !defined(TERMIOS) if (ioctl (0, TIOCSETP, &otermb) == -1) /* restore terminal settings */ printf ("closing ioctl on dev 0 failure, error = %d\n", errno); #else #ifdef OS2 setmode (1, O_TEXT); #else #ifdef MINIX if (ioctl (0, TIOCSETP, &otermio) == -1 || ioctl (0, TIOCSETC, &tcharsorig) == -1) printf ("closing ioctl on dev 0 failure, error = %d\n", errno); #else #ifdef TERMIOS if( tcsetattr(0,TCSANOW,&otermio) == -1) #else if (ioctl (0, TCSETAW, &otermio) == -1) /* restore terminal settings */ #endif printf ("closing ioctl on dev 0 failure, error = %d\n", errno); #endif /* MINIX */ if (fcntl (0, F_SETFL, kbdflgs) == -1) printf ("closing fcntl on dev 0 failure, error = %d\n", errno); #endif /* OS2 */ #endif /* BSD */ } #ifdef OS2 void ttraw (void) { #ifdef __32BIT__ signal (SIGINT, SIG_IGN); signal (SIGBREAK, SIG_IGN); #else PFNSIGHANDLER oldhandler; USHORT oldact; DosSetSigHandler ((PFNSIGHANDLER) NULL, &oldhandler, &oldact, SIGA_IGNORE, SIG_CTRLBREAK); DosSetSigHandler ((PFNSIGHANDLER) NULL, &oldhandler, &oldact, SIGA_IGNORE, SIG_CTRLC); #endif #ifndef __EMX__ kbst_std.cb = sizeof (kbst_std); KbdGetStatus (&kbst_std, 0); kbst = kbst_std; kbst.fsMask &= ~(KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE | KEYBOARD_SHIFT_REPORT); kbst.fsMask |= (KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE); KbdSetStatus (&kbst, 0); #endif } void ttcooked (void) { #ifndef __EMX__ KbdSetStatus (&kbst_std, 0); #endif } #endif /* * Write a character to the display. On VMS, terminal output is buffered, and * we just put the characters in the big array, after checking for overflow. * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on * MS-DOS (use the very very raw console output routine). */ #ifdef OS2 int tty_io_size = 0; char tty_io_buffer[2048]; #endif int ttputc (c) { #ifdef OS2 if (tty_io_size == sizeof (tty_io_buffer)) { write (1, tty_io_buffer, tty_io_size); tty_io_size = 0; } tty_io_buffer[tty_io_size++] = c; #else fputc (c, stdout); #endif return c; } /* * Flush terminal buffer. Does real work where the terminal output is buffered * up. A no-operation on systems where byte at a time terminal I/O is done. */ void ttflush () { #ifdef OS2 if (tty_io_size) { write (1, tty_io_buffer, tty_io_size); tty_io_size = 0; } #else fflush (stdout); #endif } /* * Read a character from the terminal, performing no editing and doing no echo * at all. More complex in VMS that almost anyplace else, which figures. Very * simple on CPM, because the system can do exactly what you want. */ #ifdef OS2 #ifdef __EMX__ static int chr = -1; #endif #endif int ttgetc () { #ifdef OS2 #ifdef __EMX__ if (chr != -1) { int c = chr; chr = -1; return c; } else return _read_kbd (0, 1, 0); #else static int ext, scan, chr; KBDKEYINFO ki; if (ext) { ext = 0; return scan; } else { ttflush (); KbdCharIn (&ki, IO_WAIT, 0); if (ki.chChar == 0 || ki.chChar == 0xE0) { ext = 1; scan = ki.chScan; return 0xE0; } else return ki.chChar; } #endif #else if (kbdqp) kbdqp = FALSE; else { #ifdef BSD int count; if (kbdpoll && (ioctl (0, FIONREAD, &count), count == 0)) return FALSE; read (0, &kbdq, 1); #else if (kbdpoll && fcntl (0, F_SETFL, kbdflgs) < 0) return FALSE; kbdpoll = FALSE; while (read (0, &kbdq, 1) != 1) ; #endif } return (kbdq & 127); #endif /* OS2 */ } /* typahead(): Check to see if any characters are already in the keyboard buffer */ int ttkeyready () { #ifdef OS2 #ifdef __EMX__ chr = _read_kbd (0, 0, 0); return (chr != -1); #else KBDKEYINFO ki; KbdPeek (&ki, 0); return (ki.fbStatus != 0); #endif #else if (!kbdqp) { #ifdef BSD int count; if (!kbdpoll && (ioctl (0, FIONREAD, &count), count == 0)) return FALSE; kbdpoll = TRUE; /* fix in 1.13 */ kbdqp = TRUE; #else #ifdef X_MINIX /* MINIX has non-blocking mode but it doesn't work !?!? */ return FALSE; #else if (!kbdpoll && fcntl (0, F_SETFL, kbdflgs | O_NDELAY) < 0) return (FALSE); kbdpoll = TRUE; /* fix in 1.13 */ kbdqp = (1 == read (0, &kbdq, 1)); #endif /* MINIX */ #endif /* BSD */ } return (kbdqp); #endif /* OS2 */ } #endif