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