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