2015-01-01 21:54:35 -05:00
|
|
|
/* termio.c -- implements termio.h */
|
2013-05-20 03:16:19 -04:00
|
|
|
#include "termio.h"
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2021-08-18 04:54:35 -04:00
|
|
|
#include "defines.h" /* POSIX */
|
2021-08-17 21:37:47 -04:00
|
|
|
#ifndef POSIX
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
|
|
|
|
modified by Petri Kutvonen
|
2005-05-31 11:50:56 -04:00
|
|
|
*/
|
|
|
|
|
2013-09-25 09:45:05 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2013-10-10 23:20:06 -04:00
|
|
|
#include "retcode.h"
|
2013-09-25 09:45:05 -04:00
|
|
|
#include "utf8.h"
|
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2013-04-30 22:06:08 -04:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
2021-08-17 23:35:17 -04:00
|
|
|
int ttrow = -1 ; /* Row location of HW cursor */
|
|
|
|
int ttcol = -1 ; /* Column location of HW cursor */
|
2013-09-25 09:45:05 -04:00
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
#if USG /* System V */
|
|
|
|
#include <signal.h>
|
|
|
|
#include <termio.h>
|
|
|
|
#include <fcntl.h>
|
2015-02-16 00:41:59 -05:00
|
|
|
static int kbdflgs ; /* saved keyboard fd flags */
|
|
|
|
static int kbdpoll ; /* in O_NDELAY mode */
|
|
|
|
static int kbdqp ; /* there is a char in kbdq */
|
|
|
|
static char kbdq ; /* char we've already read */
|
|
|
|
static struct termio otermio ; /* original terminal characteristics */
|
|
|
|
static struct termio ntermio ; /* characteristics to use inside */
|
2014-06-18 02:59:40 -04:00
|
|
|
#if XONXOFF
|
|
|
|
#define XXMASK 0016000
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2019-07-23 09:04:50 -04:00
|
|
|
#if BSD
|
2014-06-18 02:59:40 -04:00
|
|
|
#include <sgtty.h> /* for stty/gtty functions */
|
|
|
|
#include <signal.h>
|
|
|
|
struct sgttyb ostate; /* saved tty state */
|
|
|
|
struct sgttyb nstate; /* values for editor mode */
|
|
|
|
struct tchars otchars; /* Saved terminal special character set */
|
|
|
|
#if XONXOFF
|
2005-09-30 18:26:09 -04:00
|
|
|
struct tchars ntchars = { 0xff, 0xff, 0x11, 0x13, 0xff, 0xff };
|
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
/* A lot of nothing and XON/XOFF */
|
2005-05-31 11:50:56 -04:00
|
|
|
#else
|
2005-09-30 18:26:09 -04:00
|
|
|
struct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
/* A lot of nothing */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2014-06-18 02:59:40 -04:00
|
|
|
#if BSD & PKCODE
|
|
|
|
struct ltchars oltchars; /* Saved terminal local special character set */
|
2005-09-30 18:26:09 -04:00
|
|
|
struct ltchars nltchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
/* A lot of nothing */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if BSD
|
2014-06-18 02:59:40 -04:00
|
|
|
#include <sys/ioctl.h> /* to get at the typeahead */
|
|
|
|
extern int rtfrmshell(); /* return from suspended shell */
|
|
|
|
#define TBUFSIZ 128
|
|
|
|
char tobuf[TBUFSIZ]; /* terminal output buffer */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2019-08-07 01:17:26 -04:00
|
|
|
#if SVR4
|
2014-06-18 02:59:40 -04:00
|
|
|
extern int rtfrmshell(); /* return from suspended shell */
|
2005-05-31 11:50:56 -04:00
|
|
|
#define TBUFSIZ 128
|
2014-06-18 02:59:40 -04:00
|
|
|
char tobuf[TBUFSIZ]; /* terminal output buffer */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is called once to set up the terminal device streams.
|
2019-07-03 20:06:13 -04:00
|
|
|
* On CPM it is a no-op.
|
2005-05-31 11:50:56 -04:00
|
|
|
*/
|
2010-01-29 19:17:02 -05:00
|
|
|
void ttopen(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2014-06-18 02:59:40 -04:00
|
|
|
#if USG
|
|
|
|
ioctl(0, TCGETA, &otermio); /* save old settings */
|
|
|
|
ntermio.c_iflag = 0; /* setup new settings */
|
|
|
|
#if XONXOFF
|
|
|
|
ntermio.c_iflag = otermio.c_iflag & XXMASK; /* save XON/XOFF P.K. */
|
|
|
|
#endif
|
|
|
|
ntermio.c_oflag = 0;
|
|
|
|
ntermio.c_cflag = otermio.c_cflag;
|
|
|
|
ntermio.c_lflag = 0;
|
|
|
|
ntermio.c_line = otermio.c_line;
|
|
|
|
ntermio.c_cc[VMIN] = 1;
|
|
|
|
ntermio.c_cc[VTIME] = 0;
|
|
|
|
#if PKCODE
|
|
|
|
ioctl(0, TCSETAW, &ntermio); /* and activate them */
|
2005-05-31 11:50:56 -04:00
|
|
|
#else
|
2014-06-18 02:59:40 -04:00
|
|
|
ioctl(0, TCSETA, &ntermio); /* and activate them */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2014-06-18 02:59:40 -04:00
|
|
|
kbdflgs = fcntl(0, F_GETFL, 0);
|
|
|
|
kbdpoll = FALSE;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2019-07-23 09:04:50 -04:00
|
|
|
#if BSD
|
2014-06-18 02:59:40 -04:00
|
|
|
gtty(0, &ostate); /* save old state */
|
|
|
|
gtty(0, &nstate); /* get base of new state */
|
|
|
|
#if XONXOFF
|
|
|
|
nstate.sg_flags |= (CBREAK | TANDEM);
|
2005-05-31 11:50:56 -04:00
|
|
|
#else
|
2014-06-18 02:59:40 -04:00
|
|
|
nstate.sg_flags |= RAW;
|
|
|
|
#endif
|
|
|
|
nstate.sg_flags &= ~(ECHO | CRMOD); /* no echo for now... */
|
|
|
|
stty(0, &nstate); /* set mode */
|
|
|
|
ioctl(0, TIOCGETC, &otchars); /* Save old characters */
|
|
|
|
ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */
|
|
|
|
#if BSD & PKCODE
|
|
|
|
ioctl(0, TIOCGLTC, &oltchars); /* Save old local characters */
|
|
|
|
ioctl(0, TIOCSLTC, &nltchars); /* New local characters */
|
|
|
|
#endif
|
|
|
|
#if BSD
|
|
|
|
/* provide a smaller terminal output buffer so that
|
|
|
|
the type ahead detection works better (more often) */
|
|
|
|
setbuffer(stdout, &tobuf[0], TBUFSIZ);
|
|
|
|
signal(SIGTSTP, SIG_DFL); /* set signals so that we can */
|
|
|
|
signal(SIGCONT, rtfrmshell); /* suspend & restart emacs */
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2019-08-07 01:17:26 -04:00
|
|
|
#if SVR4
|
2014-06-18 02:59:40 -04:00
|
|
|
/* provide a smaller terminal output buffer so that
|
|
|
|
the type ahead detection works better (more often) */
|
|
|
|
setvbuf(stdout, &tobuf[0], _IOFBF, TBUFSIZ);
|
|
|
|
signal(SIGTSTP, SIG_DFL); /* set signals so that we can */
|
|
|
|
signal(SIGCONT, rtfrmshell); /* suspend & restart emacs */
|
|
|
|
TTflush();
|
2019-08-07 01:17:26 -04:00
|
|
|
#endif
|
2014-06-18 02:59:40 -04:00
|
|
|
|
|
|
|
/* on all screens we are not sure of the initial position
|
|
|
|
of the cursor */
|
2021-08-17 23:35:17 -04:00
|
|
|
ttrow = ttcol = -1 ;
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function gets called just before we go back home to the command
|
2019-07-03 20:06:13 -04:00
|
|
|
* interpreter.
|
2005-05-31 11:50:56 -04:00
|
|
|
* Another no-operation on CPM.
|
|
|
|
*/
|
2010-01-29 19:17:02 -05:00
|
|
|
void ttclose(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2014-06-18 02:59:40 -04:00
|
|
|
#if USG
|
|
|
|
#if PKCODE
|
|
|
|
ioctl(0, TCSETAW, &otermio); /* restore terminal settings */
|
2005-05-31 11:50:56 -04:00
|
|
|
#else
|
2014-06-18 02:59:40 -04:00
|
|
|
ioctl(0, TCSETA, &otermio); /* restore terminal settings */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2014-06-18 02:59:40 -04:00
|
|
|
fcntl(0, F_SETFL, kbdflgs);
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2019-07-23 09:04:50 -04:00
|
|
|
#if BSD
|
2014-06-18 02:59:40 -04:00
|
|
|
stty(0, &ostate);
|
|
|
|
ioctl(0, TIOCSETC, &otchars); /* Place old character into K */
|
|
|
|
#if BSD & PKCODE
|
|
|
|
ioctl(0, TIOCSLTC, &oltchars); /* Place old local character into K */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-05-04 22:49:02 -04:00
|
|
|
* Write a character to the display.
|
2005-05-31 11:50:56 -04:00
|
|
|
*/
|
2016-04-08 23:46:40 -04:00
|
|
|
int ttputc( unicode_t c) {
|
2017-05-04 22:49:02 -04:00
|
|
|
char utf8[ 4] ;
|
|
|
|
int bytes ;
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2017-05-04 22:49:02 -04:00
|
|
|
bytes = unicode_to_utf8( c, utf8) ;
|
|
|
|
fwrite( utf8, 1, bytes, stdout) ;
|
|
|
|
return 0 ;
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-04-30 22:06:08 -04:00
|
|
|
void ttflush( void) {
|
2019-07-23 09:04:50 -04:00
|
|
|
#if USG | BSD
|
2005-05-31 11:50:56 -04:00
|
|
|
/*
|
|
|
|
* Add some terminal output success checking, sometimes an orphaned
|
|
|
|
* process may be left looping on SunOS 4.1.
|
|
|
|
*
|
|
|
|
* How to recover here, or is it best just to exit and lose
|
|
|
|
* everything?
|
|
|
|
*
|
|
|
|
* jph, 8-Oct-1993
|
|
|
|
*/
|
|
|
|
|
2005-09-30 18:26:09 -04:00
|
|
|
#include <errno.h>
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
int status;
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
status = fflush(stdout);
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
if (status != 0 && errno != EAGAIN) {
|
|
|
|
exit(errno);
|
|
|
|
}
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a character from the terminal, performing no editing and doing no echo
|
2019-07-03 20:06:13 -04:00
|
|
|
* at all.
|
|
|
|
* Very simple on CPM, because the system can do exactly what you want.
|
2005-05-31 11:50:56 -04:00
|
|
|
*/
|
2013-04-30 22:06:08 -04:00
|
|
|
int ttgetc( void) {
|
2019-07-23 09:04:50 -04:00
|
|
|
#if BSD
|
2014-06-18 02:59:40 -04:00
|
|
|
return 255 & fgetc(stdin); /* 8BIT P.K. */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
#if USG
|
|
|
|
if (kbdqp)
|
|
|
|
kbdqp = FALSE;
|
|
|
|
else {
|
|
|
|
if (kbdpoll && fcntl(0, F_SETFL, kbdflgs) < 0)
|
|
|
|
return FALSE;
|
|
|
|
kbdpoll = FALSE;
|
|
|
|
while (read(0, &kbdq, 1) != 1);
|
|
|
|
}
|
|
|
|
return kbdq & 255;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
#if TYPEAH
|
|
|
|
/* typahead: Check to see if any characters are already in the
|
|
|
|
keyboard buffer
|
2005-05-31 11:50:56 -04:00
|
|
|
*/
|
|
|
|
|
2013-04-30 22:06:08 -04:00
|
|
|
int typahead( void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2014-06-18 02:59:40 -04:00
|
|
|
#if BSD
|
|
|
|
int x; /* holds # of pending chars */
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
return (ioctl(0, FIONREAD, &x) < 0) ? 0 : x;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
#if USG
|
|
|
|
if (!kbdqp) {
|
|
|
|
if (!kbdpoll && fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0)
|
|
|
|
return FALSE;
|
|
|
|
#if PKCODE
|
|
|
|
kbdpoll = 1;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2014-06-18 02:59:40 -04:00
|
|
|
kbdqp = (1 == read(0, &kbdq, 1));
|
|
|
|
}
|
|
|
|
return kbdqp;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2021-08-17 21:37:47 -04:00
|
|
|
# if !UNIX
|
2014-06-18 02:59:40 -04:00
|
|
|
return FALSE;
|
2021-08-17 21:37:47 -04:00
|
|
|
# endif
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
2021-08-17 21:37:47 -04:00
|
|
|
# endif
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2014-06-18 02:59:40 -04:00
|
|
|
#endif /* not POSIX */
|
2015-11-24 21:42:33 -05:00
|
|
|
|
|
|
|
/* end of termio.c */
|