sync with sylpheed 0.5.0pre5
[claws.git] / libkcc / out.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  *  Output Routines                                                   *
12  *                                                                    *
13  **********************************************************************/
14 extern void (*outascii)(), (*outkanji)(), (*outgaiji)(), (*outkana)();
15
16 /*---------------------------------------------------------------------
17     NAME
18         outsjis
19  ---------------------------------------------------------------------*/
20 void Kcc_outsjis(ddd, c1, c2)
21     register int c1, c2;
22     char **ddd;
23 {
24     register int c;
25
26     c = c1 * 2 - (c1 <= 0x9f ? 0x00e1 : (c1 < 0xf0 ? 0x0161 : 0x01bf));
27     if (c2 < 0x9f)
28         c2 = c2 - (c2 > 0x7f ? 0x20 : 0x1f);
29     else {
30         c2 = c2 - 0x7e;
31         c++;
32     }
33     (*(c1 <= 0xef ? outkanji : outgaiji))(ddd, c, c2);
34 }
35
36 /*---------------------------------------------------------------------
37     NAME
38         out
39  ---------------------------------------------------------------------*/
40 unsigned Kcc_out(ddd,   str, len, code,   outcode, inmode, insi, inso, innj, ingj)
41     char *str, **ddd;
42     int len;
43     register unsigned code;
44     enum mode *inmode;
45     unsigned long *insi, *inso, *innj, *ingj;
46     unsigned outcode;
47 {
48     register char *s;
49     register int i;
50
51     for (s = str; s < str + len; s += i) {
52         i = 1;
53         switch (*(u_char *) s) {
54         case ESC:
55             if (*inmode == M_SO)
56                 break;
57             if (Kcc_compare("$B", s + 1) || Kcc_compare("$@", s + 1)) {
58                 *inmode = M_KANJI;      /* kanji */
59                 *insi |= bitflag(((u_char *) s)[2]);
60                 i = 3;
61             } else if (Kcc_compare("&@\033$B", s + 1)) {
62                 *inmode = M_KANJI;      /* kanji 1990 */
63                 *innj |= bitflag('B');
64                 i = 6;
65             } else if (Kcc_compare("(B", s + 1) || Kcc_compare("(J", s + 1) ||
66                     Kcc_compare("(H", s + 1)) {
67                 *inmode = M_ASCII;      /* kanji end */
68                 *inso |= bitflag(((u_char *) s)[2]);
69                 i = 3;
70             } else if (Kcc_compare("(I", s + 1)) {
71                 *inmode = M_ESCI;       /* "ESC(I" */
72                 *inso |= bitflag('I');
73                 i = 3;
74             } else if (Kcc_compare("$(D", s + 1)) {
75                 *inmode = M_GAIJI;      /* gaiji */
76                 *ingj |= bitflag('D');
77                 i = 4;
78             } else
79                 break;
80             code |= JIS;
81             continue;
82         case SO:
83             if (*inmode == M_ASCII) {
84                 code |= JIS;
85                 *inmode = M_SO;
86                 continue;
87             }
88             break;
89         case SI:
90             if (*inmode == M_SO) {
91                 *inmode = M_ASCII;
92                 continue;
93             }
94             break;
95         }
96         if (*inmode != M_ASCII) {
97             if (0x20 < ((u_char *) s)[0] && ((u_char *) s)[0] < 0x7f)
98                 switch (*inmode) {
99                 case M_KANJI:
100                     (*outkanji)(ddd, ((u_char *) s)[0], ((u_char *) s)[1] & 0x7f);
101                     i = 2;
102                     continue;
103                 case M_GAIJI:
104                     (*outgaiji)(ddd, ((u_char *) s)[0], ((u_char *) s)[1] & 0x7f);
105                     i = 2;
106                     continue;
107                 case M_SO:
108                 case M_ESCI:
109                     (*outkana)(ddd, ((u_char *) s)[0]);
110                     continue;
111                 default:
112                     continue;
113                 }
114         } else if (((u_char *) s)[0] & 0x80) {
115             if (code & (EUC | DEC)) {
116                 /*
117                  * EUC or DEC:
118                  */
119                 if (0xa0 < ((u_char *) s)[0] &&
120                         ((u_char *) s)[0] < 0xff) {
121                     if (!(((u_char *) s)[1] & 0x80) && code & DEC) {
122                         /*
123                          * DEC gaiji:
124                          */
125                         code &= ~EUC;   /* definitely DEC  */
126                         (*outgaiji)(ddd, ((u_char *) s)[0] & 0x7f, ((u_char *) s)[1]);
127                     } else
128                         /*
129                          * EUC code set 1 (kanji), DEC kanji:
130                          */
131                         (*outkanji)(ddd, ((u_char *) s)[0] & 0x7f, ((u_char *) s)[1] & 0x7f);
132                 } else if (((u_char *) s)[0] == SS2 && code & EUC &&
133                         0xa0 < ((u_char *) s)[1] &&
134                         ((u_char *) s)[1] < 0xff) {
135                     /*
136                      * EUC code set 2 (hankaku kana):
137                      */
138                     code &= ~DEC;       /* probably EUC */
139                     (*outkana)(ddd, ((u_char *) s)[1] & 0x7f);
140                 } else if (((u_char *) s)[0] == SS3 && code & EUC &&
141                         0xa0 < ((u_char *) s)[1] &&
142                         ((u_char *) s)[1] < 0xff &&
143                         0xa0 < ((u_char *) s)[2] &&
144                         ((u_char *) s)[2] < 0xff) {
145                     /*
146                      * EUC code set 3 (gaiji):
147                      */
148                     code &= ~DEC;       /* probably EUC */
149                     (*outgaiji)(ddd, ((u_char *) s)[1] & 0x7f, ((u_char *) s)[2] & 0x7f);
150                     i = 3;
151                     continue;
152                 } else {
153                     /*
154                      * Control character (C1):
155                      */
156                     if (outcode != SJIS && (outcode != EUC || 
157                             (((u_char *) s)[0] != SS2 &&
158                             ((u_char *) s)[0] != SS3)))
159                         **ddd = ((u_char *) s)[0]; (*ddd)++;
160                     continue;
161                 }
162                 i = 2;
163                 continue;
164             } else if (code & (SJIS | JIS8)) {
165                 /*
166                  * Shift-JIS or JIS8:
167                  */
168                 if (!(code & SJIS) || (0xa0 < ((u_char *) s)[0] &&
169                         ((u_char *) s)[0] < 0xe0))
170                     /*
171                      * Hankaku kana:
172                      */
173                     (*outkana)(ddd, ((u_char *) s)[0] & 0x7f);
174                 else {
175                     /*
176                      * Shift-JIS kanji:
177                      */
178                     code &= ~JIS8;      /* definitely shift-JIS */
179                     Kcc_outsjis(ddd, ((u_char *) s)[0], ((u_char *) s)[1]);
180                     i = 2;
181                 }
182                 continue;
183             }
184         }
185         (*outascii)(ddd, ((u_char *) s)[0]);
186     }
187     return (code);
188 }