]> git.lyx.org Git - lyx.git/blob - 3rdparty/libiconv/1.14/lib/iso2022_jp2.h
5e3ca41555a541b072667586bd519ba6bb5fc68a
[lyx.git] / 3rdparty / libiconv / 1.14 / lib / iso2022_jp2.h
1 /*
2  * Copyright (C) 1999-2001, 2008 Free Software Foundation, Inc.
3  * This file is part of the GNU LIBICONV Library.
4  *
5  * The GNU LIBICONV Library is free software; you can redistribute it
6  * and/or modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * The GNU LIBICONV Library is distributed in the hope that it will be
11  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17  * If not, write to the Free Software Foundation, Inc., 51 Franklin Street,
18  * Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20
21 /*
22  * ISO-2022-JP-2
23  */
24
25 /* Specification: RFC 1554 */
26 /* ESC '(' 'I' for JISX0201 Katakana is an extension not found in RFC 1554 or
27    CJK.INF, but implemented in glibc-2.1 and qt-2.0. */
28
29 #define ESC 0x1b
30
31 /*
32  * The state is composed of one of the following values
33  */
34 #define STATE_ASCII             0
35 #define STATE_JISX0201ROMAN     1
36 #define STATE_JISX0201KATAKANA  2
37 #define STATE_JISX0208          3
38 #define STATE_JISX0212          4
39 #define STATE_GB2312            5
40 #define STATE_KSC5601           6
41 /*
42  * and one of the following values, << 8
43  */
44 #define STATE_G2_NONE           0
45 #define STATE_G2_ISO8859_1      1
46 #define STATE_G2_ISO8859_7      2
47
48 #define SPLIT_STATE \
49   unsigned int state1 = state & 0xff, state2 = state >> 8
50 #define COMBINE_STATE \
51   state = (state2 << 8) | state1
52
53 static int
54 iso2022_jp2_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)
55 {
56   state_t state = conv->istate;
57   SPLIT_STATE;
58   int count = 0;
59   unsigned char c;
60   for (;;) {
61     c = *s;
62     if (c == ESC) {
63       if (n < count+3)
64         goto none;
65       if (s[1] == '(') {
66         if (s[2] == 'B') {
67           state1 = STATE_ASCII;
68           s += 3; count += 3;
69           if (n < count+1)
70             goto none;
71           continue;
72         }
73         if (s[2] == 'J') {
74           state1 = STATE_JISX0201ROMAN;
75           s += 3; count += 3;
76           if (n < count+1)
77             goto none;
78           continue;
79         }
80         if (s[2] == 'I') {
81           state1 = STATE_JISX0201KATAKANA;
82           s += 3; count += 3;
83           if (n < count+1)
84             goto none;
85           continue;
86         }
87         goto ilseq;
88       }
89       if (s[1] == '$') {
90         if (s[2] == '@' || s[2] == 'B') {
91           /* We don't distinguish JIS X 0208-1978 and JIS X 0208-1983. */
92           state1 = STATE_JISX0208;
93           s += 3; count += 3;
94           if (n < count+1)
95             goto none;
96           continue;
97         }
98         if (s[2] == 'A') {
99           state1 = STATE_GB2312;
100           s += 3; count += 3;
101           if (n < count+1)
102             goto none;
103           continue;
104         }
105         if (s[2] == '(') {
106           if (n < count+4)
107             goto none;
108           if (s[3] == 'D') {
109             state1 = STATE_JISX0212;
110             s += 4; count += 4;
111             if (n < count+1)
112               goto none;
113             continue;
114           }
115           if (s[3] == 'C') {
116             state1 = STATE_KSC5601;
117             s += 4; count += 4;
118             if (n < count+1)
119               goto none;
120             continue;
121           }
122           goto ilseq;
123         }
124         goto ilseq;
125       }
126       if (s[1] == '.') {
127         if (n < count+3)
128           goto none;
129         if (s[2] == 'A') {
130           state2 = STATE_G2_ISO8859_1;
131           s += 3; count += 3;
132           if (n < count+1)
133             goto none;
134           continue;
135         }
136         if (s[2] == 'F') {
137           state2 = STATE_G2_ISO8859_7;
138           s += 3; count += 3;
139           if (n < count+1)
140             goto none;
141           continue;
142         }
143         goto ilseq;
144       }
145       if (s[1] == 'N') {
146         switch (state2) {
147           case STATE_G2_NONE:
148             goto ilseq;
149           case STATE_G2_ISO8859_1:
150             if (s[2] < 0x80) {
151               unsigned char buf = s[2]+0x80;
152               int ret = iso8859_1_mbtowc(conv,pwc,&buf,1);
153               if (ret == RET_ILSEQ)
154                 goto ilseq;
155               if (ret != 1) abort();
156               COMBINE_STATE;
157               conv->istate = state;
158               return count+3;
159             } else
160               goto ilseq;
161           case STATE_G2_ISO8859_7:
162             if (s[2] < 0x80) {
163               unsigned char buf = s[2]+0x80;
164               int ret = iso8859_7_mbtowc(conv,pwc,&buf,1);
165               if (ret == RET_ILSEQ)
166                 goto ilseq;
167               if (ret != 1) abort();
168               COMBINE_STATE;
169               conv->istate = state;
170               return count+3;
171             } else
172               goto ilseq;
173           default: abort();
174         }
175       }
176       goto ilseq;
177     }
178     break;
179   }
180   switch (state1) {
181     case STATE_ASCII:
182       if (c < 0x80) {
183         int ret = ascii_mbtowc(conv,pwc,s,1);
184         if (ret == RET_ILSEQ)
185           goto ilseq;
186         if (ret != 1) abort();
187         if (*pwc == 0x000a || *pwc == 0x000d)
188           state2 = STATE_G2_NONE;
189         COMBINE_STATE;
190         conv->istate = state;
191         return count+1;
192       } else
193         goto ilseq;
194     case STATE_JISX0201ROMAN:
195       if (c < 0x80) {
196         int ret = jisx0201_mbtowc(conv,pwc,s,1);
197         if (ret == RET_ILSEQ)
198           goto ilseq;
199         if (ret != 1) abort();
200         if (*pwc == 0x000a || *pwc == 0x000d)
201           state2 = STATE_G2_NONE;
202         COMBINE_STATE;
203         conv->istate = state;
204         return count+1;
205       } else
206         goto ilseq;
207     case STATE_JISX0201KATAKANA:
208       if (c < 0x80) {
209         unsigned char buf = c+0x80;
210         int ret = jisx0201_mbtowc(conv,pwc,&buf,1);
211         if (ret == RET_ILSEQ)
212           goto ilseq;
213         if (ret != 1) abort();
214         COMBINE_STATE;
215         conv->istate = state;
216         return count+1;
217       } else
218         goto ilseq;
219     case STATE_JISX0208:
220       if (n < count+2)
221         goto none;
222       if (s[0] < 0x80 && s[1] < 0x80) {
223         int ret = jisx0208_mbtowc(conv,pwc,s,2);
224         if (ret == RET_ILSEQ)
225           goto ilseq;
226         if (ret != 2) abort();
227         COMBINE_STATE;
228         conv->istate = state;
229         return count+2;
230       } else
231         goto ilseq;
232     case STATE_JISX0212:
233       if (n < count+2)
234         goto none;
235       if (s[0] < 0x80 && s[1] < 0x80) {
236         int ret = jisx0212_mbtowc(conv,pwc,s,2);
237         if (ret == RET_ILSEQ)
238           goto ilseq;
239         if (ret != 2) abort();
240         COMBINE_STATE;
241         conv->istate = state;
242         return count+2;
243       } else
244         goto ilseq;
245     case STATE_GB2312:
246       if (n < count+2)
247         goto none;
248       if (s[0] < 0x80 && s[1] < 0x80) {
249         int ret = gb2312_mbtowc(conv,pwc,s,2);
250         if (ret == RET_ILSEQ)
251           goto ilseq;
252         if (ret != 2) abort();
253         COMBINE_STATE;
254         conv->istate = state;
255         return count+2;
256       } else
257         goto ilseq;
258     case STATE_KSC5601:
259       if (n < count+2)
260         goto none;
261       if (s[0] < 0x80 && s[1] < 0x80) {
262         int ret = ksc5601_mbtowc(conv,pwc,s,2);
263         if (ret == RET_ILSEQ)
264           goto ilseq;
265         if (ret != 2) abort();
266         COMBINE_STATE;
267         conv->istate = state;
268         return count+2;
269       } else
270         goto ilseq;
271     default: abort();
272   }
273
274 none:
275   COMBINE_STATE;
276   conv->istate = state;
277   return RET_TOOFEW(count);
278
279 ilseq:
280   COMBINE_STATE;
281   conv->istate = state;
282   return RET_SHIFT_ILSEQ(count);
283 }
284
285 #undef COMBINE_STATE
286 #undef SPLIT_STATE
287
288 /*
289  * The state can also contain one of the following values, << 16.
290  * Values >= STATE_TAG_LANGUAGE are temporary tag parsing states.
291  */
292 #define STATE_TAG_NONE          0
293 #define STATE_TAG_LANGUAGE      4
294 #define STATE_TAG_LANGUAGE_j    5
295 #define STATE_TAG_LANGUAGE_ja   1
296 #define STATE_TAG_LANGUAGE_k    6
297 #define STATE_TAG_LANGUAGE_ko   2
298 #define STATE_TAG_LANGUAGE_z    7
299 #define STATE_TAG_LANGUAGE_zh   3
300
301 #define SPLIT_STATE \
302   unsigned int state1 = state & 0xff, state2 = (state >> 8) & 0xff, state3 = state >> 16
303 #define COMBINE_STATE \
304   state = (state3 << 16) | (state2 << 8) | state1
305
306 static int
307 iso2022_jp2_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)
308 {
309   state_t state = conv->ostate;
310   SPLIT_STATE;
311   unsigned char buf[2];
312   int ret;
313   /* This defines the conversion preferences depending on the current
314      langauge tag. */
315   enum conversion { none = 0, european, japanese, chinese, korean, other };
316   static const unsigned int conversion_lists[STATE_TAG_LANGUAGE] = {
317     /* STATE_TAG_NONE */
318     japanese + (european << 3) + (chinese << 6) + (korean << 9) + (other << 12),
319     /* STATE_TAG_LANGUAGE_ja */
320     japanese + (european << 3) + (chinese << 6) + (korean << 9) + (other << 12),
321     /* STATE_TAG_LANGUAGE_ko */
322     korean + (european << 3) + (japanese << 6) + (chinese << 9) + (other << 12),
323     /* STATE_TAG_LANGUAGE_zh */
324     chinese + (european << 3) + (japanese << 6) + (korean << 9) + (other << 12)
325   };
326   unsigned int conversion_list;
327
328   /* Handle Unicode tag characters (range U+E0000..U+E007F). */
329   if ((wc >> 7) == (0xe0000 >> 7)) {
330     char c = wc & 0x7f;
331     if (c >= 'A' && c <= 'Z')
332       c += 'a'-'A';
333     switch (c) {
334       case 0x01:
335         state3 = STATE_TAG_LANGUAGE;
336         COMBINE_STATE;
337         conv->ostate = state;
338         return 0;
339       case 'j':
340         if (state3 == STATE_TAG_LANGUAGE) {
341           state3 = STATE_TAG_LANGUAGE_j;
342           COMBINE_STATE;
343           conv->ostate = state;
344           return 0;
345         }
346         break;
347       case 'a':
348         if (state3 == STATE_TAG_LANGUAGE_j) {
349           state3 = STATE_TAG_LANGUAGE_ja;
350           COMBINE_STATE;
351           conv->ostate = state;
352           return 0;
353         }
354         break;
355       case 'k':
356         if (state3 == STATE_TAG_LANGUAGE) {
357           state3 = STATE_TAG_LANGUAGE_k;
358           COMBINE_STATE;
359           conv->ostate = state;
360           return 0;
361         }
362         break;
363       case 'o':
364         if (state3 == STATE_TAG_LANGUAGE_k) {
365           state3 = STATE_TAG_LANGUAGE_ko;
366           COMBINE_STATE;
367           conv->ostate = state;
368           return 0;
369         }
370         break;
371       case 'z':
372         if (state3 == STATE_TAG_LANGUAGE) {
373           state3 = STATE_TAG_LANGUAGE_z;
374           COMBINE_STATE;
375           conv->ostate = state;
376           return 0;
377         }
378         break;
379       case 'h':
380         if (state3 == STATE_TAG_LANGUAGE_z) {
381           state3 = STATE_TAG_LANGUAGE_zh;
382           COMBINE_STATE;
383           conv->ostate = state;
384           return 0;
385         }
386         break;
387       case 0x7f:
388         state3 = STATE_TAG_NONE;
389         COMBINE_STATE;
390         conv->ostate = state;
391         return 0;
392       default:
393         break;
394     }
395     /* Other tag characters reset the tag parsing state or are ignored. */
396     if (state3 >= STATE_TAG_LANGUAGE)
397       state3 = STATE_TAG_NONE;
398     COMBINE_STATE;
399     conv->ostate = state;
400     return 0;
401   }
402   if (state3 >= STATE_TAG_LANGUAGE)
403     state3 = STATE_TAG_NONE;
404
405   /* Try ASCII. */
406   ret = ascii_wctomb(conv,buf,wc,1);
407   if (ret != RET_ILUNI) {
408     if (ret != 1) abort();
409     if (buf[0] < 0x80) {
410       int count = (state1 == STATE_ASCII ? 1 : 4);
411       if (n < count)
412         return RET_TOOSMALL;
413       if (state1 != STATE_ASCII) {
414         r[0] = ESC;
415         r[1] = '(';
416         r[2] = 'B';
417         r += 3;
418         state1 = STATE_ASCII;
419       }
420       r[0] = buf[0];
421       if (wc == 0x000a || wc == 0x000d)
422         state2 = STATE_G2_NONE;
423       COMBINE_STATE;
424       conv->ostate = state;
425       return count;
426     }
427   }
428
429   conversion_list = conversion_lists[state3];
430
431   do {
432     switch (conversion_list & ((1 << 3) - 1)) {
433
434       case european:
435
436         /* Try ISO-8859-1. */
437         ret = iso8859_1_wctomb(conv,buf,wc,1);
438         if (ret != RET_ILUNI) {
439           if (ret != 1) abort();
440           if (buf[0] >= 0x80) {
441             int count = (state2 == STATE_G2_ISO8859_1 ? 3 : 6);
442             if (n < count)
443               return RET_TOOSMALL;
444             if (state2 != STATE_G2_ISO8859_1) {
445               r[0] = ESC;
446               r[1] = '.';
447               r[2] = 'A';
448               r += 3;
449               state2 = STATE_G2_ISO8859_1;
450             }
451             r[0] = ESC;
452             r[1] = 'N';
453             r[2] = buf[0]-0x80;
454             COMBINE_STATE;
455             conv->ostate = state;
456             return count;
457           }
458         }
459
460         /* Try ISO-8859-7. */
461         ret = iso8859_7_wctomb(conv,buf,wc,1);
462         if (ret != RET_ILUNI) {
463           if (ret != 1) abort();
464           if (buf[0] >= 0x80) {
465             int count = (state2 == STATE_G2_ISO8859_7 ? 3 : 6);
466             if (n < count)
467               return RET_TOOSMALL;
468             if (state2 != STATE_G2_ISO8859_7) {
469               r[0] = ESC;
470               r[1] = '.';
471               r[2] = 'F';
472               r += 3;
473               state2 = STATE_G2_ISO8859_7;
474             }
475             r[0] = ESC;
476             r[1] = 'N';
477             r[2] = buf[0]-0x80;
478             COMBINE_STATE;
479             conv->ostate = state;
480             return count;
481           }
482         }
483
484         break;
485
486       case japanese:
487
488         /* Try JIS X 0201-1976 Roman. */
489         ret = jisx0201_wctomb(conv,buf,wc,1);
490         if (ret != RET_ILUNI) {
491           if (ret != 1) abort();
492           if (buf[0] < 0x80) {
493             int count = (state1 == STATE_JISX0201ROMAN ? 1 : 4);
494             if (n < count)
495               return RET_TOOSMALL;
496             if (state1 != STATE_JISX0201ROMAN) {
497               r[0] = ESC;
498               r[1] = '(';
499               r[2] = 'J';
500               r += 3;
501               state1 = STATE_JISX0201ROMAN;
502             }
503             r[0] = buf[0];
504             if (wc == 0x000a || wc == 0x000d)
505               state2 = STATE_G2_NONE;
506             COMBINE_STATE;
507             conv->ostate = state;
508             return count;
509           }
510         }
511
512         /* Try JIS X 0208-1990 in place of JIS X 0208-1978 and
513            JIS X 0208-1983. */
514         ret = jisx0208_wctomb(conv,buf,wc,2);
515         if (ret != RET_ILUNI) {
516           if (ret != 2) abort();
517           if (buf[0] < 0x80 && buf[1] < 0x80) {
518             int count = (state1 == STATE_JISX0208 ? 2 : 5);
519             if (n < count)
520               return RET_TOOSMALL;
521             if (state1 != STATE_JISX0208) {
522               r[0] = ESC;
523               r[1] = '$';
524               r[2] = 'B';
525               r += 3;
526               state1 = STATE_JISX0208;
527             }
528             r[0] = buf[0];
529             r[1] = buf[1];
530             COMBINE_STATE;
531             conv->ostate = state;
532             return count;
533           }
534         }
535
536         /* Try JIS X 0212-1990. */
537         ret = jisx0212_wctomb(conv,buf,wc,2);
538         if (ret != RET_ILUNI) {
539           if (ret != 2) abort();
540           if (buf[0] < 0x80 && buf[1] < 0x80) {
541             int count = (state1 == STATE_JISX0212 ? 2 : 6);
542             if (n < count)
543               return RET_TOOSMALL;
544             if (state1 != STATE_JISX0212) {
545               r[0] = ESC;
546               r[1] = '$';
547               r[2] = '(';
548               r[3] = 'D';
549               r += 4;
550               state1 = STATE_JISX0212;
551             }
552             r[0] = buf[0];
553             r[1] = buf[1];
554             COMBINE_STATE;
555             conv->ostate = state;
556             return count;
557           }
558         }
559
560         break;
561
562       case chinese:
563
564         /* Try GB 2312-1980. */
565         ret = gb2312_wctomb(conv,buf,wc,2);
566         if (ret != RET_ILUNI) {
567           if (ret != 2) abort();
568           if (buf[0] < 0x80 && buf[1] < 0x80) {
569             int count = (state1 == STATE_GB2312 ? 2 : 5);
570             if (n < count)
571               return RET_TOOSMALL;
572             if (state1 != STATE_GB2312) {
573               r[0] = ESC;
574               r[1] = '$';
575               r[2] = 'A';
576               r += 3;
577               state1 = STATE_GB2312;
578             }
579             r[0] = buf[0];
580             r[1] = buf[1];
581             COMBINE_STATE;
582             conv->ostate = state;
583             return count;
584           }
585         }
586
587         break;
588
589       case korean:
590
591         /* Try KS C 5601-1992. */
592         ret = ksc5601_wctomb(conv,buf,wc,2);
593         if (ret != RET_ILUNI) {
594           if (ret != 2) abort();
595           if (buf[0] < 0x80 && buf[1] < 0x80) {
596             int count = (state1 == STATE_KSC5601 ? 2 : 6);
597             if (n < count)
598               return RET_TOOSMALL;
599             if (state1 != STATE_KSC5601) {
600               r[0] = ESC;
601               r[1] = '$';
602               r[2] = '(';
603               r[3] = 'C';
604               r += 4;
605               state1 = STATE_KSC5601;
606             }
607             r[0] = buf[0];
608             r[1] = buf[1];
609             COMBINE_STATE;
610             conv->ostate = state;
611             return count;
612           }
613         }
614
615         break;
616
617       case other:
618
619         /* Try JIS X 0201-1976 Kana. This is not officially part of
620            ISO-2022-JP-2, according to RFC 1554. Therefore we try this
621            only after all other attempts. */
622         ret = jisx0201_wctomb(conv,buf,wc,1);
623         if (ret != RET_ILUNI) {
624           if (ret != 1) abort();
625           if (buf[0] >= 0x80) {
626             int count = (state1 == STATE_JISX0201KATAKANA ? 1 : 4);
627             if (n < count)
628               return RET_TOOSMALL;
629             if (state1 != STATE_JISX0201KATAKANA) {
630               r[0] = ESC;
631               r[1] = '(';
632               r[2] = 'I';
633               r += 3;
634               state1 = STATE_JISX0201KATAKANA;
635             }
636             r[0] = buf[0]-0x80;
637             COMBINE_STATE;
638             conv->ostate = state;
639             return count;
640           }
641         }
642
643         break;
644
645       default:
646         abort();
647     }
648
649     conversion_list = conversion_list >> 3;
650   } while (conversion_list != 0);
651
652   return RET_ILUNI;
653 }
654
655 static int
656 iso2022_jp2_reset (conv_t conv, unsigned char *r, int n)
657 {
658   state_t state = conv->ostate;
659   SPLIT_STATE;
660   (void)state2;
661   (void)state3;
662   if (state1 != STATE_ASCII) {
663     if (n < 3)
664       return RET_TOOSMALL;
665     r[0] = ESC;
666     r[1] = '(';
667     r[2] = 'B';
668     /* conv->ostate = 0; will be done by the caller */
669     return 3;
670   } else
671     return 0;
672 }
673
674 #undef COMBINE_STATE
675 #undef SPLIT_STATE
676 #undef STATE_TAG_LANGUAGE_zh
677 #undef STATE_TAG_LANGUAGE_z
678 #undef STATE_TAG_LANGUAGE_ko
679 #undef STATE_TAG_LANGUAGE_k
680 #undef STATE_TAG_LANGUAGE_ja
681 #undef STATE_TAG_LANGUAGE_j
682 #undef STATE_TAG_LANGUAGE
683 #undef STATE_TAG_NONE
684 #undef STATE_G2_ISO8859_7
685 #undef STATE_G2_ISO8859_1
686 #undef STATE_G2_NONE
687 #undef STATE_KSC5601
688 #undef STATE_GB2312
689 #undef STATE_JISX0212
690 #undef STATE_JISX0208
691 #undef STATE_JISX0201KATAKANA
692 #undef STATE_JISX0201ROMAN
693 #undef STATE_ASCII