Merge pull request #1573 from akoeplinger/msbuild-import-empty
[mono.git] / mcs / class / I18N / CJK / CP932.cs
1 /*
2  * CP932.cs - Japanese (Shift-JIS) code page.
3  *
4  * Copyright (c) 2002  Southern Storm Software, Pty Ltd
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 //
26 // Copyright (C) 2005-2006 Novell, Inc.
27 //
28
29 namespace I18N.CJK
30 {
31
32         using System;
33         using System.Text;
34         using I18N.Common;
35
36 #if DISABLE_UNSAFE
37         using MonoEncoder = I18N.Common.MonoSafeEncoder;
38         using MonoEncoding = I18N.Common.MonoSafeEncoding;
39 #endif
40
41         [Serializable]
42         public class CP932 : MonoEncoding
43         {
44                 // Magic number used by Windows for the Shift-JIS code page.
45                 private const int SHIFTJIS_CODE_PAGE = 932;
46
47                 // Constructor.
48                 public CP932() : base(SHIFTJIS_CODE_PAGE)
49                 {
50                 }
51
52 #if !DISABLE_UNSAFE
53                 // Get the number of bytes needed to encode a character buffer.
54                 public unsafe override int GetByteCountImpl (char* chars, int count)
55                 {
56                         int index = 0;
57
58                         // Determine the length of the final output.
59                         int length = 0;
60                         int ch, value;
61 #if __PNET__
62                         byte *cjkToJis = JISConvert.Convert.cjkToJis;
63                         byte *extraToJis = JISConvert.Convert.extraToJis;
64 #else
65                         byte[] cjkToJis = JISConvert.Convert.cjkToJis;
66                         byte[] extraToJis = JISConvert.Convert.extraToJis;
67 #endif
68                         while(count > 0)
69                         {
70                                 ch = chars[index++];
71                                 --count;
72                                 ++length;
73                                 if(ch < 0x0080)
74                                 {
75                                         // Character maps to itself.
76                                         continue;
77                                 }
78                                 else if(ch < 0x0100)
79                                 {
80                                         // Check for special Latin 1 characters that
81                                         // can be mapped to double-byte code points.
82                                         if(ch == 0x00A2 || ch == 0x00A3 || ch == 0x00A7 ||
83                                            ch == 0x00A8 || ch == 0x00AC || ch == 0x00B0 ||
84                                            ch == 0x00B1 || ch == 0x00B4 || ch == 0x00B6 ||
85                                            ch == 0x00D7 || ch == 0x00F7)
86                                         {
87                                                 ++length;
88                                         }
89                                 }
90                                 else if(ch >= 0x0391 && ch <= 0x0451)
91                                 {
92                                         // Greek subset characters.
93                                         ++length;
94                                 }
95                                 else if(ch >= 0x2010 && ch <= 0x9FA5)
96                                 {
97                                         // This range contains the bulk of the CJK set.
98                                         value = (ch - 0x2010) * 2;
99                                         value = ((int)(cjkToJis[value])) |
100                                                         (((int)(cjkToJis[value + 1])) << 8);
101                                         if(value >= 0x0100)
102                                         {
103                                                 ++length;
104                                         }
105                                 }
106                                 else if(ch >= 0xE000 && ch <= 0xE757)
107                                         // PrivateUse
108                                         ++length;
109                                 else if(ch >= 0xFF01 && ch <= 0xFFEF)
110                                 {
111                                         // This range contains extra characters,
112                                         // including half-width katakana.
113                                         value = (ch - 0xFF01) * 2;
114                                         value = ((int)(extraToJis[value])) |
115                                                         (((int)(extraToJis[value + 1])) << 8);
116                                         if(value >= 0x0100)
117                                         {
118                                                 ++length;
119                                         }
120                                 }
121                         }
122
123                         // Return the length to the caller.
124                         return length;
125                 }
126
127                 // Get the bytes that result from encoding a character buffer.
128                 public unsafe override int GetBytesImpl (
129                         char* chars, int charCount, byte* bytes, int byteCount)
130                 {
131                         int charIndex = 0;
132                         int byteIndex = 0;
133                         EncoderFallbackBuffer buffer = null;
134
135                         // Convert the characters into their byte form.
136                         int posn = byteIndex;
137                         int end = charCount;
138                         int byteLength = byteCount;
139                         int ch, value;
140 #if __PNET__
141                         byte *cjkToJis = JISConvert.Convert.cjkToJis;
142                         byte *greekToJis = JISConvert.Convert.greekToJis;
143                         byte *extraToJis = JISConvert.Convert.extraToJis;
144 #else
145                         byte[] cjkToJis = JISConvert.Convert.cjkToJis;
146                         byte[] greekToJis = JISConvert.Convert.greekToJis;
147                         byte[] extraToJis = JISConvert.Convert.extraToJis;
148 #endif
149                         for (int i = charIndex; i < end; i++, charCount--)
150                         {
151                                 ch = chars[i];
152                                 if(posn >= byteLength)
153                                 {
154                                         throw new ArgumentException
155                                                 (Strings.GetString("Arg_InsufficientSpace"),
156                                                  "bytes");
157                                 }
158                                 if(ch < 0x0080)
159                                 {
160                                         // Character maps to itself.
161                                         bytes[posn++] = (byte)ch;
162                                         continue;
163                                 }
164                                 else if(ch < 0x0100)
165                                 {
166                                         // Check for special Latin 1 characters that
167                                         // can be mapped to double-byte code points.
168                                         if(ch == 0x00A2 || ch == 0x00A3 || ch == 0x00A7 ||
169                                            ch == 0x00A8 || ch == 0x00AC || ch == 0x00B0 ||
170                                            ch == 0x00B1 || ch == 0x00B4 || ch == 0x00B6 ||
171                                            ch == 0x00D7 || ch == 0x00F7)
172                                         {
173                                                 if((posn + 1) >= byteLength)
174                                                 {
175                                                         throw new ArgumentException
176                                                                 (Strings.GetString
177                                                                         ("Arg_InsufficientSpace"), "bytes");
178                                                 }
179                                                 switch(ch)
180                                                 {
181                                                 case 0x00A2:
182                                                         bytes[posn++] = (byte)0x81;
183                                                         bytes[posn++] = (byte)0x91;
184                                                         break;
185
186                                                 case 0x00A3:
187                                                         bytes[posn++] = (byte)0x81;
188                                                         bytes[posn++] = (byte)0x92;
189                                                         break;
190
191                                                 case 0x00A7:
192                                                         bytes[posn++] = (byte)0x81;
193                                                         bytes[posn++] = (byte)0x98;
194                                                         break;
195
196                                                 case 0x00A8:
197                                                         bytes[posn++] = (byte)0x81;
198                                                         bytes[posn++] = (byte)0x4E;
199                                                         break;
200
201                                                 case 0x00AC:
202                                                         bytes[posn++] = (byte)0x81;
203                                                         bytes[posn++] = (byte)0xCA;
204                                                         break;
205
206                                                 case 0x00B0:
207                                                         bytes[posn++] = (byte)0x81;
208                                                         bytes[posn++] = (byte)0x8B;
209                                                         break;
210
211                                                 case 0x00B1:
212                                                         bytes[posn++] = (byte)0x81;
213                                                         bytes[posn++] = (byte)0x7D;
214                                                         break;
215
216                                                 case 0x00B4:
217                                                         bytes[posn++] = (byte)0x81;
218                                                         bytes[posn++] = (byte)0x4C;
219                                                         break;
220
221                                                 case 0x00B6:
222                                                         bytes[posn++] = (byte)0x81;
223                                                         bytes[posn++] = (byte)0xF7;
224                                                         break;
225
226                                                 case 0x00D7:
227                                                         bytes[posn++] = (byte)0x81;
228                                                         bytes[posn++] = (byte)0x7E;
229                                                         break;
230
231                                                 case 0x00F7:
232                                                         bytes[posn++] = (byte)0x81;
233                                                         bytes[posn++] = (byte)0x80;
234                                                         break;
235                                                 }
236                                         }
237                                         else if(ch == 0x00A5)
238                                         {
239                                                 // Yen sign.
240                                                 bytes[posn++] = (byte)0x5C;
241                                         }
242                                         else
243                                         {
244                                                 HandleFallback (ref buffer,
245                                                         chars, ref charIndex, ref charCount,
246                                                         bytes, ref posn, ref byteCount, null);
247                                         }
248                                         continue;
249                                 }
250                                 else if(ch >= 0x0391 && ch <= 0x0451)
251                                 {
252                                         // Greek subset characters.
253                                         value = (ch - 0x0391) * 2;
254                                         value = ((int)(greekToJis[value])) |
255                                                         (((int)(greekToJis[value + 1])) << 8);
256                                 }
257                                 else if(ch >= 0x2010 && ch <= 0x9FA5)
258                                 {
259                                         // This range contains the bulk of the CJK set.
260                                         value = (ch - 0x2010) * 2;
261                                         value = ((int)(cjkToJis[value])) |
262                                                         (((int)(cjkToJis[value + 1])) << 8);
263                                 }
264                                 else if(ch >= 0xE000 && ch <= 0xE757)
265                                 {
266                                         // PrivateUse
267                                         int diff = ch - 0xE000;
268                                         value = ((int) (diff / 0xBC) << 8)
269                                                 + (diff % 0xBC)
270                                                 + 0xF040;
271                                         if (value % 0x100 >= 0x7F)
272                                                 value++;
273                                 }
274                                 else if(ch >= 0xFF01 && ch <= 0xFF60)
275                                 {
276                                         value = (ch - 0xFF01) * 2;
277                                         value = ((int)(extraToJis[value])) |
278                                                         (((int)(extraToJis[value + 1])) << 8);
279                                 }
280                                 else if(ch >= 0xFF60 && ch <= 0xFFA0)
281                                 {
282                                         value = ch - 0xFF60 + 0xA0;
283                                 }
284                                 else
285                                 {
286                                         // Invalid character.
287                                         value = 0;
288                                 }
289                                 if(value == 0)
290                                 {
291                                         HandleFallback (ref buffer,
292                                                 chars, ref charIndex, ref charCount,
293                                                 bytes, ref posn, ref byteCount, null);
294                                 }
295                                 else if(value < 0x0100)
296                                 {
297                                         bytes[posn++] = (byte)value;
298                                 }
299                                 else if((posn + 1) >= byteLength)
300                                 {
301                                         throw new ArgumentException
302                                                 (Strings.GetString("Arg_InsufficientSpace"),
303                                                  "bytes");
304                                 }
305                                 else if(value < 0x8000)
306                                 {
307                                         // JIS X 0208 character.
308                                         value -= 0x0100;
309                                         ch = (value / 0xBC);
310                                         value = (value % 0xBC) + 0x40;
311                                         if(value >= 0x7F)
312                                         {
313                                                 ++value;
314                                         }
315                                         if(ch < (0x9F - 0x80))
316                                         {
317                                                 bytes[posn++] = (byte)(ch + 0x81);
318                                         }
319                                         else
320                                         {
321                                                 bytes[posn++] = (byte)(ch - (0x9F - 0x80) + 0xE0);
322                                         }
323                                         bytes[posn++] = (byte)value;
324                                 }
325                                 else if (value >= 0xF040 && value <= 0xF9FC)
326                                 {
327                                         // PrivateUse
328                                         bytes[posn++] = (byte) (value / 0x100);
329                                         bytes[posn++] = (byte) (value % 0x100);
330                                 }
331                                 else
332                                 {
333                                         // JIS X 0212 character, which Shift-JIS doesn't
334                                         // support, but we've already allocated two slots.
335                                         bytes[posn++] = (byte)'?';
336                                         bytes[posn++] = (byte)'?';
337                                 }
338                         }
339
340                         // Return the final length to the caller.
341                         return posn - byteIndex;
342                 }
343 #else
344                 // Get the number of bytes needed to encode a character buffer.
345                 public override int GetByteCount(char[] chars, int index, int count)
346                 {
347                         // Determine the length of the final output.
348                         int length = 0;
349                         int ch, value;
350                         byte[] cjkToJis = JISConvert.Convert.cjkToJis;
351                         byte[] extraToJis = JISConvert.Convert.extraToJis;
352
353                         while (count > 0)
354                         {
355                                 ch = chars[index++];
356                                 --count;
357                                 ++length;
358                                 if (ch < 0x0080)
359                                 {
360                                         // Character maps to itself.
361                                         continue;
362                                 }
363                                 else if (ch < 0x0100)
364                                 {
365                                         // Check for special Latin 1 characters that
366                                         // can be mapped to double-byte code points.
367                                         if (ch == 0x00A2 || ch == 0x00A3 || ch == 0x00A7 ||
368                                            ch == 0x00A8 || ch == 0x00AC || ch == 0x00B0 ||
369                                            ch == 0x00B1 || ch == 0x00B4 || ch == 0x00B6 ||
370                                            ch == 0x00D7 || ch == 0x00F7)
371                                         {
372                                                 ++length;
373                                         }
374                                 }
375                                 else if (ch >= 0x0391 && ch <= 0x0451)
376                                 {
377                                         // Greek subset characters.
378                                         ++length;
379                                 }
380                                 else if (ch >= 0x2010 && ch <= 0x9FA5)
381                                 {
382                                         // This range contains the bulk of the CJK set.
383                                         value = (ch - 0x2010) * 2;
384                                         value = ((int)(cjkToJis[value])) |
385                                                         (((int)(cjkToJis[value + 1])) << 8);
386                                         if (value >= 0x0100)
387                                         {
388                                                 ++length;
389                                         }
390                                 }
391                                 else if (ch >= 0xE000 && ch <= 0xE757)
392                                         // PrivateUse
393                                         ++length;
394                                 else if (ch >= 0xFF01 && ch <= 0xFFEF)
395                                 {
396                                         // This range contains extra characters,
397                                         // including half-width katakana.
398                                         value = (ch - 0xFF01) * 2;
399                                         value = ((int)(extraToJis[value])) |
400                                                         (((int)(extraToJis[value + 1])) << 8);
401                                         if (value >= 0x0100)
402                                         {
403                                                 ++length;
404                                         }
405                                 }
406                         }
407
408                         // Return the length to the caller.
409                         return length;
410                 }
411
412                 // Get the bytes that result from encoding a character buffer.
413                 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
414                 {
415                         int byteCount = bytes.Length;
416                         EncoderFallbackBuffer buffer = null;
417
418                         // Convert the characters into their byte form.
419                         int posn = byteIndex;
420                         int end = charIndex + charCount;
421                         int byteLength = byteCount;
422                         int /*ch,*/ value;
423                         byte[] cjkToJis = JISConvert.Convert.cjkToJis;
424                         byte[] greekToJis = JISConvert.Convert.greekToJis;
425                         byte[] extraToJis = JISConvert.Convert.extraToJis;
426
427                         for (int i = charIndex; i < end; i++, charCount--)
428                         {
429                                 int ch = chars[i];
430
431                                 if (posn >= byteLength)
432                                 {
433                                         throw new ArgumentException
434                                                 (Strings.GetString("Arg_InsufficientSpace"),
435                                                  "bytes");
436                                 }
437                                 if (ch < 0x0080)
438                                 {
439                                         // Character maps to itself.
440                                         bytes[posn++] = (byte)ch;
441                                         continue;
442                                 }
443                                 else if (ch < 0x0100)
444                                 {
445                                         // Check for special Latin 1 characters that
446                                         // can be mapped to double-byte code points.
447                                         if (ch == 0x00A2 || ch == 0x00A3 || ch == 0x00A7 ||
448                                            ch == 0x00A8 || ch == 0x00AC || ch == 0x00B0 ||
449                                            ch == 0x00B1 || ch == 0x00B4 || ch == 0x00B6 ||
450                                            ch == 0x00D7 || ch == 0x00F7)
451                                         {
452                                                 if ((posn + 1) >= byteLength)
453                                                 {
454                                                         throw new ArgumentException
455                                                                 (Strings.GetString
456                                                                         ("Arg_InsufficientSpace"), "bytes");
457                                                 }
458                                                 switch (ch)
459                                                 {
460                                                         case 0x00A2:
461                                                                 bytes[posn++] = (byte)0x81;
462                                                                 bytes[posn++] = (byte)0x91;
463                                                                 break;
464
465                                                         case 0x00A3:
466                                                                 bytes[posn++] = (byte)0x81;
467                                                                 bytes[posn++] = (byte)0x92;
468                                                                 break;
469
470                                                         case 0x00A7:
471                                                                 bytes[posn++] = (byte)0x81;
472                                                                 bytes[posn++] = (byte)0x98;
473                                                                 break;
474
475                                                         case 0x00A8:
476                                                                 bytes[posn++] = (byte)0x81;
477                                                                 bytes[posn++] = (byte)0x4E;
478                                                                 break;
479
480                                                         case 0x00AC:
481                                                                 bytes[posn++] = (byte)0x81;
482                                                                 bytes[posn++] = (byte)0xCA;
483                                                                 break;
484
485                                                         case 0x00B0:
486                                                                 bytes[posn++] = (byte)0x81;
487                                                                 bytes[posn++] = (byte)0x8B;
488                                                                 break;
489
490                                                         case 0x00B1:
491                                                                 bytes[posn++] = (byte)0x81;
492                                                                 bytes[posn++] = (byte)0x7D;
493                                                                 break;
494
495                                                         case 0x00B4:
496                                                                 bytes[posn++] = (byte)0x81;
497                                                                 bytes[posn++] = (byte)0x4C;
498                                                                 break;
499
500                                                         case 0x00B6:
501                                                                 bytes[posn++] = (byte)0x81;
502                                                                 bytes[posn++] = (byte)0xF7;
503                                                                 break;
504
505                                                         case 0x00D7:
506                                                                 bytes[posn++] = (byte)0x81;
507                                                                 bytes[posn++] = (byte)0x7E;
508                                                                 break;
509
510                                                         case 0x00F7:
511                                                                 bytes[posn++] = (byte)0x81;
512                                                                 bytes[posn++] = (byte)0x80;
513                                                                 break;
514                                                 }
515                                         }
516                                         else if (ch == 0x00A5)
517                                         {
518                                                 // Yen sign.
519                                                 bytes[posn++] = (byte)0x5C;
520                                         }
521                                         else
522                                         {
523                                                 HandleFallback (ref buffer, chars, ref i, ref charCount, bytes, 
524                                                         ref byteIndex, ref byteCount, null);
525                                         }
526                                         continue;
527                                 }
528                                 else if (ch >= 0x0391 && ch <= 0x0451)
529                                 {
530                                         // Greek subset characters.
531                                         value = (ch - 0x0391) * 2;
532                                         value = ((int)(greekToJis[value])) |
533                                                         (((int)(greekToJis[value + 1])) << 8);
534                                 }
535                                 else if (ch >= 0x2010 && ch <= 0x9FA5)
536                                 {
537                                         // This range contains the bulk of the CJK set.
538                                         value = (ch - 0x2010) * 2;
539                                         value = ((int)(cjkToJis[value])) |
540                                                         (((int)(cjkToJis[value + 1])) << 8);
541                                 }
542                                 else if (ch >= 0xE000 && ch <= 0xE757)
543                                 {
544                                         // PrivateUse
545                                         int diff = ch - 0xE000;
546                                         value = ((int)(diff / 0xBC) << 8)
547                                                 + (diff % 0xBC)
548                                                 + 0xF040;
549                                         if (value % 0x100 >= 0x7F)
550                                                 value++;
551                                 }
552                                 else if (ch >= 0xFF01 && ch <= 0xFF60)
553                                 {
554                                         value = (ch - 0xFF01) * 2;
555                                         value = ((int)(extraToJis[value])) |
556                                                         (((int)(extraToJis[value + 1])) << 8);
557                                 }
558                                 else if (ch >= 0xFF60 && ch <= 0xFFA0)
559                                 {
560                                         value = ch - 0xFF60 + 0xA0;
561                                 }
562                                 else
563                                 {
564                                         // Invalid character.
565                                         value = 0;
566                                 }
567                                 if (value == 0)
568                                 {
569                                         HandleFallback (ref buffer, chars, ref charIndex, ref charCount,
570                                                 bytes, ref posn, ref byteCount, null);
571                                 }
572                                 else if (value < 0x0100)
573                                 {
574                                         bytes[posn++] = (byte)value;
575                                 }
576                                 else if ((posn + 1) >= byteLength)
577                                 {
578                                         throw new ArgumentException
579                                                 (Strings.GetString("Arg_InsufficientSpace"),
580                                                  "bytes");
581                                 }
582                                 else if (value < 0x8000)
583                                 {
584                                         // JIS X 0208 character.
585                                         value -= 0x0100;
586                                         ch = (value / 0xBC);
587                                         value = (value % 0xBC) + 0x40;
588                                         if (value >= 0x7F)
589                                         {
590                                                 ++value;
591                                         }
592                                         if (ch < (0x9F - 0x80))
593                                         {
594                                                 bytes[posn++] = (byte)(ch + 0x81);
595                                         }
596                                         else
597                                         {
598                                                 bytes[posn++] = (byte)(ch - (0x9F - 0x80) + 0xE0);
599                                         }
600                                         bytes[posn++] = (byte)value;
601                                 }
602                                 else if (value >= 0xF040 && value <= 0xF9FC)
603                                 {
604                                         // PrivateUse
605                                         bytes[posn++] = (byte)(value / 0x100);
606                                         bytes[posn++] = (byte)(value % 0x100);
607                                 }
608                                 else
609                                 {
610                                         // JIS X 0212 character, which Shift-JIS doesn't
611                                         // support, but we've already allocated two slots.
612                                         bytes[posn++] = (byte)'?';
613                                         bytes[posn++] = (byte)'?';
614                                 }
615                         }
616
617                         // Return the final length to the caller.
618                         return posn - byteIndex;
619                 }
620 #endif
621
622                 public override int GetCharCount (byte [] bytes, int index, int count)
623                 {
624                         return new CP932Decoder (JISConvert.Convert).GetCharCount (
625                                 bytes, index, count, true);
626                 }
627
628                 public override int GetChars (
629                         byte [] bytes, int byteIndex, int byteCount,
630                         char [] chars, int charIndex)
631                 {
632                         return new CP932Decoder (JISConvert.Convert).GetChars (bytes,
633                                 byteIndex, byteCount, chars, charIndex,
634                                 true);
635                 }
636
637                 // Get the maximum number of bytes needed to encode a
638                 // specified number of characters.
639                 public override int GetMaxByteCount(int charCount)
640                 {
641                         if(charCount < 0)
642                         {
643                                 throw new ArgumentOutOfRangeException
644                                         ("charCount",
645                                          Strings.GetString("ArgRange_NonNegative"));
646                         }
647                         return charCount * 2;
648                 }
649
650                 // Get the maximum number of characters needed to decode a
651                 // specified number of bytes.
652                 public override int GetMaxCharCount(int byteCount)
653                 {
654                         if(byteCount < 0)
655                         {
656                                 throw new ArgumentOutOfRangeException
657                                         ("byteCount",
658                                          Strings.GetString("ArgRange_NonNegative"));
659                         }
660                         return byteCount;
661                 }
662
663                 // Get a decoder that handles a rolling Shift-JIS state.
664                 public override Decoder GetDecoder()
665                 {
666                         return new CP932Decoder(JISConvert.Convert);
667                 }
668
669 #if !ECMA_COMPAT
670
671                 // Get the mail body name for this encoding.
672                 public override String BodyName {
673                         get { return "iso-2022-jp"; }
674                 }
675
676                 // Get the human-readable name for this encoding.
677                 public override String EncodingName {
678                         get { return "Japanese (Shift-JIS)"; }
679                 }
680
681                 // Get the mail agent header name for this encoding.
682                 public override String HeaderName {
683                         get { return "iso-2022-jp"; }
684                 }
685
686                 // Determine if this encoding can be displayed in a Web browser.
687                 public override bool IsBrowserDisplay {
688                         get { return true; }
689                 }
690
691                 // Determine if this encoding can be saved from a Web browser.
692                 public override bool IsBrowserSave {
693                         get { return true; }
694                 }
695
696                 // Determine if this encoding can be displayed in a mail/news agent.
697                 public override bool IsMailNewsDisplay {
698                         get { return true; }
699                 }
700
701                 // Determine if this encoding can be saved from a mail/news agent.
702                 public override bool IsMailNewsSave {
703                         get { return true; }
704                 }
705
706                 // Get the IANA-preferred Web name for this encoding.
707                 public override String WebName {
708                         get { return "shift_jis"; }
709                 }
710
711                 // Get the Windows code page represented by this object.
712                 public override int WindowsCodePage {
713                         get { return SHIFTJIS_CODE_PAGE; }
714                 }
715                 
716                 // FIXME: This doesn't make sense, but without declaring this override
717                 // System.XML regresses at Encoder.Convert() in
718                 // MonoTests.System.Xml.XmlWriterSettingsTests.EncodingTest.
719                 public override Encoder GetEncoder ()
720                 {
721                         return new MonoEncodingDefaultEncoder (this);
722                 }
723
724         }; // class CP932
725
726 #endif // !ECMA_COMPAT
727
728         // Decoder that handles a rolling Shift-JIS state.
729         sealed class CP932Decoder : DbcsEncoding.DbcsDecoder
730         {
731                 private new JISConvert convert;
732                 private int last_byte_count;
733                 private int last_byte_chars;
734
735                 // Constructor.
736                 public CP932Decoder(JISConvert convert)
737                         : base (null)
738                 {
739                         this.convert = convert;
740                 }
741
742                 // Override inherited methods.
743
744                 public override int GetCharCount (
745                         byte [] bytes, int index, int count)
746                 {
747                         return GetCharCount (bytes, index, count, false);
748                 }
749
750                 public
751                 override
752                 int GetCharCount (byte [] bytes, int index, int count, bool refresh)
753                 {
754                         CheckRange (bytes, index, count);
755
756                         // Determine the total length of the converted string.
757                         int length = 0;
758                         int byteval;
759                         int last = last_byte_count;
760                         while(count > 0)
761                         {
762                                 byteval = bytes[index++];
763                                 --count;
764                                 if(last == 0)
765                                 {
766                                         if((byteval >= 0x81 && byteval <= 0x9F) ||
767                                            (byteval >= 0xE0 && byteval <= 0xEF))
768                                         {
769                                                 // First byte in a double-byte sequence.
770                                                 last = byteval;
771                                         }
772                                         ++length;
773                                 }
774                                 else
775                                 {
776                                         // Second byte in a double-byte sequence.
777                                         last = 0;
778                                 }
779                         }
780                         if (refresh) {
781                                 if (last != 0)
782                                         length++;
783                                 last_byte_count = '\0';
784                         }
785                         else
786                                 last_byte_count = last;
787
788                         // Return the total length.
789                         return length;
790                 }
791
792                 public override int GetChars (
793                         byte [] bytes, int byteIndex, int byteCount,
794                         char [] chars, int charIndex)
795                 {
796                         return GetChars (bytes, byteIndex, byteCount,
797                                          chars, charIndex, false);
798                 }
799
800                 public
801                 override
802                 int GetChars (
803                         byte [] bytes, int byteIndex, int byteCount,
804                         char [] chars, int charIndex, bool refresh)
805                 {
806                         CheckRange (bytes, byteIndex, byteCount,
807                                 chars, charIndex);
808
809                         // Decode the bytes in the buffer.
810                         int posn = charIndex;
811                         int charLength = chars.Length;
812                         int byteval, value;
813                         int last = last_byte_chars;
814 #if __PNET__
815                         byte *table = convert.jisx0208ToUnicode;
816 #else
817                         byte[] table = convert.jisx0208ToUnicode;
818 #endif
819                         while(byteCount > 0)
820                         {
821                                 byteval = bytes[byteIndex++];
822                                 --byteCount;
823                                 if(last == 0)
824                                 {
825                                         if(posn >= charLength)
826                                         {
827                                                 throw new ArgumentException
828                                                         (Strings.GetString
829                                                                 ("Arg_InsufficientSpace"), "chars");
830                                         }
831                                         if((byteval >= 0x81 && byteval <= 0x9F) ||
832                                            (byteval >= 0xE0 && byteval <= 0xEF))
833                                         {
834                                                 // First byte in a double-byte sequence.
835                                                 last = byteval;
836                                         }
837                                         else if(byteval < 0x80)
838                                         {
839                                                 // Ordinary ASCII/Latin1 character.
840                                                 chars[posn++] = (char)byteval;
841                                         }
842                                         else if(byteval >= 0xA1 && byteval <= 0xDF)
843                                         {
844                                                 // Half-width katakana character.
845                                                 chars[posn++] = (char)(byteval - 0xA1 + 0xFF61);
846                                         }
847                                         else
848                                         {
849                                                 // Invalid first byte.
850                                                 chars[posn++] = '?';
851                                         }
852                                 }
853                                 else
854                                 {
855                                         // Second byte in a double-byte sequence.
856                                         if(last >= 0x81 && last <= 0x9F)
857                                         {
858                                                 value = (last - 0x81) * 0xBC;
859                                         }
860                                         else if (last >= 0xF0 && last <= 0xFC && byteval <= 0xFC)
861                                         {
862                                                 // PrivateUse
863                                                 value = 0xE000 + (last - 0xF0) * 0xBC + byteval;
864                                                 if (byteval > 0x7F)
865                                                         value--;
866                                         }
867                                         else
868                                         {
869                                                 value = (last - 0xE0 + (0xA0 - 0x81)) * 0xBC;
870                                         }
871                                         last = 0;
872                                         if(byteval >= 0x40 && byteval <= 0x7E)
873                                         {
874                                                 value += (byteval - 0x40);
875                                         }
876                                         else if(byteval >= 0x80 && byteval <= 0xFC)
877                                         {
878                                                 value += (byteval - 0x80 + 0x3F);
879                                         }
880                                         else
881                                         {
882                                                 // Invalid second byte.
883                                                 chars[posn++] = '?';
884                                                 continue;
885                                         }
886                                         value *= 2;
887                                         value = ((int)(table[value])) |
888                                                         (((int)(table[value + 1])) << 8);
889                                         if(value != 0)
890                                         {
891                                                 chars[posn++] = (char)value;
892                                         }
893                                         else
894                                         {
895                                                 chars[posn++] = '?';
896                                         }
897                                 }
898                         }
899                         if (refresh) {
900                                 if (last != 0)
901                                         chars[posn++] = '\u30FB';
902                                 last_byte_chars = '\0';
903                         }
904                         else
905                                 last_byte_chars = last;
906
907                         // Return the final length to the caller.
908                         return posn - charIndex;
909                 }
910
911         } // class CP932Decoder
912
913         [Serializable]
914         public class ENCshift_jis : CP932
915         {
916                 public ENCshift_jis() : base() {}
917
918         }; // class ENCshift_jis
919
920 }; // namespace I18N.CJK