4.3BSD/usr/contrib/X/CLUlib/x_keymap.clu

x_keymap = cluster is load, getc, gets

rep = null

mapsub = 85

qb = sequence[bool]

slmin = 192

slmap	= qb$[true,		% 0301 q
	      true,		% 0302 a
	      true,		% 0303 z
	      false,		% 0304
	      false,		% 0305 2
	      true,		% 0306 w
	      true,		% 0307 s
	      true,		% 0310 x
	      false,		% 0311 <
	      false,		% 0312
	      false,		% 0313 3
	      true,		% 0314 e
	      true,		% 0315 d
	      true,		% 0316 c
	      false,		% 0317
	      false,		% 0320 4
	      true,		% 0321 r
	      true,		% 0322 f
	      true,		% 0323 v
	      false,		% 0324 space
	      false,		% 0325
	      false,		% 0326 5
	      true,		% 0327 t
	      true,		% 0330 g
	      true,		% 0331 b
	      false,		% 0332
	      false,		% 0333 6
	      true,		% 0334 y
	      true,		% 0335 h
	      true,		% 0336 n
	      false,		% 0337
	      false,		% 0340 7
	      true,		% 0341 u
	      true,		% 0342 j
	      true,		% 0343 m
	      false,		% 0344
	      false,		% 0345 8
	      true,		% 0346 i
	      true,		% 0347 k
	      false,		% 0350 ,
	      false,		% 0351
	      false,		% 0352 9
	      true,		% 0353 o
	      true,		% 0354 l
	      false,		% 0355 .
	      false,		% 0356
	      false,		% 0357 0
	      true		% 0360 p
		]

qs = sequence[string]

%		plain,S,M,M-S,C,C-S,C-M,C-M-S

charmap	= qs$[
	      "\330\330\330\330\330\330\330\330",	% 0126 F1/Hold Screen
	      "\324\324\324\324\324\324\324\324",	% 0127 F2/Print Screen
	      "\325\325\325\325\325\325\325\325",	% 0130 F3/Set-Up
	      "\326\326\326\326\326\326\326\326",	% 0131 F4
	      "\327\327\327\327\327\327\327\327",	% 0132 F5/Break
	      "",					% 0133
	      "",					% 0134
	      "",					% 0135
	      "",					% 0136
	      "",					% 0137
	      "",					% 0140
	      "",					% 0141
	      "",					% 0142
	      "",					% 0143
	      "\341\341\341\341\341\341\341\341",	% 0144 F6
	      "\342\342\342\342\342\342\342\342",	% 0145 F7
	      "\343\343\343\343\343\343\343\343",	% 0146 F8
	      "\344\344\344\344\344\344\344\344",	% 0147 F9
	      "\345\345\345\345\345\345\345\345",	% 0150 F10
	      "",					% 0151
	      "",					% 0152
	      "",					% 0153
	      "",					% 0154
	      "",					% 0155
	      "",					% 0156
	      "",					% 0157
	      "",					% 0160
	      "\033\033\033\033\033\033\033\033",	% 0161 F11/ESC
	      "\b\b\210\210\b\b\210\210",		% 0162 F12/BS
	      "\n\n\212\212\n\n\212\212",		% 0163 F13/LF
	      "",					% 0164 F14
	      "",					% 0165
	      "",					% 0166
	      "",					% 0167
	      "",					% 0170
	      "",					% 0171
	      "",					% 0172
	      "",					% 0173
	      "",					% 0174 Help/F15
	      "",					% 0175 Do/F16
	      "",					% 0176
	      "",					% 0177
	      "\346\346\346\346\346\346\346\346",	% 0200 F17
	      "\347\347\347\347\347\347\347\347",	% 0201 F18
	      "\350\350\350\350\350\350\350\350",	% 0202 F19
	      "\351\351\351\351\351\351\351\351",	% 0203 F20/Hyph
	      "",					% 0204
	      "",					% 0205
	      "",					% 0206
	      "",					% 0207
	      "",					% 0210
	      "",					% 0211
	      "\261\261\261\261\261\261\261\261",	% 0212 Find
	      "\262\262\262\262\262\262\262\262",	% 0213 Insert
	      "\263\263\263\263\263\263\263\263",	% 0214 Remove
	      "\264\264\264\264\264\264\264\264",	% 0215 Select
	      "\265\265\265\265\265\265\265\265",	% 0216 Prev Screen
	      "\266\266\266\266\266\266\266\266",	% 0217 Next Screen
	      "",					% 0220
	      "",					% 0221
	      "\360\360\360\360\360\360\360\360",	% 0222 R0
	      "",					% 0223
	      "\356\356\356\356\356\356\356\356",	% 0224 R.
	      "\315\315\315\315\315\315\315\315",	% 0225 Enter
	      "\361\361\361\361\361\361\361\361",	% 0226 R1
	      "\362\362\362\362\362\362\362\362",	% 0227 R2
	      "\363\363\363\363\363\363\363\363",	% 0230 R3
	      "\364\364\364\364\364\364\364\364",	% 0231 R4
	      "\365\365\365\365\365\365\365\365",	% 0232 R5
	      "\366\366\366\366\366\366\366\366",	% 0233 R6
	      "\354\354\354\354\354\354\354\354",	% 0234 R,
	      "\367\367\367\367\367\367\367\367",	% 0235 R7
	      "\370\370\370\370\370\370\370\370",	% 0236 R8
	      "\371\371\371\371\371\371\371\371",	% 0237 R9
	      "\355\355\355\355\355\355\355\355",	% 0240 R-
	      "\320\320\320\320\320\320\320\320",	% 0241 PF1
	      "\321\321\321\321\321\321\321\321",	% 0242 PF2
	      "\322\322\322\322\322\322\322\322",	% 0243 PF3
	      "\323\323\323\323\323\323\323\323",	% 0244 PF4
	      "",					% 0245
	      "",					% 0246
	      "\304\304\304\304\304\304\304\304",	% 0247 leftarrow
	      "\303\303\303\303\303\303\303\303",	% 0250 rightarrow
	      "\302\302\302\302\302\302\302\302",	% 0251 downarrow
	      "\301\301\301\301\301\301\301\301",	% 0252 uparrow
	      "",					% 0253
	      "",					% 0254
	      "",					% 0255
	      "",					% 0256 Shift
	      "",					% 0257 Ctrl
	      "",					% 0260 Lock
	      "",					% 0261 Compose Character
	      "",					% 0262
	      "",					% 0263
	      "",					% 0264
	      "",					% 0265
	      "",					% 0266
	      "",					% 0267
	      "",					% 0270
	      "",					% 0271
	      "",					% 0272
	      "",					% 0273
	      "\177\177\377\377\177\177\377\377",	% 0274 back
	      "\r\r\215\215\r\r\215\215",		% 0275 Return
	      "\t\t\211\211\t\t\211\211",		% 0276 Tab
	      "`~\340\376",				% 0277 `
	      "1!\261\2411!",				% 0300 1
	      "qQ\361\321\021\021\221\221",		% 0301 q
	      "aA\341\301\001\001\201\201",		% 0302 a
	      "zZ\372\332\032\032\232\232",		% 0303 z
	      "",					% 0304
	      "2@\262\3002\000\262\200",		% 0305 2
	      "wW\367\327\027\027\227\227",		% 0306 w
	      "sS\363\323\023\023\223\223",		% 0307 s
	      "xX\370\330\030\030\230\230",		% 0310 x
	      "<>\274\276",				% 0311 <
	      "",					% 0312
	      "3#\263\2433#",				% 0313 3
	      "eE\345\305\005\005\205\205",		% 0314 e
	      "dD\344\304\004\004\204\204",		% 0315 d
	      "cC\343\303\003\003\203\203",		% 0316 c
	      "",					% 0317
	      "4$\264\2444$",				% 0320 4
	      "rR\362\322\022\022\222\222",		% 0321 r
	      "fF\346\306\006\006\206\206",		% 0322 f
	      "vV\366\326\026\026\226\226",		% 0323 v
	      "  \240\240\000\000\200\200",		% 0324 space
	      "",					% 0325
	      "5%\265\2455%",				% 0326 5
	      "tT\364\324\024\024\224\224",		% 0327 t
	      "gG\347\307\007\007\207\207",		% 0330 g
	      "bB\342\302\002\002\202\202",		% 0331 b
	      "",					% 0332
	      "6^\266\3366\036\266\236",		% 0333 6
	      "yY\371\331\031\031\231\231",		% 0334 y
	      "hH\350\310\010\010\210\210",		% 0335 h
	      "nN\356\316\016\016\216\216",		% 0336 n
	      "",					% 0337
	      "7&\267\2467&",				% 0340 7
	      "uU\365\325\025\025\225\225",		% 0341 u
	      "jJ\352\312\012\012\212\212",		% 0342 j
	      "mM\355\315\015\015\215\215",		% 0343 m
	      "",					% 0344
	      "8*\270\2528*",				% 0345 8
	      "iI\351\311\011\011\211\211",		% 0346 i
	      "kK\353\313\013\013\213\213",		% 0347 k
	      ",<\254\274",				% 0350 ,
	      "",					% 0351
	      "9(\271\2509(",				% 0352 9
	      "oO\357\317\017\017\217\217",		% 0353 o
	      "lL\354\314\014\014\214\214",		% 0354 l
	      ".>\256\276",				% 0355 .
	      "",					% 0356
	      "0)\260\2510(",				% 0357 0
	      "pP\360\320\020\020\220\220",		% 0360 p
	      "",					% 0361
	      ";:\273\272",				% 0362 ;
	      "/?\257\277\037\037\237\237",		% 0363 /
	      "",					% 0364
	      "=+\275\253",				% 0365 =
	      "]}\335\375\035\035\235\235",		% 0366 ]
	      "\\|\334\374\034\034\234\234",		% 0367 \
	      "",					% 0370
	      "-_\255\337-\037\255\237",		% 0371 -
	      "[{\333\373\033\033\233\233",		% 0372 [
	      "'\"\247\242"				% 0373 '
	      ]

multilist = array[multi]
multi = record[key:   int,
	       mask:  int,
	       value: string]

own havemap: bool := false
own keymap: _bytevec
own multis: multilist

load = proc (fs: string)
    if string$empty(fs)
       then fs := ".Xkeymap" end
    begin
    fn: file_name := file_name$parse(fs)
    if string$empty(fn.dir)
       then fn := file_name$create(_environ("HOME"), fn.name,
				   fn.suffix, fn.other)
       end
    c: _chan := _chan$open(fn, "read", 0)
    if _chan$getc(c, false) ~= '\372'
       then _chan$close(c)
	    return
       end
    keymap := _bytevec$create(c.length - 1)
    _chan$getb(c, keymap)
    _chan$close(c)
    havemap := _bytevec$size(keymap) >= 4096
    multis := multilist$new()
    i: int := 4097
    while true do
	multilist$addh(multis,
		       multi${key:   char$c2i(keymap[i]),
			      mask:  char$c2i(keymap[i + 1]),
			      value: string$substr(_cvt[_bytevec, string](
						       keymap),
						   i + 3,
						   char$c2i(keymap[i + 2]))})
	i := i + 3 + char$c2i(keymap[i + 2])
	end
    end except others: end
    end load

getc = proc (key, mask: int) returns (char) signals (none, multi(string))
    if havemap
       then mask := mask / 2**11
	    c: char := keymap[(key * 16) + mask + 1]
	    if c < '\375'
	       then return(c) end
	    if c = '\376'
	       then for m: multi in multilist$elements(multis) do
			if key = m.key  cand
			   (mask = m.mask  cor  m.mask = 255)
			   then if string$size(m.value) = 1
				   then return(m.value[1]) end
				if string$empty(m.value)
				   then signal none end
				signal multi(m.value)
			   end
			end
	       end
	    signal none
       end except when bounds: signal none end
    key := key - mapsub
    keymode: int := mask / 2**12 + 1
    if (mask / 2**11) // 4 = 1  cand  slmap[key + (mapsub - slmin)]
       then keymode := keymode + 1
       end except when bounds: end
    return(charmap[key][keymode])
       except when bounds: signal none end
    end getc

gets = proc (key, mask: int) returns (string) signals (none)
    if havemap
       then mask := mask / 2**11
	    c: char := keymap[(key * 16) + mask + 1]
	    if c < '\375'
	       then return(string$c2s(c)) end
	    if c = '\376'
	       then for m: multi in multilist$elements(multis) do
			if key = m.key  cand
			   (mask = m.mask  cor  m.mask = 255)
			   then if string$empty(m.value)
				   then signal none end
				return(m.value)
			   end
			end
	       end
	    signal none
       end except when bounds: signal none end
    key := key - mapsub
    keymode: int := mask / 2**12 + 1
    if (mask / 2**11) // 4 = 1  cand  slmap[key + (mapsub - slmin)]
       then keymode := keymode + 1
       end except when bounds: end
    return(string$c2s(charmap[key][keymode]))
       except when bounds: signal none end
    end gets

end x_keymap