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