[comp.os.minix] German keyboard with umlauts

hp@vmars.tuwien.ac.at (Peter Holzer) (11/08/90)

After having posted only half-thought-through ideas and requests
for help in the past, here is my first productive posting to this
group :-).

The MINIX keyboard task uses the special values 0200 to 0205 for
the shift type keys. Unfortunately two German umlauts (and four
other accented characters) are in this range, so defining a
German (or French) keyboard is not quite straightforward. To do
this I defined an additional array special[], where special
actions are defined. Here are the diffs:

WARNING: Check the index lines before appying the patch.
If you do not have Minix 1.5 from PH but patched up from a previous
version the files might be in different directories. Besides I
have filled in the file names from memory (after cat'ing the
cdiffs together).
---8<------8<------8<------8<------8<------8<------8<------8<---
Index: /usr/src/kernel/keyboard.c
*** orig/keyboard.c	Thu Nov  1 10:44:33 1990
--- keyboard.c	Thu Nov  1 20:11:17 1990
***************
*** 34,39 ****
--- 34,40 ----
  /* Scan codes whose action is not completely captured by maps. */
  #define DEL_SCAN	  83	/* DEL for use in CTRL-ALT-DEL reboot */
  #define DUTCH_EXT_SCAN	  32	/* 'd' */
+ #define GERMAN_EXT_SCAN	  34	/* 'g' */
  #define ESCAPE_CODE	0xE0	/* beginning of escape sequence */
  #define F1		  59	/* function key F1, others follow */
  #define F2		  60
***************
*** 59,64 ****
--- 60,66 ----
  #define OLIVETTI	   2	/* Olivetti keyboard */
  #define DUTCH_EXT	   3	/* Dutch extended IBM keyboard */
  #define US_EXT		   4	/* U.S. extended keyboard */
+ #define GERMAN_EXT	   5	/* German extended keyboard */
  
  /* Miscellaneous. */
  #define CTRL_S		  31	/* scan code for letter S (for CRTL-S) */
***************
*** 69,74 ****
--- 71,87 ----
  #define kb_addr(n)	(&kb_lines[CONSOLE])	/* incorrectly ignore n */
  #define KB_IBUFSIZE	  32	/* size of keyboard input buffer */
  
+ #define ACTION		0x07	/* Action mask for special []	*/
+ #define NORMAL		0x00	/* Actions ...	*/
+ #define SHIFT		0x01
+ #define CONTROL		0x02
+ #define ALT		0x03
+ #define CAPSLOCK	0x04
+ #define SHIFTLOCK	0x05
+ #define NUMLOCK		0x06
+ #define K_NUMLOCK	0x40	/* Key responds to num lock	*/
+ #define K_CAPSLOCK	0x80	/* Key responds to caps lock	*/
+ 
  PRIVATE int alt;		/* alt key state */
  PRIVATE int capslock;		/* caps lock key state */
  PRIVATE int esc;		/* escape scan code detected? */
***************
*** 79,86 ****
  PRIVATE int numlock;		/* number lock key state */
  PRIVATE int num_off;		/* 1 = normal position, 0 = depressed */
  PRIVATE int num_slash;		/* numeric slash on dutch extended keyboard */
! PRIVATE int shift1;		/* left shift key state */
! PRIVATE int shift2;		/* right shift key state */
  
  /* Scan codes to ASCII for alt keys (IBM Extended keyboard) */
  PRIVATE char alt_c[NR_SCAN_CODES];
--- 92,99 ----
  PRIVATE int numlock;		/* number lock key state */
  PRIVATE int num_off;		/* 1 = normal position, 0 = depressed */
  PRIVATE int num_slash;		/* numeric slash on dutch extended keyboard */
! PRIVATE int shift;		/* shift key state */
! PRIVATE int shiftlock;		/* shift lock key state */
  
  /* Scan codes to ASCII for alt keys (IBM Extended keyboard) */
  PRIVATE char alt_c[NR_SCAN_CODES];
***************
*** 160,189 ****
   0,0,0,0,0,0,0,0
  };
  
! /* Unshifted U.S. extended kbd */
! PRIVATE char unsh_usx[NR_SCAN_CODES] = {
!  0,'`','1','2','3','4','5','6',        '7','8','9','0','-','=','\b','\t',
!  'q','w','e','r','t','y','u','i',      'o','p','[',']',015,0202,'a','s',
!  'd','f','g','h','j','k','l',';',      047,033,0200,0134,'z','x','c','v',
!  'b','n','m',',','.','/',0201,'*',     0203,' ',0202,0241,0242,0243,0244,0245,
!  0246,0247,0250,0251,0252,0205,0210,0267,  0270,0271,0211,0264,0265,0266,0214
! ,0261,0262,0263,'0',0177,0,0,0,0,	0,0,0,0,0,0,0,0,
! 0,0,0,0,0,0,0,0
! };
! 
! /* Shifted U.S. extended kbd */
! PRIVATE char sh_usx[NR_SCAN_CODES] = {
!  0,033,'!','@','#','$','%','^',        '&','*','(',')','_','+','\b','\t',
!  'Q','W','E','R','T','Y','U','I',      'O','P','{','}',015,0202,'A','S',
!  'D','F','G','H','J','K','L',':',      042,'~',0200,'|','Z','X','C','V',
!  'B','N','M','<','>','?',0201,'*',    0203,' ',0202,0221,0222,0223,0224,0225,
!  0226,0227,0230,0231,0232,0204,0213,'7',  '8','9',0211,'4','5','6',0214,'1',
!  '2','3','0','.',0,0,0,0,		0,0,0,0,0,0,0,0,
   0,0,0,0,0,0,0,0
  };
  
! PRIVATE char scode_map[] =
! 		{'H', 'A', 'V', 'S', 'D', 'G', 'C', 'T', 'Y', 'B', 'U'};
  
  /* Keyboard structure, 1 per console. */
  struct kb_s {
--- 173,281 ----
   0,0,0,0,0,0,0,0
  };
  
! /* code tables for german extended keyboard	*/
! 
! PRIVATE char grmn_unsh[NR_SCAN_CODES] = {
!  0,033,'1','2','3','4','5','6',		'7','8','9','0', 225,'\'','\b','\t',
!  'q','w','e','r','t','z','u','i',	'o','p',129,'+','\r',0202,'a','s',
!  'd','f','g','h','j','k','l',148,	132,'^',0200,'#','y','x','c','v',
!  'b','n','m',',','.','-',0201,'*',	0203,' ',0204,0,0,0,0,0,
!  0,0,0,0,0,0205,0,183,			184,185,137,180,'5',182,140,177,
!  178,179,0,0177,0,0,'<','/',0,		0,0,0,0,0,0,0,0,
!  0,0,0,0,0,0,0,0
! };
! 
! PRIVATE char grmn_sh[NR_SCAN_CODES] = {
!  0,033,'!','\"',21,'$','%','&',	'/','(',')','=','?',96,'\b','\t',
!  'Q','W','E','R','T','Z','U','I',	'O','P',154,'*','\r',0202,'A','S',
!  'D','F','G','H','J','K','L',153,	142,248,0200,'\'','Y','X','C','V',
!  'B','N','M',';',':','_',0201,'*',	0203,' ',0204,0,0,0,0,0,
!  0,0,0,0,0,0205,0,'7',			'8','9',137,'4','5','6',140,'1',
!  '2','3','0',',',0,0,'>','/',0,		0,0,0,0,0,0,0,0,
   0,0,0,0,0,0,0,0
  };
  
! /* Code table for alt key */
! PRIVATE char grmn_alt[NR_SCAN_CODES] = {
!  0,0,0,253,252,0,0,0,		'{','[',']','}','\\',0,0,0,
!  '@',0,0,0,0,0,0,0,		0,0,0,'~',0,0202,0,0,
!  0,0,0,0,0,0,0,0,		0,170,0200,0,174,175,0,0,
!  0,0,230,0,0,0,0201,0,		0203,0,0204,0,0,0,0,0,
!  0,0,0,0,0,0205,0,0,		0,0,0,0,0,0,0,0,
!  0,0,0,0177,0,0,'|',0,0,	0,0,0,0,0,0,0,0,
!  0,0,0,0,0,0,0,0
! };
! 
! /* Unshifted U.S. extended kbd */
! PRIVATE char unsh_usx[NR_SCAN_CODES] = {
!  0,'`','1','2','3','4','5','6',        '7','8','9','0','-','=','\b','\t',
!  'q','w','e','r','t','y','u','i',      'o','p','[',']',015,0202,'a','s',
!  'd','f','g','h','j','k','l',';',      047,033,0200,0134,'z','x','c','v',
!  'b','n','m',',','.','/',0201,'*',     0203,' ',0202,0241,0242,0243,0244,0245,
!  0246,0247,0250,0251,0252,0205,0210,0267,  0270,0271,0211,0264,0265,0266,0214
! ,0261,0262,0263,'0',0177,0,0,0,0,	0,0,0,0,0,0,0,0,
! 0,0,0,0,0,0,0,0
! };
! 
! /* Shifted U.S. extended kbd */
! PRIVATE char sh_usx[NR_SCAN_CODES] = {
!  0,033,'!','@','#','$','%','^',        '&','*','(',')','_','+','\b','\t',
!  'Q','W','E','R','T','Y','U','I',      'O','P','{','}',015,0202,'A','S',
!  'D','F','G','H','J','K','L',':',      042,'~',0200,'|','Z','X','C','V',
!  'B','N','M','<','>','?',0201,'*',    0203,' ',0202,0221,0222,0223,0224,0225,
!  0226,0227,0230,0231,0232,0204,0213,'7',  '8','9',0211,'4','5','6',0214,'1',
!  '2','3','0','.',0,0,0,0,		0,0,0,0,0,0,0,0,
!  0,0,0,0,0,0,0,0
! };
! 
! PRIVATE char scode_map[] =
! 		{'H', 'A', 'V', 'S', 'D', 'G', 'C', 'T', 'Y', 'B', 'U'};
! 		
! /* scecial key map. Each entry consists of three fields:
!  *	action (bits 0 ... 2): 
!  *		0	Key is not a shift type key.
!  *		1	Shift
!  *		2	Control
!  *		3	Alt
!  *		4	Caps-Lock
!  *		5	Shift-Lock
!  *		6	Num-Lock
!  *	numlock (bit 6)
!  *		0	Key's meaning does change if numlock is active.
!  *		1	Key's meaning does not change if numlock is active.
!  *	capslock (bit 7)
!  *		0	Key's meaning does change if capslock is active.
!  *		1	Key's meaning does not change if capslock is active.
!  *		
!  *	Bits 3 ... 5 are not yet used. If you want additional shift type
!  *	keys expand the action field if necessary and add lock-sensity fields
!  *	from high to low bits so they clash with the action field as late
!  *	as possible.
!  *	
!  *	Note that I did not distinguish between left and right shift, alt,
!  *	and control keys. 
!  *	
!  */
! PRIVATE char special[NR_SCAN_CODES] = {
!  0,0,0,0,0,0,0,0,				0,0,0,0,0,0,0,0,
!  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,	0x80,0x80,0,0,0,2,0x80,0x80,
!  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0,		0,0,1,0,0x80,0x80,0x80,0x80,
!  0x80,0x80,0x80,0,0,0,1,0,			3,0,4,0,0,0,0,0,
!  0,0,0,0,0,6,0,0x40,  				0x40,0x40,0,0x40,0x40,0x40,0,0x40,
!  0x40,0x40,0x40,0x40,0,0,0,0,			0,0,0,0,0,0,0,0,
!  0,0,0,0,0,0,0,0
! };
! 
! PRIVATE char grmn_special[NR_SCAN_CODES] = {
!  0,0,0,0,0,0,0,0,				0,0,0,0,0,0,0,0,
!  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,	0x80,0x80,0x80,0,0,2,0x80,0x80,
!  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,	0x80,0,1,0,0x80,0x80,0x80,0x80,
!  0x80,0x80,0x80,0,0,0,1,0,			3,0,4,0,0,0,0,0,
!  0,0,0,0,0,6,0,0x40,  				0x40,0x40,0,0x40,0x40,0x40,0,0x40,
!  0x40,0x40,0x40,0x40,0,0,0,0,			0,0,0,0,0,0,0,0,
!  0,0,0,0,0,0,0,0
! };
! 
  
  /* Keyboard structure, 1 per console. */
  struct kb_s {
***************
*** 202,207 ****
--- 294,300 ----
  FORWARD int kb_ack();
  FORWARD int kb_wait();
  FORWARD void load_dutch_table();
+ FORWARD void load_grmn_table();
  FORWARD void load_olivetti();
  FORWARD void load_us_ext();
  FORWARD int scan_keyboard();
***************
*** 224,230 ****
     * released.  Filter out the latter, ignoring all but the shift-type keys.
     * The shift-type keys 29, 42, 54, 56, 58, and 69 must be processed normally.
     */
!   if (keyb_type == DUTCH_EXT)
  	if (esc) {
  		/* Numeric slash gives scan codes 0xE0 0x35. */
  		if (code == minus_code) code = num_slash;
--- 317,323 ----
     * released.  Filter out the latter, ignoring all but the shift-type keys.
     * The shift-type keys 29, 42, 54, 56, 58, and 69 must be processed normally.
     */
!   if (keyb_type == DUTCH_EXT || keyb_type == GERMAN_EXT)
  	if (esc) {
  		/* Numeric slash gives scan codes 0xE0 0x35. */
  		if (code == minus_code) code = num_slash;
***************
*** 235,241 ****
    k = code - 0200;		/* codes > 0200 mean key release */
    if (k > 0) {
  	/* A key has been released. */
! 	if (k != 29 && k != 42 && k != 54 && k != 56 && k != 58 && k != 69)
  		return;		/* don't call tty_task() */
    } else {
  	/* Check to see if character is CTRL-S, to stop output. Setting xoff
--- 328,334 ----
    k = code - 0200;		/* codes > 0200 mean key release */
    if (k > 0) {
  	/* A key has been released. */
! 	if ((special [k] & ACTION) == NORMAL)
  		return;		/* don't call tty_task() */
    } else {
  	/* Check to see if character is CTRL-S, to stop output. Setting xoff
***************
*** 312,318 ****
  {
  /* Convert scan codes from numeric keypad to letters for use in escape seqs. */
  
!   if (scode >= SCODE1 && scode <= SCODE2 && (shift1 || shift2 || !numlock))
  	return scode_map[scode - SCODE1];
    return 0;
  }
--- 405,412 ----
  {
  /* Convert scan codes from numeric keypad to letters for use in escape seqs. */
  
!   scode &= 0x7F;	/* just to be sure	*/
!   if ((special [scode] & K_NUMLOCK) && (shift || !numlock))
  	return scode_map[scode - SCODE1];
    return 0;
  }
***************
*** 340,407 ****
    c = ch & 0177;		/* high-order bit set on key release */
    make = (ch & 0200 ? 0 : 1);	/* 1 when key depressed, 0 when key released */
  
!   if (alt && keyb_type == DUTCH_EXT)
! 	code = alt_c[c];
!   else
! 	code = (shift1 || shift2 ? sh[c] : unsh[c]);
! 
!   if (control && c < TOP_ROW) code = sh[c];	/* CTRL-(top row) */
! 
!   if (c >= SCODE1 && c <= SCODE2 + 2)	/* numeric pad including DEL, INS */
! 	code = (shift1 || shift2 || !numlock ? unsh[c] : sh[c]);
! 
!   code &= BYTE;
!   if (code < 0200 || code >= 0206) {
! 	/* Ordinary key, i.e. not shift, control, alt, etc. */
! 	if (capslock)
! 		if (code >= 'A' && code <= 'Z')
! 			code += 'a' - 'A';
! 		else if (code >= 'a' && code <= 'z')
! 			code -= 'a' - 'A';
! 	if (alt && keyb_type != DUTCH_EXT) code |= 0200;  /* alt ORs in 0200 */
! 	if (control) code &= 037;
! 	if (make == 0) code = -1;	/* key release */
! 	return(code);
!   }
! 
!   /* Table entries 0200 - 0206 denote special actions. */
!   switch(code - 0200) {
!     case 0:	shift1 = make;		break;	/* shift key on left */
!     case 1:	shift2 = make;		break;	/* shift key on right */
!     case 2:
! #if KEYBOARD_84
! /* Until IBM invented the 101-key keyboard, the CTRL key was always to the
!  * left of the 'A'.  This fix puts it back there on the 101-key keyboard.
!  */
! 		if (make && caps_off) {
! 			capslock = 1 - capslock;
! 			set_leds();
! 		}
! 		caps_off = 1 - make;    break;	/* caps lock */
! #else
! 		control = make;		break;	/* control */
! #endif
!     case 3:	alt = make;		break;	/* alt key */
!     case 4:	
! #if KEYBOARD_84
! 		control = make;		break;	/* control */
! #else
! 		if (make && caps_off) {
! 			/* disable autorepeat for caps lock	*/
! 			capslock = 1 - capslock;
! 			set_leds();
! 		}
! 		caps_off = 1 - make;    break;	/* caps lock */
! #endif
!     case 5:	if (make && num_off) {
! 			/* disable autorepeat for num lock	*/
! 			numlock  = 1 - numlock;
! 			set_leds();
! 		}
! 		num_off = 1 - make;
! 		break;	/* num lock */
!   }
!   return(-1);
  }
  
  
--- 434,493 ----
    c = ch & 0177;		/* high-order bit set on key release */
    make = (ch & 0200 ? 0 : 1);	/* 1 when key depressed, 0 when key released */
  
!   if (code = special [c] & ACTION) {
!   	/* shift type keys yield actions not characters */
! 	switch (code) {
! 	    case SHIFT:
! 			shift = make;
! 			shiftlock = 0;
! 			set_leds ();
! 			break;	/* any shift key */
! 	    case CONTROL:
! 			control = make;		break;	/* any control key */
! 	    case ALT:	alt = make;		break;	/* any alt key */
! 	    case CAPSLOCK:	
! 			if (make && caps_off) {
! 				/* disable autorepeat for caps lock	*/
! 				capslock = 1 - capslock;
! 				set_leds();
! 			}
! 			caps_off = 1 - make;
! 			break;	/* caps lock */
! 	    case SHIFTLOCK:	/* for those who want it	*/
! 			shiftlock = 1;
! 			set_leds();
! 			break;	/* shift lock */
! 	    case NUMLOCK:
! 			if (make && num_off) {
! 				/* disable autorepeat for num lock	*/
! 				numlock  = 1 - numlock;
! 				set_leds();
! 			}
! 			num_off = 1 - make;
! 			break;	/* num lock */
! 	}
! 	return(-1);
! 
!   } else {
! 	/* Ordinary key, i.e. not shift, control, alt, etc. */
!   
! 	if (alt)
! 		code = alt_c[c];
! 	else {
! 		if (special [c] & K_CAPSLOCK) {
! 			code = ((! shift == ! capslock) ? unsh [c] : sh [c]);
! 		} else if (special [c] & K_NUMLOCK) {
! 			code = ((shift || !numlock) ? unsh[c] : sh[c]);
! 		} else {
! 			code = (shift || shiftlock || (control && c < TOP_ROW)
! 				? sh[c] : unsh[c]);
! 		}	
! 	  }
! 	code &= BYTE;
! 	if (control) code &= 037;
! 	if (!make) code = -1;	/* key release */
! 	return(code);
!   }	
  }
  
  
***************
*** 505,510 ****
--- 591,598 ----
  				load_dutch_table(); break;
  	case US_EXT_SCAN:	keyb_type = US_EXT;
  				load_us_ext(); break;
+ 	case GERMAN_EXT_SCAN:	keyb_type = GERMAN_EXT;
+ 				load_grmn_table(); break;
    }
  
    scan_keyboard();		/* stop lockup from leftover keystroke */
***************
*** 531,566 ****
  }
  
  /*===========================================================================*
!  *				load_olivetti				     *
!  *===========================================================================*/
! PRIVATE void load_olivetti()
! {
! /* Load the scan code to ASCII table for olivetti type keyboard. */
  
    register int i;
  
    for (i = 0; i < NR_SCAN_CODES; i++) {
! 	sh[i] = m24[i];
! 	unsh[i] = unm24[i];
!   }
  }
  
  /*===========================================================================*
!  *				load_us_ext				     *
!  *===========================================================================*/
! PRIVATE void load_us_ext()
! {
! /* Load the scan code to ASCII table for US extended keyboard. */
  
    register int i;
  
    for (i = 0; i < NR_SCAN_CODES; i++) {
! 	sh[i] = sh_usx[i];
! 	unsh[i] = unsh_usx[i];
    }
  }
  
  /*===========================================================================*
   *				func_key				     *
   *===========================================================================*/
  PUBLIC int func_key(ch)
--- 619,674 ----
  }
  
  /*===========================================================================*
!  *				load_grmn_table			     *
!  *===========================================================================*/
! PRIVATE void load_grmn_table()
! {
! /* Load the scan code to ASCII table for extended grmn keyboard. */
  
    register int i;
  
    for (i = 0; i < NR_SCAN_CODES; i++) {
! 	sh[i] = grmn_sh[i];
! 	unsh[i] = grmn_unsh[i];
! 	alt_c[i] = grmn_alt[i];
! 	special[i] = grmn_special[i];
!   }
! 
!   minus_code = MINUS_DU;
!   num_slash = NUM_SLASH_DU;
  }
  
  /*===========================================================================*
!  *				load_olivetti				     *
!  *===========================================================================*/
! PRIVATE void load_olivetti()
! {
! /* Load the scan code to ASCII table for olivetti type keyboard. */
  
    register int i;
  
    for (i = 0; i < NR_SCAN_CODES; i++) {
! 	sh[i] = m24[i];
! 	unsh[i] = unm24[i];
    }
  }
  
  /*===========================================================================*
+  *				load_us_ext				     *
+  *===========================================================================*/
+ PRIVATE void load_us_ext()
+ {
+ /* Load the scan code to ASCII table for US extended keyboard. */
+ 
+   register int i;
+ 
+   for (i = 0; i < NR_SCAN_CODES; i++) {
+ 	sh[i] = sh_usx[i];
+ 	unsh[i] = unsh_usx[i];
+   }
+ }
+ 
+ /*===========================================================================*
   *				func_key				     *
   *===========================================================================*/
  PUBLIC int func_key(ch)

Index: /usr/src/tools/menu.c
*** orig/menu.c	Mon Nov  5 10:08:43 1990
--- menu.c	Thu Nov  1 15:03:44 1990
***************
*** 246,252 ****
  	printf("\nHit key as follows:\n\n");
  	printf("    =  start MINIX, standard keyboard\n");
  	printf("    u  start MINIX, U.S. extended keyboard\n");
! 	printf("    d  start MINIX, Dutch keyboard for PS/2\n\n");
  	printf("    r  select root device (now %s)\n", rootname);
  	printf("    i  select RAM image device (now %s)%s\n",
  	       ramimname,
--- 246,253 ----
  	printf("\nHit key as follows:\n\n");
  	printf("    =  start MINIX, standard keyboard\n");
  	printf("    u  start MINIX, U.S. extended keyboard\n");
! 	printf("    d  start MINIX, Dutch keyboard for PS/2\n");
! 	printf("    g  start MINIX, German extended keyboard\n\n");
  	printf("    r  select root device (now %s)\n", rootname);
  	printf("    i  select RAM image device (now %s)%s\n",
  	       ramimname,
***************
*** 272,277 ****
--- 273,279 ----
  	    case '=':
  	    case 'u':
  	    case 'd':
+ 	    case 'g':
  		return(boot_parameters.bp_scancode = (c >> 8) & 0xFF);
  
  	    case 'i':
---8<------8<------8<------8<------8<------8<------8<------8<---
--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |