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