xref: /original-bsd/sys/news3400/bm/vt100.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7  *
8  * %sccs.include.redist.c%
9  *
10  * from: $Hdr: vt100.c,v 4.300 91/06/09 06:14:56 root Rel41 $ SONY
11  *
12  *	@(#)vt100.c	8.1 (Berkeley) 06/10/93
13  */
14 
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <sys/systm.h>
18 #include <news3400/iop/framebuf.h>
19 #include <news3400/iop/kbreg.h>
20 #include <news3400/iop/keyboard.h>
21 #include <news3400/fb/fbdefs.h>
22 #include <news3400/bm/vt100.h>
23 #include <news3400/bm/bitmapif.h>
24 
25 #ifdef IPC_MRX
26 #include "config.h"
27 #define kbd_ioctl(chan, cmd, argp) { \
28 	if (kb_ioctl) \
29 		(*kb_ioctl)(chan, cmd, argp); \
30 }
31 #endif
32 
33 #ifdef IPC_MRX
34 #include "mrx.h"
35 #include "process.h"
36 #include "object.h"
37 #include "console.h"
38 #endif
39 
40 #ifdef CPU_SINGLE
41 #include <news3400/sio/scc.h>
42 #endif
43 
44 extern Key_string key_str;
45 extern int tmode;
46 static unsigned int first_code;
47 
48 #ifdef IPC_MRX
49 #define SCC_KEYBOARD	0
50 #endif
51 
52 SCREEN screen;
53 struct cursor inner_buf_csr;
54 int inner_buf_tstat;
55 char c_pos_mess[C_MESS_SIZ];
56 extern struct csr_buf local_csr_buf;
57 
58 #ifdef IPC_MRX
59 int bitmap_use;
60 #ifdef IPC_3CPU
61 #include "../../ubdev/msgio.h"
62 extern int ipc_ready;
63 #endif /* IPC_3CPU */
64 extern struct cons_devsw vt100_cons;
65 #endif /* IPC_MRX */
66 
67 #ifdef CPU_DOUBLE
68 int auto_dimmer();
69 #endif
70 
71 #if CPU_SINGLE
72 extern int hz;
73 extern kbd_profun_init();
74 #endif
75 
76 lRectangle char_r1;
77 lRectangle font_r1;
78 lRectangle char_r2;
79 lRectangle font_r2;
80 
81 int	font_len1;
82 int	font_len2;
83 
84 int	fcolor;
85 int	bcolor;
86 
87 int	font_w;
88 int	font_h;
89 int	char_w;
90 int	char_h;
91 int	scr_w;
92 int	scr_h;
93 int	ch_pos;
94 int	ul_pos;
95 int	x_ofst;
96 int	y_ofst;
97 int	rit_m;
98 int	btm_m;
99 int	bell_len;
100 int	dim_cnt;
101 int	a_dim_on;
102 
103 unsigned short fbuf[256];
104 int	fp;
105 int	fpn;
106 lPoint	fpp;
107 int	fpa;
108 
109 vt100init()
110 {
111 	register int i;
112 	register SCREEN	*sp = &screen;
113 
114 	sp->s_term_mode = 0;
115 	sp->s_term_mode |= (SRM|DECSCLM|DECAWM|DECARM|DECCSR_ACTV);
116 	sp->s_current_stat = 0;
117 	sp->s_csr.csr_x = 1;
118 	sp->s_csr.csr_y = 1;
119 	sp->s_csr.csr_p.x = x_ofst;
120 	sp->s_csr.csr_p.y = y_ofst;
121 	sp->s_csr.csr_attributes = NORMALM;
122 	sp->s_region.top_margin = TOP_M;
123 	sp->s_region.btm_margin = btm_m;
124 	sp->s_plane = consfb->planemask;
125 	sp->s_bgcol = 0;
126 	fcolor = sp->s_plane;
127 	bcolor = sp->s_bgcol;
128 	for (i = 0; i < RIT_M_MAX; i++)
129 		sp->s_tab_pos[i] = 0;
130 	for (i = 9; i < RIT_M_MAX; i +=8)
131 		sp->s_tab_pos[i] = 1;
132 
133 	esc_store_csr(sp);
134 	inner_buf_tstat = sp->s_term_mode & (DECOM|DECAWM);
135 	local_csr_buf.csr_number = 1;
136 
137 	cursor_on(&sp->s_csr.csr_p);
138 }
139 
140 ncp_str(p, q, n)
141 	register char *p, *q;
142 	register int n;
143 {
144 	while (n-- > 0)
145 		*q++ = *p++;
146 }
147 
148 /*
149  *  default parameter set
150  */
151 set_default_param()
152 {
153 	register struct fbdev *cfb = consfb;
154 
155 	font_w = cfb->font_w;
156 	font_h = cfb->font_h;
157 	char_w = cfb->char_w;
158 	char_h = cfb->char_h;
159 	scr_w  = cfb->scr_w;
160 	scr_h  = cfb->scr_h;
161 	ch_pos = cfb->ch_pos;
162 	ul_pos = cfb->ul_pos;
163 	x_ofst = cfb->x_offset;
164 	y_ofst = cfb->y_offset;
165 	rit_m  = cfb->rit_m;
166 	btm_m  = cfb->btm_m;
167 	a_dim_on = 1;
168 
169 	font_r1.extent.x = font_w;
170 	font_r1.extent.y = font_h;
171 	font_r2.extent.x = font_w * 2;
172 	font_r2.extent.y = font_h;
173 	font_len1 = (font_w + 0x0f) >> 4;
174 	font_len2 = (font_w*2 + 0x0f) >> 4;
175 	char_r1.extent.x = char_w;
176 	char_r1.extent.y = char_h;
177 	char_r2.extent.x = char_w * 2;
178 	char_r2.extent.y = char_h;
179 
180 	dim_cnt = DIM_CNT_DFLT;
181 	bell_len = BELL_LEN_DFLT;
182 }
183 
184 vt100_open()
185 {
186 	static int only_one = 0;
187 	extern char **ext_fnt_addr;
188 
189 	set_default_param();
190 	vt100init();
191 	bitmapinit();
192 	if (only_one == 0) {
193 #ifdef IPC_MRX
194 #ifdef IPC_3CPU
195 		while (ipc_ready == 0)
196 			proc_sleep_self(100);
197 #endif
198 		while ((bitmap_use = object_query(BITMAP)) <= 0)
199 			proc_sleep_self(100);
200 
201 		proc_create("auto_dimmer", auto_dimmer, 401, 512, 0);
202 #endif /* IPC_MRX */
203 		only_one = 1;
204 	}
205 #define	INIT_STRING	"\033[42;1H"
206 	vt100_write(0, INIT_STRING, sizeof(INIT_STRING) - 1);
207 #ifdef CPU_SINGLE
208 	kbd_open(SCC_KEYBOARD);
209 #endif
210 }
211 
212 #ifdef IPC_MRX
213 vt100_cons_setup()
214 {
215 	int vt100_open(), vt100_read(), vt100_write(), vt100_ioctl();
216 
217 	vt100_cons.open = vt100_open;
218 	vt100_cons.read = vt100_read;
219 	vt100_cons.write = vt100_write;
220 	vt100_cons.ioctl = vt100_ioctl;
221 }
222 
223 #define DIMMER_RESET	0
224 #define DIMMER_ON	1
225 #define DIMMER_OFF	2
226 #define DIMMER_INTERVAL	60		/* sec */
227 
228 static int dimmer_stdport;
229 
230 auto_dimmer()
231 {
232 	register int select, i;
233 	register int dimm_counter = DIM_CNT_DFLT;
234 	register int dimm_level = 0;
235 	int ports[2], *mode;
236 
237 	spl0();
238 	ports[0] = dimmer_stdport = STDPORT;
239 	ports[1] = port_create("auto_dimmer_sub");
240 	register_interval(ports[1], DIMMER_INTERVAL);
241 	for(;;) {
242 		select = msg_select(2, ports);
243 		if (select == 0) {
244 			msg_recv(ports[0], NULL, &mode, NULL, 0);
245 			switch (*mode) {
246 			case DIMMER_RESET:
247 				if (!a_dim_on)
248 					break;
249 				dimm_counter = dim_cnt;
250 				if (dimm_level > 0) {
251 					dimm_level =0;
252 					for (i = 0; i < nfbdev; i++)
253 						fbbm_set_dimmer(&fbdev[i], 0);
254 				}
255 				break;
256 			case DIMMER_ON:
257 				dimm_counter = dim_cnt;
258 				dimm_level =0;
259 				for (i = 0; i < nfbdev; i++)
260 					fbbm_set_dimmer(&fbdev[i], dimm_level);
261 				a_dim_on = 1;
262 				break;
263 			case DIMMER_OFF:
264 				dimm_counter = dim_cnt;
265 				dimm_level =0;
266 				for (i = 0; i < nfbdev; i++)
267 					fbbm_set_dimmer(&fbdev[i], dimm_level);
268 				a_dim_on = 0;
269 				break;
270 			}
271 		} else {
272 			msg_recv(ports[1], NULL, NULL, NULL, 0);
273 			if (a_dim_on && (dimm_counter-- <= 0)) {
274 				if (dimm_level < 3) {
275 					dimm_level++;
276 				}
277 				for (i = 0; i < nfbdev; i++)
278 					fbbm_set_dimmer(&fbdev[i], dimm_level);
279 				dimm_counter = dim_cnt;
280 			}
281 		}
282 	}
283 }
284 
285 rst_dimmer_cnt()
286 {
287 	register int diff;
288 	static unsigned last_time;
289 	extern unsigned sys_time;
290 	int mode = DIMMER_RESET;
291 
292 	diff = sys_time - last_time;
293 	if (diff > DIMMER_INTERVAL*HZ || diff < 0) {
294 		dimmer(DIMMER_RESET);
295 		last_time = sys_time;
296 	}
297 }
298 
299 auto_dimmer_on()
300 {
301 	dimmer(DIMMER_ON);
302 }
303 
304 auto_dimmer_off()
305 {
306 	dimmer(DIMMER_OFF);
307 }
308 
309 dimmer(mode)
310 	int mode;
311 {
312 	if (dimmer_stdport)
313 		msg_send(dimmer_stdport, 0, &mode, sizeof(mode), 0);
314 }
315 #else /* IPC_MRX */
316 
317 static int dimmer_counter = DIM_CNT_DFLT;
318 static int dim_level = 0;
319 
320 #ifdef CPU_SINGLE
321 auto_dimmer()
322 {
323 	register int s, i;
324 
325 	s = spl4();
326 	if (a_dim_on && (dimmer_counter-- <= 0)) {
327 		if (dim_level < 3)
328 			dim_level++;
329 		for (i = 0; i < nfbdev; i++)
330 			fbbm_set_dimmer(&fbdev[i], dim_level);
331 		dimmer_counter = dim_cnt;
332 	}
333 	splx(s);
334 	timeout(auto_dimmer, (caddr_t) 0, 60 * hz);
335 }
336 #endif
337 
338 rst_dimmer_cnt()
339 {
340 	register int	s, i;
341 
342 	if (!a_dim_on)
343 		return;
344 #ifdef CPU_SINGLE
345 	s = spl4();
346 #endif
347 	dimmer_counter = dim_cnt;
348 
349 	if (dim_level > 0) {
350 		dim_level =0;
351 		for (i = 0; i < nfbdev; i++)
352 			fbbm_set_dimmer(&fbdev[i], 0);
353 	}
354 	splx(s);
355 }
356 
357 auto_dimmer_on()
358 {
359 	register int s, i;
360 
361 #ifdef CPU_SINGLE
362 	s = spl4();
363 #endif
364 	dimmer_counter = dim_cnt;
365 	dim_level =0;
366 	for (i = 0; i < nfbdev; i++)
367 		fbbm_set_dimmer(&fbdev[i], dim_level);
368 	a_dim_on = 1;
369 	splx(s);
370 }
371 
372 auto_dimmer_off()
373 {
374 	register int s, i;
375 
376 #ifdef CPU_SINGLE
377 	s = spl4();
378 #endif
379 	dimmer_counter = dim_cnt;
380 	dim_level =0;
381 	for (i = 0; i < nfbdev; i++)
382 		fbbm_set_dimmer(&fbdev[i], dim_level);
383 	a_dim_on = 0;
384 	splx(s);
385 }
386 #endif /* IPC_MRX */
387 /*
388  *  The routine `_putc(sp, c)' only prints a character c with the cursor
389  *  attributes by using `copy_char(x, y, c, attributes)'.
390  *  And when IRM (terminal insertion-replacement mode) is set, the characters
391  *  righthand side of the cursor are shifted right and lost when they passed
392  *  beyond the right margin.
393  *  The position is specified by the sp pointer of the structure SCREEN.
394  *
395  */
396 static
397 _putc(sp, c, kanji)
398 	register SCREEN	*sp;
399 	unsigned int c;
400 {
401 	if (sp->s_term_mode & IRM) {
402 		vt_flush(&(sp->s_csr));
403 		move_chars(sp->s_csr.csr_x, sp->s_csr.csr_y,
404 			   rit_m - sp->s_csr.csr_x - ((kanji)? 1: 0),
405 			   sp->s_csr.csr_x + ((kanji) ? 2: 1));
406 		copy_char(sp, c, kanji);
407 	}
408 	if (fp) {
409 		fbuf[fp++] = c;
410 		fpn += kanji + 1;
411 	} else {
412 		fbuf[fp++] = c;
413 		fpp = sp->s_csr.csr_p;
414 		fpa = sp->s_csr.csr_attributes;
415 		fpn = kanji + 1;
416 	}
417 }
418 
419 /*
420  *  Scroll up and down in the scroll region.
421  *  New oriented line must be cleared with terminal mode, that is whether
422  *  the screen is reverse mode or not.
423  */
424 scroll_up(top, bottom, revsw, fcol, bcol)
425 	int top;
426 	int bottom;
427 	int revsw;
428 	int fcol;
429 	int bcol;
430 {
431 	move_lines(top + 1, bottom - top, top);
432 	clear_lines(bottom, 1, revsw, fcol, bcol);
433 }
434 
435 scroll_down(top, bottom, revsw, fcol, bcol)
436 	int top;
437 	int bottom;
438 	int revsw;
439 	int fcol;
440 	int bcol;
441 {
442 	move_lines(top, bottom - top, top + 1);
443 	clear_lines(top, 1, revsw, fcol, bcol);
444 }
445 
446 /*
447  *  Back space
448  *  back_space(sp) moves cursor next to left at current cursor position.
449  *  The cursor can not move beyond left or right margin.
450  */
451 back_space(sp)
452 	register SCREEN *sp;
453 {
454 	register struct cursor *spc = &sp->s_csr;
455 
456 	cursor_off();
457 	if (spc->csr_x > LFT_M) {
458 		spc->csr_x -= 1;
459 		spc->csr_p.x -= char_w;
460 	}
461 	cursor_on(&spc->csr_p);
462 }
463 
464 /*
465  *  Tab stop
466  *  next_tab_stop(sp) moves cursor to next tab stop.
467  */
468 next_tab_stop(sp)
469 	register SCREEN *sp;
470 {
471 	register int i;
472 
473 	cursor_off();
474 	for (i = sp->s_csr.csr_x + 1; i < rit_m; i++)
475 		if (sp->s_tab_pos[i] == 1)
476 			break;
477 	sp->s_csr.csr_x = min(i, rit_m);
478 	sp->s_csr.csr_p.x = (sp->s_csr.csr_x - 1) * char_w + x_ofst;
479 	cursor_on(&sp->s_csr.csr_p);
480 }
481 
482 /*
483  *  Carriage return
484  *  carriage_ret(sp) moves cursor at beginning of the current line.
485  */
486 carriage_ret(sp)
487 	register SCREEN *sp;
488 {
489 	cursor_off();
490 	sp->s_csr.csr_x = LFT_M;
491 	sp->s_csr.csr_p.x = x_ofst;
492 	cursor_on(&sp->s_csr.csr_p);
493 }
494 
495 /*
496  *  Bell
497  */
498 static
499 bell()
500 {
501 #ifdef news1800
502 	static int port;
503 
504 	if (port == 0)
505 		port = port_create("port_cons_bell");
506 	kbd_ioctl(port, KIOCBELL, &bell_len);
507 #else
508 	kbd_ioctl(SCC_KEYBOARD, KIOCBELL, &bell_len);
509 #endif
510 	return (0);
511 }
512 
513 int
514 Putchar(c, eob)
515 	unsigned int c;
516 {
517 	register SCREEN *sp = &screen;
518 	unsigned int sftjis_to_jis();
519 
520 	c &= 0xff;
521 
522 	if (eob) {
523 		vt_flush(&(sp->s_csr));
524 		return(0);
525 	}
526 
527 	if (c == 0x1b) {	/*  c == esc */
528 		vt_flush(&(sp->s_csr));
529 		recover(sp);
530 		sp->s_current_stat |= ESCAPE;
531 		return;
532 	} else if (sp->s_current_stat & ESCAPE) {
533 		(*sp->s_esc_handler)(sp, c);
534 		return;
535 	} else if (sp->s_current_stat & SKANJI) {
536 		c = sftjis_to_jis(first_code, c);
537 		if (sp->s_current_stat & JKANJI) {
538 			addch(sp, c);
539 		} else {
540 			sp->s_current_stat |= JKANJI;
541 			addch(sp, c);
542 			sp->s_current_stat &= ~JKANJI;
543 		}
544 		sp->s_current_stat &= ~SKANJI;
545 		goto set_csr;
546 	} else if (sp->s_current_stat & EKANJI) {
547 		c = (c & 0x7f) | (first_code << 8);
548 		if (sp->s_current_stat & JKANJI) {
549 			addch(sp, c);
550 		} else {
551 			sp->s_current_stat |= JKANJI;
552 			addch(sp, c);
553 			sp->s_current_stat &= ~JKANJI;
554 		}
555 		sp->s_current_stat &= ~EKANJI;
556 		goto set_csr;
557 	} else if (sp->s_current_stat & JKANJI) {
558 		jiskanji(sp, c);
559 		goto set_csr;
560 	} else if (sp->s_current_stat & EKANA) {
561 			sp->s_current_stat &= ~EKANA;
562 			addch(sp, c);
563 		goto set_csr;
564 	}
565 	if (c < 0x20) {		/*  control code	*/
566 		vt_flush(&(sp->s_csr));
567 		switch (c) {
568 		case  0x00:	/*  ignore  */
569 			break;
570 		case  0x07:	/*  bell  */
571 			bell();
572 			break;
573 		case  0x08:	/*  back space  */
574 			back_space(sp);
575 			break;
576 		case  0x09:	/*  tabulation  */
577 			next_tab_stop(sp);
578 			break;
579 		case  0x0a:	/*  line feed  */
580 		case  0x0b:	/*  vertical feed  */
581 		case  0x0c:	/*  form feed  */
582 			esc_index(sp);
583 			break;
584 		case  0x0d:	/*  carriage return  */
585 			carriage_ret(sp);
586 			break;
587 		case  0x0e:	/*  shift out  */
588 			break;
589 		case  0x0f:	/*  shift in  */
590 			break;
591 		case  0x11:	/*  xon  */
592 			break;
593 		case  0x13:	/*  xoff  */
594 			break;
595 		case  0x18:	/*  cancel  */
596 			sp->s_current_stat &= ~ESCAPE;
597 			break;
598 		case  0x1b:	/*  escape  */
599 			/*	NOT REACHED	*/
600 			recover(sp);
601 			sp->s_current_stat |= ESCAPE;
602 			break;
603 		case  0x7f:	/*  delete  */
604 			break;
605 
606 		default:
607 			break;
608 		}
609 	} else {
610 		switch (tmode) {
611 #ifdef KM_SJIS
612 		case KM_SJIS:
613 			if ((c >= JVR1S && c <= JVR1E) ||
614 				(c >= JVR2S && c <= JVR2E)) {
615 				sp->s_current_stat |= SKANJI;
616 				first_code = c;
617 			}
618 			else
619 				addch(sp, c);
620 			break;
621 #endif
622 #ifdef KM_EUC
623 		case KM_EUC:
624 			if (c >= CS1S && c <= CS1E) {
625 				sp->s_current_stat |= EKANJI;
626 				first_code = c & 0x7f;
627 			}
628 			else if (c == SS2)
629 				sp->s_current_stat |= EKANA;
630 			else
631 				addch(sp, c);
632 			break;
633 #endif
634 #ifdef KM_JIS
635 		case KM_JIS:
636 #endif
637 #ifdef KM_ASCII
638 		case KM_ASCII:
639 #endif
640 		default:
641 			addch(sp, c);
642 		}
643 	}
644 
645 set_csr:
646 	cursor_on(&sp->s_csr.csr_p);
647 		/*  altered	*/
648 	return ;
649 }
650 
651 /*
652  *  A printable character is printed in this routine by using
653  *  the routine `_putc()'.
654  *  Anyway, a character is printed in replacement mode or insertion
655  *  mode and if the terminal is autowrap then it takes place wrapping
656  *  and if cursor is bottom margin of the scroll region then it takes
657  *  place scroll up.
658  *  The escape sequence handling is another routine.
659  *
660  */
661 addch(sp, c)
662 	register SCREEN	*sp;
663 	unsigned int c;
664 {
665 	register struct cursor *spc = &(sp->s_csr);
666 	register struct region *spr = &(sp->s_region);
667 
668 	if (spc->csr_x >= rit_m ||
669 		((sp->s_current_stat & JKANJI) && (spc->csr_x >= rit_m - 1))) {
670 		vt_flush(spc);
671 		if (sp->s_term_mode & DECAWM) {
672 			if ((sp->s_current_stat & WRAP) || (spc->csr_x == rit_m
673 					&& sp->s_current_stat & JKANJI)) {
674 				if (spc->csr_y == spr->btm_margin) {
675 					cursor_off();
676 					scroll_up(spr->top_margin,
677 						  spr->btm_margin,
678 						  sp->s_term_mode & DECSCNM,
679 						  sp->s_plane, sp->s_bgcol);
680 					cursor_on(&(spc->csr_p));
681 				} else if (spc->csr_y < btm_m) {
682 					spc->csr_y += 1;
683 					spc->csr_p.y += char_h;
684 				}
685 				spc->csr_x = LFT_M;
686 				spc->csr_p.x = x_ofst;
687 				addch(sp, c);
688 				return;
689 			}
690 			sp->s_current_stat |= WRAP;
691 		}
692 		if (sp->s_current_stat & JKANJI) {
693 			if (spc->csr_x != rit_m) {
694 				_putc(sp, c, 1);
695 			}
696 		} else {
697 			_putc(sp, c, 0);
698 		}
699 		if (spc->csr_x < rit_m) {
700 			spc->csr_x += 1;
701 			spc->csr_p.x += char_w;
702 		}
703 
704 		return ;
705 	}
706 	if (sp->s_current_stat & JKANJI) {
707 		_putc(sp, c, 1);
708 		spc->csr_x++;
709 		spc->csr_p.x += char_w;
710 	} else {
711 		_putc(sp, c, 0);
712 	}
713 
714 	spc->csr_x++;	/*  altered   */
715 	spc->csr_p.x += char_w;
716 
717 	sp->s_current_stat &= ~WRAP;
718 	return ;
719 }
720