ite.c revision 1.37 1 /* $NetBSD: ite.c,v 1.37 2004/04/23 02:58:28 simonb Exp $ */
2
3 /*
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * from: Utah $Hdr: ite.c 1.1 90/07/09$
36 *
37 * @(#)ite.c 7.6 (Berkeley) 5/16/91
38 */
39 /*
40 * Copyright (c) 1988 University of Utah.
41 *
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
44 * Science Department.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by the University of
57 * California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission.
61 *
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE.
73 *
74 * from: Utah $Hdr: ite.c 1.1 90/07/09$
75 *
76 * @(#)ite.c 7.6 (Berkeley) 5/16/91
77 */
78
79 /*
80 * ite - bitmaped terminal.
81 * Supports VT200, a few terminal features will be unavailable until
82 * the system actually probes the device (i.e. not after consinit())
83 */
84
85 #include <sys/cdefs.h>
86 __KERNEL_RCSID(0, "$NetBSD: ite.c,v 1.37 2004/04/23 02:58:28 simonb Exp $");
87
88 #include "ite.h"
89 #if NITE > 0
90
91 #include "bell.h"
92 #include "kbd.h"
93
94 #include "opt_ite.h"
95
96 #include <sys/param.h>
97 #include <sys/conf.h>
98 #include <sys/proc.h>
99 #include <sys/ioctl.h>
100 #include <sys/tty.h>
101 #include <sys/systm.h>
102 #include <sys/device.h>
103 #include <sys/malloc.h>
104
105 #include <machine/cpu.h>
106 #include <machine/kbio.h>
107 #include <machine/bus.h>
108 #include <machine/grfioctl.h>
109 #include <machine/iteioctl.h>
110
111 #include <arch/x68k/dev/grfvar.h>
112 #include <arch/x68k/dev/itevar.h>
113 #include <arch/x68k/dev/kbdmap.h>
114 #include <arch/x68k/dev/mfp.h>
115 #if NBELL > 0
116 void opm_bell __P((void));
117 #endif
118
119 #define SUBR_CNPROBE(min) itesw[min].ite_cnprobe(min)
120 #define SUBR_INIT(ip) ip->isw->ite_init(ip)
121 #define SUBR_DEINIT(ip) ip->isw->ite_deinit(ip)
122 #define SUBR_PUTC(ip,c,dy,dx,m) ip->isw->ite_putc(ip,c,dy,dx,m)
123 #define SUBR_CURSOR(ip,flg) ip->isw->ite_cursor(ip,flg)
124 #define SUBR_CLEAR(ip,sy,sx,h,w) ip->isw->ite_clear(ip,sy,sx,h,w)
125 #define SUBR_SCROLL(ip,sy,sx,count,dir) \
126 ip->isw->ite_scroll(ip,sy,sx,count,dir)
127
128 struct consdev;
129
130 __inline static void itesendch __P((int));
131 __inline static void alignment_display __P((struct ite_softc *));
132 __inline static void snap_cury __P((struct ite_softc *));
133 __inline static void ite_dnchar __P((struct ite_softc *, int));
134 static void ite_inchar __P((struct ite_softc *, int));
135 __inline static void ite_clrtoeol __P((struct ite_softc *));
136 __inline static void ite_clrtobol __P((struct ite_softc *));
137 __inline static void ite_clrline __P((struct ite_softc *));
138 __inline static void ite_clrtoeos __P((struct ite_softc *));
139 __inline static void ite_clrtobos __P((struct ite_softc *));
140 __inline static void ite_clrscreen __P((struct ite_softc *));
141 __inline static void ite_dnline __P((struct ite_softc *, int));
142 __inline static void ite_inline __P((struct ite_softc *, int));
143 __inline static void ite_index __P((struct ite_softc *));
144 __inline static void ite_lf __P((struct ite_softc *));
145 __inline static void ite_crlf __P((struct ite_softc *));
146 __inline static void ite_cr __P((struct ite_softc *));
147 __inline static void ite_rlf __P((struct ite_softc *));
148 static void iteprecheckwrap __P((struct ite_softc *ip));
149 static void itecheckwrap __P((struct ite_softc *ip));
150 static int ite_argnum __P((struct ite_softc *ip));
151 static int ite_zargnum __P((struct ite_softc *ip));
152 static void ite_sendstr __P((struct ite_softc *ip, char *str));
153 __inline static int atoi __P((const char *cp));
154 void ite_reset __P((struct ite_softc *ip));
155 struct ite_softc *getitesp __P((dev_t));
156 int iteon __P((dev_t, int));
157 void iteoff __P((dev_t, int));
158
159 struct itesw itesw[] = {
160 {0, tv_init, tv_deinit, 0,
161 0, 0, 0}
162 };
163 int nitesw = sizeof(itesw) / sizeof(itesw[0]);
164
165 /*
166 * # of chars are output in a single itestart() call.
167 * If this is too big, user processes will be blocked out for
168 * long periods of time while we are emptying the queue in itestart().
169 * If it is too small, console output will be very ragged.
170 */
171 #define ITEBURST 64
172
173 int nite = NITE;
174 struct tty *ite_tty[NITE];
175 struct ite_softc *kbd_ite = NULL;
176 struct ite_softc con_itesoftc;
177
178 struct tty *kbd_tty = NULL;
179
180 int start_repeat_timeo = 20; /* /100: initial timeout till pressed key repeats */
181 int next_repeat_timeo = 3; /* /100: timeout when repeating for next char */
182
183 u_char cons_tabs[MAX_TABS];
184
185 void itestart __P((struct tty *tp));
186
187 void iteputchar __P((int c, struct ite_softc *ip));
188 void ite_putstr __P((const u_char * s, int len, dev_t dev));
189
190 void iteattach __P((struct device *, struct device *, void *));
191 int itematch __P((struct device *, struct cfdata *, void *));
192
193 CFATTACH_DECL(ite, sizeof(struct ite_softc),
194 itematch, iteattach, NULL, NULL);
195
196 extern struct cfdriver ite_cd;
197
198 dev_type_open(iteopen);
199 dev_type_close(iteclose);
200 dev_type_read(iteread);
201 dev_type_write(itewrite);
202 dev_type_ioctl(iteioctl);
203 dev_type_tty(itetty);
204 dev_type_poll(itepoll);
205
206 const struct cdevsw ite_cdevsw = {
207 iteopen, iteclose, iteread, itewrite, iteioctl,
208 nostop, itetty, itepoll, nommap, ttykqfilter, D_TTY
209 };
210
211 int
212 itematch(pdp, cdp, auxp)
213 struct device *pdp;
214 struct cfdata *cdp;
215 void *auxp;
216 {
217 struct grf_softc *gp;
218 #if 0
219 int maj;
220 #endif
221
222 gp = auxp;
223
224 /* ite0 should be at grf0 XXX */
225 if(cdp->cf_unit != gp->g_device.dv_unit)
226 return(0);
227
228 #if 0
229 /*
230 * all that our mask allows (more than enough no one
231 * has > 32 monitors for text consoles on one machine)
232 */
233 if (cdp->cf_unit >= sizeof(ite_confunits) * NBBY)
234 return(0);
235 /*
236 * XXX
237 * normally this would be done in attach, however
238 * during early init we do not have a device pointer
239 * and thus no unit number.
240 */
241 maj = cdevsw_lookup_major(&ite_cdevsw);
242 gp->g_itedev = makedev(maj, cdp->cf_unit);
243 #endif
244 return(1);
245 }
246
247 /*
248 * iteinit() is the standard entry point for initialization of
249 * an ite device, it is also called from ite_cninit().
250 */
251 void
252 iteattach(pdp, dp, auxp)
253 struct device *pdp, *dp;
254 void *auxp;
255 {
256 struct ite_softc *ip;
257 struct grf_softc *gp;
258
259 gp = (struct grf_softc *)auxp;
260 if (dp) {
261 ip = (struct ite_softc *)dp;
262 if(con_itesoftc.grf != NULL
263 /*&& con_itesoftc.grf->g_unit == gp->g_unit*/) {
264 /*
265 * console reinit copy params over.
266 * and console always gets keyboard
267 */
268 memcpy(&ip->grf, &con_itesoftc.grf,
269 (char *)&ip[1] - (char *)&ip->grf);
270 con_itesoftc.grf = NULL;
271 kbd_ite = ip;
272 }
273 ip->grf = gp;
274 iteinit(ip->device.dv_unit); /* XXX */
275 printf(": rows %d cols %d", ip->rows, ip->cols);
276 if (kbd_ite == NULL)
277 kbd_ite = ip;
278 printf("\n");
279 } else {
280 if (con_itesoftc.grf != NULL)
281 return;
282 con_itesoftc.grf = gp;
283 con_itesoftc.tabs = cons_tabs;
284 }
285 }
286
287 struct ite_softc *
288 getitesp(dev)
289 dev_t dev;
290 {
291 extern int x68k_realconfig;
292
293 if (x68k_realconfig && con_itesoftc.grf == NULL)
294 return(ite_cd.cd_devs[UNIT(dev)]);
295
296 if (con_itesoftc.grf == NULL)
297 panic("no ite_softc for console");
298 return(&con_itesoftc);
299 }
300
301 void
302 iteinit(dev)
303 dev_t dev;
304 {
305 struct ite_softc *ip;
306
307 ip = getitesp(dev);
308
309 if (ip->flags & ITE_INITED)
310 return;
311 memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
312
313 ip->curx = 0;
314 ip->cury = 0;
315 ip->cursorx = 0;
316 ip->cursory = 0;
317
318 ip->isw = &itesw[ip->device.dv_unit]; /* XXX */
319 SUBR_INIT(ip);
320 SUBR_CURSOR(ip, DRAW_CURSOR);
321 if (!ip->tabs)
322 ip->tabs = malloc(MAX_TABS*sizeof(u_char), M_DEVBUF, M_WAITOK);
323 ite_reset(ip);
324 ip->flags |= ITE_INITED;
325 }
326
327 /*
328 * Perform functions necessary to setup device as a terminal emulator.
329 */
330 int
331 iteon(dev, flag)
332 dev_t dev;
333 int flag;
334 {
335 int unit = UNIT(dev);
336 struct ite_softc *ip;
337
338 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
339 (ip = getitesp(unit)) == NULL || (ip->flags&ITE_ALIVE) == 0)
340 return(ENXIO);
341 /* force ite active, overriding graphics mode */
342 if (flag & 1) {
343 ip->flags |= ITE_ACTIVE;
344 ip->flags &= ~(ITE_INGRF|ITE_INITED);
345 }
346 /* leave graphics mode */
347 if (flag & 2) {
348 ip->flags &= ~ITE_INGRF;
349 if ((ip->flags & ITE_ACTIVE) == 0)
350 return(0);
351 }
352 ip->flags |= ITE_ACTIVE;
353 if (ip->flags & ITE_INGRF)
354 return(0);
355 iteinit(dev);
356 if (flag & 2)
357 ite_reset(ip);
358 #if NKBD > 0
359 mfp_send_usart (0x49); /* XXX */
360 #endif
361 return(0);
362 }
363
364 /*
365 * "Shut down" device as terminal emulator.
366 * Note that we do not deinit the console device unless forced.
367 * Deinit'ing the console every time leads to a very active
368 * screen when processing /etc/rc.
369 */
370 void
371 iteoff(dev, flag)
372 dev_t dev;
373 int flag;
374 {
375 int unit = UNIT(dev);
376 register struct ite_softc *ip;
377
378 /* XXX check whether when call from grf.c */
379 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
380 (ip = getitesp(unit)) == NULL || (ip->flags&ITE_ALIVE) == 0)
381 return;
382 if (flag & 2)
383 ip->flags |= ITE_INGRF;
384
385 if ((ip->flags & ITE_ACTIVE) == 0)
386 return;
387 if ((flag & 1) ||
388 (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED)
389 SUBR_DEINIT(ip);
390
391 /*
392 * XXX When the system is rebooted with "reboot", init(8)
393 * kills the last process to have the console open.
394 * If we don't revent the ITE_ACTIVE bit from being
395 * cleared, we will never see messages printed during
396 * the process of rebooting.
397 */
398 if ((flag & 2) == 0 && (ip->flags & ITE_ISCONS) == 0) {
399 ip->flags &= ~ITE_ACTIVE;
400 #if NKBD > 0
401 mfp_send_usart (0x48); /* XXX */
402 #endif
403 }
404 }
405
406 /*
407 * standard entry points to the device.
408 */
409
410 /* ARGSUSED */
411 int
412 iteopen(dev, mode, devtype, p)
413 dev_t dev;
414 int mode, devtype;
415 struct proc *p;
416 {
417 int unit = UNIT(dev);
418 register struct tty *tp;
419 register struct ite_softc *ip;
420 register int error;
421 int first = 0;
422
423 if (unit >= ite_cd.cd_ndevs || (ip = getitesp(dev)) == NULL)
424 return (ENXIO);
425 if (!ite_tty[unit]) {
426 tp = ite_tty[unit] = ttymalloc();
427 tty_attach(tp);
428 } else
429 tp = ite_tty[unit];
430 if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
431 && p->p_ucred->cr_uid != 0)
432 return (EBUSY);
433 if ((ip->flags & ITE_ACTIVE) == 0) {
434 error = iteon(dev, 0);
435 if (error)
436 return (error);
437 first = 1;
438 }
439 tp->t_oproc = itestart;
440 tp->t_param = NULL;
441 tp->t_dev = dev;
442 if ((tp->t_state&TS_ISOPEN) == 0) {
443 ttychars(tp);
444 tp->t_iflag = TTYDEF_IFLAG;
445 tp->t_oflag = TTYDEF_OFLAG;
446 tp->t_cflag = TTYDEF_CFLAG;
447 tp->t_lflag = TTYDEF_LFLAG;
448 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
449 tp->t_state = TS_ISOPEN|TS_CARR_ON;
450 ttsetwater(tp);
451 }
452 error = (*tp->t_linesw->l_open)(dev, tp);
453 if (error == 0) {
454 tp->t_winsize.ws_row = ip->rows;
455 tp->t_winsize.ws_col = ip->cols;
456 } else if (first)
457 iteoff(dev, 0);
458 return (error);
459 }
460
461 /*ARGSUSED*/
462 int
463 iteclose(dev, flag, mode, p)
464 dev_t dev;
465 int flag, mode;
466 struct proc *p;
467 {
468 register struct tty *tp = ite_tty[UNIT(dev)];
469
470 (*tp->t_linesw->l_close)(tp, flag);
471 ttyclose(tp);
472 iteoff(dev, 0);
473 #if 0
474 ttyfree(tp);
475 ite_tty[UNIT(dev)] = (struct tty *)0;
476 #endif
477 return(0);
478 }
479
480 int
481 iteread(dev, uio, flag)
482 dev_t dev;
483 struct uio *uio;
484 int flag;
485 {
486 register struct tty *tp = ite_tty[UNIT(dev)];
487
488 return ((*tp->t_linesw->l_read)(tp, uio, flag));
489 }
490
491 int
492 itewrite(dev, uio, flag)
493 dev_t dev;
494 struct uio *uio;
495 int flag;
496 {
497 register struct tty *tp = ite_tty[UNIT(dev)];
498
499 return ((*tp->t_linesw->l_write)(tp, uio, flag));
500 }
501
502 int
503 itepoll(dev, events, p)
504 dev_t dev;
505 int events;
506 struct proc *p;
507 {
508 register struct tty *tp = ite_tty[UNIT(dev)];
509
510 return ((*tp->t_linesw->l_poll)(tp, events, p));
511 }
512
513 struct tty *
514 itetty(dev)
515 dev_t dev;
516 {
517
518 return (ite_tty[UNIT(dev)]);
519 }
520
521 int
522 iteioctl(dev, cmd, addr, flag, p)
523 dev_t dev;
524 u_long cmd;
525 caddr_t addr;
526 int flag;
527 struct proc *p;
528 {
529 struct iterepeat *irp;
530 register struct tty *tp = ite_tty[UNIT(dev)];
531 int error;
532
533 error = (*tp->t_linesw->l_ioctl)(tp, cmd, addr, flag, p);
534 if (error != EPASSTHROUGH)
535 return (error);
536
537 error = ttioctl(tp, cmd, addr, flag, p);
538 if (error != EPASSTHROUGH)
539 return (error);
540
541 switch (cmd) {
542 case ITEIOCSKMAP:
543 if (addr == 0)
544 return(EFAULT);
545 memcpy(&kbdmap, addr, sizeof(struct kbdmap));
546 return(0);
547
548 case ITEIOCGKMAP:
549 if (addr == NULL)
550 return(EFAULT);
551 memcpy(addr, &kbdmap, sizeof(struct kbdmap));
552 return(0);
553
554 case ITEIOCGREPT:
555 irp = (struct iterepeat *)addr;
556 irp->start = start_repeat_timeo;
557 irp->next = next_repeat_timeo;
558
559 case ITEIOCSREPT:
560 irp = (struct iterepeat *)addr;
561 if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
562 return(EINVAL);
563 start_repeat_timeo = irp->start;
564 next_repeat_timeo = irp->next;
565 #if x68k
566 case ITELOADFONT:
567 if (addr) {
568 memcpy(kern_font, addr, 4096 /*sizeof (kernel_font)*/);
569 ite_set_glyph();
570 return 0;
571 } else
572 return EFAULT;
573
574 case ITETVCTRL:
575 if (addr && *(u_int8_t *)addr < 0x40) {
576 return mfp_send_usart (* (u_int8_t *)addr);
577 } else {
578 return EFAULT;
579 }
580 #endif
581 }
582 return (EPASSTHROUGH);
583 }
584
585 void
586 itestart(tp)
587 register struct tty *tp;
588 {
589 struct clist *rbp;
590 struct ite_softc *ip;
591 u_char buf[ITEBURST];
592 int s, len;
593
594 ip = getitesp(tp->t_dev);
595 /*
596 * (Potentially) lower priority. We only need to protect ourselves
597 * from keyboard interrupts since that is all that can affect the
598 * state of our tty (kernel printf doesn't go through this routine).
599 */
600 s = spltty();
601 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
602 goto out;
603 tp->t_state |= TS_BUSY;
604 rbp = &tp->t_outq;
605 len = q_to_b(rbp, buf, ITEBURST);
606 /*splx(s);*/
607
608 /* Here is a really good place to implement pre/jumpscroll() */
609 ite_putstr(buf, len, tp->t_dev);
610
611 /*s = spltty();*/
612 tp->t_state &= ~TS_BUSY;
613 /* we have characters remaining. */
614 if (rbp->c_cc) {
615 tp->t_state |= TS_TIMEOUT;
616 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
617 }
618 /* wakeup we are below */
619 if (rbp->c_cc <= tp->t_lowat) {
620 if (tp->t_state & TS_ASLEEP) {
621 tp->t_state &= ~TS_ASLEEP;
622 wakeup((caddr_t)rbp);
623 }
624 selwakeup(&tp->t_wsel);
625 }
626 out:
627 splx(s);
628 }
629
630 /* XXX called after changes made in underlying grf layer. */
631 /* I want to nuke this */
632 void
633 ite_reinit(dev)
634 dev_t dev;
635 {
636 struct ite_softc *ip;
637 int unit = UNIT(dev);
638
639 /* XXX check whether when call from grf.c */
640 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
641 (ip = getitesp(unit)) == NULL)
642 return;
643
644 ip->flags &= ~ITE_INITED;
645 iteinit(dev);
646 }
647
648 void
649 ite_reset(ip)
650 struct ite_softc *ip;
651 {
652 int i;
653
654 ip->curx = 0;
655 ip->cury = 0;
656 ip->attribute = 0;
657 ip->save_curx = 0;
658 ip->save_cury = 0;
659 ip->save_attribute = 0;
660 ip->ap = ip->argbuf;
661 ip->emul_level = EMUL_VT300_8;
662 ip->eightbit_C1 = 0;
663 ip->top_margin = 0;
664 ip->bottom_margin = ip->rows - 1;
665 ip->inside_margins = 0; /* origin mode == absolute */
666 ip->linefeed_newline = 0;
667 ip->auto_wrap = 1;
668 ip->cursor_appmode = 0;
669 ip->keypad_appmode = 0;
670 ip->imode = 0;
671 ip->key_repeat = 1;
672 ip->G0 = CSET_ASCII;
673 ip->G1 = CSET_JIS1983;
674 ip->G2 = CSET_JISKANA;
675 ip->G3 = CSET_JIS1990;
676 ip->GL = &ip->G0;
677 ip->GR = &ip->G1;
678 ip->save_GL = 0;
679 ip->save_char = 0;
680 ip->fgcolor = 7;
681 ip->bgcolor = 0;
682 for (i = 0; i < ip->cols; i++)
683 ip->tabs[i] = ((i & 7) == 0);
684 /* XXX clear screen */
685 SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
686 attrclr(ip, 0, 0, ip->rows, ip->cols);
687 }
688
689 /* Used in console at startup only */
690 int
691 ite_cnfilter(c)
692 u_char c;
693 {
694 static u_char mod = 0;
695 struct key key;
696 u_char code, up, mask;
697 int s;
698
699 up = c & 0x80 ? 1 : 0;
700 c &= 0x7f;
701 code = 0;
702
703 s = spltty();
704
705 mask = 0;
706 if (c >= KBD_LEFT_ALT && !(c >= 0x63 && c <= 0x6c)) { /* 0x63: F1, 0x6c:F10 */
707 switch (c) {
708 case KBD_LEFT_SHIFT:
709 mask = KBD_MOD_SHIFT;
710 break;
711
712 case KBD_LEFT_ALT:
713 mask = KBD_MOD_LALT;
714 break;
715
716 case KBD_RIGHT_ALT:
717 mask = KBD_MOD_RALT;
718 break;
719
720 case KBD_LEFT_META:
721 mask = KBD_MOD_LMETA;
722 break;
723
724 case KBD_RIGHT_META:
725 mask = KBD_MOD_RMETA;
726 break;
727
728 case KBD_CAPS_LOCK:
729 /*
730 * capslock already behaves `right', don't need to
731 * keep track of the state in here.
732 */
733 mask = KBD_MOD_CAPS;
734 break;
735
736 case KBD_CTRL:
737 mask = KBD_MOD_CTRL;
738 break;
739
740 case KBD_RECONNECT:
741 /* ite got 0xff */
742 if (up)
743 kbd_setLED();
744 break;
745 }
746 if (mask & KBD_MOD_CAPS) {
747 if (!up) {
748 mod ^= KBD_MOD_CAPS;
749 kbdled ^= LED_CAPS_LOCK;
750 kbd_setLED();
751 }
752 } else if (up)
753 mod &= ~mask;
754 else mod |= mask;
755 splx (s);
756 return -1;
757 }
758
759 if (up) {
760 splx(s);
761 return -1;
762 }
763
764 /* translate modifiers */
765 if (mod & KBD_MOD_SHIFT) {
766 if (mod & KBD_MOD_ALT)
767 key = kbdmap.alt_shift_keys[c];
768 else
769 key = kbdmap.shift_keys[c];
770 } else if (mod & KBD_MOD_ALT)
771 key = kbdmap.alt_keys[c];
772 else {
773 key = kbdmap.keys[c];
774 /* if CAPS and key is CAPable (no pun intended) */
775 if ((mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
776 key = kbdmap.shift_keys[c];
777 }
778 code = key.code;
779
780 /* if string return */
781 if (key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
782 splx(s);
783 return -1;
784 }
785 /* handle dead keys */
786 if (key.mode & KBD_MODE_DEAD) {
787 splx(s);
788 return -1;
789 }
790 if (mod & KBD_MOD_CTRL)
791 code &= 0x1f;
792 if (mod & KBD_MOD_META)
793 code |= 0x80;
794
795 /* do console mapping. */
796 code = code == '\r' ? '\n' : code;
797
798 splx(s);
799 return (code);
800 }
801
802 /* And now the old stuff. */
803 __inline static void
804 itesendch (ch)
805 int ch;
806 {
807 (*kbd_tty->t_linesw->l_rint)(ch, kbd_tty);
808 }
809
810
811 void
812 ite_filter(c)
813 u_char c;
814 {
815 static u_short mod = 0;
816 register unsigned char code, *str;
817 u_short up, mask;
818 struct key key;
819 int s, i;
820
821 if (!kbd_ite || !(kbd_tty = ite_tty[kbd_ite->device.dv_unit]))
822 return;
823
824 /* have to make sure we're at spltty in here */
825 s = spltty ();
826
827 up = c & 0x80 ? 1 : 0;
828 c &= 0x7f;
829 code = 0;
830
831 mask = 0;
832 if (c >= KBD_LEFT_ALT &&
833 !(c >= 0x63 && c <= 0x6c)) { /* 0x63: F1, 0x6c:F10 */
834 switch (c) {
835 case KBD_LEFT_SHIFT:
836 mask = KBD_MOD_SHIFT;
837 break;
838
839 case KBD_LEFT_ALT:
840 mask = KBD_MOD_LALT;
841 break;
842
843 case KBD_RIGHT_ALT:
844 mask = KBD_MOD_RALT;
845 break;
846
847 case KBD_LEFT_META:
848 mask = KBD_MOD_LMETA;
849 break;
850
851 case KBD_RIGHT_META:
852 mask = KBD_MOD_RMETA;
853 break;
854
855 case KBD_CAPS_LOCK:
856 /*
857 * capslock already behaves `right', don't need to keep
858 * track of the state in here.
859 */
860 mask = KBD_MOD_CAPS;
861 break;
862
863 case KBD_CTRL:
864 mask = KBD_MOD_CTRL;
865 break;
866
867 case KBD_OPT1:
868 mask = KBD_MOD_OPT1;
869 break;
870
871 case KBD_OPT2:
872 mask = KBD_MOD_OPT2;
873 break;
874
875 case KBD_RECONNECT:
876 if (up) { /* ite got 0xff */
877 kbd_setLED();
878 }
879 break;
880 }
881
882 if (mask & KBD_MOD_CAPS) {
883 if (!up) {
884 mod ^= KBD_MOD_CAPS;
885 kbdled ^= LED_CAPS_LOCK;
886 kbd_setLED();
887 }
888 } else if (up) {
889 mod &= ~mask;
890 } else mod |= mask;
891
892 /*
893 * return even if it wasn't a modifier key, the other
894 * codes up here are either special (like reset warning),
895 * or not yet defined
896 */
897 splx (s);
898 return;
899 }
900
901 if (up) {
902 splx (s);
903 return;
904 }
905
906 /*
907 * intercept LAlt-LMeta-F1 here to switch back to original ascii-keymap.
908 * this should probably be configurable..
909 */
910 if (mod == (KBD_MOD_LALT|KBD_MOD_LMETA) && c == 0x63) {
911 memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
912 splx (s);
913 return;
914 }
915
916 /* translate modifiers */
917 if (mod & KBD_MOD_SHIFT) {
918 if (mod & KBD_MOD_ALT)
919 key = kbdmap.alt_shift_keys[c];
920 else
921 key = kbdmap.shift_keys[c];
922 } else if (mod & KBD_MOD_ALT)
923 key = kbdmap.alt_keys[c];
924 else {
925 key = kbdmap.keys[c];
926 /* if CAPS and key is CAPable (no pun intended) */
927 if ((mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
928 key = kbdmap.shift_keys[c];
929 else if ((mod & KBD_MOD_OPT2) && (key.mode & KBD_MODE_KPAD))
930 key = kbdmap.shift_keys[c];
931 }
932 code = key.code;
933
934 /* handle dead keys */
935 if (key.mode & KBD_MODE_DEAD) {
936 splx (s);
937 return;
938 }
939 /* if not string, apply META and CTRL modifiers */
940 if (! (key.mode & KBD_MODE_STRING)
941 && (!(key.mode & KBD_MODE_KPAD) ||
942 (kbd_ite && !kbd_ite->keypad_appmode))) {
943 if ((mod & KBD_MOD_CTRL) &&
944 (code == ' ' || (code >= '@' && code <= 'z')))
945 code &= 0x1f;
946 if (mod & KBD_MOD_META)
947 code |= 0x80;
948 } else if ((key.mode & KBD_MODE_KPAD) &&
949 (kbd_ite && kbd_ite->keypad_appmode)) {
950 static const char * const in = "0123456789-+.\r()/*";
951 static const char * const out = "pqrstuvwxymlnMPQRS";
952 char *cp = strchr(in, code);
953
954 /*
955 * keypad-appmode sends SS3 followed by the above
956 * translated character
957 */
958 (*kbd_tty->t_linesw->l_rint) (27, kbd_tty);
959 (*kbd_tty->t_linesw->l_rint) ('O', kbd_tty);
960 (*kbd_tty->t_linesw->l_rint) (out[cp - in], kbd_tty);
961 splx(s);
962 return;
963 } else {
964 /* *NO* I don't like this.... */
965 static u_char app_cursor[] =
966 {
967 3, 27, 'O', 'A',
968 3, 27, 'O', 'B',
969 3, 27, 'O', 'C',
970 3, 27, 'O', 'D'};
971
972 str = kbdmap.strings + code;
973 /*
974 * if this is a cursor key, AND it has the default
975 * keymap setting, AND we're in app-cursor mode, switch
976 * to the above table. This is *nasty* !
977 */
978 if (c >= 0x3b && c <= 0x3e && kbd_ite->cursor_appmode
979 && !memcmp(str, "\x03\x1b[", 3) &&
980 strchr("ABCD", str[3]))
981 str = app_cursor + 4 * (str[3] - 'A');
982
983 /*
984 * using a length-byte instead of 0-termination allows
985 * to embed \0 into strings, although this is not used
986 * in the default keymap
987 */
988 for (i = *str++; i; i--)
989 (*kbd_tty->t_linesw->l_rint) (*str++, kbd_tty);
990 splx(s);
991 return;
992 }
993 (*kbd_tty->t_linesw->l_rint)(code, kbd_tty);
994
995 splx(s);
996 return;
997 }
998
999 /* helper functions, makes the code below more readable */
1000 __inline static void
1001 ite_sendstr (ip, str)
1002 struct ite_softc *ip;
1003 char *str;
1004 {
1005 while (*str)
1006 itesendch (*str++);
1007 }
1008
1009 __inline static void
1010 alignment_display(ip)
1011 struct ite_softc *ip;
1012 {
1013 int i, j;
1014
1015 for (j = 0; j < ip->rows; j++)
1016 for (i = 0; i < ip->cols; i++)
1017 SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
1018 attrclr(ip, 0, 0, ip->rows, ip->cols);
1019 }
1020
1021 __inline static void
1022 snap_cury(ip)
1023 struct ite_softc *ip;
1024 {
1025 if (ip->inside_margins) {
1026 if (ip->cury < ip->top_margin)
1027 ip->cury = ip->top_margin;
1028 if (ip->cury > ip->bottom_margin)
1029 ip->cury = ip->bottom_margin;
1030 }
1031 }
1032
1033 __inline static void
1034 ite_dnchar(ip, n)
1035 struct ite_softc *ip;
1036 int n;
1037 {
1038 n = min(n, ip->cols - ip->curx);
1039 if (n < ip->cols - ip->curx) {
1040 SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
1041 attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
1042 1, ip->cols - ip->curx - n);
1043 attrclr(ip, ip->cury, ip->cols - n, 1, n);
1044 }
1045 while (n-- > 0)
1046 SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
1047 }
1048
1049 static void
1050 ite_inchar(ip, n)
1051 struct ite_softc *ip;
1052 int n;
1053 {
1054 int c = ip->save_char;
1055 ip->save_char = 0;
1056 n = min(n, ip->cols - ip->curx);
1057 if (n < ip->cols - ip->curx) {
1058 SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
1059 attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
1060 1, ip->cols - ip->curx - n);
1061 attrclr(ip, ip->cury, ip->curx, 1, n);
1062 }
1063 while (n--)
1064 SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1065 ip->save_char = c;
1066 }
1067
1068 __inline static void
1069 ite_clrtoeol(ip)
1070 struct ite_softc *ip;
1071 {
1072 int y = ip->cury, x = ip->curx;
1073 if (ip->cols - x > 0) {
1074 SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
1075 attrclr(ip, y, x, 1, ip->cols - x);
1076 }
1077 }
1078
1079 __inline static void
1080 ite_clrtobol(ip)
1081 struct ite_softc *ip;
1082 {
1083 int y = ip->cury, x = min(ip->curx + 1, ip->cols);
1084 SUBR_CLEAR(ip, y, 0, 1, x);
1085 attrclr(ip, y, 0, 1, x);
1086 }
1087
1088 __inline static void
1089 ite_clrline(ip)
1090 struct ite_softc *ip;
1091 {
1092 int y = ip->cury;
1093 SUBR_CLEAR(ip, y, 0, 1, ip->cols);
1094 attrclr(ip, y, 0, 1, ip->cols);
1095 }
1096
1097 __inline static void
1098 ite_clrtoeos(ip)
1099 struct ite_softc *ip;
1100 {
1101 ite_clrtoeol(ip);
1102 if (ip->cury < ip->rows - 1) {
1103 SUBR_CLEAR(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
1104 attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
1105 }
1106 }
1107
1108 __inline static void
1109 ite_clrtobos(ip)
1110 struct ite_softc *ip;
1111 {
1112 ite_clrtobol(ip);
1113 if (ip->cury > 0) {
1114 SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
1115 attrclr(ip, 0, 0, ip->cury, ip->cols);
1116 }
1117 }
1118
1119 __inline static void
1120 ite_clrscreen(ip)
1121 struct ite_softc *ip;
1122 {
1123 SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
1124 attrclr(ip, 0, 0, ip->rows, ip->cols);
1125 }
1126
1127
1128
1129 __inline static void
1130 ite_dnline(ip, n)
1131 struct ite_softc *ip;
1132 int n;
1133 {
1134 /*
1135 * interesting.. if the cursor is outside the scrolling
1136 * region, this command is simply ignored..
1137 */
1138 if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1139 return;
1140
1141 n = min(n, ip->bottom_margin + 1 - ip->cury);
1142 if (n <= ip->bottom_margin - ip->cury) {
1143 SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
1144 attrmov(ip, ip->cury + n, 0, ip->cury, 0,
1145 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1146 }
1147 SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1148 attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1149 }
1150
1151 __inline static void
1152 ite_inline(ip, n)
1153 struct ite_softc *ip;
1154 int n;
1155 {
1156 /*
1157 * interesting.. if the cursor is outside the scrolling
1158 * region, this command is simply ignored..
1159 */
1160 if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1161 return;
1162
1163 if (n <= 0)
1164 n = 1;
1165 else n = min(n, ip->bottom_margin + 1 - ip->cury);
1166 if (n <= ip->bottom_margin - ip->cury) {
1167 SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
1168 attrmov(ip, ip->cury, 0, ip->cury + n, 0,
1169 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1170 }
1171 SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
1172 attrclr(ip, ip->cury, 0, n, ip->cols);
1173 ip->curx = 0;
1174 }
1175
1176 __inline static void
1177 ite_index (ip)
1178 struct ite_softc *ip;
1179 {
1180 ++ip->cury;
1181 if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows)) {
1182 ip->cury--;
1183 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1184 ite_clrline(ip);
1185 }
1186 /*clr_attr(ip, ATTR_INV);*/
1187 }
1188
1189 __inline static void
1190 ite_lf (ip)
1191 struct ite_softc *ip;
1192 {
1193 ++ip->cury;
1194 if (ip->cury > ip->bottom_margin) {
1195 ip->cury--;
1196 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1197 ite_clrline(ip);
1198 }
1199 /* SUBR_CURSOR(ip, MOVE_CURSOR);*/
1200 /*clr_attr(ip, ATTR_INV);*/
1201 /* reset character set ... thanks for mohta. */
1202 ip->G0 = CSET_ASCII;
1203 ip->G1 = CSET_JIS1983;
1204 ip->G2 = CSET_JISKANA;
1205 ip->G3 = CSET_JIS1990;
1206 ip->GL = &ip->G0;
1207 ip->GR = &ip->G1;
1208 ip->save_GL = 0;
1209 ip->save_char = 0;
1210 }
1211
1212 __inline static void
1213 ite_crlf (ip)
1214 struct ite_softc *ip;
1215 {
1216 ip->curx = 0;
1217 ite_lf (ip);
1218 }
1219
1220 __inline static void
1221 ite_cr (ip)
1222 struct ite_softc *ip;
1223 {
1224 if (ip->curx) {
1225 ip->curx = 0;
1226 }
1227 }
1228
1229 __inline static void
1230 ite_rlf (ip)
1231 struct ite_softc *ip;
1232 {
1233 ip->cury--;
1234 if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1)) {
1235 ip->cury++;
1236 SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
1237 ite_clrline(ip);
1238 }
1239 clr_attr(ip, ATTR_INV);
1240 }
1241
1242 __inline static int
1243 atoi (cp)
1244 const char *cp;
1245 {
1246 int n;
1247
1248 for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
1249 n = n * 10 + *cp - '0';
1250 return n;
1251 }
1252
1253 __inline static int
1254 ite_argnum (ip)
1255 struct ite_softc *ip;
1256 {
1257 char ch;
1258 int n;
1259
1260 /* convert argument string into number */
1261 if (ip->ap == ip->argbuf)
1262 return 1;
1263 ch = *ip->ap;
1264 *ip->ap = 0;
1265 n = atoi (ip->argbuf);
1266 *ip->ap = ch;
1267
1268 return n;
1269 }
1270
1271 __inline static int
1272 ite_zargnum (ip)
1273 struct ite_softc *ip;
1274 {
1275 char ch;
1276 int n;
1277
1278 /* convert argument string into number */
1279 if (ip->ap == ip->argbuf)
1280 return 0;
1281 ch = *ip->ap;
1282 *ip->ap = 0; /* terminate string */
1283 n = atoi (ip->argbuf);
1284 *ip->ap = ch;
1285
1286 return n; /* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
1287 }
1288
1289 void
1290 ite_putstr(s, len, dev)
1291 const u_char *s;
1292 int len;
1293 dev_t dev;
1294 {
1295 struct ite_softc *ip;
1296 int i;
1297
1298 ip = getitesp(dev);
1299
1300 /* XXX avoid problems */
1301 if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
1302 return;
1303
1304 SUBR_CURSOR(ip, START_CURSOROPT);
1305 for (i = 0; i < len; i++)
1306 if (s[i])
1307 iteputchar(s[i], ip);
1308 SUBR_CURSOR(ip, END_CURSOROPT);
1309 }
1310
1311 void
1312 iteputchar(c, ip)
1313 register int c;
1314 struct ite_softc *ip;
1315 {
1316 int n, x, y;
1317 char *cp;
1318
1319 if (c >= 0x20 && ip->escape) {
1320 switch (ip->escape) {
1321
1322 case ESC:
1323 switch (c) {
1324 /* first 7bit equivalents for the 8bit control characters */
1325
1326 case 'D':
1327 c = IND;
1328 ip->escape = 0;
1329 break; /* and fall into the next switch below (same for all `break') */
1330
1331 case 'E':
1332 /* next line */
1333 c = NEL;
1334 ip->escape = 0;
1335 break;
1336
1337 case 'H':
1338 /* set TAB at current col */
1339 c = HTS;
1340 ip->escape = 0;
1341 break;
1342
1343 case 'M':
1344 /* reverse index */
1345 c = RI;
1346 ip->escape = 0;
1347 break;
1348
1349 case 'N':
1350 /* single shift G2 */
1351 c = SS2;
1352 ip->escape = 0;
1353 break;
1354
1355 case 'O':
1356 /* single shift G3 */
1357 c = SS3;
1358 ip->escape = 0;
1359 break;
1360
1361 case 'P':
1362 /* DCS detected */
1363 c = DCS;
1364 ip->escape = 0;
1365 break;
1366
1367 case '[':
1368 c = CSI;
1369 ip->escape = 0;
1370 break;
1371
1372 case '\\':
1373 /* String Terminator */
1374 c = ST;
1375 ip->escape = 0;
1376 break;
1377
1378 case ']':
1379 c = OSC;
1380 ip->escape = 0;
1381 break;
1382
1383 case '^':
1384 c = PM;
1385 ip->escape = 0;
1386 break;
1387
1388 case '_':
1389 c = APC;
1390 ip->escape = 0;
1391 break;
1392
1393
1394 /* introduces 7/8bit control */
1395 case ' ':
1396 /* can be followed by either F or G */
1397 ip->escape = ' ';
1398 break;
1399
1400
1401 /* a lot of character set selections, not yet used...
1402 94-character sets: */
1403 case '(': /* G0 */
1404 case ')': /* G1 */
1405 ip->escape = c;
1406 return;
1407
1408 case '*': /* G2 */
1409 case '+': /* G3 */
1410 case 'B': /* ASCII */
1411 case 'A': /* ISO latin 1 */
1412 case '<': /* user preferred suplemental */
1413 case '0': /* dec special graphics */
1414
1415 /* 96-character sets: */
1416 case '-': /* G1 */
1417 case '.': /* G2 */
1418 case '/': /* G3 */
1419
1420 /* national character sets: */
1421 case '4': /* dutch */
1422 case '5':
1423 case 'C': /* finnish */
1424 case 'R': /* french */
1425 case 'Q': /* french canadian */
1426 case 'K': /* german */
1427 case 'Y': /* italian */
1428 case '6': /* norwegian/danish */
1429 /* note: %5 and %6 are not supported (two chars..) */
1430
1431 ip->escape = 0;
1432 /* just ignore for now */
1433 return;
1434
1435 /* 94-multibyte character sets designate */
1436 case '$':
1437 ip->escape = '$';
1438 return;
1439
1440 /* locking shift modes */
1441 case '`':
1442 ip->GR = &ip->G1;
1443 ip->escape = 0;
1444 return;
1445
1446 case 'n':
1447 ip->GL = &ip->G2;
1448 ip->escape = 0;
1449 return;
1450
1451 case '}':
1452 ip->GR = &ip->G2;
1453 ip->escape = 0;
1454 return;
1455
1456 case 'o':
1457 ip->GL = &ip->G3;
1458 ip->escape = 0;
1459 return;
1460
1461 case '|':
1462 ip->GR = &ip->G3;
1463 ip->escape = 0;
1464 return;
1465
1466 case '~':
1467 ip->GR = &ip->G1;
1468 ip->escape = 0;
1469 return;
1470
1471 /* font width/height control */
1472 case '#':
1473 ip->escape = '#';
1474 return;
1475
1476 case 'c':
1477 /* hard terminal reset .. */
1478 ite_reset (ip);
1479 SUBR_CURSOR(ip, MOVE_CURSOR);
1480 ip->escape = 0;
1481 return;
1482
1483
1484 case '7':
1485 /* save cursor */
1486 ip->save_curx = ip->curx;
1487 ip->save_cury = ip->cury;
1488 ip->save_attribute = ip->attribute;
1489 ip->sc_om = ip->inside_margins;
1490 ip->sc_G0 = ip->G0;
1491 ip->sc_G1 = ip->G1;
1492 ip->sc_G2 = ip->G2;
1493 ip->sc_G3 = ip->G3;
1494 ip->sc_GL = ip->GL;
1495 ip->sc_GR = ip->GR;
1496 ip->escape = 0;
1497 return;
1498
1499 case '8':
1500 /* restore cursor */
1501 ip->curx = ip->save_curx;
1502 ip->cury = ip->save_cury;
1503 ip->attribute = ip->save_attribute;
1504 ip->inside_margins = ip->sc_om;
1505 ip->G0 = ip->sc_G0;
1506 ip->G1 = ip->sc_G1;
1507 ip->G2 = ip->sc_G2;
1508 ip->G3 = ip->sc_G3;
1509 ip->GL = ip->sc_GL;
1510 ip->GR = ip->sc_GR;
1511 SUBR_CURSOR(ip, MOVE_CURSOR);
1512 ip->escape = 0;
1513 return;
1514
1515 case '=':
1516 /* keypad application mode */
1517 ip->keypad_appmode = 1;
1518 ip->escape = 0;
1519 return;
1520
1521 case '>':
1522 /* keypad numeric mode */
1523 ip->keypad_appmode = 0;
1524 ip->escape = 0;
1525 return;
1526
1527 case 'Z': /* request ID */
1528 if (ip->emul_level == EMUL_VT100)
1529 ite_sendstr (ip, "\033[61;0c"); /* XXX not clean */
1530 else
1531 ite_sendstr (ip, "\033[63;0c"); /* XXX not clean */
1532 ip->escape = 0;
1533 return;
1534
1535 /* default catch all for not recognized ESC sequences */
1536 default:
1537 ip->escape = 0;
1538 return;
1539 }
1540 break;
1541
1542
1543 case '(': /* designate G0 */
1544 switch (c) {
1545 case 'B': /* USASCII */
1546 ip->G0 = CSET_ASCII;
1547 ip->escape = 0;
1548 return;
1549 case 'I':
1550 ip->G0 = CSET_JISKANA;
1551 ip->escape = 0;
1552 return;
1553 case 'J':
1554 ip->G0 = CSET_JISROMA;
1555 ip->escape = 0;
1556 return;
1557 case 'A': /* British or ISO-Latin-1 */
1558 case 'H': /* Swedish */
1559 case 'K': /* German */
1560 case 'R': /* French */
1561 case 'Y': /* Italian */
1562 case 'Z': /* Spanish */
1563 default:
1564 /* not supported */
1565 ip->escape = 0;
1566 return;
1567 }
1568
1569 case ')': /* designate G1 */
1570 ip->escape = 0;
1571 return;
1572
1573 case '$': /* 94-multibyte character set */
1574 switch (c) {
1575 case '@':
1576 ip->G0 = CSET_JIS1978;
1577 ip->escape = 0;
1578 return;
1579 case 'B':
1580 ip->G0 = CSET_JIS1983;
1581 ip->escape = 0;
1582 return;
1583 case 'D':
1584 ip->G0 = CSET_JIS1990;
1585 ip->escape = 0;
1586 return;
1587 default:
1588 /* not supported */
1589 ip->escape = 0;
1590 return;
1591 }
1592
1593 case ' ':
1594 switch (c) {
1595 case 'F':
1596 ip->eightbit_C1 = 0;
1597 ip->escape = 0;
1598 return;
1599
1600 case 'G':
1601 ip->eightbit_C1 = 1;
1602 ip->escape = 0;
1603 return;
1604
1605 default:
1606 /* not supported */
1607 ip->escape = 0;
1608 return;
1609 }
1610 break;
1611
1612 case '#':
1613 switch (c) {
1614 case '5':
1615 /* single height, single width */
1616 ip->escape = 0;
1617 return;
1618
1619 case '6':
1620 /* double width, single height */
1621 ip->escape = 0;
1622 return;
1623
1624 case '3':
1625 /* top half */
1626 ip->escape = 0;
1627 return;
1628
1629 case '4':
1630 /* bottom half */
1631 ip->escape = 0;
1632 return;
1633
1634 case '8':
1635 /* screen alignment pattern... */
1636 alignment_display (ip);
1637 ip->escape = 0;
1638 return;
1639
1640 default:
1641 ip->escape = 0;
1642 return;
1643 }
1644 break;
1645
1646
1647
1648 case CSI:
1649 /* the biggie... */
1650 switch (c) {
1651 case '0': case '1': case '2': case '3': case '4':
1652 case '5': case '6': case '7': case '8': case '9':
1653 case ';': case '\"': case '$': case '>':
1654 if (ip->ap < ip->argbuf + MAX_ARGSIZE)
1655 *ip->ap++ = c;
1656 return;
1657
1658 case 'p':
1659 *ip->ap = 0;
1660 if (!strncmp(ip->argbuf, "61\"", 3))
1661 ip->emul_level = EMUL_VT100;
1662 else if (!strncmp(ip->argbuf, "63;1\"", 5)
1663 || !strncmp(ip->argbuf, "62;1\"", 5))
1664 ip->emul_level = EMUL_VT300_7;
1665 else
1666 ip->emul_level = EMUL_VT300_8;
1667 ip->escape = 0;
1668 return;
1669
1670
1671 case '?':
1672 *ip->ap = 0;
1673 ip->escape = '?';
1674 ip->ap = ip->argbuf;
1675 return;
1676
1677
1678 case 'c':
1679 /* device attributes */
1680 *ip->ap = 0;
1681 if (ip->argbuf[0] == '>') {
1682 ite_sendstr (ip, "\033[>24;0;0;0c");
1683 } else
1684 switch (ite_zargnum(ip)) {
1685 case 0:
1686 /* primary DA request, send primary DA response */
1687 if (ip->emul_level == EMUL_VT100)
1688 ite_sendstr (ip, "\033[?1;1c");
1689 else
1690 ite_sendstr (ip, "\033[63;0c");
1691 break;
1692 }
1693 ip->escape = 0;
1694 return;
1695
1696 case 'n':
1697 switch (ite_zargnum(ip)) {
1698 case 5:
1699 ite_sendstr (ip, "\033[0n"); /* no malfunction */
1700 break;
1701 case 6:
1702 /* cursor position report */
1703 sprintf (ip->argbuf, "\033[%d;%dR",
1704 ip->cury + 1, ip->curx + 1);
1705 ite_sendstr (ip, ip->argbuf);
1706 break;
1707 }
1708 ip->escape = 0;
1709 return;
1710
1711
1712 case 'x':
1713 switch (ite_zargnum(ip)) {
1714 case 0:
1715 /* Fake some terminal parameters. */
1716 ite_sendstr (ip, "\033[2;1;1;112;112;1;0x");
1717 break;
1718 case 1:
1719 ite_sendstr (ip, "\033[3;1;1;112;112;1;0x");
1720 break;
1721 }
1722 ip->escape = 0;
1723 return;
1724
1725
1726 case 'g':
1727 /* clear tabs */
1728 switch (ite_zargnum(ip)) {
1729 case 0:
1730 if (ip->curx < ip->cols)
1731 ip->tabs[ip->curx] = 0;
1732 break;
1733 case 3:
1734 for (n = 0; n < ip->cols; n++)
1735 ip->tabs[n] = 0;
1736 break;
1737
1738 default:
1739 /* ignore */
1740 break;
1741 }
1742 ip->escape = 0;
1743 return;
1744
1745
1746 case 'h': /* set mode */
1747 case 'l': /* reset mode */
1748 n = ite_zargnum (ip);
1749 switch (n) {
1750 case 4:
1751 ip->imode = (c == 'h'); /* insert/replace mode */
1752 break;
1753 case 20:
1754 ip->linefeed_newline = (c == 'h');
1755 break;
1756 }
1757 ip->escape = 0;
1758 return;
1759
1760
1761 case 'M':
1762 /* delete line */
1763 ite_dnline (ip, ite_argnum (ip));
1764 ip->escape = 0;
1765 return;
1766
1767
1768 case 'L':
1769 /* insert line */
1770 ite_inline (ip, ite_argnum (ip));
1771 ip->escape = 0;
1772 return;
1773
1774
1775 case 'P':
1776 /* delete char */
1777 ite_dnchar (ip, ite_argnum (ip));
1778 ip->escape = 0;
1779 return;
1780
1781
1782 case '@':
1783 /* insert char(s) */
1784 ite_inchar (ip, ite_argnum (ip));
1785 ip->escape = 0;
1786 return;
1787
1788 case '!':
1789 /* soft terminal reset */
1790 ip->escape = 0; /* XXX */
1791 return;
1792
1793 case 'G':
1794 /* this one was *not* in my vt320 manual but in
1795 a vt320 termcap entry.. who is right?
1796 It's supposed to set the horizontal cursor position. */
1797 *ip->ap = 0;
1798 x = atoi (ip->argbuf);
1799 if (x) x--;
1800 ip->curx = min(x, ip->cols - 1);
1801 ip->escape = 0;
1802 SUBR_CURSOR(ip, MOVE_CURSOR);
1803 clr_attr (ip, ATTR_INV);
1804 return;
1805
1806
1807 case 'd':
1808 /* same thing here, this one's for setting the absolute
1809 vertical cursor position. Not documented... */
1810 *ip->ap = 0;
1811 y = atoi (ip->argbuf);
1812 if (y) y--;
1813 if (ip->inside_margins)
1814 y += ip->top_margin;
1815 ip->cury = min(y, ip->rows - 1);
1816 ip->escape = 0;
1817 snap_cury(ip);
1818 SUBR_CURSOR(ip, MOVE_CURSOR);
1819 clr_attr (ip, ATTR_INV);
1820 return;
1821
1822
1823 case 'H':
1824 case 'f':
1825 *ip->ap = 0;
1826 y = atoi (ip->argbuf);
1827 x = 0;
1828 cp = strchr(ip->argbuf, ';');
1829 if (cp)
1830 x = atoi (cp + 1);
1831 if (x) x--;
1832 if (y) y--;
1833 if (ip->inside_margins)
1834 y += ip->top_margin;
1835 ip->cury = min(y, ip->rows - 1);
1836 ip->curx = min(x, ip->cols - 1);
1837 ip->escape = 0;
1838 snap_cury(ip);
1839 SUBR_CURSOR(ip, MOVE_CURSOR);
1840 /*clr_attr (ip, ATTR_INV);*/
1841 return;
1842
1843 case 'A':
1844 /* cursor up */
1845 n = ite_argnum (ip);
1846 n = ip->cury - (n ? n : 1);
1847 if (n < 0) n = 0;
1848 if (ip->inside_margins)
1849 n = max(ip->top_margin, n);
1850 else if (n == ip->top_margin - 1)
1851 /* allow scrolling outside region, but don't scroll out
1852 of active region without explicit CUP */
1853 n = ip->top_margin;
1854 ip->cury = n;
1855 ip->escape = 0;
1856 SUBR_CURSOR(ip, MOVE_CURSOR);
1857 clr_attr (ip, ATTR_INV);
1858 return;
1859
1860 case 'B':
1861 /* cursor down */
1862 n = ite_argnum (ip);
1863 n = ip->cury + (n ? n : 1);
1864 n = min(ip->rows - 1, n);
1865 #if 0
1866 if (ip->inside_margins)
1867 #endif
1868 n = min(ip->bottom_margin, n);
1869 #if 0
1870 else if (n == ip->bottom_margin + 1)
1871 /* allow scrolling outside region, but don't scroll out
1872 of active region without explicit CUP */
1873 n = ip->bottom_margin;
1874 #endif
1875 ip->cury = n;
1876 ip->escape = 0;
1877 SUBR_CURSOR(ip, MOVE_CURSOR);
1878 clr_attr (ip, ATTR_INV);
1879 return;
1880
1881 case 'C':
1882 /* cursor forward */
1883 n = ite_argnum (ip);
1884 n = n ? n : 1;
1885 ip->curx = min(ip->curx + n, ip->cols - 1);
1886 ip->escape = 0;
1887 SUBR_CURSOR(ip, MOVE_CURSOR);
1888 clr_attr (ip, ATTR_INV);
1889 return;
1890
1891 case 'D':
1892 /* cursor backward */
1893 n = ite_argnum (ip);
1894 n = n ? n : 1;
1895 n = ip->curx - n;
1896 ip->curx = n >= 0 ? n : 0;
1897 ip->escape = 0;
1898 SUBR_CURSOR(ip, MOVE_CURSOR);
1899 clr_attr (ip, ATTR_INV);
1900 return;
1901
1902
1903 case 'J':
1904 /* erase screen */
1905 *ip->ap = 0;
1906 n = ite_zargnum (ip);
1907 if (n == 0)
1908 ite_clrtoeos(ip);
1909 else if (n == 1)
1910 ite_clrtobos(ip);
1911 else if (n == 2)
1912 ite_clrscreen(ip);
1913 ip->escape = 0;
1914 return;
1915
1916
1917 case 'K':
1918 /* erase line */
1919 n = ite_zargnum (ip);
1920 if (n == 0)
1921 ite_clrtoeol(ip);
1922 else if (n == 1)
1923 ite_clrtobol(ip);
1924 else if (n == 2)
1925 ite_clrline(ip);
1926 ip->escape = 0;
1927 return;
1928
1929 case 'S':
1930 /* scroll up */
1931 n = ite_zargnum (ip);
1932 if (n <= 0)
1933 n = 1;
1934 else if (n > ip->rows-1)
1935 n = ip->rows-1;
1936 SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
1937 ip->escape = 0;
1938 return;
1939
1940 case 'T':
1941 /* scroll down */
1942 n = ite_zargnum (ip);
1943 if (n <= 0)
1944 n = 1;
1945 else if (n > ip->rows-1)
1946 n = ip->rows-1;
1947 SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
1948 ip->escape = 0;
1949 return;
1950
1951 case 'X':
1952 /* erase character */
1953 n = ite_argnum(ip) - 1;
1954 n = min(n, ip->cols - 1 - ip->curx);
1955 for (; n >= 0; n--) {
1956 attrclr(ip, ip->cury, ip->curx + n, 1, 1);
1957 SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1958 }
1959 ip->escape = 0;
1960 return;
1961
1962
1963 case '}': case '`':
1964 /* status line control */
1965 ip->escape = 0;
1966 return;
1967
1968 case 'r':
1969 /* set scrolling region */
1970 ip->escape = 0;
1971 *ip->ap = 0;
1972 x = atoi (ip->argbuf);
1973 x = x ? x : 1;
1974 y = ip->rows;
1975 cp = strchr(ip->argbuf, ';');
1976 if (cp) {
1977 y = atoi (cp + 1);
1978 y = y ? y : ip->rows;
1979 }
1980 if (y <= x)
1981 return;
1982 x--;
1983 y--;
1984 ip->top_margin = min(x, ip->rows - 2);
1985 ip->bottom_margin = min(y, ip->rows - 1);
1986 if (ip->inside_margins) {
1987 ip->cury = ip->top_margin;
1988 } else
1989 ip->cury = 0;
1990 ip->curx = 0;
1991 return;
1992
1993
1994 case 'm':
1995 /* big attribute setter/resetter */
1996 {
1997 char *cp;
1998 *ip->ap = 0;
1999 /* kludge to make CSIm work (== CSI0m) */
2000 if (ip->ap == ip->argbuf)
2001 ip->ap++;
2002 for (cp = ip->argbuf; cp < ip->ap; ) {
2003 switch (*cp) {
2004 case 0:
2005 case '0':
2006 clr_attr (ip, ATTR_ALL);
2007 ip->fgcolor = 7;
2008 ip->bgcolor = 0;
2009 cp++;
2010 break;
2011
2012 case '1':
2013 set_attr (ip, ATTR_BOLD);
2014 cp++;
2015 break;
2016
2017 case '2':
2018 switch (cp[1]) {
2019 case '2':
2020 clr_attr (ip, ATTR_BOLD);
2021 cp += 2;
2022 break;
2023
2024 case '4':
2025 clr_attr (ip, ATTR_UL);
2026 cp += 2;
2027 break;
2028
2029 case '5':
2030 clr_attr (ip, ATTR_BLINK);
2031 cp += 2;
2032 break;
2033
2034 case '7':
2035 clr_attr (ip, ATTR_INV);
2036 cp += 2;
2037 break;
2038
2039 default:
2040 cp++;
2041 break;
2042 }
2043 break;
2044
2045 case '3':
2046 switch (cp[1]) {
2047 case '0': case '1': case '2': case '3':
2048 case '4': case '5': case '6': case '7':
2049 /* foreground colors */
2050 ip->fgcolor = cp[1] - '0';
2051 cp += 2;
2052 break;
2053 default:
2054 cp++;
2055 break;
2056 }
2057 break;
2058
2059 case '4':
2060 switch (cp[1]) {
2061 case '0': case '1': case '2': case '3':
2062 case '4': case '5': case '6': case '7':
2063 /* background colors */
2064 ip->bgcolor = cp[1] - '0';
2065 cp += 2;
2066 break;
2067 default:
2068 set_attr (ip, ATTR_UL);
2069 cp++;
2070 break;
2071 }
2072 break;
2073
2074 case '5':
2075 set_attr (ip, ATTR_BLINK);
2076 cp++;
2077 break;
2078
2079 case '7':
2080 set_attr (ip, ATTR_INV);
2081 cp++;
2082 break;
2083
2084 default:
2085 cp++;
2086 break;
2087 }
2088 }
2089
2090 }
2091 ip->escape = 0;
2092 return;
2093
2094
2095 case 'u':
2096 /* DECRQTSR */
2097 ite_sendstr (ip, "\033P\033\\");
2098 ip->escape = 0;
2099 return;
2100
2101 default:
2102 ip->escape = 0;
2103 return;
2104 }
2105 break;
2106
2107
2108
2109 case '?': /* CSI ? */
2110 switch (c) {
2111 case '0': case '1': case '2': case '3': case '4':
2112 case '5': case '6': case '7': case '8': case '9':
2113 case ';': case '\"': case '$':
2114 /* Don't fill the last character; it's needed. */
2115 /* XXX yeah, where ?? */
2116 if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
2117 *ip->ap++ = c;
2118 return;
2119
2120
2121 case 'n':
2122 /* Terminal Reports */
2123 *ip->ap = 0;
2124 if (ip->ap == &ip->argbuf[2]) {
2125 if (!strncmp(ip->argbuf, "15", 2))
2126 /* printer status: no printer */
2127 ite_sendstr (ip, "\033[13n");
2128
2129 else if (!strncmp(ip->argbuf, "25", 2))
2130 /* udk status */
2131 ite_sendstr (ip, "\033[20n");
2132
2133 else if (!strncmp(ip->argbuf, "26", 2))
2134 /* keyboard dialect: US */
2135 ite_sendstr (ip, "\033[27;1n");
2136 }
2137 ip->escape = 0;
2138 return;
2139
2140
2141 case 'h': /* set dec private modes */
2142 case 'l': /* reset dec private modes */
2143 n = ite_zargnum (ip);
2144 switch (n) {
2145 case 1:
2146 /* CKM - cursor key mode */
2147 ip->cursor_appmode = (c == 'h');
2148 break;
2149
2150 case 3:
2151 /* 132/80 columns (132 == 'h') */
2152 break;
2153
2154 case 4: /* smooth scroll */
2155 break;
2156
2157 case 5:
2158 /* light background (=='h') /dark background(=='l') */
2159 break;
2160
2161 case 6: /* origin mode */
2162 ip->inside_margins = (c == 'h');
2163 #if 0
2164 ip->curx = 0;
2165 ip->cury = ip->inside_margins ? ip->top_margin : 0;
2166 SUBR_CURSOR(ip, MOVE_CURSOR);
2167 #endif
2168 break;
2169
2170 case 7: /* auto wraparound */
2171 ip->auto_wrap = (c == 'h');
2172 break;
2173
2174 case 8: /* keyboard repeat */
2175 ip->key_repeat = (c == 'h');
2176 break;
2177
2178 case 20: /* newline mode */
2179 ip->linefeed_newline = (c == 'h');
2180 break;
2181
2182 case 25: /* cursor on/off */
2183 SUBR_CURSOR(ip, (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
2184 break;
2185 }
2186 ip->escape = 0;
2187 return;
2188
2189 case 'K':
2190 /* selective erase in line */
2191 case 'J':
2192 /* selective erase in display */
2193
2194 default:
2195 ip->escape = 0;
2196 return;
2197 }
2198 break;
2199
2200
2201 default:
2202 ip->escape = 0;
2203 return;
2204 }
2205 }
2206
2207 switch (c) {
2208 case 0x00: /* NUL */
2209 case 0x01: /* SOH */
2210 case 0x02: /* STX */
2211 case 0x03: /* ETX */
2212 case 0x04: /* EOT */
2213 case 0x05: /* ENQ */
2214 case 0x06: /* ACK */
2215 break;
2216
2217 case BEL:
2218 #if NBELL > 0
2219 if (kbd_ite && ite_tty[kbd_ite->device.dv_unit])
2220 opm_bell();
2221 #endif
2222 break;
2223
2224 case BS:
2225 if (--ip->curx < 0)
2226 ip->curx = 0;
2227 else
2228 SUBR_CURSOR(ip, MOVE_CURSOR);
2229 break;
2230
2231 case HT:
2232 for (n = ip->curx + 1; n < ip->cols; n++) {
2233 if (ip->tabs[n]) {
2234 ip->curx = n;
2235 SUBR_CURSOR(ip, MOVE_CURSOR);
2236 break;
2237 }
2238 }
2239 break;
2240
2241 case VT: /* VT is treated like LF */
2242 case FF: /* so is FF */
2243 case LF:
2244 /* cr->crlf distinction is done here, on output,
2245 not on input! */
2246 if (ip->linefeed_newline)
2247 ite_crlf (ip);
2248 else
2249 ite_lf (ip);
2250 break;
2251
2252 case CR:
2253 ite_cr (ip);
2254 break;
2255
2256
2257 case SO:
2258 ip->GL = &ip->G1;
2259 break;
2260
2261 case SI:
2262 ip->GL = &ip->G0;
2263 break;
2264
2265 case 0x10: /* DLE */
2266 case 0x11: /* DC1/XON */
2267 case 0x12: /* DC2 */
2268 case 0x13: /* DC3/XOFF */
2269 case 0x14: /* DC4 */
2270 case 0x15: /* NAK */
2271 case 0x16: /* SYN */
2272 case 0x17: /* ETB */
2273 break;
2274
2275 case CAN:
2276 ip->escape = 0; /* cancel any escape sequence in progress */
2277 break;
2278
2279 case 0x19: /* EM */
2280 break;
2281
2282 case SUB:
2283 ip->escape = 0; /* dito, but see below */
2284 /* should also display a reverse question mark!! */
2285 break;
2286
2287 case ESC:
2288 ip->escape = ESC;
2289 break;
2290
2291 case 0x1c: /* FS */
2292 case 0x1d: /* GS */
2293 case 0x1e: /* RS */
2294 case 0x1f: /* US */
2295 break;
2296
2297 /* now it gets weird.. 8bit control sequences.. */
2298 case IND: /* index: move cursor down, scroll */
2299 ite_index (ip);
2300 break;
2301
2302 case NEL: /* next line. next line, first pos. */
2303 ite_crlf (ip);
2304 break;
2305
2306 case HTS: /* set horizontal tab */
2307 if (ip->curx < ip->cols)
2308 ip->tabs[ip->curx] = 1;
2309 break;
2310
2311 case RI: /* reverse index */
2312 ite_rlf (ip);
2313 break;
2314
2315 case SS2: /* go into G2 for one character */
2316 ip->save_GL = ip->GR; /* GL XXX EUC */
2317 ip->GR = &ip->G2; /* GL XXX */
2318 break;
2319
2320 case SS3: /* go into G3 for one character */
2321 ip->save_GL = ip->GR; /* GL XXX EUC */
2322 ip->GR = &ip->G3; /* GL XXX */
2323 break;
2324
2325 case DCS: /* device control string introducer */
2326 ip->escape = DCS;
2327 ip->ap = ip->argbuf;
2328 break;
2329
2330 case CSI: /* control sequence introducer */
2331 ip->escape = CSI;
2332 ip->ap = ip->argbuf;
2333 break;
2334
2335 case ST: /* string terminator */
2336 /* ignore, if not used as terminator */
2337 break;
2338
2339 case OSC: /* introduces OS command. Ignore everything upto ST */
2340 ip->escape = OSC;
2341 break;
2342
2343 case PM: /* privacy message, ignore everything upto ST */
2344 ip->escape = PM;
2345 break;
2346
2347 case APC: /* application program command, ignore everything upto ST */
2348 ip->escape = APC;
2349 break;
2350
2351 case DEL:
2352 break;
2353
2354 default:
2355 if (!ip->save_char && (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI)) {
2356 ip->save_char = c;
2357 break;
2358 }
2359 if (ip->imode)
2360 ite_inchar(ip, ip->save_char ? 2 : 1);
2361 iteprecheckwrap(ip);
2362 #ifdef DO_WEIRD_ATTRIBUTES
2363 if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2364 attrset(ip, ATTR_INV);
2365 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
2366 }
2367 else
2368 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
2369 #else
2370 SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
2371 #endif
2372 /* SUBR_CURSOR(ip, DRAW_CURSOR);*/
2373 itecheckwrap(ip);
2374 if (ip->save_char) {
2375 itecheckwrap(ip);
2376 ip->save_char = 0;
2377 }
2378 if (ip->save_GL) {
2379 /*
2380 * reset single shift
2381 */
2382 ip->GR = ip->save_GL;
2383 ip->save_GL = 0;
2384 }
2385 break;
2386 }
2387 }
2388
2389 static void
2390 iteprecheckwrap(ip)
2391 struct ite_softc *ip;
2392 {
2393 if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
2394 ip->curx = 0;
2395 clr_attr(ip, ATTR_INV);
2396 if (++ip->cury >= ip->bottom_margin + 1) {
2397 ip->cury = ip->bottom_margin;
2398 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2399 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2400 ite_clrtoeol(ip);
2401 } /*else
2402 SUBR_CURSOR(ip, MOVE_CURSOR);*/
2403 }
2404 }
2405
2406 static void
2407 itecheckwrap(ip)
2408 struct ite_softc *ip;
2409 {
2410 #if 0
2411 if (++ip->curx == ip->cols) {
2412 if (ip->auto_wrap) {
2413 ip->curx = 0;
2414 clr_attr(ip, ATTR_INV);
2415 if (++ip->cury >= ip->bottom_margin + 1) {
2416 ip->cury = ip->bottom_margin;
2417 SUBR_CURSOR(ip, MOVE_CURSOR);
2418 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2419 ite_clrtoeol(ip);
2420 return;
2421 }
2422 } else
2423 /* stay there if no autowrap.. */
2424 ip->curx--;
2425 }
2426 #else
2427 if (ip->curx < ip->cols) {
2428 ip->curx++;
2429 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2430 }
2431 #endif
2432 }
2433
2434 #endif
2435
2436 #if NITE > 0 && NKBD > 0
2437
2438 /*
2439 * Console functions
2440 */
2441 #include <dev/cons.h>
2442 extern void kbdenable __P((int));
2443 extern int kbdcngetc __P((void));
2444
2445 /*
2446 * Return a priority in consdev->cn_pri field highest wins. This function
2447 * is called before any devices have been probed.
2448 */
2449 void
2450 itecnprobe(cd)
2451 struct consdev *cd;
2452 {
2453 int maj;
2454
2455 /* locate the major number */
2456 maj = cdevsw_lookup_major(&ite_cdevsw);
2457
2458 /*
2459 * return priority of the best ite (already picked from attach)
2460 * or CN_DEAD.
2461 */
2462 if (con_itesoftc.grf == NULL)
2463 cd->cn_pri = CN_DEAD;
2464 else {
2465 con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
2466 /*
2467 * hardcode the minor number.
2468 * currently we support only one ITE, it is enough for now.
2469 */
2470 con_itesoftc.isw = &itesw[0];
2471 cd->cn_pri = CN_INTERNAL;
2472 cd->cn_dev = makedev(maj, 0);
2473 }
2474
2475 }
2476
2477 void
2478 itecninit(cd)
2479 struct consdev *cd;
2480 {
2481 struct ite_softc *ip;
2482
2483 ip = getitesp(cd->cn_dev);
2484 iteinit(cd->cn_dev); /* init console unit */
2485 ip->flags |= ITE_ACTIVE | ITE_ISCONS;
2486 kbdenable(0);
2487 mfp_send_usart(0x49);
2488 }
2489
2490 /*
2491 * itecnfinish() is called in ite_init() when the device is
2492 * being probed in the normal fasion, thus we can finish setting
2493 * up this ite now that the system is more functional.
2494 */
2495 void
2496 itecnfinish(ip)
2497 struct ite_softc *ip;
2498 {
2499 static int done;
2500
2501 if (done)
2502 return;
2503 done = 1;
2504 }
2505
2506 /*ARGSUSED*/
2507 int
2508 itecngetc(dev)
2509 dev_t dev;
2510 {
2511 register int c;
2512
2513 do {
2514 c = kbdcngetc();
2515 c = ite_cnfilter(c);
2516 } while (c == -1);
2517 return (c);
2518 }
2519
2520 void
2521 itecnputc(dev, c)
2522 dev_t dev;
2523 int c;
2524 {
2525 static int paniced = 0;
2526 struct ite_softc *ip = getitesp(dev);
2527 char ch = c;
2528 #ifdef ITE_KERNEL_ATTR
2529 short save_attribute;
2530 #endif
2531
2532 if (panicstr && !paniced &&
2533 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2534 (void) iteon(dev, 3);
2535 paniced = 1;
2536 }
2537 #ifdef ITE_KERNEL_ATTR
2538 save_attribute = ip->attribute;
2539 ip->attribute = ITE_KERNEL_ATTR;
2540 #endif
2541 ite_putstr(&ch, 1, dev);
2542 #ifdef ITE_KERNEL_ATTR
2543 ip->attribute = save_attribute;
2544 #endif
2545 }
2546 #endif
2547