home *** CD-ROM | disk | FTP | other *** search
- static char sccs_id[] = "@(#) tty.c 4.0 " __DATE__ " HJR";
-
- /* tty.c (c) Copyright 1990 H.Rogers */
-
- /* SYS V tty device driver for RiscOS */
-
- #include <signal.h>
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #include <stdlib.h>
-
- #include "fcntl.h"
- #include "termio.h"
-
- #include "sys/types.h"
- #include "sys/unix.h"
- #include "sys/dev.h"
- #include "sys/tty.h"
- #include "sys/os.h"
- #include "sys/param.h"
-
- static struct tty *__t; /* current tty */
-
- #define __ttyx(x) /* increment cursor posn. by (x) */ \
- (__t->sx += (x), \
- __t->del[__t->cx = (__t->cx + 1) & (MAXPATHLEN - 1)] = (x))
-
- static int __ttyicanon (void *buf, int nbyte, struct file *f);
- static int __ttyiraw (void *buf, int nbyte, struct file *f);
-
- static int __ttyinput (int c, int iflag);
- static void __ttyecho (int c, int oflag, int lflag);
- static void __ttydel (int lflag);
- static void __ttytab (int oflag);
- static void __ttycr (int oflag);
- static void __ttynl (int oflag);
-
- static char __ttybaud[0x10] =
- {0, 9, 1, 10, 11, 2, 0, 3, 12, 4, 13, 5, 6, 7, 8, 0};
-
- /* get console window size */
-
- static void
- __tty_console_gwinsz (register struct winsize *w)
- {
- static int i[9] =
- {132, 134, 135, 133, 128, 130, 129, 131, -1};
- int o[8];
- int r[10];
-
- r[0] = (int) i;
- r[1] = (int) o;
- os_swi (0x31, r);
- w->ws_col = o[1] - o[0] + 1;
- w->ws_row = o[3] - o[2] + 1;
- w->ws_xpixel = o[5] - o[4] + 1;
- w->ws_ypixel = o[7] - o[6] + 1;
- }
-
- /* set console window size */
-
- static void
- __tty_console_swinsz (register struct winsize *w)
- {
- static int i[7] =
- {132, 135, 128, 131, 4, 5, -1};
- int o[6];
- int r[10];
- register int j;
-
- r[0] = (int) i;
- r[1] = (int) o;
- os_swi (0x31, r);
- os_vdu (28);
- os_vdu (o[0]);
- os_vdu (o[1] + w->ws_row - 1);
- os_vdu (o[0] + w->ws_col - 1);
- os_vdu (o[1]);
- os_vdu (24);
- j = o[2];
- j <<= o[4];
- os_vdu (j & 0xff);
- os_vdu (j >> 8);
- j = o[3] - (w->ws_ypixel - 1);
- j <<= o[5];
- os_vdu (j & 0xff);
- os_vdu (j >> 8);
- j = o[2] + w->ws_xpixel - 1;
- j <<= o[4];
- os_vdu (j & 0xff);
- os_vdu (j >> 8);
- j = o[3];
- j <<= o[5];
- os_vdu (j & 0xff);
- os_vdu (j >> 8);
- }
-
- /* read console */
-
- static void
- __tty_console_gterm (register struct termio *t)
- {
- int r[3];
-
- os_byte (0xdc, 0, 0xff, r);
- t->c_cc[VINTR] = r[1];
- os_byte (0xe5, 0, 0xff, r);
- if (r[1])
- t->c_lflag &= ~ISIG;
- else
- t->c_lflag |= ISIG;
- }
-
- /* set console */
-
- static void
- __tty_console_sterm (register struct termio *t)
- {
- os_byte (0xdc, t->c_cc[VINTR], 0, 0);
- if (t->c_lflag & ISIG)
- os_byte (0xe5, 0, 0, 0);
- else
- os_byte (0xe5, 0xff, 0, 0);
- }
-
- /* set RS423 */
-
- static void
- __tty_423_sterm (register struct termio *t)
- {
- register int i, c;
- int r[10];
-
- i = t->c_cflag & CIBAUD;
- i = i ? (i >> IBSHIFT) : (t->c_cflag & CBAUD);
- r[0] = 5;
- if (r[1] = __ttybaud[i])
- os_swi (0x57, r);
- i = t->c_cflag & CBAUD;
- r[0] = 6;
- if (r[1] = __ttybaud[i])
- os_swi (0x57, r);
- i = t->c_cflag;
- switch (i & CSIZE)
- {
- case CS5:
- c = 3;
- break;
- case CS6:
- c = 2;
- break;
- case CS7:
- c = 1;
- break;
- case CS8:
- default:
- c = 0;
- break;
- }
- if (i & CSTOPB)
- c |= 0x04;
- if (i & PARENB)
- {
- c |= 0x08;
- if (!(i & PARODD))
- c |= 0x10;
- }
- r[0] = 1;
- r[1] = c;
- os_swi (0x57, r);
- }
-
- int
- __ttyopen (char *file, int mode, struct file *f)
- {
- struct tty *_t;
- int l;
-
- mode = mode;
-
- switch (*(file + 5))
- {
- case 'c': /* console */
- _t = __u->tty + (l = TTY_CON);
- __u->flag = (__u->flag & ~__U_TTY) | (TTY_CON << __U_TTYSHIFT);
- break;
- case 'r': /* rs423 */
- _t = __u->tty + (l = TTY_423);
- __u->flag = (__u->flag & ~__U_TTY) | (TTY_423 << __U_TTYSHIFT);
- break;
- case 't': /* tty */
- _t = __u->tty + (l = ((__u->flag & __U_TTY) >> __U_TTYSHIFT));
- break;
- default:
- return (-1);
- break;
- }
-
- {
- register struct termio *t = _t->t;
-
- t->c_iflag = BRKINT | ICRNL | IMAXBEL;
- t->c_oflag = OPOST | ONLCR | XTABS;
- if (l == TTY_CON)
- t->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
- else if (l == TTY_423)
- t->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- t->c_lflag = ISIG | ICANON | ECHO;
- t->c_line = 0;
-
- {
- static char cc[NCC] =
- {CINTR, CQUIT, CERASE, CKILL, CEOF, CEOL, CEOL2,
- CSWTCH, CSTART, CSTOP, CSUSP, 0, CREPRINT, CDISCARD, CWERASE, CLNEXT};
-
- memcpy (t->c_cc, cc, NCC);
- }
-
- if (l == TTY_CON)
- __tty_console_gterm (t); /* RS423 is set up later */
- }
-
- {
- register struct winsize *w = _t->w;
-
- if (l == TTY_CON)
- __tty_console_gwinsz (w);
- else if (l == TTY_423)
- {
- w->ws_col = 80;
- w->ws_row = 25;
- w->ws_xpixel = w->ws_ypixel = 0;
- }
- }
-
- if (l == TTY_CON)
- {
- _t->out = os_vdu;
- _t->in = os_get;
- _t->scan = os_inkey;
- _t->init = os_console;
- _t->flush = os_keyflush;
- }
- else if (l == TTY_423)
- {
- _t->out = os_423vdu;
- _t->in = os_423get;
- _t->scan = os_423inkey;
- _t->init = os_423;
- _t->flush = os_423flush;
- }
-
- _t->buf = _t->ptr = 0;
- _t->cnt = 0;
- _t->del = 0;
- _t->sx = _t->cx = 0;
-
- {
- register int *r = f->r;
-
- r[0] = r[1] = r[2] = r[3] = r[4] = 0;
- r[5] = 0x33;
- }
-
- (*(_t->init)) ();
-
- if (l == TTY_423)
- __tty_423_sterm (_t->t);
-
- return (l);
- }
-
- int
- __ttyclose (int l, struct file *f)
- {
- register struct tty *_t;
-
- f = f;
-
- _t = __u->tty + l;
-
- if (_t->del)
- free (_t->del);
- if (_t->buf)
- free (_t->buf);
-
- _t->buf = _t->ptr = 0;
- _t->cnt = 0;
- _t->del = 0;
- _t->sx = _t->cx = 0;
-
- return (0);
- }
-
-
- int
- __ttyread (int l, void *buf, int nbyte, struct file *f)
- {
- __t = __u->tty + l;
-
- if (!__t->del)
- if (!(__t->del = malloc (MAXPATHLEN)))
- {
- errno = ENOMEM;
- return (-1);
- }
-
- return ((__t->t->c_lflag & ICANON) ? \
- __ttyicanon (buf, nbyte, f) : \
- __ttyiraw (buf, nbyte, f));
- }
-
- static int
- __ttyicanon (void *buf, register int nbyte, struct file *f)
- {
- register int c, i;
- register char *s;
- register int nflag;
- register int iflag, oflag, lflag;
- register char *cc;
- int ceof, ceol, ceol2;
-
- #define F_LNEXT 000001
- #define F_MAX 000002
- #define F_NDELAY 000004
-
- if (!__t->buf)
- {
- if (!(__t->buf = malloc (MAXPATHLEN)))
- {
- errno = ENOMEM;
- return (-1);
- }
- __t->cnt = 0;
- __t->ptr = __t->buf;
- }
-
- if (__t == __u->tty)
- os_byte (0xe5, 0xff, 0, 0); /* disable SIGINT */
-
- ret:
-
- if (__t->cnt)
- {
- if (__t == __u->tty)
- os_byte (0xe5, 0, 0, 0); /* re-enable SIGINT */
-
- i = (nbyte > __t->cnt) ? __t->cnt : nbyte;
- memcpy (buf, __t->ptr, i);
- __t->cnt -= i;
- __t->ptr += i;
- return (i);
- }
-
- nflag = (f->oflag & O_NDELAY) ? F_NDELAY : 0;
- iflag = __t->t->c_iflag;
- oflag = __t->t->c_oflag;
- lflag = __t->t->c_lflag;
- cc = (char *) __t->t->c_cc;
-
- ceof = cc[VEOF];
- if (!(ceol = cc[VEOL]))
- ceol--;
- if (!(ceol2 = cc[VEOL2]))
- ceol2--;
-
- s = __t->ptr = __t->buf;
- __t->sx = __t->cx = 0;
- i = 0;
-
- for (;;)
- {
- if (i < MAXPATHLEN)
- nflag &= ~F_MAX;
- else
- nflag |= F_MAX;
- if (nflag & F_NDELAY)
- c = (*(__t->scan)) (0);
- else
- c = (*(__t->in)) ();
- if (c < 0)
- goto eol;
- if (c == '\r' && iflag & IGNCR)
- continue;
- c = __ttyinput (c, iflag);
- if (!(nflag & F_LNEXT))
- {
- if (c == '\n' || c == ceof || c == ceol || c == ceol2)
- goto eol;
- if (c == cc[VLNEXT])
- {
- nflag |= F_LNEXT;
- continue;
- }
- if (c == cc[VERASE])
- {
- if (i)
- {
- __ttydel (lflag);
- i--;
- }
- continue;
- }
- if (c == cc[VWERASE])
- {
- while (--i >= 0 && isspace (s[i]))
- __ttydel (lflag);
- i++;
- while (--i >= 0 && !isspace (s[i]))
- __ttydel (lflag);
- i++;
- continue;
- }
- if (c == cc[VKILL])
- {
- while (--i >= 0)
- __ttydel (lflag);
- i++;
- if (lflag & ECHOK)
- __ttynl (oflag);
- continue;
- }
- if (c == cc[VREPRINT])
- {
- register int j;
- __ttyecho (c, oflag, lflag);
- __ttynl (oflag);
- if (!(oflag & ONLRET))
- __ttycr (oflag);
- for (j = 0; j < i; j++)
- __ttyecho (s[j], oflag, lflag);
- continue;
- }
- if (lflag & ISIG)
- {
- if (c == cc[VINTR])
- {
- raise (SIGINT);
- continue;
- }
- if (c == cc[VQUIT])
- {
- raise (SIGQUIT);
- continue;
- }
- }
- }
- else
- nflag &= ~F_LNEXT;
- if (nflag & F_MAX)
- {
- if (iflag & IMAXBEL)
- (*(__t->out)) ('\007');
- }
- else
- {
- __ttyecho (c, oflag, lflag);
- s[i++] = c;
- }
- }
-
- eol:
-
- if (c != cc[VEOF] && c >= 0)
- {
- if (!(nflag & F_MAX))
- {
- __ttyecho (c, oflag, lflag);
- s[i++] = c;
- }
- }
-
- if (__t->cnt = i)
- goto ret;
- else
- {
- if (__t == __u->tty)
- os_byte (0xe5, 0, 0, 0); /* re-enable SIGINT */
-
- return (0);
- }
-
- #undef F_LNEXT
- #undef F_MAX
- #undef F_NDELAY
- }
-
- static int
- __ttyiraw (void *buf, register int nbyte, struct file *f)
- {
- register int c, i;
- register char *s;
- register int nflag;
- register int iflag, oflag, lflag;
- register char *cc;
- register unsigned int vm, vt;
-
- #define F_NSCAN 000001
-
- nflag = 0;
- iflag = __t->t->c_iflag;
- oflag = __t->t->c_oflag;
- lflag = __t->t->c_lflag;
- cc = (char *) __t->t->c_cc;
-
- if (f->oflag & O_NDELAY)
- vm = vt = 0;
- else
- {
- vm = (cc[VMIN] && cc[VTIME]) ? 1 : cc[VMIN];
- vt = cc[VTIME] * 10;
- }
- if (cc[VMIN] && !cc[VTIME])
- nbyte = vm, nflag |= F_NSCAN;
-
- s = buf;
- i = 0;
-
- while (i < nbyte)
- {
- if (nflag & F_NSCAN)
- c = (*(__t->in)) ();
- else
- c = (*(__t->scan)) (vt);
- if (c < 0)
- {
- if (i >= vm)
- return (i);
- else
- continue;
- }
- if (c == '\r' && iflag & IGNCR)
- continue;
- c = __ttyinput (c, iflag);
- if (lflag & ISIG)
- {
- if (c == cc[VINTR] && __t != __u->tty)
- {
- raise (SIGINT);
- continue;
- }
- if (c == cc[VQUIT])
- {
- raise (SIGQUIT);
- continue;
- }
- }
- __ttyecho (c, oflag, lflag);
- s[i++] = c;
- }
-
- return (i);
-
- #undef F_NSCAN
- }
-
-
- int
- __ttywrite (int l, void *buf, int nbyte, struct file *f)
- {
- register int i, c;
- register char *s;
- register int oflag, lflag;
- register char *cc;
- register int (*out) (int);
-
- f = f;
-
- __t = __u->tty + l;
-
- if (!__t->del)
- if (!(__t->del = malloc (MAXPATHLEN)))
- {
- errno = ENOMEM;
- return (-1);
- }
-
- oflag = __t->t->c_oflag;
- lflag = __t->t->c_lflag;
- cc = (char *) __t->t->c_cc;
- out = __t->out;
-
- s = buf;
- i = 0;
-
- while (i < nbyte)
- {
- c = s[i++];
- if ((oflag & (OPOST | OLCUC)) == (OPOST | OLCUC))
- if (isupper (c))
- c = _tolower (c);
- if (c == cc[VERASE])
- __ttydel (lflag);
- else if (c == '\t')
- __ttytab (oflag);
- else if (c == '\n')
- __ttynl (oflag);
- else if (c == '\r')
- __ttycr (oflag);
- else
- {
- __ttyx (1);
- (*out) (c);
- }
- }
-
- return (nbyte);
- }
-
-
- static int
- __ttyinput (register int c, register int iflag)
- {
- if (iflag & ISTRIP)
- c &= 0x7f;
- if (iflag & IUCLC)
- if (isupper (c))
- c += ('a' - 'A');
- if (iflag & INLCR)
- if (c == '\n')
- c = '\r';
- if (iflag & ICRNL)
- if (c == '\r')
- c = '\n';
- return (c);
- }
-
- static void
- __ttyecho (register int c, register int oflag, register int lflag)
- {
- if (!((lflag & ECHO) || ((c == '\n') && (lflag & ECHONL))))
- return;
-
- if (c == '\t')
- __ttytab (oflag);
- else if (c == '\n')
- __ttynl (oflag);
- else if (c == '\r')
- __ttycr (oflag);
- else if (iscntrl (c))
- {
- __ttyx (2);
- (*(__t->out)) ('^');
- (*(__t->out)) ((c == 0x7f) ? '?' : (c + '@'));
- }
- else
- {
- __ttyx (1);
- (*(__t->out)) (c);
- }
- }
-
- static void
- __ttydel (register int lflag)
- {
- register int x;
-
- if (__t->sx)
- {
- x = __t->del[__t->cx];
- __t->cx = (__t->cx - 1) & (MAXPATHLEN - 1);
- }
- else
- x = 1;
-
- __t->sx = (__t->sx > x) ? (__t->sx - x) : 0;
-
- if (lflag & ECHO)
- {
- if (lflag & ECHOE)
- while (x--)
- {
- (*(__t->out)) ('\b');
- (*(__t->out)) (' ');
- (*(__t->out)) ('\b');
- }
- else
- while (x--)
- (*(__t->out)) ('\177');
- }
- }
-
- static void
- __ttytab (register int oflag)
- {
- if ((oflag & (OPOST | XTABS)) == (OPOST | XTABS))
- {
- register int x;
-
- x = (8 - (__t->sx & 0x7));
- __ttyx (x);
- while (x--)
- (*(__t->out)) (' ');
- }
- else
- {
- __ttyx (1);
- (*(__t->out)) ('\t');
- }
- }
-
- static void
- __ttycr (register int oflag)
- {
- __t->sx = 0;
- if ((oflag & (OPOST | OCRNL)) == (OPOST | OCRNL))
- (*(__t->out)) ('\n');
- else if ((oflag & (OPOST | ONOCR)) != (OPOST | ONOCR))
- (*(__t->out)) ('\r');
- }
-
- static void
- __ttynl (register int oflag)
- {
- if (oflag & OPOST)
- {
- if (oflag & ONLCR)
- if (__t->sx || !(oflag & ONOCR))
- (*(__t->out)) ('\r');
- if (oflag & (ONLCR | ONLRET))
- __t->sx = 0;
- }
- (*(__t->out)) ('\n');
- }
-
-
- long
- __ttylseek (int l, long lpos, int whence, struct file *f)
- {
- l = l;
- lpos = lpos;
- whence = whence;
- f = f;
- errno = ESPIPE;
- return (-1);
- }
-
-
- int
- __ttyioctl (int l, int request, void *arg, struct file *f)
- {
- register struct tty *_t = __u->tty + l;
-
- f = f;
-
- if (request == TIOCGWINSZ || request == TIOCSWINSZ)
- {
- register struct winsize *w = _t->w;
-
- if (request == TIOCGWINSZ)
- {
- if (l == TTY_CON)
- __tty_console_gwinsz (w);
- memcpy (arg, w, sizeof (struct winsize));
- }
- else
- {
- memcpy (w, arg, sizeof (struct winsize));
- if (l == TTY_CON)
- __tty_console_swinsz (w);
- }
- }
- else
- {
- register struct termio *t = _t->t;
-
- if (request & TCDRAIN)
- {
- _t->ptr = _t->buf;
- _t->cnt = 0;
- (*(_t->flush)) ();
- }
-
- switch (request & ~TCDRAIN)
- {
- case TCGETA:
- if (l == TTY_CON)
- __tty_console_gterm (t);
- memcpy (arg, t, sizeof (struct termio));
- break;
- case TCSETA:
- memcpy (t, arg, sizeof (struct termio));
- if (l == TTY_CON)
- __tty_console_sterm (t);
- else if (l == TTY_423)
- __tty_423_sterm (t);
- break;
- case TCSBRK:
- if (l == TTY_423 && !arg)
- os_423break (25);
- break;
- case 0:
- break;
- default:
- errno = EINVAL;
- return (-1);
- break;
- }
- }
-
- return (0);
- }
-