Line data Source code
1 : /* $OpenBSD: wsemul_subr.c,v 1.1 2013/10/18 22:06:41 miod Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2007, 2013 Miodrag Vallat.
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice, this permission notice, and the disclaimer below
9 : * appear in all copies.
10 : *
11 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 : */
19 :
20 : #include <sys/param.h>
21 : #include <sys/systm.h>
22 : #include <sys/errno.h>
23 :
24 : #include <dev/wscons/wscons_features.h>
25 : #include <dev/wscons/wsconsio.h>
26 : #include <dev/wscons/wsdisplayvar.h>
27 : #include <dev/wscons/wsemulvar.h>
28 : #include <dev/wscons/wsksymdef.h>
29 :
30 : int wsemul_local_translate(u_int32_t, kbd_t, u_char *);
31 :
32 : /*
33 : * Get characters from an input stream and update the input state.
34 : * Processing stops when the stream is empty, or a complete character
35 : * sequence has been recognized, in which case it returns zero.
36 : */
37 : int
38 0 : wsemul_getchar(const u_char **inbuf, u_int *inlen,
39 : struct wsemul_inputstate *state, int allow_utf8)
40 : {
41 : #ifndef HAVE_UTF8_SUPPORT
42 : u_int len = *inlen;
43 : const u_char *buf = *inbuf;
44 :
45 : if (len == 0)
46 : return (EAGAIN);
47 :
48 : state->inchar = *buf++;
49 : state->mbleft = 0;
50 : len--;
51 : *inlen = len;
52 : *inbuf = buf;
53 : return (0);
54 : #else
55 0 : u_int len = *inlen;
56 0 : const u_char *buf = *inbuf;
57 : int rc = EAGAIN;
58 : u_int32_t tmpchar;
59 : u_int mbleft;
60 :
61 0 : if (len == 0)
62 0 : return (rc);
63 :
64 : /*
65 : * If we do not allow multibyte sequences, process as quickly
66 : * as possible.
67 : */
68 0 : if (!allow_utf8) {
69 0 : state->inchar = *buf++;
70 0 : state->mbleft = 0;
71 0 : len--;
72 0 : *inlen = len;
73 0 : *inbuf = buf;
74 0 : return (0);
75 : }
76 :
77 0 : tmpchar = state->inchar;
78 0 : mbleft = state->mbleft;
79 :
80 0 : while (len != 0) {
81 0 : u_int32_t frag = (u_int32_t)*buf++;
82 0 : len--;
83 :
84 : /*
85 : * If we are in the middle of a multibyte sequence, try
86 : * to complete it.
87 : */
88 :
89 0 : if (mbleft != 0) {
90 0 : if ((frag & 0xc0) != 0x80) {
91 : /* Abort the sequence and continue */
92 : mbleft = 0;
93 : tmpchar = 0;
94 : rc = EILSEQ;
95 0 : } else {
96 0 : tmpchar = (tmpchar << 6) | (frag & 0x3f);
97 0 : mbleft--;
98 0 : if (mbleft == 0) {
99 : rc = 0;
100 0 : break;
101 : }
102 : }
103 : }
104 :
105 : /*
106 : * Otherwise let's decide if this is the start of a new
107 : * multibyte sequence, or a 7-bit character.
108 : */
109 :
110 0 : if ((frag & 0x80) == 0) {
111 : tmpchar = frag;
112 : rc = 0;
113 0 : break;
114 : }
115 :
116 0 : if (frag == 0xfe || frag == 0xff || (frag & 0x40) == 0) {
117 : /* Abort the sequence and continue */
118 : mbleft = 0;
119 : tmpchar = 0;
120 : rc = EILSEQ;
121 0 : } else {
122 0 : frag &= ~(0x80 | 0x40);
123 : mbleft = 1;
124 :
125 0 : if (frag & 0x20) {
126 0 : frag &= ~0x20;
127 : mbleft++;
128 0 : }
129 0 : if (frag & 0x10) {
130 0 : frag &= ~0x10;
131 0 : mbleft++;
132 0 : }
133 0 : if (frag & 0x08) {
134 0 : frag &= ~0x08;
135 0 : mbleft++;
136 0 : }
137 0 : if (frag & 0x04) {
138 0 : frag &= ~0x04;
139 0 : mbleft++;
140 0 : }
141 :
142 : tmpchar = frag;
143 : }
144 0 : }
145 :
146 0 : state->inchar = tmpchar;
147 0 : state->mbleft = mbleft;
148 0 : *inlen = len;
149 0 : *inbuf = buf;
150 0 : return (rc);
151 : #endif
152 0 : }
153 :
154 : /*
155 : * Unicode Cyrillic to KOI8 translation table (starts at U+0400),
156 : * from RFC 2319.
157 : */
158 : const u_int8_t cyrillic_to_koi8[] = {
159 : 0x00, /* IE grave */ /* 0400 */
160 : 0xb3, /* IO */
161 : 0x00, /* DJE */
162 : 0x00, /* GJE */
163 : 0xb4, /* UKR IE */
164 : 0x00, /* DZE */
165 : 0xb6, /* BYE/UKR I */
166 : 0xb7, /* YI */
167 : 0x00, /* JE */
168 : 0x00, /* LJE */
169 : 0x00, /* NJE */
170 : 0x00, /* TSHE */
171 : 0x00, /* KJE */
172 : 0x00, /* I grave */
173 : 0x00, /* short U */
174 : 0x00, /* DZHE */
175 : 0xe1, /* A */ /* 0410 */
176 : 0xe2, /* BE */
177 : 0xf7, /* VE */
178 : 0xe7, /* GHE */
179 : 0xe4, /* DE */
180 : 0xe5, /* IE */
181 : 0xf6, /* ZHE */
182 : 0xfa, /* ZE */
183 : 0xe9, /* I */
184 : 0xea, /* short I */
185 : 0xeb, /* KA */
186 : 0xec, /* EL */
187 : 0xed, /* EM */
188 : 0xee, /* EN */
189 : 0xef, /* O */
190 : 0xf0, /* PE */
191 : 0xf2, /* ER */ /* 0420 */
192 : 0xf3, /* ES */
193 : 0xf4, /* TE */
194 : 0xf5, /* U */
195 : 0xe6, /* EF */
196 : 0xe8, /* HA */
197 : 0xe3, /* TSE */
198 : 0xfe, /* CHE */
199 : 0xfb, /* SHA */
200 : 0xfd, /* SHCHA */
201 : 0xff, /* HARD SIGN */
202 : 0xf9, /* YERU */
203 : 0xf8, /* SOFT SIGN */
204 : 0xfc, /* E */
205 : 0xe0, /* YU */
206 : 0xf1, /* YA */
207 : 0xc1, /* a */ /* 0430 */
208 : 0xc2, /* be */
209 : 0xd7, /* ve */
210 : 0xc7, /* ghe */
211 : 0xc4, /* de */
212 : 0xc5, /* ie */
213 : 0xd6, /* zhe */
214 : 0xda, /* ze */
215 : 0xc9, /* i */
216 : 0xca, /* short i */
217 : 0xcb, /* ka */
218 : 0xcc, /* el */
219 : 0xcd, /* em */
220 : 0xce, /* en */
221 : 0xcf, /* o */
222 : 0xd0, /* pe */
223 : 0xd2, /* er */ /* 0440 */
224 : 0xd3, /* es */
225 : 0xd4, /* te */
226 : 0xd5, /* u */
227 : 0xc6, /* ef */
228 : 0xc8, /* ha */
229 : 0xc3, /* tse */
230 : 0xde, /* che */
231 : 0xdb, /* sha */
232 : 0xdd, /* shcha */
233 : 0xdf, /* hard sign */
234 : 0xd9, /* yeru */
235 : 0xd8, /* soft sign */
236 : 0xdc, /* e */
237 : 0xc0, /* yu */
238 : 0xd1, /* ya */
239 : 0x00, /* ie grave */ /* 0450 */
240 : 0xa3, /* io */
241 : 0x00, /* dje */
242 : 0x00, /* GJE */
243 : 0xa4, /* UKR ie */
244 : 0x00, /* DZE */
245 : 0xa6, /* BYE/UKR I */
246 : 0xa7, /* YI */
247 : 0x00, /* JE */
248 : 0x00, /* LJE */
249 : 0x00, /* NJE */
250 : 0x00, /* TSHE */
251 : 0x00, /* KJE */
252 : 0x00, /* I grave */
253 : 0x00, /* short U */
254 : 0x00 /* DZHE */
255 : };
256 :
257 : /*
258 : * Europe to Latin-2 translation table (starts at U+0100).
259 : */
260 : const u_int8_t unicode_to_latin2[] = {
261 : 0x00, /* A macron */ /* 0100 */
262 : 0x00, /* a macron */
263 : 0xc3, /* A breve */
264 : 0xe3, /* a breve */
265 : 0xa1, /* A ogonek */
266 : 0xb1, /* a ogonek */
267 : 0xc6, /* C acute */
268 : 0xe6, /* c acute */
269 : 0x00, /* C circumflex */
270 : 0x00, /* c circumflex */
271 : 0x00, /* C abovering */
272 : 0x00, /* c abovering */
273 : 0xc8, /* C caron */
274 : 0xe8, /* c caron */
275 : 0xcf, /* D caron */
276 : 0xef, /* d caron */
277 : 0xd0, /* D stroke */ /* 0110 */
278 : 0xf0, /* d stroke */
279 : 0x00, /* E macron */
280 : 0x00, /* e macron */
281 : 0x00, /* E breve */
282 : 0x00, /* e breve */
283 : 0x00, /* E abovering */
284 : 0x00, /* e abovering */
285 : 0xca, /* E ogonek */
286 : 0xea, /* e ogonek */
287 : 0xcc, /* E caron */
288 : 0xec, /* e caron */
289 : 0x00, /* G circumflex */
290 : 0x00, /* g circumflex */
291 : 0x00, /* G breve */
292 : 0x00, /* g breve */
293 : 0x00, /* G abovering */ /* 0120 */
294 : 0x00, /* g abovering */
295 : 0x00, /* G cedilla */
296 : 0x00, /* g cedilla */
297 : 0x00, /* H circumflex */
298 : 0x00, /* h circumflex */
299 : 0x00, /* H stroke */
300 : 0x00, /* h stroke */
301 : 0x00, /* I tilde */
302 : 0x00, /* i tilde */
303 : 0x00, /* I macron */
304 : 0x00, /* i macron */
305 : 0x00, /* I breve */
306 : 0x00, /* i breve */
307 : 0x00, /* I ogonek */
308 : 0x00, /* i ogonek */
309 : 0x00, /* dotted I */ /* 0130 */
310 : 0x00, /* non-dotted i */
311 : 0x00, /* ligature IJ */
312 : 0x00, /* ligature ij */
313 : 0x00, /* J circumflex */
314 : 0x00, /* j circumflex */
315 : 0x00, /* K cedilla */
316 : 0x00, /* k cedilla */
317 : 0x00, /* kra */
318 : 0xc5, /* L acute */
319 : 0xe5, /* l acute */
320 : 0x00, /* L cedilla */
321 : 0x00, /* l cedilla */
322 : 0xa5, /* L caron */
323 : 0xb5, /* l caron */
324 : 0x00, /* L middle dot */
325 : 0x00, /* l middle dot */ /* 0140 */
326 : 0xa3, /* L stroke */
327 : 0xb3, /* l stroke */
328 : 0xd1, /* N acute */
329 : 0xf1, /* n acute */
330 : 0x00, /* N cedilla */
331 : 0x00, /* n cedilla */
332 : 0xd2, /* N caron */
333 : 0xf2, /* n caron */
334 : 0x00, /* N preceded by apostrophe */
335 : 0x00, /* ENG */
336 : 0x00, /* eng */
337 : 0x00, /* O macron */
338 : 0x00, /* o macron */
339 : 0x00, /* O breve */
340 : 0x00, /* o breve */
341 : 0xd5, /* O double acute */ /* 0150 */
342 : 0xf5, /* o double acute */
343 : 0x00, /* ligature OE */
344 : 0x00, /* ligature oe */
345 : 0xc0, /* R acute */
346 : 0xe0, /* r acute */
347 : 0x00, /* R cedilla */
348 : 0x00, /* r cedilla */
349 : 0xd8, /* R caron */
350 : 0xf8, /* r caron */
351 : 0xa6, /* S acute */
352 : 0xb6, /* s acute */
353 : 0x00, /* S circumflex */
354 : 0x00, /* s circumflex */
355 : 0xaa, /* S cedilla */
356 : 0xba, /* s cedilla */
357 : 0xa9, /* S caron */ /* 0160 */
358 : 0xb9, /* s caron */
359 : 0xde, /* T cedilla */
360 : 0xfe, /* t cedilla */
361 : 0xab, /* T caron */
362 : 0xbb, /* t caron */
363 : 0x00, /* T stroke */
364 : 0x00, /* t stroke */
365 : 0x00, /* U tilde */
366 : 0x00, /* u tilde */
367 : 0x00, /* U macron */
368 : 0x00, /* u macron */
369 : 0x00, /* U breve */
370 : 0x00, /* u breve */
371 : 0xd9, /* U abovering */
372 : 0xf9, /* u abovering */
373 : 0xdb, /* U double acute */ /* 0170 */
374 : 0xfb, /* u double acute */
375 : 0x00, /* U ogonek */
376 : 0x00, /* u ogonek */
377 : 0x00, /* W circumflex */
378 : 0x00, /* w circumflex */
379 : 0x00, /* Y circumflex */
380 : 0x00, /* y circumflex */
381 : 0x00, /* Y diaeresis */
382 : 0xac, /* Z acute */
383 : 0xbc, /* z acute */
384 : 0xaf, /* Z abovering */
385 : 0xbf, /* z abovering */
386 : 0xae, /* Z caron */
387 : 0xbe, /* z caron */
388 : 0x00 /* long s */
389 : };
390 :
391 : /*
392 : * Baltic to Latin-7 translation table.
393 : */
394 : const u_int8_t unicode_to_latin7[] = {
395 : 0xc2, /* A macron */ /* 0100 */
396 : 0xe2, /* a macron */
397 : 0x00, /* A breve */
398 : 0x00, /* a breve */
399 : 0xc0, /* A ogonek */
400 : 0xe0, /* a ogonek */
401 : 0xc3, /* C acute */
402 : 0xe3, /* c acute */
403 : 0x00, /* C circumflex */
404 : 0x00, /* c circumflex */
405 : 0x00, /* C abovering */
406 : 0x00, /* c abovering */
407 : 0xc8, /* C caron */
408 : 0xe8, /* c caron */
409 : 0x00, /* D caron */
410 : 0x00, /* d caron */
411 : 0x00, /* D stroke */ /* 0110 */
412 : 0x00, /* d stroke */
413 : 0xc7, /* E macron */
414 : 0xe7, /* e macron */
415 : 0x00, /* E breve */
416 : 0x00, /* e breve */
417 : 0xcb, /* E abovering */
418 : 0xeb, /* e abovering */
419 : 0xc6, /* E ogonek */
420 : 0xe6, /* e ogonek */
421 : 0x00, /* E caron */
422 : 0x00, /* e caron */
423 : 0x00, /* G circumflex */
424 : 0x00, /* g circumflex */
425 : 0x00, /* G breve */
426 : 0x00, /* g breve */
427 : 0x00, /* G abovering */ /* 0120 */
428 : 0x00, /* g abovering */
429 : 0xcc, /* G cedilla */
430 : 0xec, /* g cedilla */
431 : 0x00, /* H circumflex */
432 : 0x00, /* h circumflex */
433 : 0x00, /* H stroke */
434 : 0x00, /* h stroke */
435 : 0x00, /* I tilde */
436 : 0x00, /* i tilde */
437 : 0xce, /* I macron */
438 : 0xee, /* i macron */
439 : 0x00, /* I breve */
440 : 0x00, /* i breve */
441 : 0xc1, /* I ogonek */
442 : 0xe1, /* i ogonek */
443 : 0x00, /* dotted I */ /* 0130 */
444 : 0x00, /* non-dotted I */
445 : 0x00, /* ligature IJ */
446 : 0x00, /* ligature ij */
447 : 0x00, /* J circumflex */
448 : 0x00, /* j circumflex */
449 : 0xcd, /* K cedilla */
450 : 0xed, /* k cedilla */
451 : 0x00, /* kra */
452 : 0x00, /* L acute */
453 : 0x00, /* l acute */
454 : 0xcf, /* L cedilla */
455 : 0xef, /* l cedilla */
456 : 0x00, /* L caron */
457 : 0x00, /* l caron */
458 : 0x00, /* L middle dot */
459 : 0x00, /* l middle dot */ /* 0140 */
460 : 0xd9, /* L stroke */
461 : 0xf9, /* l stroke */
462 : 0xd1, /* N acute */
463 : 0xf1, /* n acute */
464 : 0xd2, /* N cedilla */
465 : 0xf2, /* n cedilla */
466 : 0x00, /* N caron */
467 : 0x00, /* n caron */
468 : 0x00, /* N preceded by apostrophe */
469 : 0x00, /* ENG */
470 : 0x00, /* eng */
471 : 0xd4, /* O macron */
472 : 0xf4, /* o macron */
473 : 0x00, /* O breve */
474 : 0x00, /* o breve */
475 : 0x00, /* O double acute */ /* 0150 */
476 : 0x00, /* o double acute */
477 : 0x00, /* ligature OE */
478 : 0x00, /* ligature oe */
479 : 0x00, /* R acute */
480 : 0x00, /* r acute */
481 : 0xaa, /* R cedilla */
482 : 0xba, /* r cedilla */
483 : 0x00, /* R caron */
484 : 0x00, /* r caron */
485 : 0xda, /* S acute */
486 : 0xfa, /* s acute */
487 : 0x00, /* S circumflex */
488 : 0x00, /* s circumflex */
489 : 0x00, /* S cedilla */
490 : 0x00, /* s cedilla */
491 : 0xd0, /* S caron */ /* 0160 */
492 : 0xf0, /* s caron */
493 : 0x00, /* T cedilla */
494 : 0x00, /* t cedilla */
495 : 0x00, /* T caron */
496 : 0x00, /* t caron */
497 : 0x00, /* T stroke */
498 : 0x00, /* t stroke */
499 : 0x00, /* U tilde */
500 : 0x00, /* u tilde */
501 : 0xdb, /* U macron */
502 : 0xfb, /* u macron */
503 : 0x00, /* U breve */
504 : 0x00, /* u breve */
505 : 0x00, /* U abovering */
506 : 0x00, /* u abovering */
507 : 0x00, /* U double acute */ /* 0170 */
508 : 0x00, /* u double acute */
509 : 0xd8, /* U ogonek */
510 : 0xf8, /* u ogonek */
511 : 0x00, /* W circumflex */
512 : 0x00, /* w circumflex */
513 : 0x00, /* Y circumflex */
514 : 0x00, /* y circumflex */
515 : 0x00, /* Y diaeresis */
516 : 0xca, /* Z acute */
517 : 0xea, /* z acute */
518 : 0xdd, /* Z abovering */
519 : 0xfd, /* z abovering */
520 : 0xde, /* Z caron */
521 : 0xfe, /* z caron */
522 : 0x00 /* long s */
523 : };
524 :
525 : /*
526 : * Keysym to local 8-bit charset sequence translation function.
527 : * The out buffer is at least one character long.
528 : * The keyboard layout is used as a hint to decide which latin charset to
529 : * assume.
530 : */
531 : int
532 0 : wsemul_local_translate(u_int32_t unisym, kbd_t layout, u_char *out)
533 : {
534 0 : switch (unisym >> 7) {
535 : case 0x0080 >> 7:
536 0 : switch (KB_ENCODING(layout)) {
537 : case KB_LT:
538 : case KB_LV:
539 0 : switch (unisym) {
540 : case KS_L7_AE:
541 : unisym = 0xaf;
542 0 : break;
543 : case KS_L7_Ostroke:
544 : unisym = 0xa8;
545 0 : break;
546 : case KS_L7_ae:
547 : unisym = 0xbf;
548 0 : break;
549 : case KS_L7_ostroke:
550 : unisym = 0xb8;
551 0 : break;
552 : }
553 : }
554 : break;
555 :
556 : case 0x0100 >> 7:
557 0 : switch (KB_ENCODING(layout)) {
558 : case KB_LT:
559 : case KB_LV:
560 0 : if (unisym < 0x100 + nitems(unicode_to_latin7) &&
561 0 : unicode_to_latin7[unisym - 0x100] != 0)
562 0 : unisym = unicode_to_latin7[unisym - 0x100];
563 : break;
564 : case KB_TR:
565 0 : switch (unisym) {
566 : case KS_L5_Gbreve:
567 : unisym = 0xd0;
568 0 : break;
569 : case KS_L5_gbreve:
570 : unisym = 0xf0;
571 0 : break;
572 : case KS_L5_Idotabove:
573 : unisym = 0xdd;
574 0 : break;
575 : case KS_L5_idotless:
576 : unisym = 0xfd;
577 0 : break;
578 : case KS_L5_Scedilla:
579 : unisym = 0xde;
580 0 : break;
581 : case KS_L5_scedilla:
582 : unisym = 0xfe;
583 0 : break;
584 : }
585 : break;
586 : case KB_PL:
587 : case KB_SI:
588 0 : if (unisym < 0x100 + nitems(unicode_to_latin2) &&
589 0 : unicode_to_latin2[unisym - 0x100] != 0)
590 0 : unisym = unicode_to_latin2[unisym - 0x100];
591 : break;
592 : }
593 : break;
594 :
595 : case 0x0280 >> 7:
596 0 : switch (KB_ENCODING(layout)) {
597 : case KB_PL:
598 : case KB_SI:
599 0 : switch (unisym) {
600 : case KS_L2_caron:
601 : unisym = 0xb7;
602 0 : break;
603 : case KS_L2_breve:
604 : unisym = 0xa2;
605 0 : break;
606 : case KS_L2_dotabove:
607 : unisym = 0xff;
608 0 : break;
609 : case KS_L2_ogonek:
610 : unisym = 0xb2;
611 0 : break;
612 : case KS_L2_dblacute:
613 : unisym = 0xbd;
614 0 : break;
615 : }
616 : break;
617 : }
618 : break;
619 :
620 : case 0x0400 >> 7:
621 0 : if (unisym < 0x400 +
622 0 : sizeof(cyrillic_to_koi8) / sizeof(cyrillic_to_koi8[0]) &&
623 0 : cyrillic_to_koi8[unisym - 0x400] != 0)
624 0 : unisym = cyrillic_to_koi8[unisym - 0x400];
625 : break;
626 : case 0x0480 >> 7:
627 0 : if (unisym == KS_Cyrillic_GHEUKR)
628 0 : unisym = 0xbd; /* ukrainian GHE */
629 0 : else if (unisym == KS_Cyrillic_gheukr)
630 0 : unisym = 0xad; /* ukrainian ghe */
631 : break;
632 :
633 : case 0x2000 >> 7:
634 0 : switch (KB_ENCODING(layout)) {
635 : case KB_LT:
636 : case KB_LV:
637 0 : switch (unisym) {
638 : case KS_L7_rightsnglquot:
639 : unisym = 0xff;
640 0 : break;
641 : case KS_L7_leftdblquot:
642 : unisym = 0xb4;
643 0 : break;
644 : case KS_L7_rightdblquot:
645 : unisym = 0xa1;
646 0 : break;
647 : case KS_L7_dbllow9quot:
648 : unisym = 0xa5;
649 0 : break;
650 : }
651 : }
652 : break;
653 :
654 : }
655 :
656 0 : out[0] = unisym & 0xff;
657 0 : return (1);
658 : }
659 :
660 : /*
661 : * Keysym to UTF-8 sequence translation function.
662 : * The out buffer is at least 6 characters long.
663 : */
664 : int
665 0 : wsemul_utf8_translate(u_int32_t unisym, kbd_t layout, u_char *out,
666 : int allow_utf8)
667 : {
668 : #ifndef HAVE_UTF8_SUPPORT
669 : return (wsemul_local_translate(unisym, layout, out));
670 : #else
671 : u_int pos, length, headpat;
672 :
673 0 : if (!allow_utf8)
674 0 : return (wsemul_local_translate(unisym, layout, out));
675 :
676 0 : if (unisym >= 0x80000000) {
677 0 : return (0);
678 0 : } else if (unisym > 0x04000000) {
679 : headpat = 0xfc;
680 : length = 6;
681 0 : } else if (unisym > 0x00200000) {
682 : headpat = 0xf8;
683 : length = 5;
684 0 : } else if (unisym > 0x00010000) {
685 : headpat = 0xf0;
686 : length = 4;
687 0 : } else if (unisym > 0x00000800) {
688 : headpat = 0xe0;
689 : length = 3;
690 0 : } else if (unisym > 0x00000080) {
691 : headpat = 0xc0;
692 : length = 2;
693 0 : } else {
694 : headpat = 0x00;
695 : length = 1;
696 : }
697 :
698 0 : for (pos = length - 1; pos > 0; pos--) {
699 0 : out[pos] = 0x80 | (unisym & 0x3f);
700 0 : unisym >>= 6;
701 : }
702 0 : out[0] = headpat | unisym;
703 :
704 0 : return (length);
705 : #endif
706 0 : }
|