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