📄 ite.c
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: ite.c 1.28 92/12/20$ * * @(#)ite.c 8.2 (Berkeley) 1/12/94 *//* * Bit-mapped display terminal emulator machine independent code. * This is a very rudimentary. Much more can be abstracted out of * the hardware dependent routines. */#include "ite.h"#if NITE > 0#include "grf.h"#undef NITE#define NITE NGRF#include <sys/param.h>#include <sys/conf.h>#include <sys/proc.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/systm.h>#include <sys/malloc.h>#include <hp/dev/grfioctl.h>#include <hp/dev/grfvar.h>#include <hp/dev/itevar.h>#include <hp/dev/kbdmap.h>#define set_attr(ip, attr) ((ip)->attribute |= (attr))#define clr_attr(ip, attr) ((ip)->attribute &= ~(attr))/* * No need to raise SPL above the HIL (the only thing that can * affect our state. */#include <hp/dev/hilreg.h>#define splite() splhil()/* * # of chars are output in a single itestart() call. * If this is too big, user processes will be blocked out for * long periods of time while we are emptying the queue in itestart(). * If it is too small, console output will be very ragged. */int iteburst = 64;int nite = NITE;struct tty *kbd_tty = NULL;struct tty ite_tty[NITE];struct ite_softc ite_softc[NITE];void itestart(), iterestart();extern struct tty *constty;/* * Primary attribute buffer to be used by the first bitmapped console * found. Secondary displays alloc the attribute buffer as needed. * Size is based on a 68x128 display, which is currently our largest. */u_char console_attributes[0x2200];#define ite_erasecursor(ip, sp) { \ if ((ip)->flags & ITE_CURSORON) \ (*(sp)->ite_cursor)((ip), ERASE_CURSOR); \}#define ite_drawcursor(ip, sp) { \ if ((ip)->flags & ITE_CURSORON) \ (*(sp)->ite_cursor)((ip), DRAW_CURSOR); \}#define ite_movecursor(ip, sp) { \ if ((ip)->flags & ITE_CURSORON) \ (*(sp)->ite_cursor)((ip), MOVE_CURSOR); \}/* * Perform functions necessary to setup device as a terminal emulator. */iteon(dev, flag) dev_t dev; int flag;{ int unit = UNIT(dev); struct tty *tp = &ite_tty[unit]; struct ite_softc *ip = &ite_softc[unit]; if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0) return(ENXIO); /* force ite active, overriding graphics mode */ if (flag & 1) { ip->flags |= ITE_ACTIVE; ip->flags &= ~(ITE_INGRF|ITE_INITED); } /* leave graphics mode */ if (flag & 2) { ip->flags &= ~ITE_INGRF; if ((ip->flags & ITE_ACTIVE) == 0) return(0); } ip->flags |= ITE_ACTIVE; if (ip->flags & ITE_INGRF) return(0); if (kbd_tty == NULL || kbd_tty == tp) { kbd_tty = tp; kbdenable(unit); } iteinit(dev); return(0);}iteinit(dev) dev_t dev;{ int unit = UNIT(dev); struct ite_softc *ip = &ite_softc[unit]; if (ip->flags & ITE_INITED) return; ip->curx = 0; ip->cury = 0; ip->cursorx = 0; ip->cursory = 0; (*ip->isw->ite_init)(ip); ip->flags |= ITE_CURSORON; ite_drawcursor(ip, ip->isw); ip->attribute = 0; if (ip->attrbuf == NULL) ip->attrbuf = (u_char *) malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK); bzero(ip->attrbuf, (ip->rows * ip->cols)); ip->imode = 0; ip->flags |= ITE_INITED;}/* * "Shut down" device as terminal emulator. * Note that we do not deinit the console device unless forced. * Deinit'ing the console every time leads to a very active * screen when processing /etc/rc. */iteoff(dev, flag) dev_t dev; int flag;{ register struct ite_softc *ip = &ite_softc[UNIT(dev)]; if (flag & 2) { ip->flags |= ITE_INGRF; ip->flags &= ~ITE_CURSORON; } if ((ip->flags & ITE_ACTIVE) == 0) return; if ((flag & 1) || (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED) (*ip->isw->ite_deinit)(ip); if ((flag & 2) == 0) ip->flags &= ~ITE_ACTIVE;}/* ARGSUSED */#ifdef __STDC__iteopen(dev_t dev, int mode, int devtype, struct proc *p)#elseiteopen(dev, mode, devtype, p) dev_t dev; int mode, devtype; struct proc *p;#endif{ int unit = UNIT(dev); register struct tty *tp = &ite_tty[unit]; register struct ite_softc *ip = &ite_softc[unit]; register int error; int first = 0; if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE) && p->p_ucred->cr_uid != 0) return (EBUSY); if ((ip->flags & ITE_ACTIVE) == 0) { error = iteon(dev, 0); if (error) return (error); first = 1; } tp->t_oproc = itestart; tp->t_param = NULL; tp->t_dev = dev; if ((tp->t_state&TS_ISOPEN) == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = CS8|CREAD; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; tp->t_state = TS_ISOPEN|TS_CARR_ON; ttsetwater(tp); } error = (*linesw[tp->t_line].l_open)(dev, tp); if (error == 0) { tp->t_winsize.ws_row = ip->rows; tp->t_winsize.ws_col = ip->cols; } else if (first) iteoff(dev, 0); return (error);}/*ARGSUSED*/iteclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p;{ register struct tty *tp = &ite_tty[UNIT(dev)]; (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); iteoff(dev, 0); return(0);}iteread(dev, uio, flag) dev_t dev; struct uio *uio; int flag;{ register struct tty *tp = &ite_tty[UNIT(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag));}itewrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag;{ int unit = UNIT(dev); register struct tty *tp = &ite_tty[unit]; if ((ite_softc[unit].flags & ITE_ISCONS) && constty && (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) tp = constty; return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}iteioctl(dev, cmd, addr, flag, p) dev_t dev; int cmd; caddr_t addr; int flag; struct proc *p;{ register struct tty *tp = &ite_tty[UNIT(dev)]; int error; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p); if (error >= 0) return (error); error = ttioctl(tp, cmd, addr, flag); if (error >= 0) return (error); return (ENOTTY);}voiditerestart(tp) register struct tty *tp;{ register int s = splite(); tp->t_state &= ~TS_TIMEOUT; itestart(tp); splx(s);}voiditestart(tp) register struct tty *tp;{ register int cc, s; int hiwat = 0, hadcursor = 0; struct ite_softc *ip; /* * (Potentially) lower priority. We only need to protect ourselves * from keyboard interrupts since that is all that can affect the * state of our tty (kernel printf doesn't go through this routine). */ s = splite(); if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { splx(s); return; } tp->t_state |= TS_BUSY; cc = tp->t_outq.c_cc; if (cc <= tp->t_lowat) { if (tp->t_state & TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } selwakeup(&tp->t_wsel); } /* * Handle common (?) case */ if (cc == 1) { iteputchar(getc(&tp->t_outq), tp->t_dev); } else if (cc) { /* * Limit the amount of output we do in one burst * to prevent hogging the CPU. */ if (cc > iteburst) { hiwat++; cc = iteburst; } /* * Turn off cursor while we output multiple characters. * Saves a lot of expensive window move operations. */ ip = &ite_softc[UNIT(tp->t_dev)]; if (ip->flags & ITE_CURSORON) { ite_erasecursor(ip, ip->isw); ip->flags &= ~ITE_CURSORON; hadcursor = 1; } while (--cc >= 0) iteputchar(getc(&tp->t_outq), tp->t_dev); if (hadcursor) { ip->flags |= ITE_CURSORON; ite_drawcursor(ip, ip->isw); } if (hiwat) { tp->t_state |= TS_TIMEOUT; timeout(iterestart, tp, 1); } } tp->t_state &= ~TS_BUSY; splx(s);}itefilter(stat, c) register char stat, c;{ static int capsmode = 0; static int metamode = 0; register char code, *str; if (kbd_tty == NULL) return; switch (c & 0xFF) { case KBD_CAPSLOCK: capsmode = !capsmode; return; case KBD_EXT_LEFT_DOWN: case KBD_EXT_RIGHT_DOWN: metamode = 1; return; case KBD_EXT_LEFT_UP: case KBD_EXT_RIGHT_UP: metamode = 0; return; } c &= KBD_CHARMASK; switch ((stat>>KBD_SSHIFT) & KBD_SMASK) { case KBD_KEY: if (!capsmode) { code = kbd_keymap[c]; break; } /* FALLTHROUGH */ case KBD_SHIFT: code = kbd_shiftmap[c]; break; case KBD_CTRL: code = kbd_ctrlmap[c]; break; case KBD_CTRLSHIFT: code = kbd_ctrlshiftmap[c]; break; } if (code == NULL && (str = kbd_stringmap[c]) != NULL) { while (*str) (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty); } else { if (metamode) code |= 0x80; (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty); }}iteputchar(c, dev) register int c; dev_t dev; { int unit = UNIT(dev); register struct ite_softc *ip = &ite_softc[unit]; register struct itesw *sp = ip->isw; register int n; if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) return; if (ip->escape) {doesc: switch (ip->escape) { case '&': /* Next can be a,d, or s */ if (ip->fpd++) { ip->escape = c; ip->fpd = 0; } return; case 'a': /* cursor change */ switch (c) { case 'Y': /* Only y coord. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -