sync with sylpheed 0.6.1cvs2
[claws.git] / libkcc / guess.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5
6 #include "kcc.h"
7 #include "libkcc.h"
8
9 /**********************************************************************
10  *                                                                    *
11  *  Guessing                                                          *
12  *                                                                    *
13  **********************************************************************/
14 /*---------------------------------------------------------------------
15     NAME
16         guess - distinguish code system
17  ---------------------------------------------------------------------*/
18 unsigned Kcc_guess(str, len, extend, zenkaku, gsmode, insi, inso, innj, ingj)
19     char *str;
20     int len, extend;
21     enum mode *gsmode;
22    unsigned long *insi, *inso, *innj, *ingj;
23    bool zenkaku;
24 {
25     register char *s;
26     register int euc, sjis, dec;
27     bool jis8;
28     register unsigned code;
29     register int i;
30     enum mode old;
31
32     euc = sjis = 1;
33     dec = extend ? 1 : 0;
34     jis8 = 1;
35     code = 0;
36     for (s = str; s < str + len; s += i) {
37         i = 1;
38         switch (*(u_char *) s) {
39         case ESC:
40             if (*gsmode == M_SO)
41                 continue;
42             old = *gsmode;
43             if (Kcc_compare("$B", s + 1) || Kcc_compare("$@", s + 1)) {
44                 *gsmode = M_KANJI;      /* kanji */
45                 *insi |= bitflag(((u_char *) s)[2]);
46                 i = 3;
47             } else if (Kcc_compare("&@\033$B", s + 1)) {
48                 *gsmode = M_KANJI;      /* kanji 1990 */
49                 *innj |= bitflag('B');
50                 i = 6;
51             } else if (Kcc_compare("(B", s + 1) ||
52                     Kcc_compare("(J", s + 1) || Kcc_compare("(H", s + 1)) {
53                 *gsmode = M_ASCII;      /* kanji end */
54                 *inso |= bitflag(((u_char *) s)[2]);
55                 i = 3;
56             } else if (Kcc_compare("(I", s + 1)) {
57                 *gsmode = M_KANJI;      /* "ESC(I" */
58                 *inso |= bitflag('I');
59                 i = 3;
60             } else if (Kcc_compare("$(D", s + 1)) {
61                 *gsmode = M_KANJI;      /* gaiji */
62                 *ingj |= bitflag('D');
63                 i = 4;
64             } else
65                 break;
66             code |= JIS;
67             if (old != M_ASCII)
68                 continue;
69             break;
70         case SO:
71             if (*gsmode == M_ASCII) {
72                 code |= JIS;
73                 *gsmode = M_SO;
74                 break;
75             }
76             continue;
77         case SI:
78             if (*gsmode == M_SO) {
79                 *gsmode = M_ASCII;
80                 continue;
81             }
82             /* fall thru */
83         default:
84             if (*gsmode != M_ASCII)
85                 continue;
86             break;
87         }
88         if (*(u_char *) s & 0x80)
89             code |= NONASCII;
90         switch (euc) {
91         case 1:
92             /*
93              * EUC first byte.
94              */
95             if (*(u_char *) s & 0x80) {
96                 if ((0xa0 < *(u_char *) s && *(u_char *) s < 0xff) ||
97                         (!zenkaku && *(u_char *) s == SS2)) {
98                     euc = 2;
99                     break;
100                 }
101                 if (extend) {
102                     if (*(u_char *) s == SS3) {
103                         euc = 2;
104                         break;
105                     } else if (*(u_char *) s < 0xa0)
106                         break;
107                 }
108                 euc = 0;        /* not EUC */
109             }
110             break;
111         case 2:
112             /*
113              * EUC second byte or third byte of CS3.
114              */
115             if (((u_char *) s)[-1] == SS2) {
116                 if (0xa0 < *(u_char *) s &&
117                         *(u_char *) s < (extend ? 0xff : 0xe0)) {
118                     euc = 1;    /* hankaku kana */
119                     break;
120                 }
121             } else
122                 if (0xa0 < *(u_char *) s && *(u_char *) s < 0xff) {
123                     if (((u_char *) s)[-1] != SS3)
124                         euc = 1;/* zenkaku */
125                     break;
126                 }
127             euc = 0;            /* not EUC */
128             break;
129         }
130         if (extend)
131             switch (dec) {
132             case 1:
133                 /*
134                  * DEC first byte.
135                  */
136                 if (*(u_char *) s & 0x80) {
137                     if (0xa0 < *(u_char *) s && *(u_char *) s < 0xff) {
138                         dec = 2;
139                         break;
140                     } else if (*(u_char *) s < 0xa0)
141                         break;
142                     dec = 0;    /* not DEC */
143                 }
144                 break;
145             case 2:
146                 /*
147                  * DEC second byte.
148                  */
149                 if (0x20 < (*(u_char *) s & 0x7f) &&
150                         (*(u_char *) s & 0x7f) < 0x7f) {
151                     dec = 1;
152                 } else
153                     dec = 0;    /* not DEC */
154                 break;
155             }
156         switch (sjis) {
157         case 1:
158             /*
159              * shift-JIS first byte.
160              */
161             if (*(u_char *) s & 0x80) {
162                 if (0xa0 < *(u_char *) s && *(u_char *) s < 0xe0) {
163                     if (!zenkaku)
164                         break;  /* hankaku */
165                 } else if (*(u_char *) s != 0x80 &&
166                         *(u_char *) s != 0xa0 &&
167                         *(u_char *) s <= (extend ? 0xfc : 0xef)) {
168                     sjis = 2;   /* zenkaku */
169                     jis8 = 0;
170                     break;
171                 }
172                 sjis = 0;       /* not SJIS */
173             }
174             break;
175         case 2:
176             /*
177              * shift-JIS second byte.
178              */
179             if (0x40 <= *(u_char *) s && *(u_char *) s != 0x7f &&
180                     *(u_char *) s <= 0xfc)
181                 sjis = 1;
182             else
183                 sjis = 0;       /* not SJIS */
184             break;
185         }
186     }
187     if (euc == 1)
188         code |= EUC;
189     if (dec == 1)
190         code |= DEC;
191     if (sjis == 1)
192         code |= zenkaku || !jis8 ? SJIS : SJIS | JIS8;
193     return (code);
194 }