home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / unity / d56 / FNDUTL.ZIP / Unicode / cUnicodeCodecs.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-10-29  |  95.4 KB  |  3,054 lines

  1. {$INCLUDE ..\cDefines.inc}
  2. unit cUnicodeCodecs;
  3.  
  4. {                                                                              }
  5. {                           Unicode codecs v3.03                               }
  6. {                                                                              }
  7. {         This unit is copyright ⌐ 2002 by David Butler (david@e.co.za)        }
  8. {                                                                              }
  9. {                  This unit is part of Delphi Fundamentals.                   }
  10. {                Its original file name is cUnicodeCodecs.pas                  }
  11. {       The latest version is available from the Fundamentals home page        }
  12. {                     http://fundementals.sourceforge.net/                     }
  13. {                                                                              }
  14. {                I invite you to use this unit, free of charge.                }
  15. {        I invite you to distibute this unit, but it must be for free.         }
  16. {             I also invite you to contribute to its development,              }
  17. {             but do not distribute a modified copy of this file.              }
  18. {                                                                              }
  19. {          A forum is available on SourceForge for general discussion          }
  20. {             http://sourceforge.net/forum/forum.php?forum_id=2117             }
  21. {                                                                              }
  22. {                                                                              }
  23. { Description:                                                                 }
  24. {   Codecs (encoders/decoders) for Unicode text.                               }
  25. {                                                                              }
  26. { Revision history:                                                            }
  27. {   17/04/2002  0.01  Initial version.                                         }
  28. {                     ISO8859-1 to ISO8859-15, Mac, Win1250-Win1252, UTF-8,    }
  29. {                     UTF-16.                                                  }
  30. {   20/04/2002  0.02  Added EBCDIC-US.                                         }
  31. {                     424 lines interface. 2359 lines implementation.          }
  32. {   28/10/2002  3.03  Refactored for Fundamentals 3.                           }
  33. {                                                                              }
  34.  
  35. interface
  36.  
  37. const
  38.   UnitName      = 'cUnicodeCodecs';
  39.   UnitVersion   = '3.03';
  40.   UnitDesc      = 'Unicode codecs';
  41.   UnitCopyright = '(c) 2002 by David Butler';
  42.  
  43.  
  44.  
  45. {                                                                              }
  46. { WideChar character conversion functions                                      }
  47. {                                                                              }
  48. function  ASCIIToWideChar(const P: Char): WideChar;
  49. function  ISO8859_1ToWideChar(const P: Char): WideChar;
  50. function  ISO8859_2ToWideChar(const P: Char): WideChar;
  51. function  ISO8859_3ToWideChar(const P: Char): WideChar;
  52. function  ISO8859_4ToWideChar(const P: Char): WideChar;
  53. function  ISO8859_5ToWideChar(const P: Char): WideChar;
  54. function  ISO8859_6ToWideChar(const P: Char): WideChar;
  55. function  ISO8859_7ToWideChar(const P: Char): WideChar;
  56. function  ISO8859_8ToWideChar(const P: Char): WideChar;
  57. function  ISO8859_9ToWideChar(const P: Char): WideChar;
  58. function  ISO8859_10ToWideChar(const P: Char): WideChar;
  59. function  ISO8859_13ToWideChar(const P: Char): WideChar;
  60. function  ISO8859_14ToWideChar(const P: Char): WideChar;
  61. function  ISO8859_15ToWideChar(const P: Char): WideChar;
  62. function  KOI8_RToWideChar(const P: Char): WideChar;
  63. function  MacLatin2ToWideChar(const P: Char): WideChar;
  64. function  MacRomanToWideChar(const P: Char): WideChar;
  65. function  MacCyrillicToWideChar(const P: Char): WideChar;
  66. function  CP437ToWideChar(const P: Char): WideChar;
  67. function  Win1250ToWideChar(const P: Char): WideChar;
  68. function  Win1251ToWideChar(const P: Char): WideChar;
  69. function  Win1252ToWideChar(const P: Char): WideChar;
  70. function  EBCDIC_USToWideChar(const P: Char): WideChar;
  71.  
  72. type
  73.   TUTF8Error = (
  74.       UTF8ErrorNone,
  75.       UTF8ErrorInvalidEncoding,
  76.       UTF8ErrorIncompleteEncoding,
  77.       UTF8ErrorInvalidBuffer,
  78.       UTF8ErrorOutOfRange);
  79.  
  80. function  UTF8ToUCS4Char(const P: PChar; const Size: Integer;
  81.           var SeqSize: Integer; var Ch: UCS4Char): TUTF8Error;
  82. function  UTF8ToWideChar(const P: PChar; const Size: Integer;
  83.           var SeqSize: Integer; var Ch: WideChar): TUTF8Error;
  84.  
  85. function  WideCharToASCII(const Ch: WideChar): Char;
  86. function  WideCharToISO8859_1(const Ch: WideChar): Char;
  87. function  WideCharToISO8859_2(const Ch: WideChar): Char;
  88. function  WideCharToISO8859_3(const Ch: WideChar): Char;
  89. function  WideCharToISO8859_4(const Ch: WideChar): Char;
  90. function  WideCharToISO8859_5(const Ch: WideChar): Char;
  91. function  WideCharToISO8859_6(const Ch: WideChar): Char;
  92. function  WideCharToISO8859_7(const Ch: WideChar): Char;
  93. function  WideCharToISO8859_8(const Ch: WideChar): Char;
  94. function  WideCharToISO8859_9(const Ch: WideChar): Char;
  95. function  WideCharToISO8859_10(const Ch: WideChar): Char;
  96. function  WideCharToISO8859_13(const Ch: WideChar): Char;
  97. function  WideCharToISO8859_14(const Ch: WideChar): Char;
  98. function  WideCharToISO8859_15(const Ch: WideChar): Char;
  99. function  WideCharToKOI8_R(const Ch: WideChar): Char;
  100. function  WideCharToMacLatin2(const Ch: WideChar): Char;
  101. function  WideCharToMacRoman(const Ch: WideChar): Char;
  102. function  WideCharToMacCyrillic(const Ch: WideChar): Char;
  103. function  WideCharToCP437(const Ch: WideChar): Char;
  104. function  WideCharToWin1250(const Ch: WideChar): Char;
  105. function  WideCharToWin1251(const Ch: WideChar): Char;
  106. function  WideCharToWin1252(const Ch: WideChar): Char;
  107. function  WideCharToEBCDIC_US(const Ch: WideChar): Char;
  108.  
  109. procedure UCS4CharToUTF8(const Ch: UCS4Char; const Dest: Pointer;
  110.           const DestSize: Integer; var SeqSize: Integer);
  111. procedure WideCharToUTF8(const Ch: WideChar; const Dest: Pointer;
  112.           const DestSize: Integer; var SeqSize: Integer);
  113.  
  114.  
  115.  
  116. {                                                                              }
  117. { UTF 16 functions                                                             }
  118. {                                                                              }
  119. function  DetectUTF16Encoding(const P: PChar; const Size: Integer;
  120.           var SwapEndian: Boolean; var HeaderSize: Integer): Boolean;
  121. function  SwapUTF16Endian(const P: WideChar): WideChar;
  122.  
  123.  
  124.  
  125. {                                                                              }
  126. { Unicode codec classes                                                        }
  127. {   AUnicodeCodec is the base class for Unicode Codec implementations.         }
  128. {                                                                              }
  129. type
  130.   TUnicodeCodecType = (
  131.       ucCustom,
  132.       ucASCII,
  133.       ucISO8859_1, ucISO8859_2, ucISO8859_3, ucISO8859_4, ucISO8859_5,
  134.       ucISO8859_6, ucISO8859_7, ucISO8859_8, ucISO8859_9, ucISO8859_10,
  135.       ucISO8859_13, ucISO8859_14, ucISO8859_15,
  136.       ucKOI8_R,
  137.       ucMacLatin2, ucMacRoman, ucMacCyrillic,
  138.       ucCP437,
  139.       ucWin1250, ucWin1251, ucWin1252,
  140.       ucEBCDIC_US,
  141.       ucUTF8, ucUTF16, ucUTF16RE);
  142.   TCodecErrorAction = (eaException, eaStop, eaIgnore, eaSkip, eaReplace);
  143.   AUnicodeCodec = class
  144.   protected
  145.     FErrorAction       : TCodecErrorAction;
  146.     FDecodeReplaceChar : WideChar;
  147.  
  148.     procedure Init; virtual;
  149.  
  150.   public
  151.     class function GetUnicodeCodecType: TUnicodeCodecType; virtual; abstract;
  152.     class function GetAliasCount: Integer; virtual; abstract;
  153.     class function GetAliasByIndex(const Idx: Integer): String; virtual; abstract;
  154.  
  155.     constructor Create;
  156.  
  157.     property  ErrorAction: TCodecErrorAction read FErrorAction write FErrorAction;
  158.     property  DecodeReplaceChar: WideChar read FDecodeReplaceChar write FDecodeReplaceChar;
  159.  
  160.     procedure Decode(const Buf: Pointer; const BufSize: Integer;
  161.               const DestBuf: Pointer; const DestSize: Integer;
  162.               var ProcessedBytes, DestLength: Integer); virtual; abstract;
  163.     function  Encode(const S: PWideChar; const Length: Integer;
  164.               var ProcessedChars: Integer): String; virtual; abstract;
  165.  
  166.     function  DecodeStr(const Buf: Pointer; const BufSize: Integer;
  167.               var ProcessedBytes: Integer): WideString;
  168.     function  EncodeStr(const S: WideString;
  169.               var ProcessedChars: Integer): String;
  170.   end;
  171.   TUnicodeCodecClass = class of AUnicodeCodec;
  172.  
  173.  
  174.  
  175. {                                                                              }
  176. { Unicode codec classes                                                        }
  177. {                                                                              }
  178. type
  179.   AByteCodec = class(AUnicodeCodec)
  180.   public
  181.     function  DecodeChar(const P: Char): WideChar; virtual; abstract;
  182.     function  EncodeChar(const Ch: WideChar): Char; virtual; abstract;
  183.  
  184.     procedure Decode(const Buf: Pointer; const BufSize: Integer;
  185.               const DestBuf: Pointer; const DestSize: Integer;
  186.               var ProcessedBytes, DestLength: Integer); override;
  187.     function  Encode(const S: PWideChar; const Length: Integer;
  188.               var ProcessedChars: Integer): String; override;
  189.   end;
  190.  
  191.   TASCIICodec = class(AByteCodec)
  192.   public
  193.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  194.     class function GetAliasCount: Integer; override;
  195.     class function GetAliasByIndex(const Idx: Integer): String; override;
  196.  
  197.     function  DecodeChar(const P: Char): WideChar; override;
  198.     function  EncodeChar(const Ch: WideChar): Char; override;
  199.   end;
  200.  
  201.   TISO8859_1Codec = class(AByteCodec)
  202.   public
  203.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  204.     class function GetAliasCount: Integer; override;
  205.     class function GetAliasByIndex(const Idx: Integer): String; override;
  206.  
  207.     function  DecodeChar(const P: Char): WideChar; override;
  208.     function  EncodeChar(const Ch: WideChar): Char; override;
  209.   end;
  210.  
  211.   TISO8859_2Codec = class(AByteCodec)
  212.   public
  213.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  214.     class function GetAliasCount: Integer; override;
  215.     class function GetAliasByIndex(const Idx: Integer): String; override;
  216.  
  217.     function  DecodeChar(const P: Char): WideChar; override;
  218.     function  EncodeChar(const Ch: WideChar): Char; override;
  219.   end;
  220.  
  221.   TISO8859_3Codec = class(AByteCodec)
  222.   public
  223.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  224.     class function GetAliasCount: Integer; override;
  225.     class function GetAliasByIndex(const Idx: Integer): String; override;
  226.  
  227.     function  DecodeChar(const P: Char): WideChar; override;
  228.     function  EncodeChar(const Ch: WideChar): Char; override;
  229.   end;
  230.  
  231.   TISO8859_4Codec = class(AByteCodec)
  232.   public
  233.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  234.     class function GetAliasCount: Integer; override;
  235.     class function GetAliasByIndex(const Idx: Integer): String; override;
  236.  
  237.     function  DecodeChar(const P: Char): WideChar; override;
  238.     function  EncodeChar(const Ch: WideChar): Char; override;
  239.   end;
  240.  
  241.   TISO8859_5Codec = class(AByteCodec)
  242.   public
  243.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  244.     class function GetAliasCount: Integer; override;
  245.     class function GetAliasByIndex(const Idx: Integer): String; override;
  246.  
  247.     function  DecodeChar(const P: Char): WideChar; override;
  248.     function  EncodeChar(const Ch: WideChar): Char; override;
  249.   end;
  250.  
  251.   TISO8859_6Codec = class(AByteCodec)
  252.   public
  253.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  254.     class function GetAliasCount: Integer; override;
  255.     class function GetAliasByIndex(const Idx: Integer): String; override;
  256.  
  257.     function  DecodeChar(const P: Char): WideChar; override;
  258.     function  EncodeChar(const Ch: WideChar): Char; override;
  259.   end;
  260.  
  261.   TISO8859_7Codec = class(AByteCodec)
  262.   public
  263.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  264.     class function GetAliasCount: Integer; override;
  265.     class function GetAliasByIndex(const Idx: Integer): String; override;
  266.  
  267.     function  DecodeChar(const P: Char): WideChar; override;
  268.     function  EncodeChar(const Ch: WideChar): Char; override;
  269.   end;
  270.  
  271.   TISO8859_8Codec = class(AByteCodec)
  272.   public
  273.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  274.     class function GetAliasCount: Integer; override;
  275.     class function GetAliasByIndex(const Idx: Integer): String; override;
  276.  
  277.     function  DecodeChar(const P: Char): WideChar; override;
  278.     function  EncodeChar(const Ch: WideChar): Char; override;
  279.   end;
  280.  
  281.   TISO8859_9Codec = class(AByteCodec)
  282.   public
  283.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  284.     class function GetAliasCount: Integer; override;
  285.     class function GetAliasByIndex(const Idx: Integer): String; override;
  286.  
  287.     function  DecodeChar(const P: Char): WideChar; override;
  288.     function  EncodeChar(const Ch: WideChar): Char; override;
  289.   end;
  290.  
  291.   TISO8859_10Codec = class(AByteCodec)
  292.   public
  293.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  294.     class function GetAliasCount: Integer; override;
  295.     class function GetAliasByIndex(const Idx: Integer): String; override;
  296.  
  297.     function  DecodeChar(const P: Char): WideChar; override;
  298.     function  EncodeChar(const Ch: WideChar): Char; override;
  299.   end;
  300.  
  301.   TISO8859_13Codec = class(AByteCodec)
  302.   public
  303.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  304.     class function GetAliasCount: Integer; override;
  305.     class function GetAliasByIndex(const Idx: Integer): String; override;
  306.  
  307.     function  DecodeChar(const P: Char): WideChar; override;
  308.     function  EncodeChar(const Ch: WideChar): Char; override;
  309.   end;
  310.  
  311.   TISO8859_14Codec = class(AByteCodec)
  312.   public
  313.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  314.     class function GetAliasCount: Integer; override;
  315.     class function GetAliasByIndex(const Idx: Integer): String; override;
  316.  
  317.     function  DecodeChar(const P: Char): WideChar; override;
  318.     function  EncodeChar(const Ch: WideChar): Char; override;
  319.   end;
  320.  
  321.   TISO8859_15Codec = class(AByteCodec)
  322.   public
  323.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  324.     class function GetAliasCount: Integer; override;
  325.     class function GetAliasByIndex(const Idx: Integer): String; override;
  326.  
  327.     function  DecodeChar(const P: Char): WideChar; override;
  328.     function  EncodeChar(const Ch: WideChar): Char; override;
  329.   end;
  330.  
  331.   TKOI8_RCodec = class(AByteCodec)
  332.   public
  333.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  334.     class function GetAliasCount: Integer; override;
  335.     class function GetAliasByIndex(const Idx: Integer): String; override;
  336.  
  337.     function  DecodeChar(const P: Char): WideChar; override;
  338.     function  EncodeChar(const Ch: WideChar): Char; override;
  339.   end;
  340.  
  341.   TMacLatin2Codec = class(AByteCodec)
  342.   public
  343.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  344.     class function GetAliasCount: Integer; override;
  345.     class function GetAliasByIndex(const Idx: Integer): String; override;
  346.  
  347.     function  DecodeChar(const P: Char): WideChar; override;
  348.     function  EncodeChar(const Ch: WideChar): Char; override;
  349.   end;
  350.  
  351.   TMacRomanCodec = class(AByteCodec)
  352.   public
  353.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  354.     class function GetAliasCount: Integer; override;
  355.     class function GetAliasByIndex(const Idx: Integer): String; override;
  356.  
  357.     function  DecodeChar(const P: Char): WideChar; override;
  358.     function  EncodeChar(const Ch: WideChar): Char; override;
  359.   end;
  360.  
  361.   TMacCyrillicCodec = class(AByteCodec)
  362.   public
  363.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  364.     class function GetAliasCount: Integer; override;
  365.     class function GetAliasByIndex(const Idx: Integer): String; override;
  366.  
  367.     function  DecodeChar(const P: Char): WideChar; override;
  368.     function  EncodeChar(const Ch: WideChar): Char; override;
  369.   end;
  370.  
  371.   TCP437Codec = class(AByteCodec)
  372.   public
  373.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  374.     class function GetAliasCount: Integer; override;
  375.     class function GetAliasByIndex(const Idx: Integer): String; override;
  376.  
  377.     function  DecodeChar(const P: Char): WideChar; override;
  378.     function  EncodeChar(const Ch: WideChar): Char; override;
  379.   end;
  380.  
  381.   TWin1250Codec = class(AByteCodec)
  382.   public
  383.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  384.     class function GetAliasCount: Integer; override;
  385.     class function GetAliasByIndex(const Idx: Integer): String; override;
  386.  
  387.     function  DecodeChar(const P: Char): WideChar; override;
  388.     function  EncodeChar(const Ch: WideChar): Char; override;
  389.   end;
  390.  
  391.   TWin1251Codec = class(AByteCodec)
  392.   public
  393.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  394.     class function GetAliasCount: Integer; override;
  395.     class function GetAliasByIndex(const Idx: Integer): String; override;
  396.  
  397.     function  DecodeChar(const P: Char): WideChar; override;
  398.     function  EncodeChar(const Ch: WideChar): Char; override;
  399.   end;
  400.  
  401.   TWin1252Codec = class(AByteCodec)
  402.   public
  403.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  404.     class function GetAliasCount: Integer; override;
  405.     class function GetAliasByIndex(const Idx: Integer): String; override;
  406.  
  407.     function  DecodeChar(const P: Char): WideChar; override;
  408.     function  EncodeChar(const Ch: WideChar): Char; override;
  409.   end;
  410.  
  411.   TEBCDIC_USCodec = class(AByteCodec)
  412.   public
  413.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  414.     class function GetAliasCount: Integer; override;
  415.     class function GetAliasByIndex(const Idx: Integer): String; override;
  416.  
  417.     function  DecodeChar(const P: Char): WideChar; override;
  418.     function  EncodeChar(const Ch: WideChar): Char; override;
  419.   end;
  420.  
  421.   TUTF8Codec = class(AUnicodeCodec)
  422.   public
  423.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  424.     class function GetAliasCount: Integer; override;
  425.     class function GetAliasByIndex(const Idx: Integer): String; override;
  426.  
  427.     procedure Decode(const Buf: Pointer; const BufSize: Integer;
  428.               const DestBuf: Pointer; const DestSize: Integer;
  429.               var ProcessedBytes, DestLength: Integer); override;
  430.     function  Encode(const S: PWideChar; const Length: Integer;
  431.               var ProcessedChars: Integer): String; override;
  432.   end;
  433.  
  434.   TUTF16Codec = class(AUnicodeCodec) // UTF-16 System Endian
  435.   protected
  436.     FSwapEndian : Boolean;
  437.  
  438.     procedure Init; override;
  439.  
  440.   public
  441.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  442.     class function GetAliasCount: Integer; override;
  443.     class function GetAliasByIndex(const Idx: Integer): String; override;
  444.  
  445.     procedure Decode(const Buf: Pointer; const BufSize: Integer;
  446.               const DestBuf: Pointer; const DestSize: Integer;
  447.               var ProcessedBytes, DestLength: Integer); override;
  448.     function  Encode(const S: PWideChar; const Length: Integer;
  449.               var ProcessedChars: Integer): String; override;
  450.   end;
  451.  
  452.   TUTF16RECodec = class(TUTF16Codec) // UTF-16 Reverse Endian
  453.   protected
  454.     procedure Init; override;
  455.  
  456.   public
  457.     class function GetUnicodeCodecType: TUnicodeCodecType; override;
  458.   end;
  459.  
  460. function  GetUnicodeCodecClassByType(const CodecType: TUnicodeCodecType): TUnicodeCodecClass;
  461. function  GetUnicodeCodecClassByName(const Name: String): TUnicodeCodecClass;
  462.  
  463.  
  464.  
  465. {                                                                              }
  466. { Unicode conversion functions                                                 }
  467. {                                                                              }
  468. function  DecodeUnicodeEncoding(const Codec: TUnicodeCodecType; const Buf: Pointer;
  469.           const BufSize: Integer; var ProcessedBytes: Integer): WideString;
  470. function  EncodeUnicodeEncoding(const Codec: TUnicodeCodecType; const S: WideString;
  471.           var ProcessedChars: Integer): String;
  472.  
  473.  
  474.  
  475. {                                                                              }
  476. { Character-set conversion functions                                           }
  477. {                                                                              }
  478. function  IsASCIIStr(const S: String): Boolean;
  479. function  ISO8859_1ToUTF8(const S: String): String;
  480. function  UTF8ToWideString(const S: String): WideString;
  481. function  WideStringToUTF8(const S: WideString): String;
  482. function  UCS4CharToUTF8Str(const Ch: UCS4Char): String;
  483. function  ASCIIToWideString(const S: String): WideString;
  484.  
  485.  
  486.  
  487. implementation
  488.  
  489. uses
  490.   // Delphi
  491.   SysUtils;
  492.  
  493.  
  494.  
  495. {                                                                              }
  496. { AUnicodeCodec                                                                }
  497. {                                                                              }
  498. constructor AUnicodeCodec.Create;
  499. begin
  500.   inherited Create;
  501.   Init;
  502. end;
  503.  
  504. procedure AUnicodeCodec.Init;
  505. begin
  506.   FErrorAction := eaException;
  507.   FDecodeReplaceChar := WideChar(#$FFFD);
  508. end;
  509.  
  510. function AUnicodeCodec.DecodeStr(const Buf: Pointer; const BufSize: Integer;
  511.     var ProcessedBytes: Integer): WideString;
  512. var P: PChar;
  513.     Q: PWideChar;
  514.     L, M, I, J: Integer;
  515. begin
  516.   P := Buf;
  517.   L := BufSize;
  518.   if not Assigned(P) or (L <= 0) then
  519.     begin
  520.       ProcessedBytes := 0;
  521.       Result := '';
  522.       exit;
  523.     end;
  524.   SetLength(Result, BufSize);
  525.   M := 0;
  526.   Repeat
  527.     Q := Pointer(Result);
  528.     Inc(Q, M);
  529.     Decode(P, L, Q, BufSize, I, J);
  530.     Dec(L, I);
  531.     Inc(P, I);
  532.     Inc(M, J);
  533.     if L > 0 then
  534.       SetLength(Result, M + BufSize);
  535.   Until L = 0;
  536.   SetLength(Result, M);
  537. end;
  538.  
  539. function AUnicodeCodec.EncodeStr(const S: WideString; var ProcessedChars: Integer): String;
  540. begin
  541.   Result := Encode(Pointer(S), Length(S), ProcessedChars);
  542. end;
  543.  
  544.  
  545.  
  546. {                                                                              }
  547. { AByteCodec                                                                   }
  548. {                                                                              }
  549. procedure AByteCodec.Decode(const Buf: Pointer; const BufSize: Integer; const DestBuf: Pointer; const DestSize: Integer; var ProcessedBytes, DestLength: Integer);
  550. var P: PChar;
  551.     Q: PWideChar;
  552.     I, L, M, C: Integer;
  553. begin
  554.   P := Buf;
  555.   Q := DestBuf;
  556.   C := DestSize div Sizeof(WideChar);
  557.   if not Assigned(P) or (BufSize <= 0) or not Assigned(Q) or (C <= 0) then
  558.     begin
  559.       ProcessedBytes := 0;
  560.       DestLength := 0;
  561.       exit;
  562.     end;
  563.   L := 0;
  564.   M := 0;
  565.   For I := 1 to BufSize do
  566.     try
  567.       if L >= C then
  568.         break;
  569.       Q^ := DecodeChar(P^);
  570.       Inc(P);
  571.       Inc(Q);
  572.       Inc(L);
  573.       Inc(M);
  574.     except
  575.       Case FErrorAction of
  576.         eaException: raise;
  577.         eaSkip:
  578.           begin
  579.             Inc(P);
  580.             Inc(M);
  581.           end;
  582.         eaIgnore:
  583.           begin
  584.             Q^ := WideChar(P^);
  585.             Inc(P);
  586.             Inc(Q);
  587.             Inc(L);
  588.             Inc(M);
  589.           end;
  590.         eaReplace:
  591.           begin
  592.             Q^ := FDecodeReplaceChar;
  593.             Inc(P);
  594.             Inc(Q);
  595.             Inc(L);
  596.             Inc(M);
  597.           end;
  598.       end;
  599.     end;
  600.   DestLength := L;
  601.   ProcessedBytes := M;
  602. end;
  603.  
  604. function AByteCodec.Encode(const S: PWideChar; const Length: Integer;
  605.     var ProcessedChars: Integer): String;
  606. var P: PChar;
  607.     Q: PWideChar;
  608.     I, L: Integer;
  609. begin
  610.   Q := S;
  611.   if not Assigned(Q) or (Length <= 0) then
  612.     begin
  613.       ProcessedChars := 0;
  614.       Result := '';
  615.       exit;
  616.     end;
  617.   SetLength(Result, Length);
  618.   L := 0;
  619.   P := Pointer(Result);
  620.   For I := 1 to Length do
  621.     try
  622.       P^ := EncodeChar(Q^);
  623.       Inc(P);
  624.       Inc(Q);
  625.       Inc(L);
  626.     except
  627.       Case FErrorAction of
  628.         eaException : raise;
  629.         eaStop      : break;
  630.         eaSkip:
  631.           begin
  632.             Inc(Q);
  633.             Inc(L);
  634.           end;
  635.         eaIgnore:
  636.           begin
  637.             P^ := Char(Q^);
  638.             Inc(P);
  639.             Inc(Q);
  640.             Inc(L);
  641.           end;
  642.         eaReplace:
  643.           begin
  644.             P^ := Char(FDecodeReplaceChar);
  645.             Inc(P);
  646.             Inc(Q);
  647.             Inc(L);
  648.           end;
  649.       end;
  650.     end;
  651.   ProcessedChars := L;
  652. end;
  653.  
  654.  
  655.  
  656. {                                                                              }
  657. { ASCII                                                                        }
  658. {                                                                              }
  659. const
  660.   ASCIIAliases = 15;
  661.   ASCIIAlias: Array[1..ASCIIAliases] of String = (
  662.       'ANSI_X3.4-1968', 'ANSI_X3.4-1986', 'iso-ir-6',
  663.       'ISO_646.irv:1991', 'ISO_646.irv', 'ISO_646',
  664.       'ISO-646', 'ISO646', 'ISO646-US',
  665.       'ASCII', 'US-ASCII', 'us',
  666.       'IBM367', 'cp367', 'csASCII');
  667.  
  668. function ASCIIToWideChar(const P: Char): WideChar;
  669. begin
  670.   if Ord(P) >= $80 then
  671.     raise EConvertError.Create('Invalid ASCII encoding');
  672.   Result := WideChar(Ord(P));
  673. end;
  674.  
  675. function WideCharToASCII(const Ch: WideChar): Char;
  676. begin
  677.   if Ord(Ch) >= $80 then
  678.     raise EConvertError.Create('Can not convert to ASCII');
  679.   Result := Char(Ord(Ch));
  680. end;
  681.  
  682. class function TASCIICodec.GetUnicodeCodecType: TUnicodeCodecType;
  683. begin
  684.   Result := ucASCII;
  685. end;
  686.  
  687. class function TASCIICodec.GetAliasCount: Integer;
  688. begin
  689.   Result := ASCIIAliases;
  690. end;
  691.  
  692. class function TASCIICodec.GetAliasByIndex(const Idx: Integer): String;
  693. begin
  694.   Result := ASCIIAlias[Idx];
  695. end;
  696.  
  697. function TASCIICodec.DecodeChar(const P: Char): WideChar;
  698. begin
  699.   Result := ASCIIToWideChar(P);
  700. end;
  701.  
  702. function TASCIICodec.EncodeChar(const Ch: WideChar): Char;
  703. begin
  704.   Result := WideCharToASCII(Ch);
  705. end;
  706.  
  707.  
  708.  
  709.  
  710. {                                                                              }
  711. { ISO-8859-1 - Latin 1                                                         }
  712. { Western Europe and Americas: Afrikaans, Basque, Catalan, Danish, Dutch,      }
  713. { English, Faeroese, Finnish, French, Galician, German, Icelandic, Irish,      }
  714. { Italian, Norwegian, Portuguese, Spanish and Swedish.                         }
  715. { Default for HTTP Protocol                                                    }
  716. {                                                                              }
  717. const
  718.   ISO8859_1Aliases = 8;
  719.   ISO8859_1Alias: Array[1..ISO8859_1Aliases] of String = (
  720.       'iso-ir-100', 'ISO_8859-1:1987', 'ISO_8859-1', 'ISO-8859-1',
  721.       'latin1', 'l1', 'IBM819', 'cp819');
  722.  
  723. function ISO8859_1ToWideChar(const P: Char): WideChar;
  724. begin
  725.   Result := WideChar(Ord(P));
  726. end;
  727.  
  728. function WideCharToISO8859_1(const Ch: WideChar): Char;
  729. begin
  730.   if Ord(Ch) >= $100 then
  731.     raise EConvertError.Create('Can not convert to ISO-8859-1');
  732.   Result := Char(Ord(Ch));
  733. end;
  734.  
  735. class function TISO8859_1Codec.GetUnicodeCodecType: TUnicodeCodecType;
  736. begin
  737.   Result := ucISO8859_1;
  738. end;
  739.  
  740. class function TISO8859_1Codec.GetAliasCount: Integer;
  741. begin
  742.   Result := ISO8859_1Aliases;
  743. end;
  744.  
  745. class function TISO8859_1Codec.GetAliasByIndex(const Idx: Integer): String;
  746. begin
  747.   Result := ISO8859_1Alias[Idx];
  748. end;
  749.  
  750. function TISO8859_1Codec.DecodeChar(const P: Char): WideChar;
  751. begin
  752.   Result := ISO8859_1ToWideChar(P);
  753. end;
  754.  
  755. function TISO8859_1Codec.EncodeChar(const Ch: WideChar): Char;
  756. begin
  757.   Result := WideCharToISO8859_1(Ch);
  758. end;
  759.  
  760.  
  761.  
  762. {                                                                              }
  763. { ISO-8859-2 Latin 2                                                           }
  764. { Latin-written Slavic and Central European languages: Czech, German,          }
  765. { Hungarian, Polish, Romanian, Croatian, Slovak, Slovene.                      }
  766. {                                                                              }
  767. const
  768.   ISO8859_2Aliases = 6;
  769.   ISO8859_2Alias: Array[1..ISO8859_2Aliases] of String = (
  770.       'iso-ir-101', 'ISO_8859-2:1987', 'ISO_8859-2', 'ISO-8859-2',
  771.       'latin2', 'l2');
  772.  
  773. const
  774.   ISO8859_2Map: Array[$A0..$FF] of WideChar = (
  775.       #$00A0, #$0104, #$02D8, #$0141, #$00A4, #$013D, #$015A, #$00A7,
  776.       #$00A8, #$0160, #$015E, #$0164, #$0179, #$00AD, #$017D, #$017B,
  777.       #$00B0, #$0105, #$02DB, #$0142, #$00B4, #$013E, #$015B, #$02C7,
  778.       #$00B8, #$0161, #$015F, #$0165, #$017A, #$02DD, #$017E, #$017C,
  779.       #$0154, #$00C1, #$00C2, #$0102, #$00C4, #$0139, #$0106, #$00C7,
  780.       #$010C, #$00C9, #$0118, #$00CB, #$011A, #$00CD, #$00CE, #$010E,
  781.       #$0110, #$0143, #$0147, #$00D3, #$00D4, #$0150, #$00D6, #$00D7,
  782.       #$0158, #$016E, #$00DA, #$0170, #$00DC, #$00DD, #$0162, #$00DF,
  783.       #$0155, #$00E1, #$00E2, #$0103, #$00E4, #$013A, #$0107, #$00E7,
  784.       #$010D, #$00E9, #$0119, #$00EB, #$011B, #$00ED, #$00EE, #$010F,
  785.       #$0111, #$0144, #$0148, #$00F3, #$00F4, #$0151, #$00F6, #$00F7,
  786.       #$0159, #$016F, #$00FA, #$0171, #$00FC, #$00FD, #$0163, #$02D9);
  787.  
  788. function ISO8859_2ToWideChar(const P: Char): WideChar;
  789. begin
  790.   if Ord(P) >= $A0 then
  791.     Result := ISO8859_2Map[Ord(P)] else
  792.     Result := WideChar(Ord(P));
  793. end;
  794.  
  795. function WideCharToISO8859_2(const Ch: WideChar): Char;
  796. var I: Byte;
  797. begin
  798.   if Ord(Ch) < $A0 then
  799.     begin
  800.       Result := Char(Ord(Ch));
  801.       exit;
  802.     end;
  803.   For I := $A0 to $FF do
  804.     if ISO8859_2Map[I] = Ch then
  805.       begin
  806.         Result := Char(I);
  807.         exit;
  808.       end;
  809.   raise EConvertError.Create('Can not convert to ISO-8859-2');
  810. end;
  811.  
  812. class function TISO8859_2Codec.GetUnicodeCodecType: TUnicodeCodecType;
  813. begin
  814.   Result := ucISO8859_2;
  815. end;
  816.  
  817. class function TISO8859_2Codec.GetAliasCount: Integer;
  818. begin
  819.   Result := ISO8859_2Aliases;
  820. end;
  821.  
  822. class function TISO8859_2Codec.GetAliasByIndex(const Idx: Integer): String;
  823. begin
  824.   Result := ISO8859_2Alias[Idx];
  825. end;
  826.  
  827. function TISO8859_2Codec.DecodeChar(const P: Char): WideChar;
  828. begin
  829.   Result := ISO8859_2ToWideChar(P);
  830. end;
  831.  
  832. function TISO8859_2Codec.EncodeChar(const Ch: WideChar): Char;
  833. begin
  834.   Result := WideCharToISO8859_2(Ch);
  835. end;
  836.  
  837.  
  838.  
  839. {                                                                              }
  840. { ISO-8859-3 - Latin 3                                                         }
  841. { Esperanto, Galician, Maltese, and Turkish.                                   }
  842. {                                                                              }
  843. const
  844.   ISO8859_3Aliases = 6;
  845.   ISO8859_3Alias: Array[1..ISO8859_3Aliases] of String = (
  846.       'iso-ir-109', 'ISO_8859-3:1988', 'ISO_8859-3', 'ISO-8859-3',
  847.       'latin3', 'l3');
  848.  
  849. const
  850.   ISO8859_3Map: Array[$A0..$FF] of WideChar = (
  851.       #$00A0, #$0126, #$02D8, #$00A3, #$00A4, #$0000, #$0124, #$00A7,
  852.       #$00A8, #$0130, #$015E, #$011E, #$0134, #$00AD, #$0000, #$017B,
  853.       #$00B0, #$0127, #$00B2, #$00B3, #$00B4, #$00B5, #$0125, #$00B7,
  854.       #$00B8, #$0131, #$015F, #$011F, #$0135, #$00BD, #$0000, #$017C,
  855.       #$00C0, #$00C1, #$00C2, #$0000, #$00C4, #$010A, #$0108, #$00C7,
  856.       #$00C8, #$00C9, #$00CA, #$00CB, #$00CC, #$00CD, #$00CE, #$00CF,
  857.       #$0000, #$00D1, #$00D2, #$00D3, #$00D4, #$0120, #$00D6, #$00D7,
  858.       #$011C, #$00D9, #$00DA, #$00DB, #$00DC, #$016C, #$015C, #$00DF,
  859.       #$00E0, #$00E1, #$00E2, #$0000, #$00E4, #$010B, #$0109, #$00E7,
  860.       #$00E8, #$00E9, #$00EA, #$00EB, #$00EC, #$00ED, #$00EE, #$00EF,
  861.       #$0000, #$00F1, #$00F2, #$00F3, #$00F4, #$0121, #$00F6, #$00F7,
  862.       #$011D, #$00F9, #$00FA, #$00FB, #$00FC, #$016D, #$015D, #$02D9);
  863.  
  864. function ISO8859_3ToWideChar(const P: Char): WideChar;
  865. begin
  866.   if Ord(P) >= $A0 then
  867.     begin
  868.       Result := ISO8859_3Map[Ord(P)];
  869.       if Result = #$0000 then
  870.         raise EConvertError.Create('Invalid ISO-8859-3 encoding');
  871.     end else
  872.     Result := WideChar(Ord(P));
  873. end;
  874.  
  875. function WideCharToISO8859_3(const Ch: WideChar): Char;
  876. var I: Byte;
  877. begin
  878.   if Ord(Ch) < $A0 then
  879.     begin
  880.       Result := Char(Ord(Ch));
  881.       exit;
  882.     end;
  883.   For I := $A0 to $FF do
  884.     if ISO8859_3Map[I] = Ch then
  885.       begin
  886.         Result := Char(I);
  887.         exit;
  888.       end;
  889.   raise EConvertError.Create('Can not convert to ISO-8859-3');
  890. end;
  891.  
  892. class function TISO8859_3Codec.GetUnicodeCodecType: TUnicodeCodecType;
  893. begin
  894.   Result := ucISO8859_3;
  895. end;
  896.  
  897. class function TISO8859_3Codec.GetAliasCount: Integer;
  898. begin
  899.   Result := ISO8859_3Aliases;
  900. end;
  901.  
  902. class function TISO8859_3Codec.GetAliasByIndex(const Idx: Integer): String;
  903. begin
  904.   Result := ISO8859_3Alias[Idx];
  905. end;
  906.  
  907. function TISO8859_3Codec.DecodeChar(const P: Char): WideChar;
  908. begin
  909.   Result := ISO8859_3ToWideChar(P);
  910. end;
  911.  
  912. function TISO8859_3Codec.EncodeChar(const Ch: WideChar): Char;
  913. begin
  914.   Result := WideCharToISO8859_3(Ch);
  915. end;
  916.  
  917.  
  918.  
  919. {                                                                              }
  920. { ISO-8859-4 - Latin 4                                                         }
  921. { Scandinavia/Baltic (mostly covered by 8859-1 also): Estonian, Latvian, and   }
  922. { Lithuanian. It is an incomplete predecessor of Latin 6.                      }
  923. {                                                                              }
  924. const
  925.   ISO8859_4Aliases = 6;
  926.   ISO8859_4Alias: Array[1..ISO8859_4Aliases] of String = (
  927.       'iso-ir-110', 'ISO_8859-4:1988', 'ISO_8859-4', 'ISO-8859-4',
  928.       'latin4', 'l4');
  929.  
  930. const
  931.   ISO8859_4Map: Array[$A0..$FF] of WideChar = (
  932.       #$00A0, #$0104, #$0138, #$0156, #$00A4, #$0128, #$013B, #$00A7,
  933.       #$00A8, #$0160, #$0112, #$0122, #$0166, #$00AD, #$017D, #$00AF,
  934.       #$00B0, #$0105, #$02DB, #$0157, #$00B4, #$0129, #$013C, #$02C7,
  935.       #$00B8, #$0161, #$0113, #$0123, #$0167, #$014A, #$017E, #$014B,
  936.       #$0100, #$00C1, #$00C2, #$00C3, #$00C4, #$00C5, #$00C6, #$012E,
  937.       #$010C, #$00C9, #$0118, #$00CB, #$0116, #$00CD, #$00CE, #$012A,
  938.       #$0110, #$0145, #$014C, #$0136, #$00D4, #$00D5, #$00D6, #$00D7,
  939.       #$00D8, #$0172, #$00DA, #$00DB, #$00DC, #$0168, #$016A, #$00DF,
  940.       #$0101, #$00E1, #$00E2, #$00E3, #$00E4, #$00E5, #$00E6, #$012F,
  941.       #$010D, #$00E9, #$0119, #$00EB, #$0117, #$00ED, #$00EE, #$012B,
  942.       #$0111, #$0146, #$014D, #$0137, #$00F4, #$00F5, #$00F6, #$00F7,
  943.       #$00F8, #$0173, #$00FA, #$00FB, #$00FC, #$0169, #$016B, #$02D9);
  944.  
  945. function ISO8859_4ToWideChar(const P: Char): WideChar;
  946. begin
  947.   if Ord(P) >= $A0 then
  948.     Result := ISO8859_4Map[Ord(P)] else
  949.     Result := WideChar(Ord(P));
  950. end;
  951.  
  952. function WideCharToISO8859_4(const Ch: WideChar): Char;
  953. var I: Byte;
  954. begin
  955.   if Ord(Ch) < $A0 then
  956.     begin
  957.       Result := Char(Ord(Ch));
  958.       exit;
  959.     end;
  960.   For I := $A0 to $FF do
  961.     if ISO8859_4Map[I] = Ch then
  962.       begin
  963.         Result := Char(I);
  964.         exit;
  965.       end;
  966.   raise EConvertError.Create('Can not convert to ISO-8859-4');
  967. end;
  968.  
  969. class function TISO8859_4Codec.GetUnicodeCodecType: TUnicodeCodecType;
  970. begin
  971.   Result := ucISO8859_4;
  972. end;
  973.  
  974. class function TISO8859_4Codec.GetAliasCount: Integer;
  975. begin
  976.   Result := ISO8859_4Aliases;
  977. end;
  978.  
  979. class function TISO8859_4Codec.GetAliasByIndex(const Idx: Integer): String;
  980. begin
  981.   Result := ISO8859_4Alias[Idx];
  982. end;
  983.  
  984. function TISO8859_4Codec.DecodeChar(const P: Char): WideChar;
  985. begin
  986.   Result := ISO8859_4ToWideChar(P);
  987. end;
  988.  
  989. function TISO8859_4Codec.EncodeChar(const Ch: WideChar): Char;
  990. begin
  991.   Result := WideCharToISO8859_4(Ch);
  992. end;
  993.  
  994.  
  995.  
  996. {                                                                              }
  997. { ISO-8859-5 - Cyrillic                                                        }
  998. { Bulgarian, Byelorussian, Macedonian, Russian, Serbian and Ukrainian.         }
  999. {                                                                              }
  1000. const
  1001.   ISO8859_5Aliases = 5;
  1002.   ISO8859_5Alias: Array[1..ISO8859_5Aliases] of String = (
  1003.       'iso-ir-144', 'ISO_8859-5:1988', 'ISO_8859-5', 'ISO-8859-5',
  1004.       'cyrillic');
  1005.  
  1006. function ISO8859_5ToWideChar(const P: Char): WideChar;
  1007. begin
  1008.   Case Ord(P) of
  1009.     $00..$A0, $AD : Result := WideChar(Ord(P));
  1010.     $F0 : Result := #$2116;
  1011.     $FD : Result := #$00A7;
  1012.   else
  1013.     Result := WideChar(Ord(P) + $0360);
  1014.   end;
  1015. end;
  1016.  
  1017. function WideCharToISO8859_5(const Ch: WideChar): Char;
  1018. begin
  1019.   if Ord(Ch) <= $A0 then
  1020.     Result := Char(Ord(Ch)) else
  1021.     Case Ch of
  1022.       #$2116 : Result := #$F0;
  1023.       #$00A7 : Result := #$FD;
  1024.       #$00AD : Result := #$AD;
  1025.       #$0401..#$045F :
  1026.         Case Ch of
  1027.           #$0450, #$045D, #$040D :
  1028.             raise EConvertError.Create('Can not convert to ISO-8859-5');
  1029.         else
  1030.           Result := Char(Ord(Ch) - $0360);
  1031.         end;
  1032.     else
  1033.       raise EConvertError.Create('Can not convert to ISO-8859-5');
  1034.     end;
  1035. end;
  1036.  
  1037. class function TISO8859_5Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1038. begin
  1039.   Result := ucISO8859_5;
  1040. end;
  1041.  
  1042. class function TISO8859_5Codec.GetAliasCount: Integer;
  1043. begin
  1044.   Result := ISO8859_5Aliases;
  1045. end;
  1046.  
  1047. class function TISO8859_5Codec.GetAliasByIndex(const Idx: Integer): String;
  1048. begin
  1049.   Result := ISO8859_5Alias[Idx];
  1050. end;
  1051.  
  1052. function TISO8859_5Codec.DecodeChar(const P: Char): WideChar;
  1053. begin
  1054.   Result := ISO8859_5ToWideChar(P);
  1055. end;
  1056.  
  1057. function TISO8859_5Codec.EncodeChar(const Ch: WideChar): Char;
  1058. begin
  1059.   Result := WideCharToISO8859_5(Ch);
  1060. end;
  1061.  
  1062.  
  1063.  
  1064. {                                                                              }
  1065. { ISO-8859-6 - Arabic                                                          }
  1066. { Non-accented Arabic.                                                         }
  1067. {                                                                              }
  1068. const
  1069.   ISO8859_6Aliases = 7;
  1070.   ISO8859_6Alias: Array[1..ISO8859_6Aliases] of String = (
  1071.       'iso-ir-127', 'ISO_8859-6:1987', 'ISO_8859-6', 'ISO-8859-6',
  1072.       'ECMA-114', 'ASMO-708', 'arabic');
  1073.  
  1074. function ISO8859_6ToWideChar(const P: Char): WideChar;
  1075. begin
  1076.   Case Ord(P) of
  1077.     $00..$A0, $A4, $AD : Result := WideChar(Ord(P));
  1078.     $AC, $BB, $BF, $C1..$DA, $E0..$F2 : Result := WideChar(Ord(P) + $0580);
  1079.   else
  1080.     raise EConvertError.Create('Invalid ISO-8859-6 encoding');
  1081.   end;
  1082. end;
  1083.  
  1084. function WideCharToISO8859_6(const Ch: WideChar): Char;
  1085. begin
  1086.   if Ord(Ch) <= $A0 then
  1087.     Result := Char(Ord(Ch)) else
  1088.     Case Ch of
  1089.       #$00A4 : Result := #$A4;
  1090.       #$00AD : Result := #$AD;
  1091.       #$062C, #$063B, #$063F, #$0641..#$065A, #$0660..#$0672 :
  1092.         Result := Char(Ord(Ch) - $0580);
  1093.     else
  1094.       raise EConvertError.Create('Can not convert to ISO-8859-6');
  1095.     end;
  1096. end;
  1097.  
  1098. class function TISO8859_6Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1099. begin
  1100.   Result := ucISO8859_6;
  1101. end;
  1102.  
  1103. class function TISO8859_6Codec.GetAliasCount: Integer;
  1104. begin
  1105.   Result := ISO8859_6Aliases;
  1106. end;
  1107.  
  1108. class function TISO8859_6Codec.GetAliasByIndex(const Idx: Integer): String;
  1109. begin
  1110.   Result := ISO8859_6Alias[Idx];
  1111. end;
  1112.  
  1113. function TISO8859_6Codec.DecodeChar(const P: Char): WideChar;
  1114. begin
  1115.   Result := ISO8859_6ToWideChar(P);
  1116. end;
  1117.  
  1118. function TISO8859_6Codec.EncodeChar(const Ch: WideChar): Char;
  1119. begin
  1120.   Result := WideCharToISO8859_6(Ch);
  1121. end;
  1122.  
  1123.  
  1124.  
  1125. {                                                                              }
  1126. { ISO-8859-7 - Modern Greek                                                    }
  1127. { Greek.                                                                       }
  1128. {                                                                              }
  1129. const
  1130.   ISO8859_7Aliases = 8;
  1131.   ISO8859_7Alias: Array[1..ISO8859_7Aliases] of String = (
  1132.       'iso-ir-126', 'ISO_8859-7:1987', 'ISO_8859-7', 'ISO-8859-7',
  1133.       'ELOT_928', 'ECMA-118', 'greek', 'greek8');
  1134.  
  1135. function ISO8859_7ToWideChar(const P: Char): WideChar;
  1136. begin
  1137.   Case Ord(P) of
  1138.     $00..$A0, $A6..$A9, $AB..$AD, $B0..$B3, $B7, $BB, $BD :
  1139.       Result := WideChar(Ord(P));
  1140.     $A1 : Result := #$2018;
  1141.     $A2 : Result := #$2019;
  1142.     $AF : Result := #$2015;
  1143.     $D2, $FF : raise EConvertError.Create('Invalid ISO-8859-7 encoding');
  1144.   else
  1145.     Result := WideChar(Ord(P) + $02D0);
  1146.   end;
  1147. end;
  1148.  
  1149. function WideCharToISO8859_7(const Ch: WideChar): Char;
  1150. begin
  1151.   if Ord(Ch) <= $A0 then
  1152.     Result := Char(Ord(Ch)) else
  1153.     Case Ch of
  1154.       #$00A6..#$00A9, #$00AB..#$00AD, #$00B0..#$00B3, #$00B7, #$00BB, #$00BD :
  1155.         Result := Char(Ord(Ch));
  1156.       #$2018 : Result := #$A1;
  1157.       #$2019 : Result := #$A2;
  1158.       #$2015 : Result := #$AF;
  1159.     else
  1160.       raise EConvertError.Create('Can not convert to ISO-8859-7');
  1161.     end;
  1162. end;
  1163.  
  1164. class function TISO8859_7Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1165. begin
  1166.   Result := ucISO8859_7;
  1167. end;
  1168.  
  1169. class function TISO8859_7Codec.GetAliasCount: Integer;
  1170. begin
  1171.   Result := ISO8859_7Aliases;
  1172. end;
  1173.  
  1174. class function TISO8859_7Codec.GetAliasByIndex(const Idx: Integer): String;
  1175. begin
  1176.   Result := ISO8859_7Alias[Idx];
  1177. end;
  1178.  
  1179. function TISO8859_7Codec.DecodeChar(const P: Char): WideChar;
  1180. begin
  1181.   Result := ISO8859_7ToWideChar(P);
  1182. end;
  1183.  
  1184. function TISO8859_7Codec.EncodeChar(const Ch: WideChar): Char;
  1185. begin
  1186.   Result := WideCharToISO8859_7(Ch);
  1187. end;
  1188.  
  1189.  
  1190.  
  1191. {                                                                              }
  1192. { ISO-8859-8 - Hebrew                                                          }
  1193. { Non-accented Hebrew.                                                         }
  1194. {                                                                              }
  1195. const
  1196.   ISO8859_8Aliases = 5;
  1197.   ISO8859_8Alias: Array[1..ISO8859_8Aliases] of String = (
  1198.       'iso-ir-138', 'ISO_8859-8:1988', 'ISO_8859-8', 'ISO-8859-8',
  1199.       'hebrew');
  1200.  
  1201. function ISO8859_8ToWideChar(const P: Char): WideChar;
  1202. begin
  1203.   Case Ord(P) of
  1204.     $00..$A0, $A2..$A9, $AB..$AE, $B0..$B9, $BB..$BE :
  1205.       Result := WideChar(Ord(P));
  1206.     $AA : Result := #$00D7;
  1207.     $AF : Result := #$203E;
  1208.     $BA : Result := #$00F7;
  1209.     $DF : Result := #$2017;
  1210.     $E0..$FA :
  1211.       Result := WideChar(Ord(P) + $04E0);
  1212.   else
  1213.     raise EConvertError.Create('Invalid ISO-8859-8 encoding')
  1214.   end;
  1215. end;
  1216.  
  1217. function WideCharToISO8859_8(const Ch: WideChar): Char;
  1218. begin
  1219.   if Ord(Ch) <= $A0 then
  1220.     Result := Char(Ord(Ch)) else
  1221.     Case Ch of
  1222.       #$00A2..#$00A9, #$00AB..#$00AE, #$00B0..#$00B9, #$00BB..#$00BE :
  1223.         Result := Char(Ord(Ch));
  1224.       #$00D7 : Result := #$AA;
  1225.       #$203E : Result := #$AF;
  1226.       #$00F7 : Result := #$BA;
  1227.       #$2017 : Result := #$DF;
  1228.       #$05C0..#$05DA : Result := Char(Ord(Ch) - $04E0);
  1229.     else
  1230.       raise EConvertError.Create('Can not convert to ISO-8859-8');
  1231.     end;
  1232. end;
  1233.  
  1234. class function TISO8859_8Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1235. begin
  1236.   Result := ucISO8859_8;
  1237. end;
  1238.  
  1239. class function TISO8859_8Codec.GetAliasCount: Integer;
  1240. begin
  1241.   Result := ISO8859_8Aliases;
  1242. end;
  1243.  
  1244. class function TISO8859_8Codec.GetAliasByIndex(const Idx: Integer): String;
  1245. begin
  1246.   Result := ISO8859_8Alias[Idx];
  1247. end;
  1248.  
  1249. function TISO8859_8Codec.DecodeChar(const P: Char): WideChar;
  1250. begin
  1251.   Result := ISO8859_8ToWideChar(P);
  1252. end;
  1253.  
  1254. function TISO8859_8Codec.EncodeChar(const Ch: WideChar): Char;
  1255. begin
  1256.   Result := WideCharToISO8859_8(Ch);
  1257. end;
  1258.  
  1259.  
  1260.  
  1261. {                                                                              }
  1262. { ISO-8859-9 - Latin 5                                                         }
  1263. { Same as 8859-1 except for Turkish instead of Icelandic                       }
  1264. {                                                                              }
  1265. const
  1266.   ISO8859_9Aliases = 6;
  1267.   ISO8859_9Alias: Array[1..ISO8859_9Aliases] of String = (
  1268.       'iso-ir-148', 'ISO_8859-9:1989', 'ISO_8859-9', 'ISO-8859-9',
  1269.       'latin5', 'l5');
  1270.  
  1271. function ISO8859_9ToWideChar(const P: Char): WideChar;
  1272. begin
  1273.   Case Ord(P) of
  1274.     $D0 : Result := #$011E;
  1275.     $DD : Result := #$0130;
  1276.     $DE : Result := #$015E;
  1277.     $F0 : Result := #$011F;
  1278.     $FD : Result := #$0131;
  1279.     $FE : Result := #$015F;
  1280.   else
  1281.     Result := WideChar(Ord(P));
  1282.   end;
  1283. end;
  1284.  
  1285. function WideCharToISO8859_9(const Ch: WideChar): Char;
  1286. begin
  1287.   Case Ch of
  1288.     #$011E : Result := #$D0;
  1289.     #$0130 : Result := #$DD;
  1290.     #$015E : Result := #$DE;
  1291.     #$011F : Result := #$F0;
  1292.     #$0131 : Result := #$FD;
  1293.     #$015F : Result := #$FE;
  1294.   else
  1295.     if Ord(Ch) <= $00FF then
  1296.       Result := Char(Ord(Ch)) else
  1297.       raise EConvertError.Create('Can not convert to ISO-8859-9');
  1298.   end;
  1299. end;
  1300.  
  1301. class function TISO8859_9Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1302. begin
  1303.   Result := ucISO8859_9;
  1304. end;
  1305.  
  1306. class function TISO8859_9Codec.GetAliasCount: Integer;
  1307. begin
  1308.   Result := ISO8859_9Aliases;
  1309. end;
  1310.  
  1311. class function TISO8859_9Codec.GetAliasByIndex(const Idx: Integer): String;
  1312. begin
  1313.   Result := ISO8859_9Alias[Idx];
  1314. end;
  1315.  
  1316. function TISO8859_9Codec.DecodeChar(const P: Char): WideChar;
  1317. begin
  1318.   Result := ISO8859_9ToWideChar(P);
  1319. end;
  1320.  
  1321. function TISO8859_9Codec.EncodeChar(const Ch: WideChar): Char;
  1322. begin
  1323.   Result := WideCharToISO8859_9(Ch);
  1324. end;
  1325.  
  1326.  
  1327.  
  1328. {                                                                              }
  1329. { ISO-8859-10 - Latin 6                                                        }
  1330. { Latin6, for Lappish/Nordic/Eskimo languages: Adds the last Inuit             }
  1331. { (Greenlandic) and Sami (Lappish) letters that were missing in Latin 4 to     }
  1332. { cover the entire Nordic area.                                                }
  1333. {                                                                              }
  1334. const
  1335.   ISO8859_10Aliases = 6;
  1336.   ISO8859_10Alias: Array[1..ISO8859_10Aliases] of String = (
  1337.       'iso-ir-157', 'ISO_8859-10:1992', 'ISO_8859-10', 'ISO-8859-10',
  1338.       'latin6', 'l6');
  1339.  
  1340. const
  1341.   ISO8859_10Map: Array[$A0..$FF] of WideChar = (
  1342.       #$00A0, #$0104, #$0112, #$0122, #$012A, #$0128, #$0136, #$00A7,
  1343.       #$013B, #$0110, #$0160, #$0166, #$017D, #$00AD, #$016A, #$014A,
  1344.       #$00B0, #$0105, #$0113, #$0123, #$012B, #$0129, #$0137, #$00B7,
  1345.       #$013C, #$0111, #$0161, #$0167, #$017E, #$2014, #$016B, #$014B,
  1346.       #$0100, #$00C1, #$00C2, #$00C3, #$00C4, #$00C5, #$00C6, #$012E,
  1347.       #$010C, #$00C9, #$0118, #$00CB, #$0116, #$00CD, #$00CE, #$00CF,
  1348.       #$00D0, #$0145, #$014C, #$00D3, #$00D4, #$00D5, #$00D6, #$0168,
  1349.       #$00D8, #$0172, #$00DA, #$00DB, #$00DC, #$00DD, #$00DE, #$00DF,
  1350.       #$0101, #$00E1, #$00E2, #$00E3, #$00E4, #$00E5, #$00E6, #$012F,
  1351.       #$010D, #$00E9, #$0119, #$00EB, #$0117, #$00ED, #$00EE, #$00EF,
  1352.       #$00F0, #$0146, #$014D, #$00F3, #$00F4, #$00F5, #$00F6, #$0169,
  1353.       #$00F8, #$0173, #$00FA, #$00FB, #$00FC, #$00FD, #$00FE, #$0138);
  1354.  
  1355. function ISO8859_10ToWideChar(const P: Char): WideChar;
  1356. begin
  1357.   if Ord(P) >= $A0 then
  1358.     Result := ISO8859_10Map[Ord(P)] else
  1359.     Result := WideChar(Ord(P));
  1360. end;
  1361.  
  1362. function WideCharToISO8859_10(const Ch: WideChar): Char;
  1363. var I: Byte;
  1364. begin
  1365.   if Ord(Ch) < $A0 then
  1366.     begin
  1367.       Result := Char(Ord(Ch));
  1368.       exit;
  1369.     end;
  1370.   For I := $A0 to $FF do
  1371.     if ISO8859_10Map[I] = Ch then
  1372.       begin
  1373.         Result := Char(I);
  1374.         exit;
  1375.       end;
  1376.   raise EConvertError.Create('Can not convert to ISO-8859-10');
  1377. end;
  1378.  
  1379. class function TISO8859_10Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1380. begin
  1381.   Result := ucISO8859_10;
  1382. end;
  1383.  
  1384. class function TISO8859_10Codec.GetAliasCount: Integer;
  1385. begin
  1386.   Result := ISO8859_10Aliases;
  1387. end;
  1388.  
  1389. class function TISO8859_10Codec.GetAliasByIndex(const Idx: Integer): String;
  1390. begin
  1391.   Result := ISO8859_10Alias[Idx];
  1392. end;
  1393.  
  1394. function TISO8859_10Codec.DecodeChar(const P: Char): WideChar;
  1395. begin
  1396.   Result := ISO8859_10ToWideChar(P);
  1397. end;
  1398.  
  1399. function TISO8859_10Codec.EncodeChar(const Ch: WideChar): Char;
  1400. begin
  1401.   Result := WideCharToISO8859_10(Ch);
  1402. end;
  1403.  
  1404.  
  1405.  
  1406. {                                                                              }
  1407. { ISO-8859-13 - Latin 7                                                        }
  1408. {                                                                              }
  1409. const
  1410.   ISO8859_13Aliases = 4;
  1411.   ISO8859_13Alias: Array[1..ISO8859_13Aliases] of String = (
  1412.       'ISO_8859-13', 'ISO-8859-13', 'latin7', 'l7');
  1413.  
  1414. const
  1415.   ISO8859_13Map: Array[$A0..$FF] of WideChar = (
  1416.     #$00A0, #$201D, #$00A2, #$00A3, #$00A4, #$201E, #$00A6, #$00A7,
  1417.     #$00D8, #$00A9, #$0156, #$00AB, #$00AC, #$00AD, #$00AE, #$00C6,
  1418.     #$00B0, #$00B1, #$00B2, #$00B3, #$201C, #$00B5, #$00B6, #$00B7,
  1419.     #$00F8, #$00B9, #$0157, #$00BB, #$00BC, #$00BD, #$00BE, #$00E6,
  1420.     #$0104, #$012E, #$0100, #$0106, #$00C4, #$00C5, #$0118, #$0112,
  1421.     #$010C, #$00C9, #$0179, #$0116, #$0122, #$0136, #$012A, #$013B,
  1422.     #$0160, #$0143, #$0145, #$00D3, #$014C, #$00D5, #$00D6, #$00D7,
  1423.     #$0172, #$0141, #$015A, #$016A, #$00DC, #$017B, #$017D, #$00DF,
  1424.     #$0105, #$012F, #$0101, #$0107, #$00E4, #$00E5, #$0119, #$0113,
  1425.     #$010D, #$00E9, #$017A, #$0117, #$0123, #$0137, #$012B, #$013C,
  1426.     #$0161, #$0144, #$0146, #$00F3, #$014D, #$00F5, #$00F6, #$00F7,
  1427.     #$0173, #$0142, #$015B, #$016B, #$00FC, #$017B, #$017E, #$2019);
  1428.  
  1429. function ISO8859_13ToWideChar(const P: Char): WideChar;
  1430. begin
  1431.   if Ord(P) >= $A0 then
  1432.     Result := ISO8859_13Map[Ord(P)] else
  1433.     Result := WideChar(Ord(P));
  1434. end;
  1435.  
  1436. function WideCharToISO8859_13(const Ch: WideChar): Char;
  1437. var I: Byte;
  1438. begin
  1439.   if Ord(Ch) < $A0 then
  1440.     begin
  1441.       Result := Char(Ord(Ch));
  1442.       exit;
  1443.     end;
  1444.   For I := $A0 to $FF do
  1445.     if ISO8859_13Map[I] = Ch then
  1446.       begin
  1447.         Result := Char(I);
  1448.         exit;
  1449.       end;
  1450.   raise EConvertError.Create('Can not convert to ISO-8859-13');
  1451. end;
  1452.  
  1453. class function TISO8859_13Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1454. begin
  1455.   Result := ucISO8859_13;
  1456. end;
  1457.  
  1458. class function TISO8859_13Codec.GetAliasCount: Integer;
  1459. begin
  1460.   Result := ISO8859_13Aliases;
  1461. end;
  1462.  
  1463. class function TISO8859_13Codec.GetAliasByIndex(const Idx: Integer): String;
  1464. begin
  1465.   Result := ISO8859_13Alias[Idx];
  1466. end;
  1467.  
  1468. function TISO8859_13Codec.DecodeChar(const P: Char): WideChar;
  1469. begin
  1470.   Result := ISO8859_13ToWideChar(P);
  1471. end;
  1472.  
  1473. function TISO8859_13Codec.EncodeChar(const Ch: WideChar): Char;
  1474. begin
  1475.   Result := WideCharToISO8859_13(Ch);
  1476. end;
  1477.  
  1478.  
  1479.  
  1480. {                                                                              }
  1481. { ISO-8859-14 - Latin 8                                                        }
  1482. {                                                                              }
  1483. const
  1484.   ISO8859_14Aliases = 7;
  1485.   ISO8859_14Alias: Array[1..ISO8859_14Aliases] of String = (
  1486.       'iso-ir-199', 'ISO_8859-14:1998', 'ISO_8859-14', 'ISO-8859-14',
  1487.       'latin8', 'l8', 'iso-celtic');
  1488.  
  1489. const
  1490.   ISO8859_14Map: Array[$A0..$FF] of WideChar = (
  1491.     #$00A0, #$1E02, #$1E03, #$00A3, #$010A, #$010B, #$1E0A, #$00A7,
  1492.     #$1E80, #$00A9, #$1E82, #$1E0B, #$1EF2, #$00AD, #$00AE, #$0178,
  1493.     #$1E1E, #$1E1F, #$0120, #$0121, #$1E40, #$1E41, #$00B6, #$1E56,
  1494.     #$1E81, #$1E57, #$1E83, #$1E60, #$1EF3, #$1E84, #$1E85, #$1E61,
  1495.     #$00C0, #$00C1, #$00C2, #$00C3, #$00C4, #$00C5, #$00C6, #$00C7,
  1496.     #$00C8, #$00C9, #$00CA, #$00CB, #$00CC, #$00CD, #$00CE, #$00CF,
  1497.     #$0174, #$00D1, #$00D2, #$00D3, #$00D4, #$00D5, #$00D6, #$1E6A,
  1498.     #$00D8, #$00D9, #$00DA, #$00DB, #$00DC, #$00DD, #$0176, #$00DF,
  1499.     #$00E0, #$00E1, #$00E2, #$00E3, #$00E4, #$00E5, #$00E6, #$00E7,
  1500.     #$00E8, #$00E9, #$00EA, #$00EB, #$00EC, #$00ED, #$00EE, #$00EF,
  1501.     #$0175, #$00F1, #$00F2, #$00F3, #$00F4, #$00F5, #$00F6, #$1E6B,
  1502.     #$00F8, #$00F9, #$00FA, #$00FB, #$00FC, #$00FD, #$0177, #$00FF);
  1503.  
  1504. function ISO8859_14ToWideChar(const P: Char): WideChar;
  1505. begin
  1506.   if Ord(P) >= $A0 then
  1507.     Result := ISO8859_14Map[Ord(P)] else
  1508.     Result := WideChar(Ord(P));
  1509. end;
  1510.  
  1511. function WideCharToISO8859_14(const Ch: WideChar): Char;
  1512. var I: Byte;
  1513. begin
  1514.   if Ord(Ch) < $A0 then
  1515.     begin
  1516.       Result := Char(Ord(Ch));
  1517.       exit;
  1518.     end;
  1519.   For I := $A0 to $FF do
  1520.     if ISO8859_14Map[I] = Ch then
  1521.       begin
  1522.         Result := Char(I);
  1523.         exit;
  1524.       end;
  1525.   raise EConvertError.Create('Can not convert to ISO-8859-14');
  1526. end;
  1527.  
  1528. class function TISO8859_14Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1529. begin
  1530.   Result := ucISO8859_14;
  1531. end;
  1532.  
  1533. class function TISO8859_14Codec.GetAliasCount: Integer;
  1534. begin
  1535.   Result := ISO8859_14Aliases;
  1536. end;
  1537.  
  1538. class function TISO8859_14Codec.GetAliasByIndex(const Idx: Integer): String;
  1539. begin
  1540.   Result := ISO8859_14Alias[Idx];
  1541. end;
  1542.  
  1543. function TISO8859_14Codec.DecodeChar(const P: Char): WideChar;
  1544. begin
  1545.   Result := ISO8859_14ToWideChar(P);
  1546. end;
  1547.  
  1548. function TISO8859_14Codec.EncodeChar(const Ch: WideChar): Char;
  1549. begin
  1550.   Result := WideCharToISO8859_14(Ch);
  1551. end;
  1552.  
  1553.  
  1554.  
  1555. {                                                                              }
  1556. { ISO-8859-15 - Latin 9                                                        }
  1557. {                                                                              }
  1558. const
  1559.   ISO8859_15Aliases = 6;
  1560.   ISO8859_15Alias: Array[1..ISO8859_15Aliases] of String = (
  1561.       'ISO_8859-15', 'ISO-8859-15',
  1562.       'latin9', 'l9', 'latin0', 'l0');
  1563.  
  1564. function ISO8859_15ToWideChar(const P: Char): WideChar;
  1565. begin
  1566.   Case Ord(P) of
  1567.     $A4 : Result := #$20AC;
  1568.     $A6 : Result := #$00A6;
  1569.     $A8 : Result := #$0161;
  1570.     $B4 : Result := #$017D;
  1571.     $B8 : Result := #$017E;
  1572.     $BC : Result := #$0152;
  1573.     $BD : Result := #$0153;
  1574.     $BE : Result := #$0178;
  1575.   else
  1576.     Result := WideChar(Ord(P));
  1577.   end;
  1578. end;
  1579.  
  1580. function WideCharToISO8859_15(const Ch: WideChar): Char;
  1581. begin
  1582.   Case Ch of
  1583.     #$20AC : Result := #$A4;
  1584.     #$00A6 : Result := #$A6;
  1585.     #$0161 : Result := #$A8;
  1586.     #$017D : Result := #$B4;
  1587.     #$017E : Result := #$B8;
  1588.     #$0152 : Result := #$BC;
  1589.     #$0153 : Result := #$BD;
  1590.     #$0178 : Result := #$BE;
  1591.   else
  1592.     if Ord(Ch) <= $00FF then
  1593.       Result := Char(Ord(Ch)) else
  1594.       raise EConvertError.Create('Can not convert to ISO-8859-15');
  1595.   end;
  1596. end;
  1597.  
  1598. class function TISO8859_15Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1599. begin
  1600.   Result := ucISO8859_15;
  1601. end;
  1602.  
  1603. class function TISO8859_15Codec.GetAliasCount: Integer;
  1604. begin
  1605.   Result := ISO8859_15Aliases;
  1606. end;
  1607.  
  1608. class function TISO8859_15Codec.GetAliasByIndex(const Idx: Integer): String;
  1609. begin
  1610.   Result := ISO8859_15Alias[Idx];
  1611. end;
  1612.  
  1613. function TISO8859_15Codec.DecodeChar(const P: Char): WideChar;
  1614. begin
  1615.   Result := ISO8859_15ToWideChar(P);
  1616. end;
  1617.  
  1618. function TISO8859_15Codec.EncodeChar(const Ch: WideChar): Char;
  1619. begin
  1620.   Result := WideCharToISO8859_15(Ch);
  1621. end;
  1622.  
  1623.  
  1624.  
  1625. {                                                                              }
  1626. { KOI8-R                                                                       }
  1627. {                                                                              }
  1628. const
  1629.   KOI8_RAliases = 1;
  1630.   KOI8_RAlias: Array[1..KOI8_RAliases] of String = (
  1631.       'KOI8-R');
  1632.  
  1633. const
  1634.   KOI8_RMap: Array[$80..$FF] of WideChar = (
  1635.     #$2500, #$2502, #$250C, #$2510, #$2514, #$2518, #$251C, #$2524,
  1636.     #$252C, #$2534, #$253C, #$2580, #$2584, #$2588, #$258C, #$2590,
  1637.     #$2591, #$2592, #$2593, #$2320, #$25A0, #$2219, #$221A, #$2248,
  1638.     #$2264, #$2265, #$00A0, #$2321, #$00B0, #$00B2, #$00B7, #$00F7,
  1639.     #$2550, #$2551, #$2552, #$0451, #$2553, #$2554, #$2555, #$2556,
  1640.     #$2557, #$2558, #$2559, #$255A, #$255B, #$255C, #$255D, #$255E,
  1641.     #$255F, #$2560, #$2561, #$0401, #$2562, #$2563, #$2564, #$2565,
  1642.     #$2566, #$2567, #$2568, #$2569, #$256A, #$256B, #$256C, #$00A9,
  1643.     #$044E, #$0430, #$0431, #$0446, #$0434, #$0435, #$0444, #$0433,
  1644.     #$0445, #$0438, #$0439, #$043A, #$043B, #$043C, #$043D, #$043E,
  1645.     #$043F, #$044F, #$0440, #$0441, #$0442, #$0443, #$0436, #$0432,
  1646.     #$044C, #$044B, #$0437, #$0448, #$044D, #$0449, #$0447, #$044A,
  1647.     #$042E, #$0410, #$0411, #$0426, #$0414, #$0415, #$0424, #$0413,
  1648.     #$0425, #$0418, #$0419, #$041A, #$041B, #$041C, #$041D, #$041E,
  1649.     #$041F, #$042F, #$0420, #$0421, #$0422, #$0423, #$0416, #$0412,
  1650.     #$042C, #$042B, #$0417, #$0428, #$042D, #$0429, #$0427, #$042A);
  1651.  
  1652. function KOI8_RToWideChar(const P: Char): WideChar;
  1653. begin
  1654.   if Ord(P) >= $80 then
  1655.     Result := KOI8_RMap[Ord(P)] else
  1656.     Result := WideChar(Ord(P));
  1657. end;
  1658.  
  1659. function WideCharToKOI8_R(const Ch: WideChar): Char;
  1660. var I: Byte;
  1661. begin
  1662.   if Ord(Ch) < $80 then
  1663.     begin
  1664.       Result := Char(Ord(Ch));
  1665.       exit;
  1666.     end;
  1667.   For I := $80 to $FF do
  1668.     if KOI8_RMap[I] = Ch then
  1669.       begin
  1670.         Result := Char(I);
  1671.         exit;
  1672.       end;
  1673.   raise EConvertError.Create('Can not convert to KOI8-R');
  1674. end;
  1675.  
  1676. class function TKOI8_RCodec.GetUnicodeCodecType: TUnicodeCodecType;
  1677. begin
  1678.   Result := ucKOI8_R;
  1679. end;
  1680.  
  1681. class function TKOI8_RCodec.GetAliasCount: Integer;
  1682. begin
  1683.   Result := KOI8_RAliases;
  1684. end;
  1685.  
  1686. class function TKOI8_RCodec.GetAliasByIndex(const Idx: Integer): String;
  1687. begin
  1688.   Result := KOI8_RAlias[Idx];
  1689. end;
  1690.  
  1691. function TKOI8_RCodec.DecodeChar(const P: Char): WideChar;
  1692. begin
  1693.   Result := KOI8_RToWideChar(P);
  1694. end;
  1695.  
  1696. function TKOI8_RCodec.EncodeChar(const Ch: WideChar): Char;
  1697. begin
  1698.   Result := WideCharToKOI8_R(Ch);
  1699. end;
  1700.  
  1701.  
  1702.  
  1703. {                                                                              }
  1704. { Mac Latin-2                                                                  }
  1705. {                                                                              }
  1706. const
  1707.   MacLatin2Aliases = 3;
  1708.   MacLatin2Alias: Array[1..MacLatin2Aliases] of String = (
  1709.       'MacLatin2', 'Mac', 'Macintosh');
  1710.  
  1711. const
  1712.   MacLatin2Map: Array[$80..$FF] of WideChar = (
  1713.     #$00C4, #$0100, #$0101, #$00C9, #$0104, #$00D6, #$00DC, #$00E1,
  1714.     #$0105, #$010C, #$00E4, #$010D, #$0106, #$0107, #$00E9, #$0179,
  1715.     #$017A, #$010E, #$00ED, #$010F, #$0112, #$0113, #$0116, #$00F3,
  1716.     #$0117, #$00F4, #$00F6, #$00F5, #$00FA, #$011A, #$011B, #$00FC,
  1717.     #$2020, #$00B0, #$0118, #$00A3, #$00A7, #$2022, #$00B6, #$00DF,
  1718.     #$00AE, #$00A9, #$2122, #$0119, #$00A8, #$2260, #$0123, #$012E,
  1719.     #$012F, #$012A, #$2264, #$2265, #$012B, #$0136, #$2202, #$2211,
  1720.     #$0142, #$013B, #$013C, #$013D, #$013E, #$0139, #$013A, #$0145,
  1721.     #$0146, #$0143, #$00AC, #$221A, #$0144, #$0147, #$2206, #$00AB,
  1722.     #$00BB, #$2026, #$00A0, #$0148, #$0150, #$00D5, #$0151, #$014C,
  1723.     #$2013, #$2014, #$201C, #$201D, #$2018, #$2019, #$00F7, #$25CA,
  1724.     #$014D, #$0154, #$0155, #$0158, #$2039, #$203A, #$0159, #$0156,
  1725.     #$0157, #$0160, #$201A, #$201E, #$0161, #$015A, #$015B, #$00C1,
  1726.     #$0164, #$0165, #$00CD, #$017D, #$017E, #$016A, #$00D3, #$00D4,
  1727.     #$016B, #$016E, #$00DA, #$016F, #$0170, #$0171, #$0172, #$0173,
  1728.     #$00DD, #$00FD, #$0137, #$017B, #$0141, #$017C, #$0122, #$02C7);
  1729.  
  1730. function MacLatin2ToWideChar(const P: Char): WideChar;
  1731. begin
  1732.   if Ord(P) >= $80 then
  1733.     Result := MacLatin2Map[Ord(P)] else
  1734.     Result := WideChar(Ord(P));
  1735. end;
  1736.  
  1737. function WideCharToMacLatin2(const Ch: WideChar): Char;
  1738. var I: Byte;
  1739. begin
  1740.   if Ord(Ch) < $80 then
  1741.     begin
  1742.       Result := Char(Ord(Ch));
  1743.       exit;
  1744.     end;
  1745.   For I := $80 to $FF do
  1746.     if MacLatin2Map[I] = Ch then
  1747.       begin
  1748.         Result := Char(I);
  1749.         exit;
  1750.       end;
  1751.   raise EConvertError.Create('Can not convert to MacLatin2');
  1752. end;
  1753.  
  1754. class function TMacLatin2Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1755. begin
  1756.   Result := ucMacLatin2;
  1757. end;
  1758.  
  1759. class function TMacLatin2Codec.GetAliasCount: Integer;
  1760. begin
  1761.   Result := MacLatin2Aliases;
  1762. end;
  1763.  
  1764. class function TMacLatin2Codec.GetAliasByIndex(const Idx: Integer): String;
  1765. begin
  1766.   Result := MacLatin2Alias[Idx];
  1767. end;
  1768.  
  1769. function TMacLatin2Codec.DecodeChar(const P: Char): WideChar;
  1770. begin
  1771.   Result := MacLatin2ToWideChar(P);
  1772. end;
  1773.  
  1774. function TMacLatin2Codec.EncodeChar(const Ch: WideChar): Char;
  1775. begin
  1776.   Result := WideCharToMacLatin2(Ch);
  1777. end;
  1778.  
  1779.  
  1780.  
  1781. {                                                                              }
  1782. { Mac Roman                                                                    }
  1783. {                                                                              }
  1784. const
  1785.   MacRomanAliases = 1;
  1786.   MacRomanAlias: Array[1..MacRomanAliases] of String = (
  1787.       'MacRoman');
  1788.  
  1789. const
  1790.   MacRomanMap: Array[$80..$FF] of WideChar = (
  1791.     #$00C4, #$00C5, #$00C7, #$00C9, #$00D1, #$00D6, #$00DC, #$00E1,
  1792.     #$00E0, #$00E2, #$00E4, #$00E3, #$00E5, #$00E7, #$00E9, #$00E8,
  1793.     #$00EA, #$00EB, #$00ED, #$00EC, #$00EE, #$00EF, #$00F1, #$00F3,
  1794.     #$00F2, #$00F4, #$00F6, #$00F5, #$00FA, #$00F9, #$00FB, #$00FC,
  1795.     #$2020, #$00B0, #$00A2, #$00A3, #$00A7, #$2022, #$00B6, #$00DF,
  1796.     #$00AE, #$00A9, #$2122, #$00B4, #$00A8, #$2260, #$00C6, #$00D8,
  1797.     #$221E, #$00B1, #$2264, #$2265, #$00A5, #$00B5, #$2202, #$2211,
  1798.     #$220F, #$03C0, #$222B, #$00AA, #$00BA, #$2126, #$00E6, #$00F8,
  1799.     #$00BF, #$00A1, #$00AC, #$221A, #$0192, #$2248, #$2206, #$00AB,
  1800.     #$00BB, #$2026, #$00A0, #$00C0, #$00C3, #$00D5, #$0152, #$0153,
  1801.     #$2013, #$2014, #$201C, #$201D, #$2018, #$2019, #$00F7, #$25CA,
  1802.     #$00FF, #$0178, #$2044, #$00A4, #$2039, #$203A, #$FB01, #$FB02,
  1803.     #$2021, #$00B7, #$201A, #$201E, #$2030, #$00C2, #$00CA, #$00C1,
  1804.     #$00CB, #$00C8, #$00CD, #$00CE, #$00CF, #$00CC, #$00D3, #$00D4,
  1805.     #$0000, #$00D2, #$00DA, #$00DB, #$00D9, #$0131, #$02C6, #$02DC,
  1806.     #$00AF, #$02D8, #$02D9, #$02DA, #$00B8, #$02DD, #$02DB, #$02C7);
  1807.  
  1808. function MacRomanToWideChar(const P: Char): WideChar;
  1809. begin
  1810.   if Ord(P) >= $80 then
  1811.     begin
  1812.       Result := MacRomanMap[Ord(P)];
  1813.       if Result = #$0000 then
  1814.         raise EConvertError.Create('Invalid Mac Roman encoding');
  1815.     end else
  1816.     Result := WideChar(Ord(P));
  1817. end;
  1818.  
  1819. function WideCharToMacRoman(const Ch: WideChar): Char;
  1820. var I: Byte;
  1821. begin
  1822.   if Ord(Ch) < $80 then
  1823.     begin
  1824.       Result := Char(Ord(Ch));
  1825.       exit;
  1826.     end;
  1827.   For I := $80 to $FF do
  1828.     if MacRomanMap[I] = Ch then
  1829.       begin
  1830.         Result := Char(I);
  1831.         exit;
  1832.       end;
  1833.   raise EConvertError.Create('Can not convert to MacRoman');
  1834. end;
  1835.  
  1836. class function TMacRomanCodec.GetUnicodeCodecType: TUnicodeCodecType;
  1837. begin
  1838.   Result := ucMacRoman;
  1839. end;
  1840.  
  1841. class function TMacRomanCodec.GetAliasCount: Integer;
  1842. begin
  1843.   Result := MacRomanAliases;
  1844. end;
  1845.  
  1846. class function TMacRomanCodec.GetAliasByIndex(const Idx: Integer): String;
  1847. begin
  1848.   Result := MacRomanAlias[Idx];
  1849. end;
  1850.  
  1851. function TMacRomanCodec.DecodeChar(const P: Char): WideChar;
  1852. begin
  1853.   Result := MacRomanToWideChar(P);
  1854. end;
  1855.  
  1856. function TMacRomanCodec.EncodeChar(const Ch: WideChar): Char;
  1857. begin
  1858.   Result := WideCharToMacRoman(Ch);
  1859. end;
  1860.  
  1861.  
  1862.  
  1863. {                                                                              }
  1864. { Mac Cyrillic                                                                 }
  1865. {                                                                              }
  1866. const
  1867.   MacCyrillicAliases = 1;
  1868.   MacCyrillicAlias: Array[1..MacCyrillicAliases] of String = (
  1869.       'MacCyrillic');
  1870.  
  1871. const
  1872.   MacCyrillicMap: Array[$80..$FF] of WideChar = (
  1873.     #$0410, #$0411, #$0412, #$0413, #$0414, #$0415, #$0416, #$0417,
  1874.     #$0418, #$0419, #$041A, #$041B, #$041C, #$041D, #$041E, #$041F,
  1875.     #$0420, #$0421, #$0422, #$0423, #$0424, #$0425, #$0426, #$0427,
  1876.     #$0428, #$0429, #$042A, #$042B, #$042C, #$042D, #$042E, #$042F,
  1877.     #$2020, #$00B0, #$00A2, #$00A3, #$00A7, #$2022, #$00B6, #$0406,
  1878.     #$00AE, #$00A9, #$2122, #$0402, #$0452, #$2260, #$0403, #$0453,
  1879.     #$221E, #$00B1, #$2264, #$2265, #$0456, #$00B5, #$2202, #$0408,
  1880.     #$0404, #$0454, #$0407, #$0457, #$0409, #$0459, #$040A, #$045A,
  1881.     #$0458, #$0405, #$00AC, #$221A, #$0192, #$2248, #$2206, #$00AB,
  1882.     #$00BB, #$2026, #$00A0, #$040B, #$045B, #$040C, #$045C, #$0455,
  1883.     #$2013, #$2014, #$201C, #$201D, #$2018, #$2019, #$00F7, #$201E,
  1884.     #$040E, #$045E, #$040F, #$045F, #$2116, #$0401, #$0451, #$044F,
  1885.     #$0430, #$0431, #$0432, #$0433, #$0434, #$0435, #$0436, #$0437,
  1886.     #$0438, #$0439, #$043A, #$043B, #$043C, #$043D, #$043E, #$043F,
  1887.     #$0440, #$0441, #$0442, #$0443, #$0444, #$0445, #$0446, #$0447,
  1888.     #$0448, #$0449, #$044A, #$044B, #$044C, #$044D, #$044E, #$00A4);
  1889.  
  1890. function MacCyrillicToWideChar(const P: Char): WideChar;
  1891. begin
  1892.   if Ord(P) >= $80 then
  1893.     Result := MacCyrillicMap[Ord(P)] else
  1894.     Result := WideChar(Ord(P));
  1895. end;
  1896.  
  1897. function WideCharToMacCyrillic(const Ch: WideChar): Char;
  1898. var I: Byte;
  1899. begin
  1900.   if Ord(Ch) < $80 then
  1901.     begin
  1902.       Result := Char(Ord(Ch));
  1903.       exit;
  1904.     end;
  1905.   For I := $80 to $FF do
  1906.     if MacCyrillicMap[I] = Ch then
  1907.       begin
  1908.         Result := Char(I);
  1909.         exit;
  1910.       end;
  1911.   raise EConvertError.Create('Can not convert to MacCyrillic');
  1912. end;
  1913.  
  1914. class function TMacCyrillicCodec.GetUnicodeCodecType: TUnicodeCodecType;
  1915. begin
  1916.   Result := ucMacCyrillic;
  1917. end;
  1918.  
  1919. class function TMacCyrillicCodec.GetAliasCount: Integer;
  1920. begin
  1921.   Result := MacCyrillicAliases;
  1922. end;
  1923.  
  1924. class function TMacCyrillicCodec.GetAliasByIndex(const Idx: Integer): String;
  1925. begin
  1926.   Result := MacCyrillicAlias[Idx];
  1927. end;
  1928.  
  1929. function TMacCyrillicCodec.DecodeChar(const P: Char): WideChar;
  1930. begin
  1931.   Result := MacCyrillicToWideChar(P);
  1932. end;
  1933.  
  1934. function TMacCyrillicCodec.EncodeChar(const Ch: WideChar): Char;
  1935. begin
  1936.   Result := WideCharToMacCyrillic(Ch);
  1937. end;
  1938.  
  1939.  
  1940.  
  1941. {                                                                              }
  1942. { CP437 - DOSLatinUS                                                           }
  1943. { Original IBM PC encoding                                                     }
  1944. {                                                                              }
  1945. const
  1946.   CP437Aliases = 2;
  1947.   CP437Alias: Array[1..CP437Aliases] of String = (
  1948.       'cp437', 'IBM437');
  1949.  
  1950. const
  1951.   CP437Map: Array[$80..$FF] of WideChar = (
  1952.     #$00C7, #$00FC, #$00E9, #$00E2, #$00E4, #$00E0, #$00E5, #$00E7,
  1953.     #$00EA, #$00EB, #$00E8, #$00EF, #$00EE, #$00EC, #$00C4, #$00C5,
  1954.     #$00C9, #$00E6, #$00C6, #$00F4, #$00F6, #$00F2, #$00FB, #$00F9,
  1955.     #$00FF, #$00D6, #$00DC, #$00A2, #$00A3, #$00A5, #$20A7, #$0192,
  1956.     #$00E1, #$00ED, #$00F3, #$00FA, #$00F1, #$00D1, #$00AA, #$00BA,
  1957.     #$00BF, #$2310, #$00AC, #$00BD, #$00BC, #$00A1, #$00AB, #$00BB,
  1958.     #$2591, #$2592, #$2593, #$2502, #$2524, #$2561, #$2562, #$2556,
  1959.     #$2555, #$2563, #$2551, #$2557, #$255D, #$255C, #$255B, #$2510,
  1960.     #$2514, #$2534, #$252C, #$251C, #$2500, #$253C, #$255E, #$255F,
  1961.     #$255A, #$2554, #$2569, #$2566, #$2560, #$2550, #$256C, #$2567,
  1962.     #$2568, #$2564, #$2565, #$2559, #$2558, #$2552, #$2553, #$256B,
  1963.     #$256A, #$2518, #$250C, #$2588, #$2584, #$258C, #$2590, #$2580,
  1964.     #$03B1, #$00DF, #$0393, #$03C0, #$03A3, #$03C3, #$00B5, #$03C4,
  1965.     #$03A6, #$0398, #$03A9, #$03B4, #$221E, #$03C6, #$03B5, #$2229,
  1966.     #$2261, #$00B1, #$2265, #$2264, #$2320, #$2321, #$00F7, #$2248,
  1967.     #$00B0, #$2219, #$00B7, #$221A, #$207F, #$00B2, #$25A0, #$00A0);
  1968.  
  1969. function CP437ToWideChar(const P: Char): WideChar;
  1970. begin
  1971.   if Ord(P) >= $80 then
  1972.     Result := MacCyrillicMap[Ord(P)] else
  1973.     Result := WideChar(Ord(P));
  1974. end;
  1975.  
  1976. function WideCharToCP437(const Ch: WideChar): Char;
  1977. var I: Byte;
  1978. begin
  1979.   if Ord(Ch) < $80 then
  1980.     begin
  1981.       Result := Char(Ord(Ch));
  1982.       exit;
  1983.     end;
  1984.   For I := $80 to $FF do
  1985.     if CP437Map[I] = Ch then
  1986.       begin
  1987.         Result := Char(I);
  1988.         exit;
  1989.       end;
  1990.   raise EConvertError.Create('Can not convert to CP437');
  1991. end;
  1992.  
  1993. class function TCP437Codec.GetUnicodeCodecType: TUnicodeCodecType;
  1994. begin
  1995.   Result := ucCP437;
  1996. end;
  1997.  
  1998. class function TCP437Codec.GetAliasCount: Integer;
  1999. begin
  2000.   Result := CP437Aliases;
  2001. end;
  2002.  
  2003. class function TCP437Codec.GetAliasByIndex(const Idx: Integer): String;
  2004. begin
  2005.   Result := CP437Alias[Idx];
  2006. end;
  2007.  
  2008. function TCP437Codec.DecodeChar(const P: Char): WideChar;
  2009. begin
  2010.   Result := CP437ToWideChar(P);
  2011. end;
  2012.  
  2013. function TCP437Codec.EncodeChar(const Ch: WideChar): Char;
  2014. begin
  2015.   Result := WideCharToCP437(Ch);
  2016. end;
  2017.  
  2018.  
  2019.  
  2020. {                                                                              }
  2021. { Windows-1250                                                                 }
  2022. {                                                                              }
  2023. const
  2024.   Win1250Aliases = 3;
  2025.   Win1250Alias: Array[1..Win1250Aliases] of String = (
  2026.       'windows-1250', 'cp1250', 'WinLatin2');
  2027.  
  2028. const
  2029.   Win1250Map: Array[$80..$FF] of WideChar = (
  2030.     #$20AC, #$0000, #$201A, #$0000, #$201E, #$2026, #$2020, #$2021,
  2031.     #$0000, #$2030, #$0160, #$2039, #$015A, #$0164, #$017D, #$0179,
  2032.     #$0000, #$2018, #$2019, #$201C, #$201D, #$2022, #$2013, #$2014,
  2033.     #$0000, #$2122, #$0161, #$203A, #$015B, #$0165, #$017E, #$017A,
  2034.     #$00A0, #$02C7, #$02D8, #$0141, #$00A4, #$0104, #$00A6, #$00A7,
  2035.     #$00A8, #$00A9, #$015E, #$00AB, #$00AC, #$00AD, #$00AE, #$017B,
  2036.     #$00B0, #$00B1, #$02DB, #$0142, #$00B4, #$00B5, #$00B6, #$00B7,
  2037.     #$00B8, #$0105, #$015F, #$00BB, #$013D, #$02DD, #$013E, #$017C,
  2038.     #$0154, #$00C1, #$00C2, #$0102, #$00C4, #$0139, #$0106, #$00C7,
  2039.     #$010C, #$00C9, #$0118, #$00CB, #$011A, #$00CD, #$00CE, #$010E,
  2040.     #$0110, #$0143, #$0147, #$00D3, #$00D4, #$0150, #$00D6, #$00D7,
  2041.     #$0158, #$016E, #$00DA, #$0170, #$00DC, #$00DD, #$0162, #$00DF,
  2042.     #$0155, #$00E1, #$00E2, #$0103, #$00E4, #$013A, #$0107, #$00E7,
  2043.     #$010D, #$00E9, #$0119, #$00EB, #$011B, #$00ED, #$00EE, #$010F,
  2044.     #$0111, #$0144, #$0148, #$00F3, #$00F4, #$0151, #$00F6, #$00F7,
  2045.     #$0159, #$016F, #$00FA, #$0171, #$00FC, #$00FD, #$0163, #$02D9);
  2046.  
  2047. function Win1250ToWideChar(const P: Char): WideChar;
  2048. begin
  2049.   if Ord(P) >= $80 then
  2050.     begin
  2051.       Result := Win1250Map[Ord(P)];
  2052.       if Result = #$0000 then
  2053.         raise EConvertError.Create('Invalid Windows-1250 encoding');
  2054.     end else
  2055.     Result := WideChar(Ord(P));
  2056. end;
  2057.  
  2058. function WideCharToWin1250(const Ch: WideChar): Char;
  2059. var I: Byte;
  2060. begin
  2061.   if Ord(Ch) < $80 then
  2062.     begin
  2063.       Result := Char(Ord(Ch));
  2064.       exit;
  2065.     end;
  2066.   For I := $80 to $FF do
  2067.     if Win1250Map[I] = Ch then
  2068.       begin
  2069.         Result := Char(I);
  2070.         exit;
  2071.       end;
  2072.   raise EConvertError.Create('Can not convert to Windows-1250');
  2073. end;
  2074.  
  2075. class function TWin1250Codec.GetUnicodeCodecType: TUnicodeCodecType;
  2076. begin
  2077.   Result := ucWin1250;
  2078. end;
  2079.  
  2080. class function TWin1250Codec.GetAliasCount: Integer;
  2081. begin
  2082.   Result := Win1250Aliases;
  2083. end;
  2084.  
  2085. class function TWin1250Codec.GetAliasByIndex(const Idx: Integer): String;
  2086. begin
  2087.   Result := Win1250Alias[Idx];
  2088. end;
  2089.  
  2090. function TWin1250Codec.DecodeChar(const P: Char): WideChar;
  2091. begin
  2092.   Result := Win1250ToWideChar(P);
  2093. end;
  2094.  
  2095. function TWin1250Codec.EncodeChar(const Ch: WideChar): Char;
  2096. begin
  2097.   Result := WideCharToWin1250(Ch);
  2098. end;
  2099.  
  2100.  
  2101. {                                                                              }
  2102. { Windows-1251                                                                 }
  2103. {                                                                              }
  2104. const
  2105.   Win1251Aliases = 3;
  2106.   Win1251Alias: Array[1..Win1251Aliases] of String = (
  2107.       'windows-1251', 'cp1251', 'WinCyrillic');
  2108.  
  2109. const
  2110.   Win1251Map: Array[$80..$BF] of WideChar = (
  2111.     #$0402, #$0403, #$201A, #$0453, #$201E, #$2026, #$2020, #$2021,
  2112.     #$20AC, #$2030, #$0409, #$2039, #$040A, #$040C, #$040B, #$040F,
  2113.     #$0452, #$2018, #$2019, #$201C, #$201D, #$2022, #$2013, #$2014,
  2114.     #$0000, #$2122, #$0459, #$203A, #$045A, #$045C, #$045B, #$045F,
  2115.     #$00A0, #$040E, #$045E, #$0408, #$00A4, #$0490, #$00A6, #$00A7,
  2116.     #$0401, #$00A9, #$0404, #$00AB, #$00AC, #$00AD, #$00AE, #$0407,
  2117.     #$00B0, #$00B1, #$0406, #$0456, #$0491, #$00B5, #$00B6, #$00B7,
  2118.     #$0451, #$2116, #$0454, #$00BB, #$0458, #$0405, #$0455, #$0457);
  2119.  
  2120. function Win1251ToWideChar(const P: Char): WideChar;
  2121. begin
  2122.   Case Ord(P) of
  2123.     $00..$7F : Result := WideChar(Ord(P));
  2124.     $80..$BF :
  2125.       begin
  2126.         Result := Win1251Map[Ord(P)];
  2127.         if Result = #$0000 then
  2128.           raise EConvertError.Create('Invalid Windows-1251 encoding');
  2129.       end;
  2130.     $C0..$FF :
  2131.       Result := WideChar(Ord(P) + $0350);
  2132.     else
  2133.       raise EConvertError.Create('Invalid Windows-1251 encoding');
  2134.   end;
  2135. end;
  2136.  
  2137. function WideCharToWin1251(const Ch: WideChar): Char;
  2138. var I: Byte;
  2139. begin
  2140.   if Ord(Ch) < $80 then
  2141.     begin
  2142.       Result := Char(Ord(Ch));
  2143.       exit;
  2144.     end;
  2145.   Case Ch of
  2146.     #$0410..#$044F : Result := Char(Ord(Ch) - $0350);
  2147.   else
  2148.     begin
  2149.       For I := $80 to $BF do
  2150.         if Win1251Map[I] = Ch then
  2151.           begin
  2152.             Result := Char(I);
  2153.             exit;
  2154.           end;
  2155.       raise EConvertError.Create('Can not convert to Windows-1251');
  2156.     end;
  2157.   end;
  2158. end;
  2159.  
  2160. class function TWin1251Codec.GetUnicodeCodecType: TUnicodeCodecType;
  2161. begin
  2162.   Result := ucWin1251;
  2163. end;
  2164.  
  2165. class function TWin1251Codec.GetAliasCount: Integer;
  2166. begin
  2167.   Result := Win1251Aliases;
  2168. end;
  2169.  
  2170. class function TWin1251Codec.GetAliasByIndex(const Idx: Integer): String;
  2171. begin
  2172.   Result := Win1251Alias[Idx];
  2173. end;
  2174.  
  2175. function TWin1251Codec.DecodeChar(const P: Char): WideChar;
  2176. begin
  2177.   Result := Win1251ToWideChar(P);
  2178. end;
  2179.  
  2180. function TWin1251Codec.EncodeChar(const Ch: WideChar): Char;
  2181. begin
  2182.   Result := WideCharToWin1251(Ch);
  2183. end;
  2184.  
  2185.  
  2186.  
  2187. {                                                                              }
  2188. { Windows-1252                                                                 }
  2189. {                                                                              }
  2190. const
  2191.   Win1252Aliases = 3;
  2192.   Win1252Alias: Array[1..Win1252Aliases] of String = (
  2193.       'windows-1252', 'cp1252', 'WinLatin1');
  2194.  
  2195. const
  2196.   Win1252Map: Array[$80..$9F] of WideChar = (
  2197.     #$20AC, #$0000, #$201A, #$0192, #$201E, #$2026, #$2020, #$2021,
  2198.     #$02C6, #$2030, #$0160, #$2039, #$0152, #$0000, #$017D, #$0000,
  2199.     #$0000, #$2018, #$2019, #$201C, #$201D, #$2022, #$2013, #$2014,
  2200.     #$02DC, #$2122, #$0161, #$203A, #$0153, #$0000, #$017E, #$0178);
  2201.  
  2202. function Win1252ToWideChar(const P: Char): WideChar;
  2203. begin
  2204.   if Ord(P) in [$80..$9F] then
  2205.     begin
  2206.       Result := Win1252Map[Ord(P)];
  2207.       if Result = #$0000 then
  2208.         raise EConvertError.Create('Invalid Windows-1252 encoding');
  2209.     end else
  2210.     Result := WideChar(Ord(P));
  2211. end;
  2212.  
  2213. function WideCharToWin1252(const Ch: WideChar): Char;
  2214. var I: Byte;
  2215. begin
  2216.   if Ord(Ch) < $80 then
  2217.     begin
  2218.       Result := Char(Ord(Ch));
  2219.       exit;
  2220.     end;
  2221.   if (Ord(Ch) < $100) and (Ord(Ch) > $9F) then
  2222.     begin
  2223.       Result := Char(Ord(Ch));
  2224.       exit;
  2225.     end;
  2226.   For I := $80 to $9F do
  2227.     if Win1252Map[I] = Ch then
  2228.       begin
  2229.         Result := Char(I);
  2230.         exit;
  2231.       end;
  2232.   raise EConvertError.Create('Can not convert to Windows-1252');
  2233. end;
  2234.  
  2235. class function TWin1252Codec.GetUnicodeCodecType: TUnicodeCodecType;
  2236. begin
  2237.   Result := ucWin1252;
  2238. end;
  2239.  
  2240. class function TWin1252Codec.GetAliasCount: Integer;
  2241. begin
  2242.   Result := Win1252Aliases;
  2243. end;
  2244.  
  2245. class function TWin1252Codec.GetAliasByIndex(const Idx: Integer): String;
  2246. begin
  2247.   Result := Win1252Alias[Idx];
  2248. end;
  2249.  
  2250. function TWin1252Codec.DecodeChar(const P: Char): WideChar;
  2251. begin
  2252.   Result := Win1252ToWideChar(P);
  2253. end;
  2254.  
  2255. function TWin1252Codec.EncodeChar(const Ch: WideChar): Char;
  2256. begin
  2257.   Result := WideCharToWin1252(Ch);
  2258. end;
  2259.  
  2260.  
  2261.  
  2262. {                                                                              }
  2263. { EBCDIC-US                                                                    }
  2264. {                                                                              }
  2265. const
  2266.   EBCDIC_USAliases = 2;
  2267.   EBCDIC_USAlias: Array[1..EBCDIC_USAliases] of String = (
  2268.       'ebcdic-us', 'ebcdic');
  2269.  
  2270. function EBCDIC_USToWideChar(const P: Char): WideChar;
  2271. begin
  2272.   Case Ord(P) of
  2273.     $40 : Result := #$0020;   // SPACE
  2274.     $4A : Result := #$00A2;   // CENT SIGN
  2275.     $4B : Result := #$002E;   // FULL STOP
  2276.     $4C : Result := #$003C;   // LESS-THAN SIGN
  2277.     $4D : Result := #$0028;   // LEFT PARENTHESIS
  2278.     $4E : Result := #$002B;   // PLUS SIGN
  2279.     $4F : Result := #$007C;   // VERTICAL LINE
  2280.     $50 : Result := #$0026;   // AMPERSAND
  2281.     $5A : Result := #$0021;   // EXCLAMATION MARK
  2282.     $5B : Result := #$0024;   // DOLLAR SIGN
  2283.     $5C : Result := #$002A;   // ASTERISK
  2284.     $5D : Result := #$0029;   // RIGHT PARENTHESIS
  2285.     $5E : Result := #$003B;   // SEMICOLON
  2286.     $5F : Result := #$00AC;   // NOT SIGN
  2287.     $60 : Result := #$002D;   // HYPHEN-MINUS
  2288.     $61 : Result := #$002F;   // SOLIDUS
  2289.     $6A : Result := #$00A6;   // BROKEN BAR
  2290.     $6B : Result := #$002C;   // COMMA
  2291.     $6C : Result := #$0025;   // PERCENT SIGN
  2292.     $6D : Result := #$005F;   // LOW LINE
  2293.     $6E : Result := #$003E;   // GREATER-THAN SIGN
  2294.     $6F : Result := #$003F;   // QUESTION MARK
  2295.     $79 : Result := #$0060;   // GRAVE ACCENT
  2296.     $7A : Result := #$003A;   // COLON
  2297.     $7B : Result := #$0023;   // NUMBER SIGN
  2298.     $7C : Result := #$0040;   // COMMERCIAL AT
  2299.     $7D : Result := #$0027;   // APOSTROPHE
  2300.     $7E : Result := #$003D;   // EQUALS SIGN
  2301.     $7F : Result := #$0022;   // QUOTATION MARK
  2302.     $81..$89 : Result := WideChar(Ord(P) - $81 + $0061);   // LATIN SMALL LETTER A..I
  2303.     $91..$99 : Result := WideChar(Ord(P) - $91 + $006A);   // LATIN SMALL LETTER J..R
  2304.     $A1 : Result := #$007E;   // TILDE
  2305.     $A2..$A9 : Result := WideChar(Ord(P) - $A2 + $0073);   // LATIN SMALL LETTER S..Z
  2306.     $C0 : Result := #$007B;   // LEFT CURLY BRACKET
  2307.     $C1..$C9 : Result := WideChar(Ord(P) - $C1 + $0041);   // LATIN CAPITAL LETTER A..I
  2308.     $D0 : Result := #$007D;   // RIGHT CURLY BRACKET
  2309.     $D1..$D9 : Result := WideChar(Ord(P) - $D1 + $004A);   // LATIN CAPITAL LETTER J..R
  2310.     $E0 : Result := #$005C;   // REVERSE SOLIDUS
  2311.     $E2..$E9 : Result := WideChar(Ord(P) - $E2 + $0053);   // LATIN CAPITAL LETTER S
  2312.     $F0..$F9 : Result := WideChar(Ord(P) - $F0 + $0030);   // DIGIT ZERO
  2313.   else
  2314.     raise EConvertError.Create('Invalid EBCDIC-US encoding');
  2315.   end;
  2316. end;
  2317.  
  2318. function WideCharToEBCDIC_US(const Ch: WideChar): Char;
  2319. begin
  2320.   Case Ord(Ch) of
  2321.     $0020 : Result := #$40;   // SPACE
  2322.     $0021 : Result := #$5A;   // EXCLAMATION MARK
  2323.     $0022 : Result := #$7F;   // QUOTATION MARK
  2324.     $0023 : Result := #$7B;   // NUMBER SIGN
  2325.     $0024 : Result := #$5B;   // DOLLAR SIGN
  2326.     $0025 : Result := #$6C;   // PERCENT SIGN
  2327.     $0026 : Result := #$50;   // AMPERSAND
  2328.     $0027 : Result := #$7D;   // APOSTROPHE
  2329.     $0028 : Result := #$4D;   // LEFT PARENTHESIS
  2330.     $0029 : Result := #$5D;   // RIGHT PARENTHESIS
  2331.     $002A : Result := #$5C;   // ASTERISK
  2332.     $002B : Result := #$4E;   // PLUS SIGN
  2333.     $002C : Result := #$6B;   // COMMA
  2334.     $002D : Result := #$60;   // HYPHEN-MINUS
  2335.     $002E : Result := #$4B;   // FULL STOP
  2336.     $002F : Result := #$61;   // SOLIDUS
  2337.     $0030..$0039 : Result := Char(Ord(Ch) - $0030 + $F0);   // DIGIT ZERO-NINE
  2338.     $003A : Result := #$7A;   // COLON
  2339.     $003B : Result := #$5E;   // SEMICOLON
  2340.     $003C : Result := #$4C;   // LESS-THAN SIGN
  2341.     $003D : Result := #$7E;   // EQUALS SIGN
  2342.     $003E : Result := #$6E;   // GREATER-THAN SIGN
  2343.     $003F : Result := #$6F;   // QUESTION MARK
  2344.     $0040 : Result := #$7C;   // COMMERCIAL AT
  2345.     $0041..$0049 : Result := Char(Ord(Ch) - $0041 + $C1);   // LATIN CAPITAL LETTER A..I
  2346.     $004A..$0052 : Result := Char(Ord(Ch) - $004A + $D1);   // LATIN CAPITAL LETTER J..R
  2347.     $0053..$005A : Result := Char(Ord(Ch) - $0053 + $E2);   // LATIN CAPITAL LETTER S..Z
  2348.     $005C : Result := #$E0;   // REVERSE SOLIDUS
  2349.     $005F : Result := #$6D;   // LOW LINE
  2350.     $0060 : Result := #$79;   // GRAVE ACCENT
  2351.     $0061..$0069 : Result := Char(Ord(Ch) - $0061 + $81);   // LATIN SMALL LETTER A..I
  2352.     $006A..$0072 : Result := Char(Ord(Ch) - $006A + $91);   // LATIN SMALL LETTER J..R
  2353.     $0073..$007A : Result := Char(Ord(Ch) - $0073 + $A2);   // LATIN SMALL LETTER S..Z
  2354.     $007B : Result := #$C0;   // LEFT CURLY BRACKET
  2355.     $007C : Result := #$4F;   // VERTICAL LINE
  2356.     $007D : Result := #$D0;   // RIGHT CURLY BRACKET
  2357.     $007E : Result := #$A1;   // TILDE
  2358.     $00A2 : Result := #$4A;   // CENT SIGN
  2359.     $00A6 : Result := #$6A;   // BROKEN BAR
  2360.     $00AC : Result := #$5F;   // NOT SIGN
  2361.   else
  2362.     raise EConvertError.Create('Can not convert to EBCDIC-US');
  2363.   end;
  2364. end;
  2365.  
  2366. class function TEBCDIC_USCodec.GetUnicodeCodecType: TUnicodeCodecType;
  2367. begin
  2368.   Result := ucEBCDIC_US;
  2369. end;
  2370.  
  2371. class function TEBCDIC_USCodec.GetAliasCount: Integer;
  2372. begin
  2373.   Result := EBCDIC_USAliases;
  2374. end;
  2375.  
  2376. class function TEBCDIC_USCodec.GetAliasByIndex(const Idx: Integer): String;
  2377. begin
  2378.   Result := EBCDIC_USAlias[Idx];
  2379. end;
  2380.  
  2381. function TEBCDIC_USCodec.DecodeChar(const P: Char): WideChar;
  2382. begin
  2383.   Result := EBCDIC_USToWideChar(P);
  2384. end;
  2385.  
  2386. function TEBCDIC_USCodec.EncodeChar(const Ch: WideChar): Char;
  2387. begin
  2388.   Result := WideCharToEBCDIC_US(Ch);
  2389. end;
  2390.  
  2391.  
  2392.  
  2393. {                                                                              }
  2394. { UTF-8                                                                        }
  2395. {                                                                              }
  2396. const
  2397.   UTF8Aliases = 2;
  2398.   UTF8Alias: Array[1..UTF8Aliases] of String = (
  2399.       'utf8', 'UTF-8');
  2400.  
  2401. { UTF8ToUCS4Char returns UTF8ErrorNone if a valid UTF-8 sequence was decoded   }
  2402. { (and Ch contains the decoded UCS4 character and SeqSize contains the size    }
  2403. { of the UTF-8 sequence). If an incomplete UTF-8 sequence is encountered, the  }
  2404. { function returns UTF8ErrorIncompleteEncoding and SeqSize > Size. If an       }
  2405. { invalid UTF-8 sequence is encountered, the function returns                  }
  2406. { UTF8ErrorInvalidEncoding and SeqSize (<= Size) is the size of the            }
  2407. { invalid sequence, and Ch may be the intended character.                      }
  2408. function UTF8ToUCS4Char(const P: PChar; const Size: Integer;
  2409.     var SeqSize: Integer; var Ch: UCS4Char): TUTF8Error;
  2410. var C, D: Byte;
  2411.     V: LongWord;
  2412.     I: Integer;
  2413. begin
  2414.   if not Assigned(P) or (Size <= 0) then
  2415.     begin
  2416.       SeqSize := 0;
  2417.       Ch := 0;
  2418.       Result := UTF8ErrorInvalidBuffer;
  2419.       exit;
  2420.     end;
  2421.   C := Ord(P^);
  2422.   if C < $80 then
  2423.     begin
  2424.       SeqSize := 1;
  2425.       Ch := C;
  2426.       Result := UTF8ErrorNone;
  2427.       exit;
  2428.     end;
  2429.   if C and $C0 = $80 then
  2430.     begin
  2431.       SeqSize := 1;
  2432.       Ch := C;
  2433.       Result := UTF8ErrorInvalidEncoding;
  2434.       exit;
  2435.     end;
  2436.   if C and $20 = 0 then
  2437.     begin
  2438.       SeqSize := 2;
  2439.       V := C and $1F;
  2440.     end else
  2441.   if C and $10 = 0 then
  2442.     begin
  2443.       SeqSize := 3;
  2444.       V := C and $0F;
  2445.     end else
  2446.   if C and $08 = 0 then
  2447.     begin
  2448.       SeqSize := 4;
  2449.       V := C and $07;
  2450.     end else
  2451.     begin
  2452.       SeqSize := 1;
  2453.       Ch := C;
  2454.       Result := UTF8ErrorInvalidEncoding;
  2455.       exit;
  2456.     end;
  2457.   if Size < SeqSize then
  2458.     begin
  2459.       Ch := C;
  2460.       Result := UTF8ErrorIncompleteEncoding;
  2461.       exit;
  2462.     end;
  2463.   For I := 1 to SeqSize - 1 do
  2464.     begin
  2465.       D := Ord(P[I]);
  2466.       if D and $C0 <> $80 then
  2467.         begin
  2468.           SeqSize := 1;
  2469.           Ch := C;
  2470.           Result := UTF8ErrorInvalidEncoding;
  2471.           exit;
  2472.         end;
  2473.       V := (V shl 6) or (D and $3F);
  2474.     end;
  2475.   Ch := V;
  2476.   Result := UTF8ErrorNone;
  2477. end;
  2478.  
  2479. function UTF8ToWideChar(const P: PChar; const Size: Integer; var SeqSize: Integer; var Ch: WideChar): TUTF8Error;
  2480. var Ch4: UCS4Char;
  2481. begin
  2482.   Result := UTF8ToUCS4Char(P, Size, SeqSize, Ch4);
  2483.   if Ch4 > $FFFF then
  2484.     begin
  2485.       Result := UTF8ErrorOutOfRange;
  2486.       Ch := #$0000;
  2487.     end else
  2488.     Ch := WideChar(Ch4);
  2489. end;
  2490.  
  2491. { UCS4CharToUTF8 transforms the UCS4 char Ch to UTF-8 encoding. SeqSize        }
  2492. { returns the number of bytes needed to transform Ch. Up to DestSize           }
  2493. { bytes of the UTF-8 encoding will be placed in Dest.                          }
  2494. procedure UCS4CharToUTF8(const Ch: UCS4Char; const Dest: Pointer; const DestSize: Integer; var SeqSize: Integer);
  2495. var P: PByte;
  2496. begin
  2497.   P := Dest;
  2498.   if Ch < $80 then
  2499.     begin
  2500.       SeqSize := 1;
  2501.       if not Assigned(P) or (DestSize <= 0) then
  2502.         exit;
  2503.       P^ := Byte(Ch);
  2504.     end else
  2505.   if Ch < $800 then
  2506.     begin
  2507.       SeqSize := 2;
  2508.       if not Assigned(P) or (DestSize <= 0) then
  2509.         exit;
  2510.       P^ := $C0 or Byte(Ch shr 6);
  2511.       if DestSize = 1 then
  2512.         exit;
  2513.       Inc(P);
  2514.       P^ := $80 or (Ch and $3F);
  2515.     end else
  2516.   if Ch < $10000 then
  2517.     begin
  2518.       SeqSize := 3;
  2519.       if not Assigned(P) or (DestSize <= 0) then
  2520.         exit;
  2521.       P^ := $E0 or Byte(Ch shr 12);
  2522.       if DestSize = 1 then
  2523.         exit;
  2524.       Inc(P);
  2525.       P^ := $80 or ((Ch shr 6) and $3F);
  2526.       if DestSize = 2 then
  2527.         exit;
  2528.       Inc(P);
  2529.       P^ := Ch and $3F;
  2530.     end else
  2531.   if Ch < $200000 then
  2532.     begin
  2533.       SeqSize := 4;
  2534.       if not Assigned(P) or (DestSize <= 0) then
  2535.         exit;
  2536.       P^ := $F0 or Byte(Ch shr 18);
  2537.       if DestSize = 1 then
  2538.         exit;
  2539.       Inc(P);
  2540.       P^ := $80 or ((Ch shr 12) and $3F);
  2541.       if DestSize = 2 then
  2542.         exit;
  2543.       Inc(P);
  2544.       P^ := $80 or ((Ch shr 6) and $3F);
  2545.       if DestSize = 3 then
  2546.         exit;
  2547.       Inc(P);
  2548.       P^ := Ch and $3F;
  2549.     end else
  2550.     raise EConvertError.Create('Character out of UTF-8 range');
  2551. end;
  2552.  
  2553. procedure WideCharToUTF8(const Ch: WideChar; const Dest: Pointer; const DestSize: Integer; var SeqSize: Integer);
  2554. begin
  2555.   UCS4CharToUTF8(Ord(Ch), Dest, DestSize, SeqSize);
  2556. end;
  2557.  
  2558. class function TUTF8Codec.GetUnicodeCodecType: TUnicodeCodecType;
  2559. begin
  2560.   Result := ucUTF8;
  2561. end;
  2562.  
  2563. class function TUTF8Codec.GetAliasCount: Integer;
  2564. begin
  2565.   Result := UTF8Aliases;
  2566. end;
  2567.  
  2568. class function TUTF8Codec.GetAliasByIndex(const Idx: Integer): String;
  2569. begin
  2570.   Result := UTF8Alias[Idx];
  2571. end;
  2572.  
  2573. procedure TUTF8Codec.Decode(const Buf: Pointer; const BufSize: Integer; const DestBuf: Pointer; const DestSize: Integer; var ProcessedBytes, DestLength: Integer);
  2574. var P: PChar;
  2575.     Q: PWideChar;
  2576.     L, I, M, N: Integer;
  2577.     R: TUTF8Error;
  2578.     C: WideChar;
  2579. begin
  2580.   P := Buf;
  2581.   L := BufSize;
  2582.   Q := DestBuf;
  2583.   N := DestSize div Sizeof(WideChar);
  2584.   if not Assigned(P) or (L <= 0) or not Assigned(Q) or (N <= 0) then
  2585.     begin
  2586.       ProcessedBytes := 0;
  2587.       DestLength := 0;
  2588.       exit;
  2589.     end;
  2590.   M := 0;
  2591.   Repeat
  2592.     if M >= N then
  2593.       break;
  2594.     try
  2595.       R := UTF8ToWideChar(P, L, I, C);
  2596.       Case R of
  2597.         UTF8ErrorNone:
  2598.           begin
  2599.             Q^ := C;
  2600.             Inc(Q);
  2601.             Inc(M);
  2602.             Inc(P, I);
  2603.             Dec(L, I);
  2604.           end;
  2605.         UTF8ErrorInvalidEncoding:
  2606.           raise EConvertError.Create('Invalid UTF-8 encoding');
  2607.         UTF8ErrorIncompleteEncoding:
  2608.           begin
  2609.             ProcessedBytes := BufSize - L;
  2610.             DestLength := M;
  2611.             exit;
  2612.           end;
  2613.         UTF8ErrorOutOfRange :
  2614.           raise EConvertError.Create('UTF-8 encoding out of range');
  2615.       else
  2616.         raise EConvertError.Create('UTF-8 error (' + IntToStr(Ord(R)) + ')');
  2617.       end;
  2618.     except
  2619.       Case FErrorAction of
  2620.         eaException : raise;
  2621.         eaSkip:
  2622.           begin
  2623.             Inc(P, I);
  2624.             Dec(L, I);
  2625.           end;
  2626.         eaIgnore:
  2627.           begin
  2628.             Q^ := C;
  2629.             Inc(Q);
  2630.             Inc(M);
  2631.             Inc(P, I);
  2632.             Dec(L, I);
  2633.           end;
  2634.         eaReplace:
  2635.           begin
  2636.             Q^ := FDecodeReplaceChar;
  2637.             Inc(Q);
  2638.             Inc(M);
  2639.             Inc(P, I);
  2640.             Dec(L, I);
  2641.           end;
  2642.       end;
  2643.     end;
  2644.   Until L = 0;
  2645.   ProcessedBytes := BufSize - L;
  2646.   DestLength := M;
  2647. end;
  2648.  
  2649. function TUTF8Codec.Encode(const S: PWideChar; const Length: Integer;
  2650.     var ProcessedChars: Integer): String;
  2651. var P: PWideChar;
  2652.     Q: PChar;
  2653.     I, L, M, J: Integer;
  2654. begin
  2655.   P := S;
  2656.   if not Assigned(P) or (Length <= 0) then
  2657.     begin
  2658.       ProcessedChars := 0;
  2659.       Result := '';
  2660.       exit;
  2661.     end;
  2662.   L := Length * 3;
  2663.   SetLength(Result, L);
  2664.   Q := Pointer(Result);
  2665.   M := 0;
  2666.   For I := 1 to Length do
  2667.     begin
  2668.       WideCharToUTF8(P^, Q, L, J);
  2669.       Inc(P);
  2670.       Inc(Q, J);
  2671.       Dec(L, J);
  2672.       Inc(M, J);
  2673.     end;
  2674.   ProcessedChars := Length;
  2675.   SetLength(Result, M);
  2676. end;
  2677.  
  2678.  
  2679.  
  2680. {                                                                              }
  2681. { UTF-16                                                                       }
  2682. {                                                                              }
  2683. const
  2684.   UTF16Aliases = 4;
  2685.   UTF16Alias: Array[1..UTF16Aliases] of String = (
  2686.       'utf16', 'UTF-16', 'UTF-16BE', 'UTF-16LE');
  2687.  
  2688. { DetectUTF16Encoding returns True if the encoding was confirmed to be UTF-16. }
  2689. { SwapEndian is True if it was detected that the UTF-16 data is in reverse     }
  2690. { endian from that used by the cpu.                                            }
  2691. function DetectUTF16Encoding(const P: PChar; const Size: Integer; var SwapEndian: Boolean; var HeaderSize: Integer): Boolean;
  2692. begin
  2693.   if not Assigned(P) or (Size < 2) then
  2694.     begin
  2695.       SwapEndian := False;
  2696.       HeaderSize := 0;
  2697.       Result := False;
  2698.     end else
  2699.   if PWideChar(P)^ = WideChar($FEFF) then
  2700.     begin
  2701.       SwapEndian := False;
  2702.       HeaderSize := Sizeof(WideChar);
  2703.       Result := True;
  2704.     end else
  2705.   if PWideChar(P)^ = WideChar($FFFE) then
  2706.     begin
  2707.       SwapEndian := True;
  2708.       HeaderSize := Sizeof(WideChar);
  2709.       Result := True;
  2710.     end else
  2711.     begin
  2712.       SwapEndian := False;
  2713.       HeaderSize := 0;
  2714.       Result := False;
  2715.     end;
  2716. end;
  2717.  
  2718. function SwapUTF16Endian(const P: WideChar): WideChar;
  2719. begin
  2720.   Result := WideChar(((Ord(P) and $FF) shl 8) or (Ord(P) shr 8));
  2721. end;
  2722.  
  2723. procedure TUTF16Codec.Init;
  2724. begin
  2725.   inherited Init;
  2726.   FSwapEndian := False;
  2727. end;
  2728.  
  2729. class function TUTF16Codec.GetUnicodeCodecType: TUnicodeCodecType;
  2730. begin
  2731.   Result := ucUTF16;
  2732. end;
  2733.  
  2734. class function TUTF16Codec.GetAliasCount: Integer;
  2735. begin
  2736.   Result := UTF16Aliases;
  2737. end;
  2738.  
  2739. class function TUTF16Codec.GetAliasByIndex(const Idx: Integer): String;
  2740. begin
  2741.   Result := UTF16Alias[Idx];
  2742. end;
  2743.  
  2744. procedure TUTF16Codec.Decode(const Buf: Pointer; const BufSize: Integer; const DestBuf: Pointer; const DestSize: Integer; var ProcessedBytes, DestLength: Integer);
  2745. var I, L, M: Integer;
  2746.     P, Q: PWideChar;
  2747. begin
  2748.   L := BufSize;
  2749.   if L > DestSize then
  2750.     L := DestSize;
  2751.   if L <= 1 then
  2752.     begin
  2753.       ProcessedBytes := 0;
  2754.       DestLength := 0;
  2755.       exit;
  2756.     end;
  2757.   Dec(L, L mod Sizeof(WideChar));
  2758.   M := L div Sizeof(WideChar);
  2759.   P := Buf;
  2760.   Q := DestBuf;
  2761.   if not FSwapEndian then
  2762.     Move(P^, Q^, L) else
  2763.     For I := 1 to M do
  2764.       begin
  2765.         Q^ := SwapUTF16Endian(P^);
  2766.         Inc(P);
  2767.         Inc(Q);
  2768.       end;
  2769.   DestLength := M;
  2770.   ProcessedBytes := L;
  2771. end;
  2772.  
  2773. function TUTF16Codec.Encode(const S: PWideChar; const Length: Integer;
  2774.     var ProcessedChars: Integer): String;
  2775. var I, L: Integer;
  2776.     P, Q: PWideChar;
  2777. begin
  2778.   if Length <= 0 then
  2779.     begin
  2780.       ProcessedChars := 0;
  2781.       Result := '';
  2782.       exit;
  2783.     end;
  2784.   L := Length * 2;
  2785.   SetLength(Result, L);
  2786.   if not FSwapEndian then
  2787.     Move(S^, Pointer(Result)^, L) else
  2788.     begin
  2789.       P := S;
  2790.       Q := Pointer(Result);
  2791.       For I := 1 to Length do
  2792.         begin
  2793.           Q^ := SwapUTF16Endian(P^);
  2794.           Inc(P);
  2795.           Inc(Q);
  2796.         end;
  2797.     end;
  2798.   ProcessedChars := Length;
  2799. end;
  2800.  
  2801. class function TUTF16RECodec.GetUnicodeCodecType: TUnicodeCodecType;
  2802. begin
  2803.   Result := ucUTF16RE;
  2804. end;
  2805.  
  2806. procedure TUTF16RECodec.Init;
  2807. begin
  2808.   inherited Init;
  2809.   FSwapEndian := True;
  2810. end;
  2811.  
  2812.  
  2813.  
  2814. {                                                                              }
  2815. { TUnicodeCodecType                                                            }
  2816. {                                                                              }
  2817. const
  2818.   UnicodeCodecMap: Array[TUnicodeCodecType] of TUnicodeCodecClass = (nil,
  2819.       TASCIICodec,
  2820.       TISO8859_1Codec, TISO8859_2Codec, TISO8859_3Codec, TISO8859_4Codec, TISO8859_5Codec,
  2821.       TISO8859_6Codec, TISO8859_7Codec, TISO8859_8Codec, TISO8859_9Codec, TISO8859_10Codec,
  2822.       TISO8859_13Codec, TISO8859_14Codec, TISO8859_15Codec,
  2823.       TKOI8_RCodec,
  2824.       TMacLatin2Codec, TMacRomanCodec, TMacCyrillicCodec,
  2825.       TCP437Codec,
  2826.       TWin1250Codec, TWin1251Codec, TWin1252Codec,
  2827.       TEBCDIC_USCodec,
  2828.       TUTF8Codec, TUTF16Codec, TUTF16RECodec);
  2829.  
  2830. function GetUnicodeCodecClassByType(const CodecType: TUnicodeCodecType): TUnicodeCodecClass;
  2831. begin
  2832.   Result := UnicodeCodecMap[CodecType];
  2833. end;
  2834.  
  2835. function GetUnicodeCodecClassByName(const Name: String): TUnicodeCodecClass;
  2836. var I: TUnicodeCodecType;
  2837.     C, J: Integer;
  2838.     D: TUnicodeCodecClass;
  2839. begin
  2840.   For I := Low(TUnicodeCodecType) to High(TUnicodeCodecType) do
  2841.     begin
  2842.       D := UnicodeCodecMap[I];
  2843.       C := D.GetAliasCount;
  2844.       For J := 0 to C - 1 do
  2845.         if AnsiCompareText(Name, D.GetAliasByIndex(J)) = 0 then
  2846.           begin
  2847.             Result := D;
  2848.             exit;
  2849.           end;
  2850.     end;
  2851.   Result := nil;
  2852. end;
  2853.  
  2854.  
  2855.  
  2856. {                                                                              }
  2857. { Unicode conversion functions                                                 }
  2858. {                                                                              }
  2859. function DecodeUnicodeEncoding(const Codec: TUnicodeCodecType; const Buf: Pointer; const BufSize: Integer; var ProcessedBytes: Integer): WideString;
  2860. var C: TUnicodeCodecClass;
  2861.     D: AUnicodeCodec;
  2862. begin
  2863.   C := UnicodeCodecMap[Codec];
  2864.   if not Assigned(C) then
  2865.     begin
  2866.       Result := '';
  2867.       exit;
  2868.     end;
  2869.   D := C.Create;
  2870.   try
  2871.     Result := D.DecodeStr(Buf, BufSize, ProcessedBytes);
  2872.   finally
  2873.     D.Free;
  2874.   end;
  2875. end;
  2876.  
  2877. function EncodeUnicodeEncoding(const Codec: TUnicodeCodecType; const S: WideString;
  2878.     var ProcessedChars: Integer): String;
  2879. var C: TUnicodeCodecClass;
  2880.     D: AUnicodeCodec;
  2881. begin
  2882.   C := UnicodeCodecMap[Codec];
  2883.   if not Assigned(C) then
  2884.     begin
  2885.       ProcessedChars := 0;
  2886.       Result := '';
  2887.       exit;
  2888.     end;
  2889.   D := C.Create;
  2890.   try
  2891.     Result := D.Encode(Pointer(S), Length(S), ProcessedChars);
  2892.   finally
  2893.     D.Free;
  2894.   end;
  2895. end;
  2896.  
  2897.  
  2898.  
  2899. {                                                                              }
  2900. { Character-set conversion functions                                           }
  2901. {                                                                              }
  2902. function IsASCIIStr(const S: String): Boolean;
  2903. var I: Integer;
  2904.     P: PChar;
  2905. begin
  2906.   P := Pointer(S);
  2907.   For I := 1 to Length(S) do
  2908.     if Ord(P^) >= $80 then
  2909.       begin
  2910.         Result := False;
  2911.         exit;
  2912.       end else
  2913.       Inc(P);
  2914.   Result := True;
  2915. end;
  2916.  
  2917. function ISO8859_1ToUTF8(const S: String): String;
  2918. var P, Q: PChar;
  2919.     L, I, M, J: Integer;
  2920. begin
  2921.   L := Length(S);
  2922.   if L = 0 then
  2923.     begin
  2924.       Result := '';
  2925.       exit;
  2926.     end;
  2927.   // Calculate size
  2928.   M := L;
  2929.   P := Pointer(S);
  2930.   For I := 1 to L do
  2931.     begin
  2932.       if Ord(P^) >= $80 then
  2933.         Inc(M); // 2 bytes required for #$80-#$FF
  2934.       Inc(P);
  2935.     end;
  2936.   // Check if conversion is required
  2937.   if M = L then // All characters are ASCII
  2938.     begin
  2939.       Result := S;
  2940.       exit;
  2941.     end;
  2942.   // Convert
  2943.   SetLength(Result, M);
  2944.   Q := Pointer(Result);
  2945.   P := Pointer(S);
  2946.   For I := 1 to L do
  2947.     begin
  2948.       WideCharToUTF8(ISO8859_1ToWideChar(P^), Q, M, J);
  2949.       Inc(P);
  2950.       Inc(Q, J);
  2951.       Dec(M, J);
  2952.     end;
  2953. end;
  2954.  
  2955. function UTF8ToWideString(const S: String): WideString;
  2956. var P: PChar;
  2957.     Q: PWideChar;
  2958.     L, M, I: Integer;
  2959.     C: WideChar;
  2960. begin
  2961.   L := Length(S);
  2962.   if L = 0 then
  2963.     begin
  2964.       Result := '';
  2965.       exit;
  2966.     end;
  2967.   P := Pointer(S);
  2968.   SetLength(Result, L); // maximum size
  2969.   Q := Pointer(Result);
  2970.   M := 0;
  2971.   Repeat
  2972.     UTF8ToWideChar(P, L, I, C);
  2973.     Assert(I > 0, 'I > 0');
  2974.     Q^ := C;
  2975.     Inc(Q);
  2976.     Inc(M);
  2977.     Inc(P, I);
  2978.     Dec(L, I);
  2979.   Until L = 0;
  2980.   SetLength(Result, M); // actual size
  2981. end;
  2982.  
  2983. function WideStringToUTF8(const S: WideString): String;
  2984. var P: PWideChar;
  2985.     Q: PChar;
  2986.     I, L, M, N, J: Integer;
  2987. begin
  2988.   L := Length(S);
  2989.   if L = 0 then
  2990.     begin
  2991.       Result := '';
  2992.       exit;
  2993.     end;
  2994.   N := L * 3;
  2995.   SetLength(Result, N); // maximum size
  2996.   P := Pointer(S);
  2997.   Q := Pointer(Result);
  2998.   M := 0;
  2999.   For I := 1 to L do
  3000.     begin
  3001.       UCS4CharToUTF8(UCS4Char(P^), Q, N, J);
  3002.       Inc(P);
  3003.       Inc(Q, J);
  3004.       Dec(N, J);
  3005.       Inc(M, J);
  3006.     end;
  3007.   SetLength(Result, M); // actual size
  3008. end;
  3009.  
  3010. function UCS4CharToUTF8Str(const Ch: UCS4Char): String;
  3011. var Buf: Array[0..3] of Byte;
  3012.     Size, I: Integer;
  3013.     P, Q: PChar;
  3014. begin
  3015.   Size := 0;
  3016.   UCS4CharToUTF8(Ch, @Buf, Sizeof(Buf), Size);
  3017.   SetLength(Result, Size);
  3018.   if Size > 0 then
  3019.     begin
  3020.       P := Pointer(Result);
  3021.       Q := @Buf;
  3022.       For I := 0 to Size - 1 do
  3023.         begin
  3024.           P^ := Q^;
  3025.           Inc(P);
  3026.           Inc(Q);
  3027.         end;
  3028.     end;
  3029. end;
  3030.  
  3031. function ASCIIToWideString(const S: String): WideString;
  3032. var L, I: Integer;
  3033.     P: PChar;
  3034.     Q: PWideChar;
  3035. begin
  3036.   L := Length(S);
  3037.   SetLength(Result, L);
  3038.   if L = 0 then
  3039.     exit;
  3040.   P := Pointer(S);
  3041.   Q := Pointer(Result);
  3042.   For I := 1 to L do
  3043.     begin
  3044.       Q^ := WideChar(P^);
  3045.       Inc(P);
  3046.       Inc(Q);
  3047.     end;
  3048. end;
  3049.  
  3050.  
  3051.  
  3052. end.
  3053.  
  3054.