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