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