[comp.os.minix] kernel/tty.c

ast@cs.vu.nl (Andy Tanenbaum) (10/06/87)

64a65
> #define MAX_ESC_PARMS      2	/* number of escape sequence parameters allowed */
74,75c75,80
< #define DEL_CODE   (char) 83	/* DEL for use in CTRL-ALT-DEL reboot */
< #define AT_SIGN         0220	/* code to yield for CTRL-@ */
---
> #define AT_SIGN         0220	/* code to yield for CTRL-@ */
> #define SCODE1            71	/* scan code for Home on numeric pad */
> #define SCODE2            81	/* scan code for PgDn on numeric pad */
> #define DEL_CODE   (char) 83	/* DEL for use in CTRL-ALT-DEL reboot */
> #define ESC       (char) 033	/* escape */
> #define BRACKET          '['	/* Part of the ESC [ letter escape seq */
79c84,85
< #define F10               68	/* scan code for function key F9 */
---
> #define F9                67	/* scan code for function key F9 */
> #define F10               68	/* scan code for function key F10 */
95,96c101,104
<   char tty_esc_state;		/* 0=normal, 1 = ESC seen, 2 = ESC + x seen */
<   char tty_echar;		/* first character following an ESC */
---
>   char tty_esc_state;		/* 0=normal, 1=ESC, 2=ESC[ */
>   char tty_esc_intro;		/* Distinguishing character following ESC */
>   int tty_esc_parmv[MAX_ESC_PARMS];	/* list of escape parameters */
>   int *tty_esc_parmp;		/* pointer to current escape parameter */
103c111
<   int tty_row;			/* current row (0 at bottom of screen) */
---
>   int tty_row;			/* current row (0 at top of screen) */
152,153c160,164
< PUBLIC  int color;		/* 1 if console is color, 0 if it is mono */
< PUBLIC scan_code;		/* scan code for '=' saved by bootstrap */
---
> PRIVATE caps_off = 1;		/* 1 = normal position, 0 = depressed */
> PRIVATE num_off = 1;		/* 1 = normal position, 0 = depressed */
> PUBLIC int color;		/* 1 if console is color, 0 if it is mono */
> PUBLIC scan_code;		/* scan code for '=' saved by bootstrap */
> 
162c173
< ,0261,  0262,0263,'0',0177
---
> ,0261,0262,0263,'0',0177
172c183
<  '2','3','0',177
---
>  '2','3','0','.'
197a209
> char scode_map[] = {'H', 'A', 'V', 'S', 'D', 'G', 'C', 'T', 'Y', 'B', 'U'};
290,291c302,305
<   int mode, sig;
<   char make_break();
---
>   int mode, sig, scode;
>   char make_break();
> 
>   scode = ch;			/* save the scan code */
312,315c326,330
< 			chuck(tp);	/* remove last char entered */
< 			echo(tp, '\b');	/* remove it from the screen */
< 			echo(tp, ' ');
< 			echo(tp, '\b');
---
> 			if (chuck(tp) != -1) {	/* remove last char entered */
> 				echo(tp, '\b');	/* remove it from the screen */
> 				echo(tp, ' ');
> 				echo(tp, '\b');
> 			}
362,368c377
< 		tp->tty_inhibited = RUNNING;	/* do implied CRTL-Q */
< 		finish(tp, EINTR);		/* send reply */
< 		tp->tty_inhead = tp->tty_inqueue;	/* discard input */
< 		tp->tty_intail = tp->tty_inqueue;
< 		tp->tty_incount = 0;
< 		tp->tty_lfct = 0;
< 		cause_sig(LOW_USER + 1 + line, sig);
---
> 		sigchar(tp, line, sig);
387a397,414
> 
>   /* The numeric pad generates ASCII escape sequences: ESC [ letter */
>   if (scode >= SCODE1 && scode <= SCODE2 && 
> 		shift1 == 0 && shift2 == 0 && numlock == 0 ) {
> 	/* This key is to generate a three-character escape sequence. */
> 	*tp->tty_inhead++ = ESC; /* put ESC in the input queue */
> 	if (tp->tty_inhead == &tp->tty_inqueue[TTY_IN_BYTES])
> 		tp->tty_inhead = tp->tty_inqueue;      /* handle wraparound */
> 	tp->tty_incount++;
> 	echo(tp, 'E');
> 	*tp->tty_inhead++ = BRACKET; /* put ESC in the input queue */
> 	if (tp->tty_inhead == &tp->tty_inqueue[TTY_IN_BYTES])
> 		tp->tty_inhead = tp->tty_inqueue;      /* handle wraparound */
> 	tp->tty_incount++;
> 	echo(tp, BRACKET);
> 	ch = scode_map[scode-SCODE1];	/* generate the letter */
>   }
> 
415,422c442,451
< 	code = (shift1 || shift2 || capslock ? sh[c] : unsh[c]);
< 	if (control && c < TOP_ROW) code = sh[c];	/* CTRL-(top row) */
< 	if (c > 70 && numlock) code = sh[c];	/* numlock depressed */
<   } else {
< 	/* (Olivetti M24 or AT&T 6300) with Olivetti-style keyboard. */
< 	code = (shift1 || shift2 || capslock ? m24[c] : unm24[c]);
< 	if (control && c < TOP_ROW) code = sh[c];	/* CTRL-(top row) */
< 	if (c > 70 && numlock) code = m24[c];	/* numlock depressed */
---
> 	code = (shift1 || shift2 ? sh[c] : unsh[c]);
> 	if (control && c < TOP_ROW) code = sh[c];	/* CTRL-(top row) */
> 	if (c > 70 && numlock) 		/* numlock depressed */
> 		code = (shift1 || shift2 ? unsh[c] : sh[c]);
>   } else {
> 	/* (Olivetti M24 or AT&T 6300) with Olivetti-style keyboard. */
> 	code = (shift1 || shift2 ? m24[c] : unm24[c]);
> 	if (control && c < TOP_ROW) code = sh[c];	/* CTRL-(top row) */
> 	if (c > 70 && numlock) 		/* numlock depressed */
> 		code = (shift1 || shift2 ? unm24[c] : m24[c]);
426a456,460
> 	if (capslock)
> 		if (code >= 'A' && code <= 'Z')
> 			code += 'a' - 'A';
> 		else if (code >= 'a' && code <= 'z')
> 			code -= 'a' - 'A';
440,441c474,479
<     case 4:	if (make) capslock = 1 - capslock; break;	/* caps lock */
<     case 5:	if (make) numlock  = 1 - numlock;  break;	/* num lock */
---
>     case 4:	if (make && caps_off) capslock = 1 - capslock; 
> 		caps_off = 1 - make;
> 		break;	/* caps lock */
>     case 5:	if (make && num_off) numlock  = 1 - numlock;  
> 		num_off = 1 - make;
> 		break;	/* num lock */
755a794,813
> /*===========================================================================*
>  *				sigchar					     *
>  *===========================================================================*/
> PRIVATE sigchar(tp, line, sig)
> register struct tty_struct *tp;	/* pointer to tty_struct */
> int line;			/* line on which signal arrived */
> int sig;			/* SIGINT, SIGQUIT, or SIGKILL */
> {
> /* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard */
> 
>   tp->tty_inhibited = RUNNING;	/* do implied CRTL-Q */
>   finish(tp, EINTR);		/* send reply */
>   tp->tty_inhead = tp->tty_inqueue;	/* discard input */
>   tp->tty_intail = tp->tty_inqueue;
>   tp->tty_incount = 0;
>   tp->tty_lfct = 0;
>   cause_sig(LOW_USER + 1 + line, sig);
> }
> 
> 
792a851
> #define EGA            0x3C0	/* port for EGA card */
833c892
<    * The shift-type keys, 29, 42, 54, 56, and 69 must be processed normally.
---
>    * The shift-type keys, 29, 42, 54, 56, 58, and 69 must be processed normally.
838c897
< 	if (k != 29 && k != 42 && k != 54 && k != 56 && k != 69) {
---
> 	if (k != 29 && k != 42 && k != 54 && k != 56 && k != 58 && k != 69) {
926,936c985,988
< /* Output a character on the console. Check for escape sequences, including
<  *   ESC 32+x 32+y to move cursor to (x, y)
<  *   ESC ~ 0       to clear from cursor to end of screen
<  *   ESC ~ 1       to reverse scroll the screen 1 line
<  *   ESC z x       to set the attribute byte to x (z is a literal here)
<  */
< 
<   /* Check to see if we are part way through an escape sequence. */
<   if (tp->tty_esc_state == 1) {
< 	tp->tty_echar = c;
< 	tp->tty_esc_state = 2;
---
> /* Output a character on the console.  Check for escape sequences first. */
> 
>   if (tp->tty_esc_state > 0) {
> 	parse_escape(tp, c);
940,945d991
<   if (tp->tty_esc_state == 2) {
< 	escape(tp, tp->tty_echar, c);
< 	tp->tty_esc_state = 0;
< 	return;
<   }
< 
953c999
< 		move_to(tp, tp->tty_column, tp->tty_row + 1);
---
> 		move_to(tp, tp->tty_column, tp->tty_row - 1);
970,973c1016,1019
< 		if (tp->tty_row == 0) 
< 			scroll_screen(tp, GO_FORWARD);
< 		else
< 			tp->tty_row--;
---
> 		if (tp->tty_row == SCR_LINES-1) 
> 			scroll_screen(tp, GO_FORWARD);
> 		else
> 			tp->tty_row++;
988c1034
< 		/* Ignore tab is XTABS is off--video RAM has no hardware tab */
---
> 		/* Ignore tab if XTABS is off--video RAM has no hardware tab */
999c1045
< 		tp->tty_ramqueue[tp->tty_rwords++] = tp->tty_attribute | c;
---
> 		tp->tty_ramqueue[tp->tty_rwords++]=tp->tty_attribute|(c & BYTE);
1005d1050
< 
1013,1014c1058,1072
<   int amount, offset;
< 
---
>   int amount, offset, bytes;
> 
>   bytes = 2 * (SCR_LINES - 1) * LINE_WIDTH;	/* 2 * 24 * 80 bytes */
> #ifdef SOFTSCROLL
>   /* Software scrolling for non-IBM compatible EGA cards. */
>   if (dir == GO_FORWARD) {
> 	scr_up(vid_base);
> 	vid_copy(NIL_PTR, vid_base,
> 		tp->tty_org+bytes, LINE_WIDTH);
>   } else {
> 	scr_down(vid_base);
> 	vid_copy(NIL_PTR, vid_base, tp->tty_org, LINE_WIDTH);
>   }
> #else
>   /* Normal scrolling using the 6845 registers. */
1018c1076
< 	offset = (tp->tty_org + 2 * (SCR_LINES - 1) * LINE_WIDTH) & vid_mask;
---
> 	offset = (tp->tty_org + bytes) & vid_mask;
1024a1083
> #endif
1052c1111
< int y;				/* row (0 <= y <= 24, 0 at bottom) */
---
> int y;				/* row (0 <= y <= 24, 0 at top) */
1060c1119
<   tp->tty_vid = (tp->tty_org + 2*(SCR_LINES-1-y)*LINE_WIDTH + 2*x);
---
>   tp->tty_vid = (tp->tty_org + 2*y*LINE_WIDTH + 2*x);
1068,1104c1127,1237
< PRIVATE escape(tp, x, y)
< register struct tty_struct *tp;	/* pointer to tty struct */
< char x;				/* escape sequence is ESC x y; this is x */
< char y;				/* escape sequence is ESC x y; this is y */
< {
< /* Handle an escape sequence. */
< 
<   int n, ct, vx;
< 
< 
<   /* Check for ESC z attribute - used to change attribute byte. */
<   if (x == 'z') {
< 	/* Set attribute byte */
< 	tp->tty_attribute = y << 8;
< 	return;
<   }
<   /* Check for ESC ~ n -  used for clear screen, reverse scroll. */
<   if (x == '~') {
< 	if (y == '0') {
< 		/* Clear from cursor to end of screen */
< 		n = 2 * LINE_WIDTH * (tp->tty_row + 1) - 2 * tp->tty_column;
< 		vx = tp->tty_vid;
< 		while (n > 0) {
< 			ct = MIN(n, vid_retrace);
< 			vid_copy(NIL_PTR, vid_base, vx, ct/2);
< 			vx += ct;
< 			n -= ct;
< 		}
< 	} else if (y == '1') {
< 		/* Reverse scroll. */
< 		scroll_screen(tp, GO_BACKWARD);
< 	}
< 	return;
<   }
< 
<   /* Must be cursor movement (or invalid). */
<   move_to(tp, x - 32, y - 32);
---
> 
> PRIVATE parse_escape(tp, c)
> register struct tty_struct *tp;	/* pointer to tty struct */
> char c;				/* next character in escape sequence */
> {
> /* The following ANSI escape sequences are currently supported:
>  *   ESC M         to reverse index the screen
>  *   ESC [ y ; x H to move cursor to (x, y) [default (1,1)]
>  *   ESC [ 0 J     to clear from cursor to end of screen
>  *   ESC [ n m     to set the screen rendition
>  *			n: 0 = normal [default]
>  *			   7 = reverse
>  */
> 
>   switch (tp->tty_esc_state) {
> 	case 1: 		/* ESC seen */
> 		tp->tty_esc_intro = '\0';
> 		tp->tty_esc_parmp = tp->tty_esc_parmv;
> 		tp->tty_esc_parmv[0] = tp->tty_esc_parmv[1] = 0;
> 		switch (c) {
> 		  case '[': 	/* Control Sequence Introducer */
> 			tp->tty_esc_intro = c;
> 			tp->tty_esc_state = 2; 
> 			break;
> 		  case 'M': 	/* Reverse Index */
> 			do_escape(tp, c);
> 			break;
> 		  default: 
> 			tp->tty_esc_state = 0; 
> 			break;
> 		}
> 		break;
> 
> 	case 2: 		/* ESC [ seen */
> 		if (c >= '0' && c <= '9') {
> 			if (tp->tty_esc_parmp 
> 					< tp->tty_esc_parmv + MAX_ESC_PARMS)
> 				*tp->tty_esc_parmp =
> 				  *tp->tty_esc_parmp * 10 + (c - '0');
> 			break;
> 		}
> 		else if (c == ';') {
> 			if (++tp->tty_esc_parmp 
> 					< tp->tty_esc_parmv + MAX_ESC_PARMS)
> 				*tp->tty_esc_parmp = 0;
> 			break;
> 		}
> 		else {
> 			do_escape(tp, c);
> 		}
> 		break;
> 	default:		/* illegal state */
> 		tp->tty_esc_state = 0;
> 		break;
>   }
> }
> 
> PRIVATE do_escape(tp, c)
> register struct tty_struct *tp;	/* pointer to tty struct */
> char c;				/* next character in escape sequence */
> {
>   int n, ct, vx;
> 
>   /* Handle a sequence beginning with just ESC */
>   if (tp->tty_esc_intro == '\0') {
>     switch (c) {
> 	case 'M':		/* Reverse Index */
> 		if (tp->tty_row == 0)
> 			scroll_screen(tp, GO_BACKWARD);
> 		else
> 			tp->tty_row--;
> 		move_to(tp, tp->tty_column, tp->tty_row);
> 		break;
> 	default: break;
>     }
>   }
>   else
>   /* Handle a sequence beginning with ESC [ and parameters */
>   if (tp->tty_esc_intro == '[') {
>     switch (c) {
> 	case 'H':		/* Position cursor */
> 		move_to(tp, 
> 			MAX(1, MIN(LINE_WIDTH, tp->tty_esc_parmv[1])) - 1,
> 			MAX(1, MIN(SCR_LINES, tp->tty_esc_parmv[0])) - 1 );
> 		break;
> 	case 'J':		/* Clear from cursor to end of screen */
> 		if (tp->tty_esc_parmv[0] == 0) {
> 			n = 2 * ((SCR_LINES - (tp->tty_row + 1)) * LINE_WIDTH
> 				+ LINE_WIDTH - (tp->tty_column + 1));
> 			vx = tp->tty_vid;
> 			while (n > 0) {
> 				ct = MIN(n, vid_retrace);
> 				vid_copy(NIL_PTR, vid_base, vx, ct/2);
> 				vx += ct;
> 				n -= ct;
> 			}
> 		}
> 		break;
> 	case 'm':		/* Set graphic rendition */
>  		switch (tp->tty_esc_parmv[0]) {
>  			case 7:	tp->tty_attribute = 0160 << 8;
>  				break;
>  			default: tp->tty_attribute = 0007 << 8;
>  				break;
>  		}
> 		break;
> 	default:
> 		break;
>     }
>   }
>   tp->tty_esc_state = 0;
1168a1302,1305
>   /* Tell the EGA card, if any, to simulate a 16K CGA card. */
>   port_out(EGA + INDEX, 4);	/* register select */
>   port_out(EGA + DATA, 1);	/* no extended memory to be used */
> 
1199c1336
<   move_to(&tty_struct[0], 0, 0);	/* move cursor to lower left corner */
---
>   move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left corner */
1237,1238c1374,1377
< }
< #endif
---
>   if (ch == F9) sigchar(&tty_struct[0], 0, SIGKILL);	/* issue SIGKILL */
> }
> #endif
>