Added basic ignore settings for git.
[screen-lua.git] / src / encoding.c
blobe72057c80cc40618ae0e2bb6b659a328b431e2cf
1 /* Copyright (c) 1993-2003
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
24 #include <sys/types.h>
26 #include "config.h"
27 #include "screen.h"
28 #include "extern.h"
30 #ifdef ENCODINGS
32 extern unsigned char *null;
33 extern struct display *display, *displays;
34 extern struct layer *flayer;
36 extern char *screenencodings;
38 static int encmatch __P((char *, char *));
39 # ifdef UTF8
40 static int recode_char __P((int, int, int));
41 static int recode_char_to_encoding __P((int, int));
42 static void comb_tofront __P((int, int));
43 # ifdef DW_CHARS
44 static int recode_char_dw __P((int, int *, int, int));
45 static int recode_char_dw_to_encoding __P((int, int *, int));
46 # endif
47 # endif
49 struct encoding {
50 char *name;
51 char *charsets;
52 int deffont;
53 int usegr;
54 int noc1;
55 char *fontlist;
58 /* big5 font: ^X */
59 /* KOI8-R font: 96 ! */
60 /* CP1251 font: 96 ? */
62 struct encoding encodings[] = {
63 { "C", 0, 0, 0, 0, 0 },
64 { "eucJP", "B\002I\00401", 0, 1, 0, "\002\004I" },
65 { "SJIS", "BIBB01", 0, 1, 1, "\002I" },
66 { "eucKR", "B\003BB01", 0, 1, 0, "\003" },
67 { "eucCN", "B\001BB01", 0, 1, 0, "\001" },
68 { "Big5", "B\030BB01", 0, 1, 0, "\030" },
69 { "KOI8-R", 0, 0x80|'!', 0, 1, 0 },
70 { "CP1251", 0, 0x80|'?', 0, 1, 0 },
71 { "UTF-8", 0, -1, 0, 0, 0 },
72 { "ISO8859-2", 0, 0x80|'B', 0, 0, 0 },
73 { "ISO8859-3", 0, 0x80|'C', 0, 0, 0 },
74 { "ISO8859-4", 0, 0x80|'D', 0, 0, 0 },
75 { "ISO8859-5", 0, 0x80|'L', 0, 0, 0 },
76 { "ISO8859-6", 0, 0x80|'G', 0, 0, 0 },
77 { "ISO8859-7", 0, 0x80|'F', 0, 0, 0 },
78 { "ISO8859-8", 0, 0x80|'H', 0, 0, 0 },
79 { "ISO8859-9", 0, 0x80|'M', 0, 0, 0 },
80 { "ISO8859-10", 0, 0x80|'V', 0, 0, 0 },
81 { "ISO8859-15", 0, 0x80|'b', 0, 0, 0 },
82 { "jis", 0, 0, 0, 0, "\002\004I" },
83 { "GBK", "B\031BB01", 0x80|'b', 1, 1, "\031" }
86 #ifdef UTF8
88 static unsigned short builtin_tabs[][2] = {
89 { 0x30, 0 }, /* 0: special graphics (line drawing) */
90 { 0x005f, 0x25AE },
91 { 0x0060, 0x25C6 },
92 { 0x0061, 0x2592 },
93 { 0x0062, 0x2409 },
94 { 0x0063, 0x240C },
95 { 0x0064, 0x240D },
96 { 0x0065, 0x240A },
97 { 0x0066, 0x00B0 },
98 { 0x0067, 0x00B1 },
99 { 0x0068, 0x2424 },
100 { 0x0069, 0x240B },
101 { 0x006a, 0x2518 },
102 { 0x006b, 0x2510 },
103 { 0x006c, 0x250C },
104 { 0x006d, 0x2514 },
105 { 0x006e, 0x253C },
106 { 0x006f, 0x23BA },
107 { 0x0070, 0x23BB },
108 { 0x0071, 0x2500 },
109 { 0x0072, 0x23BC },
110 { 0x0073, 0x23BD },
111 { 0x0074, 0x251C },
112 { 0x0075, 0x2524 },
113 { 0x0076, 0x2534 },
114 { 0x0077, 0x252C },
115 { 0x0078, 0x2502 },
116 { 0x0079, 0x2264 },
117 { 0x007a, 0x2265 },
118 { 0x007b, 0x03C0 },
119 { 0x007c, 0x2260 },
120 { 0x007d, 0x00A3 },
121 { 0x007e, 0x00B7 },
122 { 0, 0},
124 { 0x34, 0 }, /* 4: Dutch */
125 { 0x0023, 0x00a3 },
126 { 0x0040, 0x00be },
127 { 0x005b, 0x00ff },
128 { 0x005c, 0x00bd },
129 { 0x005d, 0x007c },
130 { 0x007b, 0x00a8 },
131 { 0x007c, 0x0066 },
132 { 0x007d, 0x00bc },
133 { 0x007e, 0x00b4 },
134 { 0, 0},
136 { 0x35, 0 }, /* 5: Finnish */
137 { 0x005b, 0x00c4 },
138 { 0x005c, 0x00d6 },
139 { 0x005d, 0x00c5 },
140 { 0x005e, 0x00dc },
141 { 0x0060, 0x00e9 },
142 { 0x007b, 0x00e4 },
143 { 0x007c, 0x00f6 },
144 { 0x007d, 0x00e5 },
145 { 0x007e, 0x00fc },
146 { 0, 0},
148 { 0x36, 0 }, /* 6: Norwegian/Danish */
149 { 0x0040, 0x00c4 },
150 { 0x005b, 0x00c6 },
151 { 0x005c, 0x00d8 },
152 { 0x005d, 0x00c5 },
153 { 0x005e, 0x00dc },
154 { 0x0060, 0x00e4 },
155 { 0x007b, 0x00e6 },
156 { 0x007c, 0x00f8 },
157 { 0x007d, 0x00e5 },
158 { 0x007e, 0x00fc },
159 { 0, 0},
161 { 0x37, 0 }, /* 7: Swedish */
162 { 0x0040, 0x00c9 },
163 { 0x005b, 0x00c4 },
164 { 0x005c, 0x00d6 },
165 { 0x005d, 0x00c5 },
166 { 0x005e, 0x00dc },
167 { 0x0060, 0x00e9 },
168 { 0x007b, 0x00e4 },
169 { 0x007c, 0x00f6 },
170 { 0x007d, 0x00e5 },
171 { 0x007e, 0x00fc },
172 { 0, 0},
174 { 0x3d, 0}, /* =: Swiss */
175 { 0x0023, 0x00f9 },
176 { 0x0040, 0x00e0 },
177 { 0x005b, 0x00e9 },
178 { 0x005c, 0x00e7 },
179 { 0x005d, 0x00ea },
180 { 0x005e, 0x00ee },
181 { 0x005f, 0x00e8 },
182 { 0x0060, 0x00f4 },
183 { 0x007b, 0x00e4 },
184 { 0x007c, 0x00f6 },
185 { 0x007d, 0x00fc },
186 { 0x007e, 0x00fb },
187 { 0, 0},
189 { 0x41, 0}, /* A: UK */
190 { 0x0023, 0x00a3 },
191 { 0, 0},
193 { 0x4b, 0}, /* K: German */
194 { 0x0040, 0x00a7 },
195 { 0x005b, 0x00c4 },
196 { 0x005c, 0x00d6 },
197 { 0x005d, 0x00dc },
198 { 0x007b, 0x00e4 },
199 { 0x007c, 0x00f6 },
200 { 0x007d, 0x00fc },
201 { 0x007e, 0x00df },
202 { 0, 0},
204 { 0x51, 0}, /* Q: French Canadian */
205 { 0x0040, 0x00e0 },
206 { 0x005b, 0x00e2 },
207 { 0x005c, 0x00e7 },
208 { 0x005d, 0x00ea },
209 { 0x005e, 0x00ee },
210 { 0x0060, 0x00f4 },
211 { 0x007b, 0x00e9 },
212 { 0x007c, 0x00f9 },
213 { 0x007d, 0x00e8 },
214 { 0x007e, 0x00fb },
215 { 0, 0},
217 { 0x52, 0}, /* R: French */
218 { 0x0023, 0x00a3 },
219 { 0x0040, 0x00e0 },
220 { 0x005b, 0x00b0 },
221 { 0x005c, 0x00e7 },
222 { 0x005d, 0x00a7 },
223 { 0x007b, 0x00e9 },
224 { 0x007c, 0x00f9 },
225 { 0x007d, 0x00e8 },
226 { 0x007e, 0x00a8 },
227 { 0, 0},
229 { 0x59, 0}, /* Y: Italian */
230 { 0x0023, 0x00a3 },
231 { 0x0040, 0x00a7 },
232 { 0x005b, 0x00b0 },
233 { 0x005c, 0x00e7 },
234 { 0x005d, 0x00e9 },
235 { 0x0060, 0x00f9 },
236 { 0x007b, 0x00e0 },
237 { 0x007c, 0x00f2 },
238 { 0x007d, 0x00e8 },
239 { 0x007e, 0x00ec },
240 { 0, 0},
242 { 0x5a, 0}, /* Z: Spanish */
243 { 0x0023, 0x00a3 },
244 { 0x0040, 0x00a7 },
245 { 0x005b, 0x00a1 },
246 { 0x005c, 0x00d1 },
247 { 0x005d, 0x00bf },
248 { 0x007b, 0x00b0 },
249 { 0x007c, 0x00f1 },
250 { 0x007d, 0x00e7 },
251 { 0, 0},
253 { 0xe2, 0}, /* 96-b: ISO-8859-15 */
254 { 0x00a4, 0x20ac },
255 { 0x00a6, 0x0160 },
256 { 0x00a8, 0x0161 },
257 { 0x00b4, 0x017D },
258 { 0x00b8, 0x017E },
259 { 0x00bc, 0x0152 },
260 { 0x00bd, 0x0153 },
261 { 0x00be, 0x0178 },
262 { 0, 0},
264 { 0x4a, 0}, /* J: JIS 0201 Roman */
265 { 0x005c, 0x00a5 },
266 { 0x007e, 0x203e },
267 { 0, 0},
269 { 0x49, 0}, /* I: halfwidth katakana */
270 { 0x0021, 0xff61 },
271 { 0x005f|0x8000, 0xff9f },
272 { 0, 0},
274 { 0, 0}
277 struct recodetab
279 unsigned short (*tab)[2];
280 int flags;
283 #define RECODETAB_ALLOCED 1
284 #define RECODETAB_BUILTIN 2
285 #define RECODETAB_TRIED 4
287 static struct recodetab recodetabs[256];
289 void
290 InitBuiltinTabs()
292 unsigned short (*p)[2];
293 for (p = builtin_tabs; (*p)[0]; p++)
295 recodetabs[(*p)[0]].flags = RECODETAB_BUILTIN;
296 recodetabs[(*p)[0]].tab = p + 1;
297 p++;
298 while((*p)[0])
299 p++;
303 static int
304 recode_char(c, to_utf, font)
305 int c, to_utf, font;
307 int f;
308 unsigned short (*p)[2];
310 if (to_utf)
312 if (c < 256)
313 return c;
314 f = (c >> 8) & 0xff;
315 c &= 0xff;
316 /* map aliases to keep the table small */
317 switch (f)
319 case 'C':
320 f ^= ('C' ^ '5');
321 break;
322 case 'E':
323 f ^= ('E' ^ '6');
324 break;
325 case 'H':
326 f ^= ('H' ^ '7');
327 break;
328 default:
329 break;
331 p = recodetabs[f].tab;
332 if (p == 0 && recodetabs[f].flags == 0)
334 LoadFontTranslation(f, 0);
335 p = recodetabs[f].tab;
337 if (p)
338 for (; (*p)[0]; p++)
340 if ((p[0][0] & 0x8000) && (c <= (p[0][0] & 0x7fff)) && c >= p[-1][0])
341 return c - p[-1][0] + p[-1][1];
342 if ((*p)[0] == c)
343 return (*p)[1];
345 return c & 0xff; /* map to latin1 */
347 if (font == -1)
349 if (c < 256)
350 return c; /* latin1 */
351 for (font = 32; font < 128; font++)
353 p = recodetabs[font].tab;
354 if (p)
355 for (; (*p)[1]; p++)
357 if ((p[0][0] & 0x8000) && c <= p[0][1] && c >= p[-1][1])
358 return (c - p[-1][1] + p[-1][0]) | (font << 8);
359 if ((*p)[1] == c)
360 return (*p)[0] | (font << 8);
363 return '?';
365 if (c < 128 && (font & 128) != 0)
366 return c;
367 if (font >= 32)
369 p = recodetabs[font].tab;
370 if (p == 0 && recodetabs[font].flags == 0)
372 LoadFontTranslation(font, 0);
373 p = recodetabs[font].tab;
375 if (p)
376 for (; (*p)[1]; p++)
378 if ((p[0][0] & 0x8000) && c <= p[0][1] && c >= p[-1][1])
379 return (c - p[-1][1] + p[-1][0]) | (font & 128 ? 0 : font << 8);
380 if ((*p)[1] == c)
381 return (*p)[0] | (font & 128 ? 0 : font << 8);
384 return -1;
388 #ifdef DW_CHARS
389 static int
390 recode_char_dw(c, c2p, to_utf, font)
391 int c, *c2p, to_utf, font;
393 int f;
394 unsigned short (*p)[2];
396 if (to_utf)
398 f = (c >> 8) & 0xff;
399 c = (c & 255) << 8 | (*c2p & 255);
400 *c2p = 0xffff;
401 p = recodetabs[f].tab;
402 if (p == 0 && recodetabs[f].flags == 0)
404 LoadFontTranslation(f, 0);
405 p = recodetabs[f].tab;
407 if (p)
408 for (; (*p)[0]; p++)
409 if ((*p)[0] == c)
411 #ifdef DW_CHARS
412 if (!utf8_isdouble((*p)[1]))
413 *c2p = ' ';
414 #endif
415 return (*p)[1];
417 return UCS_REPL_DW;
419 if (font == -1)
421 for (font = 0; font < 030; font++)
423 p = recodetabs[font].tab;
424 if (p)
425 for (; (*p)[1]; p++)
426 if ((*p)[1] == c)
428 *c2p = ((*p)[0] & 255) | font << 8 | 0x8000;
429 return ((*p)[0] >> 8) | font << 8;
432 *c2p = '?';
433 return '?';
435 if (font < 32)
437 p = recodetabs[font].tab;
438 if (p == 0 && recodetabs[font].flags == 0)
440 LoadFontTranslation(font, 0);
441 p = recodetabs[font].tab;
443 if (p)
444 for (; (*p)[1]; p++)
445 if ((*p)[1] == c)
447 *c2p = ((*p)[0] & 255) | font << 8 | 0x8000;
448 return ((*p)[0] >> 8) | font << 8;
451 return -1;
453 #endif
455 static int
456 recode_char_to_encoding(c, encoding)
457 int c, encoding;
459 char *fp;
460 int x;
462 if (encoding == UTF8)
463 return recode_char(c, 1, -1);
464 if ((fp = encodings[encoding].fontlist) != 0)
465 while(*fp)
466 if ((x = recode_char(c, 0, (unsigned char)*fp++)) != -1)
467 return x;
468 if (encodings[encoding].deffont)
469 if ((x = recode_char(c, 0, encodings[encoding].deffont)) != -1)
470 return x;
471 return recode_char(c, 0, -1);
474 #ifdef DW_CHARS
475 static int
476 recode_char_dw_to_encoding(c, c2p, encoding)
477 int c, *c2p, encoding;
479 char *fp;
480 int x;
482 if (encoding == UTF8)
483 return recode_char_dw(c, c2p, 1, -1);
484 if ((fp = encodings[encoding].fontlist) != 0)
485 while(*fp)
486 if ((x = recode_char_dw(c, c2p, 0, (unsigned char)*fp++)) != -1)
487 return x;
488 if (encodings[encoding].deffont)
489 if ((x = recode_char_dw(c, c2p, 0, encodings[encoding].deffont)) != -1)
490 return x;
491 return recode_char_dw(c, c2p, 0, -1);
493 #endif
496 struct mchar *
497 recode_mchar(mc, from, to)
498 struct mchar *mc;
499 int from, to;
501 static struct mchar rmc;
502 int c;
504 debug3("recode_mchar %02x from %d to %d\n", mc->image, from, to);
505 if (from == to || (from != UTF8 && to != UTF8))
506 return mc;
507 rmc = *mc;
508 if (rmc.font == 0 && from != UTF8)
509 rmc.font = encodings[from].deffont;
510 if (rmc.font == 0) /* latin1 is the same in unicode */
511 return mc;
512 c = rmc.image | (rmc.font << 8);
513 #ifdef DW_CHARS
514 if (rmc.mbcs)
516 int c2 = rmc.mbcs;
517 c = recode_char_dw_to_encoding(c, &c2, to);
518 rmc.mbcs = c2;
520 else
521 #endif
522 c = recode_char_to_encoding(c, to);
523 rmc.image = c & 255;
524 rmc.font = c >> 8 & 255;
525 return &rmc;
528 struct mline *
529 recode_mline(ml, w, from, to)
530 struct mline *ml;
531 int w;
532 int from, to;
534 static int maxlen;
535 static int last;
536 static struct mline rml[2], *rl;
537 int i, c;
539 if (from == to || (from != UTF8 && to != UTF8) || w == 0)
540 return ml;
541 if (ml->font == null && encodings[from].deffont == 0)
542 return ml;
543 if (w > maxlen)
545 for (i = 0; i < 2; i++)
547 if (rml[i].image == 0)
548 rml[i].image = malloc(w);
549 else
550 rml[i].image = realloc(rml[i].image, w);
551 if (rml[i].font == 0)
552 rml[i].font = malloc(w);
553 else
554 rml[i].font = realloc(rml[i].font, w);
555 if (rml[i].image == 0 || rml[i].font == 0)
557 maxlen = 0;
558 return ml; /* sorry */
561 maxlen = w;
564 debug("recode_mline: from\n");
565 for (i = 0; i < w; i++)
566 debug1("%c", "0123456789abcdef"[(ml->image[i] >> 4) & 15]);
567 debug("\n");
568 for (i = 0; i < w; i++)
569 debug1("%c", "0123456789abcdef"[(ml->image[i] ) & 15]);
570 debug("\n");
571 for (i = 0; i < w; i++)
572 debug1("%c", "0123456789abcdef"[(ml->font[i] >> 4) & 15]);
573 debug("\n");
574 for (i = 0; i < w; i++)
575 debug1("%c", "0123456789abcdef"[(ml->font[i] ) & 15]);
576 debug("\n");
578 rl = rml + last;
579 rl->attr = ml->attr;
580 #ifdef COLOR
581 rl->color = ml->color;
582 # ifdef COLORS256
583 rl->colorx = ml->colorx;
584 # endif
585 #endif
586 for (i = 0; i < w; i++)
588 c = ml->image[i] | (ml->font[i] << 8);
589 if (from != UTF8 && c < 256)
590 c |= encodings[from].deffont << 8;
591 #ifdef DW_CHARS
592 if ((from != UTF8 && (c & 0x1f00) != 0 && (c & 0xe000) == 0) || (from == UTF8 && utf8_isdouble(c)))
594 if (i + 1 == w)
595 c = '?';
596 else
598 int c2;
599 i++;
600 c2 = ml->image[i] | (ml->font[i] << 8);
601 c = recode_char_dw_to_encoding(c, &c2, to);
602 rl->font[i - 1] = c >> 8 & 255;
603 rl->image[i - 1] = c & 255;
604 c = c2;
607 else
608 #endif
609 c = recode_char_to_encoding(c, to);
610 rl->image[i] = c & 255;
611 rl->font[i] = c >> 8 & 255;
613 last ^= 1;
614 debug("recode_mline: to\n");
615 for (i = 0; i < w; i++)
616 debug1("%c", "0123456789abcdef"[(rl->image[i] >> 4) & 15]);
617 debug("\n");
618 for (i = 0; i < w; i++)
619 debug1("%c", "0123456789abcdef"[(rl->image[i] ) & 15]);
620 debug("\n");
621 for (i = 0; i < w; i++)
622 debug1("%c", "0123456789abcdef"[(rl->font[i] >> 4) & 15]);
623 debug("\n");
624 for (i = 0; i < w; i++)
625 debug1("%c", "0123456789abcdef"[(rl->font[i] ) & 15]);
626 debug("\n");
627 return rl;
630 struct combchar {
631 unsigned short c1;
632 unsigned short c2;
633 unsigned short next;
634 unsigned short prev;
636 struct combchar **combchars;
638 void
639 AddUtf8(c)
640 int c;
642 ASSERT(D_encoding == UTF8);
643 if (c >= 0xd800 && c < 0xe000 && combchars && combchars[c - 0xd800])
645 AddUtf8(combchars[c - 0xd800]->c1);
646 c = combchars[c - 0xd800]->c2;
648 if (c >= 0x800)
650 AddChar((c & 0xf000) >> 12 | 0xe0);
651 c = (c & 0x0fff) | 0x1000;
653 if (c >= 0x80)
655 AddChar((c & 0x1fc0) >> 6 ^ 0xc0);
656 c = (c & 0x3f) | 0x80;
658 AddChar(c);
662 ToUtf8_comb(p, c)
663 char *p;
664 int c;
666 int l;
668 if (c >= 0xd800 && c < 0xe000 && combchars && combchars[c - 0xd800])
670 l = ToUtf8_comb(p, combchars[c - 0xd800]->c1);
671 return l + ToUtf8(p ? p + l : 0, combchars[c - 0xd800]->c2);
673 return ToUtf8(p, c);
677 ToUtf8(p, c)
678 char *p;
679 int c;
681 int l = 1;
682 if (c >= 0x800)
684 if (p)
685 *p++ = (c & 0xf000) >> 12 | 0xe0;
686 l++;
687 c = (c & 0x0fff) | 0x1000;
689 if (c >= 0x80)
691 if (p)
692 *p++ = (c & 0x1fc0) >> 6 ^ 0xc0;
693 l++;
694 c = (c & 0x3f) | 0x80;
696 if (p)
697 *p++ = c;
698 return l;
702 * returns:
703 * -1: need more bytes, sequence not finished
704 * -2: corrupt sequence found, redo last char
705 * >= 0: decoded character
708 FromUtf8(c, utf8charp)
709 int c, *utf8charp;
711 int utf8char = *utf8charp;
712 if (utf8char)
714 if ((c & 0xc0) != 0x80)
716 *utf8charp = 0;
717 return -2; /* corrupt sequence! */
719 else
720 c = (c & 0x3f) | (utf8char << 6);
721 if (!(utf8char & 0x40000000))
723 /* check for overlong sequences */
724 if ((c & 0x820823e0) == 0x80000000)
725 c = 0xfdffffff;
726 else if ((c & 0x020821f0) == 0x02000000)
727 c = 0xfff7ffff;
728 else if ((c & 0x000820f8) == 0x00080000)
729 c = 0xffffd000;
730 else if ((c & 0x0000207c) == 0x00002000)
731 c = 0xffffff70;
734 else
736 /* new sequence */
737 if (c >= 0xfe)
738 c = UCS_REPL;
739 else if (c >= 0xfc)
740 c = (c & 0x01) | 0xbffffffc; /* 5 bytes to follow */
741 else if (c >= 0xf8)
742 c = (c & 0x03) | 0xbfffff00; /* 4 */
743 else if (c >= 0xf0)
744 c = (c & 0x07) | 0xbfffc000; /* 3 */
745 else if (c >= 0xe0)
746 c = (c & 0x0f) | 0xbff00000; /* 2 */
747 else if (c >= 0xc2)
748 c = (c & 0x1f) | 0xfc000000; /* 1 */
749 else if (c >= 0xc0)
750 c = 0xfdffffff; /* overlong */
751 else if (c >= 0x80)
752 c = UCS_REPL;
754 *utf8charp = utf8char = (c & 0x80000000) ? c : 0;
755 if (utf8char)
756 return -1;
757 if (c & 0xffff0000)
758 c = UCS_REPL; /* sorry, only know 16bit Unicode */
759 if (c >= 0xd800 && (c <= 0xdfff || c == 0xfffe || c == 0xffff))
760 c = UCS_REPL; /* illegal code */
761 return c;
765 void
766 WinSwitchEncoding(p, encoding)
767 struct win *p;
768 int encoding;
770 int i, j, c;
771 struct mline *ml;
772 struct display *d;
773 struct canvas *cv;
774 struct layer *oldflayer;
776 if ((p->w_encoding == UTF8) == (encoding == UTF8))
778 p->w_encoding = encoding;
779 return;
781 oldflayer = flayer;
782 for (d = displays; d; d = d->d_next)
783 for (cv = d->d_cvlist; cv; cv = cv->c_next)
784 if (p == Layer2Window(cv->c_layer))
786 flayer = cv->c_layer;
787 while(flayer->l_next)
789 if (oldflayer == flayer)
790 oldflayer = flayer->l_next;
791 ExitOverlayPage();
794 flayer = oldflayer;
795 for (j = 0; j < p->w_height + p->w_histheight; j++)
797 #ifdef COPY_PASTE
798 ml = j < p->w_height ? &p->w_mlines[j] : &p->w_hlines[j - p->w_height];
799 #else
800 ml = &p->w_mlines[j];
801 #endif
802 if (ml->font == null && encodings[p->w_encoding].deffont == 0)
803 continue;
804 for (i = 0; i < p->w_width; i++)
806 c = ml->image[i] | (ml->font[i] << 8);
807 if (p->w_encoding != UTF8 && c < 256)
808 c |= encodings[p->w_encoding].deffont << 8;
809 if (c < 256)
810 continue;
811 if (ml->font == null)
813 if ((ml->font = (unsigned char *)malloc(p->w_width + 1)) == 0)
815 ml->font = null;
816 break;
818 bzero(ml->font, p->w_width + 1);
820 #ifdef DW_CHARS
821 if ((p->w_encoding != UTF8 && (c & 0x1f00) != 0 && (c & 0xe000) == 0) || (p->w_encoding == UTF8 && utf8_isdouble(c)))
823 if (i + 1 == p->w_width)
824 c = '?';
825 else
827 int c2;
828 i++;
829 c2 = ml->image[i] | (ml->font[i] << 8);
830 c = recode_char_dw_to_encoding(c, &c2, encoding);
831 ml->font[i - 1] = c >> 8 & 255;
832 ml->image[i - 1] = c & 255;
833 c = c2;
836 else
837 #endif
838 c = recode_char_to_encoding(c, encoding);
839 ml->image[i] = c & 255;
840 ml->font[i] = c >> 8 & 255;
843 p->w_encoding = encoding;
844 return;
847 #ifdef DW_CHARS
849 utf8_isdouble(c)
850 int c;
852 return
853 (c >= 0x1100 &&
854 (c <= 0x115f || /* Hangul Jamo init. consonants */
855 (c >= 0x2e80 && c <= 0xa4cf && (c & ~0x0011) != 0x300a &&
856 c != 0x303f) || /* CJK ... Yi */
857 (c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
858 (c >= 0xdf00 && c <= 0xdfff) || /* dw combining sequence */
859 (c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
860 (c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
861 (c >= 0xff00 && c <= 0xff5f) || /* Fullwidth Forms */
862 (c >= 0xffe0 && c <= 0xffe6) ||
863 (c >= 0x20000 && c <= 0x2ffff)));
865 #endif
868 utf8_iscomb(c)
869 int c;
871 /* taken from Markus Kuhn's wcwidth */
872 static struct {
873 unsigned short first;
874 unsigned short last;
875 } combining[] = {
876 { 0x0300, 0x034F }, { 0x0360, 0x036F }, { 0x0483, 0x0486 },
877 { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
878 { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
879 { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
880 { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
881 { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
882 { 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },
883 { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },
884 { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
885 { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
886 { 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
887 { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },
888 { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },
889 { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 },
890 { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 },
891 { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 },
892 { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 },
893 { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },
894 { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
895 { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA },
896 { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 },
897 { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 },
898 { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD },
899 { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },
900 { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 },
901 { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC },
902 { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 },
903 { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 },
904 { 0x1160, 0x11FF }, { 0x1712, 0x1714 }, { 0x1732, 0x1734 },
905 { 0x1752, 0x1753 }, { 0x1772, 0x1773 }, { 0x17B7, 0x17BD },
906 { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x180B, 0x180E },
907 { 0x18A9, 0x18A9 }, { 0x200B, 0x200F }, { 0x202A, 0x202E },
908 { 0x2060, 0x2063 }, { 0x206A, 0x206F }, { 0x20D0, 0x20EA },
909 { 0x302A, 0x302F }, { 0x3099, 0x309A }, { 0xFB1E, 0xFB1E },
910 { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF },
911 { 0xFFF9, 0xFFFB }
913 int mid, min = 0, max = sizeof(combining)/sizeof(*combining) - 1;
915 if (c < 0x0300 || c > 0xfffb)
916 return 0;
917 while (max >= min)
919 mid = (min + max) / 2;
920 if (c > combining[mid].last)
921 min = mid + 1;
922 else if (c < combining[mid].first)
923 max = mid - 1;
924 else
925 return 1;
927 return 0;
930 static void
931 comb_tofront(root, i)
932 int root, i;
934 for (;;)
936 debug1("bring to front: %x\n", i);
937 combchars[combchars[i]->prev]->next = combchars[i]->next;
938 combchars[combchars[i]->next]->prev = combchars[i]->prev;
939 combchars[i]->next = combchars[root]->next;
940 combchars[i]->prev = root;
941 combchars[combchars[root]->next]->prev = i;
942 combchars[root]->next = i;
943 i = combchars[i]->c1;
944 if (i < 0xd800 || i >= 0xe000)
945 return;
946 i -= 0xd800;
950 void
951 utf8_handle_comb(c, mc)
952 int c;
953 struct mchar *mc;
955 int root, i, c1;
956 int isdouble;
958 c1 = mc->image | (mc->font << 8);
959 isdouble = c1 >= 0x1100 && utf8_isdouble(c1);
960 if (!combchars)
962 combchars = (struct combchar **)malloc(sizeof(struct combchar *) * 0x802);
963 if (!combchars)
964 return;
965 bzero((char *)combchars, sizeof(struct combchar *) * 0x802);
966 combchars[0x800] = (struct combchar *)malloc(sizeof(struct combchar));
967 combchars[0x801] = (struct combchar *)malloc(sizeof(struct combchar));
968 if (!combchars[0x800] || !combchars[0x801])
970 if (combchars[0x800])
971 free(combchars[0x800]);
972 if (combchars[0x801])
973 free(combchars[0x801]);
974 free(combchars);
975 return;
977 combchars[0x800]->c1 = 0x000;
978 combchars[0x800]->c2 = 0x700;
979 combchars[0x800]->next = 0x800;
980 combchars[0x800]->prev = 0x800;
981 combchars[0x801]->c1 = 0x700;
982 combchars[0x801]->c2 = 0x800;
983 combchars[0x801]->next = 0x801;
984 combchars[0x801]->prev = 0x801;
986 root = isdouble ? 0x801 : 0x800;
987 for (i = combchars[root]->c1; i < combchars[root]->c2; i++)
989 if (!combchars[i])
990 break;
991 if (combchars[i]->c1 == c1 && combchars[i]->c2 == c)
992 break;
994 if (i == combchars[root]->c2)
996 /* full, recycle old entry */
997 if (c1 >= 0xd800 && c1 < 0xe000)
998 comb_tofront(root, c1 - 0xd800);
999 i = combchars[root]->prev;
1000 if (c1 == i + 0xd800)
1002 /* completely full, can't recycle */
1003 debug("utf8_handle_comp: completely full!\n");
1004 mc->image = '?';
1005 mc->font = 0;
1006 return;
1008 /* FIXME: delete old char from all buffers */
1010 else if (!combchars[i])
1012 combchars[i] = (struct combchar *)malloc(sizeof(struct combchar));
1013 if (!combchars[i])
1014 return;
1015 combchars[i]->prev = i;
1016 combchars[i]->next = i;
1018 combchars[i]->c1 = c1;
1019 combchars[i]->c2 = c;
1020 mc->image = i & 0xff;
1021 mc->font = (i >> 8) + 0xd8;
1022 debug3("combinig char %x %x -> %x\n", c1, c, i + 0xd800);
1023 comb_tofront(root, i);
1026 #else /* !UTF8 */
1028 void
1029 WinSwitchEncoding(p, encoding)
1030 struct win *p;
1031 int encoding;
1033 p->w_encoding = encoding;
1034 return;
1037 #endif /* UTF8 */
1039 static int
1040 encmatch(s1, s2)
1041 char *s1;
1042 char *s2;
1044 int c1, c2;
1047 c1 = (unsigned char)*s1;
1048 if (c1 >= 'A' && c1 <= 'Z')
1049 c1 += 'a' - 'A';
1050 if (!(c1 >= 'a' && c1 <= 'z') && !(c1 >= '0' && c1 <= '9'))
1052 s1++;
1053 continue;
1055 c2 = (unsigned char)*s2;
1056 if (c2 >= 'A' && c2 <= 'Z')
1057 c2 += 'a' - 'A';
1058 if (!(c2 >= 'a' && c2 <= 'z') && !(c2 >= '0' && c2 <= '9'))
1060 s2++;
1061 continue;
1063 if (c1 != c2)
1064 return 0;
1065 s1++;
1066 s2++;
1068 while(c1);
1069 return 1;
1073 FindEncoding(name)
1074 char *name;
1076 int encoding;
1078 debug1("FindEncoding %s\n", name);
1079 if (name == 0 || *name == 0)
1080 return 0;
1081 if (encmatch(name, "euc"))
1082 name = "eucJP";
1083 if (encmatch(name, "off") || encmatch(name, "iso8859-1"))
1084 return 0;
1085 #ifndef UTF8
1086 if (encmatch(name, "UTF-8"))
1087 return -1;
1088 #endif
1089 for (encoding = 0; encoding < (int)(sizeof(encodings)/sizeof(*encodings)); encoding++)
1090 if (encmatch(name, encodings[encoding].name))
1092 #ifdef UTF8
1093 LoadFontTranslationsForEncoding(encoding);
1094 #endif
1095 return encoding;
1097 return -1;
1100 char *
1101 EncodingName(encoding)
1102 int encoding;
1104 if (encoding >= (int)(sizeof(encodings)/sizeof(*encodings)))
1105 return 0;
1106 return encodings[encoding].name;
1110 EncodingDefFont(encoding)
1111 int encoding;
1113 return encodings[encoding].deffont;
1116 void
1117 ResetEncoding(p)
1118 struct win *p;
1120 char *c;
1121 int encoding = p->w_encoding;
1123 c = encodings[encoding].charsets;
1124 if (c)
1125 SetCharsets(p, c);
1126 #ifdef UTF8
1127 LoadFontTranslationsForEncoding(encoding);
1128 #endif
1129 if (encodings[encoding].usegr)
1131 p->w_gr = 2;
1132 p->w_FontE = encodings[encoding].charsets[1];
1134 else
1135 p->w_FontE = 0;
1136 if (encodings[encoding].noc1)
1137 p->w_c1 = 0;
1141 DecodeChar(c, encoding, statep)
1142 int c;
1143 int encoding;
1144 int *statep;
1146 int t;
1148 debug2("Decoding char %02x for encoding %d\n", c, encoding);
1149 #ifdef UTF8
1150 if (encoding == UTF8)
1151 return FromUtf8(c, statep);
1152 #endif
1153 if (encoding == SJIS)
1155 if (!*statep)
1157 if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))
1159 *statep = c;
1160 return -1;
1162 if (c < 0x80)
1163 return c;
1164 return c | (KANA << 16);
1166 t = c;
1167 c = *statep;
1168 *statep = 0;
1169 if (0x40 <= t && t <= 0xfc && t != 0x7f)
1171 if (c <= 0x9f)
1172 c = (c - 0x81) * 2 + 0x21;
1173 else
1174 c = (c - 0xc1) * 2 + 0x21;
1175 if (t <= 0x7e)
1176 t -= 0x1f;
1177 else if (t <= 0x9e)
1178 t -= 0x20;
1179 else
1180 t -= 0x7e, c++;
1181 return (c << 8) | t | (KANJI << 16);
1183 return t;
1185 if (encoding == EUC_JP || encoding == EUC_KR || encoding == EUC_CN)
1187 if (!*statep)
1189 if (c & 0x80)
1191 *statep = c;
1192 return -1;
1194 return c;
1196 t = c;
1197 c = *statep;
1198 *statep = 0;
1199 if (encoding == EUC_JP)
1201 if (c == 0x8e)
1202 return t | (KANA << 16);
1203 if (c == 0x8f)
1205 *statep = t | (KANJI0212 << 8);
1206 return -1;
1209 c &= 0xff7f;
1210 t &= 0x7f;
1211 c = c << 8 | t;
1212 if (encoding == EUC_KR)
1213 return c | (3 << 16);
1214 if (encoding == EUC_CN)
1215 return c | (1 << 16);
1216 if (c & (KANJI0212 << 16))
1217 return c;
1218 else
1219 return c | (KANJI << 16);
1221 if (encoding == BIG5 || encoding == GBK)
1223 if (!*statep)
1225 if (c & 0x80)
1227 if (encoding == GBK && c == 0x80)
1228 return 0xa4 | (('b'|0x80) << 16);
1229 *statep = c;
1230 return -1;
1232 return c;
1234 t = c;
1235 c = *statep;
1236 *statep = 0;
1237 c &= 0x7f;
1238 return c << 8 | t | (encoding == BIG5 ? 030 << 16 : 031 << 16);
1240 return c | (encodings[encoding].deffont << 16);
1244 EncodeChar(bp, c, encoding, fontp)
1245 char *bp;
1246 int c;
1247 int encoding;
1248 int *fontp;
1250 int t, f, l;
1252 debug2("Encoding char %02x for encoding %d\n", c, encoding);
1253 if (c == -1 && fontp)
1255 if (*fontp == 0)
1256 return 0;
1257 if (bp)
1259 *bp++ = 033;
1260 *bp++ = '(';
1261 *bp++ = 'B';
1263 return 3;
1265 f = c >> 16;
1267 #ifdef UTF8
1268 if (encoding == UTF8)
1270 if (f)
1272 # ifdef DW_CHARS
1273 if (is_dw_font(f))
1275 int c2 = c & 0xff;
1276 c = (c >> 8 & 0xff) | (f << 8);
1277 c = recode_char_dw_to_encoding(c, &c2, encoding);
1279 else
1280 # endif
1282 c = (c & 0xff) | (f << 8);
1283 c = recode_char_to_encoding(c, encoding);
1286 return ToUtf8(bp, c);
1288 if ((c & 0xff00) && f == 0) /* is_utf8? */
1290 # ifdef DW_CHARS
1291 if (utf8_isdouble(c))
1293 int c2 = 0xffff;
1294 c = recode_char_dw_to_encoding(c, &c2, encoding);
1295 c = (c << 8) | (c2 & 0xff);
1297 else
1298 # endif
1300 c = recode_char_to_encoding(c, encoding);
1301 c = ((c & 0xff00) << 8) | (c & 0xff);
1303 debug1("Encode: char mapped from utf8 to %x\n", c);
1304 f = c >> 16;
1306 #endif
1307 if (f & 0x80) /* map special 96-fonts to latin1 */
1308 f = 0;
1310 if (encoding == SJIS)
1312 if (f == KANA)
1313 c = (c & 0xff) | 0x80;
1314 else if (f == KANJI)
1316 if (!bp)
1317 return 2;
1318 t = c & 0xff;
1319 c = (c >> 8) & 0xff;
1320 t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e;
1321 c = (c - 0x21) / 2 + ((c < 0x5f) ? 0x81 : 0xc1);
1322 *bp++ = c;
1323 *bp++ = t;
1324 return 2;
1327 if (encoding == EUC)
1329 if (f == KANA)
1331 if (bp)
1333 *bp++ = 0x8e;
1334 *bp++ = c;
1336 return 2;
1338 if (f == KANJI)
1340 if (bp)
1342 *bp++ = (c >> 8) | 0x80;
1343 *bp++ = c | 0x80;
1345 return 2;
1347 if (f == KANJI0212)
1349 if (bp)
1351 *bp++ = 0x8f;
1352 *bp++ = c >> 8;
1353 *bp++ = c;
1355 return 3;
1358 if ((encoding == EUC_KR && f == 3) || (encoding == EUC_CN && f == 1))
1360 if (bp)
1362 *bp++ = (c >> 8) | 0x80;
1363 *bp++ = c | 0x80;
1365 return 2;
1367 if ((encoding == BIG5 && f == 030) || (encoding == GBK && f == 031))
1369 if (bp)
1371 *bp++ = (c >> 8) | 0x80;
1372 *bp++ = c;
1374 return 2;
1376 if (encoding == GBK && f == 0 && c == 0xa4)
1377 c = 0x80;
1379 l = 0;
1380 if (fontp && f != *fontp)
1382 *fontp = f;
1383 if (f && f < ' ')
1385 if (bp)
1387 *bp++ = 033;
1388 *bp++ = '$';
1389 if (f > 2)
1390 *bp++ = '(';
1391 *bp++ = '@' + f;
1393 l += f > 2 ? 4 : 3;
1395 else if (f < 128)
1397 if (f == 0)
1398 f = 'B';
1399 if (bp)
1401 *bp++ = 033;
1402 *bp++ = '(';
1403 *bp++ = f;
1405 l += 3;
1408 if (c & 0xff00)
1410 if (bp)
1411 *bp++ = c >> 8;
1412 l++;
1414 if (bp)
1415 *bp++ = c;
1416 return l + 1;
1420 CanEncodeFont(encoding, f)
1421 int encoding, f;
1423 switch(encoding)
1425 #ifdef UTF8
1426 case UTF8:
1427 return 1;
1428 #endif
1429 case SJIS:
1430 return f == KANJI || f == KANA;
1431 case EUC:
1432 return f == KANJI || f == KANA || f == KANJI0212;
1433 case EUC_KR:
1434 return f == 3;
1435 case EUC_CN:
1436 return f == 1;
1437 case BIG5:
1438 return f == 030;
1439 case GBK:
1440 return f == 031;
1441 default:
1442 break;
1444 return 0;
1447 #ifdef DW_CHARS
1449 PrepareEncodedChar(c)
1450 int c;
1452 int encoding;
1453 int t = 0;
1454 int f;
1456 encoding = D_encoding;
1457 f = D_rend.font;
1458 t = D_mbcs;
1459 if (encoding == SJIS)
1461 if (f == KANA)
1462 return c | 0x80;
1463 else if (f == KANJI)
1465 t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e;
1466 c = (c - 0x21) / 2 + ((c < 0x5f) ? 0x81 : 0xc1);
1467 D_mbcs = t;
1469 return c;
1471 if (encoding == EUC)
1473 if (f == KANA)
1475 AddChar(0x8e);
1476 return c | 0x80;
1478 if (f == KANJI)
1480 D_mbcs = t | 0x80;
1481 return c | 0x80;
1483 if (f == KANJI0212)
1485 AddChar(0x8f);
1486 D_mbcs = t | 0x80;
1487 return c | 0x80;
1490 if ((encoding == EUC_KR && f == 3) || (encoding == EUC_CN && f == 1))
1492 D_mbcs = t | 0x80;
1493 return c | 0x80;
1495 if ((encoding == BIG5 && f == 030) || (encoding == GBK && f == 031))
1496 return c | 0x80;
1497 return c;
1499 #endif
1502 RecodeBuf(fbuf, flen, fenc, tenc, tbuf)
1503 unsigned char *fbuf;
1504 int flen;
1505 int fenc, tenc;
1506 unsigned char *tbuf;
1508 int c, i, j;
1509 int decstate = 0, font = 0;
1511 for (i = j = 0; i < flen; i++)
1513 c = fbuf[i];
1514 c = DecodeChar(c, fenc, &decstate);
1515 if (c == -2)
1516 i--;
1517 if (c < 0)
1518 continue;
1519 j += EncodeChar(tbuf ? (char *)tbuf + j : 0, c, tenc, &font);
1521 j += EncodeChar(tbuf ? (char *)tbuf + j : 0, -1, tenc, &font);
1522 return j;
1525 #ifdef UTF8
1527 ContainsSpecialDeffont(ml, xs, xe, encoding)
1528 struct mline *ml;
1529 int xs, xe;
1530 int encoding;
1532 unsigned char *f, *i;
1533 int c, x, dx;
1535 if (encoding == UTF8 || encodings[encoding].deffont == 0)
1536 return 0;
1537 i = ml->image + xs;
1538 f = ml->font + xs;
1539 dx = xe - xs + 1;
1540 while (dx-- > 0)
1542 if (*f++)
1543 continue;
1544 c = *i++;
1545 x = recode_char_to_encoding(c | (encodings[encoding].deffont << 8), UTF8);
1546 if (c != x)
1548 debug2("ContainsSpecialDeffont: yes %02x != %02x\n", c, x);
1549 return 1;
1552 debug("ContainsSpecialDeffont: no\n");
1553 return 0;
1558 LoadFontTranslation(font, file)
1559 int font;
1560 char *file;
1562 char buf[1024], *myfile;
1563 FILE *f;
1564 int i;
1565 int fo;
1566 int x, u, c, ok;
1567 unsigned short (*p)[2], (*tab)[2];
1569 myfile = file;
1570 if (myfile == 0)
1572 if (font == 0 || screenencodings == 0)
1573 return -1;
1574 if (strlen(screenencodings) > sizeof(buf) - 10)
1575 return -1;
1576 sprintf(buf, "%s/%02x", screenencodings, font & 0xff);
1577 myfile = buf;
1579 debug1("LoadFontTranslation: trying %s\n", myfile);
1580 if ((f = secfopen(myfile, "r")) == 0)
1581 return -1;
1582 i = ok = 0;
1583 for (;;)
1585 for(; i < 12; i++)
1586 if (getc(f) != "ScreenI2UTF8"[i])
1587 break;
1588 if (getc(f) != 0) /* format */
1589 break;
1590 fo = getc(f); /* id */
1591 if (fo == EOF)
1592 break;
1593 if (font != -1 && font != fo)
1594 break;
1595 i = getc(f);
1596 x = getc(f);
1597 if (x == EOF)
1598 break;
1599 i = i << 8 | x;
1600 getc(f);
1601 while ((x = getc(f)) && x != EOF)
1602 getc(f); /* skip font name (padded to 2 bytes) */
1603 if ((p = malloc(sizeof(*p) * (i + 1))) == 0)
1604 break;
1605 tab = p;
1606 while(i > 0)
1608 x = getc(f);
1609 x = x << 8 | getc(f);
1610 u = getc(f);
1611 c = getc(f);
1612 u = u << 8 | c;
1613 if (c == EOF)
1614 break;
1615 (*p)[0] = x;
1616 (*p)[1] = u;
1617 p++;
1618 i--;
1620 (*p)[0] = 0;
1621 (*p)[1] = 0;
1622 if (i || (tab[0][0] & 0x8000))
1624 free(tab);
1625 break;
1627 if (recodetabs[fo].tab && (recodetabs[fo].flags & RECODETAB_ALLOCED) != 0)
1628 free(recodetabs[fo].tab);
1629 recodetabs[fo].tab = tab;
1630 recodetabs[fo].flags = RECODETAB_ALLOCED;
1631 debug1("Successful load of recodetab %02x\n", fo);
1632 c = getc(f);
1633 if (c == EOF)
1635 ok = 1;
1636 break;
1638 if (c != 'S')
1639 break;
1640 i = 1;
1642 fclose(f);
1643 if (font != -1 && file == 0 && recodetabs[font].flags == 0)
1644 recodetabs[font].flags = RECODETAB_TRIED;
1645 return ok ? 0 : -1;
1648 void
1649 LoadFontTranslationsForEncoding(encoding)
1650 int encoding;
1652 char *c;
1653 int f;
1655 debug1("LoadFontTranslationsForEncoding: encoding %d\n", encoding);
1656 if ((c = encodings[encoding].fontlist) != 0)
1657 while ((f = (unsigned char)*c++) != 0)
1658 if (recodetabs[f].flags == 0)
1659 LoadFontTranslation(f, 0);
1660 f = encodings[encoding].deffont;
1661 if (f > 0 && recodetabs[f].flags == 0)
1662 LoadFontTranslation(f, 0);
1665 #endif /* UTF8 */
1667 #else /* !ENCODINGS */
1669 /* Simple version of EncodeChar to encode font changes for
1670 * copy/paste mode
1673 EncodeChar(bp, c, encoding, fontp)
1674 char *bp;
1675 int c;
1676 int encoding;
1677 int *fontp;
1679 int f, l;
1680 f = (c == -1) ? 0 : c >> 16;
1681 l = 0;
1682 if (fontp && f != *fontp)
1684 *fontp = f;
1685 if (f && f < ' ')
1687 if (bp)
1689 *bp++ = 033;
1690 *bp++ = '$';
1691 if (f > 2)
1692 *bp++ = '(';
1693 *bp++ = '@' + f;
1695 l += f > 2 ? 4 : 3;
1697 else if (f < 128)
1699 if (f == 0)
1700 f = 'B';
1701 if (bp)
1703 *bp++ = 033;
1704 *bp++ = '(';
1705 *bp++ = f;
1707 l += 3;
1710 if (c == -1)
1711 return l;
1712 if (c & 0xff00)
1714 if (bp)
1715 *bp++ = c >> 8;
1716 l++;
1718 if (bp)
1719 *bp++ = c;
1720 return l + 1;
1723 #endif /* ENCODINGS */