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