5 // Hye-Shik Chang (perky@FreeBSD.org)
15 internal class CP949 : KoreanEncoding
17 // Magic number used by Windows for the UHC code page.
18 private const int UHC_CODE_PAGE = 949;
21 public CP949 () : base (UHC_CODE_PAGE, true)
25 // Get the mail body name for this encoding.
26 public override String BodyName
28 get { return "ks_c_5601-1987"; }
31 // Get the human-readable name for this encoding.
32 public override String EncodingName
34 get { return "Korean (UHC)"; }
37 // Get the mail agent header name for this encoding.
38 public override String HeaderName
40 get { return "ks_c_5601-1987"; }
43 // Get the IANA-preferred Web name for this encoding.
44 public override String WebName
46 get { return "ks_c_5601-1987"; }
50 // Get the Windows code page represented by this object.
51 public override int WindowsCodePage
53 get { return UHC_PAGE; }
59 internal class CP51949 : KoreanEncoding
61 // Magic number used by Windows for the euc-kr code page.
62 private const int EUCKR_CODE_PAGE = 51949;
65 public CP51949 () : base (EUCKR_CODE_PAGE, false)
69 // Get the mail body name for this encoding.
70 public override String BodyName
72 get { return "euc-kr"; }
75 // Get the human-readable name for this encoding.
76 public override String EncodingName
78 get { return "Korean (EUC)"; }
81 // Get the mail agent header name for this encoding.
82 public override String HeaderName
84 get { return "euc-kr"; }
87 // Get the IANA-preferred Web name for this encoding.
88 public override String WebName
90 get { return "euc-kr"; }
94 // Get the Windows code page represented by this object.
95 public override int WindowsCodePage
97 get { return UHC_PAGE; }
104 internal class KoreanEncoding : DbcsEncoding
107 public KoreanEncoding (int codepage, bool useUHC) : base (codepage) {
108 this.useUHC = useUHC;
111 internal override DbcsConvert GetConvert ()
113 return KSConvert.Convert;
118 // Get the bytes that result from encoding a character buffer.
119 public unsafe override int GetBytesImpl (char* chars, int charCount,
120 byte* bytes, int byteCount)
124 DbcsConvert convert = GetConvert ();
126 EncoderFallbackBuffer buffer = null;
130 int origIndex = byteIndex;
131 while (charCount-- > 0) {
132 char c = chars[charIndex++];
133 if (c <= 0x80 || c == 0xFF) { // ASCII
134 bytes[byteIndex++] = (byte)c;
137 byte b1 = convert.u2n[((int)c) * 2];
138 byte b2 = convert.u2n[((int)c) * 2 + 1];
139 if (b1 == 0 && b2 == 0) {
141 HandleFallback (ref buffer, chars, ref charIndex, ref charCount,
142 bytes, ref byteIndex, ref byteCount);
144 bytes[byteIndex++] = (byte)'?';
147 bytes[byteIndex++] = b1;
148 bytes[byteIndex++] = b2;
151 return byteIndex - origIndex;
154 // Get the characters that result from decoding a byte buffer.
155 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
156 char[] chars, int charIndex)
158 DbcsConvert convert = GetConvert ();
159 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
160 int origIndex = charIndex;
163 while (byteCount-- > 0) {
164 int b = bytes[byteIndex++];
166 if (b <= 0x80 || b == 0xFF) { // ASCII
167 chars[charIndex++] = (char)b;
176 if (useUHC && lastByte < 0xa1) { // UHC Level 1
177 int ord = 8836 + (lastByte - 0x81) * 178;
179 if (b >= 0x41 && b <= 0x5A)
181 else if (b >= 0x61 && b <= 0x7A)
182 ord += b - 0x61 + 26;
183 else if (b >= 0x81 && b <= 0xFE)
184 ord += b - 0x81 + 52;
188 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
189 c1 = (char)(convert.n2u[ord*2] +
190 convert.n2u[ord*2 + 1] * 256);
193 } else if (useUHC && lastByte <= 0xC6 && b < 0xa1) { // UHC Level 2
194 int ord = 14532 + (lastByte - 0xA1) * 84;
196 if (b >= 0x41 && b <= 0x5A)
198 else if (b >= 0x61 && b <= 0x7A)
199 ord += b - 0x61 + 26;
200 else if (b >= 0x81 && b <= 0xA0)
201 ord += b - 0x81 + 52;
205 if (ord >= 0 && ord * 2 < convert.n2u.Length)
206 c1 = (char)(convert.n2u[ord*2] +
207 convert.n2u[ord*2 + 1] * 256);
210 } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001
211 int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2;
213 c1 = ord < 0 || ord >= convert.n2u.Length ?
214 '\0' : (char)(convert.n2u[ord] +
215 convert.n2u[ord + 1] * 256);
220 chars[charIndex++] = '?';
222 chars[charIndex++] = c1;
225 return charIndex - origIndex;
228 // Get a decoder that handles a rolling UHC state.
229 public override Decoder GetDecoder()
231 return new KoreanDecoder (GetConvert (), useUHC);
234 // Decoder that handles a rolling UHC state.
235 private sealed class KoreanDecoder : DbcsDecoder
238 public KoreanDecoder (DbcsConvert convert, bool useUHC)
241 this.useUHC = useUHC;
245 public override int GetChars(byte[] bytes, int byteIndex,
246 int byteCount, char[] chars, int charIndex)
248 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
249 int origIndex = charIndex;
250 while (byteCount-- > 0) {
251 int b = bytes[byteIndex++];
253 if (b <= 0x80 || b == 0xFF) { // ASCII
254 chars[charIndex++] = (char)b;
263 if (useUHC && lastByte < 0xa1) { // UHC Level 1
264 int ord = 8836 + (lastByte - 0x81) * 178;
266 if (b >= 0x41 && b <= 0x5A)
268 else if (b >= 0x61 && b <= 0x7A)
269 ord += b - 0x61 + 26;
270 else if (b >= 0x81 && b <= 0xFE)
271 ord += b - 0x81 + 52;
275 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
276 c1 = (char)(convert.n2u[ord*2] +
277 convert.n2u[ord*2 + 1] * 256);
280 } else if (useUHC && lastByte <= 0xC6 && b < 0xA1) { // UHC Level 2
281 int ord = 14532 + (lastByte - 0xA1) * 84;
283 if (b >= 0x41 && b <= 0x5A)
285 else if (b >= 0x61 && b <= 0x7A)
286 ord += b - 0x61 + 26;
287 else if (b >= 0x81 && b <= 0xA0)
288 ord += b - 0x81 + 52;
292 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
293 c1 = (char)(convert.n2u[ord*2] +
294 convert.n2u[ord*2 + 1] * 256);
297 } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001
298 int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2;
300 c1 = ord < 0 || ord >= convert.n2u.Length ?
301 '\0' : (char)(convert.n2u[ord] +
302 convert.n2u[ord + 1] * 256);
307 chars[charIndex++] = '?';
309 chars[charIndex++] = c1;
312 return charIndex - origIndex;
318 internal class ENCuhc : CP949
324 internal class ENCeuc_kr: CP51949
326 public ENCeuc_kr() {}