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