xref: /original-bsd/sys/news3400/bm/vt100esc.c (revision 6a4e3636)
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: vt100esc.c,v 4.300 91/06/09 06:14:59 root Rel41 $ SONY
11  *
12  *	@(#)vt100esc.c	7.6 (Berkeley) 05/30/93
13  */
14 
15 /*
16  *  vt100 escape sequence handler
17  */
18 
19 #ifdef IPC_MRX
20 #include "../../h/param.h"
21 #include "../../h/systm.h"
22 #include "../../iop/framebuf.h"
23 #else
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <news3400/iop/framebuf.h>
27 #endif
28 
29 #include <news3400/bm/vt100.h>
30 #include <news3400/bm/bitmapif.h>
31 
32 #include <news3400/fb/fbdefs.h>
33 
34 #ifdef IPC_MRX
35 #include "../../iop/kbreg.h"
36 #include "../../iop/keyboard.h"
37 #else
38 #include <news3400/iop/kbreg.h>
39 #include <news3400/iop/keyboard.h>
40 #endif
41 
42 #if CPU_SINGLE
43 #include <news3400/sio/scc.h>
44 #endif
45 
46 #ifdef IPC_MRX
47 #include "config.h"
48 #define kbd_ioctl(chan, cmd, argp) { \
49 	if (kb_ioctl) \
50 		(*kb_ioctl)(chan, cmd, argp); \
51 }
52 #endif
53 
54 /*
55  *  escape sequece functions
56  */
57 int	esc_csi();
58 int	esc_csi_ansi();
59 int	esc_csi_dec();
60 int	esc_store_csr();
61 int	esc_restore_csr();
62 int	esc_index();
63 int	esc_next_line();
64 int	esc_tab_set();
65 int	esc_rev_index();
66 int	esc_numeric_kpad();
67 int	esc_application_kpad();
68 int	esc_line_size();
69 int	esc_char_setr();
70 int	esc_char_setl();
71 int	esc_kanji_set();
72 int	esc_parm_set();
73 int	esc_pf_define();
74 int	esc_ignore();
75 
76 struct  esc_sequence esc_seq_table[] = {
77 	{'[', "ABCDfgHhJKLlMmnPr", esc_csi},
78 	{'7', "", esc_store_csr},
79 	{'8', "", esc_restore_csr},
80 	{'D', "", esc_index},
81 	{'E', "", esc_next_line},
82 	{'H', "", esc_tab_set},
83 	{'M', "", esc_rev_index},
84 	{'=', "", esc_application_kpad},
85 	{'>', "", esc_numeric_kpad},
86 	{'#', "34568", esc_line_size},
87 	{'(', "0ABJH", esc_char_setr},
88 	{')', "0AB", esc_char_setl},
89 	{'$', "B@", esc_kanji_set},
90 	{'~', "fcpsomdbDiGCBTtE", esc_parm_set},
91 	{'P', "pPZiI", esc_pf_define},
92 	{'\0', "", esc_ignore},
93 };
94 
95 struct	key_pad	key_pad[] = {
96 	{ '0', 'p' },	/*	0	*/
97 	{ '1', 'q' },	/*	1	*/
98 	{ '2', 'r' },	/*	2	*/
99 	{ '3', 's' },	/*	3	*/
100 	{ '4', 't' },	/*	4	*/
101 	{ '5', 'u' },	/*	5	*/
102 	{ '6', 'v' },	/*	6	*/
103 	{ '7', 'w' },	/*	7	*/
104 	{ '8', 'x' },	/*	8	*/
105 	{ '9', 'y' },	/*	9	*/
106 	{ '.', 'n' },	/*  period	*/
107 	{ '-', 'm' },	/*  minus	*/
108 	{ '+', 'k' },	/*  plus	*/
109 	{ ',', 'l' },	/*  comma	*/
110 	{ '\n', 'M' },	/*  enter	*/
111 	{ 'A', 'A' },	/*  cursor up	*/
112 	{ 'B', 'B' },	/*  cursor down	*/
113 	{ 'C', 'C' },	/*  cursor right */
114 	{ 'D', 'D' },	/*  cursor left	*/
115 	{ '\0', '\0' }	/*	*/
116 };
117 
118 static	char	esc_buf[ESC_BUF_SIZ];
119 static	char	*esc_bp = esc_buf;
120 extern	char	c_pos_mess[];
121 
122 static change_csr_key_pad(), change_aux_key_pad(), itoa();
123 
124 Key_string	key_str;
125 Pfk_string	pfk_str;
126 
127 unsigned  int	first_jcode;
128 
129 /*
130  *  put out jis-code kanji
131  */
132 jiskanji(sp, c)
133 	register SCREEN *sp;
134 	register unsigned int c;
135 {
136 	if (first_jcode) {
137 		addch(sp, c | (first_jcode << 8));
138 		first_jcode = 0;
139 	} else {
140 		first_jcode = c;
141 	}
142 }
143 
144 /*
145  *  This routine is the command analiser using second character.
146  *  If a command has found then switch to particular escape handling
147  *  routine, and directly called by mother routine.
148  *  The arguments are passed through the routine.
149  */
150 esc_top_level(sp, c)
151 	register SCREEN	*sp;
152 	char c;
153 {
154 	register  struct  esc_sequence	*estp;
155 
156 	for (estp = esc_seq_table; estp->command ; estp++) {
157 		if (estp->command == c) {
158 					/* command found  */
159 			sp->s_estp = estp;
160 			if (*estp->terminators == '\0') {
161 				(*estp->esc_func)(sp);
162 				sp->s_current_stat &= ~ESCAPE;
163 			} else {
164 				sp->s_esc_handler = estp->esc_func;
165 			}
166 			return;
167 		}
168 	}
169 	sp->s_current_stat &= ~ESCAPE;
170 }
171 
172 /*
173  *  Undo the ESCAPE flag, escape buffer
174  *  and the esc_handler routine
175  *  This routine has to be called when escape sequence has started.
176  */
177 recover(sp)
178 	register SCREEN *sp;
179 {
180 	register int *ip = (int *) esc_buf;
181 	register int *sup = (int *) (esc_buf + ESC_BUF_SIZ);
182 
183 	sp->s_current_stat &= ~ESCAPE;
184 	sp->s_esc_handler = esc_top_level;
185 	while (ip < sup)
186 		*ip++ = 0;
187 	esc_bp = esc_buf;
188 }
189 
190 /*
191  *  This routine in_str(c, string) returns
192  *  if string contains c then TRUE (1) else FALSE (0)
193  */
194 in_str(c, string)
195 	char c;
196 	register char *string;
197 {
198 	while(*string)
199 		if (c == *string++)
200 			return(TRUE);
201 	return(FALSE);
202 }
203 
204 /*
205  *  Control sequence introducer (CSI)
206  *  Which begins `^[[' and terminates one of `ABCDfgHhJKLlMmPr'
207  */
208 esc_csi(sp, c)
209 	register SCREEN *sp;
210 	unsigned int c;
211 {
212 	static int bufc = 0;
213 
214 	if (in_str(c, sp->s_estp->terminators)) {
215 		esc_csi_ansi(sp, esc_bp, c);
216 		sp->s_current_stat &= ~ESCAPE;
217 		bufc = 0;
218 		return;
219 	}
220 	/*  buffering arguments  */
221 	if (bufc < ESC_BUF_SIZ) {
222 		if (c >= '0' && c <= '9') {
223 			*esc_bp = *esc_bp *10 + (c - '0');
224 		} else if (c == ';') {
225 			esc_bp++;
226 			bufc++;
227 		} else if (c == '?') {
228 			if (esc_bp == esc_buf) {
229 				sp->s_esc_handler = esc_csi_dec;
230 			} else {
231 				esc_buf[0] = INVALID;
232 			}
233 		} else {
234 			sp->s_current_stat &= ~ESCAPE;
235 			bufc = 0;
236 		}
237 	}
238 }
239 
240 #ifdef IPC_MRX
241 #define SCC_KEYBOARD	0
242 #endif
243 
244 /*
245  *  Ansi standard csi handler
246  */
247 esc_csi_ansi(sp, esc_bp, terminator)
248 	register SCREEN *sp;
249 	char *esc_bp;
250 	char terminator;
251 {
252 	register char *cp = esc_buf;
253 	register struct cursor *spc = &sp->s_csr;
254 	register char *p;
255 	register int i;
256 
257 	if (*cp == INVALID)
258 		return;
259 
260 	cursor_off();
261 	switch (terminator) {
262 	case 'A':		/*  CUU	 */
263 		if (spc->csr_y < sp->s_region.top_margin) {
264 			spc->csr_y = max(spc->csr_y - max(*cp, 1)
265 					,TOP_M);
266 		} else {
267 			spc->csr_y = max(spc->csr_y - max(*cp, 1)
268 					,sp->s_region.top_margin);
269 		}
270 		spc->csr_p.y = (spc->csr_y - 1) * char_h + y_ofst;
271 		sp->s_current_stat &= ~WRAP;
272 		break;
273 	case 'B':		/*  CUD	 */
274 		if (spc->csr_y > sp->s_region.btm_margin) {
275 			spc->csr_y = min(spc->csr_y + max(*cp, 1)
276 					,btm_m);
277 		} else {
278 			spc->csr_y = min(spc->csr_y + max(*cp, 1)
279 					,sp->s_region.btm_margin);
280 		}
281 		spc->csr_p.y = (spc->csr_y - 1) * char_h + y_ofst;
282 		sp->s_current_stat &= ~WRAP;
283 		break;
284 	case 'C':		/*  CUF	 */
285 		spc->csr_x = min(spc->csr_x + max(*cp, 1), rit_m);
286 		spc->csr_p.x = (spc->csr_x - 1) * char_w + x_ofst;
287 		sp->s_current_stat &= ~WRAP;
288 		break;
289 	case 'D':		/*  CUB	 */
290 		spc->csr_x = max(spc->csr_x - max(*cp, 1), LFT_M);
291 		spc->csr_p.x = (spc->csr_x - 1) * char_w + x_ofst;
292 		sp->s_current_stat &= ~WRAP;
293 		break;
294 	case 'g':		/*  TBC	 */
295 		switch (*cp) {
296 		case 0:
297 			sp->s_tab_pos[spc->csr_x] = 0;
298 			break;
299 		case 3:
300 			for (i = 0; i <= rit_m; i++)
301 				sp->s_tab_pos[i] = 0;
302 			break;
303 		default:
304 			break;
305 		}
306 		break;
307 	case 'f':		/*  HVP	 */
308 	case 'H':		/*  CUP  same as HVP	*/
309 		csr_pos(sp, cp[1], cp[0]);
310 		sp->s_current_stat &= ~WRAP;
311 		break;
312 	case 'J':		/*  ED	*/
313 		erase_disp(sp, cp[0]);
314 		sp->s_current_stat &= ~WRAP;
315 		break;
316 	case 'K':		/*  EL	*/
317 		erase_line(sp, cp[0]);
318 		sp->s_current_stat &= ~WRAP;
319 		break;
320 	case 'L':		/*  IL	*/
321 		insert_line(sp, cp[0]);
322 		break;
323 	case 'M':		/*  DL	*/
324 		delete_line(sp, cp[0]);
325 		break;
326 	case 'P':		/*  DCH	 */
327 		delete_char(sp, cp[0]);
328 		sp->s_current_stat &= ~WRAP;
329 		break;
330 	case 'r':		/*  DECSTBM	*/
331 		cp[2] = max(cp[0] == 0 ? TOP_M: cp[0], TOP_M);
332 		cp[3] = min(cp[1] == 0 ? btm_m: cp[1], btm_m);
333 		if (cp[2] >= cp[3])
334 			break;
335 
336 		sp->s_region.top_margin = cp[2];
337 		sp->s_region.btm_margin = cp[3];
338 
339 		spc->csr_x = LFT_M;
340 		spc->csr_p.x = x_ofst;
341 		if (sp->s_term_mode & DECOM) {
342 			spc->csr_y = sp->s_region.top_margin;
343 			spc->csr_p.y = (spc->csr_y - 1) * char_h + y_ofst;
344 		} else {
345 			spc->csr_y = TOP_M;
346 			spc->csr_p.y = y_ofst;
347 		}
348 		break;
349 	case 'm':		/*  CRA	 */
350 		while (cp <= esc_bp) {
351 			switch (*cp++) {
352 			case 0:
353 				spc->csr_attributes &= NORMALM;
354 				if (sp->s_term_mode & DECSCNM) {
355 					fcolor = sp->s_bgcol;
356 					bcolor = sp->s_plane;
357 				}
358 				else {
359 					fcolor = sp->s_plane;
360 					bcolor = sp->s_bgcol;
361 				}
362 				break;
363 			case 1:		/*  bold	*/
364 				spc->csr_attributes |= BOLD;
365 				break;
366 			case 4:		/*  under score	 */
367 				spc->csr_attributes |= USCORE;
368 				break;
369 			case 5:		/*  blinking	*/
370 				spc->csr_attributes |= BLINK;
371 				break;
372 			case 7:		/*  reverse	*/
373 				spc->csr_attributes |= REVERSE;
374 				if (sp->s_term_mode & DECSCNM) {
375 					fcolor = sp->s_plane;
376 					bcolor = sp->s_bgcol;
377 				}
378 				else {
379 					fcolor = sp->s_bgcol;
380 					bcolor = sp->s_plane;
381 				}
382 				break;
383 			case 22:	/*  unbold	*/
384 				spc->csr_attributes &= ~BOLD;
385 				break;
386 			case 24:	/*  no under score	*/
387 				spc->csr_attributes &= ~USCORE;
388 				break;
389 			case 25:	/*  no blinking	 */
390 				spc->csr_attributes &= ~BLINK;
391 				break;
392 			case 27:	/*  re-reverse	*/
393 				spc->csr_attributes &= ~REVERSE;
394 				if (sp->s_term_mode & DECSCNM) {
395 					fcolor = sp->s_bgcol;
396 					bcolor = sp->s_plane;
397 				}
398 				else {
399 					fcolor = sp->s_plane;
400 					bcolor = sp->s_bgcol;
401 				}
402 				break;
403 			default:
404 				break;
405 			}
406 		}
407 		break;
408 	case 'n':
409 		while (cp <= esc_bp) {	/*  DSR(status request)	*/
410 			switch (*cp++) {
411 			case 6:		/*  inquiry cursor position	*/
412 				key_str.key_string = c_pos_mess;
413 				key_str.key_length = spr(c_pos_mess,
414 				    "\033[%d;%dR", (sp->s_term_mode & DECOM) ?
415 				    spc->csr_y - sp->s_region.top_margin + 1:
416 				    spc->csr_y, spc->csr_x);
417 				kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
418 				break;
419 			default:
420 				break;
421 			}
422 		}
423 		break;
424 	case 'h':		/*  SM	*/
425 		while (cp <= esc_bp) {
426 			switch (*cp++) {
427 			case 2:		/*  Keyboard Action	*/
428 				sp->s_term_mode |= KAM;
429 				break;
430 			case 4:		/*  Insert Replace	*/
431 				sp->s_term_mode |= IRM;
432 				break;
433 			case 12:	/*  Local echo disable	*/
434 				sp->s_term_mode |= SRM;
435 				break;
436 			case 20:	/*  Linefeed newline	*/
437 				sp->s_term_mode |= LNM;
438 				break;
439 			default:
440 				break;
441 			}
442 		}
443 		break;
444 	case 'l':		/*  RM	*/
445 		while (cp <= esc_bp) {
446 			switch (*cp++) {
447 			case 2:		/*  Keyboard Action	*/
448 				sp->s_term_mode &= ~KAM;
449 				break;
450 			case 4:		/*  Insert Replace	*/
451 				sp->s_term_mode &= ~IRM;
452 				break;
453 			case 12:	/*  Local echo disable	*/
454 				sp->s_term_mode &= ~SRM;
455 				break;
456 			case 20:	/*  Linefeed newline	*/
457 				sp->s_term_mode &= ~LNM;
458 				break;
459 			default:
460 				break;
461 			}
462 		}
463 		break;
464 	default:
465 		break;
466 	}
467 	cursor_on(&spc->csr_p);
468 	sp->s_current_stat &= ~ESCAPE;
469 }
470 
471 
472 /*
473  *  Cursor position.
474  *  csr_pos(sp, x, y) moves the cursor to (x, y).
475  */
476 csr_pos(sp, x, y)
477 	register SCREEN *sp;
478 	register int x, y;
479 {
480 	if (sp->s_term_mode & DECOM) {
481 		sp->s_csr.csr_y = min(sp->s_region.top_margin +
482 				max(y, 1) - 1, sp->s_region.btm_margin);
483 	} else {
484 		sp->s_csr.csr_y = min(TOP_M + max(y, 1) - 1, btm_m);
485 	}
486 	sp->s_csr.csr_x = max(min(x, rit_m), LFT_M);
487 	sp->s_csr.csr_p.x = (sp->s_csr.csr_x -1) * char_w + x_ofst;
488 	sp->s_csr.csr_p.y = (sp->s_csr.csr_y -1) * char_h + y_ofst;
489 }
490 
491 
492 /*
493  *  Erase in display.
494  *  erase_disp(sp, pn) erases display from the cursor to the end, from
495  *  the beginning to the cursor or completely according to pn = 0, 1 or 2
496  *  respectively.
497  */
498 erase_disp(sp, pn)
499 	register SCREEN *sp;
500 	register int pn;
501 {
502 	register  struct  cursor  *spc = &sp->s_csr;
503 
504 	switch (pn) {
505 	case 0:		/*  cursor to end	*/
506 		erase_line(sp, 0);
507 		clear_lines(min(spc->csr_y + 1, btm_m),
508 			btm_m - spc->csr_y, sp->s_term_mode & DECSCNM,
509 			sp->s_plane, sp->s_bgcol);
510 		break;
511 	case 1:		/*  beginning to cursor	*/
512 		erase_line(sp, 1);
513 		clear_lines(TOP_M, spc->csr_y - TOP_M, sp->s_term_mode & DECSCNM,
514 			sp->s_plane, sp->s_bgcol);
515 		break;
516 	case 2:		/*  whole	*/
517 		clear_lines(TOP_M, btm_m - TOP_M + 1,
518 			sp->s_term_mode & DECSCNM,
519 			sp->s_plane, sp->s_bgcol);
520 		break;
521 	default:
522 		break;
523 	}
524 }
525 
526 
527 
528 /*
529  *  Erase in line.
530  *  erase_line(sp, pn) erases line from the cursor to the end, from the
531  *  beginning to the cursor or completely according to pn = 0, 1 or 2
532  *  respectively.
533  */
534 erase_line(sp, pn)
535 	register SCREEN *sp;
536 	register int pn;
537 {
538 	register struct cursor *spc = &sp->s_csr;
539 
540 	switch(pn) {
541 	case 0:
542 		clear_chars(spc->csr_x, spc->csr_y,
543 			rit_m - spc->csr_x + 1, sp->s_term_mode & DECSCNM,
544 			sp->s_plane, sp->s_bgcol);
545 		break;
546 	case 1:
547 		clear_chars(LFT_M, spc->csr_y,
548 			spc->csr_x - LFT_M + 1, sp->s_term_mode & DECSCNM,
549 			sp->s_plane, sp->s_bgcol);
550 		break;
551 	case 2:
552 		clear_lines(spc->csr_y, 1, sp->s_term_mode & DECSCNM,
553 			sp->s_plane, sp->s_bgcol);
554 		break;
555 	default:
556 		break;
557 	}
558 }
559 
560 /*
561  *  Insert line.
562  *  insert_line(sp, pn) inserts pn lines in scroll region
563  */
564 insert_line(sp, pn)
565 	register SCREEN *sp;
566 	register int pn;
567 {
568 	register struct cursor *spc = &sp->s_csr;
569 	register struct region *spr = &sp->s_region;
570 
571 	pn = max(pn, 1);
572 	if (spc->csr_y < spr->top_margin || spc->csr_y > spr->btm_margin)
573 		return;
574 	if (pn <= spr->btm_margin - spc->csr_y) {
575 		move_lines(spc->csr_y, spr->btm_margin - pn - spc->csr_y + 1,
576 			spc->csr_y + pn);
577 	}
578 	clear_lines(spc->csr_y,
579 		min(spc->csr_y + pn - 1, spr->btm_margin) - spc->csr_y + 1,
580 		sp->s_term_mode & DECSCNM, sp->s_plane, sp->s_bgcol);
581 	spc->csr_x = LFT_M;
582 	spc->csr_p.x = x_ofst;
583 }
584 
585 /*
586  *  Delete line.
587  *  delete_line(sp, pn) deletes pn lines in scroll region
588  */
589 delete_line(sp, pn)
590 	register SCREEN *sp;
591 	register int pn;
592 {
593 	register struct cursor *spc = &sp->s_csr;
594 	register struct region *spr = &sp->s_region;
595 	register int aux;
596 
597 	pn = max(pn, 1);
598 	if (spc->csr_y < spr->top_margin || spc->csr_y > spr->btm_margin)
599 		return;
600 	if (pn <= spr->btm_margin - spc->csr_y) {
601 		aux = spc->csr_y + pn;
602 		move_lines(aux, spr->btm_margin - aux + 1, spc->csr_y);
603 	}
604 	aux = max(spr->btm_margin - pn + 1, spc->csr_y);
605 	clear_lines(aux, spr->btm_margin - aux + 1, sp->s_term_mode & DECSCNM,
606 		sp->s_plane, sp->s_bgcol);
607 	spc->csr_x = LFT_M;
608 	spc->csr_p.x = x_ofst;
609 }
610 
611 /*
612  *  Delete character.
613  *  delete_char(sp, pn) deletes pn characters right side of the cursor.
614  */
615 delete_char(sp, pn)
616 	register SCREEN *sp;
617 	register int pn;
618 {
619 	register struct cursor *spc = &sp->s_csr;
620 	register int aux;
621 
622 	pn = max(pn, 1);
623 	if (pn < rit_m - spc->csr_x + 1) {
624 		move_chars(spc->csr_x + pn, spc->csr_y,
625 			rit_m - spc->csr_x - pn + 1 ,spc->csr_x);
626 	}
627 	aux = max(rit_m - pn + 1, spc->csr_x);
628 	clear_chars(aux, spc->csr_y, rit_m - aux + 1,
629 		sp->s_term_mode & DECSCNM, sp->s_plane, sp->s_bgcol);
630 }
631 
632 /*
633  *  This escape control sequence begins `^[[?' and ends `h' or `l'
634  */
635 esc_csi_dec(sp, c)
636 	register SCREEN *sp;
637 	char c;
638 {
639 	register char *cp;
640 
641 	if (in_str(c, sp->s_estp->terminators)) {
642 		if (esc_buf[0] != INVALID) {
643 			cursor_off();
644 			switch (c) {
645 			case 'h':	/*  set mode	*/
646 			for (cp = esc_buf; cp <= esc_bp; cp++) {
647 				switch (*cp) {
648 				case 1:		/*  cursor key application  */
649 					sp->s_term_mode |= DECCKM;
650 					change_csr_key_pad(APPLIC);
651 					break;
652 				case 3:		/*  132 column mode	*/
653 					sp->s_term_mode |= DECCOLM;
654 					break;
655 				case 4:		/*  jump scroll	*/
656 					sp->s_term_mode |= DECSCLM;
657 					break;
658 				case 5:		/*  reverse	*/
659 					if ((sp->s_term_mode & DECSCNM) == 0)
660 						reverse_rec(sp->s_bgcol,
661 							sp->s_plane);
662 					sp->s_term_mode |= DECSCNM;
663 					if (sp->s_csr.csr_attributes & REVERSE)
664 					{
665 						fcolor = sp->s_plane;
666 						bcolor = sp->s_bgcol;
667 					} else {
668 						fcolor = sp->s_bgcol;
669 						bcolor = sp->s_plane;
670 					}
671 					break;
672 				case 6:		/*  origin	*/
673 					sp->s_term_mode |= DECOM;
674 					sp->s_csr.csr_x = LFT_M;
675 					sp->s_csr.csr_y =
676 						sp->s_region.top_margin;
677 					sp->s_csr.csr_p.x = x_ofst;
678 					sp->s_csr.csr_p.y =
679 					   (sp->s_csr.csr_y - 1) * char_h +
680 						y_ofst;
681 					break;
682 				case 7:		/*  auto wrap	*/
683 					sp->s_term_mode |= DECAWM;
684 					break;
685 				case 8:		/*  auto repeat	 */
686 					if ((sp->s_term_mode & DECARM) == 0) {
687 						kbd_ioctl(SCC_KEYBOARD, KIOCREPT,
688 							  (int *)0);
689 					}
690 					sp->s_term_mode |= DECARM;
691 					break;
692 				case 25:	/* cursor active */
693 					sp->s_term_mode |= DECCSR_ACTV;
694 					break;
695 				default:
696 					break;
697 				}
698 			}
699 			break;
700 			case 'l':	/*  reset mode	*/
701 			for (cp = esc_buf; cp <= esc_bp; cp++) {
702 				switch (*cp) {
703 				case 1:		/*  cursor key application  */
704 					sp->s_term_mode &= ~DECCKM;
705 					change_csr_key_pad(NUMERIC);
706 					break;
707 				case 3:		/*  132 column mode	*/
708 					sp->s_term_mode &= ~DECCOLM;
709 					break;
710 				case 4:		/*  jump scroll	*/
711 					sp->s_term_mode &= ~DECSCLM;
712 					break;
713 				case 5:		/*  reverse	*/
714 					if (sp->s_term_mode & DECSCNM)
715 						reverse_rec(sp->s_plane,
716 							sp->s_bgcol);
717 					sp->s_term_mode &= ~DECSCNM;
718 					if (sp->s_csr.csr_attributes & REVERSE)
719 					{
720 						fcolor = sp->s_bgcol;
721 						bcolor = sp->s_plane;
722 					} else {
723 						fcolor = sp->s_plane;
724 						bcolor = sp->s_bgcol;
725 					}
726 					break;
727 				case 6:		/*  origin	*/
728 					sp->s_term_mode &= ~DECOM;
729 					sp->s_csr.csr_x = LFT_M;
730 					sp->s_csr.csr_y = TOP_M;
731 					sp->s_csr.csr_p.x = x_ofst;
732 					sp->s_csr.csr_p.y = y_ofst;
733 					break;
734 				case 7:		/*  auto wrap	*/
735 					sp->s_term_mode &= ~DECAWM;
736 					break;
737 				case 8:		/*  auto repeat	 */
738 					if (sp->s_term_mode & DECARM) {
739 						kbd_ioctl(SCC_KEYBOARD, KIOCNRPT,
740 							(int *) 0);
741 					}
742 					sp->s_term_mode &= ~DECARM;
743 					break;
744 				case 25:	/* cursor non-active */
745 					sp->s_term_mode &= ~DECCSR_ACTV;
746 					break;
747 				default:
748 					break;
749 				}
750 			}
751 			break;
752 			default:
753 				break;
754 			}
755 			cursor_on(&sp->s_csr.csr_p);
756 		}
757 		sp->s_current_stat &= ~ESCAPE;
758 	} else {	/*  buffering  arguments	*/
759 		if (c >= '0' && c <= '9') {
760 			*esc_bp = *esc_bp * 10 + (c - '0');
761 		} else if (c == ';') {
762 			esc_bp++;
763 		} else if (c == '?') {
764 			esc_buf[0] = INVALID;
765 		} else {
766 			sp->s_current_stat &= ~ESCAPE;
767 		}
768 	}
769 }
770 
771 /*
772  *  changes cursor key pad to ansi_ctl
773  */
774 static
775 change_csr_key_pad(applic)
776 	register int applic;
777 {
778 	char pad[4];
779 	register Pfk_string *pfk = &pfk_str;
780 	register Key_string *kys = &pfk_str.pfk_string;
781 	register struct key_pad  *kpd;
782 	register int i;
783 
784 	kpd = &key_pad[UP-N0];
785 	pad[0] = '\033';
786 	pad[1] = (applic) ? 'O': '[';
787 	for (i = UP; i <= LEFT; i++) {
788 		pfk->pfk_num = i;
789 		kys->key_length = (applic) ? 3: 3;
790 		pad[2] = (applic) ? kpd->kpd_applic: kpd->kpd_numeric;
791 		kys->key_string = pad;
792 		kpd++;
793 		pfk->pfk_shift = PF_NORMAL;
794 		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
795 		pfk->pfk_shift = PF_SHIFT;
796 		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
797 	}
798 }
799 
800 extern struct cursor inner_buf_csr;
801 extern int inner_buf_tstat;
802 /*
803  *  Store cursor position and attributes.
804  *  The SCREEN structure is stored inner structure.
805  */
806 esc_store_csr(sp)
807 	register SCREEN *sp;
808 {
809 	inner_buf_csr = sp->s_csr;
810 	inner_buf_tstat = (DECOM|DECAWM) & sp->s_term_mode;
811 }
812 
813 /*
814  *  Restore cursor position and attributes.
815  *  The SCREEN structure  is restored from inner structure.
816  *  Prevail error from unexpected use of this command, inner structure
817  *  must be initialized.
818  */
819 esc_restore_csr(sp)
820 	register SCREEN *sp;
821 {
822 	cursor_off();
823 	sp->s_csr = inner_buf_csr;
824 	sp->s_term_mode = (sp->s_term_mode & ~(DECOM|DECAWM)) | inner_buf_tstat;
825 	cursor_on(&sp->s_csr.csr_p);
826 }
827 
828 /*
829  *  index()
830  *  esc_index(sp) moves the cursor down if the cursor is not at
831  *  bottom margin. If the cursor is at the bottom margin then
832  *  scroll up.
833  */
834 esc_index(sp)
835 	register SCREEN *sp;
836 {
837 	cursor_off();
838 	if (sp->s_csr.csr_y == sp->s_region.btm_margin)
839 		scroll_up(sp->s_region.top_margin,
840 			sp->s_region.btm_margin, sp->s_term_mode & DECSCNM,
841 			sp->s_plane, sp->s_bgcol);
842 	else {
843 		if (sp->s_csr.csr_y < btm_m) {
844 			sp->s_csr.csr_y += 1;
845 			sp->s_csr.csr_p.y += char_h;
846 		}
847 	}
848 	sp->s_current_stat &= ~WRAP;
849 	cursor_on(&sp->s_csr.csr_p);
850 }
851 
852 /*
853  *  next line
854  *  esc_next_line(sp) moves the cursor down like index but the cursor
855  *  position is the beginning of the next line.
856  */
857 esc_next_line(sp)
858 	register SCREEN *sp;
859 {
860 	sp->s_csr.csr_x = LFT_M;
861 	sp->s_csr.csr_p.x = x_ofst;
862 	esc_index(sp);
863 }
864 
865 /*
866  *  tabulation set
867  *  esc_tab_set(sp) sets tabulation stop at the current cursor point.
868  */
869 esc_tab_set(sp)
870 	register SCREEN *sp;
871 {
872 	sp->s_tab_pos[sp->s_csr.csr_x] = 1;
873 }
874 
875 /*
876  *  reverse index
877  *  esc_rev_index(sp) moves the cursor up if the cursor is not at the top
878  *  margin. If the cursor is at the top margin then the screen takes place
879  *  scroll down.
880  */
881 esc_rev_index(sp)
882 	register SCREEN *sp;
883 {
884 	cursor_off();
885 	if (sp->s_csr.csr_y == sp->s_region.top_margin)
886 		scroll_down(sp->s_region.top_margin,
887 			sp->s_region.btm_margin, sp->s_term_mode & DECSCNM,
888 			sp->s_plane, sp->s_bgcol);
889 	else {
890 		if (sp->s_csr.csr_y > TOP_M) {
891 			sp->s_csr.csr_y -= 1;
892 			sp->s_csr.csr_p.y -= char_h;
893 		}
894 	}
895 	sp->s_current_stat &= ~WRAP;
896 	cursor_on(&sp->s_csr.csr_p);
897 }
898 
899 /*
900  *  numeric key pad
901  *  esc_numeric_kpad(sp) changes key pad of cursor to numeric one.
902  *  This sequence is used in vi.
903  *  currently not supported
904  */
905 esc_numeric_kpad(sp)
906 	register SCREEN *sp;
907 {
908 	change_aux_key_pad(NUMERIC);
909 	sp->s_current_stat &= ~ESCAPE;
910 }
911 
912 /*
913  *  application key pad
914  *  esc_application_kpad(sp) changes key pad of cursor to application one.
915  *  This sequence is also used in vi.
916  *  currently not supported.
917  */
918 esc_application_kpad(sp)
919 	register SCREEN *sp;
920 {
921 	change_aux_key_pad(APPLIC);
922 	sp->s_current_stat &= ~ESCAPE;
923 }
924 
925 /*
926  *  change auxiliary keypad
927  */
928 static
929 change_aux_key_pad(applic)
930 	register int applic;
931 {
932 	char pad[4];
933 	register Pfk_string *pfk = &pfk_str;
934 	register Key_string *kys = &pfk_str.pfk_string;
935 	register struct key_pad *kpd;
936 	register int i;
937 
938 	kpd = &key_pad[0];
939 	if (applic) {
940 		pad[0] = '\033';
941 		pad[1] = 'O';
942 	}
943 	for (i = N0; i <= NENTER; i++) {
944 
945 		pfk->pfk_num = i;
946 		kys->key_length = (applic) ? 3: 1;
947 		if (applic) {
948 			pad[2] = kpd->kpd_applic;
949 		} else {
950 			pad[0] = kpd->kpd_numeric;
951 		}
952 		kys->key_string = pad;
953 		kpd++;
954 		pfk->pfk_shift = PF_NORMAL;
955 		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
956 		pfk->pfk_shift = PF_SHIFT;
957 		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
958 	}
959 	if (!applic) {
960 		pfk->pfk_shift = PF_SHIFT;
961 		kys->key_length = 1;
962 
963 		pfk->pfk_num = MINUS;
964 		kys->key_string = "/";
965 		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
966 
967 		pfk->pfk_num = PLUS;
968 		kys->key_string = "*";
969 		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
970 
971 		pfk->pfk_num = COMMA;
972 		kys->key_string = "=";
973  		kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
974 	}
975 }
976 
977 extern	struct	csr_buf	local_csr_buf;
978 /*
979  *  change line size
980  *  esc_line_size(sp, pn) changes line size.
981  *	c = `3'	double side double height(top half)
982  *	c = `4'	double side double height(bottom half)
983  *	c = `5'	sigle width line
984  *	c = `6'	double width line
985  *  currently not supported
986  */
987 esc_line_size(sp, c)
988 	register SCREEN *sp;
989 	char c;
990 {
991 	register int i;
992 	register int j;
993 	int save_f, save_b;
994 
995 	cursor_off();
996 	switch (c) {
997 	case '5':
998 		local_csr_buf.csr_number = 1;
999 		break;
1000 	case '6':
1001 		local_csr_buf.csr_number = 2;
1002 		break;
1003 	case '8':
1004 		sp->s_region.top_margin = TOP_M;
1005 		sp->s_region.btm_margin = btm_m;
1006 		save_f = fcolor;
1007 		save_b = bcolor;
1008 		fcolor = sp->s_bgcol;
1009 		bcolor = sp->s_plane;
1010 		sp->s_csr.csr_p.y = y_ofst;
1011 		for (i = TOP_M; i <= btm_m; i++) {
1012 			sp->s_csr.csr_p.x = x_ofst;
1013 			sp->s_csr.csr_y = i;
1014 			for (j = LFT_M; j <= rit_m; j++) {
1015 				sp->s_csr.csr_x = j;
1016 				copy_char(sp, 'E', 0);
1017 				sp->s_csr.csr_p.x += char_w;
1018 			}
1019 			sp->s_csr.csr_p.y += char_h;
1020 		}
1021 		sp->s_csr.csr_x = LFT_M;
1022 		sp->s_csr.csr_y = TOP_M;
1023 		sp->s_csr.csr_p.x = x_ofst;
1024 		sp->s_csr.csr_p.y = y_ofst;
1025 		fcolor = save_f;
1026 		bcolor = save_b;
1027 		break;
1028 	default:
1029 		break;
1030 	}
1031 	cursor_on(&sp->s_csr.csr_p);
1032 	sp->s_current_stat &= ~ESCAPE;
1033 }
1034 
1035 /*
1036  *  character set
1037  *  esc_char_setr sets which character set you use in right graphic set.
1038  *  currently not supported
1039  */
1040 esc_char_setr(sp, c)
1041 	register SCREEN *sp;
1042 	int c;
1043 {
1044 #if defined(IPC_MRX) || defined(CPU_SINGLE)
1045 	switch (c) {
1046 	case 'J':
1047 	case 'H':
1048 		font_jisroman();
1049 #ifdef CPU_SINGLE
1050 		font_jisroman24();
1051 #endif
1052 		sp->s_current_stat &= ~JKANJI;
1053 		break;
1054 	case 'B':
1055 		font_ascii();
1056 #ifdef CPU_SINGLE
1057 		font_ascii24();
1058 #endif
1059 		sp->s_current_stat &= ~JKANJI;
1060 		break;
1061 	}
1062 #else /* IPC_MRX || CPU_SINGLE */
1063 	if (c == 'B' || c == 'J' || c == 'H') {
1064 		sp->s_current_stat &= ~JKANJI;
1065 	}
1066 #endif /* IPC_MRX || CPU_SINGLE */
1067 	sp->s_current_stat &= ~ESCAPE;
1068 }
1069 
1070 /*
1071  *  character set to left graphic set
1072  *  esc_char_setl sets which character set you use in left graphic set.
1073  *  currently not supported
1074  */
1075 esc_char_setl(sp, c)
1076 	register SCREEN *sp;
1077 	int c;
1078 {
1079 	sp->s_current_stat &= ~ESCAPE;
1080 }
1081 
1082 extern tmode;
1083 extern  unsigned  int	first_jcode;
1084 /*
1085  *  character set to kanji
1086  *  esc_kanji_set sets kanji
1087  */
1088 esc_kanji_set(sp, c)
1089 	register SCREEN *sp;
1090 	int c;
1091 {
1092 
1093 #ifdef KM_JIS
1094 	if (tmode == KM_JIS && (c == 'B' || c == '@')) {
1095 		sp->s_current_stat |= JKANJI;
1096 		first_jcode = 0;
1097 	}
1098 #endif
1099 	sp->s_current_stat &= ~ESCAPE;
1100 }
1101 
1102 static short parm_buf[PARM_BUF_SIZ];
1103 static short *parm_bp = parm_buf;
1104 static int sensitive = 0;
1105 static int pval = 0;
1106 /*
1107  *  terminal parameter set command
1108  *  esc_parm_set(sp, c)  sets terminal parameters such as font-width,
1109  *  font-height, character-width, character-height, character-position,
1110  *  underlind-position, screen-width, screen-height, x-offset, y-offset,
1111  *  right-mergin, bottom-mergin, dimmer-count, bell-length.
1112  */
1113 esc_parm_set(sp, c)
1114 	register SCREEN *sp;
1115 	register unsigned int c;
1116 {
1117 	static int bufc = 0;
1118 
1119 	if (in_str(c, sp->s_estp->terminators)) {
1120 		if (sensitive) {
1121 			*parm_bp++ = pval;
1122 		} else {
1123 			*parm_bp++ = -1;
1124 		}
1125 		*parm_bp++ = -1;
1126 		parm_set(sp, parm_buf, c);
1127 		sp->s_current_stat &= ~ESCAPE;
1128 		sensitive = pval = 0;
1129 		parm_bp = parm_buf;
1130 		bufc = 0;
1131 		return;
1132 	}
1133 	/*  buffering arguments  */
1134 	if (bufc < PARM_BUF_SIZ) {
1135 		if (c >= '0' && c <= '9') {
1136 			pval = pval *10 + (c - '0');
1137 			sensitive = 1;
1138 		} else if (c == ';') {
1139 			if (sensitive) {
1140 				*parm_bp++ = pval;
1141 			} else {
1142 				*parm_bp++ = -1;
1143 			}
1144 			sensitive = pval = 0;
1145 			bufc++;
1146 		} else {
1147 			sp->s_current_stat &= ~ESCAPE;
1148 			sensitive = pval = 0;
1149 			parm_bp = parm_buf;
1150 			bufc = 0;
1151 		}
1152 	}
1153 }
1154 
1155 static	char	an_buf[AN_BUF_SIZ];
1156 
1157 parm_set(sp, parm, terminator)
1158 	SCREEN *sp;
1159 	short *parm;
1160 	unsigned int terminator;
1161 {
1162 	register char *bp = an_buf;
1163 	register char *p;
1164 
1165 	switch (terminator) {
1166 	case 'f':
1167 		if (parm[0] >= FONT_W_MIN && parm[0] <= consfb->font_w &&
1168 							parm[0] < char_w)
1169 			font_w =  parm[0];
1170 
1171 		if (parm[1] >= FONT_H_MIN && parm[1] <= consfb->font_h &&
1172 					parm[1] <= (char_h - ch_pos))
1173 			font_h = parm[1];
1174 		break;
1175 	case 'c':
1176 		if (parm[0] >= CHAR_W_MIN && parm[0] > font_w &&
1177 						parm[0] <= CHAR_W_MAX)
1178 			char_w = parm[0];
1179 
1180 		if (parm[1] >= CHAR_H_MIN && parm[1] >= (font_h + ch_pos) &&
1181 				parm[1] > ul_pos && parm[1] <= CHAR_H_MAX)
1182 			char_h = parm[1];
1183 
1184 		break;
1185 	case 'p':
1186 		if (parm[0] >= UL_POS_MIN && parm[0] <= UL_POS_MAX &&
1187 						parm[0] < char_h) {
1188 			ul_pos = parm[0];
1189 		}
1190 		if (parm[1] >= CH_POS_MIN && parm[1] <= CH_POS_MAX &&
1191 					parm[1] < (char_h - font_h)) {
1192 			ch_pos = parm[1];
1193 		}
1194 		break;
1195 	case 's':
1196 		if (parm[0] > SCR_W_MIN && parm[0] <= consfb->scr_w)
1197 			scr_w = (parm[0] < char_w) ? char_w: parm[0];
1198 		if (parm[1] > SCR_H_MIN && parm[1] <= consfb->scr_h)
1199 			scr_h = (parm[1] < char_h) ? char_h: parm[1];
1200 		break;
1201 	case 'o':
1202 		if (parm[0] >= X_OFST_MIN && parm[0] <= X_OFST_MAX)
1203 			x_ofst = (parm[0] > scr_w - char_w) ?
1204 				(scr_w - char_w): parm[0];
1205 		if (parm[1] >= Y_OFST_MIN && parm[1] <= Y_OFST_MAX)
1206 			y_ofst = (parm[1] > scr_h - char_h) ?
1207 				(scr_h - char_h): parm[1];
1208 		break;
1209 	case 'm':
1210 		if (parm[0] >= RIT_M_MIN) {
1211 			if (parm[0] > RIT_M_MAX /* consfb->rit_m */) {
1212 				parm[0] = consfb->rit_m;
1213 			}
1214 			rit_m = (parm[0] > (scr_w - x_ofst)/char_w) ?
1215 				(scr_w - x_ofst)/char_w: parm[0];
1216 		}
1217 		if (parm[1] >= BTM_M_MIN) {
1218 			if (parm[1] > BTM_M_MAX /* consfb->btm_m */) {
1219 				parm[1] = consfb->btm_m;
1220 			}
1221 			btm_m = (parm[1] > (scr_h - y_ofst)/char_h) ?
1222 				(scr_h - y_ofst)/char_h: parm[1];
1223 		}
1224 		break;
1225 	case 'd':
1226 		if (parm[0] >= DIM_CNT_MIN /* && parm[0] <= DIM_CNT_MAX */)
1227 			dim_cnt = a_dim_on = parm[0];
1228 		else
1229 			a_dim_on = 0;
1230 		break;
1231 	case 'b':
1232 		if (parm[0] >= BELL_LEN_MIN && parm[0] <= BELL_LEN_MAX)
1233 			bell_len = parm[0];
1234 		break;
1235 	case 'D':
1236 		set_default_param();
1237 		vt100init();
1238 		bitmapinit();
1239 		break;
1240 	case 'i':
1241 		cursor_off();
1242 		csr_pos(sp, LFT_M, TOP_M);
1243 		key_str.key_string = c_pos_mess;
1244 		key_str.key_length = spr(c_pos_mess, "f=(%d,%d), ",
1245 							font_w, font_h);
1246 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1247 
1248 		key_str.key_length = spr(c_pos_mess, "c=(%d,%d), ",
1249 							char_w, char_h);
1250 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1251 
1252 		csr_pos(sp, LFT_M, (TOP_M - 1));
1253 		key_str.key_string = c_pos_mess;
1254 		key_str.key_length = spr(c_pos_mess, "p=(%d,%d), ",
1255 							ul_pos, ch_pos);
1256 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1257 		key_str.key_length = spr(c_pos_mess, "s=(%d,%d), ",
1258 							scr_w, scr_h);
1259 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1260 
1261 		csr_pos(sp, LFT_M, (TOP_M - 2));
1262 		key_str.key_string = c_pos_mess;
1263 		key_str.key_length = spr(c_pos_mess, "o=(%d,%d), ",
1264 							x_ofst, y_ofst);
1265 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1266 		key_str.key_length = spr(c_pos_mess, "m=(%d,%d)",
1267 							rit_m, btm_m);
1268 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1269 
1270 		cursor_on(&sp->s_csr.csr_p);
1271 		return;
1272 	case 'G':
1273 		line(parm);
1274 		return;
1275 	case 'C':
1276 		if (parm[0] >= 0) {
1277 			sp->s_plane = fbbm_get_pixel(consfb, parm[0]);
1278 		}
1279 		if (parm[1] >= 0) {
1280 			sp->s_bgcol = fbbm_get_pixel(consfb, parm[1]);
1281 		}
1282 		cursor_off();
1283 		if ((sp->s_csr.csr_attributes & REVERSE) ^
1284 			(sp->s_term_mode & DECSCNM)) {
1285 			fcolor = sp->s_bgcol;
1286 			bcolor = sp->s_plane;
1287 		}
1288 		else {
1289 			fcolor = sp->s_plane;
1290 			bcolor = sp->s_bgcol;
1291 		}
1292 		cursor_on(&sp->s_csr.csr_p);
1293 		return;
1294 	case 'T':
1295 		if (parm[0] < 0 || consfb->Mono)
1296 			return;
1297 		/*
1298 		 *  what value is defined on pallet N?
1299 		 *    put string in an_buf
1300 		 */
1301 		*bp++ = '\033';
1302 		*bp++ = '~';
1303 		bp += itoa(bm_pallet_read(parm[0]), 10, bp);
1304 		*bp++ = 'a';
1305 		key_str.key_length = bp - an_buf;
1306 		key_str.key_string = an_buf;
1307 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1308 		return;
1309 	case 't':
1310 		if (parm[0] >= 0 && !consfb->Mono) {
1311 			bm_pallet_write(parm[0],
1312 					(unsigned) parm[1] << 16
1313 					| (unsigned) parm[2] << 8
1314 					| (unsigned) parm[3]
1315 			);
1316 		}
1317 		return;
1318 	default:
1319 		return;
1320 	}
1321 	if (char_w < font_w) char_w = font_w;
1322 	if (char_h < font_h) char_h = font_h;
1323 	if (ch_pos > char_h - font_h) {
1324 		ch_pos = char_h - font_h;
1325 		ul_pos = char_h - 1;
1326 	}
1327 	if (rit_m > (scr_w - x_ofst)/char_w)
1328 		rit_m = (scr_w - x_ofst)/char_w;
1329 	if (btm_m > (scr_h - y_ofst)/char_h)
1330 		btm_m = (scr_h - y_ofst)/char_h;
1331 	sp->s_region.top_margin = TOP_M;
1332 	sp->s_region.btm_margin = btm_m;
1333 	font_r1.extent.x = font_w;
1334 	font_r1.extent.y = font_h;
1335 	font_r2.extent.x = font_w * 2;
1336 	font_r2.extent.y = font_h;
1337 	font_len1 = (font_w + 0x0f)>>4;
1338 	font_len2 = (font_w*2 + 0x0f)>>4;
1339 	cursor_off();
1340 	char_r1.extent.x = char_w;
1341 	char_r1.extent.y = char_h;
1342 	char_r2.extent.x = char_w * 2;
1343 	char_r2.extent.y = char_h;
1344 	csr_pos(sp, sp->s_csr.csr_x, sp->s_csr.csr_y);
1345 	sp->s_csr.csr_p.x = (sp->s_csr.csr_x - 1) * char_w + x_ofst;
1346 	sp->s_csr.csr_p.y = (sp->s_csr.csr_y - 1) * char_h + y_ofst;
1347 	cursor_on(&sp->s_csr.csr_p);
1348 }
1349 
1350 /* VARARGS */
1351 spr(s, fmt, ad, dummy)
1352 	register char *s, *fmt;
1353 	u_int ad;
1354 {
1355 	register int b, c;
1356 	register u_int *adx = &ad;
1357 	char *base = s;
1358 
1359 	for (;;) {
1360 		while ((c = *fmt++) != '%') {
1361 			*s++ = c;
1362 			if (c == '\0')
1363 				return (s - base - 1);
1364 		}
1365 
1366 		c = *fmt++;
1367 		switch (c) {
1368 
1369 		case 'x': case 'X':
1370 			b = 16;
1371 			goto number;
1372 		case 'd': case 'D':
1373 			b = 10;
1374 			goto number;
1375 		case 'o': case 'O':
1376 			b = 8;
1377 number:
1378 			s += itoa(*adx, b, s);
1379 			break;
1380 
1381 		case 'c':
1382 			*s++ = *adx;
1383 			break;
1384 
1385 		case '%':
1386 			*s++ = c;
1387 			break;
1388 		}
1389 		adx++;
1390 	}
1391 }
1392 
1393 static int pfn = -1;
1394 static int active_buf = 0;
1395 /*
1396  *  define the programable function keys and answer back message.
1397  *  the vt100 facilities do not contain this command!
1398  *  command sequence is as follows:
1399  *       "^[Pn|n1;n2;...;nmp"		(normal mode)
1400  *  or
1401  *       "^[Pn|n1;n2;...;nmP"		(shift mode)
1402  *  or
1403  *       "^[Pn|n1;n2;...;nmZ"		(answer backe message)
1404  *  where, `n' denotes the decimal number asigned to function key,
1405  *          from `n1' to `nm' denote hexa number, finally,
1406  *	    `p' , `E' or `Z' tells that the sequence has terminated.
1407  *  remark:
1408  *	  when the terminator is `Z', the function number `n' can be omitted,
1409  *	  and even though the number is specified, there is no affection to
1410  *	  the result.
1411  *
1412  *
1413  *  ADDITION:
1414  *	  there is a question: what strings are defined in programable function
1415  *	  key of key-number n?
1416  *	  in order to anwer this question, another escape sequence has appended.
1417  *	  command sequence is as follows:
1418  *
1419  *	   "^[Pn|i"			(normal mode)
1420  *  or
1421  *	   "^[Pn|I"			(shift	mode)
1422  *
1423  *	  then the answer is
1424  *
1425  *	   "^[Pn|n1;n2;...;nmr"		(normal	mode)
1426  *  or
1427  *	   "^[Pn|n1;n2;...;nmR"		(shift	mode)
1428  *
1429  */
1430 esc_pf_define(sp, c)
1431 	SCREEN *sp;
1432 	unsigned int c;
1433 {
1434 	static bufc = 0;
1435 
1436 	if (in_str(c, sp->s_estp->terminators)) {
1437 		pf_define(pfn, esc_bp - esc_buf + active_buf, c);
1438 		sp->s_current_stat &= ~ESCAPE;
1439 		active_buf = 0;
1440 		pfn = -1;
1441 		bufc = 0;
1442 		return;
1443 	}
1444 	/*  buffering arguments  */
1445 	if (bufc < ESC_BUF_SIZ) {
1446 		if (pfn < 0) {
1447 			if (c >= '0' && c <= '9') {
1448 				*esc_bp = *esc_bp *10 + (c - '0');
1449 			} else if (c == '|') {
1450 				pfn = *esc_bp;
1451 				*esc_bp = 0;
1452 			} else {
1453 				sp->s_current_stat &= ~ESCAPE;
1454 				active_buf = 0;
1455 				pfn = -1;
1456 			}
1457 		} else {
1458 			active_buf = 1;
1459 			if (c >= '0' && c <= '9') {
1460 				*esc_bp = *esc_bp * 16 + (c - '0');
1461 			} else if (c >= 'a' && c <= 'f') {
1462 				*esc_bp = *esc_bp * 16 + (c - 'a' + 10);
1463 			} else if (c >= 'A' && c <= 'F') {
1464 				*esc_bp = *esc_bp * 16 + (c - 'A' + 10);
1465 			} else if (c == ';') {
1466 				esc_bp++;
1467 				bufc++;
1468 			} else {
1469 				sp->s_current_stat &= ~ESCAPE;
1470 				pfn = -1;
1471 				active_buf = 0;
1472 				bufc = 0;
1473 			}
1474 		}
1475 	} else {
1476 		active_buf = 0;
1477 	}
1478 }
1479 
1480 pf_define(pfn, length, terminator)
1481 	int pfn;
1482 	int length;
1483 	unsigned int terminator;
1484 {
1485 	register Pfk_string *pfk = &pfk_str;
1486 	register Key_string *kys = &pfk_str.pfk_string;
1487 
1488 	if (terminator == 'Z')
1489 		return;
1490 
1491 	if (pfn < 0 || pfn > N_PFK)
1492 		return;
1493 	if (terminator == 'i' || terminator == 'I') {
1494 		pf_answer(pfn, terminator);
1495 		return;
1496 	}
1497 	pfk->pfk_num = pfn ? pfn: 1;
1498 	pfk->pfk_shift = (terminator == 'p') ? PF_NORMAL: PF_SHIFT;
1499 	kys->key_length = length;
1500 	kys->key_string = esc_buf;
1501  	kbd_ioctl(SCC_KEYBOARD, KIOCSETS, pfk);
1502 }
1503 
1504 /*
1505  *  pf_answer(pfn, terminator)
1506  *  this routine answers what strings defined on pfn.
1507  */
1508 
1509 char def_seq[ESC_BUF_SIZ];
1510 
1511 pf_answer(pfn, terminator)
1512 	int pfn;
1513 	unsigned int terminator;
1514 {
1515 	register Pfk_string *pfk = &pfk_str;
1516 	register Key_string *kys = &pfk_str.pfk_string;
1517 	register char *bp = an_buf;
1518 	register char *p = def_seq;
1519 	register int length;
1520 	register int j;
1521 
1522 	/*
1523 	 *  function key inquiry
1524 	 *    get string in def_seq
1525 	 */
1526 	pfk->pfk_num = pfn ? pfn: 1;
1527 	pfk->pfk_shift = (terminator == 'i') ? PF_NORMAL: PF_SHIFT;
1528 	kys->key_length = ESC_BUF_SIZ;
1529 	kys->key_string = def_seq;
1530 	kbd_ioctl(SCC_KEYBOARD, KIOCGETS, pfk);
1531 	length = kys->key_length;
1532 
1533 	/*
1534 	 *  function key answer
1535 	 *    put string in an_buf
1536 	 */
1537 	*bp++ = '\033';
1538 	*bp++ = 'P';
1539 	bp += itoa(pfn, 10, bp);
1540 	*bp++ = '|';
1541 	key_str.key_length = bp - an_buf;
1542 	key_str.key_string = an_buf;
1543 	kbd_ioctl(SCC_KEYBOARD, KIOCBACK, &key_str);
1544 
1545 	bp = an_buf;
1546 	if (length--) {
1547 		bp += itoa(*p++ & 0xff, 16, bp);
1548 	}
1549 	while (length > 0) {
1550 		for (j = 0; (j < 10) && (length-- > 0); j++) {
1551 			*bp++ = ';';
1552 			bp += itoa(*p++ & 0xff, 16, bp);
1553 		}
1554 		key_str.key_length = bp - an_buf;
1555 		kbd_ioctl(SCC_KEYBOARD, KIOCBACK, (int *)&key_str);
1556 		bp = an_buf;
1557 	}
1558 	*bp++ = (terminator == 'i') ? 'r': 'R';
1559 	key_str.key_length = bp - an_buf;
1560 	kbd_ioctl(SCC_KEYBOARD, KIOCBACK, (int *)&key_str);
1561 }
1562 
1563 /*
1564  *  ignore
1565  *  esc_ignore(sp) is not called ordinally work.
1566  */
1567 esc_ignore(sp)
1568 	register SCREEN *sp;
1569 {
1570 	sp->s_current_stat &= ~ESCAPE;
1571 }
1572 
1573 static  char	*nmr = "0123456789abcdef";
1574 /*
1575  *  itoa
1576  *  this routine converts binary to ascii decimal or hexa number
1577  *  according to mod.
1578  */
1579 static
1580 itoa(n, mod, buf)
1581 	register int n;
1582 	register int mod;
1583 	register char *buf;
1584 {
1585 	register  int	i = 0;
1586 	register  int	cnt;
1587 	int	first = 1;
1588 	int	k;
1589 
1590 	n &= 0xffff;
1591 	for (cnt = mod*mod*mod*mod*mod*mod*mod; cnt > 0; cnt /= mod) {
1592 		k = n / cnt;
1593 		n -= k * cnt;
1594 		if (k == 0) {
1595 			if (first == 0) {
1596 				*buf++ = nmr[k];
1597 				i++;
1598 			}
1599 		} else {
1600 			*buf++ = nmr[k];
1601 			i++;
1602 			first = 0;
1603 		}
1604 	}
1605 	if (first == 1) {
1606 		*buf++ = '0';
1607 		i++;
1608 	}
1609 	return(i);
1610 }
1611