diff options
Diffstat (limited to 'dviware/beebe/src/keybrd.c')
-rw-r--r-- | dviware/beebe/src/keybrd.c | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/dviware/beebe/src/keybrd.c b/dviware/beebe/src/keybrd.c new file mode 100644 index 0000000000..346515102e --- /dev/null +++ b/dviware/beebe/src/keybrd.c @@ -0,0 +1,920 @@ +/*********************************************************************** + +This package implements a simple keyboard input interface to permit +character-at-a-time input, plus optional suppression of character +translation. + +This is one of the areas where operating systems (even variants of Unix) +are horribly non-standard, and the problem is not really addressed +satisfactorily by either the emerging draft ANSI C Standard (01-Oct-86), +or the IEEE Trial Use Standard: Portable Operating System for Computer +Environments (POSIX), IEEE Std 1003.1, (14-Apr-86). + +This package is intentionally simple--only one keyboard input device is +supported (NOT Unix stdin!), and where possible, it is implemented with +rather ordinary Unix library calls. The functionality provided is open, +close, flush, get, unget, set-mode, and inquire-mode. All functions +(except kbfile()) use the stdio.h EOF value to signal an error, and none +set the global errno flag (that is not the prerogative of non-system +software). + +User programs need only use a '#include "key.h"' statement to get +definitions of all visible flags, functions, and types in this package. +Global data which is private to this package is declared static to +ensure just that. + +The mode parameter set in calls to kbopen() and kbmode(), and returned +by them, is simply a collection of bit flags, but for future +expandability, it has a special type KEYMODE, instead of being an int. +The mode flags require some explanation. They are based on the terminal +I/O model in Berkeley Unix. Essentially three terminal modes are +supported: normal, cbreak, and raw. + +In normal mode, keyboard input is handled like fopen() / getchar() / +fclose(), so that input editing characters are supported (and handled by +the terminal driver, not this package!). Input may be available before +a <CR> is typed (e.g. 4.3BSD, TOPS-20, MS-DOS), or may not (System V, +VMS). + +In cbreak mode, input editing characters should still work, but input is +guaranteed to be available before a <CR> is typed, provided that the +operating system supports that (CDC and IBM do not). Interrupt +characters (CTL-C, CTL-Z, et al) are not readable--they still cause +interrupts which are not handled here. Other control characters (HT, +ESC, et al) must be readable. + +In raw mode, all characters in the host character set may be input, and +no character-initiated interrupts are possible. + +These three modes are selected by OR'ing into the mode value one of +KB_CBREAK, KB_NORMAL, or KB_RAW; they are mutually exclusive, and an +error is raised if more than one is specified. + +The current mode may be saved (internally) with KB_SAVE, restored with +KB_RESTORE, or inquired with KB_INQUIRE; any other KB_xxxx flags set +with these are ignored, and the current mode is not changed. Only one +level of save/restore is provided; successive restore requests without +an intervening save are permissible, and simply restore the saved mode. +The intent is that save/restore normally only be done once at job start +and end. + +Normally, input characters are not echoed to the terminal; if the +side-effect of echoing is wanted, it must be requested by KB_ECHO. + +The effect of these modes on input (and output) via other file +descriptors is operating-system dependent. On Unix, the terminal modes +are job-wide, and persist after a program terminates. On MS-DOS and VAX +VMS, they affect terminal I/O, but only for the duration of the job, and +only for that file descriptor. On TOPS-20, some of the modes can +persist after the job (e.g. terminal width and pause-on-end-of-page). + +All functions return the EOF error indicator if the keyboard file is not +open. This can be done with an initial call to kbopen(mode); on +success, it returns the argument mode value. + +When processing is complete, kbclose() should be called. Further calls +of the kbxxxx() functions will return error codes until kbopen() is +called again. kbclose() must restore the terminal to the state it was +in when kbopen() was called; kbmode() does not necessarily do that +(since the default mode for kbopen() is no echo). + +kbget() and kbunget(c) provide for single-character input, and +single-character push-back. kbget() returns a non-negative ordinal +value on success, and EOF on error. The pushed-back character given to +kbunget(c) need not be one obtained from the last call to kbget(). +Attempts to push back more than one character are ignored, and result in +an EOF error return. Depending on the mode (raw, cbreak, normal), +kbget() may not be able to return an end-of-file indicator; it cannot in +raw mode, but for portability, EOF returns from kbget() should not be +expected. + +kbflush() simply flushes typeahead. It returns EOF only if the keyboard +file is not open; otherwise it returns 0. + +In many applications, it is often important to have the capability of +determining whether or nor input is available. For example, a screen +display algorithm probably should suspend display if input is awaiting +that is likely to change the state of the screen. The kbinput() +function is therefore an important one; it returns 0 if no input is +available to be read by kbget(), returns EOF on error, and otherwise +returns a positive number which in some implementations may be the +number of unread input characters, and in others may be arbitrary. This +function is one which is difficult to implement on some operating +systems, with Unix System III and V being the worst. The implementation +below for the latter is borrowed from Marc Rochkind's excellent book, +"Advanced Unix Programming", Prentice-Hall (1985). + +There is one other function provided, kbfile(); it returns the FILE* +pointer for the keyboard file, or (FILE*)NULL is none is open, or if +this package is not implemented with standard C I/O routines. Its use +is strongly discouraged, but the author's long programming experience +has shown that on rare occasions, it may be useful. Character push-back +with direct calls to ungetc(c,kbfile()) will probably not work as +expected, but other stdio functions should. fopen() and fclose() should +not be called with the kbfile() value; that would corrupt internal data +structures here. + +Most functions are necessarily internally system-dependent, and +preprocessor conditionals encapsulate the gory details. Preprocessor +flags are as follows; at least one implementation flag, and one +compatible operating system flag, must be chosen: + +C Implementations: + ATT -- AT&T Unix (System III, V) + BSD -- Berkeley 4.xBSD + HPUX -- HP 9000 series Unix (System V based) + IBM_PC_MICROSOFT-- IBM PC Microsoft Version 3.x or later C compiler + KCC_20 -- SRI's KCC Compiler on TOPS-20 + PCC_20 -- Portable C Compiler on TOPS-20 + +Operating systems: + OS_PCDOS -- IBM (and clones) PC DOS and MS DOS + OS_TOPS20 -- DEC-20 TOPS-20 + OS_UNIX -- Unix (almost any variant) + OS_VAXVMS -- VAX VMS + +Testing of this package has been carried on TOPS-20 (KCC-20 and PCC-20) +on DEC-20/60, , VAX VMS (CC) on VAX 8600, 4.3BSD Unix on VAX 8600, HPUX +on HP 9000, and PC DOS (IBM PC XT). It appears to work satisfactorily +on all of these, with the single exception that CTL-C handling on PC DOS +is not restored after a switch from raw mode; under all modes, CTL-C +still echoes as ^C<CR><LF>. Using DOS interrupt 0x33 instead of +signal() to save and restore the ctl-break status does not provide an +acceptable alternative; CTL-C always terminates execution. Further work +is necessary to resolve this. + +[08-Apr-87] +***********************************************************************/ + +#include <stdio.h> +#include "keydef.h" + +#ifndef OS_PCDOS +#define OS_PCDOS 0 +#endif + +#ifndef IBM_PC_MICROSOFT +#define IBM_PC_MICROSOFT 0 +#endif + +#ifndef OS_TOPS20 +#define OS_TOPS20 0 +#endif + +#ifndef KCC_20 +#define KCC_20 0 +#endif + +#ifndef PCC_20 +#define PCC_20 0 +#endif + +#ifndef OS_UNIX +#define OS_UNIX 0 +#endif + +#ifndef ATT +#define ATT 0 +#endif + +#ifndef BSD +#define BSD 0 +#endif + +#ifndef HPUX +#define HPUX 0 +#endif + +#ifndef OS_VAXVMS +#define OS_VAXVMS 0 +#endif + +#if OS_TOPS20 +#if (KCC_20 | PCC_20) +#else +#undef PCC_20 +#define PCC_20 1 /* PCC-20 is default for Tops-20 */ +#endif +#endif + +#if (OS_PCDOS | OS_TOPS20 | OS_UNIX | OS_VAXVMS) +#else +#undef OS_UNIX +#define OS_UNIX 1 /* Unix is default operating system */ +#endif + +#if (ATT | BSD | HPUX) +#else +#undef BSD +#define BSD 1 /* BSD is default Unix variant */ +#endif + +#if OS_PCDOS +#include <conio.h> +#include <signal.h> + +#define TTYOPENFLAGS "rb" +#define TTYNAME "con" + +#define interrupt catch_int /* MSC Version 5.0 raises syntax error otherwise */ +static int (*signal_status)(); +static void interrupt(); +#endif /* OS_PCDOS */ + +#if OS_TOPS20 +#define TTYNAME "TTY:" +static int w_rfmod; /* terminal mode word */ +static int w_rpcap; /* process capability word */ +static int w_rtiw; /* terminal interrupt word */ +static int w_morxo; /* end-of-page mode */ +static int kbrestore(); /* restore terminal settings */ +/* +** KCC-20 and PCC-20 have similar enough JSYS interfaces that we just +** use KCC symbolic names, and then redefine them for PCC-20. PCC-20 +** has a working ioctl() that could be used for Unix-style processing +** too, although it has a bug in that it resets the terminal width to 0, +** and disables pause at end of page. It therefore seems easier to use +** direct Monitor calls both both KCC-20 and PCC-20. +*/ + +#if KCC_20 +#include <jsys.h> +#include <monsym.h> +#define jfnof(x) _CTTRM /* we use direct JSYS'es for now */ +#define TTYASCMOD FLD(_TTASC,TT_DAM) +#define TTYBINMOD FLD(_TTBIN,TT_DAM) +#define TTYDAM FLD(-1,TT_DAM) +#define TTYECHO FLD(-1,TT_ECO) +#define TTYOPENFLAGS "rb8" +#define TTYPGM FLD(-1,TT_PGM) +#endif /* KCC_20 */ + +#if PCC_20 +#include <file.h> +#include <monsym.h> +#undef jfnof +#define jfnof(x) _CTTRM /* we use direct JSYS'es for now */ +/* Convert names in better KCC-20 style to PCC-20 style */ +#define BIN JSbin +#define DOBE JSdobe +#define MTOPR JSmtopr +#define RFMOD JSrfmod +#define RPCAP JSrpcap +#define RTIW JSrtiw +#define SC_CTC makefield(SC_ctc,-1) /* WARNING: PCC bug--see below */ +#define SFMOD JSsfmod +#define SIBE JSsibe +#define STIW JSstiw +#define STPAR JSstpar +#define TTYASCMOD makefield(TT_dam,TTasc) +#define TTYBINMOD makefield(TT_dam,TTbin) +#define TTYDAM makefield(TT_dam,-1) +#define TTYPGM makefield(TT_pgm,-1) +#define TTYECHO makefield(TT_eco,-1) +#define TTYOPENFLAGS "rb" +#define _CTTRM CTtrm +#define _FHJOB 0777773 +#define _FHSLF FHslf +#define _MOXOF MOxof +#define _MOOFF MOoff +#define _MORXO MOrxo +#endif /* PCC_20 */ + +#endif /* OS_TOPS20 */ + +#if OS_UNIX + +#if (ATT | HPUX) +typedef int BOOLEAN; +#define FALSE 0 +#define TRUE 1 + +#include <fcntl.h> +#include <termio.h> + +static struct termio tty; +static struct termio ttysave; +static int setblock(); +#endif + +#if BSD +#include <sgtty.h> +#include <sys/ioctl.h> + +static struct sgttyb tty; +static struct sgttyb ttysave; +#endif + +#define TTYOPENFLAGS "r" +#define TTYNAME "/dev/tty" +#endif /* OS_UNIX */ + +#if OS_VAXVMS +#include <ssdef.h> +#include <descrip.h> +#include <iodef.h> +#include <ttdef.h> +#include <tt2def.h> + +#define TTYOPENFLAGS "rb" +#define TTYNAME ctermid((char*)NULL) +static int status; /* system service status */ +static int tt_channel = -1; /* terminal channel for image QIO's */ +static int iomask; /* QIO flag mask */ +static $DESCRIPTOR(sys_in,"TT:"); /* terminal descriptor */ + +static struct +{ + unsigned char class; + unsigned char type; + unsigned short buffer_size; + unsigned long tt; + unsigned long tt2; +} mode_buf,mode_save; + +static struct +{ + unsigned short typeahead_count; + unsigned char first_char; + unsigned char reserved[5]; +} typeahead_buf; + +#define FAILED(status) (~(status) & 1) /* failure if LSB is 0 */ + +#endif /* OS_VAXVMS */ + +/*====================================================================*/ + +#define BADMODE ((KEYMODE)(EOF)) /* unset mode value */ +#define EMPTY 32767 /* flag for empty pushback buffer */ + +static KEYMODE kbcurrmode = BADMODE; /* current mode */ +static KEYMODE kbsavedmode = BADMODE; /* saved mode */ +static int kbpushback = EMPTY; /* character pushback buffer */ +static FILE* kbfp = (FILE*)NULL; /* keyboard file pointer */ +static int kbinit = 0; /* initialization flag */ + +#if OS_PCDOS +/*====================================================================*/ + +static void +interrupt() +{ + if (kbpushback == EMPTY) + kbpushback = 3; /* CTL-C */ +} +#endif /* OS_PCDOS */ + +/*====================================================================*/ + +int +kbclose() /* close the keyboard file */ +{ /* return EOF on error, 0 on success */ + if (!kbinit) + return (EOF); + kbinit = 0; + +#if OS_PCDOS + (void)signal(SIGINT,signal_status); + return (0); +#endif /* OS_PCDOS */ + +#if OS_TOPS20 + return (kbrestore()); +#endif /* OS_TOPS20 */ + + +#if OS_UNIX +#if (ATT | HPUX) + if (ioctl(fileno(kbfp),TCSETAF,&ttysave) == -1) + return (EOF); +#endif /* (ATT | HPUX) */ +#if BSD + if (ioctl(fileno(kbfp),TIOCSETP,&ttysave) == -1) + return (EOF); +#endif /* BSD */ + + return (kbfp == (FILE *)NULL ? EOF : fclose(kbfp)); +#endif /* OS_UNIX */ + +#if OS_VAXVMS + status = sys$qiow(0,tt_channel,IO$_SETMODE,0,0,0, &mode_save,12,0,0,0,0); + if (FAILED(status)) + return (EOF); + return (0); +#endif /* OS_VAXVMS */ +} + +/*====================================================================*/ + +FILE* +kbfile() /* return keyboard file pointer */ +{ + return (kbinit ? kbfp : (FILE*)NULL); +} + +/*====================================================================*/ + +int +kbflush() /* flush current input buffer */ +{ + if (!kbinit) + return (EOF); + while (kbinput() > 0) + (void)kbget(); + return (0); +} + + +/*====================================================================*/ + +int +kbget() /* blocking read of character */ +{ /* return character, or EOF on end-of-file or error */ + int c; + + if (!kbinit) + return (EOF); + else if (kbpushback == EMPTY) + { + +#if OS_PCDOS + c = (kbcurrmode & KB_ECHO) ? getche() : getch(); +#endif /* OS_PCDOS */ + +#if OS_TOPS20 + ac1 = _CTTRM; + c = ((jsys(BIN,acs) == JSok) ? ac2 : EOF); +#endif /* OS_TOPS20 */ + + +#if OS_UNIX +#if (ATT | HPUX) + if (setblock(fileno(kbfp),TRUE) == EOF) + return (EOF); + if (read(fileno(kbfp),&c,1) <= 0) + c = EOF; +#endif /* (ATT | HPUX) */ +#if BSD + c = getc(kbfp); +#endif /* BSD */ +#endif /* OS_UNIX */ + +#if OS_VAXVMS + status = sys$qiow(0,tt_channel,iomask,0,0,0,&c,1,0,0,0,0); + if (FAILED(status)) + c = EOF; +#endif /* OS_VAXVMS */ + + } + else + { + c = kbpushback; + kbpushback = EMPTY; + } + return (c == EOF ? c : (int)(0377 & c)); /* make sure it is 8-bit value */ +} + +/*====================================================================*/ + +int +kbinput() /* input available? */ +{ /* return count of available input characters, 0 if none, or EOF on error */ + + if (!kbinit) + return (EOF); + else if (kbpushback != EMPTY) + return (1); + else + { +#if OS_PCDOS + return (kbhit() ? 1 : 0); /* otherwise returns 255 */ +#endif /* OS_PCDOS */ + +#if OS_TOPS20 + ac1 = jfnof(fileno(kbfp)); + if (jsys(SIBE,acs) == JSok) + return (0); /* input buffer empty */ + else + return (ac2); /* input character count */ +#endif /* OS_TOPS20 */ + +#if OS_UNIX +#if (ATT | HPUX) + { + char c; + + if (setblock(fileno(kbfp),FALSE) == EOF) + return (EOF); + switch (read(fileno(kbfp),&c,1)) + { + case -1: + return (EOF); + + case 0: + return (0); + + default: + kbpushback = (int)c; + return (1); + } + } +#endif /* (ATT | HPUX) */ +#if BSD + { + int count; + + return ((ioctl(fileno(kbfp), FIONREAD, &count) == -1) ? EOF : count); + } +#endif /* BSD */ +#endif /* OS_UNIX */ + +#if OS_VAXVMS + status = sys$qiow(0,tt_channel,IO$_SENSEMODE | IO$M_TYPEAHDCNT, + 0,0,0,&typeahead_buf,8,0,0,0,0); + return (FAILED(status) ? EOF : typeahead_buf.typeahead_count); +#endif /* OS_VAXVMS */ + } +} + +/*====================================================================*/ + +KEYMODE +kbmode(mode) /* keyboard mode */ +KEYMODE mode; /* return new mode on success, EOF on error */ +{ + if (!kbinit) + return (EOF); + + switch (mode & (KB_INQUIRE | KB_RESTORE | KB_SAVE)) + { + case 0: + break; /* must be a set-mode operation */ + + case KB_INQUIRE: + return (kbcurrmode); + + case KB_RESTORE: + if (kbsavedmode = BADMODE) + return (BADMODE); + else + { + kbcurrmode = kbsavedmode; + kbcurrmode &= ~(KB_INQUIRE | KB_RESTORE | KB_SAVE); + return (kbmode(kbcurrmode)); + } + + case KB_SAVE: + kbsavedmode = kbcurrmode; + return (kbcurrmode); + + default: /* do not allow mixed mode flags */ + return (BADMODE); + } + +#if OS_TOPS20 + if (kbrestore() == EOF) /* restore terminal settings */ + return (BADMODE); +#endif /* OS_TOPS20 */ + + switch (mode & (KB_CBREAK | KB_NORMAL | KB_RAW)) /* set-mode request */ + { +#if OS_PCDOS + case KB_CBREAK: + case KB_NORMAL: + (void)signal(SIGINT,signal_status); + break; + + case KB_RAW: + (void)signal(SIGINT,interrupt); + break; +#endif /* OS_PCDOS */ + +#if OS_TOPS20 + case KB_CBREAK: + case KB_NORMAL: + ac1 = jfnof(fileno(kbfp)); + ac2 = w_rfmod & ~TTYECHO; /* clear TT%ECO field (want no echo) */ + if (jsys(SFMOD,acs) != JSok) + return (BADMODE); + if (jsys(STPAR,acs) != JSok) + return (BADMODE); + break; + + case KB_RAW: + /* Wait for output to flush; if the screen is at end-of-page, we + are waiting for the user to type CTL-Q, which will have no + effect once we enter raw mode, and the terminal will be hung! */ + ac1 = _CTTRM; + if (jsys(DOBE,acs) != JSok) /* dismiss until output buffer empty */ + return (BADMODE); + + ac1 = jfnof(fileno(kbfp)); + ac2 = w_rfmod; + ac2 &= ~(TTYECHO | TTYDAM | TTYPGM); /* clear fields */ + ac2 |= TTYBINMOD; /* set binary mode */ + if (jsys(SFMOD,acs) != JSok) + return (BADMODE); + if (jsys(STPAR,acs) != JSok) + return (BADMODE); + + ac1 = _FHJOB; + +#if KCC_20 + if (w_rpcap & SC_CTC) /* then have CTL-C capability */ +#endif /* KCC_20 */ +#if PCC_20 + ac3 = 0600000000000; /* PCC BUG: 0400000000000 becomes 0! */ + ac3 &=0200000000000; /* so make it on-the-fly */ + if (w_rpcap & ac3) +#endif /* PCC_20 */ + ac2 &= 077; /* read all ctl-chars */ + else + ac2 &= 0040000000077; /* read all ctl-chars but CTL-C */ + if (jsys(STIW,acs) != JSok) /* reset terminal interrupt word */ + return (BADMODE); + + ac1 = _CTTRM; + ac2 = _MOXOF; + ac3 = _MOOFF; /* disable pause at end-of-page */ + if (jsys(MTOPR,acs) != JSok) /* otherwise we can hang waiting for */ + return (BADMODE); /* a CTL-Q which is eaten as input! */ + + break; +#endif /* OS_TOPS20 */ + +#if OS_UNIX +#if (ATT | HPUX) + case KB_CBREAK: + tty = ttysave; + tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | ISTRIP | IXON | BRKINT); + tty.c_lflag &= ~(ECHO | ICANON); + tty.c_cc[4] = 5; /* MIN */ + tty.c_cc[5] = 2; /* TIME */ + if (ioctl(fileno(kbfp),TCSETAF,&tty) == -1) + return (BADMODE); + break; + + case KB_NORMAL: + tty = ttysave; + tty.c_lflag &= ~ECHO; + tty.c_cc[4] = 5; /* MIN */ + tty.c_cc[5] = 2; /* TIME */ + if (ioctl(fileno(kbfp),TCSETAF,&tty) == -1) + return (BADMODE); + break; + + case KB_RAW: + tty = ttysave; + tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | ISTRIP | IXON | BRKINT); + tty.c_lflag &= ~(ICANON | ISIG | ECHO); + tty.c_cc[4] = 5; /* MIN */ + tty.c_cc[5] = 2; /* TIME */ + if (ioctl(fileno(kbfp),TCSETAF,&tty) == -1) + return (BADMODE); + break; +#endif /* (ATT | HPUX) */ + +#if BSD + case KB_CBREAK: + tty = ttysave; + tty.sg_flags &= ~(CRMOD | ECHO | LCASE); + tty.sg_flags |= CBREAK; + if (ioctl(fileno(kbfp),TIOCSETP,&tty) == -1) + return (BADMODE); + break; + + case KB_NORMAL: + tty = ttysave; + tty.sg_flags &= ~(CBREAK | CRMOD | ECHO | LCASE | RAW); + if (ioctl(fileno(kbfp),TIOCSETP,&tty) == -1) + return (BADMODE); + break; + + case KB_RAW: + tty = ttysave; + tty.sg_flags &= ~(CRMOD | ECHO | LCASE | TANDEM); + tty.sg_flags |= (CBREAK | RAW); + if (ioctl(fileno(kbfp),TIOCSETP,&tty) == -1) + return (BADMODE); + + break; +#endif /* BSD */ +#endif /* OS_UNIX */ + +#if OS_VAXVMS + case KB_CBREAK: + case KB_NORMAL: + mode_buf = mode_save; + mode_buf.tt &= ~TT$M_WRAP; + status = sys$qiow(0,tt_channel,IO$_SETMODE,0,0,0,&mode_buf,12,0,0,0,0); + if (FAILED(status)) + return (EOF); + iomask = IO$_TTYREADALL | IO$M_NOECHO; + break; + + case KB_RAW: + mode_buf = mode_save; + mode_buf.tt &= ~(TT$M_TTSYNC | TT$M_WRAP); + mode_buf.tt2 |= TT2$M_PASTHRU; + mode_buf.tt2 &= ~TT2$M_XON; + status = sys$qiow(0,tt_channel,IO$_SETMODE,0,0,0,&mode_buf,12,0,0,0,0); + if (FAILED(status)) + return (EOF); + iomask = IO$_TTYREADALL | IO$M_NOECHO; + break; +#endif /* OS_VAXVMS */ + + default: /* do not allow mixed mode flags */ + return (BADMODE); + } + kbcurrmode = mode; + kbcurrmode &= ~(KB_INQUIRE | KB_RESTORE | KB_SAVE); + + if (mode & KB_ECHO) + { +#if OS_PCDOS + /* NO-OP */ ; +#endif /* OS_PCDOS */ + +#if OS_TOPS20 + ac1 = jfnof(fileno(kbfp)); + ac2 = w_rfmod | TTYECHO; /* set echo mode */ + if (jsys(SFMOD,acs) != JSok) + return (BADMODE); +#endif /* OS_TOPS20 */ + + +#if OS_UNIX +#if (ATT | HPUX) + /* ??? do not yet know how to handle this ??? */ +#endif /* (ATT | HPUX) */ +#if BSD + if (ioctl(fileno(kbfp),TIOCGETP,&tty) == -1) + return (BADMODE); + tty.sg_flags |= ECHO; + if (ioctl(fileno(kbfp),TIOCSETP,&tty) == -1) + return (BADMODE); +#endif /* BSD */ +#endif /* OS_UNIX */ + +#if OS_VAXVMS + iomask &= ~IO$M_NOECHO; /* turn off no-echo flag */ +#endif /* OS_VAXVMS */ + } + return (kbcurrmode); +} + +/*====================================================================*/ + +int +kbopen(mode) /* open keyboard with mode (KB_xxxx flags) */ +int mode; /* return 0 on success, EOF on error */ +{ + if (kbinit) /* ignore if already open */ + return (EOF); + +#if OS_PCDOS + kbfp = (FILE*)NULL; /* we use direct console input */ + signal_status = signal(SIGINT,SIG_IGN); + (void)signal(SIGINT,signal_status); +#endif /* OS_PCDOS */ + +#if OS_TOPS20 + kbfp = (FILE*)NULL; /* we use direct JSYS'es */ + + /* save terminal characteristics for later modification and restoration */ + ac1 = _CTTRM; + if (jsys(RFMOD,acs) != JSok) /* request terminal mode word */ + return (EOF); + w_rfmod = ac2; + + ac1 = _FHSLF; + if (jsys(RPCAP,acs) != JSok) /* request process capabilities */ + return (EOF); + w_rpcap = ac2; + + ac1 = _FHJOB; + if (jsys(RTIW,acs) != JSok) /* request terminal interrupt word */ + return (EOF); + w_rtiw = ac2; + + ac1 = _CTTRM; + ac2 = _MORXO; + if (jsys(MTOPR,acs) != JSok) /* request end-of-page mode */ + return (EOF); + w_morxo = ac3; +#endif /* OS_TOPS20 */ + +#if OS_UNIX + if ((kbfp = fopen(TTYNAME,TTYOPENFLAGS)) == (FILE*)NULL) + return (EOF); + +#if (ATT | HPUX) + if (ioctl(fileno(kbfp),TCGETA,&ttysave) == -1) + return (EOF); +#endif + +#if BSD + if (ioctl(fileno(kbfp),TIOCGETP,&ttysave) == -1) + return (EOF); +#endif /* BSD */ +#endif /* OS_UNIX */ + +#if OS_VAXVMS + kbfp = (FILE*)NULL; /* we use direct system calls */ + + status = sys$assign(&sys_in,&tt_channel,0,0); + if (FAILED(status)) + return (EOF); + status = sys$qiow(0,tt_channel,IO$_SENSEMODE,0,0,0, &mode_save,12,0,0,0,0); + if (FAILED(status)) + return (EOF); +#endif /* OS_VAXVMS */ + + kbinit = 1; + if (kbmode(mode) == (KEYMODE)EOF) + { + if (kbfp != (FILE*)NULL) + (void)fclose(kbfp); + kbinit = 0; + kbfp = (FILE*)NULL; + return (EOF); + } + + return (0); +} + +#if OS_TOPS20 +/*====================================================================*/ +static int +kbrestore() /* restore terminal settings */ +{ /* return 0 on success, EOF on error */ + ac1 = jfnof(fileno(kbfp)); + ac2 = w_rfmod; + if (jsys(SFMOD,acs) != JSok) /* set program-related modes */ + return (EOF); + if (jsys(STPAR,acs) != JSok) /* set device-related modes */ + return (EOF); + + ac1 = _FHJOB; + ac2 = w_rtiw; + if (jsys(STIW,acs) != JSok) /* set terminal interrupt word */ + return (EOF); + + ac1 = _CTTRM; + ac2 = _MOXOF; + ac3 = w_morxo; + if (jsys(MTOPR,acs) != JSok) /* restore end-of-page mode */ + return (EOF); + + return (0); +} + +#endif /* OS_TOPS20 */ + +/*====================================================================*/ + +int +kbunget(c) /* unget keyboard character (1-level pushback) */ +char c; /* return c, or EOF on error (already pushed back character) */ +{ + if (!kbinit) + return (EOF); + else if (kbpushback != EMPTY) + return (EOF); + else + { + kbpushback = (int)c; + return (kbpushback); + } +} + + +#if OS_UNIX +#if (ATT | HPUX) +static int +setblock(fd,on) /* turn blocking on or off */ + /* return EOF on error, 0 on success */ +int fd; /* file descriptor */ +BOOLEAN on; /* FALSE == turn off, TRUE == turn on */ +{ + static int blockf; + static int nonblockf; + static BOOLEAN first = TRUE; + int flags; + + if (first) + { + first = FALSE; + if ((flags = fcntl(fd,F_GETFL,0)) == -1) + return (EOF); + blockf = flags & ~O_NDELAY; /* turn off O_NDELAY */ + nonblockf = flags | O_NDELAY; /* turn on O_NDELAY */ + } + if (fcntl(fd,F_SETFL,on ? blockf : nonblockf) == -1) + return (EOF); + return (0); +} +#endif /* (ATT | HPUX) */ +#endif /* OS_UNIX */ |