Unicode学习笔记和一些“手筋”作品,大家看着有用的话就拿去--顶者皆有分!!!(200分)

韦剑

Unregistered / Unconfirmed
GUEST, unregistred user!
==========================================================
一个完整提供了处理所有Unicode编码格式和编码机制的底层
功能例程的动态链接库(DLL)--包括所有源程序、参考资
料和演示程序。
下载地址:http://blog.2ok.cn/UploadFiles/2006-8/813543954.rar
==========================================================
  因为要做支持Unicode的程序,半年前开始自己啃Unicode标准的原文。发现虽然Delphi7自带有不少支持Unicode的机制,而第三方的TntUnicode组件包也对Delphi开发环境下的Unicode编码处理提供了强大的支持。但老实说,如果不是自己阅读过Unicode标准的原文的并了解其编码原理的话,是很难说真正掌握了TntUnicode的强大功能的。
  而在学习Unicode标准的过程中,我对照了Unicode编码框架和TntUnicode提供的例程库,发现TntUnicode虽然提供了很多处理Unicode编码的例程,但并不完整,而且TntUnicode组件包及其官方网址上提供的参考资料很少,所以即便看着TntUnicode的源码也往往不知所云。
  正好这几个月中在大富翁上参与了几个有关Unicode帖子的讨论,发觉现在还是有很多跟当初的自己一样,因为缺少对第一手的Unicode标准资料的了解,而迟迟没能跨入Unicode这片广阔天地的程序员朋友的。根据目前能在中文网站上搜集得到的有关编程处理Unicode编码的资料的基本情况,我觉得很有必要系统地整理一套编程处理所急需的、程序员看了马上能根据其中讲述的原理上手写程序解决实际问题的Unicode标准资料。所以我把自己在学习Unicode标准原文时翻译的资料和心得体会整理了一下,把自己为验证Unicode编码原理练手时而写的底层编码处理函数加上TntUnicode所欠缺的那部分,组成一个完整的Unicode编码处理例程库用DLL项目的形式公布出来,顺带把自己为试验这些例程所写的一个验证程序也一并给出。大家可以把这个软件包当作一块完整体验Unicode标准及其编码处理原理的“敲门砖”,里面附带的源程序、参考资料和算法设计原理完全公开,没有任何使用和传播上的限制。
  当然,如果哪位朋友完善或改进了这个软件包,希望大家能本着Unicode标准自由、公开、共享的原则,让更多的程序员朋友一起分享这个有用的工具。
  如果大家对这个软件包有什么问题或建议,欢迎来信至craftsman1986@163.com与我讨论。谢谢!
 
沙发啊,多点分!
 
写心得还要送坛币 真是雷锋啊 不过下载不了
 
怎么下载下来是 --------- UCS瑞士军刀演武堂
???
 
打造UCS瑞士军刀
Unicode是由国际组织设计,可以容纳全世界所有语言文字的编码方案。Unicode的学名是“Universal Multiple-Octet Coded Character Set”,简称为UCS。UCS可以看作是“Unicode Character Set”的缩写。
瑞士军刀――在一把小型刀具上赋予了许多的实用小工具,解决了人们在日常工作及生活中的种种难题。而且不论在何种环境下,瑞士军刀都表现出它非凡的实用价值及相应的质量品质。
本文意在抛砖引玉,希望通过我自己掌握的一些关于Unicode标准的知识,编写、收集一些原生代码的通用Unicode文本处理算法。虽然在很多主流的软件开发工具包中,并不缺乏类似这样的函数库或组件包。但既然经常在文本处理编程中摸爬滚打,多掌握一些底层的编程技术和原理并不是什么坏事――谁知道呢,说不定哪天这些技巧可以有助于提高你程序的性能,而你自己则可以很清楚地知道这些性能是怎么被“榨取”出来的――这是使用封装过的库函数或组件接口所无法获得的对核心技术的掌握,这样即使将来编码标准有什么改变,你也能第一时间对算法库进行相应的更新。
因为我自己从事的是Windows平台上的软件开发工作,平时用得最多的开发工具是Delphi7。所以我在这里给出的算法实例程序是基于Win32平台、使用Delphi语法编写的。不过既然是通用算法库,我把它们的接口组织为适合编译成Windows DLL动态链接库的形式:函数调用方式、入口参数和返回值的数据类型均按照Win32 API的标准设置。只要稍作修改,就可以用Delphi编译成DLL,完全可以提供给用MASM32、Delphi、C++Builder、VC和VB等Win32通用软件开发工具编写的程序调用。使用其他开发工具的朋友,欢迎分享这些算法的相应编程语言版本的源程序,或者你有其他有关Unicode文本处理任务的通用算法实现程序,也欢迎共享。
好啦,闲话少叙,现在就先从各种操作系统中应用最广泛的UTF-16编码格式开始吧。

UTF-16编码格式
因为UTF-16编码格式是在大多数操作系统中首选的Unicode内码实现方案,所以在这些操作系统上的软件开发工具提供的标准Unicode字符串数据类型从存取格式上来说其实就是UTF-16编码单元序列。所谓编码单元是指在某种编码格式中,可以直接存取和处理的一个编码单位,以计算机的存储单位来衡量。比如UTF-16使用16位编码单元,UTF-16字符串的每个元素都是一个16位编码单元。
对于使用UTF-16作为Unicode内码实现方案的操作系统来说,应用程序可以直接存取Unicode字符串中的每个16位编码单元,所以如果字符串中都是BMP字符的话,使用单个的16位编码单元就可以表示每一个字符了。在这种情况下,UTF-16字符串的处理并没有什么特别和复杂的地方。
UTF-16编码格式的特别之处在于:因为Unicode标准已经扩展了超过BMP范围之外的16个增补字符平面,而这些增补字符的编码点都是大于U+FFFF的,所以不能用单个的16位编码单元来直接表示它们。为此UTF-16引入了被称为“代理对”的编码机制,用两个相连不可分割的16位编码单元来表示一个增补字符。
以下是代理对机制的基本要素:
 代理对由前后两个16位编码单元组成,分别称为高位代理和低位代理。
 高位代理的取值范围在U+D800到U+DBFF之间,低位代理的取值范围在U+DC00到U+DFFF之间。由于高低代理的取值范围是前后相接的,所以合并起来得到U+ D800到U+DFFF这个“代理取值范围”。
 在字符串中,凡是取值在U+ D800到U+DFFF之外的编码单元就是BMP字符,否则就是代理对编码单元。
 在字符串中,代理必须成对给出,不可分割。也就是说,高位代理的后面必须是一个低位代理,低位代理的前面必须是一个高位代理;高位代理的前面不能是一个高位代理,低位代理的后面不能是一个低位代理。
因此在UTF-16字符串中,如果要对代理对提供完整支持的话,至少应该实现以下几个基本功能:
1. 在字符串中判断某个位置上的编码单元的类型(即是无效编码单元、BMP字符、高位代理还是低位代理)。
2. 把编码点转换为UTF-16字符串。
3. 计算UTF-16字符串中指定位置上的编码单元所属的那个字符的编码点。
4. 把代理对转换为编码点。
5. 编码点转换为代理对。
编码单元类型识别
原理:很简单,根据前面总结的几条代理对机制基本元素,就可以编写出相应的识别算法了。
编程:
// 判断UTF-16编码格式字符串中指定位置编码单元的类型:
// 0 表示 无效编码单元
// 1 表示 BMP字符
// 2 表示 高位代理
// 3 表示 低位代理
function UTF16CodeUnitType(UTF16Str:pWideChar;Index:integer):integer;
stdcall;
var
UTF16Code:Word;
begin
if (UTF16Str<>nil) and (UTF16Str^<>#0) then
begin
UTF16Code:=Ord(UTF16Str[Index-1]);
if (UTF16Code>=$D800) and (UTF16Code<=$DFFF) then
begin
if UTF16Code<=$DBFF then
begin
if UTF16Str[Index]<>#0 then
begin
UTF16Code:=Ord(UTF16Str[Index]);
if (UTF16Code>=$DC00) and (UTF16Code<=$DFFF) then
Result:=2
else
Result:=0
end
else
Result:=0
end
else
if Index>1 then
begin
UTF16Code:=Ord(UTF16Str[Index-2]);
if (UTF16Code>=$D800) and (UTF16Code<=$DBFF) then
Result:=3
else
Result:=0
end
else
Result:=0
end
else
Result:=1
end
else
Result:=0
end;

把编码点转换为UTF-16字符串
原理:因为代理对由前后两个代理组成,所以根据高低代理取值范围的定义,可以很容易地计算出代理对可以表示的增补字符总数=(0xDBFF-0xD800+1)*(0xDFFF-0xDC00+1)=1048576。而在Unicode标准里面,每个字符平面的大小是65536,由于1048576/65536=16,所以增补字符平面总共有16个。所有增补字符的Unicode编码点取值范围在U+10000到U+10FFFF之间,其中第一个增补平面在U+10000到U+1FFFF之间;第二个增补平面在U+20000至U+2FFFF之间;……第十六个增补平面在U+100000到U+10FFFF之间。
对于把编码点转换为UTF-16字符串的工作来说,如果是BMP编码点的话很简单,编码点的值就等于UTF-16编码单元的值。关键部分在于增补字符也就是增补编码点如何转换为代理对的问题。既然已经知道代理对由前后两个代理编码单元组成,而且所有增补编码点都被分配到了16个相同大小的增补平面中,那么对问题的分析不妨从高位代理取值范围、低位代理取值范围、增补平面的数量、每个字符平面的大小等四个已知条件之间的关系入手。先来考虑一种比较“理想化”的情况:在高低两个代理中,如果高位代理代表的是增补编码点所在的增补平面的编号(比如U+10000在第一增补平面,U+2003F在第二增补平面),而低位代理就应该代表增补编码点在它所在的增补平面中的编码位置(比如U+10000在第一增补平面的第0x00编码位置上,U+2003F在第二增补平面的第0x3F编码位置上)。
那么根据这个思路,低位代理的取值范围至少应该满足一个条件:那就是总共可以提供65536个可能的低位代理。但通过简单的计算,0xDFFF-0xDC00+1=1024,也就是实际上总共只会有1024个可能的低位代理。这与上面这个假设所需要的65536差很远,但并非完全没有希望,因为还没有讨论高位代理那边的情况呢。根据高位代理的取值范围进行简单的计算,0xDBFF-0xD800+1=1024,这就是说总共会有1024个可能的高位代理,而前面进行的“高位代理代表增补平面编号”这个假设只需要16个就够了,那么1024/16=64,这意味着高位代理在履行完表示增补平面编号这个职责之后,还能提供额外的因数(64)继续参与原来的假设。那么剩下的最后一个悬念就是:高位代理的第二个因数64和低位代理的1024个编码位置相乘,到底能不能达到一个字符平面的大小。验证过程简单而激动人心,因为结果证明了先前的假设,64*1024=65536。
既然假设是成立的,就得出了另一个计算代理对可以组合出的增补编码点总数的公式:16*64*1024=1048576,其中16*64=0xDBFF-0xD800+1。
分析到了这里,就可以对增补编码点和代理对之间的转换算法总结出以下几个关键点:
&#61548; 高位代理从0xD800开始,低位代理从0xDC00开始。
&#61548; 高位代理取值范围分为16个区,每个区有包含64个高位代理。因此对于一个给定的高位代理,减去0xD800后的值就可以用来计算高位代理所在的分区编号和分区内的编码位置了。因为16个分区的区段划分如下:0xD800至0xD83F(第一区)、0xD840至0xD87F(第二区)、……0xDBC0至0xDBFF(第十六区)。这16个分区对应16个增补平面,也就是说每个增补平面会分到64个高位代理。
&#61548; 对于一个给定的低位代理,减去0xDC00后的值等于相应的增补编码点在它所在的增补平面中的编码位置对1024取余。
最后,可以得到三个公式:
高位代理=0xD800+(编码点 div 0x10000 - 1)*64+(编码点 mod 0x10000) div 1024
低位代理=0xDC00+(编码点 mod 0x10000) mod 1024
编码点=((高位代理-0xD800) div 64 + 1)*0x10000+(高位代理-0xD800) mod 64 *1024+低位代理-0xDC00
注:在上述公式中,div和mod两个运算符号分别表示“整除”和“取余”。
编程:
// 把编码点转换为UTF-16编码单元序列
function CPToUTF16CUS(UTF16Str:pWideChar;Code:DWORD):integer;
stdcall;
var
HighSurr,LowSurr,PosOfPanel:Word;
begin
if Code<=$10FFFF then
begin
if Code<=$FFFF then
begin
if UTF16Str<>nil then
begin
UTF16Str[0]:=WideChar(Code);
UTF16Str[1]:=#0
end;
Result:=1
end
else
begin
if UTF16Str<>nil then
begin
PosOfPanel:=Code mod $10000;
HighSurr:=$D800+(Code div $10000 - 1)*64+PosOfPanel div 1024;
LowSurr:=$DC00+PosOfPanel mod 1024;
UTF16Str[0]:=WideChar(HighSurr);
UTF16Str[1]:=WideChar(LowSurr);
UTF16Str[2]:=#0
end;
Result:=2
end
end
else
Result:=0
end;

UTF-16字符转换为编码点
原理:这个算法的原理和公式在前面的“把编码点转换为UTF-16字符串”中已经分析过了。
编程:
// 把UTF-16编码格式字符串中指定位置上的编码单元所属的字符的
// 编码单元序列转换为编码点
function UTF16CUSToCP(UTF16Str:pWideChar;Index:integer):DWORD;
stdcall;
var
HighSurr,LowSurr:Word;
Unicode:DWORD;
begin
if (UTF16Str<>nil) and (UTF16Str^<>#0) then
begin
HighSurr:=UTF16CodeUnitType(UTF16Str,Index);
case HighSurr of
1:
Result:=Ord(UTF16Str[Index-1]);
2,3:
begin
if HighSurr=2 then
begin
HighSurr:=Ord(UTF16Str[Index-1]);
LowSurr:=Ord(UTF16Str[Index])
end
else
begin
HighSurr:=Ord(UTF16Str[Index-2]);
LowSurr:=Ord(UTF16Str[Index-1])
end;
HighSurr:=HighSurr-$D800;
Unicode:=(HighSurr div 64 + 1)*$10000;
LowSurr:=HighSurr mod 64 * 1024+LowSurr-$DC00;
Result:=Unicode+LowSurr
end
else
Result:=$FFFFFFFF
end
end
else
Result:=$FFFFFFFF
end;

代理对转换为编码点
原理:借助UTF16CUSToCP函数把指定的代理对(参数HighSurr、LowSurr分别代表高位代理和低位代理)转换为相应的增补编码点。
编程:
// 代理对转换为编码点
function SurrPairToCP(HighSurr,LowSurr:WORD):DWORD;
stdcall;
var
S:array [0..1] of WideChar;
begin
S[0]:=WideChar(HighSurr);
S[1]:=WideChar(LowSurr);
Result:=UTF16CUSToCP(S,1)
end;

编码点转换为代理对
原理:借助CPToUTF16CUS函数把指定的增补编码点转换为相应的代理对。
编程:
// 编码点转换为代理对
function CPToSurrPair(UnicodeValue:DWORD):DWORD;
stdcall;
var
S:array [0..2] of WideChar;
begin
CPToUTF16CUS(S,UnicodeValue);
Result:=Ord(S[0]) shl 16 + Ord(S[1])
end;


UTF-8编码格式
对于UTF-8编码格式的处理,关键是两个表(表头的表号是该表在Unicode标准原文中的编号,而不是本文的编号)。
表3-5. UTF-8 位分配规则
Unicode数字 第一字节 第二字节 第三字节 第四字节
00000000 0xxxxxxx 0xxxxxxx
00000yyy yyxxxxxx 110yyyyy 10xxxxxx
zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx

表3-6. 有效UTF-8 格式字节序列
编码点 第一字节 第二字节 第三字节 第四字节
U+0000..U+007F 00..7F
U+0080..U+07FF C2..DF 80..BF
U+0800..U+0FFF E0 A0..BF 80..BF
U+1000..U+CFFF E1..EC 80..BF 80..BF
U+D000..U+D7FF ED 80..9F 80..BF
U+E000..U+FFFF EE..EF 80..BF 80..BF
U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
大多数情况下第二个字节的取值范围都在80..BF之间,但有少数几个是例外,这些例外取值范围已经在表中用粗斜体标记了出来。
结合这些格式规则可以得出一个结论:取值在C0–C1或F5–FF.之间的字节都是无效UTF-8格式编码单元。
对UTF-8编码格式的处理有以下几个关键点:
&#61548; UTF-8使用8位编码单元,因此UTF-8字符串的每个单元就是一个字节。
&#61548; 对于目前已经确定的所有非代理Uniocde编码点(U+0000至U+10FFFF),UTF-8编码格式需要1到4个字节的编码序列来表示它们。编码点数值越大,所需的UTF-8编码单元序列就越长。
&#61548; 对于某个有效UTF-8格式字节序列来说,可以用检查它的第一个字节值的方法来判断这个序列的长度:如果它的最高位为0,则表示序列的长度为1;如果它的最高两位为1,第六位为0,则表示序列的长度为2;如果它的最高3位为1,第五位为0,则表示序列的长度为3;如果它的最高4位为1,第四位为0,则表示序列的长度为4。
&#61548; 根据编码单元序列中具体各个字节的取值定义情况的相似性,U+0000到U+10FFFF范围内的所有非代理编码点中,可以划分归纳为9个不同的区段(编号0-8)。这个编码点区段划分我称之为“UTF-8编码点分段”,有关这9个区段的详细信息(包括:1.编码点范围;2.所需UTF-8编码字节数;3.各字节上的取值范围),已经在表3-6中描述得很清楚了。
因为UTF-8字符串的最大特点就是它跟ANSI字符串一样,也是8位编码单元的序列。所以它非常适合那些不支持UTF-16字符串数据类型的“古董级”开发工具使用,比如那些DOS下的软件开发工具所提供的ANSI字符串数据类型完全可以用来处理UTF-8字符串。
即使是像Delphi这样的现代软件开发工具,它里面提供的UTF-8处理函数也是用ANSI字符串数据类型来存储UTF-8字符串的。而且就我自己的感觉而言,用传统的ANSI字符串来存储UTF-8字符串确实也很方便。因此,在以下这些跟UTF-8编码格式处理有关的算法中,也是用ANSI字符串来存储UTF-8字符串。
求UTF-8编码格式字符串中某个位置上的编码单元在它自己所属的字符中的索引位置
原理:判断指定位置上的那个字节的值,根据表3-6对UTF-8编码字节序列的规定,如果当前字节是序列中的第一个字节的话,就可以返回索引位置(1)了。
如果当前字节不是序列中的第一个字节,就必须向前检索,直到找到序列的第一个字节或整个字符串的第一个字节为止:如果一直检索到了字符串的第一个字节也没有找到序列的第一个字节,就说明从字符串的第一个字节开始到第一次检查的那个字节为止的序列,是一个无效字节序列;如果找到了序列中的第一个字节,就通过当前字节索引和第一次检查的那个字节的索引计算出返回索引位置(2-4)。
编程:
// 求UTF-8编码格式字符串中某个位置上的编码单元在它自己所属的
// 字符中的索引位置:0表示无效编码单元;1表示第一个编码单元;
// 2表示第二个编码单元,3表示第三个编码单元,4表示第四个编码
// 单元。同时通过变参CPPartIndexOfUTF8返回该(有效)字符的编
// 码点在UTF8编码格式中的分段索引;CharSize返回该(有效)字
// 符的长度。
function UTF8CUIndexOfChar(UTF8Str:pChar;Index:integer;
CPPartIndexOfUTF8,CharSize:pInteger):integer;
stdcall;
label 10;
var
TmpByte:Byte;
i:integer;
InvalUTF8CUSet:set of Byte;
begin
if (UTF8Str<>nil) and (UTF8Str^<>#0) then
begin
InvalUTF8CUSet:= [$C0..$C1,$F5..$FF];
TmpByte:=Ord(UTF8Str[Index-1]);
if TmpByte in InvalUTF8CUSet then
begin
CPPartIndexOfUTF8^:=-1;
CharSize^:=0;
Result:=0
end
else
begin
i:=0;
10:
case TmpByte of
$00..$7F:
begin
CPPartIndexOfUTF8^:=0;
CharSize^:=1;
Result:=1;
exit
end;
$C2..$F4:
case TmpByte of
$C2..$DF:
begin
CPPartIndexOfUTF8^:=1;
CharSize^:=2
end;
$E0..$EF:
begin
case TmpByte of
$E0:
CPPartIndexOfUTF8^:=2;
$E1..$EC:
CPPartIndexOfUTF8^:=3;
$ED:
CPPartIndexOfUTF8^:=4
else
CPPartIndexOfUTF8^:=5
end;
CharSize^:=3
end
else
begin
case TmpByte of
$F0:
CPPartIndexOfUTF8^:=6;
$F1..$F3:
CPPartIndexOfUTF8^:=7
else
CPPartIndexOfUTF8^:=8
end;
CharSize^:=4
end
end
else
begin
if Index>1 then
begin
if i=0 then
i:=Index;
dec(Index);
TmpByte:=Ord(UTF8Str[Index-1])
end
else
begin
if i=0 then
i:=Index+1
else
inc(i);
While UTF8Str[i-1]<>#0do
begin
TmpByte:=Ord(UTF8Str[i-1]);
if (TmpByte in InvalUTF8CUSet) or (TmpByte and $C0 = $80) then
inc(i)
else
Break
end;
CPPartIndexOfUTF8^:=-1;
CharSize^:=i-Index;
Result:=-1*Index;
exit
end;
goto 10
end
end;

if (CPPartIndexOfUTF8^ in [1..8])
and
(CharSize^ in [2..4])
and
(Index+CharSize^-1<=StrLen(UTF8Str))
then
begin
if i>0 then
Result:=i-Index+1
else
Result:=1
end
else
begin
CPPartIndexOfUTF8^:=-1;
CharSize^:=0;
Result:=0
end
end
end
else
begin
CPPartIndexOfUTF8^:=-1;
CharSize^:=0;
Result:=0
end
end;

把Unicode编码点转换为UTF-8编码单元序列
原理:表3-6把所有非代理编码点划分为了九个区段,每个区段都规定了各自的编码点取值范围,以及用来表示这个范围内的编码点的UTF-8编码单元序列上各个字节的取值范围。比如第3区段(区段编号从0到8)的定义是这样的:

这个区段定义的意思是说:所有取值在U+1000到U+CFFF范围内的编码点的UTF-8编码单元序列由3个字节组成,其中第一字节的取值范围是0xE1到0xEC;第二字节的取值范围是0x80到0xBF;第三字节的取值范围是0x80到0xBF。
既然第3区段下辖的编码点总数=0xCFFF-0x1000+1=49152,而那三个UTF-8编码格式的字节组成的序列又是用来表示这49152个编码点的,那么按理来说就应该有:第一字节允许的取值总数×第二字节允许的取值总数×第三字节允许的取值总数(注:所谓允许,就是指该字节被UTF-8编码格式规范限制在哪个范围内取值)=49152。经过简单的计算,(0xEC-0xE1+1)*(0xBF-0x80+1)* (0xBF-0x80+1)=49152。也就是说可以得到下面这个等式:
0xCFFF-0x1000+1=(0xEC-0xE1+1)*(0xBF-0x80+1)* (0xBF-0x80+1)
这个等式是以第3区段为例得到的,经过对其他几个区段做类似的验算也得到了同样的结果。也就是说这是存在于所有UTF-8编码点分段的一个普遍规律,因此可以总结出下面这条公式:
编码点取值范围最大值-编码点取值范围最小值+1=(第1个字节取值范围最大值-第1个字节取值范围最小值+1)* (第2个字节取值范围最大值-第2个字节取值范围最小值+1)* (第3个字节取值范围最大值-第3个字节取值范围最小值+1)* (第4个字节取值范围最大值-第4个字节取值范围最小值+1)
注:这个公式是按照最长4个字节的编码单元序列来给出的,但因为并不是所有的编码点都对应4字节UTF-8序列,所以实际转换时是需要多少个字节就取多少个字节的取值范围来计算。对于取值范围是单一值的字节,可以当作是取值范围的上下限值相同来处理。
接下来可以探讨问题的关键――编码点和UTF-8编码单元序列之间的关系了。仍以UTF-8编码点分段的第3区段为例,假设有编码点U+2300,它对应的UTF-8编码单元序列为<E2 8C 80>,经过简单的计算,可以得到如下的等式:
0x2300-0x1000=(0xE2-0xE1)* (0xBF-0x80+1)* (0xBF-0x80+1)+(0x8C-0x80)* (0xBF-0x80+1)+(0x80-0x80)
把这个等式的变量部分(也就是输入的编码点和输出的UTF-8字节序列部分)和常量部分(也就是UTF-8编码点分段取值范围下限值和各UTF-8字节的取值范围下限值)分别替换成相应的通用名称,可以等到如下这个公式:
编码点-UTF8编码点分段取值范围下限值=(第1字节值-第1字节取值范围下限取值)*(第1字节取值范围上限值-第1字节取值范围下限值+1)* (第2字节取值范围上限值-第2字节取值范围下限值+1)+(第2字节值-第2字节取值范围下限值)* (第2字节取值范围上限值-第2字节取值范围下限值+1)+(第3字节值-第3字节取值范围下限值)
把这个“公式”应用到其他8个UTF-8编码点分段中进行验算,可以证明这个公式是同样有效的――这样一来,实际上就得到了一个Unicode编码点和它对应的UTF-8编码单元序列之间的关系式,有了这个关系式,编写这两者之间的转换算法就是一件很简单的事情了。
注:上面这个“关系式”是以3个字节的UTF-8编码单元序列为例得到的,但对于1、2或4个字节长度的UTF-8序列来说道理都是一样的。简单地“同理可证”即可,限于篇幅,我就不一一列出实际的式子和验算实例了(当初我自己做的全部推演经过和结果是记在纸上的,现在那稿纸已经扔了,我只能随便选一例来说明了)。根据最终推导出来的关系式,我编写了以下两个算法,如果看不明白我上面的推导过程和关系式也不要紧,看算法程序也是一样的――而且,这些个算法可不只是“纸上谈兵”,而是早已应用在我的软件中,经过实践检验过的了。要不然我也不会以DLL输出例程的形式来写它们了,因为在我实际产品的源代码里面,它们本来就是这样子的,我不过把它们从IDE中复制过来罢了。会Delphi的朋友不妨把它们用在自己的程序里面,方知余言不谬也。
附录
下面的两个算法中用到了两个全局变量:InvalUTF8CUSet和CPPartOfUTF8Info,现在先给出它们的定义和初始化。实际上它们两个应该是常量,因为它们属于UTF-8处理例程工作过程中的管理数据结构,涉及了UTF-8编码格式的一些特性,所以它们的值在整个程序生命周期中都是不变的。只不过由于它们是结构数据类型,无法用常量定义而已。
type
// UTF-8编码格式对Unicode编码点的分段的具体编码区间类型
TCPPartOfUTF8CodeRange=
Record
MinCode,MaxCode:DWORD
end;

// UTF-8编码单元的取值范围类型
TCUValueRangeOfUTF8=
Record
MinValue,MaxValue:Byte
end;

// 各编码单元的取值范围类型
TCUValueRange=array [0..3] of TCUValueRangeOfUTF8;
// UTF-8编码格式对Unicode编码点的分段的信息类型
TCPPartOfUTF8Info=
Record
// 分段的编码点区间
CodeRange:TCPPartOfUTF8CodeRange;

CUValueRange:TCUValueRange // 各编码单元的取值范围
end;
// 指向UTF-8编码格式对Unicode编码点的分段的信息的指针类型
TPCPPartOfUTF8Info=^TCPPartOfUTF8Info;

// UTF-8编码格式对Unicode编码点的分段的信息类型
TCPPartsOfUTF8Info=array [0..8] of TCPPartOfUTF8Info;
var
// 无效UTF-8格式编码单元集合
InvalUTF8CUSet:set of Byte=[$C0..$C1,$F5..$FF];
// UTF-8编码格式对Unicode编码点的分段的信息
CPPartOfUTF8Info:TCPPartsOfUTF8Info=
(
(
CodeRange:(MinCode:$0000;MaxCode:$007F);
CUValueRange:
(
(MinValue:$00;MaxValue:$7F),
(MinValue:$FF;MaxValue:$FF),
(MinValue:$FF;MaxValue:$FF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$0080;MaxCode:$07FF);
CUValueRange:
(
(MinValue:$C2;MaxValue:$DF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$0800;MaxCode:$0FFF);
CUValueRange:
(
(MinValue:$E0;MaxValue:$E0),
(MinValue:$A0;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$1000;MaxCode:$CFFF);
CUValueRange:
(
(MinValue:$E1;MaxValue:$EC),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$D000;MaxCode:$D7FF);
CUValueRange:
(
(MinValue:$ED;MaxValue:$ED),
(MinValue:$80;MaxValue:$9F),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$E000;MaxCode:$FFFF);
CUValueRange:
(
(MinValue:$EE;MaxValue:$EF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$10000;MaxCode:$3FFFF);
CUValueRange:
(
(MinValue:$F0;MaxValue:$F0),
(MinValue:$90;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF)
)
),
(
CodeRange:(MinCode:$40000;MaxCode:$FFFFF);
CUValueRange:
(
(MinValue:$F1;MaxValue:$F3),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF)
)
),
(
CodeRange:(MinCode:$100000;MaxCode:$10FFFF);
CUValueRange:
(
(MinValue:$F4;MaxValue:$F4),
(MinValue:$80;MaxValue:$8F),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF)
)
)
);
编程:
// 把编码点转换为UTF-8编码单元序列
function CPToUTF8CUS(UTF8Str:pChar;Code:DWORD):integer;
stdcall;
var
i,j,k:integer;
c:DWORD;
c1:Byte;
begin
j:=0;
for i:=0 to 8do
With CPPartOfUTF8Infodo
if (Code>=CodeRange.MinCode)
and
(Code<=CodeRange.MaxCode)
then
begin
j:=3;
Repeat
if (CUValueRange[j].MinValue in InvalUTF8CUSet)
or
(CUValueRange[j].MaxValue in InvalUTF8CUSet)
then
dec(j)
else
begin
if UTF8Str<>nil then
begin
Code:=Code-CodeRange.MinCode;
c:=1;
for k:=jdo
wnto 0do
begin
c1:=CUValueRange[k].MaxValue-CUValueRange[k].MinValue+1;
UTF8Str[k]:=Chr(CUValueRange[k].MinValue + Code div c mod c1);
c:=c*c1;
Code:=Code-Code mod c
end;
UTF8Str[j+1]:=#0
end;

Break
end
Until j<0;
inc(j);
Break
end;

Result:=j
end;

UTF-8编码单元序列转换为编码点
原理:跟前面把编码点转换为UTF-8UTF-8编码单元序列算法的原理是一样的。
编程:
// 把UTF-8编码格式字符串中指定位置上的编码单元所属的字符的
// 编码单元序列转换为编码点
function UTF8CUSToCP(UTF8Str:pChar;Index:integer):DWORD;
stdcall;
var
i,chrsize:integer;
c,CPCode:DWORD;
begin
c:=UTF8CUIndexOfChar(UTF8Str,Index,@i,@chrsize);
if c in [1..MaxCodeUnitCountOfUTF8] then
begin
Index:=Index-c+1;
With CPPartOfUTF8Infodo
begin
c:=1;
CPCode:=CodeRange.MinCode;
for chrsize:=chrsize-1do
wnto 0do
begin
CPCode:=CPCode+(Ord(UTF8Str[Index-1+chrsize])-
CUValueRange[chrsize].MinValue)*c;
c:=c*(CUValueRange[chrsize].MaxValue-
CUValueRange[chrsize].MinValue+1)
end;
Result:=CPCode
end
end
else
Result:=$FFFFFFFF
end;

求指定编码点所在的UTF-8编码点分段
原理:根据给定的一个Unicode编码点数字,检索CPPartOfUTF8Info信息结构数组,看看这个编码点属于UTF-8编码点分段中的哪一段(第0到8段)。
编程:
// 求指定编码点所在的UTF-8编码点分段
function GetCPPartIndexOfUTF8(Code:DWORD;
PCPPartOfUTF8Info:TPCPPartOfUTF8Info):integer;
stdcall;
var
i:integer;
begin
i:=0;
While (i<9)
and
(
(Code<CPPartOfUTF8Info.CodeRange.MinCode)
or
(Code>CPPartOfUTF8Info.CodeRange.MaxCode)
)
do
inc(i);
if (i in [0..8])
and
(Code>=CPPartOfUTF8Info.CodeRange.MinCode)
and
(Code<=CPPartOfUTF8Info.CodeRange.MaxCode)
then
begin
PCPPartOfUTF8Info^:=CPPartOfUTF8Info;
Result:=i
end
else
Result:=-1
end;


Unicode编码格式的相互转换
在Unicode标准定义的三种编码格式(即UTF-8、UTF-16和UTF-32)中,UTF-8和UTF-16都不能用一个单独的编码单元表示出所有的Unicode编码点,所以这两个是不定长编码格式。而因为UTF-32能用一个单独的编码单元表示出所有的Unicode编码点,所以它是定长编码格式。由于UTF-32定长编码的特性,所以一个Unicode编码点数字本身就是它的UTF-32编码值。基于这个原因,在实际的Unicode编码处理系统中,真正需要进行的编码格式转换工作只存在于UTF-8和UTF-16编码格式之间,而这两种编码格式与UTF-32编码格式之间的转换实际上等价于它们与Unicode编码点之间的转换――这种转换算法已经在前面实现了。
(单个Unicode编码点的)UTF-16编码单元序列转UTF-8编码单元序列
原理:根据Unicode标准的建议,标准的编码格式之间的转换过程应该是先从源编码格式转换到Unicode编码点,然后再从编码点转换到目标编码格式。
按照这种思路的话,在设计UTF-16转换为UTF-8编码格式的算法时,只需要简单地依次调用UTF16CUSToCP(UTF-16编码单元序列转编码点)和CPToUTF8CUS(编码点转UTF-8编码单元序列)两个函数就可以了。
不过,Unicode标准也提到了一点,就是在充分理解了源编码格式和目标编码格式之间的关系的基础上,利用它设计出一个不需要经过编码点这个“中转站”,直接从源编码格式转换为目标编码格式的新算法,并明显能比“源编码格式->编码点->目标编码格式”的标准转换方式提高性能的做法是值得提倡的。
因此,我把UTF16CUSToCP和CPToUTF8CUS两个函数的核心算法抽取出来,重新结合成了一个新的UTF16ToUTF8ForChar函数,实现了直接从UTF-16编码格式转换为UTF-8编码格式的功能。由于这个新函数在工作过程中根据UTF-16编码格式的特点,对于BMP字符直接通过CPToUTF8CUS函数进行转换,只有增补字符才需要经过先转为编码点这一步骤。而且并不需完全把UTF-16源编码格式转换为Unicode编码点数字,只需要计算出增补编码点的整数部分即可,另外因为所有的增补编码点都需要4个字节的UTF-8编码单元序列,所以转换过程中也不需要经过计算编码单元序列长度这一步骤。这样由于整体上省却了几个关键但又占据相当处理时间的步骤,所以它能明显地比“源编码格式->编码点->目标编码格式”的标准转换方式提高性能(因为在标准转换方式中,上述这几个步骤是不可能省掉的)。
编程:
// (单个Unicode编码点的)UTF-16编码单元序列转UTF-8编码单元序列
function UTF16ToUTF8ForChar(UTF16Str:pWideChar;Index:integer;
UTF8Str:pChar):integer;
stdcall;
var
HighSurr,LowSurr:WORD;
c,c1,Code:DWORD;
TmpByte:Byte;
CPPartOfUTF8Info:TCPPartOfUTF8Info;
begin
case UTF16CodeUnitType(UTF16Str,Index) of
1:
begin
Result:=CPToUTF8CUS(UTF8Str,Ord(UTF16Str[Index-1]));
exit
end;
2:
begin
HighSurr:=Ord(UTF16Str[Index-1]);
LowSurr:=Ord(UTF16Str[Index])
end;
3:
begin
HighSurr:=Ord(UTF16Str[Index-2]);
LowSurr:=Ord(UTF16Str[Index-1])
end
else
begin
Result:=0;
exit
end
end;

if UTF8Str<>nil then
begin
HighSurr:=HighSurr-HighSurrStart;
Code:=(HighSurr div $40 + 1)*$10000;
GetCPPartIndexOfUTF8(Code,@CPPartOfUTF8Info);
With CPPartOfUTF8Infodo
begin
Code:=Code-CodeRange.MinCode;
c1:=HighSurr mod $40 *1024+LowSurr-LowSurrStart;
c:=CUValueRange[3].MaxValue-CUValueRange[3].MinValue+1;
UTF8Str[3]:=Chr(CUValueRange[3].MinValue + c1 mod c);
c1:=c1 div c;
TmpByte:=CUValueRange[2].MaxValue-CUValueRange[2].MinValue+1;
UTF8Str[2]:=Chr(CUValueRange[2].MinValue + c1 mod TmpByte);
c1:=c1 div TmpByte;
c:=c*TmpByte;
TmpByte:=CUValueRange[1].MaxValue-CUValueRange[1].MinValue+1;
UTF8Str[1]:=Chr(CUValueRange[1].MinValue + Code div c mod TmpByte + c1);
c:=c*TmpByte;
if CUValueRange[0].MinValue=CUValueRange[0].MaxValue then
UTF8Str[0]:=Chr(CUValueRange[0].MinValue)
else
UTF8Str[0]:=Chr(CUValueRange[0].MinValue + Code div c)
end;
UTF8Str[4]:=#0
end;
Result:=4
end;

(单个Unicode编码点的)UTF-8编码单元序列转UTF-16编码单元序列
原理:遗憾的是,在UTF-8向UTF-16编码格式转换算法的设计当中,我没能找得到像UTF-16编码格式转UTF-8那样的可以改进标准转换方式性能的直接转换方法。所以只能采用“UTF-8编码格式->编码点->UTF-16编码格式”这样的标准转换方法了。即依次调用UTF8CUSToCP和CPToUTF16CUS这两个函数实现UTF-8到UTF-16编码格式的转换。
编程:
// (单个Unicode编码点的)UTF-8编码单元序列转UTF-16编码单元序列
function UTF8ToUTF16ForChar(UTF8Str:pChar;Index:integer;
UTF16Str:pWideChar):integer;
stdcall;
begin
Result:=CPToUTF16CUS(UTF16Str,UTF8CUSToCP(UTF8Str,Index))
end;

UTF-16字符串转换为UTF-8字符串
原理:从头到尾检索UTF-16字符串,每识别出一个字符(UTF-16编码单元序列),就调用UTF16ToUTF8ForChar函数把它转换为UTF-8编码单元序列添加到UTF-8字符串中去。
编程:
// UTF-16字符串转换为UTF-8字符串
function UTF16ToUTF8ForStr(UTF16Str:pWideChar;UTF8Str:pChar):integer;
stdcall;
var
j,c:integer;
begin
if (UTF16Str<>nil) and (UTF16Str^<>#0) then
begin
j:=0;
Repeat
if UTF8Str<>nil then
c:=UTF16ToUTF8ForChar(UTF16Str,1,UTF8Str+j)
else
c:=UTF16ToUTF8ForChar(UTF16Str,1,nil);
if TUTF16CUT(UTF16CodeUnitType(UTF16Str,1))=HighSurr then
UTF16Str:=UTF16Str+2
else
inc(UTF16Str);
j:=j+c
Until UTF16Str^=#0;
if UTF8Str<>nil then
UTF8Str[j]:=#0;
Result:=j
end
else
Result:=0
end;

UTF-8字符串转换为UTF-16字符串
原理:从头到尾检索UTF-8字符串,每识别出一个字符(UTF-8编码单元序列),就调用UTF8ToUTF16ForChar函数把它转换为UTF-16编码单元序列添加到UTF-16字符串中去。
编程:
// UTF-8字符串转换为UTF-16字符串
function UTF8ToUTF16ForStr(UTF8Str:pChar;UTF16Str:pWideChar):integer;
stdcall;
var
i,c,charsize:integer;
begin
if UTF8Str<>nil then
begin
i:=0;
While UTF8Str^<>#0do
begin
if UTF16Str<>nil then
c:=UTF8ToUTF16ForChar(UTF8Str,1,UTF16Str+i)
else
c:=UTF8ToUTF16ForChar(UTF8Str,1,nil);
i:=i+c;
c:=UTF8CUIndexOfChar(UTF8Str,1,@c,@CharSize);
if c>0 then
UTF8Str:=UTF8Str+CharSize
else
if c=0 then
Break
else
UTF8Str:=UTF8Str+Abs(c)+CharSize-1
end;

if UTF16Str<>nil then
UTF16Str:=#0;
Result:=i
end
else
Result:=0
end;

小工具:统计字符串中的字符总数
因为UTF-8和UTF-16都是不定长编码格式,所以在以它们为编码的字符串中,编码单元的数量并不一定等于字符数量,因此一个专门的统计字符串字符总数的算法是必不可少的。以下几个函数的原理十分简单,用于统计各种编码格式的字符串中的字符总数,可以很方便地使用在其他算法中,简化算法的设计。
注:三种Unicode编码格式里面,UTF-8字符串可以用传统的ANSI字符串来存储,UTF-16字符串可以用16位Wide字符串(各类现代编程语言都提供有16位的Unicode字符串数据类型,原理和处理方法大同小异)来存储,但因为现在还没有哪种操作系统是以UTF-32编码格式为Unicode内码实现方案的,所以相应的也就没有哪个编程语言或软件开发工具提供有32位的Unicode字符串数据类型了。不过根据Unicode标准的描述,既然计算机程序里面所称的“字符串”可以等价于标准原文所说的“(特定编码格式的)编码单元序列”,所以我在以下涉及UTF-32编码格式的算法里,统一使用双字(DWORD)数组来表示UTF-32编码单元序列。
编程:
// 计算UTF-16字符串中的字符数目
function CharCountOfUTF16Str(UTF16Str:pWideChar):integer;
stdcall;
var
i:integer;
begin
if UTF16Str<>nil then
begin
i:=0;
While UTF16Str^<>#0do
case TUTF16CUT(UTF16CodeUnitType(UTF16Str,1)) of
BMPCP:
begin
inc(i);
inc(UTF16Str)
end;
HighSurr:
begin
inc(i);
UTF16Str:=UTF16Str+2
end
else
inc(UTF16Str)
end;
Result:=i
end
else
Result:=0
end;

// 计算UTF-8字符串中的字符数目
function CharCountOfUTF8Str(UTF8Str:pChar):integer;
stdcall;
var
i,j,charsize:integer;
begin
if UTF8Str<>nil then
begin
i:=0;
While UTF8Str^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8Str,1,@j,@charsize);
if j>0 then
begin
inc(i);
UTF8Str:=UTF8Str+charsize
end
else
if j=0 then
Break
else
UTF8Str:=UTF8Str+Abs(j)+CharSize-1
end;
Result:=i
end
else
Result:=0
end;

// 计算UTF-32字符串中的字符数目
function CharCountOfUTF32Str(UTF32:pDWORD):integer;
stdcall;
var
i:integer;
begin
if UTF32<>nil then
begin
i:=0;
While UTF32^<>0do
begin
if (UTF32^>=0) and (UTF32^<HighSurrStart)
or
(UTF32^>LowSurrEnd) and (UTF32^<=MaxUnicodeValue)
then
inc(i);
inc(UTF32)
end;
Result:=i
end
else
Result:=0
end;

// UTF-16字符串转换为UTF-32字符串(编码单元序列)
function UTF16ToUTF32ForStr(UTF16Str:pWideChar;UTF32Str:pDWORD):integer;
stdcall;
var
tmpp:pDWORD;
UTF32Code:DWORD;
begin
if UTF16Str<>nil then
begin
if UTF32Str<>nil then
begin
tmpp:=UTF32Str;
While UTF16Str^<>#0do
begin
UTF32Code:=UTF16CUSToCP(UTF16Str,1);
if (UTF32Code>=0) and (UTF32Code<HighSurrStart)
or
(UTF32Code>LowSurrEnd) and (UTF32Code<=MaxUnicodeValue)
then
begin
UTF32Str^:=UTF32Code;
inc(UTF32Str);
if UTF32Code>MaxBMPCP then
UTF16Str:=UTF16Str+2
else
inc(UTF16Str)
end
else
inc(UTF16Str)
end;
UTF32Str^:=0;
Result:=(Integer(UTF32Str)-Integer(tmpp)) div SizeOf(DWORD)
end
else
Result:=CharCountOfUTF16Str(UTF16Str)+1 // 这里多加一个空结束符位置
end
else
Result:=0
end;

// UTF-32字符串(编码单元序列)转换为UTF-16字符串
function UTF32ToUTF16ForStr(UTF32Str:pDWORD;UTF16Str:pWideChar):integer;
stdcall;
var
i,c:integer;
begin
if UTF32Str<>nil then
begin
i:=0;
While UTF32Str^<>0do
begin
if (UTF32Str^>=0) and (UTF32Str^<HighSurrStart)
or
(UTF32Str^>LowSurrEnd) and (UTF32Str^<=MaxUnicodeValue)
then
begin
if UTF16Str<>nil then
c:=CPToUTF16CUS(UTF16Str+i,UTF32Str^)
else
c:=CPToUTF16CUS(nil,UTF32Str^);
if c>0 then
i:=i+c
end;

inc(UTF32Str)
end;

if UTF16Str<>nil then
UTF16Str:=#0;
Result:=i
end
else
Result:=0
end;

// UTF-8字符串转换为UTF-32字符串(编码单元序列)
function UTF8ToUTF32ForStr(UTF8Str:pChar;UTF32Str:pDWORD):integer;
stdcall;
var
tmpp:pDWORD;
UTF32Code:DWORD;
i,j:integer;
begin
if UTF8Str<>nil then
begin
if UTF32Str<>nil then
begin
tmpp:=UTF32Str;
While UTF8Str^<>#0do
begin
UTF32Code:=UTF8CUSToCP(UTF8Str,1);
if (UTF32Code>=0) and (UTF32Code<HighSurrStart)
or
(UTF32Code>LowSurrEnd) and (UTF32Code<=MaxUnicodeValue)
then
begin
UTF32Str^:=UTF32Code;
inc(UTF32Str);
UTF8CUIndexOfChar(UTF8Str,1,@i,@j);
UTF8Str:=UTF8Str+j
end
else
inc(UTF8Str)
end;
UTF32Str^:=0;
Result:=(Integer(UTF32Str)-Integer(tmpp)) div SizeOf(DWORD)
end
else
Result:=CharCountOfUTF8Str(UTF8Str)+1 // 这里多加一个空结束符位置
end
else
Result:=0
end;

// UTF-32字符串(编码单元序列)转换为UTF-8字符串
function UTF32ToUTF8ForStr(UTF32Str:pDWORD;UTF8Str:pChar):integer;
stdcall;
var
i,c:integer;
begin
if UTF32Str<>nil then
begin
i:=0;
While UTF32Str^<>0do
begin
if (UTF32Str^>=0) and (UTF32Str^<HighSurrStart)
or
(UTF32Str^>LowSurrEnd) and (UTF32Str^<=MaxUnicodeValue)
then
begin
if UTF8Str<>nil then
c:=CPToUTF8CUS(UTF8Str+i,UTF32Str^)
else
c:=CPToUTF8CUS(nil,UTF32Str^);
if c>0 then
i:=i+c
end;

inc(UTF32Str)
end;

if UTF8Str<>nil then
UTF8Str:=#0;
Result:=i
end
else
Result:=0
end;


Unicode编码机制
对于Unicode编码机制的应用,首先应该澄清的一点就是:编码格式和编码机制是两个不同的概念,但由于历史的原因,Unicode编码格式通常被认为是等同于Unicode(或UCS)转码格式(UTF)的。因此造成的结果是编码格式和编码机制这两个概念在使用上往往被混淆了。
编码机制和编码格式之间的不同之处在于前者处理的是编码字节序列,它用在以字节为单位处理二进制数据的场合(比如通信网络中的数据传输、文本内容在外存储器上的保存等);后者处理的是编码单元序列,它用在以特定存储长度的(内)存储单元为单位处理文本字符数据的场合(比如操作系统对Unicode字符集的内码实现方案、各种编程语言提供的Unicode字符串数据类型的实现方案等),根据不同的应用需要,各类编码格式的编码单元的存储长度并不相同,比如UTF-8编码格式使用8位编码单元、UTF-16编码格式使用16位编码单元、UTF-32编码格式使用32位编码单元。
虽然处理对象不同,但编码机制却是和编码格式息息相关的,讲编码机制的时候绝对离不开对编码格式的讨论,简单来说就是:Unicode编码机制是一种把特定Unicode编码格式的编码单元序列转换为相应编码格式的编码字节序列的方法,同时还包括一组处理字节顺序标志(BOM)的规则。
相反地,由于编码格式按编码单元来处理数据,而不是字节,所以它不需要理会字节顺序的问题。这样一来,编码格式在理解和处理上就显得比编码机制要简单得多――从编码格式去理解编码机制,并实现出编码格式到编码机制的转换是很容易的,在此基础上再去实现编码机制到编码格式的转换就只是一个顺延回溯的问题了。但如果反过来:先去理解编码机制,由于任何一种编码机制都是和特定编码格式相关的,在事先完全不知道什么是编码格式的情况下,难免陷入“两线作战”的境地。
另一方面,从抽象程度的角度而言,Unicode编码字符集的编码方法从高到低可以分为三个层次:编码点数字、编码格式和编码机制。抽象层次越高就越容易理解,比如编码点数字是最好理解的,套用一句大家最耳熟能详的话就是:为世界上每一个仍在使用的字符分配一个唯一的数字。这个“唯一数字”就是Unicode编码点数字,它从0开始顺序分配给每一个需要收录进Unicode字符集的字符,除了需要考虑实际应用中编码方法承受能力的限制(比如UTF-16编码格式对编码点取值范围的限制)之外,只要有字符需要编码,就会为它分配一个编码点。因此编码点的概念完全是面向语言文字应用中的“字”、“符号”等这些抽象概念的,这就有点像编程中的面向对象思维方式,最容易被人接受;而第二抽象层的编码格式就有点像编程中的面向过程思维方式,事实上几乎可以认为编码格式完全就是为计算机程序理解和处理Unicode文本字符数据而定义的,程序员只要按照其他任何一种基于简单数据类型元素的线性数据结构的方式来理解特定编码格式的编码单元序列,就可以很容易地理解Unicode字符串数据的基本原理和处理方法了;位于最低层的编码机制与编程中的面向机器思维方式如出一辙,完全从机器处理数据的角度考虑问题,把各种编码格式的Unicode文本数据转换为一个个的字节数据,此时各字节的数据值已经完全看不出“字符”、“编码”这样的含义,无非就是为了方便计算机或相关的硬件设备对它们的存取,因为计算机最基本的存取单位是字节,这一点“本性”无论是对于8位、16位、32位还是64位字长的计算机来说都不会变的。
正因为编码机制比起编码格式和编码点来说,都要更繁杂和难于理解,所以本文是先给出编码格式的处理算法,然后再给出编码机制的处理算法的。而后来的开发事实也说明,在具备了相关编码格式处理算法的基础上,编写编码机制处理算法是很容易的一件事情。而如果反过来的话,先实现编码机制处理算法,就会发现举步为艰,几乎每设计一个算法都要完全重新实现一些事实上属于基础公共处理部分的算法,而这些算法很多都是属于编码格式处理的。
因为不论是何种编码格式的编码机制,都表现为一个编码字节序列,所以本文给出的所有涉及编码机制处理的算法中,都是用ANSI字符串数据类型来存储任何一种编码格式的编码机制的。
在开始给出算法之前,先给出各算法中所用到的全局变量及相关的常量、类型的定义和值初始化。
const
// **** UTF-16编码单元类型(开始) ****
MaxBMPCP=$FFFF;
// BMP编码点最大取值
MaxUnicodeValue=$10FFFF;
// Unicode数字最大取值
HighSurrStart=$D800;
// 高位代理取值范围下限
HighSurrEnd=$DBFF;
// 高位代理取值范围上限
LowSurrStart=$DC00;
// 低位代理取值范围下限
LowSurrEnd=$DFFF;
// 低位代理取值范围上限
UTF16CUT_InvalCodeUnit=0;
// 无效编码单元
UTF16CUT_BMPCP=1;
// BMP编码点
UTF16CUT_HighSurr=2;
// 高位代理
UTF16CUT_LowSurr=3;
// 低位代理
// **** UTF-16编码单元类型(结束) ****
// **** UTF-8编码格式管理数据(开始) ****
CPPartCountOfUTF8=9;
// UTF-8编码格式对Unicode编码点的分段数量
MaxCodeUnitCountOfUTF8=4;
// 单个编码点所需的最大UTF-8编码单元数量
// **** UTF-8编码格式管理数据(结束) ****
// **** Unicode编码格式字节序列BOM标识常量(开始) ****
BOMType_Default=0;
// 默认字节序
BOMType_BE=1;
// 大尾字节序
BOMType_LE=2;
// 小尾字节序
// **** Unicode编码格式字节序列BOM标识常量(结束) ****
// **** BOM管理数据(开始) ****
BOMSizeOfUTF8=3;
// UTF-8 BOM 的长度
BOMSizeOfUTF16=2;
// UTF-16 BOM 的长度
BOMSizeOfUTF32=4;
// UTF-32 BOM 的长度
// **** BOM管理数据(结束) ****
type
TUTF16CUT=( // UTF-16编码单元类型
InvalCodeUnit, // 无效编码单元
BMPCP, // BMP编码点
HighSurr, // 高位代理
LowSurr // 低位代理
);
// UTF-8编码格式管理信息(开始) ****
// UTF-8编码格式对Unicode编码点的分段的具体编码区间类型
TCPPartOfUTF8CodeRange=
Record
MinCode,MaxCode:DWORD
end;

// UTF-8编码单元的取值范围类型
TCUValueRangeOfUTF8=
Record
MinValue,MaxValue:Byte
end;

// 各编码单元的取值范围类型
TCUValueRange=array [0..MaxCodeUnitCountOfUTF8-1] of TCUValueRangeOfUTF8;
// UTF-8编码格式对Unicode编码点的分段的信息类型
TCPPartOfUTF8Info=
Record
// 分段的编码点区间
CodeRange:TCPPartOfUTF8CodeRange;

CUValueRange:TCUValueRange // 各编码单元的取值范围
end;
// 指向UTF-8编码格式对Unicode编码点的分段的信息的指针类型
TPCPPartOfUTF8Info=^TCPPartOfUTF8Info;
// UTF-8编码格式管理信息(结束) ****
TBOM=( // BOM类型
BOMDefault, // 默认字节序
BOMBE, // 大尾字节序
BOMLE // 小尾字节序
);

var
// 无效UTF-8格式编码单元集合
InvalUTF8CUSet:set of Byte=[$C0..$C1,$F5..$FF];
// UTF-8 BOM
BOMOfUTF8:array [0..BOMSizeOfUTF8-1] of Byte=($EF,$BB,$BF);
// UTF-16 BOMBE
BOMBEOfUTF16:array [0..BOMSizeOfUTF16-1] of Byte=($FE,$FF);
// UTF-16 BOMLE
BOMLEOfUTF16:array [0..BOMSizeOfUTF16-1] of Byte=($FF,$FE);
// UTF-32 BOMBE
BOMBEOfUTF32:array [0..BOMSizeOfUTF32-1] of Byte=($00,$00,$FE,$FF);
// UTF-32 BOMLE
BOMLEOfUTF32:array [0..BOMSizeOfUTF32-1] of Byte=($FF,$FE,$00,$00);
UTF-8编码单元序列和UTF-8编码格式字节序列之间的转换
原理:本来,因为UTF-8编码格式使用8位编码单元的特性,UTF-8编码单元序列“天然”的就是字节序列。所以UTF-8编码单元序列和UTF-8编码格式字节序列之间是无所谓转不转换的。不过,既然在UTF-8编码单元/字节序列前面加上一个<EF BB BF>的BOM的话,更方便程序把它识别为一个UTF-8编码格式字节序列,所以以下两个算法就是在支持对UTF-8 BOM的识别的情况下,实现在UTF-8编码单元序列和UTF-8编码格式字节序列之间的转换工作。在整个转换过程中,算法会严格检验每一个字节上的值,只有在识别出一个有效的字符的情况下,才会把它转换到目标序列中去。
编程:
// 把UTF-8编码单元序列转换为带BOM的UTF-8编码格式字节序列
function CUSToBSForUTF8(UTF8_CUS,UTF8_BS:pChar):integer;
stdcall;
var
i,j,k,charsize:integer;
begin
if UTF8_CUS<>nil then
begin
if UTF8_BS<>nil then
for k:=0 to BOMSizeOfUTF8-1do
UTF8_BS[k]:=Chr(BOMOfUTF8[k]);
i:=1;
j:=BOMSizeOfUTF8;
While UTF8_CUS[i-1]<>#0do
begin
k:=UTF8CUIndexOfChar(UTF8_CUS,i,@k,@charsize);
if k>0 then
begin
if UTF8_BS<>nil then
for k:=1 to charsizedo
begin
UTF8_BS[j]:=UTF8_CUS[i-1];
inc(i);
inc(j)
end
else
begin
i:=i+charsize;
j:=j+charsize
end
end
else
if k=0 then
Break
else
i:=-1*k+charsize
end;

if j>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-8编码格式字节序列转换为UTF-8编码单元序列
function BSToCUSForUTF8(UTF8_BS,UTF8_CUS:pChar):integer;
stdcall;
var
i,j,charsize:integer;
begin
if UTF8_BS<>nil then
begin
i:=0;
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+3;
While UTF8_BS^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8_BS,1,@j,@charsize);
if j>0 then
begin
if UTF8_CUS<>nil then
for j:=1 to charsizedo
begin
UTF8_CUS:=UTF8_BS^;
inc(i);
inc(UTF8_BS)
end
else
begin
i:=i+charsize;
UTF8_BS:=UTF8_BS+charsize
end
end
else
if j=0 then
Break
else
UTF8_BS:=UTF8_BS+Abs(j)+charsize-1
end;

if i>0 then
begin
if UTF8_CUS<>nil then
UTF8_CUS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

UTF-16编码单元序列和UTF-16编码格式字节序列之间的转换
原理:以下两个算法在支持对UTF-16 BOM的识别的情况下,实现在UTF-16编码单元序列和UTF-16编码格式字节序列之间的转换工作。在整个转换过程中,算法会严格检验每一个编码单元/字节上的值,只有在识别出一个有效的字符的情况下,才会把它转换到目标序列中去。注:按照Unicode标准的规定,当BOM缺省时,一律按大尾(BE)字节序来处理。
编程:
// 把UTF-16编码单元序列转换为带BOM的UTF-16编码格式字节序列
function CUSToBSForUTF16(UTF16_CUS:pWideChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j,k,CodeUnitCount:integer;
BOM:TBOM;
begin
if UTF16_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if UTF16_BS<>nil then
for k:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMLE:
UTF16_BS[k]:=Chr(BOMLEOfUTF16[k]);
else
UTF16_BS[k]:=Chr(BOMBEOfUTF16[k])
end;
i:=1;
j:=BOMSizeOfUTF16;
While UTF16_CUS[i-1]<>#0do
begin
case TUTF16CUT(UTF16CodeUnitType(UTF16_CUS,i)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;

if UTF16_BS<>nil then
for k:=1 to CodeUnitCountdo
begin
case BOM of
BOMLE:
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS[i+k-2]));
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS[i+k-2]) shr 8)
end
else
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS[i+k-2]) shr 8);
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS[i+k-2]))
end
end;
j:=j+2
end
else
j:=j+CodeUnitCount*2;
i:=i+CodeUnitCount
end;

if j>BOMSizeOfUTF16 then
begin
if UTF16_BS<>nil then
UTF16_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-16编码格式字节序列转换为UTF-16编码单元序列
function BSToCUSForUTF16(UTF16_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
label 10;
var
i,j,k,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
k:=0;
While (k<BOMSizeOfUTF16) and (UTF16_BS[k]=Chr(BOMBEOfUTF16[k]))do
inc(k);
if k>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
k:=0;
While (k<BOMSizeOfUTF16) and (UTF16_BS[k]=Chr(BOMLEOfUTF16[k]))do
inc(k);
if k>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF16+1;
j:=0;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
10:
if UTF16_CUS<>nil then
for k:=1 to CodeUnitCountdo
begin
UTF16_CUS[j]:=CP[k-1];
inc(j)
end
else
j:=j+CodeUnitCount;
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>0 then
begin
if UTF16_CUS<>nil then
UTF16_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-32编码单元序列和UTF-32编码格式字节序列之间的转换
原理:以下两个算法在支持对UTF-32 BOM的识别的情况下,实现在UTF-32编码单元序列和UTF-32编码格式字节序列之间的转换工作。在整个转换过程中,算法会严格检验每一个编码单元/字节上的值,只有在识别出一个有效的字符的情况下,才会把它转换到目标序列中去。注:按照Unicode标准的规定,当BOM缺省时,一律按大尾(BE)字节序来处理。
编程:
// 把UTF-32编码单元序列转换为带BOM的UTF-32编码格式字节序列
function CUSToBSForUTF32(UTF32_CUS:pDWORD;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
j,k,CodeUnitCount:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if UTF32_BS<>nil then
for k:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMLE:
UTF32_BS[k]:=Chr(BOMLEOfUTF32[k]);
else
UTF32_BS[k]:=Chr(BOMBEOfUTF32[k])
end;
j:=BOMSizeOfUTF32;
While UTF32_CUS^<>0do
begin
CP:=UTF32_CUS^;
if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
if UTF32_BS<>nil then
case BOM of
BOMLE:
for k:=0 to 3do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
else
for k:=3do
wnto 0do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
end
else
j:=j+4;
inc(UTF32_CUS)
end;

if j>BOMSizeOfUTF32 then
begin
if UTF32_BS<>nil then
UTF32_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-32编码格式字节序列转换为UTF-32编码单元序列
function BSToCUSForUTF32(UTF32_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
var
i,k,CodeUnitCount:integer;
BOM:TBOM;
CP:DWORD;
tmpp:pDWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
k:=0;
While (k<BOMSizeOfUTF32) and (UTF32_BS[k]=Chr(BOMBEOfUTF32[k]))do
inc(k);
if k>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
k:=0;
While (k<BOMSizeOfUTF32) and (UTF32_BS[k]=Chr(BOMLEOfUTF32[k]))do
inc(k);
if k>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF32+1;
tmpp:=UTF32_CUS;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
if UTF32_CUS<>nil then
tmpp^:=CP;
inc(tmpp)
end;

i:=i+4
end;

if tmpp<>UTF32_CUS then
begin
if UTF32_CUS<>nil then
begin
tmpp^:=0;
Result:=(Integer(tmpp)-Integer(UTF32_CUS)) div SizeOf(DWORD)
end
else
Result:=(Integer(tmpp)-Integer(UTF32_CUS)) div SizeOf(DWORD) + 1
end
else
Result:=0
end
else
Result:=0
end;

UTF-8编码格式字节序列转换为UTF-16编码格式字节序列
原理:本来,从简化算法设计的角度考虑,做UTF-8编码格式字节序列转换为UTF-16编码格式字节序列的函数时,应该考虑依次调用BSToCUSForUTF8、UTF8ToUTF16ForStr、CUSToBSForUTF16几个现有的函数,按照“UTF-8编码格式字节序列”->“UTF-8编码单元序列”->“UTF-16编码单元序列”->“UTF-16编码格式字节序列”这样的顺序来辗转实现的。可是这样一来,虽然编程上倒是简单不少,但是由于所需的中转过程过多,而且临时存储开销太大,实际中不太可能采用。
于是,我对算法进行了全新的设计,借助UTF-8编码格式字节序列(除了前面的BOM头之外)实际上完全等价于UTF-8编码单元序列的特点,直接就在UTF-8编码格式字节序列数据的基础上依次读出每个有效字符,然后把它转换为UTF-16编码单元序列,最后再把UTF-16编码单元序列转换为UTF-16编码格式字节序列。这样一来就把所需的中间转换过程减少到了一个,并且这个中转过程所需的临时存储开销只有一个字符的UTF-16编码单元序列所需的存储空间而已,不像原来的那个方法那样需要为整个字符串的每个字符都分配一个临时的转存开销。因此新算法无论是从时间和空间的消耗上来说都是比较合理的,并且也充分利用现有的其它函数快速地实现。
编程:
// UTF8编码格式字节序列转换为UTF16编码格式字节序列
function UTF8ToUTF16ForBS(UTF8_BS:pChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j,charsize,CodeUnitCount:integer;
BOM:TBOM;
UTF16_CUS:array [0..2] of WideChar;
begin
if UTF8_BS<>nil then
begin

BOM:=TBOM(BOMType);
if UTF16_BS<>nil then
for i:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMLE:
UTF16_BS:=Chr(BOMLEOfUTF16);
else
UTF16_BS:=Chr(BOMBEOfUTF16)
end;
j:=BOMSizeOfUTF16;
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
While UTF8_BS^<>#0do
begin
i:=UTF8CUIndexOfChar(UTF8_BS,1,@i,@charsize);
if i>0 then
begin
CodeUnitCount:=UTF8ToUTF16ForChar(UTF8_BS,1,UTF16_CUS);
if UTF16_BS<>nil then
for i:=0 to CodeUnitCount-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS));
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS) shr 8)
end
else
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS) shr 8);
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS))
end
end;
j:=j+2
end
else
j:=j+CodeUnitCount*2;
UTF8_BS:=UTF8_BS+charsize
end
else
if i=0 then
Break
else
UTF8_BS:=UTF8_BS+(-1*i)+charsize-1
end;

if j>BOMSizeOfUTF16 then
begin
if UTF16_BS<>nil then
UTF16_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-8编码格式字节序列转换为UTF-32编码格式字节序列
原理:这个函数的算法原理和上面那个差不多,都是借助UTF-8编码格式字节序列中除了前面的BOM头之外,其他部分实际上完全等价于UTF-8编码单元序列的特点。直接将UTF-8编码单元序列转换为Unicode编码点数字,然后又借助UTF-32编码单元值等于编码点数字值的特点,马上就可以根据编码点数字转换出UTF-32编码格式字节序列了。
编程:
// UTF-8编码格式字节序列转换为UTF-32编码格式字节序列
function UTF8ToUTF32ForBS(UTF8_BS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j,k,charsize:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF8_BS<>nil then
begin
BOM:=TBOM(BOMType);
if UTF32_BS<>nil then
for i:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMLE:
UTF32_BS:=Chr(BOMLEOfUTF32);
else
UTF32_BS:=Chr(BOMBEOfUTF32)
end;
j:=BOMSizeOfUTF32;
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
While UTF8_BS^<>#0do
begin
i:=UTF8CUIndexOfChar(UTF8_BS,1,@i,@charsize);
if i>0 then
begin
CP:=UTF8CUSToCP(UTF8_BS,1);
if UTF32_BS<>nil then
case BOM of
BOMLE:
for k:=0 to 3do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
else
for k:=3do
wnto 0do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
end
else
j:=j+4;
UTF8_BS:=UTF8_BS+charsize
end
else
if i=0 then
Break
else
UTF8_BS:=UTF8_BS+(-1*i)+charsize-1
end;

if j>BOMSizeOfUTF32 then
begin
if UTF32_BS<>nil then
UTF32_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-16编码格式字节序列转为UTF-8编码格式字节序列
原理:从UTF-16编码格式字节序列中依次读出每个有效的UTF-16编码格式字符,然后把它转换为UTF-8编码单元序列(等价于UTF-8编码格式字节序列)就行了。
编程:
// UTF-16编码格式字节序列转为UTF-8编码格式字节序列
function UTF16ToUTF8ForBS(UTF16_BS:pChar;Count:integer;UTF8_BS:pChar):integer;
stdcall;
label 10;
var
i,j,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if UTF8_BS<>nil then
for i:=0 to BOMSizeOfUTF8-1do
UTF8_BS:=Chr(BOMOfUTF8);
j:=BOMSizeOfUTF8;
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMLEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF16+1;

While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
10:
if UTF8_BS<>nil then
j:=j+UTF16ToUTF8ForChar(CP,1,UTF8_BS+j)
else
j:=j+UTF16ToUTF8ForChar(CP,1,nil);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-16编码格式字节序列转换为UTF-32编码格式字节序列
原理:从UTF-16编码格式字节序列中依次读出每个有效的UTF-16编码格式字符,然后把它转换为Unicode编码点数字(其值等于UTF-32编码单元值)就行了,最后再把UTF-32编码单元转换成UTF-32编码格式字节序列就行了。
编程:
// UTF-16编码格式字节序列转换为UTF-32编码格式字节序列
function UTF16ToUTF32ForBS(UTF16_BS:pChar;Count,BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
label 10;
var
i,j,k,CodeUnitCount:integer;
BOM,BOM1:TBOM;
CP:array [0..1] of WideChar;
CPValue:DWORD;
begin
if UTF16_BS<>nil then
begin
BOM1:=TBOM(BOMType);
if UTF32_BS<>nil then
for i:=0 to BOMSizeOfUTF32-1do
case BOM1 of
BOMLE:
UTF32_BS:=Chr(BOMLEOfUTF32);
else
UTF32_BS:=Chr(BOMBEOfUTF32)
end;
j:=BOMSizeOfUTF32;
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMLEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF16+1;

While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
CPValue:=UTF16CUSToCP(CP,1);
if (CPValue>=0) and (CPValue<=MaxBMPCP) then
CodeUnitCount:=1
else
if CPValue<=MaxUnicodeValue then
CodeUnitCount:=2
else
begin
inc(i);
Continue
end;
if UTF32_BS<>nil then
case BOM1 of
BOMLE:
for k:=0 to 3do
begin
UTF32_BS[j]:=Chr(CPValue shr (8*k));
inc(j)
end
else
for k:=3do
wnto 0do
begin
UTF32_BS[j]:=Chr(CPValue shr (8*k));
inc(j)
end
end
else
j:=j+4;
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>BOMSizeOfUTF32 then
begin
if UTF32_BS<>nil then
UTF32_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-32编码格式字节序列转UTF-8编码格式字节序列
原理:这个算法很简单,先把UTF-32编码格式字节序列中的字符逐个转换为Unicode编码点数字,然后利用UTF-8编码单元序列等价于UTF-8编码格式字节序列(除了前面的BOM头之外)的特点,通过CPToUTF8CUS函数把编码点转换为UTF-8编码格式字节序列。
编程:
// UTF-32编码格式字节序列转UTF-8编码格式字节序列
function UTF32ToUTF8ForBS(UTF32_BS:pChar;Count:integer;UTF8_BS:pChar):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
k:=0;
While (k<BOMSizeOfUTF32) and (UTF32_BS[k]=Chr(BOMBEOfUTF32[k]))do
inc(k);
if k>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
k:=0;
While (k<BOMSizeOfUTF32) and (UTF32_BS[k]=Chr(BOMLEOfUTF32[k]))do
inc(k);
if k>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF32+1;
if UTF8_BS<>nil then
for k:=0 to BOMSizeOfUTF8-1do
UTF8_BS[k]:=Chr(BOMOfUTF8[k]);
j:=BOMSizeOfUTF8;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
if UTF8_BS<>nil then
j:=j+CPToUTF8CUS(UTF8_BS+j,CP)
else
j:=j+CPToUTF8CUS(nil,CP);
i:=i+4
end;

if j>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-32编码格式字节序列转UTF-16编码格式字节序列
原理:先把UTF-32编码格式字节序列中的字符逐个转换为Unicode编码点数字,然后把编码点转换为UTF-16编码单元序列,最后再把UTF-16编码单元序列转换为UTF-16编码格式字节序列。
编程:
// UTF-32编码格式字节序列转UTF-16编码格式字节序列
function UTF32ToUTF16ForBS(UTF32_BS:pChar;Count,BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j,k:integer;
BOM,BOM1:TBOM;
CP:DWORD;
CUS:array [0..2] of WideChar;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
k:=0;
While (k<BOMSizeOfUTF32) and (UTF32_BS[k]=Chr(BOMBEOfUTF32[k]))do
inc(k);
if k>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
k:=0;
While (k<BOMSizeOfUTF32) and (UTF32_BS[k]=Chr(BOMLEOfUTF32[k]))do
inc(k);
if k>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF32+1;
BOM1:=TBOM(BOMType);
if UTF16_BS<>nil then
for k:=0 to BOMSizeOfUTF16-1do
case BOM1 of
BOMLE:
UTF16_BS[k]:=Chr(BOMLEOfUTF16[k]);
else
UTF16_BS[k]:=Chr(BOMBEOfUTF16[k])
end;
j:=BOMSizeOfUTF16;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
CPToUTF16CUS(CUS,CP);
case TUTF16CUT(UTF16CodeUnitType(CUS,1)) of
BMPCP:
k:=1;
HighSurr:
k:=2
else
begin
inc(i);
Continue
end
end;

if UTF16_BS<>nil then
for k:=0 to k-1do
begin
case BOM1 of
BOMLE:
begin
UTF16_BS[j]:=Chr(Ord(CUS[k]));
UTF16_BS[j+1]:=Chr(Ord(CUS[k]) shr 8)
end
else
begin
UTF16_BS[j]:=Chr(Ord(CUS[k]) shr 8);
UTF16_BS[j+1]:=Chr(Ord(CUS[k]))
end
end;
j:=j+2
end
else
j:=j+k*2
end;

i:=i+4
end;

if j>BOMSizeOfUTF16 then
begin
if UTF16_BS<>nil then
UTF16_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-8编码单元序列转UTF-16编码格式字节序列
原理:从UTF-8编码单元序列中依次读出每个有效字符,把它们转换为Unicode编码点数字,然后把编码点转换为UTF-16编码单元序列,最后再把UTF-16编码单元序列转换为UTF-16编码格式字节序列。
编程:
// UTF-8编码单元序列转UTF-16编码格式字节序列
function UTF8CUSToUTF16BS(UTF8_CUS:pChar;BOMType:
integer;UTF16_BS:pChar):integer;
stdcall;
var
i,j,k,charsize:integer;
BOM:TBOM;
UTF16_CUS:array [0..2] of WideChar;
begin
if UTF8_CUS<>nil then
begin
i:=1;

BOM:=TBOM(BOMType);
if UTF16_BS<>nil then
for k:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMLE:
UTF16_BS[k]:=Chr(BOMLEOfUTF16[k]);
else
UTF16_BS[k]:=Chr(BOMBEOfUTF16[k])
end;
j:=BOMSizeOfUTF16;
While UTF8_CUS[i-1]<>#0do
begin
k:=UTF8CUIndexOfChar(UTF8_CUS,i,@k,@charsize);
if k>0 then
begin
if UTF16_BS<>nil then
for k:=0 to CPToUTF16CUS(UTF16_CUS,UTF8CUSToCP(UTF8_CUS,i))-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS[k]));
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS[k]) shr 8)
end
else
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS[k]) shr 8);
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS[k]))
end
end;
j:=j+2
end
else
if charsize<4 then
j:=j+2
else
j:=j+4;
i:=i+charsize
end
else
if k=0 then
Break
else
i:=-1*k+charsize
end;

if j>BOMSizeOfUTF16 then
begin
if UTF16_BS<>nil then
UTF16_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-8编码单元序列转UTF-32编码格式字节序列
原理:从UTF-8编码单元序列中依次读出每个有效字符,把它们转换为Unicode编码点数字,然后把编码点转换成UTF-32编码格式字节序列。
编程:
// UTF-8编码单元序列转UTF-32编码格式字节序列
function UTF8CUSToUTF32BS(UTF8_CUS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j,k,charsize:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF8_CUS<>nil then
begin
i:=1;

BOM:=TBOM(BOMType);
if UTF32_BS<>nil then
for k:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMLE:
UTF32_BS[k]:=Chr(BOMLEOfUTF32[k]);
else
UTF32_BS[k]:=Chr(BOMBEOfUTF32[k])
end;
j:=BOMSizeOfUTF32;
While UTF8_CUS[i-1]<>#0do
begin
k:=UTF8CUIndexOfChar(UTF8_CUS,i,@k,@charsize);
if k>0 then
begin
if UTF32_BS<>nil then
begin
CP:=UTF8CUSToCP(UTF8_CUS,i);
case BOM of
BOMLE:
for k:=0 to 3do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
else
for k:=3do
wnto 0do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
end
end
else
j:=j+4;
i:=i+charsize
end
else
if k=0 then
Break
else
i:=-1*k+charsize
end;

if j>BOMSizeOfUTF32 then
begin
if UTF32_BS<>nil then
UTF32_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-16编码单元序列转UTF-8编码格式字节序列
原理:用UTF16ToUTF8ForStr函数直接把UTF-16编码单元序列转换成UTF-8编码单元序列,然后再在UTF-8编码单元序列的前面加上UTF-8编码格式字节序列的BOM就OK了。
编程:
// UTF-16编码单元序列转UTF-8编码格式字节序列
function UTF16CUSToUTF8BS(UTF16_CUS:pWideChar;UTF8_BS:pChar):integer;
stdcall;
var
i:integer;
begin
if UTF16_CUS<>nil then
begin
if UTF8_BS<>nil then
begin
for i:=0 to BOMSizeOfUTF8-1do
UTF8_BS:=Chr(BOMOfUTF8);

i:=UTF16ToUTF8ForStr(UTF16_CUS,UTF8_BS+BOMSizeOfUTF8)
end
else
i:=UTF16ToUTF8ForStr(UTF16_CUS,nil);
if i>0 then
begin
if UTF8_BS<>nil then
UTF8_BS[BOMSizeOfUTF8+i]:=#0;
Result:=BOMSizeOfUTF8+i
end
else
Result:=0
end
else
Result:=0
end;

UTF-16编码单元序列转UTF-32编码格式字节序列
原理:从UTF-16编码单元序列中依次读出每个有效字符,把它们转换成Unicode编码点数字,然后再把编码点转换成UTF-32编码格式字节序列。
编程:
// UTF-16编码单元序列转UTF-32编码格式字节序列
function UTF16CUSToUTF32BS(UTF16_CUS:pWideChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j:integer;
UTF32Code:DWORD;
BOM:TBOM;
begin
if UTF16_CUS<>nil then
begin
if UTF32_BS<>nil then
begin
BOM:=TBOM(BOMType);
for i:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMLE:
UTF32_BS:=Chr(BOMLEOfUTF32);
else
UTF32_BS:=Chr(BOMBEOfUTF32)
end;
i:=BOMSizeOfUTF32;
While UTF16_CUS^<>#0do
begin
UTF32Code:=UTF16CUSToCP(UTF16_CUS,1);
if UTF32Code<=MaxUnicodeValue then
case BOM of
BOMLE:
for j:=0 to 3do
begin
UTF32_BS:=Chr(UTF32Code shr (8*j));
inc(i)
end
else
for j:=3do
wnto 0do
begin
UTF32_BS:=Chr(UTF32Code shr (8*j));
inc(i)
end
end
else
i:=i+4;
if UTF32Code>MaxBMPCP then
UTF16_CUS:=UTF16_CUS+2
else
inc(UTF16_CUS)
end;

if i>BOMSizeOfUTF32 then
begin
UTF32_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=BOMSizeOfUTF32+CharCountOfUTF16Str(UTF16_CUS)*4
end
else
Result:=0
end;

UTF-32编码单元序列转UTF-8编码格式字节序列
原理:从UTF-32编码单元序列中依次读出每个有效Unicode编码点数字,把它转换为UTF-8编码单元序列,而UTF-8编码单元序列等价于UTF-8编码格式字节序列。
编程:
// UTF-32编码单元序列转UTF-8编码格式字节序列
function UTF32CUSToUTF8BS(UTF32_CUS:pDWORD;UTF8_BS:pChar):integer;
stdcall;
var
i:integer;
CP:DWORD;
begin
if UTF32_CUS<>nil then
begin
if UTF8_BS<>nil then
for i:=0 to BOMSizeOfUTF8-1do
UTF8_BS:=Chr(BOMOfUTF8);
i:=BOMSizeOfUTF8;
While UTF32_CUS^<>0do
begin
CP:=UTF32_CUS^;
if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
if UTF8_BS<>nil then
i:=i+CPToUTF8CUS(UTF8_BS+i,CP)
else
i:=i+CPToUTF8CUS(nil,CP);
inc(UTF32_CUS)
end;

if i>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

UTF-32编码单元序列转UTF-16编码格式字节序列
原理:从UTF-32编码单元序列中依次读出每个有效Unicode编码点数字,把它转换为UTF-16编码单元序列,然后再把UTF-16编码单元序列转换为UTF-16编码格式字节序列。
编程:
// UTF-32编码单元序列转UTF-16编码格式字节序列
function UTF32CUSToUTF16BS(UTF32_CUS:pDWORD;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j:integer;
BOM:TBOM;
CP:DWORD;
UTF16_CUS:array [0..2] of WideChar;
begin
if UTF32_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if UTF16_BS<>nil then
for i:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMLE:
UTF16_BS:=Chr(BOMLEOfUTF16);
else
UTF16_BS:=Chr(BOMBEOfUTF16)
end;
i:=BOMSizeOfUTF16;
While UTF32_CUS^<>0do
begin
CP:=UTF32_CUS^;
if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
if CP>MaxBMPCP then
j:=2
else
j:=1;
if UTF16_BS<>nil then
begin
CPToUTF16CUS(UTF16_CUS,CP);
for j:=0 to j-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]));
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]) shr 8)
end
else
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]) shr 8);
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]))
end
end;
i:=i+2
end
end
else
i:=i+j*2
end;

inc(UTF32_CUS)
end;

if i>BOMSizeOfUTF16 then
begin
if UTF16_BS<>nil then
UTF16_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

UTF-8编码格式字节序列转UTF-16编码单元序列
原理:实际上就是把UTF-8编码格式序列去除BOM头(如果有的话),然后把剩下的部分用UTF8ToUTF16ForStr函数转换为UTF-16编码单元序列即可。
编程:
// UTF-8编码格式字节序列转UTF-16编码单元序列
function UTF8BSToUTF16CUS(UTF8_BS:pChar;UTF16_CUS:pWideChar):integer;
stdcall;
begin
if UTF8_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
Result:=UTF8ToUTF16ForStr(UTF8_BS,UTF16_CUS)
end
else
Result:=0
end;

UTF-8编码格式字节序列转UTF-32编码单元序列
原理:实际上就是把UTF-8编码格式序列去除BOM头(如果有的话),然后把剩下的部分用UTF8ToUTF32ForStr函数转换为UTF-32编码单元序列即可。
编程:
// UTF-8编码格式字节序列转UTF-32编码单元序列
function UTF8BSToUTF32CUS(UTF8_BS:pChar;UTF32_CUS:pDWORD):integer;
stdcall;
begin
if UTF8_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
Result:=UTF8ToUTF32ForStr(UTF8_BS,UTF32_CUS)
end
else
Result:=0
end;

UTF-16编码格式字节序列转UTF-8编码单元序列
原理:依次从UTF-16编码格式字节序列中读出每个有效字符,把它转换为UTF-16编码单元序列,然后把UTF-16编码单元序列转换为UTF-8编码单元序列。
编程:
// UTF-16编码格式字节序列转UTF-8编码单元序列
function UTF16BSToUTF8CUS(UTF16_BS:pChar;Count:integer;UTF8_CUS:pChar):integer;
stdcall;
label 10;
var
i,j,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMLEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF16+1;
j:=0;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
if UTF8_CUS<>nil then
j:=j+UTF16ToUTF8ForChar(CP,1,UTF8_CUS+j)
else
j:=j+UTF16ToUTF8ForChar(CP,1,nil);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>0 then
begin
if UTF8_CUS<>nil then
UTF8_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-16编码格式字节序列转UTF-32编码单元序列
原理:依次从UTF-16编码格式字节序列中读出每个有效字符,把它转换为UTF-16编码单元序列,然后把UTF-16编码单元序列转换为UTF-32编码单元序列。
编程:
// UTF-16编码格式字节序列转UTF-32编码单元序列
function UTF16BSToUTF32CUS(UTF16_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
label 10;
var
i,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
tempp:pDWORD;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMLEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF16+1;
tempp:=UTF32_CUS;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
if UTF32_CUS<>nil then
tempp^:=UTF16CUSToCP(CP,1);
inc(tempp);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if tempp<>UTF32_CUS then
begin
if UTF32_CUS<>nil then
begin
tempp^:=0;
Result:=(Integer(tempp)-Integer(UTF32_CUS)) div SizeOf(DWORD)
end
else
Result:=(Integer(tempp)-Integer(UTF32_CUS)) div SizeOf(DWORD) + 1
end
else
Result:=0
end
else
Result:=0
end;

UTF-32编码格式字节序列转UTF-8编码单元序列
原理:从UTF-32编码格式字节序列中依次读出每个有效字符,把它转换为Unicode编码点数字,然后把编码点转换为UTF-8编码单元序列。
编程:
// UTF-32编码格式字节序列转UTF-8编码单元序列
function UTF32BSToUTF8CUS(UTF32_BS:pChar;Count:integer;UTF8_CUS:pChar):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMLEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF32+1;
j:=0;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if UTF8_CUS<>nil then
j:=j+CPToUTF8CUS(UTF8_CUS+j,CP)
else
j:=j+CPToUTF8CUS(nil,CP);
i:=i+4
end;

if j>0 then
begin
if UTF8_CUS<>nil then
UTF8_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

UTF-32编码格式字节序列转UTF-16编码单元序列
原理:从UTF-32编码格式字节序列中依次读出每个有效字符,把它转换为Unicode编码点数字,然后把编码点转换为UTF-16编码单元序列。
编程:
// UTF-32编码格式字节序列转UTF-16编码单元序列
function UTF32BSToUTF16CUS(UTF32_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMLEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM=BOMDefault then
i:=1
else
i:=BOMSizeOfUTF32+1;
j:=0;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if UTF16_CUS<>nil then
j:=j+CPToUTF16CUS(UTF16_CUS+j,CP)
else
j:=j+CPToUTF16CUS(nil,CP);
i:=i+4
end;

if j>0 then
begin
if UTF16_CUS<>nil then
UTF16_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;


判断给定的字节序列所使用的Unicode编码机制
这个功能很常见,比如对于一个文本文件,怎么知道它是UTF-16还是UTF-8编码机制的?如果不知道编码胡乱打开,就很容易出现“乱码”。乱码可不只是ASNI文本才有的“专利”,Unicode文本处理不当也同样可能会出现乱码,因为Unicode的编码机制有七种之多。只有具体知道了所使用的编码机制,才能正确读出文本内容。
按照Unicode标准的建议,应用程序在输出一个特定编码格式的字节序列的时候,应该在序列的头部给出BOM标记,这样另一个读取该字节序列的程序就可以根据BOM判断出这个字节序列所使用的Unicode编码机制了。又或者,输出字节序列的程序可以不给出BOM,但它可以通过其他的方式“告诉”要读出这个字节序列的程序所使用的编码机制。但在现实的环境中,更多地可能出现这样一种情况:应用程序读取到的字节序列没有任何的BOM标记,也没有任何其他的编码机制提示信息。此时,如果想尽可能正确地读出文本内容的话,就只有靠“猜”了――也就是根据各种Unicode编码机制的规则,依次读出字节序列中的每个字节,看看这些字节比较“符合”哪种编码机制的编码规则――那它就极有可能是这种编码机制的文本了。当然,“猜测”结果不可能保证百分之百准确,但这也是没有办法的事,毕竟如果源文本没有按规定给出BOM标记的话,责任在输出程序一方。而输入程序则只管按标准规定的方法读出文本内容就好了,如果源文本的编码规律超出了Unicode标准处理方法可以承受的极限的话,则可以判定该文本使用了无效的Unicode编码机制,没有必要继续再按Unicode的方式来处理了。
另外,按照Unicode标准的规定:当未知编码格式字节序列中缺少BOM标记时,如果决定按UTF-16或UTF-32编码机制读取的话,则一律按大尾字节序的规则来处理每一个读出的字节,不用考虑小尾字节序的情况了。因此,虽然Unicode编码机制有七种之多,但在靠“猜”的情况下,却没有必要尝试完所有的每种编码机制,而只需要尝试UTF-8、UTF-16BE、UTF-16LE、UTF-32BE、UTF-32LE这五种就可以了。
那么,具体怎么“猜”呢?本算法库采用的是一种我称之为“有效字节数百分比评定准则”的方法。以UTF-8编码机制为例:首先给出要判断其编码机制的字节序列(S)、总共要在序列中读取的字节总数(C,可以小于序列的实际长度)和当判定成功时,符合UTF-8编码机制规则的字节占全部已读到的字节的百分比(P)。从S的第一个字节开始,读出S的每一个(或多个)字节,如果每次读到的子字节序列代表一个有效的Unicode编码点数字,则把本次读出的字节数量累加到“符合UTF-8编码机制的字节数”中去,然后再继续读取下一个子字节序列,重复上述判断操作……直到已读取字节总数大于等于C为止。最后计算“符合UTF-8编码机制的字节数”对于C的百分比,如果这个百分比大于等于P,则表示S中符合UTF-8编码机制规则的编码字节数在序列中所占的百分比达到了规定的最低比例,可以判定S是UTF-8编码格式字节序列了。至于UTF-16BE、UTF-16LE、UTF-32BE、UTF-32LE其它四种编码机制的猜测原则也是一样的。
以上是算法原理分析,实际的算法是由以下四个函数实现的――
先给出相关的常量和类型定义:
const
// **** Unicode编码机制类型标识常量(开始) ****
BSType_Unknow=0;
// 未知类型字节序列
BSType_UTF8=1;
// UTF-8编码格式字节序列
BSType_UTF16=2;
// UTF-16编码格式字节序列
BSType_UTF32=3;
// UTF-32编码格式字节序列
// **** Unicode编码机制类型标识常量(结束) ****
type
TBSType=( // 编码机制类型
BS_Unknow, // 未知类型字节序列
BS_UTF8, // UTF-8编码格式字节序列
BS_UTF16, // UTF-16编码格式字节序列
BS_UTF32 // UTF-32编码格式字节序列
);

好,下面是程序:
// 在一个未知编码格式的字节序列中按照UTF-8编码机制的规则,计算出全部
// 有效字符的字节序列总长度。
function GuessUTF8BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
var
i,j,k,charsize:integer;
begin
if (InputBS<>nil) and (Count<>nil) then
begin
if UTF8CUSToCP(InputBS,1)=$FEFF then
i:=BOMSizeOfUTF8
else
i:=1;
j:=i;

While i<=Count^do
begin
k:=UTF8CUIndexOfChar(InputBS,i,@k,@charsize);
if k>0 then
begin
j:=j+charsize;
i:=i+charsize
end
else
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end;

Count^:=i-1;
Result:=j-1
end
else
Result:=0
end;

// 在一个未知编码格式的字节序列中按照UTF-16编码机制的规则,计算出全部
// 有效字符的字节序列总长度。
function GuessUTF16BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
label 10;
var
i,j,charsize:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if (InputBS<>nil) and (Count<>nil) then
begin
if Count^>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (InputBS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(InputBS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
begin
i:=BOMSizeOfUTF16+1;
j:=i
end
else
begin
i:=1;
j:=0
end;

While i<=Count^do
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(InputBS) shl 8 + Ord(InputBS[i-1]));
if i<Count^-2 then
CP[1]:=WideChar(Ord(InputBS[i+2]) shl 8 + Ord(InputBS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(InputBS[i-1]) shl 8 + Ord(InputBS));
if i<Count^-2 then
CP[1]:=WideChar(Ord(InputBS[i+1]) shl 8 + Ord(InputBS[i+2]))
else
CP[1]:=#0
end
end;
10:
if CP[0]<>#0 then
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
begin
charsize:=1;
j:=j+2;
i:=i+2
end;
HighSurr:
begin
charsize:=2;
j:=j+4;
i:=i+4
end
else
begin
inc(i);
Continue
end
end
else
Break;
if (charsize=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count^-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(InputBS[i+2]) shl 8 + Ord(InputBS[i+1]))
else
CP[1]:=WideChar(Ord(InputBS[i+1]) shl 8 + Ord(InputBS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

Count^:=i-1;
if BOM<>BOMDefault then
Result:=j-1
else
Result:=j
end
else
Result:=0
end;

// 在一个未知编码格式的字节序列中按照UTF-32编码机制的规则,计算出全部
// 有效字符的字节序列总长度。
function GuessUTF32BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if (InputBS<>nil) and (Count<>nil) then
begin
if Count^>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (InputBS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(InputBS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
begin
i:=BOMSizeOfUTF32+1;
j:=i
end
else
begin
i:=1;
j:=0
end;

While i<=Count^-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(InputBS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(InputBS[k])
end
else
begin
CP:=Ord(InputBS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(InputBS[k])
end
end;

if (CP>0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
j:=j+4;
i:=i+4
end
else
inc(i)
end;

Count^:=i-1;
if BOM<>BOMDefault then
Result:=j-1
else
Result:=j
end
else
Result:=0
end;

// “猜测”一个未知编码格式字节序列所使用的Unicode编码机制
function GuessBSType(InputBS:pChar;Count:pInteger;
GuessSuccPercent:integer):integer;
stdcall;
var
i,j:integer;
SuccPercent:real;
BSType:TBSType;
begin
if Count<>nil then
begin
if (GuessSuccPercent>0) and (GuessSuccPercent<=100) then
SuccPercent:=GuessSuccPercent/100
else
SuccPercent:=0.8;
i:=Count^;
j:=GuessUTF8BSAvaiByteCount(InputBS,Count);
if (j>0) and (Count^>0) and (j/Count^>=SuccPercent) then
BSType:=BS_UTF8
else
begin
Count^:=i;
j:=GuessUTF16BSAvaiByteCount(InputBS,Count);
if (j>0) and (Count^>0) and (j/Count^>=SuccPercent) then
BSType:=BS_UTF16
else
begin
Count^:=i;
j:=GuessUTF32BSAvaiByteCount(InputBS,Count);
if (j>0) and (Count^>0) and (j/Count^>=SuccPercent) then
BSType:=BS_UTF32
else
BSType:=BS_Unknow
end
end
end
else
BSType:=BS_Unknow;
Result:=Integer(BSType)
end;

UTF-16编码单元位置转字符位置
原理:首先初始化字符数累加器为0,然后从UTF-16编码单元序列的第一个编码单元开始,依次扫描每个编码单元,如果当前检索到的那个编码单元代表一个有效字符,则字符数累加1……一直扫描到编码单元索引等于指定的索引位置为止。最后字符数累加器的值就是字符串中指定索引位置上那个编码单元在字符串中的字符位置了。
编程:
// UTF-16编码单元位置转字符位置
function UTF16CUToCharIndex(UTF16Str:pWideChar;Index:integer):integer;
stdcall;
var
i,j:integer;
begin
if UTF16Str<>nil then
begin
i:=1;
j:=0;
While (i<=Index) and (UTF16Str[i-1]<>#0)do
begin
case TUTF16CUT(UTF16CodeUnitType(UTF16Str,i)) of
BMPCP:
inc(i);
HighSurr:
i:=i+2
else
begin
j:=-1*j;
Break
end
end;
inc(j)
end;
if (i<=Index) and (UTF16Str[i-1]=#0) then
Result:=-1*j
else
Result:=j
end
else
Result:=0
end;

UTF-16字符位置转编码单元位置
原理:首先初始化字符数累加器为0,然后从UTF-16编码单元序列的第一个编码单元开始,依次扫描每个编码单元,如果当前检索到的那个编码单元代表一个有效字符,则字符数累加1……一直扫描到字符数累加器的值等于指定的字符索引位置为止。最后的编码单元索引值就是字符串中指定位置上那个字符在字符串中的编码单元位置了。
编程:
// UTF-16字符位置转编码单元位置
function UTF16CharToCUIndex(UTF16Str:pWideChar;Index:integer):integer;
stdcall;
var
i,j,c:integer;
begin
if UTF16Str<>nil then
begin
i:=1;
j:=0;
While (j<Index) and (UTF16Str[i-1]<>#0)do
begin
case TUTF16CUT(UTF16CodeUnitType(UTF16Str,i)) of
BMPCP:
c:=1;
HighSurr:
c:=2;
else
Break
end;
i:=i+c;
inc(j)
end;
if j<Index then
Result:=-1*i
else
Result:=i-c
end
else
Result:=0
end;

UTF-8编码单元位置转字符位置
原理:首先初始化字符数累加器为0,然后从UTF-8编码单元序列的第一个编码单元开始,依次扫描每个编码单元,如果当前检索到的那个编码单元代表一个有效字符,则字符数累加1……一直扫描到编码单元索引等于指定的索引位置为止。最后字符数累加器的值就是字符串中指定索引位置上那个编码单元在字符串中的字符位置了。
编程:
// UTF-8编码单元位置转字符位置
function UTF8CUToCharIndex(UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
var
i,j,k,charsize:integer;
begin
if UTF8Str<>nil then
begin
i:=1;
j:=0;
While (i<=Index) and (UTF8Str[i-1]<>#0)do
begin
k:=UTF8CUIndexOfChar(UTF8Str,i,@k,@charsize);
if k>0 then
begin
inc(j);
i:=i+charsize
end
else
if IgnoInvalCU then
begin
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end
else
begin
j:=-1*j;
Break
end
end;
if (i<=Index) and (UTF8Str[i-1]=#0) then
Result:=-1*j
else
Result:=j
end
else
Result:=0
end;

UTF-8字符位置转编码单元位置
原理:首先初始化字符数累加器为0,然后从UTF-8编码单元序列的第一个编码单元开始,依次扫描每个编码单元,如果当前检索到的那个编码单元代表一个有效字符,则字符数累加1……一直扫描到字符数累加器的值等于指定的字符索引位置为止。最后的编码单元索引值就是字符串中指定位置上那个字符在字符串中的编码单元位置了。
编程:
// UTF-8编码单元位置转字符位置
function UTF8CUToCharIndex(UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
var
i,j,k,charsize:integer;
begin
if UTF8Str<>nil then
begin
i:=1;
j:=0;
While (i<=Index) and (UTF8Str[i-1]<>#0)do
begin
k:=UTF8CUIndexOfChar(UTF8Str,i,@k,@charsize);
if k>0 then
begin
inc(j);
i:=i+charsize
end
else
if IgnoInvalCU then
begin
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end
else
begin
j:=-1*j;
Break
end
end;
if (i<=Index) and (UTF8Str[i-1]=#0) then
Result:=-1*j
else
Result:=j
end
else
Result:=0
end;


判断特定编码格式字节序列的BOM类型
即对于UTF-8编码格式字节序列,判断它是否有BOM;对于UTF-16和UTF-32编码格式字节序列,判断它有无BOM,如果有的话,是大尾BOM还是小尾BOM?
原理:这几个函数的判断原理都很简单,即对于特定编码格式的字节序列,根据相应编码机制的规则,检测序列中前面固定长度的几个字节(UTF-8 BOM是3个字节的,UTF-16 BOM是2个字节的,UTF-32 BOM是4个字节的)的值,看看是否和某种BOM字节序列完全符合:如果检测到有符合的BOM类型,就说明该字节序列的BOM类型就是这种了;如果检测完所有可能的BOM类型都没有符合的话,则判断为“默认字节序”BOM类型――对于UTF-8编码格式字节序列来说,是指不带BOM;对于UTF-16或UTF-32编码格式字节序列来说,是指大尾字节序。
编程:
// 检测一个UTF-8编码格式字节序列的BOM类型
function BOMTypeOfUTF8BS(UTF8_BS:pChar):integer;
stdcall;
begin
if (Length(UTF8_BS)>BOMSizeOfUTF8) and (UTF8CUSToCP(UTF8_BS,1)=$FEFF) then
Result:=1
else
Result:=0
end;

// 检测一个UTF-16编码格式字节序列的BOM类型
function BOMTypeOfUTF16BS(UTF16_BS:pChar;Count:integer):integer;
stdcall;
var
i:integer;
BOM:TBOM;
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
Result:=Ord(BOM)
end;

// 检测一个UTF-32编码格式字节序列的BOM类型
function BOMTypeOfUTF32BS(UTF32_BS:pChar;Count:integer):integer;
stdcall;
var
i:integer;
BOM:TBOM;
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
Result:=Ord(BOM)
end;


后记
有关Unicode编码框架的底层处理内容就是这些了,诸如Unicode文本信息的分析处理等较高层面上的工作,则不在本例程库的讨论范围之内。至于像Unicode编码和其他编码(如GBK)之间的转换这样的工作,由于Windows系统对此已经提供了完整的支持,我在这里就没有必要画蛇添足了。
最后想要说明的一点就是:本文所述的主要内容是有关xcUCSStrRoutines.dll例程库中各主要函数的基本算法的设计原理,所给出的源程序样例只是本文在写作每个函数时,该函数在DLL源程序中当时的版本,仅作解释算法原理的参考之用,并不代表这些函数在xcUCSStrRoutines.dll的项目源程序里面的最终版本也完全是这个样子的。如果想要看到这些函数最终版本的源程序的话,请用Delphi打开本软件包附带的xcUCSStrRoutines.dll的项目源程序。当然了,虽然本文给出的示例程序有可能和DLL项目源程序的最终版本不一样,但设计它们的算法原理还是一样。
如果你有任何关于这个软件包开源项目的问题或想法,欢迎来信至craftsman1986@163.com与我讨论,谢谢!。
 
楼主太强了.
强人的人生价值在于从帮助别人并从中体会到快乐.
羡慕ing
 
既然贴了一大段了 索性全部贴出来 以后下载地址失效了还可以找到这个贴:
UCS瑞士军刀目录下:
9,162 xcUCSDLLDynaUnit.pas
7,464 xcUCSDLLStatUnit.pas
4,947 xcUCSRLDataStruUnit.pas
67,072 xcUCSStrRoutines.dll
80,901 xcUCSStrRoutines.dpr
519,168 打造UCS瑞士军刀.doc
//////////////////////////xcUCSStrRoutines.dpr///////////////////////////////
library xcUCSStrRoutines;
// Unicode文本(字符串)处理
// 动态链接库--xcUCSStrRoutines.dll。
uses
SysUtils,
Classes,
Types,
Windows,
TntSystem,
TntSysUtils,
TntClasses,
TntWideStrUtils,
TntWideStrings,
xcUCSRLDataStruUnit in 'xcUCSRLDataStruUnit.pas';
type
// UTF-8编码格式对Unicode编码点的分段的信息类型
TCPPartsOfUTF8Info=array [0..CPPartCountOfUTF8-1] of TCPPartOfUTF8Info;
const
// UTF-8编码格式对Unicode编码点的分段的信息
CPPartOfUTF8Info:TCPPartsOfUTF8Info=
(
(
CodeRange:(MinCode:$0000;MaxCode:$007F);
CUValueRange:
(
(MinValue:$00;MaxValue:$7F),
(MinValue:$FF;MaxValue:$FF),
(MinValue:$FF;MaxValue:$FF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$0080;MaxCode:$07FF);
CUValueRange:
(
(MinValue:$C2;MaxValue:$DF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$0800;MaxCode:$0FFF);
CUValueRange:
(
(MinValue:$E0;MaxValue:$E0),
(MinValue:$A0;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$1000;MaxCode:$CFFF);
CUValueRange:
(
(MinValue:$E1;MaxValue:$EC),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$D000;MaxCode:$D7FF);
CUValueRange:
(
(MinValue:$ED;MaxValue:$ED),
(MinValue:$80;MaxValue:$9F),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$E000;MaxCode:MaxBMPCP);
CUValueRange:
(
(MinValue:$EE;MaxValue:$EF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$FF;MaxValue:$FF)
)
),
(
CodeRange:(MinCode:$10000;MaxCode:$3FFFF);
CUValueRange:
(
(MinValue:$F0;MaxValue:$F0),
(MinValue:$90;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF)
)
),
(
CodeRange:(MinCode:$40000;MaxCode:$FFFFF);
CUValueRange:
(
(MinValue:$F1;MaxValue:$F3),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF)
)
),
(
CodeRange:(MinCode:$100000;MaxCode:MaxUnicodeValue);
CUValueRange:
(
(MinValue:$F4;MaxValue:$F4),
(MinValue:$80;MaxValue:$8F),
(MinValue:$80;MaxValue:$BF),
(MinValue:$80;MaxValue:$BF)
)
)
);
var
TempBS:string;
// 临时Unicode编码格式字节序列
TempInt:integer;
// 临时整型变量
{$R *.res}
// **** UTF-16编码格式处理例程(开始) ****
// 判断UTF-16编码格式字符串中指定位置编码单元的类型:
// 0 表示 无效编码单元
// 1 表示 BMP字符
// 2 表示 高位代理
// 3 表示 低位代理
function UTF16CodeUnitType(UTF16Str:pWideChar;Index:integer):integer;
stdcall;
var
UTF16Code:Word;
UTF16CUT:TUTF16CUT;
begin
if (UTF16Str<>nil) and (UTF16Str^<>#0) then
begin
UTF16Code:=Ord(UTF16Str[Index-1]);
if (UTF16Code>=HighSurrStart) and (UTF16Code<=LowSurrEnd) then
begin
if UTF16Code<=HighSurrEnd then
begin
if UTF16Str[Index]<>#0 then
begin
UTF16Code:=Ord(UTF16Str[Index]);
if (UTF16Code>=LowSurrStart) and (UTF16Code<=LowSurrEnd) then
UTF16CUT:=HighSurr
else
UTF16CUT:=InvalCodeUnit
end
else
UTF16CUT:=InvalCodeUnit
end
else
if Index>1 then
begin
UTF16Code:=Ord(UTF16Str[Index-2]);
if (UTF16Code>=HighSurrStart) and (UTF16Code<=HighSurrEnd) then
UTF16CUT:=LowSurr
else
UTF16CUT:=InvalCodeUnit
end
else
UTF16CUT:=InvalCodeUnit
end
else
UTF16CUT:=BMPCP
end
else
UTF16CUT:=InvalCodeUnit;
Result:=Ord(UTF16CUT)
end;

// 求UTF-16编码格式字符串中某个位置上的编码单元在它自己所属的
// 字符中的索引位置:0表示无效编码单元;1表示第一个编码单元;
// 2表示第二个编码单元。同时通过变参CharSize返回该(有效)字符
// 的长度。
function UTF16CUIndexOfChar(UTF16Str:pWideChar;Index:integer;
CharSize:pInteger):integer;
stdcall;
begin
case UTF16CodeUnitType(UTF16Str,Index) of
1:
begin
CharSize^:=1;
Result:=1
end;
2:
begin
CharSize^:=2;
Result:=1
end;
3:
begin
CharSize^:=2;
Result:=2
end
else
begin
CharSize^:=0;
Result:=0
end
end
end;

// UTF-16编码单元位置转字符位置
function UTF16CUToCharIndex(UTF16Str:pWideChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
var
i,j,l:integer;
begin
if UTF16Str<>nil then
begin
i:=1;
j:=0;
l:=Length(UTF16Str);
While (i<=Index) and (i<=l)do
begin
case TUTF16CUT(UTF16CodeUnitType(UTF16Str,i)) of
BMPCP:
inc(i);
HighSurr:
i:=i+2
else
if IgnoInvalCU then
begin
inc(i);
Continue
end
else
begin
j:=-1*i;
Break
end
end;
inc(j)
end;
if (i<=Index) and (UTF16Str[i-1]=#0) then
Result:=-1*i
else
Result:=j
end
else
Result:=0
end;

// UTF-16字符位置转编码单元位置
function UTF16CharToCUIndex(UTF16Str:pWideChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
var
i,j,c,l:integer;
begin
if UTF16Str<>nil then
begin
i:=1;
j:=0;
l:=Length(UTF16Str);
While (j<Index) and (i<=l)do
begin
case TUTF16CUT(UTF16CodeUnitType(UTF16Str,i)) of
BMPCP:
c:=1;
HighSurr:
c:=2;
else
if IgnoInvalCU then
begin
inc(i);
Continue
end
else
Break
end;
i:=i+c;
inc(j)
end;
if j<Index then
Result:=-1*i
else
Result:=i-c
end
else
Result:=0
end;

// 把编码点转换为UTF-16编码单元序列
function CPToUTF16CUS(UTF16Str:pWideChar;Code:DWORD):integer;
stdcall;
var
HighSurr,LowSurr,PosOfPanel:Word;
begin
if Code<=MaxUnicodeValue then
begin
if Code<=MaxBMPCP then
begin
if (Code<HighSurrStart) or (Code>LowSurrEnd) then
begin
if UTF16Str<>nil then
begin
UTF16Str[0]:=WideChar(Code);
UTF16Str[1]:=#0
end;
Result:=1
end
else
Result:=0
end
else
begin
if UTF16Str<>nil then
begin
PosOfPanel:=Code mod $10000;
HighSurr:=HighSurrStart+(Code div $10000 - 1)*$40+PosOfPanel div 1024;
LowSurr:=LowSurrStart+PosOfPanel mod 1024;
UTF16Str[0]:=WideChar(HighSurr);
UTF16Str[1]:=WideChar(LowSurr);
UTF16Str[2]:=#0
end;
Result:=2
end
end
else
Result:=0
end;

// 把UTF-16编码格式字符串中指定位置上的编码单元所属的字符的
// 编码单元序列转换为编码点
function UTF16CUSToCP(UTF16Str:pWideChar;Index:integer):DWORD;
stdcall;
var
HighSurr,LowSurr:Word;
Unicode:DWORD;
begin
if (UTF16Str<>nil) and (UTF16Str^<>#0) then
begin
HighSurr:=UTF16CodeUnitType(UTF16Str,Index);
case HighSurr of
1:
Result:=Ord(UTF16Str[Index-1]);
2,3:
begin
if HighSurr=2 then
begin
HighSurr:=Ord(UTF16Str[Index-1]);
LowSurr:=Ord(UTF16Str[Index])
end
else
begin
HighSurr:=Ord(UTF16Str[Index-2]);
LowSurr:=Ord(UTF16Str[Index-1])
end;
HighSurr:=HighSurr-HighSurrStart;
Unicode:=(HighSurr div $40 + 1)*$10000;
LowSurr:=HighSurr mod $40 *1024+LowSurr-LowSurrStart;
Result:=Unicode+LowSurr
end
else
Result:=$FFFFFFFF
end
end
else
Result:=$FFFFFFFF
end;

// 代理对转换为编码点
function SurrPairToCP(HighSurr,LowSurr:WORD):DWORD;
stdcall;
var
S:array [0..1] of WideChar;
CP:DWORD;
begin
S[0]:=WideChar(HighSurr);
S[1]:=WideChar(LowSurr);
CP:=UTF16CUSToCP(S,1);
if CP>MaxBMPCP then
Result:=CP
else
Result:=$FFFFFFFF
end;

// 编码点转换为代理对
function CPToSurrPair(UnicodeValue:DWORD):DWORD;
stdcall;
var
S:array [0..2] of WideChar;
CP:DWORD;
i:integer;
begin
CP:=0;
for i:=0 to CPToUTF16CUS(S,UnicodeValue)-1do
CP:=CP shl 16 + Ord(S);
Result:=CP
end;

// **** UTF-16编码格式处理例程(结束) ****

// **** UTF-8编码格式处理例程(开始) ****
// 求UTF-8编码格式字符串中某个位置上的编码单元在它自己所属的
// 字符中的索引位置:0表示无效编码单元;1表示第一个编码单元;
// 2表示第二个编码单元,3表示第三个编码单元,4表示第四个编码
// 单元。同时通过变参CPPartIndexOfUTF8返回该(有效)字符的编
// 码点在UTF8编码格式中的分段索引;CharSize返回该(有效)字
// 符的长度。
function UTF8CUIndexOfChar(UTF8Str:pChar;Index:integer;
CPPartIndexOfUTF8,CharSize:pInteger):integer;
stdcall;
label 10,20;
var
TmpByte:Byte;
i,j:integer;
begin
if (UTF8Str<>nil) and (UTF8Str^<>#0) then
begin
TmpByte:=Ord(UTF8Str[Index-1]);
if TmpByte in InvalUTF8CUSet then
begin
CPPartIndexOfUTF8^:=-1;
CharSize^:=1;
Result:=-1*Index
end
else
begin
i:=0;
10:
case TmpByte of
$00..$7F:
begin
CPPartIndexOfUTF8^:=0;
CharSize^:=1;
Result:=1;
exit
end;
$C2..$F4:
case TmpByte of
$C2..$DF:
begin
CPPartIndexOfUTF8^:=1;
CharSize^:=2
end;
$E0..$EF:
begin
case TmpByte of
$E0:
CPPartIndexOfUTF8^:=2;
$E1..$EC:
CPPartIndexOfUTF8^:=3;
$ED:
CPPartIndexOfUTF8^:=4
else
CPPartIndexOfUTF8^:=5
end;
CharSize^:=3
end
else
begin
case TmpByte of
$F0:
CPPartIndexOfUTF8^:=6;
$F1..$F3:
CPPartIndexOfUTF8^:=7
else
CPPartIndexOfUTF8^:=8
end;
CharSize^:=4
end
end
else
begin
if Index>1 then
begin
if i=0 then
i:=Index
else
if TmpByte in InvalUTF8CUSet then
begin
inc(Index);
goto 20
end;
dec(Index);
TmpByte:=Ord(UTF8Str[Index-1])
end
else
begin
20:
if i=0 then
i:=Index+1
else
inc(i);
While UTF8Str[i-1]<>#0do
begin
TmpByte:=Ord(UTF8Str[i-1]);
if TmpByte and $C0 = $80 then
inc(i)
else
Break
end;
CPPartIndexOfUTF8^:=-1;
CharSize^:=i-Index;
Result:=-1*Index;
exit
end;
goto 10
end
end;

for j:=1 to CharSize^-1do
With CPPartOfUTF8Info[CPPartIndexOfUTF8^].CUValueRange[j]do
begin
TmpByte:=Ord(UTF8Str[Index+j-1]);
if (TmpByte=0) or (TmpByte<MinValue) or (TmpByte>MaxValue) then
begin
CPPartIndexOfUTF8^:=-1*CPPartIndexOfUTF8^;
// 出错编码单元序列长度尚需商榷--
// CharSize^:=?
// 是按序列首字节规定的“标准长度”,
// 还是从首字节到出错位置为止的“实际长度”?
// 现在暂时先取“标准长度”。
if i>0 then
Result:=-1*(i-Index+1)
else
Result:=-1;
exit
end
end;

if i>0 then
Result:=i-Index+1
else
Result:=1
end
end
else
begin
CPPartIndexOfUTF8^:=-1;
CharSize^:=0;
Result:=0
end
end;

// UTF-8编码单元位置转字符位置
function UTF8CUToCharIndex(UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
var
i,j,k,charsize,l:integer;
begin
if UTF8Str<>nil then
begin
i:=1;
j:=0;
l:=Length(UTF8Str);
While (i<=Index) and (i<=l)do
begin
k:=UTF8CUIndexOfChar(UTF8Str,i,@k,@charsize);
if k>0 then
begin
inc(j);
i:=i+charsize
end
else
if IgnoInvalCU then
begin
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end
else
begin
j:=-1*i;
Break
end
end;
if (i<=Index) and (UTF8Str[i-1]=#0) then
Result:=-1*i
else
Result:=j
end
else
Result:=0
end;

// UTF-8字符位置转UTF-8编码单元位置
function UTF8CharToCUIndex(UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
var
i,j,k,charsize,l:integer;
begin
if UTF8Str<>nil then
begin
i:=1;
j:=0;
l:=Length(UTF8Str);
While (j<Index) and (i<=l)do
begin
k:=UTF8CUIndexOfChar(UTF8Str,i,@k,@charsize);
if k>0 then
begin
inc(j);
i:=i+charsize
end
else
if IgnoInvalCU then
begin
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end
else
Break
end;
if j<Index then
Result:=-1*i
else
Result:=i-charsize
end
else
Result:=0
end;

// 把编码点转换为UTF-8编码单元序列
function CPToUTF8CUS(UTF8Str:pChar;Code:DWORD):integer;
stdcall;
var
i,j,k:integer;
c:DWORD;
c1:Byte;
begin
j:=0;
for i:=0 to CPPartCountOfUTF8-1do
With CPPartOfUTF8Infodo
if (Code>=CodeRange.MinCode)
and
(Code<=CodeRange.MaxCode)
then
begin
j:=MaxCodeUnitCountOfUTF8-1;
Repeat
if (CUValueRange[j].MinValue in InvalUTF8CUSet)
or
(CUValueRange[j].MaxValue in InvalUTF8CUSet)
then
dec(j)
else
begin
if UTF8Str<>nil then
begin
Code:=Code-CodeRange.MinCode;
c:=1;
for k:=jdo
wnto 0do
begin
c1:=CUValueRange[k].MaxValue-CUValueRange[k].MinValue+1;
UTF8Str[k]:=Chr(CUValueRange[k].MinValue + Code div c mod c1);
c:=c*c1;
Code:=Code-Code mod c
end;
UTF8Str[j+1]:=#0
end;

Break
end
Until j<0;
inc(j);
Break
end;

Result:=j
end;

// 把UTF-8编码格式字符串中指定位置上的编码单元所属的字符的
// 编码单元序列转换为编码点
function UTF8CUSToCP(UTF8Str:pChar;Index:integer):DWORD;
stdcall;
var
i,chrsize:integer;
c,CPCode:DWORD;
begin
c:=UTF8CUIndexOfChar(UTF8Str,Index,@i,@chrsize);
if c in [1..MaxCodeUnitCountOfUTF8] then
begin
Index:=Index-c+1;
With CPPartOfUTF8Infodo
begin
c:=1;
CPCode:=CodeRange.MinCode;
for chrsize:=chrsize-1do
wnto 0do
begin
CPCode:=CPCode+(Ord(UTF8Str[Index-1+chrsize])-
CUValueRange[chrsize].MinValue)*c;
c:=c*(CUValueRange[chrsize].MaxValue-
CUValueRange[chrsize].MinValue+1)
end;
Result:=CPCode
end
end
else
Result:=$FFFFFFFF
end;

// 求指定编码点所在的UTF-8编码点分段
function GetCPPartIndexOfUTF8(Code:DWORD;
PCPPartOfUTF8Info:TPCPPartOfUTF8Info):integer;
stdcall;
var
i:integer;
begin
i:=0;
While (i<CPPartCountOfUTF8)
and
(
(Code<CPPartOfUTF8Info.CodeRange.MinCode)
or
(Code>CPPartOfUTF8Info.CodeRange.MaxCode)
)
do
inc(i);
if (i in [0..CPPartCountOfUTF8-1])
and
(Code>=CPPartOfUTF8Info.CodeRange.MinCode)
and
(Code<=CPPartOfUTF8Info.CodeRange.MaxCode)
then
begin
if PCPPartOfUTF8Info<>nil then
PCPPartOfUTF8Info^:=CPPartOfUTF8Info;
Result:=i
end
else
Result:=-1
end;

// **** UTF-8编码格式处理例程(结束) ****

// **** 编码格式综合例程(开始) ****
// 求VCL WideString 字符串的存储长度(单位:字节)
function GetByteLenOfVCLWideString(S:pWideChar):integer;
stdcall;
begin
if S<>nil then
Result:=PInteger(Integer(S)-4)^
else
Result:=0
end;

// (单个Unicode编码点的)UTF-16编码单元序列转UTF-8编码单元序列
function UTF16ToUTF8ForChar(UTF16Str:pWideChar;Index:integer;
UTF8Str:pChar):integer;
stdcall;
var
HighSurr,LowSurr:WORD;
c,c1,Code:DWORD;
TmpByte:Byte;
CPPartOfUTF8Info:TCPPartOfUTF8Info;
begin
case UTF16CodeUnitType(UTF16Str,Index) of
1:
begin
Result:=CPToUTF8CUS(UTF8Str,Ord(UTF16Str[Index-1]));
exit
end;
2:
begin
HighSurr:=Ord(UTF16Str[Index-1]);
LowSurr:=Ord(UTF16Str[Index])
end;
3:
begin
HighSurr:=Ord(UTF16Str[Index-2]);
LowSurr:=Ord(UTF16Str[Index-1])
end
else
begin
Result:=0;
exit
end
end;

if UTF8Str<>nil then
begin
HighSurr:=HighSurr-HighSurrStart;
Code:=(HighSurr div $40 + 1)*$10000;
GetCPPartIndexOfUTF8(Code,@CPPartOfUTF8Info);
With CPPartOfUTF8Infodo
begin
Code:=Code-CodeRange.MinCode;
c1:=HighSurr mod $40 *1024+LowSurr-LowSurrStart;
c:=CUValueRange[3].MaxValue-CUValueRange[3].MinValue+1;
UTF8Str[3]:=Chr(CUValueRange[3].MinValue + c1 mod c);
c1:=c1 div c;
TmpByte:=CUValueRange[2].MaxValue-CUValueRange[2].MinValue+1;
UTF8Str[2]:=Chr(CUValueRange[2].MinValue + c1 mod TmpByte);
c1:=c1 div TmpByte;
c:=c*TmpByte;
TmpByte:=CUValueRange[1].MaxValue-CUValueRange[1].MinValue+1;
UTF8Str[1]:=Chr(CUValueRange[1].MinValue + Code div c mod TmpByte + c1);
c:=c*TmpByte;
if CUValueRange[0].MinValue=CUValueRange[0].MaxValue then
UTF8Str[0]:=Chr(CUValueRange[0].MinValue)
else
UTF8Str[0]:=Chr(CUValueRange[0].MinValue + Code div c)
end;
UTF8Str[4]:=#0
end;
Result:=4
end;

// (单个Unicode编码点的)UTF-8编码单元序列转UTF-16编码单元序列
function UTF8ToUTF16ForChar(UTF8Str:pChar;Index:integer;
UTF16Str:pWideChar):integer;
stdcall;
begin
Result:=CPToUTF16CUS(UTF16Str,UTF8CUSToCP(UTF8Str,Index))
end;

// UTF-16字符串转换为UTF-8字符串
function UTF16ToUTF8ForStr(UTF16Str:pWideChar;UTF8Str:pChar):integer;
stdcall;
var
j,c:integer;
begin
if (UTF16Str<>nil) and (UTF16Str^<>#0) then
begin
j:=0;
Repeat
if UTF8Str<>nil then
c:=UTF16ToUTF8ForChar(UTF16Str,1,UTF8Str+j)
else
c:=UTF16ToUTF8ForChar(UTF16Str,1,nil);
if c<4 then
inc(UTF16Str)
else
UTF16Str:=UTF16Str+2;
j:=j+c
Until UTF16Str^=#0;
if UTF8Str<>nil then
UTF8Str[j]:=#0;
Result:=j
end
else
Result:=0
end;

// UTF-8字符串转换为UTF-16字符串
function UTF8ToUTF16ForStr(UTF8Str:pChar;UTF16Str:pWideChar):integer;
stdcall;
var
i,c,charsize:integer;
begin
if UTF8Str<>nil then
begin
i:=0;
While UTF8Str^<>#0do
begin
if UTF16Str<>nil then
c:=UTF8ToUTF16ForChar(UTF8Str,1,UTF16Str+i)
else
c:=UTF8ToUTF16ForChar(UTF8Str,1,nil);
i:=i+c;
c:=UTF8CUIndexOfChar(UTF8Str,1,@c,@CharSize);
if c>0 then
UTF8Str:=UTF8Str+CharSize
else
if c=0 then
Break
else
UTF8Str:=UTF8Str+(-1*c)+CharSize-1
end;

if UTF16Str<>nil then
UTF16Str:=#0;
Result:=i
end
else
Result:=0
end;

// 计算UTF-16字符串中的字符数目
function CharCountOfUTF16Str(UTF16Str:pWideChar):integer;
stdcall;
var
i:integer;
begin
if UTF16Str<>nil then
begin
i:=0;
While UTF16Str^<>#0do
case TUTF16CUT(UTF16CodeUnitType(UTF16Str,1)) of
BMPCP:
begin
inc(i);
inc(UTF16Str)
end;
HighSurr:
begin
inc(i);
UTF16Str:=UTF16Str+2
end
else
inc(UTF16Str)
end;
Result:=i
end
else
Result:=0
end;

// 计算UTF-8字符串中的字符数目
function CharCountOfUTF8Str(UTF8Str:pChar):integer;
stdcall;
var
i,j,charsize:integer;
begin
if UTF8Str<>nil then
begin
i:=0;
While UTF8Str^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8Str,1,@j,@charsize);
if j>0 then
begin
inc(i);
UTF8Str:=UTF8Str+charsize
end
else
if j=0 then
Break
else
UTF8Str:=UTF8Str+(-1*j)+CharSize-1
end;
Result:=i
end
else
Result:=0
end;

// 计算UTF-32字符串中的字符数目
function CharCountOfUTF32Str(UTF32:pDWORD):integer;
stdcall;
var
i:integer;
begin
if UTF32<>nil then
begin
i:=0;
While UTF32^<>0do
begin
if (UTF32^>=0) and (UTF32^<HighSurrStart)
or
(UTF32^>LowSurrEnd) and (UTF32^<=MaxUnicodeValue)
then
inc(i);
inc(UTF32)
end;
Result:=i
end
else
Result:=0
end;

// UTF-16字符串转换为UTF-32字符串(编码单元序列)
function UTF16ToUTF32ForStr(UTF16Str:pWideChar;UTF32Str:pDWORD):integer;
stdcall;
var
tmpp:pDWORD;
UTF32Code:DWORD;
begin
if UTF16Str<>nil then
begin
if UTF32Str<>nil then
begin
tmpp:=UTF32Str;
While UTF16Str^<>#0do
begin
UTF32Code:=UTF16CUSToCP(UTF16Str,1);
if UTF32Code<=MaxUnicodeValue then
begin
UTF32Str^:=UTF32Code;
inc(UTF32Str);
if UTF32Code>MaxBMPCP then
UTF16Str:=UTF16Str+2
else
inc(UTF16Str)
end
else
inc(UTF16Str)
end;
UTF32Str^:=0;
Result:=(Integer(UTF32Str)-Integer(tmpp)) div SizeOf(DWORD)
end
else
Result:=CharCountOfUTF16Str(UTF16Str)+1 // 这里多加一个空结束符位置
end
else
Result:=0
end;

// UTF-32字符串(编码单元序列)转换为UTF-16字符串
function UTF32ToUTF16ForStr(UTF32Str:pDWORD;UTF16Str:pWideChar):integer;
stdcall;
var
i,c:integer;
begin
if UTF32Str<>nil then
begin
i:=0;
While UTF32Str^<>0do
begin
if UTF16Str<>nil then
c:=CPToUTF16CUS(UTF16Str+i,UTF32Str^)
else
c:=CPToUTF16CUS(nil,UTF32Str^);
if c>0 then
i:=i+c;
inc(UTF32Str)
end;

if UTF16Str<>nil then
UTF16Str:=#0;
Result:=i
end
else
Result:=0
end;

// UTF-8字符串转换为UTF-32字符串(编码单元序列)
function UTF8ToUTF32ForStr(UTF8Str:pChar;UTF32Str:pDWORD):integer;
stdcall;
var
tmpp:pDWORD;
UTF32Code:DWORD;
i,j:integer;
begin
if UTF8Str<>nil then
begin
if UTF32Str<>nil then
begin
tmpp:=UTF32Str;
While UTF8Str^<>#0do
begin
UTF32Code:=UTF8CUSToCP(UTF8Str,1);
if (UTF32Code>=0) and (UTF32Code<HighSurrStart)
or
(UTF32Code>LowSurrEnd) and (UTF32Code<=MaxUnicodeValue)
then
begin
UTF32Str^:=UTF32Code;
inc(UTF32Str);
UTF8CUIndexOfChar(UTF8Str,1,@i,@j);
UTF8Str:=UTF8Str+j
end
else
inc(UTF8Str)
end;
UTF32Str^:=0;
Result:=(Integer(UTF32Str)-Integer(tmpp)) div SizeOf(DWORD)
end
else
Result:=CharCountOfUTF8Str(UTF8Str)+1 // 这里多加一个空结束符位置
end
else
Result:=0
end;

// UTF-32字符串(编码单元序列)转换为UTF-8字符串
function UTF32ToUTF8ForStr(UTF32Str:pDWORD;UTF8Str:pChar):integer;
stdcall;
var
i,c:integer;
begin
if UTF32Str<>nil then
begin
i:=0;
While UTF32Str^<>0do
begin
if UTF8Str<>nil then
c:=CPToUTF8CUS(UTF8Str+i,UTF32Str^)
else
c:=CPToUTF8CUS(nil,UTF32Str^);
if c>0 then
i:=i+c;
inc(UTF32Str)
end;

if UTF8Str<>nil then
UTF8Str:=#0;
Result:=i
end
else
Result:=0
end;

// **** 编码格式综合例程(结束) ****

// **** Unicode编码机制处理例程(开始) ****
// 把UTF-8编码单元序列转换为带BOM的UTF-8编码格式字节序列
function CUSToBSForUTF8(UTF8_CUS,UTF8_BS:pChar):integer;
stdcall;
var
i,j,charsize:integer;
begin
if UTF8_CUS<>nil then
begin
if UTF8_BS<>nil then
for i:=0 to BOMSizeOfUTF8-1do
UTF8_BS:=Chr(BOMOfUTF8);
i:=BOMSizeOfUTF8;
While UTF8_CUS^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8_CUS,1,@j,@charsize);
if j>0 then
begin
if UTF8_BS<>nil then
for j:=1 to charsizedo
begin
UTF8_BS:=UTF8_CUS^;
inc(UTF8_CUS);
inc(i)
end
else
begin
UTF8_CUS:=UTF8_CUS+charsize;
i:=i+charsize
end
end
else
if j=0 then
Break
else
UTF8_CUS:=UTF8_CUS+(-1*j)+charsize-1
end;

if i>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-8编码格式字节序列转换为UTF-8编码单元序列
function BSToCUSForUTF8(UTF8_BS,UTF8_CUS:pChar):integer;
stdcall;
var
i,j,charsize:integer;
begin
if UTF8_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
i:=0;

While UTF8_BS^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8_BS,1,@j,@charsize);
if j>0 then
begin
if UTF8_CUS<>nil then
for j:=1 to charsizedo
begin
UTF8_CUS:=UTF8_BS^;
inc(i);
inc(UTF8_BS)
end
else
begin
i:=i+charsize;
UTF8_BS:=UTF8_BS+charsize
end
end
else
if j=0 then
Break
else
UTF8_BS:=UTF8_BS+(-1*j)+charsize-1
end;

if i>0 then
begin
if UTF8_CUS<>nil then
UTF8_CUS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-16编码单元序列转换为带BOM的UTF-16编码格式字节序列
function CUSToBSForUTF16(UTF16_CUS:pWideChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j,CodeUnitCount:integer;
BOM:TBOM;
begin
if UTF16_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF16_BS<>nil then
for i:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMBE:
UTF16_BS:=Chr(BOMBEOfUTF16);
BOMLE:
UTF16_BS:=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)])
end;
i:=BOMSizeOfUTF16
end
else
i:=0;
While UTF16_CUS^<>#0do
begin
case TUTF16CUT(UTF16CodeUnitType(UTF16_CUS,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(UTF16_CUS);
Continue
end
end;

if UTF16_BS<>nil then
for j:=0 to CodeUnitCount-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]));
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]) shr 8)
end
else
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]) shr 8);
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]))
end
end;
i:=i+2
end
else
i:=i+CodeUnitCount*2;
UTF16_CUS:=UTF16_CUS+CodeUnitCount
end;

if (BOM in NotDefaultBOMSet) and (i>BOMSizeOfUTF16) or (i>0) then
begin
if UTF16_BS<>nil then
UTF16_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-16编码格式字节序列转换为UTF-16编码单元序列
function BSToCUSForUTF16(UTF16_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
label 10;
var
i,j,k,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF16+1
else
i:=1;
j:=0;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
if UTF16_CUS<>nil then
for k:=1 to CodeUnitCountdo
begin
UTF16_CUS[j]:=CP[k-1];
inc(j)
end
else
j:=j+CodeUnitCount;
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>0 then
begin
if UTF16_CUS<>nil then
UTF16_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// 把UTF-32编码单元序列转换为带BOM的UTF-32编码格式字节序列
function CUSToBSForUTF32(UTF32_CUS:pDWORD;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF32_BS<>nil then
for i:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMBE:
UTF32_BS:=Chr(BOMBEOfUTF32);
BOMLE:
UTF32_BS:=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)])
end;
i:=BOMSizeOfUTF32
end
else
i:=0;
if UTF32_BS<>nil then
begin
While UTF32_CUS^<>0do
begin
CP:=UTF32_CUS^;
if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
case BOM of
BOMLE:
for j:=0 to 3do
begin
UTF32_BS:=Chr(CP shr (8*j));
inc(i)
end
else
for j:=3do
wnto 0do
begin
UTF32_BS:=Chr(CP shr (8*j));
inc(i)
end
end;

inc(UTF32_CUS)
end;

if (BOM in NotDefaultBOMSet) and (i>BOMSizeOfUTF32) or (i>0) then
begin
UTF32_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=i+4*CharCountOfUTF32Str(UTF32_CUS)
end
else
Result:=0
end;

// 计算UTF-8编码格式字节序列中的(有效)字符数
function CharCountOfUTF8BS(UTF8_BS:pChar):integer;
stdcall;
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
Result:=CharCountOfUTF8Str(UTF8_BS+BOMSizeOfUTF8)
else
Result:=CharCountOfUTF8Str(UTF8_BS)
end;

// 计算UTF-16编码格式字节序列中的(有效)字符数
function CharCountOfUTF16BS(UTF16_BS:pChar;Count:integer):integer;
stdcall;
label 10;
var
i,j,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF16+1
else
i:=1;
j:=0;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
inc(j);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

Result:=j
end
else
Result:=0
end;

// 计算UTF-32编码格式字节序列中的(有效)字符数
function CharCountOfUTF32BS(UTF32_BS:pChar;Count:integer):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF32+1
else
i:=1;
j:=0;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
inc(j);
i:=i+4
end
else
inc(i)
end;

Result:=j
end
else
Result:=0
end;

// 把UTF-32编码格式字节序列转换为UTF-32编码单元序列
function BSToCUSForUTF32(UTF32_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
var
i,j:integer;
BOM:TBOM;
CP:DWORD;
tmpp:pDWORD;
begin
if UTF32_BS<>nil then
begin
if UTF32_CUS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF32+1
else
i:=1;
tmpp:=UTF32_CUS;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for j:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[j])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for j:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[j])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
tmpp^:=CP;
inc(tmpp);
i:=i+4
end
else
inc(i)
end;

if tmpp<>UTF32_CUS then
begin
tmpp^:=0;
Result:=(Integer(tmpp)-Integer(UTF32_CUS)) div SizeOf(DWORD)
end
else
Result:=0
end
else
Result:=CharCountOfUTF32BS(UTF32_BS,Count)+1
end
else
Result:=0
end;

// UTF-8编码格式字节序列转换为UTF-16编码格式字节序列
function UTF8ToUTF16ForBS(UTF8_BS:pChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j,charsize:integer;
BOM:TBOM;
UTF16_CUS:array [0..2] of WideChar;
begin
if UTF8_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF16_BS<>nil then
for i:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMBE:
UTF16_BS:=Chr(BOMBEOfUTF16);
BOMLE:
UTF16_BS:=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)])
end;
i:=BOMSizeOfUTF16
end
else
i:=0;

While UTF8_BS^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8_BS,1,@j,@charsize);
if j>0 then
begin
j:=UTF8ToUTF16ForChar(UTF8_BS,1,UTF16_CUS);
if UTF16_BS<>nil then
for j:=0 to j-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]));
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]) shr 8)
end
else
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]) shr 8);
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]))
end
end;
i:=i+2
end
else
i:=i+j*2;
UTF8_BS:=UTF8_BS+charsize
end
else
if j=0 then
Break
else
UTF8_BS:=UTF8_BS+(-1*j)+charsize-1
end;

if (BOM in NotDefaultBOMSet) and (i>BOMSizeOfUTF16) or (i>0) then
begin
if UTF16_BS<>nil then
UTF16_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// UTF-8编码格式字节序列转换为UTF-32编码格式字节序列
function UTF8ToUTF32ForBS(UTF8_BS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j,charsize:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF8_BS<>nil then
begin
BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF32_BS<>nil then
for i:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMBE:
UTF32_BS:=Chr(BOMBEOfUTF32);
BOMLE:
UTF32_BS:=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)])
end;
i:=BOMSizeOfUTF32
end
else
i:=0;
if UTF32_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;

While UTF8_BS^<>#0do
begin
j:=UTF8CUIndexOfChar(UTF8_BS,1,@j,@charsize);
if j>0 then
begin
CP:=UTF8CUSToCP(UTF8_BS,1);
case BOM of
BOMLE:
for j:=0 to 3do
begin
UTF32_BS:=Chr(CP shr (8*j));
inc(i)
end
else
for j:=3do
wnto 0do
begin
UTF32_BS:=Chr(CP shr (8*j));
inc(i)
end
end;

UTF8_BS:=UTF8_BS+charsize
end
else
if j=0 then
Break
else
UTF8_BS:=UTF8_BS+(-1*j)+charsize-1
end;

if (BOM in NotDefaultBOMSet) and (i>BOMSizeOfUTF32) or (i>0) then
begin
UTF32_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=i+4*CharCountOfUTF8BS(UTF8_BS)
end
else
Result:=0
end;

// UTF-16编码格式字节序列转为UTF-8编码格式字节序列
function UTF16ToUTF8ForBS(UTF16_BS:pChar;Count:integer;UTF8_BS:pChar):integer;
stdcall;
label 10;
var
i,j,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF16+1
else
i:=1;

if UTF8_BS<>nil then
for j:=0 to BOMSizeOfUTF8-1do
UTF8_BS[j]:=Chr(BOMOfUTF8[j]);
j:=BOMSizeOfUTF8;

While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
if UTF8_BS<>nil then
j:=j+UTF16ToUTF8ForChar(CP,1,UTF8_BS+j)
else
j:=j+UTF16ToUTF8ForChar(CP,1,nil);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-16编码格式字节序列转换为UTF-32编码格式字节序列
function UTF16ToUTF32ForBS(UTF16_BS:pChar;Count,BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
label 10;
var
i,j,k,CodeUnitCount:integer;
BOM,BOM1:TBOM;
CP:array [0..1] of WideChar;
CPValue:DWORD;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF16+1
else
i:=1;
BOM1:=TBOM(BOMType);
if BOM1 in NotDefaultBOMSet then
begin
if UTF32_BS<>nil then
for j:=0 to BOMSizeOfUTF32-1do
case BOM1 of
BOMBE:
UTF32_BS[j]:=Chr(BOMBEOfUTF32[j]);
BOMLE:
UTF32_BS[j]:=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(j+1)])
end;
j:=BOMSizeOfUTF32
end
else
j:=0;

While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
CPValue:=UTF16CUSToCP(CP,1);
if (CPValue>=0) and (CPValue<=MaxBMPCP) then
CodeUnitCount:=1
else
if CPValue<=MaxUnicodeValue then
CodeUnitCount:=2
else
begin
inc(i);
Continue
end;
if UTF32_BS<>nil then
case BOM1 of
BOMLE:
for k:=0 to 3do
begin
UTF32_BS[j]:=Chr(CPValue shr (8*k));
inc(j)
end
else
for k:=3do
wnto 0do
begin
UTF32_BS[j]:=Chr(CPValue shr (8*k));
inc(j)
end
end
else
j:=j+4;
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if (BOM1 in NotDefaultBOMSet) and (j>BOMSizeOfUTF32) or (j>0) then
begin
if UTF32_BS<>nil then
UTF32_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-32编码格式字节序列转UTF-8编码格式字节序列
function UTF32ToUTF8ForBS(UTF32_BS:pChar;Count:integer;UTF8_BS:pChar):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF32+1
else
i:=1;
if UTF8_BS<>nil then
for k:=0 to BOMSizeOfUTF8-1do
UTF8_BS[k]:=Chr(BOMOfUTF8[k]);
j:=BOMSizeOfUTF8;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
if UTF8_BS<>nil then
j:=j+CPToUTF8CUS(UTF8_BS+j,CP)
else
j:=j+CPToUTF8CUS(nil,CP);
i:=i+4
end;

if j>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-32编码格式字节序列转UTF-16编码格式字节序列
function UTF32ToUTF16ForBS(UTF32_BS:pChar;Count,BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j,k:integer;
BOM,BOM1:TBOM;
CP:DWORD;
CUS:array [0..2] of WideChar;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF32+1
else
i:=1;

BOM1:=TBOM(BOMType);
if BOM1 in NotDefaultBOMSet then
begin
if UTF16_BS<>nil then
for j:=0 to BOMSizeOfUTF16-1do
case BOM1 of
BOMBE:
UTF16_BS[j]:=Chr(BOMBEOfUTF16[j]);
BOMLE:
UTF16_BS[j]:=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(j+1)])
end;
j:=BOMSizeOfUTF16
end
else
j:=0;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if (CP>=0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
CPToUTF16CUS(CUS,CP);
case TUTF16CUT(UTF16CodeUnitType(CUS,1)) of
BMPCP:
k:=1;
HighSurr:
k:=2
else
begin
inc(i);
Continue
end
end;

if UTF16_BS<>nil then
for k:=0 to k-1do
begin
case BOM1 of
BOMLE:
begin
UTF16_BS[j]:=Chr(Ord(CUS[k]));
UTF16_BS[j+1]:=Chr(Ord(CUS[k]) shr 8)
end
else
begin
UTF16_BS[j]:=Chr(Ord(CUS[k]) shr 8);
UTF16_BS[j+1]:=Chr(Ord(CUS[k]))
end
end;
j:=j+2
end
else
j:=j+k*2
end;

i:=i+4
end;

if (BOM1 in NotDefaultBOMSet) and (j>BOMSizeOfUTF16) or (j>0) then
begin
if UTF16_BS<>nil then
UTF16_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-8编码单元序列转UTF-16编码格式字节序列
function UTF8CUSToUTF16BS(UTF8_CUS:pChar;BOMType:
integer;UTF16_BS:pChar):integer;
stdcall;
var
i,j,k,charsize:integer;
BOM:TBOM;
UTF16_CUS:array [0..2] of WideChar;
begin
if UTF8_CUS<>nil then
begin
i:=1;

BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF16_BS<>nil then
for j:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMBE:
UTF16_BS[j]:=Chr(BOMBEOfUTF16[j]);
BOMLE:
UTF16_BS[j]:=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(j+1)])
end;
j:=BOMSizeOfUTF16
end
else
j:=0;
While UTF8_CUS[i-1]<>#0do
begin
k:=UTF8CUIndexOfChar(UTF8_CUS,i,@k,@charsize);
if k>0 then
begin
if UTF16_BS<>nil then
for k:=0 to CPToUTF16CUS(UTF16_CUS,UTF8CUSToCP(UTF8_CUS,i))-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS[k]));
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS[k]) shr 8)
end
else
begin
UTF16_BS[j]:=Chr(Ord(UTF16_CUS[k]) shr 8);
UTF16_BS[j+1]:=Chr(Ord(UTF16_CUS[k]))
end
end;
j:=j+2
end
else
if charsize<4 then
j:=j+2
else
j:=j+4;
i:=i+charsize
end
else
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end;

if (BOM in NotDefaultBOMSet) and (j>BOMSizeOfUTF16) or (j>0) then
begin
if UTF16_BS<>nil then
UTF16_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-8编码单元序列转UTF-32编码格式字节序列
function UTF8CUSToUTF32BS(UTF8_CUS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j,k,charsize:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF8_CUS<>nil then
begin
i:=1;


BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF32_BS<>nil then
for j:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMBE:
UTF32_BS[j]:=Chr(BOMBEOfUTF32[j]);
BOMLE:
UTF32_BS[j]:=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(j+1)])
end;
j:=BOMSizeOfUTF32
end
else
j:=0;
if UTF32_BS<>nil then
begin
While UTF8_CUS[i-1]<>#0do
begin
k:=UTF8CUIndexOfChar(UTF8_CUS,i,@k,@charsize);
if k>0 then
begin
CP:=UTF8CUSToCP(UTF8_CUS,i);
case BOM of
BOMLE:
for k:=0 to 3do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
else
for k:=3do
wnto 0do
begin
UTF32_BS[j]:=Chr(CP shr (8*k));
inc(j)
end
end;

i:=i+charsize
end
else
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end;

if (BOM in NotDefaultBOMSet) and (j>BOMSizeOfUTF32) or (j>0) then
begin
UTF32_BS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=j+4*CharCountOfUTF8Str(UTF8_CUS)
end
else
Result:=0
end;

// UTF-16编码单元序列转UTF-8编码格式字节序列
function UTF16CUSToUTF8BS(UTF16_CUS:pWideChar;UTF8_BS:pChar):integer;
stdcall;
var
i:integer;
begin
if UTF16_CUS<>nil then
begin
if UTF8_BS<>nil then
begin
for i:=0 to BOMSizeOfUTF8-1do
UTF8_BS:=Chr(BOMOfUTF8);

i:=UTF16ToUTF8ForStr(UTF16_CUS,UTF8_BS+BOMSizeOfUTF8)
end
else
i:=UTF16ToUTF8ForStr(UTF16_CUS,nil);
if i>0 then
begin
i:=BOMSizeOfUTF8+i;
if UTF8_BS<>nil then
UTF8_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// UTF-16编码单元序列转UTF-32编码格式字节序列
function UTF16CUSToUTF32BS(UTF16_CUS:pWideChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
var
i,j:integer;
UTF32Code:DWORD;
BOM:TBOM;
begin
if UTF16_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF32_BS<>nil then
for i:=0 to BOMSizeOfUTF32-1do
case BOM of
BOMBE:
UTF32_BS:=Chr(BOMBEOfUTF32);
BOMLE:
UTF32_BS:=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)])
end;
i:=BOMSizeOfUTF32
end
else
i:=0;
if UTF32_BS<>nil then
begin
While UTF16_CUS^<>#0do
begin
UTF32Code:=UTF16CUSToCP(UTF16_CUS,1);
if UTF32Code<=MaxUnicodeValue then
case BOM of
BOMLE:
for j:=0 to 3do
begin
UTF32_BS:=Chr(UTF32Code shr (8*j));
inc(i)
end
else
for j:=3do
wnto 0do
begin
UTF32_BS:=Chr(UTF32Code shr (8*j));
inc(i)
end
end
else
i:=i+4;
if UTF32Code>MaxBMPCP then
UTF16_CUS:=UTF16_CUS+2
else
inc(UTF16_CUS)
end;

if (BOM in NotDefaultBOMSet) and (i>BOMSizeOfUTF32) or (i>0) then
begin
UTF32_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=i+4*CharCountOfUTF16Str(UTF16_CUS)
end
else
Result:=0
end;

// UTF-32编码单元序列转UTF-8编码格式字节序列
function UTF32CUSToUTF8BS(UTF32_CUS:pDWORD;UTF8_BS:pChar):integer;
stdcall;
var
i:integer;
begin
if UTF32_CUS<>nil then
begin
if UTF8_BS<>nil then
for i:=0 to BOMSizeOfUTF8-1do
UTF8_BS:=Chr(BOMOfUTF8);
i:=BOMSizeOfUTF8;
While UTF32_CUS^<>0do
begin
if UTF8_BS<>nil then
i:=i+CPToUTF8CUS(UTF8_BS+i,UTF32_CUS^)
else
i:=i+CPToUTF8CUS(nil,UTF32_CUS^);
inc(UTF32_CUS)
end;

if i>BOMSizeOfUTF8 then
begin
if UTF8_BS<>nil then
UTF8_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// UTF-32编码单元序列转UTF-16编码格式字节序列
function UTF32CUSToUTF16BS(UTF32_CUS:pDWORD;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
var
i,j:integer;
BOM:TBOM;
UTF16_CUS:array [0..2] of WideChar;
begin
if UTF32_CUS<>nil then
begin
BOM:=TBOM(BOMType);
if BOM in NotDefaultBOMSet then
begin
if UTF16_BS<>nil then
for i:=0 to BOMSizeOfUTF16-1do
case BOM of
BOMBE:
UTF16_BS:=Chr(BOMBEOfUTF16);
BOMLE:
UTF16_BS:=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)])
end;
i:=BOMSizeOfUTF16
end
else
i:=0;
While UTF32_CUS^<>0do
begin
j:=CPToUTF16CUS(UTF16_CUS,UTF32_CUS^);
if UTF16_BS<>nil then
begin
for j:=0 to j-1do
begin
case BOM of
BOMLE:
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]));
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]) shr 8)
end
else
begin
UTF16_BS:=Chr(Ord(UTF16_CUS[j]) shr 8);
UTF16_BS[i+1]:=Chr(Ord(UTF16_CUS[j]))
end
end;
i:=i+2
end
end
else
i:=i+j*2;
inc(UTF32_CUS)
end;

if (BOM in NotDefaultBOMSet) and (i>BOMSizeOfUTF16) or (i>0) then
begin
if UTF16_BS<>nil then
UTF16_BS:=#0;
Result:=i
end
else
Result:=0
end
else
Result:=0
end;

// UTF-8编码格式字节序列转UTF-16编码单元序列
function UTF8BSToUTF16CUS(UTF8_BS:pChar;UTF16_CUS:pWideChar):integer;
stdcall;
begin
if UTF8_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
Result:=UTF8ToUTF16ForStr(UTF8_BS,UTF16_CUS)
end
else
Result:=0
end;

// UTF-8编码格式字节序列转UTF-32编码单元序列
function UTF8BSToUTF32CUS(UTF8_BS:pChar;UTF32_CUS:pDWORD):integer;
stdcall;
begin
if UTF8_BS<>nil then
begin
if UTF8CUSToCP(UTF8_BS,1)=$FEFF then
UTF8_BS:=UTF8_BS+BOMSizeOfUTF8;
Result:=UTF8ToUTF32ForStr(UTF8_BS,UTF32_CUS)
end
else
Result:=0
end;

// UTF-16编码格式字节序列转UTF-8编码单元序列
function UTF16BSToUTF8CUS(UTF16_BS:pChar;Count:integer;UTF8_CUS:pChar):integer;
stdcall;
label 10;
var
i,j,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if UTF16_BS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF16+1
else
i:=1;
j:=0;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
if UTF8_CUS<>nil then
j:=j+UTF16ToUTF8ForChar(CP,1,UTF8_CUS+j)
else
j:=j+UTF16ToUTF8ForChar(CP,1,nil);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if j>0 then
begin
if UTF8_CUS<>nil then
UTF8_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-16编码格式字节序列转UTF-32编码单元序列
function UTF16BSToUTF32CUS(UTF16_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
label 10;
var
i,CodeUnitCount:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
tempp:pDWORD;
begin
if UTF16_BS<>nil then
begin
if UTF32_CUS<>nil then
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF16+1
else
i:=1;
tempp:=UTF32_CUS;
While i<Countdo
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(UTF16_BS) shl 8 + Ord(UTF16_BS[i-1]));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(UTF16_BS[i-1]) shl 8 + Ord(UTF16_BS));
if i<Count-2 then
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
else
CP[1]:=#0
end
end;
10:
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
CodeUnitCount:=1;
HighSurr:
CodeUnitCount:=2
else
begin
inc(i);
Continue
end
end;
tempp^:=UTF16CUSToCP(CP,1);
inc(tempp);
i:=i+CodeUnitCount*2;
if (CodeUnitCount=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(UTF16_BS[i+2]) shl 8 + Ord(UTF16_BS[i+1]))
else
CP[1]:=WideChar(Ord(UTF16_BS[i+1]) shl 8 + Ord(UTF16_BS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

if tempp<>UTF32_CUS then
begin
tempp^:=0;
Result:=(Integer(tempp)-Integer(UTF32_CUS)) div SizeOf(DWORD)
end
else
Result:=0
end
else
Result:=CharCountOfUTF16BS(UTF16_BS,Count) + 1
end
else
Result:=0
end;

// UTF-32编码格式字节序列转UTF-8编码单元序列
function UTF32BSToUTF8CUS(UTF32_BS:pChar;Count:integer;UTF8_CUS:pChar):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF32+1
else
i:=1;
j:=0;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if UTF8_CUS<>nil then
k:=CPToUTF8CUS(UTF8_CUS+j,CP)
else
k:=CPToUTF8CUS(nil,CP);
if k>0 then
begin
j:=j+k;
i:=i+4
end
else
inc(i)
end;

if j>0 then
begin
if UTF8_CUS<>nil then
UTF8_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// UTF-32编码格式字节序列转UTF-16编码单元序列
function UTF32BSToUTF16CUS(UTF32_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if UTF32_BS<>nil then
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
i:=BOMSizeOfUTF32+1
else
i:=1;
j:=0;
While i<Count-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(UTF32_BS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
else
begin
CP:=Ord(UTF32_BS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(UTF32_BS[k])
end
end;

if UTF16_CUS<>nil then
k:=CPToUTF16CUS(UTF16_CUS+j,CP)
else
k:=CPToUTF16CUS(nil,CP);
if k>0 then
begin
j:=j+k;
i:=i+4
end
else
inc(i)
end;

if j>0 then
begin
if UTF16_CUS<>nil then
UTF16_CUS[j]:=#0;
Result:=j
end
else
Result:=0
end
else
Result:=0
end;

// 在一个未知编码格式的字节序列中按照UTF-8编码机制的规则,计算出全部
// 有效字符的字节序列总长度。
function GuessUTF8BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
var
i,j,k,charsize:integer;
begin
if (InputBS<>nil) and (Count<>nil) then
begin
if UTF8CUSToCP(InputBS,1)=$FEFF then
i:=BOMSizeOfUTF8
else
i:=1;
j:=i;

While i<=Count^do
begin
k:=UTF8CUIndexOfChar(InputBS,i,@k,@charsize);
if k>0 then
begin
j:=j+charsize;
i:=i+charsize
end
else
if k=0 then
Break
else
i:=i+(-1*k)+charsize-1
end;

Count^:=i-1;
Result:=j-1
end
else
Result:=0
end;

// 在一个未知编码格式的字节序列中按照UTF-16编码机制的规则,计算出全部
// 有效字符的字节序列总长度。
function GuessUTF16BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
label 10;
var
i,j,charsize:integer;
BOM:TBOM;
CP:array [0..1] of WideChar;
begin
if (InputBS<>nil) and (Count<>nil) then
begin
if Count^>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (InputBS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(InputBS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
begin
i:=BOMSizeOfUTF16+1;
j:=i
end
else
begin
i:=1;
j:=0
end;

While i<=Count^do
begin
case BOM of
BOMLE:
begin
CP[0]:=WideChar(Ord(InputBS) shl 8 + Ord(InputBS[i-1]));
if i<Count^-2 then
CP[1]:=WideChar(Ord(InputBS[i+2]) shl 8 + Ord(InputBS[i+1]))
else
CP[1]:=#0
end
else
begin
CP[0]:=WideChar(Ord(InputBS[i-1]) shl 8 + Ord(InputBS));
if i<Count^-2 then
CP[1]:=WideChar(Ord(InputBS[i+1]) shl 8 + Ord(InputBS[i+2]))
else
CP[1]:=#0
end
end;
10:
if CP[0]<>#0 then
case TUTF16CUT(UTF16CodeUnitType(CP,1)) of
BMPCP:
begin
charsize:=1;
j:=j+2;
i:=i+2
end;
HighSurr:
begin
charsize:=2;
j:=j+4;
i:=i+4
end
else
begin
inc(i);
Continue
end
end
else
Break;
if (charsize=1) and (CP[1]<>#0) then
begin
CP[0]:=CP[1];
if i<Count^-2 then
case BOM of
BOMLE:
CP[1]:=WideChar(Ord(InputBS[i+2]) shl 8 + Ord(InputBS[i+1]))
else
CP[1]:=WideChar(Ord(InputBS[i+1]) shl 8 + Ord(InputBS[i+2]))
end
else
CP[1]:=#0;
goto 10
end
end;

Count^:=i-1;
if BOM<>BOMDefault then
Result:=j-1
else
Result:=j
end
else
Result:=0
end;

// 在一个未知编码格式的字节序列中按照UTF-32编码机制的规则,计算出全部
// 有效字符的字节序列总长度。
function GuessUTF32BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
var
i,j,k:integer;
BOM:TBOM;
CP:DWORD;
begin
if (InputBS<>nil) and (Count<>nil) then
begin
if Count^>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (InputBS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(InputBS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
if BOM<>BOMDefault then
begin
i:=BOMSizeOfUTF32+1;
j:=i
end
else
begin
i:=1;
j:=0
end;

While i<=Count^-2do
begin
case BOM of
BOMLE:
begin
CP:=Ord(InputBS[i+2]);
for k:=i+1do
wnto i-1do
CP:=CP shl 8 + Ord(InputBS[k])
end
else
begin
CP:=Ord(InputBS[i-1]);
for k:=i to i+2do
CP:=CP shl 8 + Ord(InputBS[k])
end
end;

if (CP>0) and (CP<HighSurrStart)
or
(CP>LowSurrEnd) and (CP<=MaxUnicodeValue)
then
begin
j:=j+4;
i:=i+4
end
else
inc(i)
end;

Count^:=i-1;
if BOM<>BOMDefault then
Result:=j-1
else
Result:=j
end
else
Result:=0
end;

// 检测一个UTF-8编码格式字节序列的BOM类型
function BOMTypeOfUTF8BS(UTF8_BS:pChar):integer;
stdcall;
begin
if (Length(UTF8_BS)>BOMSizeOfUTF8) and (UTF8CUSToCP(UTF8_BS,1)=$FEFF) then
Result:=1
else
Result:=0
end;

// 检测一个UTF-16编码格式字节序列的BOM类型
function BOMTypeOfUTF16BS(UTF16_BS:pChar;Count:integer):integer;
stdcall;
var
i:integer;
BOM:TBOM;
begin
if Count>BOMSizeOfUTF16 then
begin
i:=0;
While (i<BOMSizeOfUTF16) and (UTF16_BS=Chr(BOMBEOfUTF16))do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF16)
and
(UTF16_BS=Chr(BOMBEOfUTF16[BOMSizeOfUTF16-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF16 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
Result:=Ord(BOM)
end;

// 检测一个UTF-32编码格式字节序列的BOM类型
function BOMTypeOfUTF32BS(UTF32_BS:pChar;Count:integer):integer;
stdcall;
var
i:integer;
BOM:TBOM;
begin
if Count>BOMSizeOfUTF32 then
begin
i:=0;
While (i<BOMSizeOfUTF32) and (UTF32_BS=Chr(BOMBEOfUTF32))do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMBE
else
begin
i:=0;
While (i<BOMSizeOfUTF32)
and
(UTF32_BS=Chr(BOMBEOfUTF32[BOMSizeOfUTF32-(i+1)]))
do
inc(i);
if i>=BOMSizeOfUTF32 then
BOM:=BOMLE
else
BOM:=BOMDefault
end
end
else
BOM:=BOMDefault;
Result:=Ord(BOM)
end;

// “猜测”一个未知编码格式字节序列所使用的Unicode编码机制
function GuessBSType(InputBS:pChar;Count:pInteger;
GuessSuccPercent:integer):integer;
stdcall;
var
i,j:integer;
SuccPercent:real;
BSType:TBSType;
begin
if Count<>nil then
begin
if (GuessSuccPercent>0) and (GuessSuccPercent<=100) then
SuccPercent:=GuessSuccPercent/100
else
SuccPercent:=0.8;
i:=Count^;
j:=GuessUTF8BSAvaiByteCount(InputBS,Count);
if (j>0) and (Count^>0) and (j/Count^>=SuccPercent) then
begin
if BOMTypeOfUTF8BS(InputBS)=1 then
BSType:=BS_UTF8WithBOM
else
BSType:=BS_UTF8WithoutBOM
end
else
begin
Count^:=i;
j:=GuessUTF16BSAvaiByteCount(InputBS,Count);
if (j>0) and (Count^>0) and (j/Count^>=SuccPercent) then
begin
case TBOM(BOMTypeOfUTF16BS(InputBS,Count^)) of
BOMBE:
BSType:=BS_UTF16BE;
BOMLE:
BSType:=BS_UTF16LE
else
BSType:=BS_UTF16Default
end
end
else
begin
Count^:=i;
j:=GuessUTF32BSAvaiByteCount(InputBS,Count);
if (j>0) and (Count^>0) and (j/Count^>=SuccPercent) then
begin
case TBOM(BOMTypeOfUTF32BS(InputBS,Count^)) of
BOMBE:
BSType:=BS_UTF32BE;
BOMLE:
BSType:=BS_UTF32LE
else
BSType:=BS_UTF32Default
end
end
else
BSType:=BS_Unknow
end
end
end
else
BSType:=BS_Unknow;
Result:=Integer(BSType)
end;

// Unicode编码格式字节序列写出到文本文件
function SaveUniByteSequToFile(ByteSequ:pChar;OutputCount:integer;
FileName:pWideChar):BOOL;
stdcall;
var
fs:TTntFileStream;
begin
if ByteSequ<>nil then
begin
Try
fs:=TTntFileStream.Create(FileName,fmCreate);
fs.Write(ByteSequ^,OutputCount);
fs.Free;
Result:=true
except
Result:=false
end
end
else
Result:=false
end;

// 从文本文件中读入Unicode编码格式字节序列
function LoadUniByteSequFromFile(FileName:pWideChar;Count:pInteger;
ByteSequ:pChar;BSType:pInteger):integer;
stdcall;
var
fs:TTntFileStream;
begin
if (ByteSequ=nil) and (Count<>nil) and (BSType<>nil) then
begin
Try
fs:=TTntFileStream.Create(FileName,fmOpenRead);
if fs.Size>0 then
begin
SetLength(TempBS,fs.Size);
TempInt:=fs.Read(TempBS[1],fs.Size)
end
else
TempInt:=0;
if (Count^<=0) or (Count^>fs.Size) then
Count^:=fs.Size;
fs.Free
except
Result:=0;
exit
end;
BSType^:=GuessBSType(Pointer(TempBS),Count,0);
if BSType^<>BSType_Unknow then
Result:=TempInt
else
begin
SetLength(TempBS,0);
Result:=0
end
end
else
if ByteSequ<>nil then
begin
StrMove(ByteSequ,Pointer(TempBS),TempInt);
SetLength(TempBS,0);
Result:=TempInt
end
else
begin
SetLength(TempBS,0);
Result:=0
end
end;

// **** Unicode编码机制处理例程(结束) ****
exports
UTF16CodeUnitType,
UTF16CUIndexOfChar,
UTF16CUToCharIndex,
UTF16CharToCUIndex,
CPToUTF16CUS,
UTF16CUSToCP,
SurrPairToCP,
CPToSurrPair,
UTF8CUIndexOfChar,
UTF8CUToCharIndex,
UTF8CharToCUIndex,
CPToUTF8CUS,
UTF8CUSToCP,
GetCPPartIndexOfUTF8,
GetByteLenOfVCLWideString,
UTF16ToUTF8ForChar,
UTF8ToUTF16ForChar,
UTF16ToUTF8ForStr,
UTF8ToUTF16ForStr,
CharCountOfUTF16Str,
CharCountOfUTF8Str,
CharCountOfUTF32Str,
UTF16ToUTF32ForStr,
UTF32ToUTF16ForStr,
UTF8ToUTF32ForStr,
UTF32ToUTF8ForStr,
CUSToBSForUTF8,
BSToCUSForUTF8,
CUSToBSForUTF16,
BSToCUSForUTF16,
CUSToBSForUTF32,
CharCountOfUTF8BS,
CharCountOfUTF16BS,
CharCountOfUTF32BS,
BSToCUSForUTF32,
UTF8ToUTF16ForBS,
UTF8ToUTF32ForBS,
UTF16ToUTF8ForBS,
UTF16ToUTF32ForBS,
UTF32ToUTF8ForBS,
UTF32ToUTF16ForBS,
UTF8CUSToUTF16BS,
UTF8CUSToUTF32BS,
UTF16CUSToUTF8BS,
UTF16CUSToUTF32BS,
UTF32CUSToUTF8BS,
UTF32CUSToUTF16BS,
UTF8BSToUTF16CUS,
UTF8BSToUTF32CUS,
UTF16BSToUTF8CUS,
UTF16BSToUTF32CUS,
UTF32BSToUTF8CUS,
UTF32BSToUTF16CUS,
GuessUTF8BSAvaiByteCount,
GuessUTF16BSAvaiByteCount,
GuessUTF32BSAvaiByteCount,
BOMTypeOfUTF8BS,
BOMTypeOfUTF16BS,
BOMTypeOfUTF32BS,
GuessBSType,
SaveUniByteSequToFile,
LoadUniByteSequFromFile;
begin
end.
//////////////////////////xcUCSDLLDynaUnit.pas//////////////////////////////
unit xcUCSDLLDynaUnit;
// Unicode文本(字符串)处理
// 动态链接库--xcUCSStrRoutines.dll 的动态调用接口单元。
interface
uses Types,xcUCSRLDataStruUni,Windows;
const
DLLName='xcUCSStrRoutines.dll';
// **** 接口函数名(开始) ****
FnUTF16CodeUnitType='UTF16CodeUnitType';
FnUTF16CUIndexOfChar='UTF16CUIndexOfChar';
FnUTF16CUToCharIndex='UTF16CUToCharIndex';
FnUTF16CharToCUIndex='UTF16CharToCUIndex';
FnCPToUTF16CUS='CPToUTF16CUS';
FnUTF16CUSToCP='UTF16CUSToCP';
FnSurrPairToCP='SurrPairToCP';
FnCPToSurrPair='CPToSurrPair';
FnCPToUTF8CUS='CPToUTF8CUS';
FnUTF8CUSToCP='UTF8CUSToCP';
FnUTF8CUIndexOfChar='UTF8CUIndexOfChar';
FnUTF8CUToCharIndex='UTF8CUToCharIndex';
FnUTF8CharToCUIndex='UTF8CharToCUIndex';
FnGetCPPartIndexOfUTF8='GetCPPartIndexOfUTF8';
FnGetByteLenOfVCLWideString='GetByteLenOfVCLWideString';
FnUTF16ToUTF8ForChar='UTF16ToUTF8ForChar';
FnUTF8ToUTF16ForChar='UTF8ToUTF16ForChar';
FnUTF16ToUTF8ForStr='UTF16ToUTF8ForStr';
FnUTF8ToUTF16ForStr='UTF8ToUTF16ForStr';
FnCharCountOfUTF16Str='CharCountOfUTF16Str';
FnCharCountOfUTF8Str='CharCountOfUTF8Str';
FnCharCountOfUTF32Str='CharCountOfUTF32Str';
FnUTF16ToUTF32ForStr='UTF16ToUTF32ForStr';
FnUTF32ToUTF16ForStr='UTF32ToUTF16ForStr';
FnUTF8ToUTF32ForStr='UTF8ToUTF32ForStr';
FnUTF32ToUTF8ForStr='UTF32ToUTF8ForStr';
FnCUSToBSForUTF8='CUSToBSForUTF8';
FnBSToCUSForUTF8='BSToCUSForUTF8';
FnCUSToBSForUTF16='CUSToBSForUTF16';
FnBSToCUSForUTF16='BSToCUSForUTF16';
FnCUSToBSForUTF32='CUSToBSForUTF32';
FnCharCountOfUTF8BS='CharCountOfUTF8BS';
FnCharCountOfUTF16BS='CharCountOfUTF16BS';
FnCharCountOfUTF32BS='CharCountOfUTF32BS';
FnBSToCUSForUTF32='BSToCUSForUTF32';
FnUTF8ToUTF16ForBS='UTF8ToUTF16ForBS';
FnUTF8ToUTF32ForBS='UTF8ToUTF32ForBS';
FnUTF16ToUTF32ForBS='UTF16ToUTF32ForBS';
FnUTF16ToUTF8ForBS='UTF16ToUTF8ForBS';
FnUTF32ToUTF8ForBS='UTF32ToUTF8ForBS';
FnUTF32ToUTF16ForBS='UTF32ToUTF16ForBS';
FnUTF8CUSToUTF16BS='UTF8CUSToUTF16BS';
FnUTF8CUSToUTF32BS='UTF8CUSToUTF32BS';
FnUTF16CUSToUTF8BS='UTF16CUSToUTF8BS';
FnUTF16CUSToUTF32BS='UTF16CUSToUTF32BS';
FnUTF32CUSToUTF8BS='UTF32CUSToUTF8BS';
FnUTF32CUSToUTF16BS='UTF32CUSToUTF16BS';
FnUTF8BSToUTF16CUS='UTF8BSToUTF16CUS';
FnUTF8BSToUTF32CUS='UTF8BSToUTF32CUS';
FnUTF16BSToUTF8CUS='UTF16BSToUTF8CUS';
FnUTF16BSToUTF32CUS='UTF16BSToUTF32CUS';
FnUTF32BSToUTF8CUS='UTF32BSToUTF8CUS';
FnUTF32BSToUTF16CUS='UTF32BSToUTF16CUS';
FnGuessUTF8BSAvaiByteCount='GuessUTF8BSAvaiByteCount';
FnGuessUTF16BSAvaiByteCount='GuessUTF16BSAvaiByteCount';
FnGuessUTF32BSAvaiByteCount='GuessUTF32BSAvaiByteCount';
FnBOMTypeOfUTF8BS='BOMTypeOfUTF8BS';
FnBOMTypeOfUTF16BS='BOMTypeOfUTF16BS';
FnBOMTypeOfUTF32BS='BOMTypeOfUTF32BS';
FnGuessBSType='GuessBSType';
FnSaveUniByteSequToFile='SaveUniByteSequToFile';
FnLoadUniByteSequFromFile='LoadUniByteSequFromFile';
// **** 接口函数名(结束) ****
type
// 判断UTF-16编码格式字符串中指定位置编码单元的类型:
// 0 表示 无效编码单元
// 1 表示 BMP字符
// 2 表示 高位代理
// 3 表示 低位代理
TUTF16CodeUnitType=function (UTF16Str:pWideChar;Index:integer):integer;
stdcall;
TUTF16CUIndexOfChar=function (UTF16Str:pWideChar;Index:integer;
CharSize:pInteger):integer;
stdcall;
TUTF16CUToCharIndex=function (UTF16Str:pWideChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
TUTF16CharToCUIndex=function (UTF16Str:pWideChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
TCPToUTF16CUS=function (UTF16Str:pWideChar;Code:DWORD):integer;
stdcall;
TUTF16CUSToCP=function (UTF16Str:pWideChar;Index:integer):DWORD;
stdcall;
TSurrPairToCP=function (HighSurr,LowSurr:WORD):DWORD;
stdcall;
TCPToSurrPair=function (UnicodeValue:DWORD):DWORD;
stdcall;
TCPToUTF8CUS=function (UTF8Str:pChar;Code:DWORD):integer;
stdcall;
TUTF8CUSToCP=function (UTF8Str:pChar;Index:integer):DWORD;
stdcall;
TUTF8CUIndexOfChar=function (UTF8Str:pChar;Index:integer;
CPPartIndexOfUTF8,CharSize:pInteger):integer;
stdcall;
TUTF8CUToCharIndex=function (UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
TUTF8CharToCUIndex=function (UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
TGetCPPartIndexOfUTF8=function (Code:DWORD;
PCPPartOfUTF8Info:TPCPPartOfUTF8Info):integer;
stdcall;
TGetByteLenOfVCLWideString=function (S:pWideChar):integer;
stdcall;
TUTF16ToUTF8ForChar=function (UTF16Str:pWideChar;Index:integer;
UTF8Str:pChar):integer;
stdcall;
TUTF8ToUTF16ForChar=function (UTF8Str:pChar;Index:integer;
UTF16Str:pWideChar):integer;
stdcall;
TUTF16ToUTF8ForStr=function (UTF16Str:pWideChar;UTF8Str:pChar):integer;
stdcall;
TUTF8ToUTF16ForStr=function (UTF8Str:pChar;UTF16Str:pWideChar):integer;
stdcall;
TCharCountOfUTF16Str=function (UTF16Str:pWideChar):integer;
stdcall;
TCharCountOfUTF8Str=function (UTF8Str:pChar):integer;
stdcall;
TCharCountOfUTF32Str=function (UTF32:pDWORD):integer;
stdcall;
TUTF16ToUTF32ForStr=function (UTF16Str:pWideChar;UTF32Str:pDWORD):integer;
stdcall;
TUTF32ToUTF16ForStr=function (UTF32Str:pDWORD;UTF16Str:pWideChar):integer;
stdcall;
TUTF8ToUTF32ForStr=function (UTF8Str:pChar;UTF32Str:pDWORD):integer;
stdcall;
TUTF32ToUTF8ForStr=function (UTF32Str:pDWORD;UTF8Str:pChar):integer;
stdcall;
TCUSToBSForUTF8=function (UTF8_CUS,UTF8_BS:pChar):integer;
stdcall;
TBSToCUSForUTF8=function (UTF8_BS,UTF8_CUS:pChar):integer;
stdcall;
TCUSToBSForUTF16=function (UTF16_CUS:pWideChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
TBSToCUSForUTF16=function (UTF16_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
TCUSToBSForUTF32=function (UTF32_CUS:pDWORD;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
TCharCountOfUTF8BS=function (UTF8_BS:pChar):integer;
stdcall;
TCharCountOfUTF16BS=function (UTF16_BS:pChar;Count:integer):integer;
stdcall;
TCharCountOfUTF32BS=function (UTF32_BS:pChar;Count:integer):integer;
stdcall;

TBSToCUSForUTF32=function (UTF32_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
TUTF8ToUTF16ForBS=function (UTF8_BS:pChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
TUTF8ToUTF32ForBS=function (UTF8_BS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
TUTF16ToUTF8ForBS=function (UTF16_BS:pChar;Count:integer;
UTF8_BS:pChar):integer;
stdcall;
TUTF16ToUTF32ForBS=function (UTF16_BS:pChar;Count,BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
TSaveUniByteSequToFile=function (ByteSequ:pChar;OutputCount:integer;
FileName:pWideChar):BOOL;
stdcall;
TUTF32ToUTF8ForBS=function (UTF32_BS:pChar;Count:integer;
UTF8_BS:pChar):integer;
stdcall;
TUTF32ToUTF16ForBS=function (UTF32_BS:pChar;Count,BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
TUTF8CUSToUTF16BS=function (UTF8_CUS:pChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
TUTF8CUSToUTF32BS=function (UTF8_CUS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
TUTF16CUSToUTF8BS=function (UTF16_CUS:pWideChar;UTF8_BS:pChar):integer;
stdcall;
TUTF16CUSToUTF32BS=function (UTF16_CUS:pWideChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
TUTF32CUSToUTF8BS=function (UTF32_CUS:pDWORD;UTF8_BS:pChar):integer;
stdcall;
TUTF32CUSToUTF16BS=function (UTF32_CUS:pDWORD;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
TUTF8BSToUTF16CUS=function (UTF8_BS:pChar;UTF16_CUS:pWideChar):integer;
stdcall;
TUTF8BSToUTF32CUS=function (UTF8_BS:pChar;UTF32_CUS:pDWORD):integer;
stdcall;
TUTF16BSToUTF8CUS=function (UTF16_BS:pChar;Count:integer;
UTF8_CUS:pChar):integer;
stdcall;
TUTF16BSToUTF32CUS=function (UTF16_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
TUTF32BSToUTF8CUS=function (UTF32_BS:pChar;Count:integer;
UTF8_CUS:pChar):integer;
stdcall;
TUTF32BSToUTF16CUS=function (UTF32_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
TGuessUTF8BSAvaiByteCount=function (InputBS:pChar;Count:pInteger):integer;
stdcall;
TGuessUTF16BSAvaiByteCount=function (InputBS:pChar;Count:pInteger):integer;
stdcall;
TGuessUTF32BSAvaiByteCount=function (InputBS:pChar;Count:pInteger):integer;
stdcall;
TBOMTypeOfUTF8BS=function (UTF8_BS:pChar):integer;
stdcall;
TBOMTypeOfUTF16BS=function (UTF16_BS:pChar;Count:integer):integer;
stdcall;
TBOMTypeOfUTF32BS=function (UTF32_BS:pChar;Count:integer):integer;
stdcall;
TGuessBSType=function (InputBS:pChar;Count:pInteger;
GuessSuccPercent:integer):integer;
stdcall;
TLoadUniByteSequFromFile=function (FileName:pWideChar;Count:pInteger;
ByteSequ:pChar;BSType:pInteger):integer;
stdcall;
implementation
end.
///////////////////////// xcUCSDLLStatUnit.pas///////////////////////////
unit xcUCSDLLStatUnit;
// Unicode文本(字符串)处理
// 动态链接库--xcUCSStrRoutines.dll 的静态调用接口单元。
interface
uses Types,xcUCSRLDataStruUnit,Windows;

const
DLLName='xcUCSStrRoutines.dll';
// 判断UTF-16编码格式字符串中指定位置编码单元的类型:
// 0 表示 无效编码单元
// 1 表示 BMP字符
// 2 表示 高位代理
// 3 表示 低位代理
function UTF16CodeUnitType(UTF16Str:pWideChar;Index:integer):integer;
stdcall;
external DLLName;
function UTF16CUIndexOfChar(UTF16Str:pWideChar;Index:integer;
CharSize:pInteger):integer;
stdcall;
external DLLName;
function UTF16CUToCharIndex(UTF16Str:pWideChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
external DLLName;
function UTF16CharToCUIndex(UTF16Str:pWideChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
external DLLName;
function CPToUTF16CUS(UTF16Str:pWideChar;Code:DWORD):integer;
stdcall;
external DLLName;
function UTF16CUSToCP(UTF16Str:pWideChar;Index:integer):DWORD;
stdcall;
external DLLName;
function SurrPairToCP(HighSurr,LowSurr:WORD):DWORD;
stdcall;
external DLLName;
function CPToSurrPair(UnicodeValue:DWORD):DWORD;
stdcall;
external DLLName;
function UTF8CUIndexOfChar(UTF8Str:pChar;Index:integer;
CPPartIndexOfUTF8,CharSize:pInteger):integer;
stdcall;
external DLLName;
function UTF8CUToCharIndex(UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
external DLLName;
function UTF8CharToCUIndex(UTF8Str:pChar;Index:integer;
IgnoInvalCU:BOOL):integer;
stdcall;
external DLLName;
function CPToUTF8CUS(UTF8Str:pChar;Code:DWORD):integer;
stdcall;
external DLLName;
function UTF8CUSToCP(UTF8Str:pChar;Index:integer):DWORD;
stdcall;
external DLLName;
function GetCPPartIndexOfUTF8(Code:DWORD;
PCPPartOfUTF8Info:TPCPPartOfUTF8Info):integer;
stdcall;
external DLLName;
function GetByteLenOfVCLWideString(S:pWideChar):integer;
stdcall;
external DLLName;
function UTF16ToUTF8ForChar(UTF16Str:pWideChar;Index:integer;
UTF8Str:pChar):integer;
stdcall;
external DLLName;
function UTF8ToUTF16ForChar(UTF8Str:pChar;Index:integer;
UTF16Str:pWideChar):integer;
stdcall;
external DLLName;
function UTF16ToUTF8ForStr(UTF16Str:pWideChar;UTF8Str:pChar):integer;
stdcall;
external DLLName;
function UTF8ToUTF16ForStr(UTF8Str:pChar;UTF16Str:pWideChar):integer;
stdcall;
external DLLName;
function CharCountOfUTF16Str(UTF16Str:pWideChar):integer;
stdcall;
external DLLName;
function CharCountOfUTF8Str(UTF8Str:pChar):integer;
stdcall;
external DLLName;
function CharCountOfUTF32Str(UTF32:pDWORD):integer;
stdcall;
external DLLName;
function UTF16ToUTF32ForStr(UTF16Str:pWideChar;UTF32Str:pDWORD):integer;
stdcall;
external DLLName;
function UTF32ToUTF16ForStr(UTF32Str:pDWORD;UTF16Str:pWideChar):integer;
stdcall;
external DLLName;
function UTF8ToUTF32ForStr(UTF8Str:pChar;UTF32Str:pDWORD):integer;
stdcall;
external DLLName;
function UTF32ToUTF8ForStr(UTF32Str:pDWORD;UTF8Str:pChar):integer;
stdcall;
external DLLName;
function CUSToBSForUTF8(UTF8_CUS,UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function BSToCUSForUTF8(UTF8_BS,UTF8_CUS:pChar):integer;
stdcall;
external DLLName;
function CUSToBSForUTF16(UTF16_CUS:pWideChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
external DLLName;
function BSToCUSForUTF16(UTF16_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
external DLLName;
function CUSToBSForUTF32(UTF32_CUS:pDWORD;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
external DLLName;
function CharCountOfUTF8BS(UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function CharCountOfUTF16BS(UTF16_BS:pChar;Count:integer):integer;
stdcall;
external DLLName;
function CharCountOfUTF32BS(UTF32_BS:pChar;Count:integer):integer;
stdcall;
external DLLName;
function BSToCUSForUTF32(UTF32_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
external DLLName;
function UTF8ToUTF16ForBS(UTF8_BS:pChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
external DLLName;
function UTF8ToUTF32ForBS(UTF8_BS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
external DLLName;
function UTF16ToUTF8ForBS(UTF16_BS:pChar;Count:integer;UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function UTF16ToUTF32ForBS(UTF16_BS:pChar;Count,BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
external DLLName;
function SaveUniByteSequToFile(ByteSequ:pChar;OutputCount:integer;
FileName:pWideChar):BOOL;
stdcall;
external DLLName;
function UTF32ToUTF8ForBS(UTF32_BS:pChar;Count:integer;UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function UTF32ToUTF16ForBS(UTF32_BS:pChar;Count,BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
external DLLName;
function UTF8CUSToUTF16BS(UTF8_CUS:pChar;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
external DLLName;
function UTF8CUSToUTF32BS(UTF8_CUS:pChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
external DLLName;
function UTF16CUSToUTF8BS(UTF16_CUS:pWideChar;UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function UTF16CUSToUTF32BS(UTF16_CUS:pWideChar;BOMType:integer;
UTF32_BS:pChar):integer;
stdcall;
external DLLName;
function UTF32CUSToUTF8BS(UTF32_CUS:pDWORD;UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function UTF32CUSToUTF16BS(UTF32_CUS:pDWORD;BOMType:integer;
UTF16_BS:pChar):integer;
stdcall;
external DLLName;
function UTF8BSToUTF16CUS(UTF8_BS:pChar;UTF16_CUS:pWideChar):integer;
stdcall;
external DLLName;
function UTF8BSToUTF32CUS(UTF8_BS:pChar;UTF32_CUS:pDWORD):integer;
stdcall;
external DLLName;
function UTF16BSToUTF8CUS(UTF16_BS:pChar;Count:integer;
UTF8_CUS:pChar):integer;
stdcall;
external DLLName;
function UTF16BSToUTF32CUS(UTF16_BS:pChar;Count:integer;
UTF32_CUS:pDWORD):integer;
stdcall;
external DLLName;
function UTF32BSToUTF8CUS(UTF32_BS:pChar;Count:integer;
UTF8_CUS:pChar):integer;
stdcall;
external DLLName;
function UTF32BSToUTF16CUS(UTF32_BS:pChar;Count:integer;
UTF16_CUS:pWideChar):integer;
stdcall;
external DLLName;
function GuessUTF8BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
external DLLName;
function GuessUTF16BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
external DLLName;
function GuessUTF32BSAvaiByteCount(InputBS:pChar;Count:pInteger):integer;
stdcall;
external DLLName;
function BOMTypeOfUTF8BS(UTF8_BS:pChar):integer;
stdcall;
external DLLName;
function BOMTypeOfUTF16BS(UTF16_BS:pChar;Count:integer):integer;
stdcall;
external DLLName;
function BOMTypeOfUTF32BS(UTF32_BS:pChar;Count:integer):integer;
stdcall;
external DLLName;
function GuessBSType(InputBS:pChar;Count:pInteger;
GuessSuccPercent:integer):integer;
stdcall;
external DLLName;
function LoadUniByteSequFromFile(FileName:pWideChar;Count:pInteger;
ByteSequ:pChar;BSType:pInteger):integer;
stdcall;
external DLLName;
implementation
end.
///////////////////////////xcUCSRLDataStruUnit.pas/////////////////////////
unit xcUCSRLDataStruUnit;
// Unicode文本(字符串)处理
// 动态链接库--xcUCSStrRoutines.dll 的数据结构接口单元。
interface
uses Types;
const
// **** UTF-16编码格式管理数据(开始) ****
MaxBMPCP=$FFFF;
// BMP编码点最大取值
MaxUnicodeValue=$10FFFF;
// Unicode编码点数字最大取值
HighSurrStart=$D800;
// 高位代理取值范围下限
HighSurrEnd=$DBFF;
// 高位代理取值范围上限
LowSurrStart=$DC00;
// 低位代理取值范围下限
LowSurrEnd=$DFFF;
// 低位代理取值范围上限
// **** UTF-16编码格式管理数据(结束) ****
// **** UTF-16编码单元类型(开始) ****
UTF16CUT_InvalCodeUnit=0;
// 无效编码单元
UTF16CUT_BMPCP=1;
// BMP编码点
UTF16CUT_HighSurr=2;
// 高位代理
UTF16CUT_LowSurr=3;
// 低位代理
// **** UTF-16编码单元类型(结束) ****
// **** UTF-8编码格式管理数据(开始) ****
CPPartCountOfUTF8=9;
// UTF-8编码格式对Unicode编码点的分段数量
MaxCodeUnitCountOfUTF8=4;
// 单个编码点所需的最大UTF-8编码单元数量
// **** UTF-8编码格式管理数据(结束) ****
// **** Unicode编码格式字节序列BOM标识常量(开始) ****
BOMType_Default=0;
// 默认字节序
BOMType_BE=1;
// 大尾字节序
BOMType_LE=2;
// 小尾字节序
// **** Unicode编码格式字节序列BOM标识常量(结束) ****
// **** BOM管理数据(开始) ****
BOMSizeOfUTF8=3;
// UTF-8 BOM 的长度
BOMSizeOfUTF16=2;
// UTF-16 BOM 的长度
BOMSizeOfUTF32=4;
// UTF-32 BOM 的长度
// **** BOM管理数据(结束) ****
// **** Unicode编码机制类型标识常量(开始) ****
BSType_Unknow=0;
// 未知类型字节序列
BSType_UTF8WithBOM=1;
// 带BOM的UTF-8编码格式字节序列
BSType_UTF8WithoutBOM=2;
// 不带BOM的UTF-8编码格式字节序列
BSType_UTF16Default=3;
// 不带BOM的UTF-16编码格式字节序列
BSType_UTF16BE=4;
// 带有大尾字节序BOM的UTF-16编码格式字节序列
BSType_UTF16LE=5;
// 带有小尾字节序BOM的UTF-16编码格式字节序列
BSType_UTF32Default=6;
// 不带BOM的UTF-32编码格式字节序列
BSType_UTF32BE=7;
// 带有大尾字节序BOM的UTF-32编码格式字节序列
BSType_UTF32LE=8;
// 带有小尾字节序BOM的UTF-32编码格式字节序列
// **** Unicode编码机制类型标识常量(结束) ****
type
TUTF16CUT=( // UTF-16编码单元类型
InvalCodeUnit, // 无效编码单元
BMPCP, // BMP编码点
HighSurr, // 高位代理
LowSurr // 低位代理
);
// **** UTF-8编码格式管理信息(开始) ****
// UTF-8编码格式对Unicode编码点的分段的具体编码区间类型
TCPPartOfUTF8CodeRange=
Record
MinCode,MaxCode:DWORD
end;

// UTF-8编码单元的取值范围类型
TCUValueRangeOfUTF8=
Record
MinValue,MaxValue:Byte
end;

// 各编码单元的取值范围类型
TCUValueRange=array [0..MaxCodeUnitCountOfUTF8-1] of TCUValueRangeOfUTF8;
// UTF-8编码格式对Unicode编码点的分段的信息类型
TCPPartOfUTF8Info=
Record
// 分段的编码点区间
CodeRange:TCPPartOfUTF8CodeRange;

CUValueRange:TCUValueRange // 各编码单元的取值范围
end;
// 指向UTF-8编码格式对Unicode编码点的分段的信息的指针类型
TPCPPartOfUTF8Info=^TCPPartOfUTF8Info;
// **** UTF-8编码格式管理信息(结束) ****
TBOM=( // BOM类型
BOMDefault, // 默认字节序
BOMBE, // 大尾字节序
BOMLE // 小尾字节序
);
TBSType=( // 编码机制类型
BS_Unknow, // 未知类型字节序列
BS_UTF8WithoutBOM, // 不带BOM的UTF-8编码格式字节序列
BS_UTF8WithBOM, // 带BOM的UTF-8编码格式字节序列
BS_UTF16Default, // 不带BOM的UTF-16编码格式字节序列
BS_UTF16BE, // 带有大尾字节序BOM的UTF-16编码格式字节序列
BS_UTF16LE, // 带有小尾字节序BOM的UTF-16编码格式字节序列
BS_UTF32Default, // 不带BOM的UTF-32编码格式字节序列
BS_UTF32BE, // 带有大尾字节序BOM的UTF-32编码格式字节序列
BS_UTF32LE // 带有小尾字节序BOM的UTF-32编码格式字节序列
);

const
// 无效UTF-8格式编码单元集合
InvalUTF8CUSet:set of Byte=[$C0..$C1,$F5..$FF];
// 非默认BOM类型集合
NotDefaultBOMSet:set of TBOM=[BOMBE..BOMLE];
// UTF-8 BOM
BOMOfUTF8:array [0..BOMSizeOfUTF8-1] of Byte=($EF,$BB,$BF);
// UTF-16 BOMBE
BOMBEOfUTF16:array [0..BOMSizeOfUTF16-1] of Byte=($FE,$FF);
// UTF-32 BOMBE
BOMBEOfUTF32:array [0..BOMSizeOfUTF32-1] of Byte=($00,$00,$FE,$FF);
implementation
end.
 
UCS瑞士军刀演武堂
//////////////////////////UCSRLTestbed.dpr/////////////////////////////
program UCSRLTestbed;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.Title := 'UCSRLTestbed';
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
///////////////////////////////Unit1.pas///////////////////////////////////
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TntForms, ComCtrls, TntComCtrls, StdCtrls, TntStdCtrls,
xcUCSRLDataStruUnit, xcUCSDLLStatUnit, TntSysUtils, TntDialogs;
type
TForm1 = class(TTntForm)
TntPageControl1: TTntPageControl;
TntTabSheet1: TTntTabSheet;
TntTabSheet2: TTntTabSheet;
TntTabSheet3: TTntTabSheet;
TntTabSheet4: TTntTabSheet;
TntPageControl2: TTntPageControl;
TntTabSheet5: TTntTabSheet;
TntTabSheet6: TTntTabSheet;
TntTabSheet7: TTntTabSheet;
TntTabSheet8: TTntTabSheet;
TntRichEdit1: TTntRichEdit;
TntGroupBox1: TTntGroupBox;
TntRadioButton1: TTntRadioButton;
TntRadioButton2: TTntRadioButton;
TntButton1: TTntButton;
Edit1: TEdit;
TntGroupBox2: TTntGroupBox;
TntRadioButton3: TTntRadioButton;
TntRadioButton4: TTntRadioButton;
TntButton2: TTntButton;
Edit2: TEdit;
TntGroupBox3: TTntGroupBox;
Edit3: TEdit;
TntButton3: TTntButton;
TntGroupBox4: TTntGroupBox;
Edit4: TEdit;
TntButton4: TTntButton;
TntGroupBox5: TTntGroupBox;
TntRadioButton5: TTntRadioButton;
TntRadioButton6: TTntRadioButton;
TntButton5: TTntButton;
Edit5: TEdit;
TntGroupBox6: TTntGroupBox;
Edit6: TEdit;
TntButton6: TTntButton;
TntGroupBox7: TTntGroupBox;
Edit7: TEdit;
TntButton7: TTntButton;
Edit8: TEdit;
TntRichEdit2: TTntRichEdit;
TntRichEdit3: TTntRichEdit;
TntGroupBox8: TTntGroupBox;
TntRadioButton7: TTntRadioButton;
TntRadioButton8: TTntRadioButton;
TntButton8: TTntButton;
Edit9: TEdit;
TntGroupBox9: TTntGroupBox;
TntRadioButton9: TTntRadioButton;
TntRadioButton10: TTntRadioButton;
TntButton9: TTntButton;
Edit10: TEdit;
TntGroupBox10: TTntGroupBox;
TntRadioButton11: TTntRadioButton;
TntRadioButton12: TTntRadioButton;
TntButton10: TTntButton;
Edit11: TEdit;
TntGroupBox11: TTntGroupBox;
Edit12: TEdit;
TntButton11: TTntButton;
TntGroupBox12: TTntGroupBox;
Edit13: TEdit;
TntButton12: TTntButton;
TntGroupBox13: TTntGroupBox;
TntRadioButton13: TTntRadioButton;
TntRadioButton14: TTntRadioButton;
TntButton13: TTntButton;
Edit14: TEdit;
TntRichEdit4: TTntRichEdit;
TntRadioButton15: TTntRadioButton;
TntRadioButton16: TTntRadioButton;
TntRichEdit5: TTntRichEdit;
TntRichEdit6: TTntRichEdit;
TntOpenDialog1: TTntOpenDialog;
TntSaveDialog1: TTntSaveDialog;
TntGroupBox14: TTntGroupBox;
TntRadioButton17: TTntRadioButton;
TntRadioButton18: TTntRadioButton;
TntButton14: TTntButton;
Edit15: TEdit;
TntRadioButton19: TTntRadioButton;
TntGroupBox15: TTntGroupBox;
TntRadioButton20: TTntRadioButton;
TntRadioButton21: TTntRadioButton;
TntButton15: TTntButton;
Edit16: TEdit;
TntRadioButton22: TTntRadioButton;
TntGroupBox16: TTntGroupBox;
TntButton16: TTntButton;
TntRadioButton23: TTntRadioButton;
TntGroupBox17: TTntGroupBox;
TntButton17: TTntButton;
TntRadioButton24: TTntRadioButton;
TntGroupBox18: TTntGroupBox;
TntButton18: TTntButton;
TntRadioButton25: TTntRadioButton;
TntGroupBox19: TTntGroupBox;
TntButton19: TTntButton;
TntGroupBox20: TTntGroupBox;
TntButton20: TTntButton;
TntRadioButton26: TTntRadioButton;
TntRadioButton27: TTntRadioButton;
TntGroupBox21: TTntGroupBox;
TntButton21: TTntButton;
TntRadioButton28: TTntRadioButton;
TntRichEdit7: TTntRichEdit;
TntRichEdit8: TTntRichEdit;
TntGroupBox22: TTntGroupBox;
TntButton22: TTntButton;
TntRadioButton29: TTntRadioButton;
TntGroupBox23: TTntGroupBox;
TntButton23: TTntButton;
TntRadioButton30: TTntRadioButton;
TntGroupBox24: TTntGroupBox;
TntButton24: TTntButton;
TntRadioButton31: TTntRadioButton;
TntPageControl3: TTntPageControl;
TntTabSheet9: TTntTabSheet;
TntTabSheet10: TTntTabSheet;
TntTabSheet11: TTntTabSheet;
TntRichEdit9: TTntRichEdit;
TntRichEdit10: TTntRichEdit;
TntGroupBox25: TTntGroupBox;
TntButton25: TTntButton;
TntRadioButton32: TTntRadioButton;
TntComboBox1: TTntComboBox;
TntGroupBox26: TTntGroupBox;
TntButton26: TTntButton;
TntRadioButton33: TTntRadioButton;
TntGroupBox27: TTntGroupBox;
TntButton27: TTntButton;
TntComboBox2: TTntComboBox;
TntRadioButton34: TTntRadioButton;
TntGroupBox28: TTntGroupBox;
TntButton28: TTntButton;
TntRadioButton35: TTntRadioButton;
TntGroupBox29: TTntGroupBox;
TntButton29: TTntButton;
TntComboBox3: TTntComboBox;
TntRadioButton36: TTntRadioButton;
TntGroupBox30: TTntGroupBox;
TntButton30: TTntButton;
TntRadioButton37: TTntRadioButton;
TntRichEdit11: TTntRichEdit;
TntRichEdit12: TTntRichEdit;
TntGroupBox31: TTntGroupBox;
TntButton31: TTntButton;
TntRadioButton38: TTntRadioButton;
TntGroupBox32: TTntGroupBox;
TntButton32: TTntButton;
TntRadioButton39: TTntRadioButton;
TntGroupBox33: TTntGroupBox;
TntButton33: TTntButton;
TntRadioButton40: TTntRadioButton;
TntGroupBox34: TTntGroupBox;
TntButton34: TTntButton;
TntRadioButton41: TTntRadioButton;
TntGroupBox35: TTntGroupBox;
TntButton35: TTntButton;
TntRadioButton42: TTntRadioButton;
TntGroupBox36: TTntGroupBox;
TntButton36: TTntButton;
TntRadioButton43: TTntRadioButton;
TntComboBox4: TTntComboBox;
TntComboBox5: TTntComboBox;
TntComboBox6: TTntComboBox;
TntComboBox7: TTntComboBox;
TntRichEdit13: TTntRichEdit;
TntRichEdit14: TTntRichEdit;
TntGroupBox37: TTntGroupBox;
TntButton37: TTntButton;
TntRadioButton44: TTntRadioButton;
TntGroupBox38: TTntGroupBox;
TntButton38: TTntButton;
TntRadioButton45: TTntRadioButton;
TntGroupBox39: TTntGroupBox;
TntButton39: TTntButton;
TntRadioButton46: TTntRadioButton;
TntPageControl4: TTntPageControl;
TntTabSheet12: TTntTabSheet;
TntRichEdit15: TTntRichEdit;
TntRichEdit16: TTntRichEdit;
TntGroupBox40: TTntGroupBox;
TntButton40: TTntButton;
TntComboBox8: TTntComboBox;
TntRadioButton47: TTntRadioButton;
TntGroupBox41: TTntGroupBox;
TntButton41: TTntButton;
TntComboBox9: TTntComboBox;
TntRadioButton48: TTntRadioButton;
TntGroupBox42: TTntGroupBox;
TntButton42: TTntButton;
TntRadioButton49: TTntRadioButton;
TntGroupBox43: TTntGroupBox;
TntButton43: TTntButton;
TntComboBox10: TTntComboBox;
TntRadioButton50: TTntRadioButton;
TntGroupBox44: TTntGroupBox;
TntButton44: TTntButton;
TntRadioButton51: TTntRadioButton;
TntGroupBox45: TTntGroupBox;
TntButton45: TTntButton;
TntComboBox11: TTntComboBox;
TntRadioButton52: TTntRadioButton;
TntTabSheet13: TTntTabSheet;
TntRichEdit17: TTntRichEdit;
TntRichEdit18: TTntRichEdit;
TntGroupBox46: TTntGroupBox;
TntButton46: TTntButton;
TntRadioButton53: TTntRadioButton;
TntGroupBox47: TTntGroupBox;
TntButton47: TTntButton;
TntRadioButton54: TTntRadioButton;
TntGroupBox48: TTntGroupBox;
TntButton48: TTntButton;
TntRadioButton55: TTntRadioButton;
TntGroupBox49: TTntGroupBox;
TntButton49: TTntButton;
TntComboBox14: TTntComboBox;
TntRadioButton56: TTntRadioButton;
TntGroupBox50: TTntGroupBox;
TntButton50: TTntButton;
TntRadioButton57: TTntRadioButton;
TntGroupBox51: TTntGroupBox;
TntButton51: TTntButton;
TntComboBox15: TTntComboBox;
TntRadioButton58: TTntRadioButton;
TntComboBox12: TTntComboBox;
TntComboBox13: TTntComboBox;
TntPageControl5: TTntPageControl;
TntTabSheet14: TTntTabSheet;
TntRichEdit19: TTntRichEdit;
TntRichEdit20: TTntRichEdit;
TntGroupBox52: TTntGroupBox;
TntButton52: TTntButton;
TntGroupBox53: TTntGroupBox;
TntButton53: TTntButton;
TntGroupBox54: TTntGroupBox;
TntButton54: TTntButton;
TntGroupBox55: TTntGroupBox;
TntButton55: TTntButton;
TntGroupBox56: TTntGroupBox;
TntButton56: TTntButton;
TntGroupBox57: TTntGroupBox;
TntButton57: TTntButton;
TntGroupBox58: TTntGroupBox;
TntButton58: TTntButton;
TntTabSheet15: TTntTabSheet;
TntRichEdit21: TTntRichEdit;
TntRichEdit22: TTntRichEdit;
TntGroupBox59: TTntGroupBox;
TntButton59: TTntButton;
TntGroupBox60: TTntGroupBox;
TntButton60: TTntButton;
procedure TntRadioButton1Click(Sender: TObject);
procedure TntRadioButton2Click(Sender: TObject);
procedure Edit1Change(Sender: TObject);
procedure TntButton1Click(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject;
var Key: Char);
procedure TntRadioButton3Click(Sender: TObject);
procedure TntButton2Click(Sender: TObject);
procedure Edit2KeyPress(Sender: TObject;
var Key: Char);
procedure Edit1Enter(Sender: TObject);
procedure TntFormCreate(Sender: TObject);
procedure Edit3KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton3Click(Sender: TObject);
procedure Edit4Change(Sender: TObject);
procedure Edit4KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton4Click(Sender: TObject);
procedure TntRadioButton5Click(Sender: TObject);
procedure Edit5KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton5Click(Sender: TObject);
procedure Edit7KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton7Click(Sender: TObject);
procedure Edit6KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton6Click(Sender: TObject);
procedure TntRichEdit2Change(Sender: TObject);
procedure TntRichEdit2SelectionChange(Sender: TObject);
procedure TntFormShow(Sender: TObject);
procedure TntRichEdit3SelectionChange(Sender: TObject);
procedure TntButton8Click(Sender: TObject);
procedure TntRadioButton8Click(Sender: TObject);
procedure TntRadioButton7Click(Sender: TObject);
procedure Edit9KeyPress(Sender: TObject;
var Key: Char);
procedure TntRadioButton9Click(Sender: TObject);
procedure Edit10KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton9Click(Sender: TObject);
procedure TntRadioButton11Click(Sender: TObject);
procedure TntRadioButton12Click(Sender: TObject);
procedure Edit11KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton10Click(Sender: TObject);
procedure Edit12KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton11Click(Sender: TObject);
procedure Edit13KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton12Click(Sender: TObject);
procedure TntRadioButton13Click(Sender: TObject);
procedure Edit14KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton13Click(Sender: TObject);
procedure TntRadioButton10Click(Sender: TObject);
procedure TntRadioButton14Click(Sender: TObject);
procedure TntRichEdit1Change(Sender: TObject);
procedure TntRichEdit1SelectionChange(Sender: TObject);
procedure TntRichEdit1DblClick(Sender: TObject);
procedure TntRichEdit4SelectionChange(Sender: TObject);
procedure TntRadioButton4Click(Sender: TObject);
procedure TntRadioButton15Click(Sender: TObject);
procedure TntRadioButton16Click(Sender: TObject);
procedure TntRadioButton6Click(Sender: TObject);
procedure TntRichEdit2DblClick(Sender: TObject);
procedure TntRichEdit5Change(Sender: TObject);
procedure TntRichEdit5DblClick(Sender: TObject);
procedure TntRichEdit5SelectionChange(Sender: TObject);
procedure TntRichEdit6SelectionChange(Sender: TObject);
procedure TntRadioButton17Click(Sender: TObject);
procedure TntRadioButton18Click(Sender: TObject);
procedure TntButton14Click(Sender: TObject);
procedure Edit15KeyPress(Sender: TObject;
var Key: Char);
procedure InitGroupBox7_1;
procedure InitGroupBox7_2;
procedure InitGroupBox7_5;
procedure TntRadioButton19Click(Sender: TObject);
procedure TntRadioButton20Click(Sender: TObject);
procedure TntRadioButton21Click(Sender: TObject);
procedure Edit16KeyPress(Sender: TObject;
var Key: Char);
procedure TntButton15Click(Sender: TObject);
procedure TntButton16Click(Sender: TObject);
procedure TntButton17Click(Sender: TObject);
procedure TntButton18Click(Sender: TObject);
procedure TntButton19Click(Sender: TObject);
procedure TntButton20Click(Sender: TObject);
procedure TntButton21Click(Sender: TObject);
procedure InitGroupBox8_1;
procedure InitGroupBox8_2;
procedure InitGroupBox8_3;
procedure InitGroupBox9_1;
procedure InitGroupBox9_2;
procedure InitGroupBox9_3;
procedure DispBSCommonProc_9(BSType:integer);
procedure InitGroupBox9_4;
procedure InitGroupBox9_5;
procedure InitGroupBox9_6;
procedure InitGroupBox10_1;
procedure InitGroupBox10_2;
procedure InitGroupBox10_3;
procedure DispBSCommonProc_10(BSType:integer);
procedure InitGroupBox10_4;
procedure InitGroupBox10_5;
procedure InitGroupBox10_6;
procedure DispBSCommonProc_11(BSType:integer);
procedure InitGroupBox11_4;
procedure InitGroupBox11_5;
procedure InitGroupBox11_6;
procedure InitGroupBox12_1;
procedure InitGroupBox12_2;
procedure InitGroupBox12_3;
procedure DispBSCommonProc_12(BSType:integer);
procedure InitGroupBox12_4;
procedure InitGroupBox12_5;
procedure InitGroupBox12_6;
procedure InitGroupBox13_1;
procedure InitGroupBox13_2;
procedure InitGroupBox13_3;
procedure DispBSCommonProc_13(BSType:integer);
procedure InitGroupBox13_4;
procedure InitGroupBox13_5;
procedure InitGroupBox13_6;
procedure DispBSCommonProc_14(BSType:integer);
procedure DispBSCommonProc_15(BSType:integer);
procedure TntRichEdit7Change(Sender: TObject);
procedure TntRichEdit7DblClick(Sender: TObject);
procedure TntRichEdit7SelectionChange(Sender: TObject);
procedure TntRichEdit8SelectionChange(Sender: TObject);
procedure TntRadioButton29Click(Sender: TObject);
procedure TntButton22Click(Sender: TObject);
procedure TntButton23Click(Sender: TObject);
procedure TntButton24Click(Sender: TObject);
procedure TntTabSheet9Show(Sender: TObject);
procedure TntTabSheet5Show(Sender: TObject);
procedure TntTabSheet6Show(Sender: TObject);
procedure TntTabSheet7Show(Sender: TObject);
procedure TntTabSheet8Show(Sender: TObject);
procedure TntTabSheet1Show(Sender: TObject);
procedure TntRichEdit9Change(Sender: TObject);
procedure TntRichEdit9DblClick(Sender: TObject);
procedure TntRichEdit9SelectionChange(Sender: TObject);
procedure TntRichEdit10SelectionChange(Sender: TObject);
procedure TntButton25Click(Sender: TObject);
procedure TntRadioButton32Click(Sender: TObject);
procedure TntButton26Click(Sender: TObject);
procedure TntButton27Click(Sender: TObject);
procedure TntButton28Click(Sender: TObject);
procedure TntButton29Click(Sender: TObject);
procedure TntButton30Click(Sender: TObject);
procedure TntTabSheet10Show(Sender: TObject);
procedure TntRichEdit11Change(Sender: TObject);
procedure TntRadioButton38Click(Sender: TObject);
procedure TntRichEdit11DblClick(Sender: TObject);
procedure TntRichEdit11SelectionChange(Sender: TObject);
procedure TntRichEdit12SelectionChange(Sender: TObject);
procedure TntButton31Click(Sender: TObject);
procedure TntButton32Click(Sender: TObject);
procedure TntButton33Click(Sender: TObject);
procedure TntButton34Click(Sender: TObject);
procedure TntButton35Click(Sender: TObject);
procedure TntButton36Click(Sender: TObject);
procedure TntTabSheet11Show(Sender: TObject);
procedure TntRadioButton44Click(Sender: TObject);
procedure TntRichEdit13Change(Sender: TObject);
procedure TntRichEdit13DblClick(Sender: TObject);
procedure TntRichEdit13SelectionChange(Sender: TObject);
procedure TntRichEdit14SelectionChange(Sender: TObject);
procedure TntButton37Click(Sender: TObject);
procedure TntButton38Click(Sender: TObject);
procedure TntButton39Click(Sender: TObject);
procedure TntTabSheet12Show(Sender: TObject);
procedure TntRichEdit15Change(Sender: TObject);
procedure TntRichEdit15DblClick(Sender: TObject);
procedure TntRichEdit15SelectionChange(Sender: TObject);
procedure TntRichEdit16SelectionChange(Sender: TObject);
procedure TntRadioButton47Click(Sender: TObject);
procedure TntButton40Click(Sender: TObject);
procedure TntButton41Click(Sender: TObject);
procedure TntButton42Click(Sender: TObject);
procedure TntButton43Click(Sender: TObject);
procedure TntButton44Click(Sender: TObject);
procedure TntButton45Click(Sender: TObject);
procedure TntTabSheet13Show(Sender: TObject);
procedure TntRichEdit17Change(Sender: TObject);
procedure TntRichEdit17DblClick(Sender: TObject);
procedure TntRichEdit17SelectionChange(Sender: TObject);
procedure TntRichEdit18SelectionChange(Sender: TObject);
procedure TntRadioButton53Click(Sender: TObject);
procedure TntButton46Click(Sender: TObject);
procedure TntButton47Click(Sender: TObject);
procedure TntComboBox12Select(Sender: TObject);
procedure TntButton48Click(Sender: TObject);
procedure TntButton49Click(Sender: TObject);
procedure TntButton50Click(Sender: TObject);
procedure TntButton51Click(Sender: TObject);
procedure TntTabSheet14Show(Sender: TObject);
procedure TntRichEdit19SelectionChange(Sender: TObject);
procedure TntRichEdit20SelectionChange(Sender: TObject);
procedure TntRichEdit19Change(Sender: TObject);
procedure TntButton52Click(Sender: TObject);
procedure TntButton53Click(Sender: TObject);
procedure TntButton54Click(Sender: TObject);
procedure TntButton55Click(Sender: TObject);
procedure TntButton56Click(Sender: TObject);
procedure TntButton57Click(Sender: TObject);
procedure TntButton58Click(Sender: TObject);
procedure TntTabSheet15Show(Sender: TObject);
procedure TntRichEdit21Change(Sender: TObject);
procedure TntRichEdit21SelectionChange(Sender: TObject);
procedure TntRichEdit22SelectionChange(Sender: TObject);
procedure TntButton59Click(Sender: TObject);
procedure TntButton60Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
TmpUTF8Str:string;
// 临时UTF-8字符串
TmpUTF32Str:array of DWORD;
// 临时UTF-32字符串
TmpUTFBS:string;
// 临时Unicode编码格式字节序列
// 单选框控件数组
RadioBtnArray:array of TTntRadioButton;
// 分组框控件数组
GroupBoxArray:array of TTntGroupBox;
EnabGroupBoxIndex:integer;
// 当前可用分组框在数组中的索引
implementation
{$R *.dfm}
procedure TForm1.TntRadioButton1Click(Sender: TObject);
begin
Edit1.SetFocus;
Edit1.Text:='';
Edit1.OnChange(Edit1)
end;

procedure TForm1.TntRadioButton2Click(Sender: TObject);
begin
TntRichEdit4.SetFocus;
TntRichEdit4.OnSelectionChange(TntRichEdit4);
TntButton1.Enabled:=true
end;

procedure TForm1.Edit1Change(Sender: TObject);
var
s:string;
i,j,k:integer;
Edit:TEdit;
begin
if (Sender<>nil) and (Sender is TEdit) then
begin
Edit:=Sender as TEdit;
if Edit.Tag=0 then
begin
s:='';
k:=0;
j:=0;
i:=1;
While i<=Length(Edit.Text)do
case ord(ByteType(Edit.Text,i)) of
0:
begin
if Edit.Text in ['0'..'9'] then
s:=s+Edit.Text
else
begin
k:=i-j;
inc(j)
end;
inc(i)
end;
1:
begin
k:=i-j;
j:=j+2;
i:=i+2
end
else
begin
k:=i-j;
Break
end
end;
if k>0 then
begin
Edit.Tag:=1;
Edit.Text:=s;
Edit.SelStart:=k-1
end
end
else
Edit.Tag:=0;
if Edit=Edit1 then
TntButton1.Enabled:=Edit.Text<>'';
if Edit=Edit2 then
TntButton2.Enabled:=Edit.Text<>'';
if Edit=Edit3 then
TntButton3.Enabled:=Edit.Text<>'';
if Edit=Edit5 then
TntButton5.Enabled:=Edit.Text<>'';
if Edit=Edit9 then
TntButton8.Enabled:=Edit.Text<>'';
if Edit=Edit10 then
TntButton9.Enabled:=Edit.Text<>'';
if Edit=Edit11 then
TntButton10.Enabled:=Edit.Text<>'';
if Edit=Edit14 then
TntButton13.Enabled:=Edit.Text<>'';
if Edit=Edit15 then
TntButton14.Enabled:=Edit.Text<>'';
if Edit=Edit16 then
TntButton15.Enabled:=Edit.Text<>''
end
end;

procedure TForm1.TntButton1Click(Sender: TObject);
var
s:WideString;
i:integer;
begin
if TntRadioButton1.Checked then
begin
case TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit1.Text),strtoint(
Edit1.Text))) of
BMPCP:
s:='BMP编码点';
HighSurr:
s:='高位代理';
LowSurr:
s:='低位代理'
else
s:='无效编码单元'
end;
s:='第'+Edit1.Text+'个编码单元的类型是'+s;
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CodeUnitType函数',mb_ok);
Edit1.SetFocus
end
else
begin
TntRadioButton2.OnClick(TntRadioButton2);
i:=TntRichEdit4.SelStart div 5 + 1;
case TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit1.Text),i)) of
BMPCP:
s:='BMP编码点';
HighSurr:
s:='高位代理';
LowSurr:
s:='低位代理'
else
s:='无效编码单元'
end;
s:='第'+inttostr(i)+'个编码单元的类型是'+s;
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CodeUnitType函数',mb_ok);
TntRichEdit1.SetFocus
end
end;

procedure TForm1.Edit1KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton1.Enabled then
TntButton1.Click
end
end;

procedure TForm1.TntRadioButton3Click(Sender: TObject);
begin
Edit2.SetFocus;
Edit2.Text:='';
Edit2.OnChange(Edit2)
end;

procedure TForm1.TntButton2Click(Sender: TObject);
var
s:WideString;
i:integer;
begin
if TntRadioButton3.Checked then
begin
s:='第'+Edit2.Text+'个编码单元属于第'+inttostr(UTF16CUToCharIndex(
Pointer(TntRichEdit1.Text),strtoint(Edit2.Text),true))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CUToCharIndex函数',mb_ok);
Edit2.SetFocus
end
else
begin
TntRadioButton4.OnClick(TntRichEdit4);
i:=TntRichEdit4.SelStart div 5 + 1;
s:='第'+inttostr(i)+'个编码单元属于第'+inttostr(UTF16CUToCharIndex(
Pointer(TntRichEdit1.Text),i,true))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CUToCharIndex函数',mb_ok);
TntRichEdit4.SetFocus
end
end;

procedure TForm1.Edit2KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton2.Enabled then
TntButton2.Click
end
end;

procedure TForm1.Edit1Enter(Sender: TObject);
begin
if (Sender<>nil) and (Sender is TEdit) then
(Sender as TEdit).SelectAll
end;

procedure TForm1.TntFormCreate(Sender: TObject);
begin
Application.HintHidePause:=10000
end;

procedure TForm1.Edit3KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton3.Enabled then
TntButton3.Click
end
end;

procedure TForm1.TntButton3Click(Sender: TObject);
var
s:WideString;
i:integer;
begin
if TntRadioButton15.Checked then
begin
s:='第'+Edit3.Text+'个字符的第一个编码单元是字符串中的第'+inttostr(
UTF16CharToCUIndex(Pointer(TntRichEdit1.Text),strtoint(Edit3.Text),true))+
'个编码单元';
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CharToCUIndex函数',mb_ok);
Edit3.SetFocus
end
else
begin
TntRadioButton16.OnClick(TntRadioButton16);
i:=UTF16CUToCharIndex(Pointer(TntRichEdit1.Text),TntRichEdit1.SelStart+1,
true);
s:='第'+inttostr(i)+'个字符的第一个编码单元是字符串中的第'+inttostr(
UTF16CharToCUIndex(Pointer(TntRichEdit1.Text),i,true))+'个编码单元';
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CharToCUIndex函数',mb_ok);
TntRichEdit1.SetFocus
end
end;

procedure TForm1.Edit4Change(Sender: TObject);
var
s:string;
i,j,k:integer;
Edit:TEdit;
begin
if (Sender<>nil) and (Sender is TEdit) then
begin
Edit:=Sender as TEdit;
if Edit.Tag=0 then
begin
s:='';
i:=1;
j:=0;
k:=0;
While i<=Length(Edit.Text)do
case ord(ByteType(Edit.Text,i)) of
0:
begin
if Edit.Text in ['0'..'9','A'..'F'] then
s:=s+Edit.Text
else
begin
k:=i-j;
inc(j)
end;
inc(i)
end;
1:
begin
k:=i-j;
j:=j+2;
i:=i+2
end
else
begin
k:=i-j;
Break
end
end;
if j>0 then
begin
Edit.Tag:=1;
Edit.Text:=s;
Edit.SelStart:=k-1
end
end
else
Edit.Tag:=0;
if Edit=Edit4 then
TntButton4.Enabled:=Edit.Text<>'';
if (Edit=Edit7) or (Edit=Edit8) then
TntButton7.Enabled:=(Edit7.Text<>'') and (Edit8.Text<>'');
if Edit=Edit6 then
TntButton6.Enabled:=Edit.Text<>'';
if Edit=Edit12 then
TntButton11.Enabled:=Edit.Text<>'';
if Edit=Edit13 then
TntButton12.Enabled:=Edit.Text<>''
end
end;

procedure TForm1.Edit4KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton4.Enabled then
TntButton4.Click
end
end;

procedure TForm1.TntButton4Click(Sender: TObject);
var
UTF16_CUS:array [0..2] of WideChar;
i:integer;
s:WideString;
begin
s:='';
for i:=0 to CPToUTF16CUS(UTF16_CUS,strtoint('$'+Edit4.Text))-1do
begin
if i>0 then
s:=s+WideChar(' ');
s:=s+inttohex(ord(UTF16_CUS),1)
end;
if s<>'' then
s:='Unicode编码点数字U+'+Edit4.Text+'对应的UTF16编码单元序列是<'+s+'>'
else
s:='0x'+Edit4.Text+s+'不是一个有效的Unicode编码点数字';
MessageBoxW(Form1.Handle,Pointer(s),'试练CPToUTF16CUS函数',mb_ok);
Edit4.SetFocus
end;

procedure TForm1.TntRadioButton5Click(Sender: TObject);
begin
Edit5.SetFocus;
Edit5.Text:='';
Edit5.OnChange(Edit5)
end;

procedure TForm1.Edit5KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton5.Enabled then
TntButton5.Click
end
end;

procedure TForm1.TntButton5Click(Sender: TObject);
var
CP:DWORD;
s:WideString;
i:integer;
begin
if TntRadioButton5.Checked then
begin
CP:=UTF16CUSToCP(Pointer(TntRichEdit1.Text),strtoint(Edit5.Text));
if CP<>$FFFFFFFF then
s:='第'+Edit5.Text+'个编码单元所属的字符的Unicode编码点数字是U+'+
inttohex(CP,1)
else
s:='第'+Edit5.Text+'个编码单元所属的子编码单元序列是一个无效编码单元'+
'序列';
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CUToCP函数',mb_ok);
Edit5.SetFocus
end
else
begin
TntRadioButton6.OnClick(TntRadioButton6);
i:=TntRichEdit4.SelStart div 5 + 1;
CP:=UTF16CUSToCP(Pointer(TntRichEdit1.Text),i);
if CP<>$FFFFFFFF then
s:='第'+inttostr(i)+'个编码单元所属的字符的'+
'Unicode编码点数字是U+'+inttohex(CP,1)
else
s:='第'+inttostr(i)+'个编码单元所属的子编码'+'单元序列是一个无效编码单'+
'元序列';
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16CUToCP函数',mb_ok);
TntRichEdit4.SetFocus
end
end;

procedure TForm1.Edit7KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton7.Enabled then
TntButton7.Click
end
end;

procedure TForm1.TntButton7Click(Sender: TObject);
var
CP:DWORD;
s:WideString;
begin
CP:=SurrPairToCP(strtoint('$'+Edit7.Text),strtoint('$'+Edit8.Text));
if CP<>$FFFFFFFF then
s:='代理对<'+Edit7.Text+#32+Edit8.Text+'>对应的Unicode编码点数字是U+'+
inttohex(CP,1)
else
s:='<'+Edit7.Text+#32+Edit8.Text+'>不是一个有效的代理对';
MessageBoxW(Form1.Handle,Pointer(s),'试练SurrPairToCP函数',mb_ok)
end;

procedure TForm1.Edit6KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton6.Enabled then
TntButton6.Click
end
end;

procedure TForm1.TntButton6Click(Sender: TObject);
var
s:WideString;
SurrPair,CP:DWORD;
HighSurr,LowSurr:WORD;
begin
CP:=strtoint('$'+Edit6.Text);
SurrPair:=CPToSurrPair(CP);
if SurrPair>MaxBMPCP then
begin
HighSurr:=SurrPair shr 16;
LowSurr:=SurrPair;
s:='增补Unicode编码点数字U+'+Edit6.Text+'对应的代理对是<'+inttohex(
HighSurr,4)+#32+inttohex(LowSurr,4)+'>'
end
else
if CP<=MaxUnicodeValue then
s:='U+'+Edit6.Text+'不是有效的增补Unicode编码点数字'
else
s:='0x'+Edit6.Text+'不是不是有效的Unicode编码点';
MessageBoxW(Form1.Handle,Pointer(s),'试练CPToSurrPair函数',mb_ok)
end;

procedure TForm1.TntRichEdit2Change(Sender: TObject);
var
i,l,j:integer;
s,s1:string;
ps:pChar;
b,b1:Byte;
begin
TntRichEdit3.Clear;
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s1,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s1))=i then
begin
l:=i*3;
SetLength(s,l);
ps:=Pointer(s);
j:=0;
for i:=1 to Length(s1)do
begin
b:=Ord(s1);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
ps[j]:=Chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
ps[j+1]:=Chr(b1);
ps[j+2]:=#32;
j:=j+3
end;
TntRichEdit3.Text:=s
end
end
end;

procedure TForm1.TntRichEdit2SelectionChange(Sender: TObject);
var
i,j,k:integer;
s:string;
begin
if TntRichEdit2.ReadOnly then
if TntRichEdit2.Tag=0 then
begin
TntRichEdit2.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit2.Text),
TntRichEdit2.SelStart+1))=BMPCP
then
TntRichEdit2.SelLength:=1
else
TntRichEdit2.SelLength:=2;
i:=UTF16ToUTF8ForStr(Pointer(TntRichedit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
i:=UTF8CharToCUIndex(Pointer(s),UTF16CUToCharIndex(Pointer(
TntRichEdit2.Text),TntRichEdit2.SelStart+1,true),true);
if (i<=Length(s)) and (UTF8CUIndexOfChar(Pointer(s),i,@j,@k)=1) then
begin
TntRichEdit3.Tag:=1;
TntRichEdit3.SelStart:=(i-1)*3;
TntRichEdit3.SelLength:=(k-1)*3+2
end
end
end
end
else
if TntRichEdit2.SelLength>0 then
TntRichEdit2.Tag:=0
end;

procedure TForm1.TntFormShow(Sender: TObject);
var
i,j,k:integer;
begin
for i:=TntPageControl1.PageCount-1do
wnto 0do
begin
TntPageControl1.ActivePageIndex:=i;
for j:=TntPageControl1.ActivePage.ControlCount-1do
wnto 0do
if TntPageControl1.ActivePage.Controls[j] is TTntPageControl then
for k:=(TntPageControl1.ActivePage.Controls[j] as
TTntPageControl).PageCount-1do
wnto 0do
(TntPageControl1.ActivePage.Controls[j] as
TTntPageControl).ActivePageIndex:=k
end
end;

procedure TForm1.TntRichEdit3SelectionChange(Sender: TObject);
var
i,j:integer;
s:string;
begin
if TntRichEdit3.Tag=0 then
begin
i:=TntRichEdit3.SelStart div 3 + 1;
TntRichEdit3.Tag:=1;
TntRichEdit3.SelStart:=(i-1)*3;
TntRichEdit3.SelLength:=2;
j:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if j>0 then
begin
SetLength(s,j);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=j then
begin
i:=UTF8CUToCharIndex(Pointer(s),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit2.Text),i,true);
TntRichEdit2.Tag:=1;
TntRichEdit2.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit2.Text),i))
=BMPCP
then
TntRichEdit2.SelLength:=1
else
TntRichEdit2.SelLength:=2;
TntRichEdit2.Tag:=0
end
end
end
else
if TntRichEdit3.SelLength>0 then
TntRichEdit3.Tag:=0
end;

procedure TForm1.TntButton8Click(Sender: TObject);
var
i,j,k,charsize:integer;
s:string;
s1:WideString;
begin
if TntRadioButton7.Checked then
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
i:=strtoint(Edit9.Text);
k:=UTF8CUToCharIndex(Pointer(s),i,true);
i:=UTF8CUIndexOfChar(Pointer(s),i,@j,@charsize);
s1:='字符串的第'+Edit9.Text+'个编码单元是第'+inttostr(k)+'个字符的第'+
inttostr(i)+'个编码单元;'+CRLF+'第'+inttostr(k)+
'个字符位于UTF-8编码点分段的第'+inttostr(j)+'段;'+CRLF+
'第'+inttostr(k)+'个字符的编码单元序列长度为'+inttostr(charsize);
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CUIndexOfChar函数',mb_ok)
end
end;
Edit9.SetFocus
end
else
begin
TntRichEdit3.OnSelectionChange(TntRichEdit3);
TntRichEdit3.SetFocus;
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
i:=TntRichEdit3.SelStart div 3 + 1;
k:=UTF8CUToCharIndex(Pointer(s),i,true);
i:=UTF8CUIndexOfChar(Pointer(s),i,@j,@charsize);
s1:='字符串的第'+inttostr(TntRichEdit3.SelStart div 3 + 1)+
'个编码单元是第'+inttostr(k)+'个字符的第'+inttostr(i)+'个编码单元;'+
CRLF+'第'+inttostr(k)+'个字符位于UTF-8编码点分段的第'+inttostr(j)+
'段;'+CRLF+'第'+inttostr(k)+'个字符的编码单元序列长度为'+
inttostr(charsize);
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CUIndexOfChar函数',mb_ok)
end
end
end
end;

procedure TForm1.TntRadioButton8Click(Sender: TObject);
begin
TntRichEdit3.SetFocus;
TntRichEdit3.OnSelectionChange(TntRichEdit3);
TntButton8.Enabled:=true
end;

procedure TForm1.TntRadioButton7Click(Sender: TObject);
begin
Edit9.SetFocus;
Edit9.Text:='';
Edit9.OnChange(Edit9)
end;

procedure TForm1.Edit9KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton8.Enabled then
TntButton8.Click
end
end;

procedure TForm1.TntRadioButton9Click(Sender: TObject);
begin
Edit10.SetFocus;
Edit10.Text:='';
Edit10.OnChange(Edit10)
end;

procedure TForm1.Edit10KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton9.Enabled then
TntButton9.Click
end
end;

procedure TForm1.TntButton9Click(Sender: TObject);
var
i:integer;
s:string;
s1:WideString;
begin
if TntRadioButton9.Checked then
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
s1:='字符串的第'+Edit10.Text+'个编码单元属于第'+inttostr(
UTF8CUToCharIndex(Pointer(s),strtoint(Edit10.Text),true))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CUToCharIndex函数',mb_ok)
end
end;
Edit10.SetFocus
end
else
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
i:=TntRichEdit3.SelStart div 3 + 1;
s1:='字符串的第'+inttostr(i)+'个编码单元属于第'+inttostr(
UTF8CUToCharIndex(Pointer(s),i,true))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CUToCharIndex函数',mb_ok)
end
end;
TntRichEdit3.SetFocus
end
end;

procedure TForm1.TntRadioButton11Click(Sender: TObject);
begin
Edit11.SetFocus;
Edit11.Text:='';
Edit11.OnChange(Edit11)
end;

procedure TForm1.TntRadioButton12Click(Sender: TObject);
begin
TntRichEdit2.SetFocus;
TntRichEdit2.OnSelectionChange(TntRichEdit2);
TntButton10.Enabled:=true
end;

procedure TForm1.Edit11KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton10.Enabled then
TntButton10.Click
end
end;

procedure TForm1.TntButton10Click(Sender: TObject);
var
i:integer;
s:string;
s1:WideString;
begin
if TntRadioButton11.Checked then
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
s1:='字符串的第'+Edit11.Text+'个字符的第一个编码单元是字符串的第'+
inttostr(UTF8CharToCUIndex(Pointer(s),strtoint(Edit11.Text),true))+
'个编码单元';
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CharToCUIndex函数',mb_ok)
end
end;
Edit11.SetFocus
end
else
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
i:=UTF16CUToCharIndex(Pointer(TntRichEdit2.Text),
TntRichEdit2.SelStart+1,true);
s1:='字符串的第'+inttostr(i)+'个字符的第一个编码单元是字符串的第'+
inttostr(UTF8CharToCUIndex(Pointer(s),i,true))+'个编码单元';
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CharToCUIndex函数',mb_ok)
end
end;
TntRichEdit2.SetFocus
end
end;

procedure TForm1.Edit12KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton11.Enabled then
TntButton11.Click
end
end;

procedure TForm1.TntButton11Click(Sender: TObject);
var
i:integer;
s:string;
s1:WideString;
cp:DWORD;
b,b1:Byte;
begin
cp:=strtoint('$'+Edit12.Text);
i:=CPToUTF8CUS(nil,cp);
if i>0 then
begin
SetLength(s,i);
if CPToUTF8CUS(Pointer(s),cp)=i then
begin
s1:='';
for i:=1 to ido
begin
if i>1 then
s1:=s1+#32;
b:=ord(s);
b1:=b shr 4;
if b1>9 then
s1:=s1+chr(b1+$37)
else
s1:=s1+chr(b1+$30);
b1:=b and $F;
if b1>9 then
s1:=s1+chr(b1+$37)
else
s1:=s1+chr(b1+$30)
end;
s1:='Unicode编码点数字U+'+Edit12.Text+'对应的UTF-8编码单元序列是<'+s1+
'>';
MessageBoxW(Form1.Handle,Pointer(s1),'试练CPToUTF8CUS函数',mb_ok)
end
end
else
begin
s1:='0x'+Edit12.Text+'不是一个有效的Unicode编码点数字';
MessageBoxW(Form1.Handle,Pointer(s1),'试练GetCPPartIndexOfUTF8函数',mb_ok)
end;
Edit12.SetFocus
end;

procedure TForm1.Edit13KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton12.Enabled then
TntButton12.Click
end
end;

procedure TForm1.TntButton12Click(Sender: TObject);
var
CPPartOfUTF8Info:TCPPartOfUTF8Info;
i,j:integer;
s:WideString;
b:Byte;
begin
i:=GetCPPartIndexOfUTF8(strtoint('$'+Edit13.Text),@CPPartOfUTF8Info);
if i in [0..CPPartCountOfUTF8-1] then
With CPPartOfUTF8Infodo
begin
s:='Unicode编码点数字U+'+Edit13.Text+'位于UTF-8编码点分段的第'+
inttostr(i)+'段,该分段的属性为:'+CRLF+CRLF+#9'编码点区间 - [U+'+
inttohex(CodeRange.MinCode,1)+',U+'+inttohex(CodeRange.MaxCode,1)+']'+
CRLF+CRLF;
for j:=0 to MaxCodeUnitCountOfUTF8-1do
if (CUValueRange[j].MinValue in InvalUTF8CUSet)
or
(CUValueRange[j].MaxValue in InvalUTF8CUSet)
then
Break
else
begin
if j>0 then
s:=s+CRLF;
b:=CUValueRange[j].MinValue shr 4;
if b>9 then
s:=s+#9'第'+inttostr(j+1)+'个编码单元的取值范围 - ['+chr(b+$37)
else
s:=s+#9'第'+inttostr(j+1)+'个编码单元的取值范围 - ['+chr(b+$30);
b:=CUValueRange[j].MinValue and $F;
if b>9 then
s:=s+chr(b+$37)+','
else
s:=s+chr(b+$30)+',';
b:=CUValueRange[j].MaxValue shr 4;
if b>9 then
s:=s+chr(b+$37)
else
s:=s+chr(b+$30);
b:=CUValueRange[j].MaxValue and $F;
if b>9 then
s:=s+chr(b+$37)+']'
else
s:=s+chr(b+$30)+']'
end;
MessageBoxW(Form1.Handle,Pointer(s),'试练GetCPPartIndexOfUTF8函数',mb_ok)
end
else
begin
s:='0x'+Edit13.Text+'不是一个有效的Unicode编码点数字';
MessageBoxW(Form1.Handle,Pointer(s),'试练GetCPPartIndexOfUTF8函数',mb_ok)
end;
Edit13.SetFocus
end;

procedure TForm1.TntRadioButton13Click(Sender: TObject);
begin
Edit14.SetFocus;
Edit14.Text:='';
Edit14.OnChange(Edit14)
end;

procedure TForm1.Edit14KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton13.Enabled then
TntButton13.Click
end
end;

procedure TForm1.TntButton13Click(Sender: TObject);
var
CP:DWORD;
s:string;
s1:WideString;
i:integer;
begin
if TntRadioButton13.Checked then
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
CP:=UTF8CUSToCP(Pointer(s),strtoint('$'+Edit14.Text));
if CP<>$FFFFFFFF then
begin
s1:='字符串的第'+Edit14.Text+'个编码单元所属的字符对应的Unicode'+
'编码点数字是U+'+inttohex(CP,1);
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CUSToCP函数',mb_ok)
end
end
end;
Edit14.SetFocus
end
else
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit2.Text),Pointer(s))=i then
begin
i:=TntRichEdit3.SelStart div 3 + 1;
CP:=UTF8CUSToCP(Pointer(s),i);
if CP<>$FFFFFFFF then
begin
s1:='字符串的第'+inttostr(i)+'个编码单元所属的字符对应的Unicode'+
'编码点数字是U+'+inttohex(CP,1);
MessageBoxW(Form1.Handle,Pointer(s1),'试练UTF8CUSToCP函数',mb_ok)
end
end
end;
TntRichEdit3.SetFocus
end
end;

procedure TForm1.TntRadioButton10Click(Sender: TObject);
begin
TntRichEdit3.SetFocus;
TntRichEdit3.OnSelectionChange(TntRichEdit3);
TntButton9.Enabled:=true
end;

procedure TForm1.TntRadioButton14Click(Sender: TObject);
begin
TntRichEdit3.SetFocus;
TntRichEdit3.OnSelectionChange(TntRichEdit3);
TntButton13.Enabled:=true
end;

procedure TForm1.TntRichEdit1Change(Sender: TObject);
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit1.Text);
SetLength(s,5*Length(TntRichEdit1.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit1.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit4.Text:=s
end;

procedure TForm1.TntRichEdit1SelectionChange(Sender: TObject);
begin
if TntRichEdit1.ReadOnly then
if TntRichEdit1.Tag=0 then
begin
TntRichEdit1.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit1.Text),
TntRichEdit1.SelStart+1))=BMPCP
then
TntRichEdit1.SelLength:=1
else
TntRichEdit1.SelLength:=2;
TntRichEdit4.Tag:=1;
TntRichEdit4.SelStart:=TntRichEdit1.SelStart*5;
if TntRichEdit1.SelLength=1 then
TntRichEdit4.SelLength:=4
else
TntRichEdit4.SelLength:=9
end
else
if TntRichEdit1.SelLength>0 then
TntRichEdit1.Tag:=0
end;

procedure TForm1.TntRichEdit1DblClick(Sender: TObject);
begin
TntRichEdit1.ReadOnly:=not TntRichEdit1.ReadOnly;
if TntRichEdit1.ReadOnly then
begin
TntRichEdit1.Cursor:=crArrow;
TntRichEdit1.OnSelectionChange(TntRichEdit1)
end
else
begin
TntRichEdit1.Cursor:=crDefault;
TntRichEdit1.SelLength:=0
end;
TntRichEdit4.HideSelection:=not TntRichEdit1.ReadOnly;
TntRichEdit1.Tag:=0
end;

procedure TForm1.TntRichEdit4SelectionChange(Sender: TObject);
var
i,j:integer;
begin
if TntRichEdit4.Tag=0 then
begin
i:=TntRichEdit4.SelStart div 5 + 1;
TntRichEdit4.Tag:=1;
TntRichEdit4.SelStart:=(i-1)*5;
TntRichEdit4.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit1.Text),i,@j);
TntRichEdit1.Tag:=1;
TntRichEdit1.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit1.Text),i))=BMPCP then
TntRichEdit1.SelLength:=1
else
TntRichEdit1.SelLength:=2;
TntRichEdit1.Tag:=0
end
else
if TntRichEdit4.SelLength>0 then
TntRichEdit4.Tag:=0
end;

procedure TForm1.TntRadioButton4Click(Sender: TObject);
begin
TntRichEdit4.SetFocus;
TntRichEdit4.OnSelectionChange(TntRichEdit4);
TntButton2.Enabled:=true
end;

procedure TForm1.TntRadioButton15Click(Sender: TObject);
begin
Edit3.SetFocus;
Edit3.Text:='';
Edit3.OnChange(Edit3)
end;

procedure TForm1.TntRadioButton16Click(Sender: TObject);
begin
TntRichEdit1.SetFocus;
TntRichEdit1.OnSelectionChange(TntRichEdit4);
TntButton3.Enabled:=true
end;

procedure TForm1.TntRadioButton6Click(Sender: TObject);
begin
TntRichEdit4.SetFocus;
TntRichEdit4.OnSelectionChange(TntRichEdit4);
TntButton5.Enabled:=true
end;

procedure TForm1.TntRichEdit2DblClick(Sender: TObject);
begin
TntRichEdit2.ReadOnly:=not TntRichEdit2.ReadOnly;
if TntRichEdit2.ReadOnly then
begin
TntRichEdit2.Cursor:=crArrow;
TntRichEdit2.OnSelectionChange(TntRichEdit2)
end
else
begin
TntRichEdit2.Cursor:=crDefault;
TntRichEdit2.SelLength:=0
end;
TntRichEdit3.HideSelection:=not TntRichEdit2.ReadOnly;
TntRichEdit2.Tag:=0
end;

procedure TForm1.TntRichEdit5Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0,2,4:
InitGroupBox7_1;
1,3,6:
InitGroupBox7_2;
5,7:
InitGroupBox7_5
end
end;

procedure TForm1.TntRichEdit5DblClick(Sender: TObject);
begin
TntRichEdit5.ReadOnly:=not TntRichEdit5.ReadOnly;
if TntRichEdit5.ReadOnly then
begin
TntRichEdit5.Cursor:=crArrow;
TntRichEdit5.OnSelectionChange(TntRichEdit5)
end
else
begin
TntRichEdit5.Cursor:=crDefault;
TntRichEdit5.SelLength:=0
end;
TntRichEdit6.HideSelection:=not TntRichEdit5.ReadOnly;
TntRichEdit5.Tag:=0
end;

procedure TForm1.TntRichEdit5SelectionChange(Sender: TObject);
var
i,j,charsize:integer;
begin
if TntRichEdit5.ReadOnly then
if TntRichEdit5.Tag=0 then
begin
TntRichEdit5.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit5.Text),
TntRichEdit5.SelStart+1))=BMPCP
then
TntRichEdit5.SelLength:=1
else
TntRichEdit5.SelLength:=2;
if TntRichEdit6.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit6.Tag;
TntRichEdit6.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit6.SelStart:=TntRichEdit5.SelStart*5;
if TntRichEdit5.SelLength=1 then
TntRichEdit6.SelLength:=4
else
TntRichEdit6.SelLength:=9
end;
2:
begin
i:=UTF16CUToCharIndex(Pointer(TntRichEdit5.Text),
TntRichEdit5.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
TntRichEdit6.SelStart:=(i-1)*3;
TntRichEdit6.SelLength:=(charsize-1)*3+2
end;
3:
begin
TntRichEdit6.SelStart:=TntRichEdit5.SelStart*9;
TntRichEdit6.SelLength:=8
end
end
end
end
else
if TntRichEdit5.SelLength>0 then
TntRichEdit5.Tag:=0
end;

procedure TForm1.TntRichEdit6SelectionChange(Sender: TObject);
var
i,j:integer;
begin
if TntRichEdit6.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit6.Tag;
case TntRichEdit6.Tag of
0:
begin
i:=TntRichEdit6.SelStart div 5 + 1;
TntRichEdit6.Tag:=1;
TntRichEdit6.SelStart:=(i-1)*5;
TntRichEdit6.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit5.Text),i,@j);
TntRichEdit5.Tag:=1;
TntRichEdit5.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit5.Text),i))=BMPCP then
TntRichEdit5.SelLength:=1
else
TntRichEdit5.SelLength:=2
end;
2:
begin
i:=TntRichEdit6.SelStart div 3 + 1;
TntRichEdit6.Tag:=1;
TntRichEdit6.SelStart:=(i-1)*3;
TntRichEdit6.SelLength:=2;
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit5.Text),i,true);
TntRichEdit5.Tag:=1;
TntRichEdit5.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit5.Text),i))=BMPCP then
TntRichEdit5.SelLength:=1
else
TntRichEdit5.SelLength:=2
end;
3:
begin
i:=TntRichEdit6.SelStart div 9 + 1;
TntRichEdit6.Tag:=1;
TntRichEdit6.SelStart:=(i-1)*9;
TntRichEdit6.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit5.Text),i,true);
TntRichEdit5.Tag:=1;
TntRichEdit5.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit5.Text),i))=BMPCP then
TntRichEdit5.SelLength:=1
else
TntRichEdit5.SelLength:=2
end;
1:
if TntRichEdit6.SelLength>0 then
TntRichEdit6.Tag:=TntGroupBox14.Tag
end;
TntRichEdit5.Tag:=0
end;

procedure TForm1.TntRadioButton17Click(Sender: TObject);
begin
Edit15.SetFocus;
Edit15.Text:='';
Edit15.OnChange(Edit15)
end;

procedure TForm1.TntRadioButton18Click(Sender: TObject);
begin
TntRichEdit6.SetFocus;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntButton14.Enabled:=true
end;

procedure TForm1.TntButton14Click(Sender: TObject);
var
i,j:integer;
s1:string;
s:WideString;
b,b1:Byte;
begin
if TntRadioButton17.Checked then
begin
j:=strtoint(Edit15.Text);
i:=UTF16ToUTF8ForChar(Pointer(TntRichEdit1.Text),j,nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForChar(Pointer(TntRichEdit1.Text),j,Pointer(TmpUTF8Str))
=i
then
begin
s1:='<';
for i:=1 to Length(TmpUTF8Str)do
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
s1:=s1+chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
s1:=s1+chr(b1)+#32
end;
s1:=s1+'>';
s:='字符串中第'+Edit15.Text+'个编码单元所属字符的UTF-16编码单元序列'+
'已经转换为UTF-8编码单元序列'+s1;
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16ToUTF8ForChar函数',mb_ok)
end
end;
Edit15.SetFocus
end
else
begin
j:=TntRichEdit6.SelStart div 5 + 1;
i:=UTF16ToUTF8ForChar(Pointer(TntRichEdit1.Text),j,nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForChar(Pointer(TntRichEdit1.Text),j,Pointer(TmpUTF8Str))
=i
then
begin
s1:='<';
for i:=1 to Length(TmpUTF8Str)do
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
s1:=s1+chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
s1:=s1+chr(b1)+#32
end;
s1:=s1+'>';
s:='字符串中第'+inttostr(j)+'个编码单元所属字符的UTF-16编码单元序列'+
'已经转换为UTF-8编码单元序列'+s1;
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF16ToUTF8ForChar函数',mb_ok)
end
end;
TntRichEdit6.SetFocus
end
end;

procedure TForm1.Edit15KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton14.Enabled then
TntButton14.Click
end
end;

procedure TForm1.InitGroupBox7_1;
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit5.Text);
SetLength(s,5*Length(TntRichEdit5.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit5.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit6.Tag:=0;
TntRichEdit6.Text:=s
end;

procedure TForm1.InitGroupBox7_2;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit5.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit5.Text),Pointer(TmpUTF8Str))
=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit6.Tag:=2;
TntRichEdit6.Text:=s
end
end
end;

procedure TForm1.InitGroupBox7_5;
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit5.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit5.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit6.Tag:=3;
TntRichEdit6.Text:=s
end
end
end;

procedure TForm1.TntRadioButton19Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0,2,4:
InitGroupBox7_1;
1,3,6:
InitGroupBox7_2;
5,7:
InitGroupBox7_5
end;
TntRichEdit6.SetFocus;
TntRichEdit6.OnSelectionChange(TntRichEdit6)
end
end;

procedure TForm1.TntRadioButton20Click(Sender: TObject);
begin
Edit16.SetFocus;
Edit16.Text:='';
Edit16.OnChange(Edit16)
end;

procedure TForm1.TntRadioButton21Click(Sender: TObject);
begin
TntRichEdit6.SetFocus;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntButton15.Enabled:=true
end;

procedure TForm1.Edit16KeyPress(Sender: TObject;
var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
if TntButton15.Enabled then
TntButton15.Click
end
end;

procedure TForm1.TntButton15Click(Sender: TObject);
var
i,j,k:integer;
s:WideString;
s1:string;
cp:WORD;
b:Byte;
begin
if TntRadioButton20.Checked then
begin
i:=strtoint(Edit16.Text);
j:=UTF8ToUTF16ForChar(Pointer(TmpUTF8Str),i,nil);
if j>0 then
begin
SetLength(s,j);
if UTF8ToUTF16ForChar(Pointer(TmpUTF8Str),i,Pointer(s))=j then
begin
s1:='<';
for j:=1 to jdo
begin
if j>1 then
s1:=s1+#32;
cp:=ord(s[j]);
for k:=3do
wnto 0do
begin
b:=cp shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
s1:=s1+chr(b)
end
end;
s1:=s1+'>';
s:='字符串中第'+Edit16.Text+'个编码单元所属字符的UTF-8编码单元序列'+
'已经转换为UTF-16编码单元序列'+s1;
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF8ToUTF16ForChar函数',mb_ok)
end
end
end
else
begin
i:=TntRichEdit6.SelStart div 3 + 1;
j:=UTF8ToUTF16ForChar(Pointer(TmpUTF8Str),i,nil);
if j>0 then
begin
SetLength(s,j);
if UTF8ToUTF16ForChar(Pointer(TmpUTF8Str),i,Pointer(s))=j then
begin
s1:='<';
for j:=1 to jdo
begin
if j>1 then
s1:=s1+#32;
cp:=ord(s[j]);
for k:=3do
wnto 0do
begin
b:=cp shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
s1:=s1+chr(b)
end
end;
s1:=s1+'>';
s:='字符串中第'+inttostr(i)+'个编码单元所属字符的UTF-8编码单元序列'+
'已经转换为UTF-16编码单元序列'+s1;
MessageBoxW(Form1.Handle,Pointer(s),'试练UTF8ToUTF16ForChar函数',mb_ok)
end
end
end
end;

procedure TForm1.TntButton16Click(Sender: TObject);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit5.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit5.Text),Pointer(TmpUTF8Str))=i then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit6.Tag:=2;
TntRichEdit6.Text:=s;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntRichEdit6.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16字符串转换为UTF-8编码格式',
'试练UTF16ToUTF8ForStr函数',mb_ok)
end
end
end;

procedure TForm1.TntButton17Click(Sender: TObject);
var
i,j,k:integer;
s:WideString;
s1:string;
p:pChar;
cp:WORD;
b:Byte;
begin
i:=UTF8ToUTF16ForStr(Pointer(TmpUTF8Str),nil);
if i>0 then
begin
SetLength(s,i);
if UTF8ToUTF16ForStr(Pointer(TmpUTF8Str),Pointer(s))=i then
begin
SetLength(s1,5*i);
p:=Pointer(s1);
j:=0;
for i:=1 to ido
begin
cp:=ord(s);
for k:=3do
wnto 0do
begin
b:=cp shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit6.Tag:=0;
TntRichEdit6.Text:=s1;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntRichEdit6.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8字符串转换为UTF-16编码格式',
'试练UTF8ToUTF16ForStr函数',mb_ok)
end
end
end;

procedure TForm1.TntButton18Click(Sender: TObject);
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit5.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit5.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit6.Tag:=3;
TntRichEdit6.Text:=s;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntRichEdit6.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16字符串转换为UTF-32编码格式',
'试练UTF16ToUTF32ForStr函数',mb_ok)
end
end
end;

procedure TForm1.TntButton19Click(Sender: TObject);
var
i,j,k:integer;
s:string;
p:pChar;
s1:WideString;
cp:WORD;
b:Byte;
begin
i:=UTF32ToUTF16ForStr(@TmpUTF32Str[0],nil);
if i>0 then
begin
SetLength(s1,i);
if UTF32ToUTF16ForStr(@TmpUTF32Str[0],Pointer(s1))=i then
begin
SetLength(s,5*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
cp:=ord(s1);
for k:=3do
wnto 0do
begin
b:=cp shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit6.Tag:=0;
TntRichEdit6.Text:=s;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntRichEdit6.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32字符串转换为UTF-16编码格式',
'试练UTF32ToUTF16ForStr函数',mb_ok)
end
end
end;

procedure TForm1.TntButton20Click(Sender: TObject);
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF8ToUTF32ForStr(Pointer(TmpUTF8Str),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF8ToUTF32ForStr(Pointer(TmpUTF8Str),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit6.Tag:=3;
TntRichEdit6.Text:=s;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntRichEdit6.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8字符串转换为UTF-32编码格式',
'试练UTF8ToUTF32ForStr函数',mb_ok)
end
end
end;

procedure TForm1.TntButton21Click(Sender: TObject);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF32ToUTF8ForStr(@TmpUTF32Str[0],nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF32ToUTF8ForStr(@TmpUTF32Str[0],Pointer(TmpUTF8Str))=i then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit6.Tag:=2;
TntRichEdit6.Text:=s;
TntRichEdit6.OnSelectionChange(TntRichEdit6);
TntRichEdit6.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32字符串转换为UTF-8编码格式',
'试练UTF32ToUTF8ForStr函数',mb_ok)
end
end
end;

procedure TForm1.InitGroupBox8_1;
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit7.Text);
SetLength(s,5*Length(TntRichEdit7.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit7.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit8.Tag:=0;
TntRichEdit8.Text:=s
end;

procedure TForm1.InitGroupBox8_2;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit7.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit7.Text),Pointer(TmpUTF8Str))
=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit8.Tag:=2;
TntRichEdit8.Text:=s
end
end
end;

procedure TForm1.InitGroupBox8_3;
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit7.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit7.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit8.Tag:=3;
TntRichEdit8.Text:=s
end
end
end;

procedure TForm1.InitGroupBox9_1;
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit9.Text);
SetLength(s,5*Length(TntRichEdit9.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit9.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit10.Tag:=0;
TntRichEdit10.Text:=s
end;

procedure TForm1.InitGroupBox9_2;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit9.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit9.Text),Pointer(TmpUTF8Str))
=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit10.Tag:=2;
TntRichEdit10.Text:=s
end
end
end;

procedure TForm1.InitGroupBox9_3;
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit9.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit9.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit10.Tag:=3;
TntRichEdit10.Text:=s
end
end
end;

procedure TForm1.DispBSCommonProc_9(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit10.Tag:=BSType;
TntRichEdit10.Text:=s
end;

procedure TForm1.InitGroupBox9_4;
var
i:integer;
begin
i:=UTF16CUSToUTF8BS(Pointer(TntRichEdit9.Text),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF8BS(Pointer(TntRichEdit9.Text),Pointer(TmpUTFBS))
=i
then
DispBSCommonProc_9(4)
end
end;

procedure TForm1.InitGroupBox9_5;
var
i:integer;
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit9.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit9.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_9(5)
end
end;

procedure TForm1.InitGroupBox9_6;
var
i:integer;
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit9.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit9.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_9(6)
end
end;

procedure TForm1.InitGroupBox10_1;
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit11.Text);
SetLength(s,5*Length(TntRichEdit11.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit11.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit12.Tag:=0;
TntRichEdit12.Text:=s
end;

procedure TForm1.InitGroupBox10_2;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit11.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit11.Text),Pointer(TmpUTF8Str))
=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit12.Tag:=2;
TntRichEdit12.Text:=s
end
end
end;

procedure TForm1.InitGroupBox10_3;
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit11.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit11.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit12.Tag:=3;
TntRichEdit12.Text:=s
end
end
end;

procedure TForm1.DispBSCommonProc_10(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit12.Tag:=BSType;
TntRichEdit12.Text:=s
end;

procedure TForm1.InitGroupBox10_4;
var
i:integer;
begin
i:=UTF16CUSToUTF8BS(Pointer(TntRichEdit11.Text),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF8BS(Pointer(TntRichEdit11.Text),Pointer(TmpUTFBS))
=i
then
DispBSCommonProc_10(4)
end
end;

procedure TForm1.InitGroupBox10_5;
var
i:integer;
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit11.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit11.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_10(5)
end
end;

procedure TForm1.InitGroupBox10_6;
var
i:integer;
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit11.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit11.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_10(6)
end
end;

procedure TForm1.DispBSCommonProc_11(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit14.Tag:=BSType;
TntRichEdit14.Text:=s
end;

procedure TForm1.InitGroupBox11_4;
var
i:integer;
begin
i:=UTF16CUSToUTF8BS(Pointer(TntRichEdit13.Text),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF8BS(Pointer(TntRichEdit13.Text),Pointer(TmpUTFBS))
=i
then
DispBSCommonProc_11(4)
end
end;

procedure TForm1.InitGroupBox11_5;
var
i:integer;
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit13.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit13.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_11(5)
end
end;

procedure TForm1.InitGroupBox11_6;
var
i:integer;
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit13.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit13.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_11(6)
end
end;

procedure TForm1.InitGroupBox12_1;
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit15.Text);
SetLength(s,5*Length(TntRichEdit15.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit15.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit16.Tag:=0;
TntRichEdit16.Text:=s
end;

procedure TForm1.InitGroupBox12_2;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit15.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit15.Text),Pointer(TmpUTF8Str))
=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit16.Tag:=2;
TntRichEdit16.Text:=s
end
end
end;

procedure TForm1.InitGroupBox12_3;
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit15.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit15.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit16.Tag:=3;
TntRichEdit16.Text:=s
end
end
end;

procedure TForm1.DispBSCommonProc_12(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit16.Tag:=BSType;
TntRichEdit16.Text:=s
end;

procedure TForm1.InitGroupBox12_4;
var
i:integer;
begin
i:=UTF16CUSToUTF8BS(Pointer(TntRichEdit15.Text),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF8BS(Pointer(TntRichEdit15.Text),Pointer(TmpUTFBS))
=i
then
DispBSCommonProc_12(4)
end
end;

procedure TForm1.InitGroupBox12_5;
var
i:integer;
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit15.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit15.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_12(5)
end
end;

procedure TForm1.InitGroupBox12_6;
var
i:integer;
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit15.Text),BOMType_BE,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit15.Text),BOMType_BE,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_12(6)
end
end;

procedure TForm1.InitGroupBox13_1;
var
p:pWideChar;
i,j,k:integer;
s:string;
ps:pChar;
CU:WORD;
b:Byte;
begin
p:=Pointer(TntRichEdit17.Text);
SetLength(s,5*Length(TntRichEdit17.Text));
ps:=Pointer(s);
j:=0;
for i:=0 to Length(TntRichEdit17.Text)-1do
begin
CU:=ord(p);
for k:=3do
wnto 0do
begin
b:=CU shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
ps[j]:=chr(b);
inc(j)
end;
ps[j]:=#32;
inc(j)
end;
TntRichEdit18.Tag:=0;
TntRichEdit18.Text:=s
end;

procedure TForm1.InitGroupBox13_2;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16ToUTF8ForStr(Pointer(TntRichEdit17.Text),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16ToUTF8ForStr(Pointer(TntRichEdit17.Text),Pointer(TmpUTF8Str))
=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit18.Tag:=2;
TntRichEdit18.Text:=s
end
end
end;

procedure TForm1.InitGroupBox13_3;
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=UTF16ToUTF32ForStr(Pointer(TntRichEdit17.Text),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16ToUTF32ForStr(Pointer(TntRichEdit17.Text),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit18.Tag:=3;
TntRichEdit18.Text:=s
end
end
end;

procedure TForm1.DispBSCommonProc_13(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit18.Tag:=BSType;
TntRichEdit18.Text:=s
end;

procedure TForm1.InitGroupBox13_4;
var
i:integer;
begin
i:=UTF16CUSToUTF8BS(Pointer(TntRichEdit17.Text),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF8BS(Pointer(TntRichEdit17.Text),Pointer(TmpUTFBS))
=i
then
DispBSCommonProc_13(4)
end
end;

procedure TForm1.InitGroupBox13_5;
var
i:integer;
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit17.Text),TntComboBox12.Tag,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit17.Text),TntComboBox12.Tag,Pointer(
TmpUTFBS))=i
then
DispBSCommonProc_13(5)
end
end;

procedure TForm1.InitGroupBox13_6;
var
i:integer;
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit17.Text),TntComboBox14.Tag,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit17.Text),TntComboBox14.Tag,
Pointer(TmpUTFBS))=i
then
DispBSCommonProc_13(6)
end
end;

procedure TForm1.DispBSCommonProc_14(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit20.Tag:=BSType;
TntRichEdit20.Text:=s
end;

procedure TForm1.DispBSCommonProc_15(BSType:integer);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=Length(TmpUTFBS);
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit22.Tag:=BSType;
TntRichEdit22.Text:=s
end;

procedure TForm1.TntRichEdit7Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0:
InitGroupBox8_1;
1:
InitGroupBox8_2;
2:
InitGroupBox8_3
end
end;

procedure TForm1.TntRichEdit7DblClick(Sender: TObject);
begin
TntRichEdit7.ReadOnly:=not TntRichEdit7.ReadOnly;
if TntRichEdit7.ReadOnly then
begin
TntRichEdit7.Cursor:=crArrow;
TntRichEdit7.OnSelectionChange(TntRichEdit7)
end
else
begin
TntRichEdit7.Cursor:=crDefault;
TntRichEdit7.SelLength:=0
end;
TntRichEdit8.HideSelection:=not TntRichEdit7.ReadOnly;
TntRichEdit7.Tag:=0
end;

procedure TForm1.TntRichEdit7SelectionChange(Sender: TObject);
var
i,j,charsize:integer;
begin
if TntRichEdit7.ReadOnly then
if TntRichEdit7.Tag=0 then
begin
TntRichEdit7.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit7.Text),
TntRichEdit7.SelStart+1))=BMPCP
then
TntRichEdit7.SelLength:=1
else
TntRichEdit7.SelLength:=2;
if TntRichEdit8.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit8.Tag;
TntRichEdit8.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit8.SelStart:=TntRichEdit7.SelStart*5;
if TntRichEdit7.SelLength=1 then
TntRichEdit8.SelLength:=4
else
TntRichEdit8.SelLength:=9
end;
2:
begin
i:=UTF16CUToCharIndex(Pointer(TntRichEdit7.Text),
TntRichEdit7.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
TntRichEdit8.SelStart:=(i-1)*3;
TntRichEdit8.SelLength:=(charsize-1)*3+2
end;
3:
begin
TntRichEdit8.SelStart:=TntRichEdit7.SelStart*9;
TntRichEdit8.SelLength:=8
end
end
end
end
else
if TntRichEdit7.SelLength>0 then
TntRichEdit7.Tag:=0
end;

procedure TForm1.TntRichEdit8SelectionChange(Sender: TObject);
var
i,j:integer;
begin
if TntRichEdit8.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit8.Tag;
case TntRichEdit8.Tag of
0:
begin
i:=TntRichEdit8.SelStart div 5 + 1;
TntRichEdit8.Tag:=1;
TntRichEdit8.SelStart:=(i-1)*5;
TntRichEdit8.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit7.Text),i,@j);
TntRichEdit7.Tag:=1;
TntRichEdit7.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit7.Text),i))=BMPCP then
TntRichEdit7.SelLength:=1
else
TntRichEdit7.SelLength:=2
end;
2:
begin
i:=TntRichEdit8.SelStart div 3 + 1;
TntRichEdit8.Tag:=1;
TntRichEdit8.SelStart:=(i-1)*3;
TntRichEdit8.SelLength:=2;
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit7.Text),i,true);
TntRichEdit7.Tag:=1;
TntRichEdit7.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit7.Text),i))=BMPCP then
TntRichEdit7.SelLength:=1
else
TntRichEdit7.SelLength:=2
end;
3:
begin
i:=TntRichEdit8.SelStart div 9 + 1;
TntRichEdit8.Tag:=1;
TntRichEdit8.SelStart:=(i-1)*9;
TntRichEdit8.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit7.Text),i,true);
TntRichEdit7.Tag:=1;
TntRichEdit7.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit7.Text),i))=BMPCP then
TntRichEdit7.SelLength:=1
else
TntRichEdit7.SelLength:=2
end;
1:
if TntRichEdit8.SelLength>0 then
TntRichEdit8.Tag:=TntGroupBox14.Tag
end;
TntRichEdit7.Tag:=0
end;

procedure TForm1.TntRadioButton29Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0:
InitGroupBox8_1;
1:
InitGroupBox8_2;
2:
InitGroupBox8_3
end;
TntRichEdit8.SetFocus;
TntRichEdit8.OnSelectionChange(TntRichEdit8)
end
end;

procedure TForm1.TntButton22Click(Sender: TObject);
var
s:WideString;
begin
s:='UTF-16字符串里面共有'+inttostr(CharCountOfUTF16Str(Pointer(
TntRichEdit7.Text)))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练CharCountOfUTF16Str函数',mb_ok)
end;

procedure TForm1.TntButton23Click(Sender: TObject);
var
s:WideString;
begin
s:='UTF-8字符串里面共有'+inttostr(CharCountOfUTF8Str(Pointer(TmpUTF8Str)))+
'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练CharCountOfUTF16Str函数',mb_ok)
end;

procedure TForm1.TntButton24Click(Sender: TObject);
var
s:WideString;
begin
s:='UTF-32字符串里面共有'+inttostr(CharCountOfUTF32Str(@TmpUTF32Str[0]))+
'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练CharCountOfUTF16Str函数',mb_ok)
end;

procedure TForm1.TntTabSheet9Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit9.Text:=TntRichEdit1.Text;
TntRichEdit9.OnSelectionChange(TntRichEdit9);
TntRichEdit9.SetFocus;
TntRichEdit9.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet9.ControlCount-1do
if TntTabSheet9.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet9.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet9.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet9.Controls as TTntGroupBox
end
end;

procedure TForm1.TntTabSheet5Show(Sender: TObject);
begin
TntRichEdit1.Text:=WideString('这是由Delphi大富翁韦剑共享出来的Unicode编码'+
'处理例程库演示程序。你现在看到的这段演示文本里面包含有两个属于Unicode第2增'+
'补平面的CJK ExtB汉字,它们是U+20000的【')+WideChar($D840)+WideChar($DC00)+
WideString('】和U+20001的【')+WideChar($D840)+WideChar($DC01)+
WideString('】。如果你的系统上无法看到这两个汉字,可以安装海峰五笔的超大'+
'字集支持包(http://okuc.net/software/UniFonts.exe)来解决。');
TntRichEdit1.OnSelectionChange(TntRichEdit1);
TntRichEdit1.SetFocus;
TntRichEdit1.Tag:=0
end;

procedure TForm1.TntTabSheet6Show(Sender: TObject);
begin
TntRichEdit2.Text:=TntRichEdit1.Text;
TntRichEdit2.OnSelectionChange(TntRichEdit2);
TntRichEdit2.SetFocus;
TntRichEdit2.Tag:=0
end;

procedure TForm1.TntTabSheet7Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit5.Text:=TntRichEdit1.Text;
TntRichEdit5.OnSelectionChange(TntRichEdit5);
TntRichEdit5.SetFocus;
TntRichEdit5.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet7.ControlCount-1do
if TntTabSheet7.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet7.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet7.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet7.Controls as TTntGroupBox
end
end;

procedure TForm1.TntTabSheet8Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit7.Text:=TntRichEdit1.Text;
TntRichEdit7.OnSelectionChange(TntRichEdit7);
TntRichEdit7.SetFocus;
TntRichEdit7.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet8.ControlCount-1do
if TntTabSheet8.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet8.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet8.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet8.Controls as TTntGroupBox
end
end;

procedure TForm1.TntTabSheet1Show(Sender: TObject);
var
i:integer;
TntTabSheet:TTntTabSheet;
begin
if Sender is TTntTabSheet then
begin
TntTabSheet:=Sender as TTntTabSheet;
for i:=TntTabSheet.ControlCount-1do
wnto 0do
if TntTabSheet.Controls is TTntPageControl then
(TntTabSheet.Controls as TTntPageControl).ActivePage.OnShow(
(TntTabSheet.Controls as TTntPageControl).ActivePage)
end
end;

procedure TForm1.TntRichEdit9Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0:
InitGroupBox9_2;
1:
InitGroupBox9_4;
2:
InitGroupBox9_1;
3:
InitGroupBox9_5;
4:
InitGroupBox9_3;
5:
InitGroupBox9_6
end
end;

procedure TForm1.TntRichEdit9DblClick(Sender: TObject);
begin
TntRichEdit9.ReadOnly:=not TntRichEdit9.ReadOnly;
if TntRichEdit9.ReadOnly then
begin
TntRichEdit9.Cursor:=crArrow;
TntRichEdit9.OnSelectionChange(TntRichEdit9)
end
else
begin
TntRichEdit9.Cursor:=crDefault;
TntRichEdit9.SelLength:=0
end;
TntRichEdit10.HideSelection:=not TntRichEdit9.ReadOnly;
TntRichEdit9.Tag:=0
end;

procedure TForm1.TntRichEdit9SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit9.ReadOnly then
if TntRichEdit9.Tag=0 then
begin
TntRichEdit9.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),
TntRichEdit9.SelStart+1))=BMPCP
then
TntRichEdit9.SelLength:=1
else
TntRichEdit9.SelLength:=2;
if TntRichEdit10.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit10.Tag;
TntRichEdit10.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit10.SelStart:=TntRichEdit9.SelStart*5;
if TntRichEdit9.SelLength=1 then
TntRichEdit10.SelLength:=4
else
TntRichEdit10.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit9.Text),
TntRichEdit9.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit10.SelStart:=(i-1)*3;
TntRichEdit10.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit9.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit9.Text),i,true);
TntRichEdit10.SelStart:=(i-1)*9;
TntRichEdit10.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit9.SelStart+1
else
i:=TntRichEdit9.SelStart;
TntRichEdit10.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),
TntRichEdit9.SelStart+1))=BMPCP
then
TntRichEdit10.SelLength:=5
else
TntRichEdit10.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit9.Text),
TntRichEdit9.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit10.SelStart:=i*4*3;
TntRichEdit10.SelLength:=11
end
end
end
end
else
if TntRichEdit9.SelLength>0 then
TntRichEdit9.Tag:=0
end;

procedure TForm1.TntRichEdit10SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit10.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit10.Tag;
case TntRichEdit10.Tag of
0:
begin
i:=TntRichEdit10.SelStart div 5 + 1;
TntRichEdit10.Tag:=1;
TntRichEdit10.SelStart:=(i-1)*5;
TntRichEdit10.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit9.Text),i,@j);
TntRichEdit9.Tag:=1;
TntRichEdit9.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),i))=BMPCP then
TntRichEdit9.SelLength:=1
else
TntRichEdit9.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit10.SelStart div 3 + 1;
TntRichEdit10.Tag:=1;
TntRichEdit10.SelStart:=(i-1)*3;
TntRichEdit10.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit9.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit9.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit9.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit9.Text),i,true);
TntRichEdit9.Tag:=1;
TntRichEdit9.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),i))=BMPCP then
TntRichEdit9.SelLength:=1
else
TntRichEdit9.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit10.SelStart div 9 + 1;
TntRichEdit10.Tag:=1;
TntRichEdit10.SelStart:=(i-1)*9;
TntRichEdit10.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit9.Text),i,true);
TntRichEdit9.Tag:=1;
TntRichEdit9.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),i))=BMPCP then
TntRichEdit9.SelLength:=1
else
TntRichEdit9.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit10.SelStart div 3 + 1;
TntRichEdit10.Tag:=1;
TntRichEdit10.SelStart:=(i-1)*3;
TntRichEdit10.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit9.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit9.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit9.HideSelection:=false;
if not TntRichEdit9.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit9.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit9.Text),i,true);
TntRichEdit9.Tag:=1;
TntRichEdit9.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),i))=BMPCP then
TntRichEdit9.SelLength:=1
else
TntRichEdit9.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit10.SelStart div 3 + 1;
TntRichEdit10.Tag:=1;
TntRichEdit10.SelStart:=(i-1)*3;
TntRichEdit10.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit9.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit9.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit9.HideSelection:=false;
if not TntRichEdit9.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit9.Text),i,true);
TntRichEdit9.Tag:=1;
TntRichEdit9.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit9.Text),i))=BMPCP then
TntRichEdit9.SelLength:=1
else
TntRichEdit9.SelLength:=2
end
end;
1:
if TntRichEdit10.SelLength>0 then
TntRichEdit10.Tag:=TntGroupBox14.Tag
end;
TntRichEdit9.Tag:=0
end;

procedure TForm1.TntButton25Click(Sender: TObject);
label 10;
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
if TntComboBox1.ItemIndex=0 then
begin
TmpUTFBS:=TmpUTF8Str;
i:=Length(TmpUTFBS);
goto 10
end
else
begin
i:=CUSToBSForUTF8(Pointer(TmpUTF8Str),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF8(Pointer(TmpUTF8Str),Pointer(TmpUTFBS))=i then
begin
10:
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit10.Tag:=4;
TntRichEdit10.Text:=s;
TntRichEdit10.OnSelectionChange(TntRichEdit10);
TntRichEdit10.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8编码单元序列转换为带或不带'+
'BOM的UTF-8编码格式字节序列','试练CUSToBSForUTF8函数',mb_ok)
end
end
end
end;

procedure TForm1.TntRadioButton32Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0:
InitGroupBox9_2;
1:
InitGroupBox9_4;
2:
InitGroupBox9_1;
3:
InitGroupBox9_5;
4:
InitGroupBox9_3;
5:
InitGroupBox9_6
end;
TntRichEdit9.SetFocus;
TntRichEdit9.OnSelectionChange(TntRichEdit9)
end
end;

procedure TForm1.TntButton26Click(Sender: TObject);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=BSToCUSForUTF8(Pointer(TmpUTFBS),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if BSToCUSForUTF8(Pointer(TmpUTFBS),Pointer(TmpUTF8Str))=i then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit10.Tag:=2;
TntRichEdit10.Text:=s;
TntRichEdit10.OnSelectionChange(TntRichEdit10);
TntRichEdit10.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8编码格式字节序列转换为UTF-8'+
'编码单元序列','试练BSToCUSForUTF8函数',mb_ok)
end
end
end;

procedure TForm1.TntButton27Click(Sender: TObject);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit9.Text),TntComboBox2.ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit9.Text),TntComboBox2.ItemIndex,
Pointer(TmpUTFBS))=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTFBS);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit10.Tag:=5;
TntRichEdit10.Text:=s;
TntRichEdit10.OnSelectionChange(TntRichEdit10);
TntRichEdit10.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16编码单元序列转换为带或不带'+
'BOM的UTF-16编码格式字节序列','试练CUSToBSForUTF16函数',mb_ok)
end
end
end;

procedure TForm1.TntButton28Click(Sender: TObject);
var
i,j,k:integer;
s:WideString;
s1:string;
p:pChar;
cp:WORD;
b:Byte;
begin
i:=BSToCUSForUTF16(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if BSToCUSForUTF16(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))=i then
begin
SetLength(s1,5*i);
p:=Pointer(s1);
j:=0;
for i:=1 to ido
begin
cp:=ord(s);
for k:=3do
wnto 0do
begin
b:=cp shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j);
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit10.Tag:=0;
TntRichEdit10.Text:=s1;
TntRichEdit10.OnSelectionChange(TntRichEdit10);
TntRichEdit10.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把带或不带BOM的UTF-16编码格式字节序列'+
'转换为UTF-16编码单元序列','试练BSToCUSForUTF16函数',mb_ok)
end
end
end;

procedure TForm1.TntButton29Click(Sender: TObject);
var
i:integer;
begin
i:=CUSToBSForUTF32(@TmpUTF32Str[0],TntComboBox3.ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF32(@TmpUTF32Str[0],TntComboBox3.ItemIndex,Pointer(
TmpUTFBS))=i
then
begin
DispBSCommonProc_9(6);
TntRichEdit10.OnSelectionChange(TntRichEdit10);
TntRichEdit10.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32编码单元序列转换为带或不带'+
'BOM的UTF-32编码格式字节序列','试练CUSToBSForUTF32函数',mb_ok)
end
end
end;

procedure TForm1.TntButton30Click(Sender: TObject);
var
i,j,k:integer;
s:string;
p:pChar;
b:Byte;
begin
i:=BSToCUSForUTF32(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if BSToCUSForUTF32(Pointer(TmpUTFBS),Length(TmpUTFBS),@TmpUTF32Str[0])=
i-1
then
begin
SetLength(s,9*(i-1));
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
for k:=7do
wnto 0do
begin
b:=TmpUTF32Str shr (k*4) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j);
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit10.Tag:=3;
TntRichEdit10.Text:=s;
TntRichEdit10.OnSelectionChange(TntRichEdit10);
TntRichEdit10.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把带或不带BOM的UTF-32编码格式字节序列'+
'转换为UTF-32编码单元序列','试练BSToCUSForUTF32函数',mb_ok)
end
end
end;

procedure TForm1.TntTabSheet10Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit11.Text:=TntRichEdit1.Text;
TntRichEdit11.OnSelectionChange(TntRichEdit11);
TntRichEdit11.SetFocus;
TntRichEdit11.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet10.ControlCount-1do
if TntTabSheet10.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet10.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet10.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet10.Controls as TTntGroupBox
end
end;

procedure TForm1.TntRichEdit11Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0,1:
InitGroupBox10_4;
2,3:
InitGroupBox10_5;
4,5:
InitGroupBox10_6
end
end;

procedure TForm1.TntRadioButton38Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0,1:
InitGroupBox10_4;
2,3:
InitGroupBox10_5;
4,5:
InitGroupBox10_6
end;
TntRichEdit11.SetFocus;
TntRichEdit11.OnSelectionChange(TntRichEdit11)
end
end;

procedure TForm1.TntRichEdit11DblClick(Sender: TObject);
begin
TntRichEdit11.ReadOnly:=not TntRichEdit11.ReadOnly;
if TntRichEdit11.ReadOnly then
begin
TntRichEdit11.Cursor:=crArrow;
TntRichEdit11.OnSelectionChange(TntRichEdit11)
end
else
begin
TntRichEdit11.Cursor:=crDefault;
TntRichEdit11.SelLength:=0
end;
TntRichEdit12.HideSelection:=not TntRichEdit11.ReadOnly;
TntRichEdit11.Tag:=0
end;

procedure TForm1.TntRichEdit11SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit11.ReadOnly then
if TntRichEdit11.Tag=0 then
begin
TntRichEdit11.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),
TntRichEdit11.SelStart+1))=BMPCP
then
TntRichEdit11.SelLength:=1
else
TntRichEdit11.SelLength:=2;
if TntRichEdit12.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit12.Tag;
TntRichEdit12.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit12.SelStart:=TntRichEdit11.SelStart*5;
if TntRichEdit11.SelLength=1 then
TntRichEdit12.SelLength:=4
else
TntRichEdit12.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit11.Text),
TntRichEdit11.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit12.SelStart:=(i-1)*3;
TntRichEdit12.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit11.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit11.Text),i,true);
TntRichEdit12.SelStart:=(i-1)*9;
TntRichEdit12.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit11.SelStart+1
else
i:=TntRichEdit11.SelStart;
TntRichEdit12.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),
TntRichEdit11.SelStart+1))=BMPCP
then
TntRichEdit12.SelLength:=5
else
TntRichEdit12.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit11.Text),
TntRichEdit11.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit12.SelStart:=i*4*3;
TntRichEdit12.SelLength:=11
end
end
end
end
else
if TntRichEdit11.SelLength>0 then
TntRichEdit11.Tag:=0
end;

procedure TForm1.TntRichEdit12SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit12.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit12.Tag;
case TntRichEdit12.Tag of
0:
begin
i:=TntRichEdit12.SelStart div 5 + 1;
TntRichEdit12.Tag:=1;
TntRichEdit12.SelStart:=(i-1)*5;
TntRichEdit12.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit11.Text),i,@j);
TntRichEdit11.Tag:=1;
TntRichEdit11.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),i))=BMPCP then
TntRichEdit11.SelLength:=1
else
TntRichEdit11.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit12.SelStart div 3 + 1;
TntRichEdit12.Tag:=1;
TntRichEdit12.SelStart:=(i-1)*3;
TntRichEdit12.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit11.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit11.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit11.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit11.Text),i,true);
TntRichEdit11.Tag:=1;
TntRichEdit11.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),i))=BMPCP then
TntRichEdit11.SelLength:=1
else
TntRichEdit11.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit12.SelStart div 9 + 1;
TntRichEdit12.Tag:=1;
TntRichEdit12.SelStart:=(i-1)*9;
TntRichEdit12.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit11.Text),i,true);
TntRichEdit11.Tag:=1;
TntRichEdit11.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),i))=BMPCP then
TntRichEdit11.SelLength:=1
else
TntRichEdit11.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit12.SelStart div 3 + 1;
TntRichEdit12.Tag:=1;
TntRichEdit12.SelStart:=(i-1)*3;
TntRichEdit12.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit11.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit11.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit11.HideSelection:=false;
if not TntRichEdit11.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit11.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit11.Text),i,true);
TntRichEdit11.Tag:=1;
TntRichEdit11.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),i))=BMPCP then
TntRichEdit11.SelLength:=1
else
TntRichEdit11.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit12.SelStart div 3 + 1;
TntRichEdit12.Tag:=1;
TntRichEdit12.SelStart:=(i-1)*3;
TntRichEdit12.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit11.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit11.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit11.HideSelection:=false;
if not TntRichEdit11.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit11.Text),i,true);
TntRichEdit11.Tag:=1;
TntRichEdit11.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit11.Text),i))=BMPCP then
TntRichEdit11.SelLength:=1
else
TntRichEdit11.SelLength:=2
end
end;
1:
if TntRichEdit12.SelLength>0 then
TntRichEdit12.Tag:=TntGroupBox14.Tag
end;
TntRichEdit11.Tag:=0
end;

procedure TForm1.TntButton31Click(Sender: TObject);
var
i:integer;
s:string;
begin
i:=Length(TmpUTFBS);
if not (TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80))
in [BS_UTF8WithBOM,BS_UTF8WithoutBOM])
then
InitGroupBox10_4;
i:=UTF8ToUTF16ForBS(Pointer(TmpUTFBS),TntComboBox4.ItemIndex,nil);
if i>0 then
begin
SetLength(s,i);
if UTF8ToUTF16ForBS(Pointer(TmpUTFBS),TntComboBox4.ItemIndex,
Pointer(s))=i
then
begin
TmpUTFBS:=s;
DispBSCommonProc_10(5)
end;
TntRichEdit12.OnSelectionChange(TntRichEdit12);
TntRichEdit12.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8编码格式字节序列转换为带或不带'+
'BOM的UTF-16编码格式字节序列','试练UTF8ToUTF16ForBS函数',mb_ok)
end
end;

procedure TForm1.TntButton32Click(Sender: TObject);
var
i:integer;
s:string;
begin
i:=Length(TmpUTFBS);
if not (TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80))
in [BS_UTF8WithBOM,BS_UTF8WithoutBOM])
then
InitGroupBox10_4;
i:=UTF8ToUTF32ForBS(Pointer(TmpUTFBS),TntComboBox5.ItemIndex,nil);
if i>0 then
begin
SetLength(s,i);
if UTF8ToUTF32ForBS(Pointer(TmpUTFBS),TntComboBox5.ItemIndex,
Pointer(s))=i
then
begin
TmpUTFBS:=s;
DispBSCommonProc_10(6)
end;
TntRichEdit12.OnSelectionChange(TntRichEdit12);
TntRichEdit12.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8编码格式字节序列转换为带或不带'+
'BOM的UTF-32编码格式字节序列','试练UTF8ToUTF32ForBS函数',mb_ok)
end
end;

procedure TForm1.TntButton33Click(Sender: TObject);
var
i:integer;
s:string;
begin
i:=UTF16ToUTF8ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF8ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))=i then
begin
TmpUTFBS:=s;
DispBSCommonProc_10(4)
end;
TntRichEdit12.OnSelectionChange(TntRichEdit12);
TntRichEdit12.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16编码格式字节序列转换为带BOM的'+
'UTF-8编码格式字节序列','试练UTF16ToUTF8ForBS函数',mb_ok)
end
end;

procedure TForm1.TntButton34Click(Sender: TObject);
var
i:integer;
s:string;
begin
i:=Length(TmpUTFBS);
if not (TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80))
in [BS_UTF16Default..BS_UTF16LE])
then
InitGroupBox10_5;
i:=UTF16ToUTF32ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),
TntComboBox6.ItemIndex,nil);
if i>0 then
begin
SetLength(s,i);
if UTF16ToUTF32ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),
TntComboBox6.ItemIndex,Pointer(s))=i
then
begin
TmpUTFBS:=s;
DispBSCommonProc_10(6)
end;
TntRichEdit12.OnSelectionChange(TntRichEdit12);
TntRichEdit12.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16编码格式字节序列转换为带或不带'+
'BOM的UTF-32编码格式字节序列','试练UTF16ToUTF32ForBS函数',mb_ok)
end
end;

procedure TForm1.TntButton35Click(Sender: TObject);
var
i:integer;
s:string;
begin
i:=UTF32ToUTF8ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF32ToUTF8ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))=i then
begin
TmpUTFBS:=s;
DispBSCommonProc_10(4)
end;
TntRichEdit12.OnSelectionChange(TntRichEdit12);
TntRichEdit12.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32编码格式字节序列转换为带BOM的'+
'UTF-8编码格式字节序列','试练UTF32ToUTF8ForBS函数',mb_ok)
end
end;

procedure TForm1.TntButton36Click(Sender: TObject);
var
i:integer;
s:string;
begin
i:=Length(TmpUTFBS);
if not (TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80))
in [BS_UTF32Default..BS_UTF32LE])
then
InitGroupBox10_6;
i:=UTF32ToUTF16ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),
TntComboBox7.ItemIndex,nil);
if i>0 then
begin
SetLength(s,i);
if UTF32ToUTF16ForBS(Pointer(TmpUTFBS),Length(TmpUTFBS),
TntComboBox7.ItemIndex,Pointer(s))=i
then
begin
TmpUTFBS:=s;
DispBSCommonProc_10(5)
end;
TntRichEdit12.OnSelectionChange(TntRichEdit12);
TntRichEdit12.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32编码格式字节序列转换为带或不带'+
'BOM的UTF-16编码格式字节序列','试练UTF32ToUTF16ForBS函数',mb_ok)
end
end;

procedure TForm1.TntTabSheet11Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit13.Text:=TntRichEdit1.Text;
TntRichEdit13.OnSelectionChange(TntRichEdit13);
TntRichEdit13.SetFocus;
TntRichEdit13.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet11.ControlCount-1do
if TntTabSheet11.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet11.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet11.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet11.Controls as TTntGroupBox
end
end;

procedure TForm1.TntRadioButton44Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0:
InitGroupBox11_4;
1:
InitGroupBox11_5;
2:
InitGroupBox11_6
end;
TntRichEdit13.SetFocus;
TntRichEdit13.OnSelectionChange(TntRichEdit13)
end
end;

procedure TForm1.TntRichEdit13Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0:
InitGroupBox11_4;
1:
InitGroupBox11_5;
2:
InitGroupBox11_6
end
end;

procedure TForm1.TntRichEdit13DblClick(Sender: TObject);
begin
TntRichEdit13.ReadOnly:=not TntRichEdit13.ReadOnly;
if TntRichEdit13.ReadOnly then
begin
TntRichEdit13.Cursor:=crArrow;
TntRichEdit13.OnSelectionChange(TntRichEdit13)
end
else
begin
TntRichEdit13.Cursor:=crDefault;
TntRichEdit13.SelLength:=0
end;
TntRichEdit14.HideSelection:=not TntRichEdit13.ReadOnly;
TntRichEdit13.Tag:=0
end;

procedure TForm1.TntRichEdit13SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit13.ReadOnly then
if TntRichEdit13.Tag=0 then
begin
TntRichEdit13.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),
TntRichEdit13.SelStart+1))=BMPCP
then
TntRichEdit13.SelLength:=1
else
TntRichEdit13.SelLength:=2;
if TntRichEdit14.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit14.Tag;
TntRichEdit14.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit14.SelStart:=TntRichEdit13.SelStart*5;
if TntRichEdit13.SelLength=1 then
TntRichEdit14.SelLength:=4
else
TntRichEdit14.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit13.Text),
TntRichEdit13.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit14.SelStart:=(i-1)*3;
TntRichEdit14.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit13.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit13.Text),i,true);
TntRichEdit14.SelStart:=(i-1)*9;
TntRichEdit14.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit13.SelStart+1
else
i:=TntRichEdit13.SelStart;
TntRichEdit14.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),
TntRichEdit13.SelStart+1))=BMPCP
then
TntRichEdit14.SelLength:=5
else
TntRichEdit14.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit13.Text),
TntRichEdit13.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit14.SelStart:=i*4*3;
TntRichEdit14.SelLength:=11
end
end
end
end
else
if TntRichEdit13.SelLength>0 then
TntRichEdit13.Tag:=0
end;

procedure TForm1.TntRichEdit14SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit14.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit14.Tag;
case TntRichEdit14.Tag of
0:
begin
i:=TntRichEdit14.SelStart div 5 + 1;
TntRichEdit14.Tag:=1;
TntRichEdit14.SelStart:=(i-1)*5;
TntRichEdit14.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit13.Text),i,@j);
TntRichEdit13.Tag:=1;
TntRichEdit13.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),i))=BMPCP then
TntRichEdit13.SelLength:=1
else
TntRichEdit13.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit14.SelStart div 3 + 1;
TntRichEdit14.Tag:=1;
TntRichEdit14.SelStart:=(i-1)*3;
TntRichEdit14.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit13.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit13.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit13.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit13.Text),i,true);
TntRichEdit13.Tag:=1;
TntRichEdit13.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),i))=BMPCP then
TntRichEdit13.SelLength:=1
else
TntRichEdit13.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit14.SelStart div 9 + 1;
TntRichEdit14.Tag:=1;
TntRichEdit14.SelStart:=(i-1)*9;
TntRichEdit14.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit13.Text),i,true);
TntRichEdit13.Tag:=1;
TntRichEdit13.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),i))=BMPCP then
TntRichEdit13.SelLength:=1
else
TntRichEdit13.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit14.SelStart div 3 + 1;
TntRichEdit14.Tag:=1;
TntRichEdit14.SelStart:=(i-1)*3;
TntRichEdit14.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit13.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit13.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit13.HideSelection:=false;
if not TntRichEdit13.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit13.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit13.Text),i,true);
TntRichEdit13.Tag:=1;
TntRichEdit13.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),i))=BMPCP then
TntRichEdit13.SelLength:=1
else
TntRichEdit13.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit14.SelStart div 3 + 1;
TntRichEdit14.Tag:=1;
TntRichEdit14.SelStart:=(i-1)*3;
TntRichEdit14.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit13.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit13.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit13.HideSelection:=false;
if not TntRichEdit13.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit13.Text),i,true);
TntRichEdit13.Tag:=1;
TntRichEdit13.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit13.Text),i))=BMPCP then
TntRichEdit13.SelLength:=1
else
TntRichEdit13.SelLength:=2
end
end;
1:
if TntRichEdit14.SelLength>0 then
TntRichEdit14.Tag:=TntGroupBox14.Tag
end;
TntRichEdit13.Tag:=0
end;

procedure TForm1.TntButton37Click(Sender: TObject);
var
s:WideString;
begin
s:='当前UTF-8编码格式字节序列中共有'+inttostr(CharCountOfUTF8BS(Pointer(
TmpUTFBS)))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练CharCountOfUTF8BS函数',
mb_ok)
end;

procedure TForm1.TntButton38Click(Sender: TObject);
var
s:WideString;
begin
s:='当前UTF-16编码格式字节序列中共有'+inttostr(CharCountOfUTF16BS(Pointer(
TmpUTFBS),Length(TmpUTFBS)))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练CharCountOfUTF16BS函数',
mb_ok)
end;

procedure TForm1.TntButton39Click(Sender: TObject);
var
s:WideString;
begin
s:='当前UTF-32编码格式字节序列中共有'+inttostr(CharCountOfUTF32BS(Pointer(
TmpUTFBS),Length(TmpUTFBS)))+'个字符';
MessageBoxW(Form1.Handle,Pointer(s),'试练CharCountOfUTF32BS函数',
mb_ok)
end;

procedure TForm1.TntTabSheet12Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit15.Text:=TntRichEdit1.Text;
TntRichEdit15.OnSelectionChange(TntRichEdit15);
TntRichEdit15.SetFocus;
TntRichEdit15.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet12.ControlCount-1do
if TntTabSheet12.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet12.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet12.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet12.Controls as TTntGroupBox
end
end;

procedure TForm1.TntRichEdit15Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0,1:
InitGroupBox12_2;
2,3:
InitGroupBox12_1;
4,5:
InitGroupBox12_3
end
end;

procedure TForm1.TntRichEdit15DblClick(Sender: TObject);
begin
TntRichEdit15.ReadOnly:=not TntRichEdit15.ReadOnly;
if TntRichEdit15.ReadOnly then
begin
TntRichEdit15.Cursor:=crArrow;
TntRichEdit15.OnSelectionChange(TntRichEdit15)
end
else
begin
TntRichEdit15.Cursor:=crDefault;
TntRichEdit15.SelLength:=0
end;
TntRichEdit16.HideSelection:=not TntRichEdit15.ReadOnly;
TntRichEdit15.Tag:=0
end;

procedure TForm1.TntRichEdit15SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit15.ReadOnly then
if TntRichEdit15.Tag=0 then
begin
TntRichEdit15.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),
TntRichEdit15.SelStart+1))=BMPCP
then
TntRichEdit15.SelLength:=1
else
TntRichEdit15.SelLength:=2;
if TntRichEdit16.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit16.Tag;
TntRichEdit16.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit16.SelStart:=TntRichEdit15.SelStart*5;
if TntRichEdit15.SelLength=1 then
TntRichEdit16.SelLength:=4
else
TntRichEdit16.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit15.Text),
TntRichEdit15.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit16.SelStart:=(i-1)*3;
TntRichEdit16.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit15.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit15.Text),i,true);
TntRichEdit16.SelStart:=(i-1)*9;
TntRichEdit16.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit15.SelStart+1
else
i:=TntRichEdit15.SelStart;
TntRichEdit16.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),
TntRichEdit15.SelStart+1))=BMPCP
then
TntRichEdit16.SelLength:=5
else
TntRichEdit16.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit15.Text),
TntRichEdit15.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit16.SelStart:=i*4*3;
TntRichEdit16.SelLength:=11
end
end
end
end
else
if TntRichEdit15.SelLength>0 then
TntRichEdit15.Tag:=0
end;

procedure TForm1.TntRichEdit16SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit16.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit16.Tag;
case TntRichEdit16.Tag of
0:
begin
i:=TntRichEdit16.SelStart div 5 + 1;
TntRichEdit16.Tag:=1;
TntRichEdit16.SelStart:=(i-1)*5;
TntRichEdit16.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit15.Text),i,@j);
TntRichEdit15.Tag:=1;
TntRichEdit15.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),i))=BMPCP then
TntRichEdit15.SelLength:=1
else
TntRichEdit15.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit16.SelStart div 3 + 1;
TntRichEdit16.Tag:=1;
TntRichEdit16.SelStart:=(i-1)*3;
TntRichEdit16.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit15.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit15.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit15.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit15.Text),i,true);
TntRichEdit15.Tag:=1;
TntRichEdit15.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),i))=BMPCP then
TntRichEdit15.SelLength:=1
else
TntRichEdit15.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit16.SelStart div 9 + 1;
TntRichEdit16.Tag:=1;
TntRichEdit16.SelStart:=(i-1)*9;
TntRichEdit16.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit15.Text),i,true);
TntRichEdit15.Tag:=1;
TntRichEdit15.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),i))=BMPCP then
TntRichEdit15.SelLength:=1
else
TntRichEdit15.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit16.SelStart div 3 + 1;
TntRichEdit16.Tag:=1;
TntRichEdit16.SelStart:=(i-1)*3;
TntRichEdit16.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit15.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit15.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit15.HideSelection:=false;
if not TntRichEdit15.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit15.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit15.Text),i,true);
TntRichEdit15.Tag:=1;
TntRichEdit15.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),i))=BMPCP then
TntRichEdit15.SelLength:=1
else
TntRichEdit15.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit16.SelStart div 3 + 1;
TntRichEdit16.Tag:=1;
TntRichEdit16.SelStart:=(i-1)*3;
TntRichEdit16.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit15.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit15.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit15.HideSelection:=false;
if not TntRichEdit15.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit15.Text),i,true);
TntRichEdit15.Tag:=1;
TntRichEdit15.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit15.Text),i))=BMPCP then
TntRichEdit15.SelLength:=1
else
TntRichEdit15.SelLength:=2
end
end;
1:
if TntRichEdit16.SelLength>0 then
TntRichEdit16.Tag:=TntGroupBox14.Tag
end;
TntRichEdit15.Tag:=0
end;

procedure TForm1.TntRadioButton47Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0,1:
InitGroupBox12_2;
2,3:
InitGroupBox12_1;
4,5:
InitGroupBox12_3
end;
TntRichEdit15.SetFocus;
TntRichEdit15.OnSelectionChange(TntRichEdit15)
end
end;

procedure TForm1.TntButton40Click(Sender: TObject);
var
i:integer;
begin
i:=UTF8CUSToUTF16BS(Pointer(TmpUTF8Str),TntComboBox8.ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF8CUSToUTF16BS(Pointer(TmpUTF8Str),TntComboBox8.ItemIndex,Pointer(
TmpUTFBS))=i
then
begin
DispBSCommonProc_12(5);
TntRichEdit16.OnSelectionChange(TntRichEdit16);
TntRichEdit16.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8编码单元序列转换为带或不带BOM'+
'的UTF-16编码格式字节序列','试练UTF8CUSToUTF16BS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton41Click(Sender: TObject);
var
i:integer;
begin
i:=UTF8CUSToUTF32BS(Pointer(TmpUTF8Str),TntComboBox9.ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF8CUSToUTF32BS(Pointer(TmpUTF8Str),TntComboBox9.ItemIndex,Pointer(
TmpUTFBS))=i
then
begin
DispBSCommonProc_12(6);
TntRichEdit16.OnSelectionChange(TntRichEdit16);
TntRichEdit16.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-8编码单元序列转换为带或不带BOM'+
'的UTF-32编码格式字节序列','试练UTF8CUSToUTF32BS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton42Click(Sender: TObject);
var
i:integer;
begin
i:=UTF16CUSToUTF8BS(Pointer(TntRichEdit15.Text),nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF8BS(Pointer(TntRichEdit15.Text),Pointer(TmpUTFBS))=i then
begin
DispBSCommonProc_12(4);
TntRichEdit16.OnSelectionChange(TntRichEdit16);
TntRichEdit16.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16编码单元序列转换为UTF-8编码'+
'格式字节序列','试练UTF16CUSToUTF8BS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton43Click(Sender: TObject);
var
i:integer;
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit15.Text),TntComboBox10.ItemIndex,
nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit15.Text),TntComboBox10.ItemIndex,
Pointer(TmpUTFBS))=i
then
begin
DispBSCommonProc_12(6);
TntRichEdit16.OnSelectionChange(TntRichEdit16);
TntRichEdit16.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-16编码单元序列转换为带或不带BOM'+
'的UTF-32编码格式字节序列','试练UTF16CUSToUTF32BS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton44Click(Sender: TObject);
var
i:integer;
begin
i:=UTF32CUSToUTF8BS(@TmpUTF32Str[0],nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF32CUSToUTF8BS(@TmpUTF32Str[0],Pointer(TmpUTFBS))=i then
begin
DispBSCommonProc_12(4);
TntRichEdit16.OnSelectionChange(TntRichEdit16);
TntRichEdit16.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32编码单元序列转换为UTF-8编码'+
'格式字节序列','试练UTF32CUSToUTF8BS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton45Click(Sender: TObject);
var
i:integer;
begin
i:=UTF32CUSToUTF16BS(@TmpUTF32Str[0],TntComboBox11.ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF32CUSToUTF16BS(@TmpUTF32Str[0],TntComboBox11.ItemIndex,Pointer(
TmpUTFBS))=i
then
begin
DispBSCommonProc_12(5);
TntRichEdit16.OnSelectionChange(TntRichEdit16);
TntRichEdit16.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把UTF-32编码单元序列转换为带或不带BOM'+
'的UTF-16编码格式字节序列','试练UTF32CUSToUTF16BS函数',mb_ok)
end
end
end;

procedure TForm1.TntTabSheet13Show(Sender: TObject);
var
i,c,c1:integer;
begin
TntRichEdit17.Text:=TntRichEdit1.Text;
TntRichEdit17.OnSelectionChange(TntRichEdit17);
TntRichEdit17.SetFocus;
TntRichEdit17.Tag:=0;
SetLength(RadioBtnArray,0);
SetLength(GroupBoxArray,0);
c:=0;
c1:=0;
for i:=0 to TntTabSheet13.ControlCount-1do
if TntTabSheet13.Controls is TTntRadioButton then
begin
inc(c);
SetLength(RadioBtnArray,c);
RadioBtnArray[c-1]:=TntTabSheet13.Controls as TTntRadioButton;
RadioBtnArray[c-1].Tag:=c-1;
GroupBoxArray[c-1].Enabled:=RadioBtnArray[c-1].Checked;
if GroupBoxArray[c-1].Enabled then
EnabGroupBoxIndex:=c-1
end
else
if TntTabSheet13.Controls is TTntGroupBox then
begin
inc(c1);
SetLength(GroupBoxArray,c1);
GroupBoxArray[c1-1]:=TntTabSheet13.Controls as TTntGroupBox
end
end;

procedure TForm1.TntRichEdit17Change(Sender: TObject);
begin
case EnabGroupBoxIndex of
0,1:
InitGroupBox13_4;
2,3:
InitGroupBox13_5;
4,5:
InitGroupBox13_6
end
end;

procedure TForm1.TntRichEdit17DblClick(Sender: TObject);
begin
TntRichEdit17.ReadOnly:=not TntRichEdit17.ReadOnly;
if TntRichEdit17.ReadOnly then
begin
TntRichEdit17.Cursor:=crArrow;
TntRichEdit17.OnSelectionChange(TntRichEdit17)
end
else
begin
TntRichEdit17.Cursor:=crDefault;
TntRichEdit17.SelLength:=0
end;
TntRichEdit18.HideSelection:=not TntRichEdit17.ReadOnly;
TntRichEdit17.Tag:=0
end;

procedure TForm1.TntRichEdit17SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit17.ReadOnly then
if TntRichEdit17.Tag=0 then
begin
TntRichEdit17.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),
TntRichEdit17.SelStart+1))=BMPCP
then
TntRichEdit17.SelLength:=1
else
TntRichEdit17.SelLength:=2;
if TntRichEdit18.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit18.Tag;
TntRichEdit18.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit18.SelStart:=TntRichEdit17.SelStart*5;
if TntRichEdit17.SelLength=1 then
TntRichEdit18.SelLength:=4
else
TntRichEdit18.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit17.Text),
TntRichEdit17.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit18.SelStart:=(i-1)*3;
TntRichEdit18.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit17.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit17.Text),i,true);
TntRichEdit18.SelStart:=(i-1)*9;
TntRichEdit18.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit17.SelStart+1
else
i:=TntRichEdit17.SelStart;
TntRichEdit18.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),
TntRichEdit17.SelStart+1))=BMPCP
then
TntRichEdit18.SelLength:=5
else
TntRichEdit18.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit17.Text),
TntRichEdit17.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit18.SelStart:=i*4*3;
TntRichEdit18.SelLength:=11
end
end
end
end
else
if TntRichEdit17.SelLength>0 then
TntRichEdit17.Tag:=0
end;

procedure TForm1.TntRichEdit18SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit18.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit18.Tag;
case TntRichEdit18.Tag of
0:
begin
i:=TntRichEdit18.SelStart div 5 + 1;
TntRichEdit18.Tag:=1;
TntRichEdit18.SelStart:=(i-1)*5;
TntRichEdit18.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit17.Text),i,@j);
TntRichEdit17.Tag:=1;
TntRichEdit17.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),i))=BMPCP then
TntRichEdit17.SelLength:=1
else
TntRichEdit17.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit18.SelStart div 3 + 1;
TntRichEdit18.Tag:=1;
TntRichEdit18.SelStart:=(i-1)*3;
TntRichEdit18.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit17.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit17.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit17.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit17.Text),i,true);
TntRichEdit17.Tag:=1;
TntRichEdit17.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),i))=BMPCP then
TntRichEdit17.SelLength:=1
else
TntRichEdit17.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit18.SelStart div 9 + 1;
TntRichEdit18.Tag:=1;
TntRichEdit18.SelStart:=(i-1)*9;
TntRichEdit18.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit17.Text),i,true);
TntRichEdit17.Tag:=1;
TntRichEdit17.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),i))=BMPCP then
TntRichEdit17.SelLength:=1
else
TntRichEdit17.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit18.SelStart div 3 + 1;
TntRichEdit18.Tag:=1;
TntRichEdit18.SelStart:=(i-1)*3;
TntRichEdit18.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit17.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit17.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit17.HideSelection:=false;
if not TntRichEdit17.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit17.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit17.Text),i,true);
TntRichEdit17.Tag:=1;
TntRichEdit17.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),i))=BMPCP then
TntRichEdit17.SelLength:=1
else
TntRichEdit17.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit18.SelStart div 3 + 1;
TntRichEdit18.Tag:=1;
TntRichEdit18.SelStart:=(i-1)*3;
TntRichEdit18.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit17.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit17.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit17.HideSelection:=false;
if not TntRichEdit17.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit17.Text),i,true);
TntRichEdit17.Tag:=1;
TntRichEdit17.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit17.Text),i))=BMPCP then
TntRichEdit17.SelLength:=1
else
TntRichEdit17.SelLength:=2
end
end;
1:
if TntRichEdit18.SelLength>0 then
TntRichEdit18.Tag:=TntGroupBox14.Tag
end;
TntRichEdit17.Tag:=0
end;

procedure TForm1.TntRadioButton53Click(Sender: TObject);
var
i:integer;
begin
if Sender is TTntRadioButton then
begin
i:=(Sender as TTntRadioButton).Tag;
GroupBoxArray.Enabled:=true;
GroupBoxArray[EnabGroupBoxIndex].Enabled:=false;
EnabGroupBoxIndex:=i;
case EnabGroupBoxIndex of
0,1:
InitGroupBox13_4;
2,3:
begin
if EnabGroupBoxIndex=2 then
TntComboBox12.Tag:=TntComboBox12.ItemIndex
else
TntComboBox12.Tag:=TntComboBox14.ItemIndex;
InitGroupBox13_5
end;
4,5:
begin
if EnabGroupBoxIndex=4 then
TntComboBox13.Tag:=TntComboBox13.ItemIndex
else
TntComboBox13.Tag:=TntComboBox15.ItemIndex;
InitGroupBox13_6
end
end;
TntRichEdit17.SetFocus;
TntRichEdit17.OnSelectionChange(TntRichEdit17)
end
end;

procedure TForm1.TntButton46Click(Sender: TObject);
var
i,j,k:integer;
s:WideString;
s1:string;
p:pChar;
cp:WORD;
b:Byte;
begin
i:=UTF8BSToUTF16CUS(Pointer(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF8BSToUTF16CUS(Pointer(TmpUTFBS),Pointer(s))=i then
begin
SetLength(s1,5*i);
p:=Pointer(s1);
j:=0;
for i:=1 to ido
begin
cp:=ord(s);
for k:=3do
wnto 0do
begin
b:=cp shr (4*k) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit18.Tag:=0;
TntRichEdit18.Text:=s1;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把一个UTF-8编码格式字节序列转换为'+
'UTF-16编码单元序列','试练UTF8BSToUTF16CUS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton47Click(Sender: TObject);
var
i,j,k:integer;
s:string;
p:pChar;
cp:DWORD;
b:Byte;
begin
i:=UTF8BSToUTF32CUS(Pointer(TmpUTFBS),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF8BSToUTF32CUS(Pointer(TmpUTFBS),@TmpUTF32Str[0])=i-1 then
begin
SetLength(s,9*i);
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
cp:=ord(TmpUTF32Str);
for k:=7do
wnto 0do
begin
b:=cp shr (4*k) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit18.Tag:=3;
TntRichEdit18.Text:=s;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把一个UTF-8编码格式字节序列转换为'+
'UTF-32编码单元序列','试练UTF8BSToUTF32CUS函数',mb_ok)
end
end
end;

procedure TForm1.TntComboBox12Select(Sender: TObject);
var
i:integer;
begin
if Sender is TTntComboBox then
begin
case EnabGroupBoxIndex of
2,3:
begin
i:=CUSToBSForUTF16(Pointer(TntRichEdit17.Text),(Sender as
TTntComboBox).ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if CUSToBSForUTF16(Pointer(TntRichEdit17.Text),(Sender as
TTntComboBox).ItemIndex,Pointer(TmpUTFBS))=i
then
DispBSCommonProc_13(5)
end
end;
4,5:
begin
i:=UTF16CUSToUTF32BS(Pointer(TntRichEdit17.Text),(Sender as
TTntComboBox).ItemIndex,nil);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if UTF16CUSToUTF32BS(Pointer(TntRichEdit17.Text),(Sender as
TTntComboBox).ItemIndex,Pointer(TmpUTFBS))=i
then
DispBSCommonProc_13(6)
end
end
end;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus
end
end;

procedure TForm1.TntButton48Click(Sender: TObject);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF16BSToUTF8CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF16BSToUTF8CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(
TmpUTF8Str))=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit18.Tag:=2;
TntRichEdit18.Text:=s;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把一个UTF-16编码格式直接序列转换为'+
'UTF-8编码单元序列','试练UTF16BSToUTF8CUS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton49Click(Sender: TObject);
var
i,j,k:integer;
s:string;
p:pChar;
cp:DWORD;
b:Byte;
begin
i:=UTF16BSToUTF32CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(TmpUTF32Str,i);
if UTF16BSToUTF32CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),@TmpUTF32Str[0])
=i-1
then
begin
SetLength(s,9*i);
p:=Pointer(s);
j:=0;
for i:=0 to i-2do
begin
cp:=ord(TmpUTF32Str);
for k:=7do
wnto 0do
begin
b:=cp shr (4*k) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit18.Tag:=3;
TntRichEdit18.Text:=s;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把一个UTF-16编码格式直接序列转换为'+
'UTF-32编码单元序列','试练UTF16BSToUTF32CUS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton50Click(Sender: TObject);
var
i,j:integer;
s:string;
p:pChar;
b,b1:Byte;
begin
i:=UTF32BSToUTF8CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(TmpUTF8Str,i);
if UTF32BSToUTF8CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(
TmpUTF8Str))=i
then
begin
SetLength(s,3*i);
p:=Pointer(s);
j:=0;
for i:=1 to ido
begin
b:=ord(TmpUTF8Str);
b1:=b shr 4;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j]:=chr(b1);
b1:=b and $F;
if b1>9 then
b1:=b1+$37
else
b1:=b1+$30;
p[j+1]:=chr(b1);
p[j+2]:=#32;
j:=j+3
end;
TntRichEdit18.Tag:=2;
TntRichEdit18.Text:=s;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把一个UTF-32编码格式直接序列转换为'+
'UTF-8编码单元序列','试练UTF32BSToUTF8CUS函数',mb_ok)
end
end
end;

procedure TForm1.TntButton51Click(Sender: TObject);
var
i,j,k:integer;
s:WideString;
s1:string;
p:pChar;
cp:WORD;
b:Byte;
begin
i:=UTF32BSToUTF16CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF32BSToUTF16CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))=i then
begin
SetLength(s1,5*i);
p:=Pointer(s1);
j:=0;
for i:=1 to ido
begin
cp:=ord(s);
for k:=3do
wnto 0do
begin
b:=cp shr (4*k) and $F;
if b>9 then
b:=b+$37
else
b:=b+$30;
p[j]:=chr(b);
inc(j)
end;
p[j]:=#32;
inc(j)
end;
TntRichEdit18.Tag:=0;
TntRichEdit18.Text:=s1;
TntRichEdit18.OnSelectionChange(TntRichEdit18);
TntRichEdit18.SetFocus;
MessageBoxW(Form1.Handle,'已经成功把一个UTF-32编码格式字节序列转换为'+
'UTF-16编码单元序列','试练UTF32BSToUTF16CUS函数',mb_ok)
end
end
end;

procedure TForm1.TntTabSheet14Show(Sender: TObject);
begin
TntRichEdit19.OnChange(TntRichEdit19);
TntRichEdit19.OnSelectionChange(TntRichEdit19);
TntRichEdit19.SetFocus;
TntRichEdit19.Tag:=0
end;

procedure TForm1.TntRichEdit19SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit19.ReadOnly then
if TntRichEdit19.Tag=0 then
begin
TntRichEdit19.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),
TntRichEdit19.SelStart+1))=BMPCP
then
TntRichEdit19.SelLength:=1
else
TntRichEdit19.SelLength:=2;
if TntRichEdit20.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit20.Tag;
TntRichEdit20.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit20.SelStart:=TntRichEdit19.SelStart*5;
if TntRichEdit19.SelLength=1 then
TntRichEdit20.SelLength:=4
else
TntRichEdit20.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit19.Text),
TntRichEdit19.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit20.SelStart:=(i-1)*3;
TntRichEdit20.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit19.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit19.Text),i,true);
TntRichEdit20.SelStart:=(i-1)*9;
TntRichEdit20.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit19.SelStart+1
else
i:=TntRichEdit19.SelStart;
TntRichEdit20.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),
TntRichEdit19.SelStart+1))=BMPCP
then
TntRichEdit20.SelLength:=5
else
TntRichEdit20.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit19.Text),
TntRichEdit19.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit20.SelStart:=i*4*3;
TntRichEdit20.SelLength:=11
end
end
end
end
else
if TntRichEdit19.SelLength>0 then
TntRichEdit19.Tag:=0
end;

procedure TForm1.TntRichEdit20SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit20.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit20.Tag;
case TntRichEdit20.Tag of
0:
begin
i:=TntRichEdit20.SelStart div 5 + 1;
TntRichEdit20.Tag:=1;
TntRichEdit20.SelStart:=(i-1)*5;
TntRichEdit20.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit19.Text),i,@j);
TntRichEdit19.Tag:=1;
TntRichEdit19.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),i))=BMPCP then
TntRichEdit19.SelLength:=1
else
TntRichEdit19.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit20.SelStart div 3 + 1;
TntRichEdit20.Tag:=1;
TntRichEdit20.SelStart:=(i-1)*3;
TntRichEdit20.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit19.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit19.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit19.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit19.Text),i,true);
TntRichEdit19.Tag:=1;
TntRichEdit19.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),i))=BMPCP then
TntRichEdit19.SelLength:=1
else
TntRichEdit19.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit20.SelStart div 9 + 1;
TntRichEdit20.Tag:=1;
TntRichEdit20.SelStart:=(i-1)*9;
TntRichEdit20.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit19.Text),i,true);
TntRichEdit19.Tag:=1;
TntRichEdit19.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),i))=BMPCP then
TntRichEdit19.SelLength:=1
else
TntRichEdit19.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit20.SelStart div 3 + 1;
TntRichEdit20.Tag:=1;
TntRichEdit20.SelStart:=(i-1)*3;
TntRichEdit20.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit19.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit19.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit19.HideSelection:=false;
if not TntRichEdit19.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit19.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit19.Text),i,true);
TntRichEdit19.Tag:=1;
TntRichEdit19.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),i))=BMPCP then
TntRichEdit19.SelLength:=1
else
TntRichEdit19.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit20.SelStart div 3 + 1;
TntRichEdit20.Tag:=1;
TntRichEdit20.SelStart:=(i-1)*3;
TntRichEdit20.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit19.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit19.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit19.HideSelection:=false;
if not TntRichEdit19.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit19.Text),i,true);
TntRichEdit19.Tag:=1;
TntRichEdit19.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit19.Text),i))=BMPCP then
TntRichEdit19.SelLength:=1
else
TntRichEdit19.SelLength:=2
end
end;
1:
if TntRichEdit20.SelLength>0 then
TntRichEdit20.Tag:=TntGroupBox14.Tag
end;
TntRichEdit19.Tag:=0
end;

procedure TForm1.TntRichEdit19Change(Sender: TObject);
var
i:integer;
s:WideString;
begin
i:=Length(TmpUTFBS);
case TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80)) of
BS_UTF8WithoutBOM,BS_UTF8WithBOM:
begin
i:=UTF8BSToUTF16CUS(Pointer(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF8BSToUTF16CUS(Pointer(TmpUTFBS),Pointer(s))=i then
begin
TntRichEdit19.Text:=s;
TmpUTF8Str:=TmpUTFBS;
i:=4
end
else
i:=0
end
else
i:=0
end;
BS_UTF16Default..BS_UTF16LE:
begin
i:=BSToCUSForUTF16(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if BSToCUSForUTF16(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))=i then
begin
TntRichEdit19.Text:=s;
i:=5
end
else
i:=0
end
else
i:=0
end;
BS_UTF32Default..BS_UTF32LE:
begin
i:=UTF32BSToUTF16CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF32BSToUTF16CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))
=i
then
begin
TntRichEdit19.Text:=s;
i:=6
end
else
i:=0
end
else
i:=0
end
else
i:=0
end;
DispBSCommonProc_14(i)
end;

procedure TForm1.TntButton52Click(Sender: TObject);
var
i:integer;
s:WideString;
begin
i:=Length(TmpUTFBS);
s:='在未知编码格式字节序列中检测到了'+inttostr(GuessUTF8BSAvaiByteCount(
Pointer(TmpUTFBS),@i))+'个符合UTF-8编码机制规范的字节,总共检测了序列中的'+
inttostr(i)+'个字节';
MessageBoxW(Form1.Handle,Pointer(s),'试练GuessUTF8BSAvaiByteCount函数',
mb_ok)
end;

procedure TForm1.TntButton53Click(Sender: TObject);
var
i:integer;
s:WideString;
begin
i:=Length(TmpUTFBS);
s:='在未知编码格式字节序列中检测到了'+inttostr(GuessUTF16BSAvaiByteCount(
Pointer(TmpUTFBS),@i))+'个符合UTF-16编码机制规范的字节,总共检测了序列中的'+
inttostr(i)+'个字节';
MessageBoxW(Form1.Handle,Pointer(s),'试练GuessUTF16BSAvaiByteCount函数',
mb_ok)
end;

procedure TForm1.TntButton54Click(Sender: TObject);
var
i:integer;
s:WideString;
begin
i:=Length(TmpUTFBS);
s:='在未知编码格式字节序列中检测到了'+inttostr(GuessUTF32BSAvaiByteCount(
Pointer(TmpUTFBS),@i))+'个符合UTF-32编码机制规范的字节,总共检测了序列中的'+
inttostr(i)+'个字节';
MessageBoxW(Form1.Handle,Pointer(s),'试练GuessUTF32BSAvaiByteCount函数',
mb_ok)
end;

procedure TForm1.TntButton55Click(Sender: TObject);
begin
if BOMTypeOfUTF8BS(Pointer(TmpUTFBS))=0 then
MessageBoxW(Form1.Handle,'这个UTF-8编码格式字节序列不带有BOM头','试练'+
'BOMTypeOfUTF8BS函数',mb_ok)
else
MessageBoxW(Form1.Handle,'这个UTF-8编码格式字节序列带有BOM头','试练'+
'BOMTypeOfUTF8BS函数',mb_ok)
end;

procedure TForm1.TntButton56Click(Sender: TObject);
var
s:WideString;
begin
s:='这个UTF-16编码格式字节序列';
case TBOM(BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS))) of
BOMDefault:
s:=s+'不带有BOM头';
BOMBE:
s:=s+'带有大尾字节序BOM';
BOMLE:
s:=s+'带有小尾字节序BOM'
end;
MessageBoxW(Form1.Handle,Pointer(s),'试练BOMTypeOfUTF16BS函数',mb_ok)
end;

procedure TForm1.TntButton57Click(Sender: TObject);
var
s:WideString;
begin
s:='这个UTF-32编码格式字节序列';
case TBOM(BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS))) of
BOMDefault:
s:=s+'不带有BOM头';
BOMBE:
s:=s+'带有大尾字节序BOM';
BOMLE:
s:=s+'带有小尾字节序BOM'
end;
MessageBoxW(Form1.Handle,Pointer(s),'试练BOMTypeOfUTF32BS函数',mb_ok)
end;

procedure TForm1.TntButton58Click(Sender: TObject);
var
s:WideString;
i:integer;
begin
s:='这是一个';
i:=Length(TmpUTFBS);
case TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80)) of
BS_Unknow:
s:=s+'未知类型';
BS_UTF8WithoutBOM:
s:=s+'不带BOM头的UTF-8';
BS_UTF8WithBOM:
s:=s+'带BOM头的UTF-8';
BS_UTF16Default:
s:=s+'默认字节序的UTF-16';
BS_UTF16BE:
s:=s+'大尾字节序的UTF-16';
BS_UTF16LE:
s:=s+'小尾字节序的UTF-16';
BS_UTF32Default:
s:=s+'默认字节序的UTF-32';
BS_UTF32BE:
s:=s+'大尾字节序的UTF-32';
BS_UTF32LE:
s:=s+'小尾字节序的UTF-32'
end;
s:=s+'编码格式字节序列';
MessageBoxW(Form1.Handle,Pointer(s),'试练GuessBSType函数',mb_ok)
end;

procedure TForm1.TntTabSheet15Show(Sender: TObject);
begin
TntRichEdit21.OnChange(TntRichEdit21);
TntRichEdit21.OnSelectionChange(TntRichEdit21);
TntRichEdit21.SetFocus;
TntRichEdit21.Tag:=0
end;

procedure TForm1.TntRichEdit21Change(Sender: TObject);
var
i:integer;
s:WideString;
begin
i:=Length(TmpUTFBS);
case TBSType(GuessBSType(Pointer(TmpUTFBS),@i,80)) of
BS_UTF8WithoutBOM,BS_UTF8WithBOM:
begin
i:=UTF8BSToUTF16CUS(Pointer(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF8BSToUTF16CUS(Pointer(TmpUTFBS),Pointer(s))=i then
begin
TntRichEdit21.Text:=s;
TmpUTF8Str:=TmpUTFBS;
i:=4
end
else
i:=0
end
else
i:=0
end;
BS_UTF16Default..BS_UTF16LE:
begin
i:=BSToCUSForUTF16(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if BSToCUSForUTF16(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))=i then
begin
TntRichEdit21.Text:=s;
i:=5
end
else
i:=0
end
else
i:=0
end;
BS_UTF32Default..BS_UTF32LE:
begin
i:=UTF32BSToUTF16CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),nil);
if i>0 then
begin
SetLength(s,i);
if UTF32BSToUTF16CUS(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(s))
=i
then
begin
TntRichEdit21.Text:=s;
i:=6
end
else
i:=0
end
else
i:=0
end
else
i:=0
end;
DispBSCommonProc_15(i)
end;

procedure TForm1.TntRichEdit21SelectionChange(Sender: TObject);
label 10;
var
i,j,charsize:integer;
begin
if TntRichEdit21.ReadOnly then
if TntRichEdit21.Tag=0 then
begin
TntRichEdit21.Tag:=1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),
TntRichEdit21.SelStart+1))=BMPCP
then
TntRichEdit21.SelLength:=1
else
TntRichEdit21.SelLength:=2;
if TntRichEdit22.Tag<>1 then
begin
TntGroupBox14.Tag:=TntRichEdit22.Tag;
TntRichEdit22.Tag:=1;
case TntGroupBox14.Tag of
0:
begin
TntRichEdit22.SelStart:=TntRichEdit21.SelStart*5;
if TntRichEdit21.SelLength=1 then
TntRichEdit22.SelLength:=4
else
TntRichEdit22.SelLength:=9
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=UTF16CUToCharIndex(Pointer(TntRichEdit21.Text),
TntRichEdit21.SelStart+1,true);
i:=UTF8CharToCUIndex(Pointer(TmpUTF8Str),i,true);
UTF8CUIndexOfChar(Pointer(TmpUTF8Str),i,@j,@charsize);
i:=i+BOMSizeOfUTF8*TntButton25.Tag;
TntRichEdit22.SelStart:=(i-1)*3;
TntRichEdit22.SelLength:=(charsize-1)*3+2
end;
3:
begin
i:=TntRichEdit21.SelStart+1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit21.Text),i,true);
TntRichEdit22.SelStart:=(i-1)*9;
TntRichEdit22.SelLength:=8
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
if TntButton27.Tag>0 then
i:=TntRichEdit21.SelStart+1
else
i:=TntRichEdit21.SelStart;
TntRichEdit22.SelStart:=i*2*3;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),
TntRichEdit21.SelStart+1))=BMPCP
then
TntRichEdit22.SelLength:=5
else
TntRichEdit22.SelLength:=11
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(
TmpUTFBS));
i:=UTF16CUToCharIndex(Pointer(TntRichEdit21.Text),
TntRichEdit21.SelStart+1,true)-1;
if TntButton29.Tag>0 then
inc(i);
TntRichEdit22.SelStart:=i*4*3;
TntRichEdit22.SelLength:=11
end
end
end
end
else
if TntRichEdit21.SelLength>0 then
TntRichEdit21.Tag:=0
end;

procedure TForm1.TntRichEdit22SelectionChange(Sender: TObject);
label 10;
var
i,j:integer;
begin
if TntRichEdit22.Tag<>1 then
TntGroupBox14.Tag:=TntRichEdit22.Tag;
case TntRichEdit22.Tag of
0:
begin
i:=TntRichEdit22.SelStart div 5 + 1;
TntRichEdit22.Tag:=1;
TntRichEdit22.SelStart:=(i-1)*5;
TntRichEdit22.SelLength:=4;
j:=UTF16CUIndexOfChar(Pointer(TntRichEdit21.Text),i,@j);
TntRichEdit21.Tag:=1;
TntRichEdit21.SelStart:=i-j;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),i))=BMPCP then
TntRichEdit21.SelLength:=1
else
TntRichEdit21.SelLength:=2
end;
2:
begin
TntButton25.Tag:=0;
10:
i:=TntRichEdit22.SelStart div 3 + 1;
TntRichEdit22.Tag:=1;
TntRichEdit22.SelStart:=(i-1)*3;
TntRichEdit22.SelLength:=2;
if (TntButton25.Tag=1) and (i<=BOMSizeOfUTF8) then
begin
TntRichEdit21.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-8编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit21.HideSelection:=false;
i:=i-BOMSizeOfUTF8*TntButton25.Tag;
if not TntRichEdit21.HideSelection then
begin
i:=UTF8CUToCharIndex(Pointer(TmpUTF8Str),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit21.Text),i,true);
TntRichEdit21.Tag:=1;
TntRichEdit21.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),i))=BMPCP then
TntRichEdit21.SelLength:=1
else
TntRichEdit21.SelLength:=2
end
end;
3:
begin
i:=TntRichEdit22.SelStart div 9 + 1;
TntRichEdit22.Tag:=1;
TntRichEdit22.SelStart:=(i-1)*9;
TntRichEdit22.SelLength:=8;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit21.Text),i,true);
TntRichEdit21.Tag:=1;
TntRichEdit21.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),i))=BMPCP then
TntRichEdit21.SelLength:=1
else
TntRichEdit21.SelLength:=2
end;
4:
begin
TntButton25.Tag:=BOMTypeOfUTF8BS(Pointer(TmpUTFBS));
goto 10
end;
5:
begin
TntButton27.Tag:=BOMTypeOfUTF16BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit22.SelStart div 3 + 1;
TntRichEdit22.Tag:=1;
TntRichEdit22.SelStart:=(i-1)*3;
TntRichEdit22.SelLength:=2;
if TntButton27.Tag>0 then
begin
if i<=BOMSizeOfUTF16 then
begin
TntRichEdit21.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-16编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit21.HideSelection:=false;
i:=i-BOMSizeOfUTF16
end
else
TntRichEdit21.HideSelection:=false;
if not TntRichEdit21.HideSelection then
begin
i:=(i-1) div 2 + 1;
i:=UTF16CUToCharIndex(Pointer(TntRichEdit21.Text),i,true);
i:=UTF16CharToCUIndex(Pointer(TntRichEdit21.Text),i,true);
TntRichEdit21.Tag:=1;
TntRichEdit21.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),i))=BMPCP then
TntRichEdit21.SelLength:=1
else
TntRichEdit21.SelLength:=2
end
end;
6:
begin
TntButton29.Tag:=BOMTypeOfUTF32BS(Pointer(TmpUTFBS),Length(TmpUTFBS));
i:=TntRichEdit22.SelStart div 3 + 1;
TntRichEdit22.Tag:=1;
TntRichEdit22.SelStart:=(i-1)*3;
TntRichEdit22.SelLength:=2;
if TntButton29.Tag>0 then
begin
if i<=BOMSizeOfUTF32 then
begin
TntRichEdit21.HideSelection:=true;
MessageBoxW(Form1.Handle,'你点中的是属于UTF-32编码格式字节序列BOM的字节',
'点击非字符编码字节提示',mb_ok)
end
else
TntRichEdit21.HideSelection:=false;
i:=i-BOMSizeOfUTF32
end
else
TntRichEdit21.HideSelection:=false;
if not TntRichEdit21.HideSelection then
begin
i:=(i-1) div 4 + 1;
i:=UTF16CharToCUIndex(Pointer(TntRichEdit21.Text),i,true);
TntRichEdit21.Tag:=1;
TntRichEdit21.SelStart:=i-1;
if TUTF16CUT(UTF16CodeUnitType(Pointer(TntRichEdit21.Text),i))=BMPCP then
TntRichEdit21.SelLength:=1
else
TntRichEdit21.SelLength:=2
end
end;
1:
if TntRichEdit22.SelLength>0 then
TntRichEdit22.Tag:=TntGroupBox14.Tag
end;
TntRichEdit21.Tag:=0
end;

procedure TForm1.TntButton59Click(Sender: TObject);
begin
if TntSaveDialog1.Execute then
if SaveUniByteSequToFile(Pointer(TmpUTFBS),Length(TmpUTFBS),Pointer(
TntSaveDialog1.FileName))
then
MessageBoxW(Form1.Handle,'已经成功把这个字节序列保存为文本文件了','试练'+
'SaveUniByteSequToFile函数',mb_ok)
end;

procedure TForm1.TntButton60Click(Sender: TObject);
var
i,j,k:integer;
s:WideString;
begin
if TntOpenDialog1.Execute then
begin
i:=0;
i:=LoadUniByteSequFromFile(Pointer(TntOpenDialog1.FileName),@i,nil,@j);
if i>0 then
begin
SetLength(TmpUTFBS,i);
if LoadUniByteSequFromFile(nil,nil,Pointer(TmpUTFBS),nil)=i then
TntRichEdit21.OnChange(TntRichEdit21)
end
end
end;

end.
/////////////////////////////////Unit1.dfm////////////////////////////////
object Form1: TForm1
Left = 192
Top = 114
ActiveControl = TntPageControl5
BorderIcons = [biSystemMenu, biMinimize]
BorderStyle = bsSingle
Caption = 'UCS'#29790#22763#20891#20992#28436#27494#22530
ClientHeight = 446
ClientWidth = 688
Color = clBtnFace
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = #26032#23435#20307
Font.Style = []
OldCreateOrder = False
Position = poDesktopCenter
ShowHint = True
OnCreate = TntFormCreate
OnShow = TntFormShow
PixelsPerInch = 96
TextHeight = 12
object TntPageControl1: TTntPageControl
Left = 0
Top = 0
Width = 688
Height = 446
ActivePage = TntTabSheet4
Align = alClient
TabOrder = 0
object TntTabSheet1: TTntTabSheet
Caption = 'Unicode'#32534#30721#26684#24335#22788#29702
OnShow = TntTabSheet1Show
object TntPageControl2: TTntPageControl
Left = 0
Top = 0
Width = 680
Height = 419
ActivePage = TntTabSheet5
Align = alClient
TabOrder = 0
TabPosition = tpBottom
object TntTabSheet5: TTntTabSheet
Caption = 'UTF-16'#32534#30721#26684#24335#22788#29702#20363#31243
OnShow = TntTabSheet5Show
object TntRichEdit1: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit1Change
OnDblClick = TntRichEdit1DblClick
OnSelectionChange = TntRichEdit1SelectionChange
end
object TntGroupBox1: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 89
Caption = 'UTF16CodeUnitType'#20989#25968
TabOrder = 1
object TntRadioButton1: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton1Click
end
object TntRadioButton2: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton2Click
end
object TntButton1: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #21028#26029'UTF-16'#32534#30721#26684#24335#23383#31526#20018#20013#25351#23450#20301#32622#19978#37027#20010#32534#30721#21333#20803#30340#31867#22411
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton1Click
end
object Edit1: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit1KeyPress
end
end
object TntGroupBox2: TTntGroupBox
Left = 404
Top = 100
Width = 265
Height = 89
Caption = 'UTF16CUToCharIndex'#20989#25968
TabOrder = 2
object TntRadioButton3: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton3Click
end
object TntRadioButton4: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton4Click
end
object TntButton2: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #35745#31639'UTF-16'#23383#31526#20018#20013#25351#23450#20301#32622#19978#37027#20010#32534#30721#21333#20803#25152#23646#30340#23383#31526#26159#23383#31526#20018#20013#30340#31532#20960#20010#23383#31526
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton2Click
end
object Edit2: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit2KeyPress
end
end
object TntGroupBox3: TTntGroupBox
Left = 404
Top = 200
Width = 265
Height = 89
Caption = 'UTF16CharToCUIndex'#20989#25968
TabOrder = 3
object Edit3: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 0
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit3KeyPress
end
object TntButton3: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #35745#31639'UTF-16'#23383#31526#20018#20013#25351#23450#20301#32622#19978#37027#20010#23383#31526#30340#31532#19968#20010#32534#30721#21333#20803#26159#23383#31526#20018#20013#30340#31532#20960#20010#32534#30721#21333#20803
Caption = #35797#32451
TabOrder = 1
OnClick = TntButton3Click
end
object TntRadioButton15: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#23383#31526#20301#32622
TabOrder = 2
OnClick = TntRadioButton15Click
end
object TntRadioButton16: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#23383#31526#20301#32622
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton16Click
end
end
object TntGroupBox4: TTntGroupBox
Left = 0
Top = 269
Width = 186
Height = 55
Caption = 'CPToUTF16CUS'#20989#25968
TabOrder = 4
object Edit4: TEdit
Left = 10
Top = 18
Width = 80
Height = 20
CharCase = ecUpperCase
MaxLength = 8
TabOrder = 0
OnChange = Edit4Change
OnEnter = Edit1Enter
OnKeyPress = Edit4KeyPress
end
object TntButton4: TTntButton
Left = 95
Top = 18
Width = 75
Height = 25
Hint = #25226'Unicode'#32534#30721#28857#25968#23383#36716#25442#20026'UTF-16'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
Enabled = False
TabOrder = 1
OnClick = TntButton4Click
end
end
object TntGroupBox5: TTntGroupBox
Left = 404
Top = 300
Width = 265
Height = 89
Caption = 'UTF16CUSToCP'#20989#25968
TabOrder = 5
object TntRadioButton5: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton5Click
end
object TntRadioButton6: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton6Click
end
object TntButton5: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#21333#20803#24207#21015#36716#25442#20026'Unicode'#32534#30721#28857#25968#23383
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton5Click
end
object Edit5: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit5KeyPress
end
end
object TntGroupBox6: TTntGroupBox
Left = 0
Top = 334
Width = 186
Height = 55
Caption = 'CPToSurrPair'#20989#25968
TabOrder = 6
object Edit6: TEdit
Left = 10
Top = 18
Width = 80
Height = 20
CharCase = ecUpperCase
MaxLength = 8
TabOrder = 0
OnChange = Edit4Change
OnEnter = Edit1Enter
OnKeyPress = Edit6KeyPress
end
object TntButton6: TTntButton
Left = 95
Top = 18
Width = 75
Height = 25
Hint = #25226#22686#34917'Unicode'#32534#30721#28857#25968#23383#36716#25442#20026'UTF-16'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
Enabled = False
TabOrder = 1
OnClick = TntButton6Click
end
end
object TntGroupBox7: TTntGroupBox
Left = 196
Top = 269
Width = 117
Height = 120
Caption = 'SurrPairToCP'#20989#25968
TabOrder = 7
object Edit7: TEdit
Left = 10
Top = 18
Width = 40
Height = 20
CharCase = ecUpperCase
MaxLength = 4
TabOrder = 0
OnChange = Edit4Change
OnEnter = Edit1Enter
OnKeyPress = Edit7KeyPress
end
object TntButton7: TTntButton
Left = 10
Top = 83
Width = 75
Height = 25
Hint = #25226#25351#23450#30340#20195#29702#23545#36716#25442#20026#30456#24212#30340'Unicode'#32534#30721#28857#25968#23383
Caption = #35797#32451
Enabled = False
TabOrder = 2
OnClick = TntButton7Click
end
object Edit8: TEdit
Left = 10
Top = 42
Width = 40
Height = 20
CharCase = ecUpperCase
MaxLength = 4
TabOrder = 1
OnChange = Edit4Change
OnEnter = Edit1Enter
OnKeyPress = Edit7KeyPress
end
end
object TntRichEdit4: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 8
WantTabs = True
OnSelectionChange = TntRichEdit4SelectionChange
end
end
object TntTabSheet6: TTntTabSheet
Caption = 'UTF-8'#32534#30721#26684#24335#22788#29702#20363#31243
OnShow = TntTabSheet6Show
object TntRichEdit2: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit2Change
OnDblClick = TntRichEdit2DblClick
OnSelectionChange = TntRichEdit2SelectionChange
end
object TntRichEdit3: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit3SelectionChange
end
object TntGroupBox8: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 89
Caption = 'UTF8CUIndexOfChar'#20989#25968
TabOrder = 2
object TntRadioButton7: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton7Click
end
object TntRadioButton8: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton8Click
end
object TntButton8: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #22312#19968#20010'UTF-8 '#23383#31526#20018#20013#65292#21028#26029#25351#23450#20301#32622#19978#30340#32534#30721#21333#20803#26159#23427#25152#23646#30340#37027#20010#23383#31526#30340#31532#20960#20010#32534#30721#21333#20803
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton8Click
end
object Edit9: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit9KeyPress
end
end
object TntGroupBox9: TTntGroupBox
Left = 404
Top = 92
Width = 265
Height = 89
Caption = 'UTF8CUToCharIndex'#20989#25968
TabOrder = 3
object TntRadioButton9: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton9Click
end
object TntRadioButton10: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton10Click
end
object TntButton9: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #22312#19968#20010'UTF-8 '#23383#31526#20018#20013#65292#21028#26029#25351#23450#20301#32622#19978#30340#32534#30721#21333#20803#25152#23646#30340#37027#20010#23383#31526#26159#23383#31526#20018#20013#30340#31532#20960#20010#23383#31526
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton9Click
end
object Edit10: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit10KeyPress
end
end
object TntGroupBox10: TTntGroupBox
Left = 404
Top = 184
Width = 265
Height = 89
Caption = 'UTF8CharToCUIndex'#20989#25968
TabOrder = 4
object TntRadioButton11: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#23383#31526#20301#32622
TabOrder = 0
OnClick = TntRadioButton11Click
end
object TntRadioButton12: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#23383#31526#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton12Click
end
object TntButton10: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #22312#19968#20010'UTF-8 '#23383#31526#20018#20013#65292#21028#26029#25351#23450#20301#32622#19978#30340#23383#31526#30340#31532#19968#20010#32534#30721#21333#20803#26159#23383#31526#20018#20013#30340#31532#20960#20010#32534#30721#21333#20803
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton10Click
end
object Edit11: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit11KeyPress
end
end
object TntGroupBox11: TTntGroupBox
Left = 404
Top = 277
Width = 186
Height = 55
Caption = 'CPToUTF8CUS'#20989#25968
TabOrder = 5
object Edit12: TEdit
Left = 10
Top = 18
Width = 80
Height = 20
CharCase = ecUpperCase
MaxLength = 8
TabOrder = 0
OnChange = Edit4Change
OnEnter = Edit1Enter
OnKeyPress = Edit12KeyPress
end
object TntButton11: TTntButton
Left = 95
Top = 18
Width = 75
Height = 25
Hint = #25226#25351#23450#30340'Unicode'#32534#30721#28857#25968#23383#36716#25442#20026#30456#24212#30340'UTF-8'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
Enabled = False
TabOrder = 1
OnClick = TntButton11Click
end
end
object TntGroupBox12: TTntGroupBox
Left = 404
Top = 334
Width = 186
Height = 55
Caption = 'GetCPPartIndexOfUTF8'#20989#25968
TabOrder = 6
object Edit13: TEdit
Left = 10
Top = 18
Width = 80
Height = 20
CharCase = ecUpperCase
MaxLength = 8
TabOrder = 0
OnChange = Edit4Change
OnEnter = Edit1Enter
OnKeyPress = Edit13KeyPress
end
object TntButton12: TTntButton
Left = 95
Top = 18
Width = 75
Height = 25
Hint = #21028#26029#19968#20010#25351#23450#30340'Unicode'#32534#30721#28857#25968#23383#23646#20110'UTF-8'#32534#30721#28857#20998#27573#30340#21738#19968#27573
Caption = #35797#32451
Enabled = False
TabOrder = 1
OnClick = TntButton12Click
end
end
object TntGroupBox13: TTntGroupBox
Left = 134
Top = 300
Width = 265
Height = 89
Caption = 'UTF8CUSToCP'#20989#25968
TabOrder = 7
object TntRadioButton13: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton13Click
end
object TntRadioButton14: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton14Click
end
object TntButton13: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#21333#20803#24207#21015#36716#25442#20026'Unicode'#32534#30721#28857#25968#23383
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton13Click
end
object Edit14: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit14KeyPress
end
end
end
object TntTabSheet7: TTntTabSheet
Caption = #32534#30721#26684#24335#32508#21512#22788#29702
OnShow = TntTabSheet7Show
object TntRichEdit5: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit5Change
OnDblClick = TntRichEdit5DblClick
OnSelectionChange = TntRichEdit5SelectionChange
end
object TntRichEdit6: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit6SelectionChange
end
object TntGroupBox14: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 89
TabOrder = 2
object TntRadioButton17: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton17Click
end
object TntRadioButton18: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton18Click
end
object TntButton14: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #22312#19968#20010'UTF-16'#23383#31526#20018#20013#65292#25226#25351#23450#20301#32622#19978#37027#20010#32534#30721#21333#20803#25152#23646#30340#23383#31526#30340#32534#30721#21333#20803#24207#21015#36716#25442#25104'UTF-8 '#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton14Click
end
object Edit15: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit15KeyPress
end
end
object TntRadioButton19: TTntRadioButton
Left = 410
Top = 0
Width = 153
Height = 17
Caption = 'UTF16ToUTF8ForChar'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton19Click
end
object TntGroupBox15: TTntGroupBox
Left = 404
Top = 92
Width = 265
Height = 89
TabOrder = 4
object TntRadioButton20: TTntRadioButton
Left = 10
Top = 24
Width = 113
Height = 17
Caption = #25351#23450#32534#30721#21333#20803#20301#32622
TabOrder = 0
OnClick = TntRadioButton20Click
end
object TntRadioButton21: TTntRadioButton
Left = 138
Top = 24
Width = 113
Height = 17
Caption = #24403#21069#32534#30721#21333#20803#20301#32622
Checked = True
TabOrder = 1
TabStop = True
OnClick = TntRadioButton21Click
end
object TntButton15: TTntButton
Left = 138
Top = 53
Width = 75
Height = 25
Hint = #22312#19968#20010'UTF-8'#23383#31526#20018#20013#65292#25226#25351#23450#20301#32622#19978#30340#32534#30721#21333#20803#25152#23646#30340#37027#20010#23383#31526#30340#32534#30721#21333#20803#24207#21015#36716#25442#20026'UTF-16'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 3
OnClick = TntButton15Click
end
object Edit16: TEdit
Left = 10
Top = 53
Width = 121
Height = 20
TabOrder = 2
OnChange = Edit1Change
OnEnter = Edit1Enter
OnKeyPress = Edit16KeyPress
end
end
object TntRadioButton22: TTntRadioButton
Left = 410
Top = 91
Width = 153
Height = 17
Caption = 'UTF8ToUTF16ForChar'#20989#25968
TabOrder = 5
OnClick = TntRadioButton19Click
end
object TntGroupBox16: TTntGroupBox
Left = 404
Top = 184
Width = 265
Height = 65
TabOrder = 6
object TntButton16: TTntButton
Left = 138
Top = 24
Width = 75
Height = 25
Hint = #25226'UTF-16'#23383#31526#20018#36716#25442#20026'UTF-8'#23383#31526#20018
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton16Click
end
end
object TntRadioButton23: TTntRadioButton
Left = 410
Top = 184
Width = 147
Height = 17
Caption = 'UTF16ToUTF8ForStr'#20989#25968
TabOrder = 7
OnClick = TntRadioButton19Click
end
object TntGroupBox17: TTntGroupBox
Left = 404
Top = 265
Width = 265
Height = 60
TabOrder = 8
object TntButton17: TTntButton
Left = 138
Top = 24
Width = 75
Height = 25
Hint = #25226'UTF-8'#23383#31526#20018#36716#25442#20026'UTF-16'#23383#31526#20018
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton17Click
end
end
object TntRadioButton24: TTntRadioButton
Left = 410
Top = 267
Width = 147
Height = 17
Caption = 'UTF8ToUTF16ForStr'#20989#25968
TabOrder = 9
OnClick = TntRadioButton19Click
end
object TntGroupBox18: TTntGroupBox
Left = 404
Top = 329
Width = 265
Height = 60
TabOrder = 10
object TntButton18: TTntButton
Left = 138
Top = 24
Width = 75
Height = 25
Hint = #25226'UTF-16'#23383#31526#20018#36716#25442#20026'UTF-32'#23383#31526#20018
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton18Click
end
end
object TntRadioButton25: TTntRadioButton
Left = 410
Top = 329
Width = 153
Height = 17
Caption = 'UTF16ToUTF32ForStr'#20989#25968
TabOrder = 11
OnClick = TntRadioButton19Click
end
object TntGroupBox19: TTntGroupBox
Left = 203
Top = 265
Width = 196
Height = 60
TabOrder = 12
object TntButton19: TTntButton
Left = 100
Top = 24
Width = 75
Height = 25
Hint = #25226'UTF-32'#23383#31526#20018#36716#25442#20026'UTF-16'#23383#31526#20018
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton19Click
end
end
object TntGroupBox20: TTntGroupBox
Left = 203
Top = 329
Width = 196
Height = 60
TabOrder = 13
object TntButton20: TTntButton
Left = 100
Top = 24
Width = 75
Height = 25
Hint = #25226'UTF-8'#23383#31526#20018#36716#25442#20026'UTF-32'#23383#31526#20018
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton20Click
end
end
object TntRadioButton26: TTntRadioButton
Left = 209
Top = 267
Width = 153
Height = 17
Caption = 'UTF32ToUTF16ForStr'#20989#25968
TabOrder = 14
OnClick = TntRadioButton19Click
end
object TntRadioButton27: TTntRadioButton
Left = 209
Top = 329
Width = 148
Height = 17
Caption = 'UTF8ToUTF32ForStr'#20989#25968
TabOrder = 15
OnClick = TntRadioButton19Click
end
object TntGroupBox21: TTntGroupBox
Left = 0
Top = 265
Width = 196
Height = 60
TabOrder = 16
object TntButton21: TTntButton
Left = 100
Top = 24
Width = 75
Height = 25
Hint = #25226'UTF-32'#23383#31526#20018#36716#25442#20026'UTF-8'#23383#31526#20018
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton21Click
end
end
object TntRadioButton28: TTntRadioButton
Left = 6
Top = 267
Width = 147
Height = 17
Caption = 'UTF32ToUTF8ForStr'#20989#25968
TabOrder = 17
OnClick = TntRadioButton19Click
end
end
object TntTabSheet8: TTntTabSheet
Caption = #36741#21161#27169#22359
OnShow = TntTabSheet8Show
object TntRichEdit7: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit7Change
OnDblClick = TntRichEdit7DblClick
OnSelectionChange = TntRichEdit7SelectionChange
end
object TntRichEdit8: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit8SelectionChange
end
object TntGroupBox22: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 65
TabOrder = 2
object TntButton22: TTntButton
Left = 138
Top = 24
Width = 75
Height = 25
Hint = #35745#31639'UTF-16'#23383#31526#20018#20013#30340#23383#31526#25968#30446
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton22Click
end
end
object TntRadioButton29: TTntRadioButton
Left = 410
Top = 0
Width = 159
Height = 17
Caption = 'CharCountOfUTF16Str'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton29Click
end
object TntGroupBox23: TTntGroupBox
Left = 404
Top = 69
Width = 265
Height = 60
TabOrder = 4
object TntButton23: TTntButton
Left = 138
Top = 24
Width = 75
Height = 25
Hint = #35745#31639'UTF-8'#23383#31526#20018#20013#30340#23383#31526#25968#30446
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton23Click
end
end
object TntRadioButton30: TTntRadioButton
Left = 410
Top = 69
Width = 154
Height = 17
Caption = 'CharCountOfUTF8Str'#20989#25968
TabOrder = 5
OnClick = TntRadioButton29Click
end
object TntGroupBox24: TTntGroupBox
Left = 404
Top = 133
Width = 265
Height = 60
TabOrder = 6
object TntButton24: TTntButton
Left = 138
Top = 24
Width = 75
Height = 25
Hint = #35745#31639'UTF-32'#23383#31526#20018#20013#30340#23383#31526#25968#30446
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton24Click
end
end
object TntRadioButton31: TTntRadioButton
Left = 410
Top = 133
Width = 160
Height = 17
Caption = 'CharCountOfUTF32Str'#20989#25968
TabOrder = 7
OnClick = TntRadioButton29Click
end
end
end
end
object TntTabSheet2: TTntTabSheet
Caption = 'Unicode'#32534#30721#26426#21046#22788#29702
OnShow = TntTabSheet1Show
object TntPageControl3: TTntPageControl
Left = 0
Top = 0
Width = 680
Height = 419
ActivePage = TntTabSheet9
Align = alClient
TabOrder = 0
TabPosition = tpBottom
object TntTabSheet9: TTntTabSheet
Caption = #30456#21516'UTF'#30340#32534#30721#26684#24335#21644#32534#30721#26426#21046#20043#38388#30340#36716#25442
OnShow = TntTabSheet9Show
object TntRichEdit9: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit9Change
OnDblClick = TntRichEdit9DblClick
OnSelectionChange = TntRichEdit9SelectionChange
end
object TntRichEdit10: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit10SelectionChange
end
object TntGroupBox25: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
TabOrder = 2
object TntButton25: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#21333#20803#24207#21015#36716#25442#20026#24102'BOM'#30340'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton25Click
end
object TntComboBox1: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'
Items.Strings = (
#19981#24102'BOM'
#24102'BOM')
end
end
object TntRadioButton32: TTntRadioButton
Left = 410
Top = 0
Width = 129
Height = 17
Caption = 'CUSToBSForUTF8'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton32Click
end
object TntGroupBox26: TTntGroupBox
Left = 404
Top = 66
Width = 265
Height = 54
TabOrder = 4
object TntButton26: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#36716#25442#20026'UTF-8'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton26Click
end
end
object TntRadioButton33: TTntRadioButton
Left = 410
Top = 66
Width = 129
Height = 17
Caption = 'BSToCUSForUTF8'#20989#25968
TabOrder = 5
OnClick = TntRadioButton32Click
end
object TntGroupBox27: TTntGroupBox
Left = 404
Top = 132
Width = 265
Height = 54
TabOrder = 6
object TntButton27: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#21333#20803#24207#21015#36716#20026'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton27Click
end
object TntComboBox2: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton34: TTntRadioButton
Left = 410
Top = 132
Width = 135
Height = 17
Caption = 'CUSToBSForUTF16'#20989#25968
TabOrder = 7
OnClick = TntRadioButton32Click
end
object TntGroupBox28: TTntGroupBox
Left = 404
Top = 200
Width = 265
Height = 54
TabOrder = 8
object TntButton28: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-16'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton28Click
end
end
object TntRadioButton35: TTntRadioButton
Left = 410
Top = 200
Width = 135
Height = 17
Caption = 'BSToCUSForUTF16'#20989#25968
TabOrder = 9
OnClick = TntRadioButton32Click
end
object TntGroupBox29: TTntGroupBox
Left = 404
Top = 268
Width = 265
Height = 54
TabOrder = 10
object TntButton29: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-32'#32534#30721#21333#20803#24207#21015#36716#20026'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton29Click
end
object TntComboBox3: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton36: TTntRadioButton
Left = 410
Top = 268
Width = 135
Height = 17
Caption = 'CUSToBSForUTF32'#20989#25968
TabOrder = 11
OnClick = TntRadioButton32Click
end
object TntGroupBox30: TTntGroupBox
Left = 404
Top = 335
Width = 265
Height = 54
TabOrder = 12
object TntButton30: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-32'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton30Click
end
end
object TntRadioButton37: TTntRadioButton
Left = 410
Top = 335
Width = 135
Height = 17
Caption = 'BSToCUSForUTF32'#20989#25968
TabOrder = 13
OnClick = TntRadioButton32Click
end
end
object TntTabSheet10: TTntTabSheet
Caption = #19981#21516#32534#30721#26426#21046#20043#38388#30340#36716#25442
OnShow = TntTabSheet10Show
object TntRichEdit11: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit11Change
OnDblClick = TntRichEdit11DblClick
OnSelectionChange = TntRichEdit11SelectionChange
end
object TntRichEdit12: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit12SelectionChange
end
object TntGroupBox31: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
TabOrder = 2
object TntButton31: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#36716#25442#20026'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton31Click
end
object TntComboBox4: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton38: TTntRadioButton
Left = 410
Top = 0
Width = 141
Height = 17
Caption = 'UTF8ToUTF16ForBS'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton38Click
end
object TntGroupBox32: TTntGroupBox
Left = 404
Top = 66
Width = 265
Height = 54
TabOrder = 4
object TntButton32: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton32Click
end
object TntComboBox5: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton39: TTntRadioButton
Left = 410
Top = 66
Width = 141
Height = 17
Caption = 'UTF8ToUTF32ForBS'#20989#25968
TabOrder = 5
OnClick = TntRadioButton38Click
end
object TntGroupBox33: TTntGroupBox
Left = 404
Top = 133
Width = 265
Height = 54
TabOrder = 6
object TntButton33: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton33Click
end
end
object TntRadioButton40: TTntRadioButton
Left = 410
Top = 133
Width = 141
Height = 17
Caption = 'UTF16ToUTF8ForBS'#20989#25968
TabOrder = 7
OnClick = TntRadioButton38Click
end
object TntGroupBox34: TTntGroupBox
Left = 404
Top = 202
Width = 265
Height = 54
TabOrder = 8
object TntButton34: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton34Click
end
object TntComboBox6: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton41: TTntRadioButton
Left = 410
Top = 202
Width = 147
Height = 17
Caption = 'UTF16ToUTF32ForBS'#20989#25968
TabOrder = 9
OnClick = TntRadioButton38Click
end
object TntGroupBox35: TTntGroupBox
Left = 404
Top = 270
Width = 265
Height = 54
TabOrder = 10
object TntButton35: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton35Click
end
end
object TntRadioButton42: TTntRadioButton
Left = 410
Top = 270
Width = 141
Height = 17
Caption = 'UTF32ToUTF8ForBS'#20989#25968
TabOrder = 11
OnClick = TntRadioButton38Click
end
object TntGroupBox36: TTntGroupBox
Left = 404
Top = 335
Width = 265
Height = 54
TabOrder = 12
object TntButton36: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#36716#25442#20026'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton36Click
end
object TntComboBox7: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton43: TTntRadioButton
Left = 410
Top = 335
Width = 147
Height = 17
Caption = 'UTF32ToUTF16ForBS'#20989#25968
TabOrder = 13
OnClick = TntRadioButton38Click
end
end
object TntTabSheet11: TTntTabSheet
Caption = #36741#21161#27169#22359
OnShow = TntTabSheet11Show
object TntRichEdit13: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit13Change
OnDblClick = TntRichEdit13DblClick
OnSelectionChange = TntRichEdit13SelectionChange
end
object TntRichEdit14: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit14SelectionChange
end
object TntGroupBox37: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
TabOrder = 2
object TntButton37: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #35745#31639'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#20013#30340#23383#31526#25968#30446
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton37Click
end
end
object TntRadioButton44: TTntRadioButton
Left = 410
Top = 0
Width = 147
Height = 17
Caption = 'CharCountOfUTF8BS'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton44Click
end
object TntGroupBox38: TTntGroupBox
Left = 404
Top = 64
Width = 265
Height = 54
TabOrder = 4
object TntButton38: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #35745#31639'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#20013#30340#23383#31526#25968#30446
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton38Click
end
end
object TntRadioButton45: TTntRadioButton
Left = 410
Top = 64
Width = 153
Height = 17
Caption = 'CharCountOfUTF16BS'#20989#25968
TabOrder = 5
OnClick = TntRadioButton44Click
end
object TntGroupBox39: TTntGroupBox
Left = 404
Top = 128
Width = 265
Height = 54
TabOrder = 6
object TntButton39: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #35745#31639'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#20013#30340#23383#31526#25968#30446
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton39Click
end
end
object TntRadioButton46: TTntRadioButton
Left = 410
Top = 128
Width = 153
Height = 17
Caption = 'CharCountOfUTF32BS'#20989#25968
TabOrder = 7
OnClick = TntRadioButton44Click
end
end
end
end
object TntTabSheet3: TTntTabSheet
Caption = #32534#30721#26684#24335#21644#32534#30721#26426#21046#32508#21512#22788#29702
OnShow = TntTabSheet1Show
object TntPageControl4: TTntPageControl
Left = 0
Top = 0
Width = 680
Height = 419
ActivePage = TntTabSheet13
Align = alClient
TabOrder = 0
TabPosition = tpBottom
object TntTabSheet12: TTntTabSheet
Caption = #19981#21516'UTF'#30340#32534#30721#26684#24335#21521#32534#30721#26426#21046#30340#36716#25442
OnShow = TntTabSheet12Show
object TntRichEdit15: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit15Change
OnDblClick = TntRichEdit15DblClick
OnSelectionChange = TntRichEdit15SelectionChange
end
object TntRichEdit16: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit16SelectionChange
end
object TntGroupBox40: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
TabOrder = 2
object TntButton40: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#21333#20803#24207#21015#36716#25442#20026'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton40Click
end
object TntComboBox8: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton47: TTntRadioButton
Left = 410
Top = 0
Width = 141
Height = 17
Caption = 'UTF8CUSToUTF16BS'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton47Click
end
object TntGroupBox41: TTntGroupBox
Left = 404
Top = 66
Width = 265
Height = 54
TabOrder = 4
object TntButton41: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#21333#20803#24207#21015#36716#20026'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton41Click
end
object TntComboBox9: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton48: TTntRadioButton
Left = 410
Top = 66
Width = 141
Height = 17
Caption = 'UTF8CUSToUTF32BS'#20989#25968
TabOrder = 5
OnClick = TntRadioButton47Click
end
object TntGroupBox42: TTntGroupBox
Left = 404
Top = 133
Width = 265
Height = 54
TabOrder = 6
object TntButton42: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#21333#20803#24207#21015#36716#20026'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton42Click
end
end
object TntRadioButton49: TTntRadioButton
Left = 410
Top = 133
Width = 141
Height = 17
Caption = 'UTF16CUSToUTF8BS'#20989#25968
TabOrder = 7
OnClick = TntRadioButton47Click
end
object TntGroupBox43: TTntGroupBox
Left = 404
Top = 202
Width = 265
Height = 54
TabOrder = 8
object TntButton43: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#21333#20803#24207#21015#36716#20026'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton43Click
end
object TntComboBox10: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton50: TTntRadioButton
Left = 410
Top = 202
Width = 147
Height = 17
Caption = 'UTF16CUSToUTF32BS'#20989#25968
TabOrder = 9
OnClick = TntRadioButton47Click
end
object TntGroupBox44: TTntGroupBox
Left = 404
Top = 270
Width = 265
Height = 54
TabOrder = 10
object TntButton44: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-32'#32534#30721#21333#20803#24207#21015#36716#20026'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton44Click
end
end
object TntRadioButton51: TTntRadioButton
Left = 410
Top = 270
Width = 141
Height = 17
Caption = 'UTF32CUSToUTF8BS'#20989#25968
TabOrder = 11
OnClick = TntRadioButton47Click
end
object TntGroupBox45: TTntGroupBox
Left = 404
Top = 335
Width = 265
Height = 54
TabOrder = 12
object TntButton45: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = 'UTF-32'#32534#30721#21333#20803#24207#21015#36716'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton45Click
end
object TntComboBox11: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton52: TTntRadioButton
Left = 410
Top = 335
Width = 147
Height = 17
Caption = 'UTF32CUSToUTF16BS'#20989#25968
TabOrder = 13
OnClick = TntRadioButton47Click
end
end
object TntTabSheet13: TTntTabSheet
Caption = #19981#21516'UTF'#30340#32534#30721#26426#21046#21521#32534#30721#26684#24335#30340#36716#25442
OnShow = TntTabSheet13Show
object TntRichEdit17: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit17Change
OnDblClick = TntRichEdit17DblClick
OnSelectionChange = TntRichEdit17SelectionChange
end
object TntRichEdit18: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit18SelectionChange
end
object TntGroupBox46: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
TabOrder = 2
object TntButton46: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-16'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton46Click
end
end
object TntRadioButton53: TTntRadioButton
Left = 410
Top = 0
Width = 141
Height = 17
Caption = 'UTF8BSToUTF16CUS'#20989#25968
Checked = True
TabOrder = 3
TabStop = True
OnClick = TntRadioButton53Click
end
object TntGroupBox47: TTntGroupBox
Left = 404
Top = 66
Width = 265
Height = 54
TabOrder = 4
object TntButton47: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-32'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton47Click
end
end
object TntRadioButton54: TTntRadioButton
Left = 410
Top = 66
Width = 141
Height = 17
Caption = 'UTF8BSToUTF32CUS'#20989#25968
TabOrder = 5
OnClick = TntRadioButton53Click
end
object TntGroupBox48: TTntGroupBox
Left = 404
Top = 133
Width = 265
Height = 54
TabOrder = 6
object TntButton48: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-8'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton48Click
end
object TntComboBox12: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
OnSelect = TntComboBox12Select
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton55: TTntRadioButton
Left = 410
Top = 133
Width = 141
Height = 17
Caption = 'UTF16BSToUTF8CUS'#20989#25968
TabOrder = 7
OnClick = TntRadioButton53Click
end
object TntGroupBox49: TTntGroupBox
Left = 404
Top = 202
Width = 265
Height = 54
TabOrder = 8
object TntButton49: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-32'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton49Click
end
object TntComboBox14: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
OnSelect = TntComboBox12Select
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton56: TTntRadioButton
Left = 410
Top = 202
Width = 147
Height = 17
Caption = 'UTF16BSToUTF32CUS'#20989#25968
TabOrder = 9
OnClick = TntRadioButton53Click
end
object TntGroupBox50: TTntGroupBox
Left = 404
Top = 270
Width = 265
Height = 54
TabOrder = 10
object TntButton50: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#36716#20026'UTF-8'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton50Click
end
object TntComboBox13: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
OnSelect = TntComboBox12Select
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton57: TTntRadioButton
Left = 410
Top = 270
Width = 141
Height = 17
Caption = 'UTF32BSToUTF8CUS'#20989#25968
TabOrder = 11
OnClick = TntRadioButton53Click
end
object TntGroupBox51: TTntGroupBox
Left = 404
Top = 335
Width = 265
Height = 54
TabOrder = 12
object TntButton51: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = 'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#36716'UTF-16'#32534#30721#21333#20803#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton51Click
end
object TntComboBox15: TTntComboBox
Left = 10
Top = 21
Width = 165
Height = 20
Style = csDropDownList
ItemHeight = 12
ItemIndex = 0
TabOrder = 1
Text = #19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
OnSelect = TntComboBox12Select
Items.Strings = (
#19981#24102'BOM'#30340#40664#35748#23383#33410#24207#24207#21015
#24102'BOM'#30340#22823#23614#23383#33410#24207#24207#21015
#24102'BOM'#30340#23567#23614#23383#33410#24207#24207#21015)
end
end
object TntRadioButton58: TTntRadioButton
Left = 410
Top = 335
Width = 147
Height = 17
Caption = 'UTF32BSToUTF16CUS'#20989#25968
TabOrder = 13
OnClick = TntRadioButton53Click
end
end
end
end
object TntTabSheet4: TTntTabSheet
Caption = #36741#21161#27169#22359
OnShow = TntTabSheet1Show
object TntPageControl5: TTntPageControl
Left = 0
Top = 0
Width = 680
Height = 419
ActivePage = TntTabSheet15
Align = alClient
TabOrder = 0
TabPosition = tpBottom
object TntTabSheet14: TTntTabSheet
Caption = #21028#26029#26410#30693#32534#30721#26684#24335#23383#33410#24207#21015#30340#31867#22411
OnShow = TntTabSheet14Show
object TntRichEdit19: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit19Change
OnSelectionChange = TntRichEdit19SelectionChange
end
object TntRichEdit20: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit20SelectionChange
end
object TntGroupBox52: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
Caption = 'GuessUTF8BSAvaiByteCount'#20989#25968
TabOrder = 2
object TntButton52: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #22312#19968#20010#26410#30693#32534#30721#26684#24335#30340#23383#33410#24207#21015#20013#25353#29031'UTF-8 '#32534#30721#26426#21046#30340#35268#21017#65292#35745#31639#20986#20840#37096#26377#25928#23383#31526#30340#23383#33410#24207#21015#24635#38271#24230
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton52Click
end
end
object TntGroupBox53: TTntGroupBox
Left = 404
Top = 66
Width = 265
Height = 54
Caption = 'GuessUTF16BSAvaiByteCount'#20989#25968
TabOrder = 3
object TntButton53: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #22312#19968#20010#26410#30693#32534#30721#26684#24335#30340#23383#33410#24207#21015#20013#25353#29031'UTF-16'#32534#30721#26426#21046#30340#35268#21017#65292#35745#31639#20986#20840#37096#26377#25928#23383#31526#30340#23383#33410#24207#21015#24635#38271#24230
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton53Click
end
end
object TntGroupBox54: TTntGroupBox
Left = 404
Top = 133
Width = 265
Height = 54
Caption = 'GuessUTF32BSAvaiByteCount'#20989#25968
TabOrder = 4
object TntButton54: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #22312#19968#20010#26410#30693#32534#30721#26684#24335#30340#23383#33410#24207#21015#20013#25353#29031'UTF-32'#32534#30721#26426#21046#30340#35268#21017#65292#35745#31639#20986#20840#37096#26377#25928#23383#31526#30340#23383#33410#24207#21015#24635#38271#24230
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton54Click
end
end
object TntGroupBox55: TTntGroupBox
Left = 404
Top = 200
Width = 265
Height = 54
Caption = 'BOMTypeOfUTF8BS'#20989#25968
TabOrder = 5
object TntButton55: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #26816#27979#19968#20010'UTF-8'#32534#30721#26684#24335#23383#33410#24207#21015#30340'BOM'#31867#22411
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton55Click
end
end
object TntGroupBox56: TTntGroupBox
Left = 404
Top = 269
Width = 265
Height = 54
Caption = 'BOMTypeOfUTF16BS'#20989#25968
TabOrder = 6
object TntButton56: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #26816#27979#19968#20010'UTF-16'#32534#30721#26684#24335#23383#33410#24207#21015#30340'BOM'#31867#22411
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton56Click
end
end
object TntGroupBox57: TTntGroupBox
Left = 404
Top = 334
Width = 265
Height = 54
Caption = 'BOMTypeOfUTF32BS'#20989#25968
TabOrder = 7
object TntButton57: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #26816#27979#19968#20010'UTF-32'#32534#30721#26684#24335#23383#33410#24207#21015#30340'BOM'#31867#22411
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton57Click
end
end
object TntGroupBox58: TTntGroupBox
Left = 134
Top = 269
Width = 265
Height = 54
Caption = 'GuessBSType'#20989#25968
TabOrder = 8
object TntButton58: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #8220#29468#27979#8221#19968#20010#26410#30693#32534#30721#26684#24335#30340#23383#33410#24207#21015#25152#20351#29992#30340'Unicode'#32534#30721#26426#21046#31867#22411
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton58Click
end
end
end
object TntTabSheet15: TTntTabSheet
Caption = #25991#26412#25991#20214'I/O'
OnShow = TntTabSheet15Show
object TntRichEdit21: TTntRichEdit
Left = 0
Top = 0
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WantTabs = True
OnChange = TntRichEdit21Change
OnSelectionChange = TntRichEdit21SelectionChange
end
object TntRichEdit22: TTntRichEdit
Left = 0
Top = 133
Width = 399
Height = 132
Cursor = crArrow
TabStop = False
Align = alCustom
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Sun-ExtB'
Font.Style = []
HideSelection = False
ParentFont = False
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 1
WantTabs = True
OnSelectionChange = TntRichEdit22SelectionChange
end
object TntGroupBox59: TTntGroupBox
Left = 404
Top = 0
Width = 265
Height = 54
Caption = 'SaveUniByteSequToFile'#20989#25968
TabOrder = 2
object TntButton59: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #25226#19968#20010'Unicode'#32534#30721#26684#24335#23383#33410#24207#21015#20889#20986#21040#25351#23450#30340#25991#20214#20013
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton59Click
end
end
object TntGroupBox60: TTntGroupBox
Left = 404
Top = 66
Width = 265
Height = 54
Caption = 'LoadUniByteSequFromFile'#20989#25968
TabOrder = 3
object TntButton60: TTntButton
Left = 180
Top = 21
Width = 75
Height = 25
Hint = #20174#25991#26412#25991#20214#20013#35835#20837'Unicode'#32534#30721#26684#24335#23383#33410#24207#21015
Caption = #35797#32451
TabOrder = 0
OnClick = TntButton60Click
end
end
end
end
end
end
object TntOpenDialog1: TTntOpenDialog
Left = 160
Top = 235
end
object TntSaveDialog1: TTntSaveDialog
Left = 192
Top = 235
end
end
 
下载了,学习。
 
散分了。
 

Similar threads

回复
0
查看
864
不得闲
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
顶部