xref: /original-bsd/sys/news3400/bm/kb_encode.c (revision daedb501)
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: kb_encode.c,v 4.300 91/06/09 06:14:51 root Rel41 $ SONY
11  *
12  *	@(#)kb_encode.c	7.2 (Berkeley) 07/28/92
13  */
14 
15 #include "../include/fix_machine_type.h"
16 
17 #ifdef IPC_MRX
18 #include "../../h/param.h"
19 #include "../../h/systm.h"
20 #include "../../h/types.h"
21 #include "../../h/ioctl.h"
22 #include "../../iop/keyboard.h"
23 #include "../../iop/kbreg.h"
24 #else
25 #include "param.h"
26 #include "systm.h"
27 #include "types.h"
28 #include "ioctl.h"
29 #include "../iop/keyboard.h"
30 #include "../iop/kbreg.h"
31 #endif
32 #include "malloc.h"
33 
34 extern int tmode;
35 extern int country;
36 extern Pfk_table pfk_table[];
37 extern Pfk_table pfk_init[];
38 extern Key_table *key_table_addr;
39 
40 int	kbd_status;
41 int	shifttype;
42 extern int iscaps;
43 
44 /*
45  *	kbd_encode(c)
46  *		int c;		keyboard address code
47  *
48  *	kbd_encode() converts keyboard address code to character code.
49  *	kbd_encode() calls back machine dependent function
50  *
51  *		put_code(buf, cnt)
52  *			char *buf;	encoded characters
53  *			int cnt;	character count
54  *
55  *	to store encoded data.
56  */
57 kbd_encode(c)
58 	register int c;
59 {
60 	register Key_table *kp;
61 	register int c_mask;
62 
63 	c_mask = c & 0x7f;
64 	c &= 0xff;
65 	if (c_mask > N_KEY)
66 		return (0);
67 	kp = &key_table_addr[c_mask];
68 	if (c & OFF)
69 		kp->key_flags &= ~KEY_PRESS;
70 	else if ((kp->key_flags & KEY_PRESS) &&
71 	    ((kbd_status & KBD_NOTREPT) || (kp->key_flags & NOT_REPT)))
72 		return (0);
73 	else
74 		kp->key_flags |= KEY_PRESS;
75 
76 	if (kp->key_flags & (PSH_SHFT|SW_SHFT)) {
77 		kbd_shift(c);
78 		return (0);
79 	}
80 	if ((kp->key_flags & ALT_FUNC) && (kbd_status & KBD_ALT) ||
81 	    (kp->key_flags & PRG_FUNC))
82 		return (kbd_pfunc(c));
83 	return (kbd_normal(c));
84 }
85 
86 
87 #define KFLAGSW(a, b)	((a) ? (kbd_status |= (b)) : (kbd_status &= ~(b)))
88 #define	LOCKTYPE(a, b)	(shifttype = ((a) ? (a) : (b)))
89 
90 static
91 kbd_shift(c)
92 	register int c;
93 {
94 	register Key_table *kp = &key_table_addr[c & 0x7f];
95 	register int push = (c & OFF) == 0;
96 
97 	switch (kp->normal_code) {
98 
99 	case S_CTRL:
100 		KFLAGSW(push, KBD_CTRL);
101 		break;
102 
103 	case S_RSHFT:
104 		KFLAGSW(push, KBD_RSHIFT);
105 		break;
106 
107 	case S_LSHFT:
108 		KFLAGSW(push, KBD_LSHIFT);
109 		break;
110 
111 	case S_ALT:
112 		KFLAGSW(push, KBD_ALT);
113 		break;
114 
115 	case S_CAPS:
116 		if (push) {
117 			kbd_status ^= KBD_CAPS;
118 			LOCKTYPE(iscaps, CAPSLOCK);
119 		}
120 		break;
121 
122 	case S_AN:
123 		if (push) {
124 			kbd_status &= ~KBD_KANA;
125 		}
126 		break;
127 
128 	case S_KANA:
129 		if (push) {
130 			switch (country) {
131 			case K_JAPANESE_J:
132 				kbd_status |= KBD_KANA;
133 			default:
134 				break;
135 			}
136 		}
137 		break;
138 
139 	case S_ALTGR:
140 		KFLAGSW(push, KBD_ALTGR);
141 		break;
142 
143 	default:
144 		break;
145 
146 	}
147 	return (0);
148 }
149 
150 static
151 kbd_pfunc(c)
152 	register int c;
153 {
154 	register Pfk_table *kp;
155 
156 	if (c & OFF)
157 		return (0);
158 	for (kp = pfk_table; kp < pfk_table + N_PFK; kp++) {
159 		if (kp->pfk_addr != c)
160 			continue;
161 		if (kbd_status & KBD_SHIFT)
162 			return (put_code(kp->pfk_shift.key_string,
163 			    kp->pfk_shift.key_length));
164 		return (put_code(kp->pfk_normal.key_string,
165 		    kp->pfk_normal.key_length));
166 	}
167 	return (0);
168 }
169 
170 #define	PUT(cond, code, len)		((cond) ? put_code(code, len) : 0)
171 #define	PUT_KANA(cond, code, len)	((cond) ? put_kana(code, len) : 0)
172 
173 static
174 kbd_normal(c)
175 	int c;
176 {
177 	register Key_table *kp = &key_table_addr[c & 0x7f];
178 
179 	if (c & OFF)
180 		return (0);
181 	if (kbd_status & KBD_ALT)
182 		return (PUT(kp->key_flags & A, &kp->alt_code, 1));
183 	if (kbd_status & KBD_CTRL)
184 		return (PUT(kp->key_flags & C, &kp->ctrl_code, 1));
185 	if (kbd_status & KBD_ALTGR)
186 		return (PUT(kp->key_flags & G, &kp->kana_code, 1));
187 	if (kbd_status & KBD_KANA) {
188 		if (kbd_status & KBD_SHIFT)
189 			return (PUT_KANA(kp->key_flags & J, &kp->kshft_code, 1));
190 		return (PUT_KANA(kp->key_flags & K, &kp->kana_code, 1));
191 	}
192 	if (kbd_status & KBD_CAPS) {
193 		if ((kbd_status & KBD_SHIFT) && (kp->key_flags & S)) {
194 			if (kp->key_flags & CAP_LOCK) {
195 				switch (shifttype) {
196 
197 				case CAPSLOCK:
198 					return (put_code(&kp->shift_code, 1));
199 
200 				case SHIFTLOCK:
201 				case SHIFTLOCK2:
202 					return (put_code(&kp->normal_code, 1));
203 
204 				default:
205 					return (0);
206 				}
207 			}
208 			switch (shifttype) {
209 
210 			case CAPSLOCK:
211 			case SHIFTLOCK:
212 				return (put_code(&kp->shift_code, 1));
213 
214 			case SHIFTLOCK2:
215 				return (put_code(&kp->normal_code, 1));
216 
217 			default:
218 				return (0);
219 			}
220 		}
221 		if (kp->key_flags & N) {
222 			if (kp->key_flags & CAP_LOCK)
223 				return (put_code(&kp->shift_code, 1));
224 			switch (shifttype) {
225 
226 			case CAPSLOCK:
227 			case SHIFTLOCK:
228 				return (put_code(&kp->normal_code, 1));
229 
230 			case SHIFTLOCK2:
231 				return (put_code(&kp->shift_code, 1));
232 
233 			default:
234 				return (0);
235 			}
236 		}
237 	}
238 	if (kbd_status & KBD_SHIFT)
239  		return (PUT(kp->key_flags & S, &kp->shift_code, 1));
240 	return (PUT(kp->key_flags & N, &kp->normal_code, 1));
241 }
242 
243 kbd_string(cmd, p)
244 	int cmd;
245 	register Pfk_string *p;
246 {
247 	register Key_string *pk;
248 
249 	if (p->pfk_num < 0 || p->pfk_num >= N_PFK)
250 		return (0);
251 	switch (p->pfk_shift) {
252 
253 	case PF_NORMAL:
254 		pk = &pfk_table[p->pfk_num].pfk_normal;
255 		break;
256 
257 	case PF_SHIFT:
258 		pk = &pfk_table[p->pfk_num].pfk_shift;
259 		break;
260 
261 	default:
262 		return (0);
263 	}
264 	switch (cmd) {
265 
266 	case KIOCSETS:
267 		if (pk->key_string != NULL) {
268 			free(pk->key_string, M_DEVBUF);
269 			pk->key_string = NULL;
270 			pk->key_length = 0;
271 		}
272 		if (pk->key_length = p->pfk_string.key_length) {
273 			pk->key_string =
274 			    (char *)malloc(p->pfk_string.key_length, M_DEVBUF, M_WAITOK);
275 			bcopy(p->pfk_string.key_string, pk->key_string,
276 			    p->pfk_string.key_length);
277 		} else
278 			pk->key_string = NULL;
279 		bcopy(p->pfk_string.key_string, pk->key_string,
280 		    p->pfk_string.key_length);
281 		pk->key_length = p->pfk_string.key_length;
282 		break;
283 
284 	case KIOCGETS:
285 		p->pfk_string.key_length =
286 		    min(p->pfk_string.key_length, pk->key_length);
287 		bcopy(pk->key_string, p->pfk_string.key_string,
288 		    p->pfk_string.key_length);
289 		break;
290 
291 	default:
292 		return (0);
293 	}
294 	return (0);
295 }
296 
297 kbd_init()
298 {
299 	int i;
300 	Pfk_string pfk_buf;
301 
302 	for (i = 0; i < N_PFK; i++) {
303 		pfk_table[i].pfk_addr = pfk_init[i].pfk_addr;
304 		if (pfk_init[i].pfk_normal.key_length > 0) {
305 			pfk_buf.pfk_num = i;
306 			pfk_buf.pfk_shift = PF_NORMAL;
307 			pfk_buf.pfk_string = pfk_init[i].pfk_normal;
308 			kbd_string(KIOCSETS, &pfk_buf);
309 		}
310 		if (pfk_init[i].pfk_shift.key_length > 0) {
311 			pfk_buf.pfk_num = i;
312 			pfk_buf.pfk_shift = PF_SHIFT;
313 			pfk_buf.pfk_string = pfk_init[i].pfk_shift;
314 			kbd_string(KIOCSETS, &pfk_buf);
315 		}
316 	}
317 	kbd_status = 0;
318 }
319 
320 kbd_repeat(f)
321 	int f;
322 {
323 
324 	if (f)
325 		kbd_status &= ~KBD_NOTREPT;
326 	else
327 		kbd_status |= KBD_NOTREPT;
328 	return (0);
329 }
330 
331 
332 static
333 put2char(c1, c2)
334 	int c1, c2;
335 {
336 	char buf[2];
337 
338 	buf[0] = c1;
339 	buf[1] = c2;
340 	return (put_code(buf, 2));
341 }
342 
343 #define	SS2		0x8e
344 
345 static
346 put_kana(s, len)
347 	register u_char *s;
348 	int len;
349 {
350 	register int i;
351 	register u_char *p;
352 	u_char eucbuf[8];
353 
354 	if (len <= 0)
355 		return (0);
356 #ifdef KM_EUC
357 	if ((tmode == KM_EUC) && ((*s >= 0xa1) && (*s <= 0xdf))) {
358 		p = eucbuf;
359 		for (i = len; i > 0; i--) {
360 			*p++ = SS2;
361 			*p++ = *s++;
362 		}
363 		return (put_code(eucbuf, len * 2));
364 	}
365 #endif /* KM_EUC */
366 	return (put_code(s, len));
367 }
368