Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / nsgmls / SJISCodingSystem.C
1 /* $XConsortium: SJISCodingSystem.C /main/1 1996/07/29 17:03:20 cde-hp $ */
2 // Copyright (c) 1994 James Clark
3 // See the file COPYING for copying permission.
4
5 #include "splib.h"
6
7 #ifdef SP_MULTI_BYTE
8
9 #include "SJISCodingSystem.h"
10 #include <iostream.h>
11
12 #ifdef SP_NAMESPACE
13 namespace SP_NAMESPACE {
14 #endif
15
16 class SJISDecoder : public Decoder {
17 public:
18   SJISDecoder();
19   size_t decode(Char *, const char *, size_t, const char **);
20 private:
21 };
22
23 class SJISEncoder : public Encoder {
24 public:
25   SJISEncoder();
26   void output(const Char *, size_t, streambuf *);
27 };
28
29 Decoder *SJISCodingSystem::makeDecoder() const
30 {
31   return new SJISDecoder;
32 }
33
34 Encoder *SJISCodingSystem::makeEncoder() const
35 {
36   return new SJISEncoder;
37 }
38
39
40 SJISDecoder::SJISDecoder()
41 {
42 }
43
44 size_t SJISDecoder::decode(Char *to, const char *s,
45                            size_t slen, const char **rest)
46 {
47   Char *start = to;
48   while (slen > 0) {
49     unsigned char c = *(unsigned char *)s;
50     if (!(c & 0x80)) {
51       *to++ = c;
52       s++;
53       slen--;
54     }
55     else if (129 <= c && c <= 159) {
56       if (slen < 2)
57         break;
58       s++;
59       slen -= 2;
60       unsigned char c2 = *(unsigned char *)s++;
61       unsigned short n = ((c - 112) << 9) | c2;
62       if (64 <= c2 && c2 <= 127)
63         n -= 31 + (1 << 8);
64       else if (c2 <= 158)
65         n -= 32 + (1 << 8);
66       else if (c2 <= 252)
67         n -= 126;
68       else
69         continue;
70       n |= 0x8080;
71       *to++ = n;
72     }
73     else if (224 <= c && c <= 239) {
74       if (slen < 2)
75         break;
76       s++;
77       slen -= 2;
78       unsigned char c2 = *(unsigned char *)s++;
79       unsigned short n = ((c - 176) << 9) | c2;
80       if (64 <= c2 && c2 <= 127)
81         n -= 31 + (1 << 8);
82       else if (c2 <= 158)
83         n -= 32 + (1 << 8);
84       else if (c2 <= 252)
85         n -= 126;
86       else
87         continue;
88       n |= 0x8080;
89       *to++ = n;
90     }
91     else if (161 <= c && c <= 223) {
92       slen--;
93       s++;
94       *to++ = c;
95     }
96     else {
97       // 128, 160, 240-255
98       slen--;
99       s++;
100     }
101   }
102   *rest = s;
103   return to - start;
104 }
105
106 SJISEncoder::SJISEncoder()
107 {
108 }
109
110 // FIXME handle errors from streambuf::sputc
111
112 void SJISEncoder::output(const Char *s, size_t n, streambuf *sb)
113 {
114   for (; n > 0; s++, n--) {
115     Char c = *s;
116     unsigned short mask = (unsigned short)(c & 0x8080);
117     if (mask == 0)
118       sb->sputc(char(c & 0xff));
119     else if (mask == 0x8080) {
120       unsigned char c1 = (c >> 8) & 0x7f;
121       unsigned char c2 = c & 0x7f;
122       char out1;
123       if (c1 < 33)
124         out1 = 0;
125       else if (c1 < 95)
126         out1 = ((c1 + 1) >> 1) + 112;
127       else if (c1 < 127)
128         out1 = ((c1 + 1) >> 1) + 176;
129       else
130         out1 = 0;
131       if (out1) {
132         char out2;
133         if (c1 & 1) {
134           if (c2 < 33)
135             out2 = 0;
136           else if (c2 <= 95)
137             out2 = c2 + 31;
138           else if (c2 <= 126)
139             out2 = c2 + 32;
140           else
141             out2 = 0;
142         }
143         else {
144           if (33 <= c2 && c2 <= 126)
145             out2 = c2 + 126;
146           else
147             out2 = 0;
148         }
149         if (out2) {
150           sb->sputc(out1);
151           sb->sputc(out2);
152         }
153         else
154           handleUnencodable(c, sb);
155       }
156       else
157         handleUnencodable(c, sb);
158     }
159     else if (mask == 0x0080) {
160       if (161 <= c && c <= 223)
161         sb->sputc(char(c & 0xff));
162       else
163         handleUnencodable(c, sb);
164     }
165     else
166       handleUnencodable(c, sb);
167   }
168 }
169
170 #ifdef SP_NAMESPACE
171 }
172 #endif
173
174 #else /* not SP_MULTI_BYTE */
175
176 #ifndef __GNUG__
177 static char non_empty_translation_unit; // sigh
178 #endif
179
180 #endif /* not SP_MULTI_BYTE */