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