关于文本对象模型

文本对象模型(TOM)定义一组文本作接口,这些接口由多个Microsoft文本解决方案(包括丰富的编辑控件)支持不同程度。 本主题提供 TOM 的高级概述。 本文讨论以下主题。

TOM 版本 2 对象

TOM 版本 2 (TOM 2) 扩展原始文本对象模型:新接口派生自旧接口。 更新的 TOM API 包括对新字符和段落格式属性、表格模型、多选和对数学和 ruby 的内联对象支持。

顶级 TOM 2 对象由 ITextDocument2 接口定义,该接口具有创建和检索对象层次结构中较低对象的方法。 对于简单的纯文本处理,可以从 ITextDocument2 对象获取 ITextRange2 对象,并使用该对象执行大部分作。 如果需要添加富文本格式,可以从 ITextRange2 对象中获取 ITextFont2ITextPara2 对象。 ITextFont2 提供与 Microsoft Word 格式字体对话框等效的编程, ITextPara2 提供与 Word 格式段落对话框等效的编程。

除了这三个较低级别的对象外,TOM 2 还有一个选择对象(ITextSelection2),它是一个 ITextRange2 对象,其中突出显示了选定内容和一些面向 UI 的方法。

范围和选择对象包括面向屏幕的方法,这些方法使程序能够检查屏幕上的文本或可滚动到屏幕上的文本。 例如,这些功能有助于使视力受损的人能够访问文本。

具有 2 个后缀的每个接口都继承自相应的接口,而不继承 2 个后缀。 例如, ITextDocument2 继承自 ITextDocument

TOM 2 对象具有以下层次结构。

ITextDocument2         Top-level editing object
    ITextRange2        Primary text interface: a range of text
        ITextFont2     Character-attribute interface
        ITextPara2     Paragraph-attribute interface
        ITextRow       Table interface
    ITextSelection2    Screen highlighted text range
        ITextRange2    Selection inherits all range methods
    ITextDisplays      Displays collection (not yet defined)
    ITextStrings       Rich-text strings collection
    ITextStoryRanges2  Enumerator for stories in document

ITextDocument2 对象描述一个或多个称为故事的文本连续范围。 故事表示文档的各个部分,例如文档的主文本、页眉和页脚、脚注、批注和富文本暂存板。 在线性格式的数学表达式和内置窗体之间进行转换时,将使用暂存板故事。 当保存一个当前复制源的范围内容,而这些内容即将更改时,还会使用暂存板记录。

ITextRange2 对象由其开始和结束字符位置偏移量和故事对象定义。 它不与其父故事对象独立存在,尽管其文本可以复制到剪贴板或其他目标。 文本范围对象不同于电子表格和其他范围对象,这些对象由其他类型的偏移量定义:例如,行/列或图形位置(x,y)。 文本范围对象可以以各种方式修改自身,可以返回自身的重复项,并且可以命令复制其开始和结束字符位置以及指向当前所选内容的故事指针。

不需要显式情节对象,因为始终可以创建 ITextRange 对象来表示任何给定的故事。 具体而言, ITextDocument 对象可以创建 一个 ITextStoryRanges 对象,以范围来枚举文档中的故事,其中包含描述完整故事(如 0 和 tomForward)的起始和结束字符位置值。

使用 ITextStoryRanges2 对象时,不需要显式故事对象,因为每个故事都由 ITextRange2 对象描述。 具体而言,ITextDocument2 对象可以创建 ITextStoryRanges2 对象,以按起始和结束字符位置值的范围枚举文档中的所有完整的故事(如 0 和 tomForward)。

ITextRow 接口与 ITextRange::MoveITextRange::Expand 方法一起提供插入、查询和更改表的功能。

TOM 接口约定

所有 TOM 方法都返回 HRESULT 值。 通常,TOM 方法返回以下标准值。

  • E_OUTOFMEMORY
  • E_INVALIDARG
  • E_NOTIMPL
  • E_FILENOTFOUND
  • E_ACCESSDENIED(访问被拒绝)
  • E_FAIL
  • CO_E_RELEASED
  • NOERROR (与S_OK相同)
  • S_FALSE

请注意,如果删除与 TOM 对象(如 ITextRange )关联的编辑实例,TOM 对象将变得无用,并且其所有方法都会返回CO_E_RELEASED。

除了 HRESULT 返回值之外,许多方法还包含 out 参数,这是用于返回值的指针。 对于所有接口,应检查所有指针参数,以确保在使用这些参数之前它们是非零的。 如果将 null 值传递给需要有效指针的方法,该方法将返回E_INVALIDARG。 忽略具有 null 值的可选 out 指针。

使用具有 Get 和 Set 前缀的方法来获取和设置属性。 布尔变量将 tomFalse (0) 用于 FALSE,将 tomTrue (-1) 用于 TRUE

TOM 常量在 tomConstants 枚举类型中定义,以前缀 tom 开头,例如 tomWord

tomBool 类型

许多 TOM 方法对具有二进制状态的富文本属性使用名为“tomBool”的特殊类型的变量。 tomBool 类型不同于 布尔 类型,因为它可以采用四个值:tomTruetomFalsetomToggletomUndefinedtomTruetomFalse 值指示 true 和 false。 tomToggle 值用于切换属性。 tomUndefined 值(更传统的称为 NINCH)是一种特殊的无输入、无更改值,适用于 longs、floats 和 COLORREFs。 对于字符串, tomUndefined (或 NINCH) 由 null 字符串表示。 对于属性设置作,使用 tomUndefined 不会更改目标属性。 在属性获取操作中,tomUndefined 表示范围内的字符具有不同的值(在属性对话框中显示为灰色复选框)。

数学递增和递减

可以使用 ITextRange2::BuildUpMath 方法将线性格式的数学表达式转换为内置版本。 ITextRange2::Linearize 方法执行相反的转换(称为线性化或向下生成)将数学表达式的内置版本转换回线性格式。 需要导出纯文本或启用某些类型的编辑时,数学生成功能非常有用。

TOM RTF

在 TOM 中,富文本交换可以通过一组显式方法调用或 RTF 中的富文本传输来实现。 本部分为段落属性和字符属性提供 RTF 控件单词的表。

TOM RTF 段落控制词

控制单词 含义
\ fi n 第一行缩进(默认值为零)。
\保持 保持段落不变。
\ keepn 继续下一段
\ li n 左缩进(默认值为零)。
\ noline 无行编号。
\ nowidctlpar 关闭寡妇/孤立控件。
\ pagebb 在段落前插入分页符。
\㩱 新段落。
\豹 重置为默认段落属性。
\ ql 左对齐(默认值)。
\ qr 右对齐。
\ qj 合理。
\ qc 居中。
\ ri n 右缩进(默认值为零)。
\ s n 样式 n.
\ sa n 之后的空格(默认值为零)。
\ sb n 前空格(默认值为零)。
\ sl n 如果缺少 或 n=1000,则行距由行中最高的字符确定(单行间距):如果 为 n> 零,则至少使用此大小;如果 n 为 < 零,则完全 |n|是使用的。 行距是多行间距,如果后面有 \ slmult 1。
\ slmult m 后跟 \ sl. m = 零:按 \ sl n 所述,至少或完全行距。 m = 1:行距 = n/240 次单行间距。
\ tb n 条形图选项卡位置(以 twips 为单位)从左边距开始。
\ tldot 制表符前导点。
\ tleq 制表符引导线等号。
\ tlhyph 制表符前导连字符。
\ tlth 制表符前导粗线。
\ tlul Tab 前导符下划线。
tqc 居中选项卡。
\ tqdec “小数”选项卡。
\ tqr 右对齐选项卡
\ tx n Tab 位置(以 twips 为单位)从左边距。

 

TOM RTF 字符格式控制词

控制单词 含义
\ 动画 n 将动画类型设置为 n
\ b 大胆。
\帽 所有首都。
\ cf n 前景颜色(默认值为 tomAutocolor)。
\ cs n 字符样式 n.
\ dn n 下标位置以半点为单位(默认值为 6)。
\ embo 浮雕。
\ f n 字号, n 表示字体表中的条目。
\ fs n 字号以半点为单位(默认值为 24)。
\ 突出显示 n 背景色(默认值为 tomAutocolor)。
\ i 斜体的。
\ impr 印记。
\ lang n 将语言应用于字符。 n 是对应于语言的数字。 \ 纯控件字将语言属性重置为文档属性中 \deflang n 定义的语言。
\ nosupersub 关闭上标或下标。
\ outl 大纲。
\平原 将字符格式属性重置为应用程序定义的默认值。 关联的字符格式属性(RTF 规范中的关联字符属性部分中所述)也会重置。
\ scaps 小型大写字母
\西鲱 影子。
\打 删除线。
\子 将下标应用于文本,并根据字体信息减小点大小。
\超 将上标应用于文本,并根据字体信息减小点大小。
\ ul 连续下划线。 \ul0 关闭所有下划线。
\ uld 点状下划线
\ uldb 双下划线。
\ ulnone 停止所有下划线。
\ ulw Word 下划线。
\ up n 上标位置在半点(默认值为 6)。
\ v 隐藏的文本。

 

查找富文本

可以使用 TOM 方法查找由一系列文本定义的富文本。 在文字处理中经常需要精确地找到如此丰富的文本,然而,它从未在“所见即所得”(WYSIWYG)文字处理器中实现过。 显然,有一个较大的格式文本匹配域,允许忽略某些字符格式属性(或包括段落格式和/或对象内容),但这种通用化超出了本部分的范围。

此功能的一个用途是使用富文本 “查找 ”对话框来定义要在文档中查找的富文本。 对话框将使用丰富的编辑控件实现,TOM 方法将用于通过文档执行搜索。 可以将所需的富文本从文档复制到 “查找” 对话框中,或者直接在 “查找” 对话框中输入并格式化。

以下示例演示如何使用 TOM 方法查找包含精确字符格式组合的文本。 该算法在匹配范围内搜索纯文本,并命名为 pr1。 如果找到纯文本,则由一个命名 pr2的试用范围指向它。 然后,使用两个插入点范围(prip1prip2)遍历试验范围,将其字符格式与它的 pr1字符格式进行比较。 如果它们完全匹配,则输入范围(由 ppr给定)更新为指向试用范围的文本,并且该函数返回匹配区域中的字符计数。 两个 ITextFont 对象,pf1pf2,用于字符格式比较。 它们连接到插入点范围 prip1prip2

LONG FindRichText (
    ITextRange **ppr,             // Ptr to range to search
    ITextRange *pr1)              // Range with rich text to find
{
    BSTR        bstr;             // pr1 plain-text to search for
    LONG        cch;              // Text string count
    LONG        cch1, cch2;       // tomCharFormat run char counts
    LONG        cchMatch = 0;     // Nothing matched yet
    LONG        cp;               // Handy char position
    LONG        cpFirst1;         // pr1 cpFirst
    LONG        cpFirst2;         // pr2 cpFirst
    ITextFont  *    pf1, *pf      // Fonts corresponding to IPs prip1 and prip2
    ITextRange *pr2;              // Range duplicate to search with
    ITextRange *prip1, *prip      // Insertion points to walk pr1, pr2

    if (!ppr || !*ppr || !pr1)
        return E_INVALIDARG;

    // Initialize range and font objects used in search
    if ((*ppr)->GetDuplicate(&pr2)    != NOERROR ||
        pr1->GetDuplicate(&prip1)     != NOERROR ||
        pr2->GetDuplicate(&prip2)     != NOERROR ||
        prip1->GetFont(&pf1)          != NOERROR ||
        prip2->GetFont(&pf2)          != NOERROR ||
        pr1->GetText(&bstr)           != NOERROR )
    {
        return E_OUTOFMEMORY;
    }

    pr1->GetStart(&cpFirst1);

    // Keep searching till rich text is matched or no more plain-text hits
    while(!cchMatch && pr2->FindText(bstr, tomForward, 0, &cch) == NOERROR)
    {
        pr2->GetStart(&cpFirst2);                 // pr2 is a new trial range
        prip1->SetRange(cpFirst1, cpFirst1);      // Set up IPs to scan match
        prip2->SetRange(cpFirst2, cpFirst2);      //  and trial ranges

        while(cch > 0 &&
            pf1->IsEqual(pf2, NULL) == NOERROR)   // Walk match & trial ranges
        {                                         //  together comparing font
            prip1->GetStart(&cch1);               //  properties
            prip1->Move(tomCharFormat, 1, NULL);
            prip1->GetStart(&cp);
            cch1 = cp - cch1;                     // cch of next match font run

            prip2->GetStart(&cch2);
            prip2->Move(tomCharFormat, 1, NULL);
            prip2->GetStart(&cp);
            cch2 = cp - cch2;                      // cch of next trial font run

            if(cch1 < cch)                         // There is more to compare
            {
                if(cch1 != cch2)                   // Different run lengths:
                    break;                         //  no formatting match
                cch = cch - cch1;                  // Matched format run
            }
            else if(cch2 < cch)                    // Trial range format run too
                break;                             //  short

            else                                   // Both match and trial runs
            {                                      //  reach at least to match
                pr2->GetEnd(&cp);                  //  text end: rich-text match
                (*ppr)->SetRange(cpFirst2, cp)     // Set input range to hit
                cchMatch = cp - cpFirst2;          //  coordinates and return
                break;                             //  length of matched string
            }
        }
    }
    pr2->Release();
    prip1->Release();
    prip2->Release();
    pf1->Release();
    pf2->Release();
    SysFreeString(bstr);

    return cchMatch;
}

TOM 辅助功能

TOM 通过 ITextSelectionITextRange 接口提供辅助功能支持。 本部分介绍对辅助功能有用的方法,以及程序如何确定对象的 xy 屏幕位置。

由于基于 UI 的辅助功能程序通常适用于屏幕和鼠标,因此一个共同的问题是查找当前鼠标位置的相应 ITextDocument 接口(在屏幕坐标中)。 以下部分提供了两种方法来确定正确的接口:

有关详细信息,请参阅 Microsoft Active Accessibility 规范。 从屏幕位置获取对象后,可以用于 ITextDocument 接口,并调用 RangeFromPoint 方法以获取与屏幕位置对应的 cp 处的空范围对象。

运行对象表的接口

正在运行的对象表 (ROT) 指示哪些对象实例处于活动状态。 通过查询此表,可以加速在对象正在运行时将客户端连接到对象的过程。 在程序可以通过正在运行的对象表 (ROT) 访问面向对象模型 (TOM) 接口之前,具有窗口的 TOM 实例需要使用标识符在 ROT 中注册。 你可以从一个包含其 HWND 十六进制值的字符串中构造一个标识符对象。 下面的代码示例演示如何执行此作。

// This TOM implementation code is executed when a new windowed 
// instance starts up. 
// Variables with leading underscores are members of this class.

HRESULT hr;
OLECHAR szBuf[10];            // Place to put moniker
MONIKER *pmk;

hr = StringCchPrintf(szBuff, 10, "%x", _hwnd);
if (FAILED(hr))
{
    //
    // TODO: write error handler
    //
}
CreateFileMoniker(szBuf, &pmk);
OleStdRegisterAsRunning(this, pmk, &_dwROTcookie);
....................
 
// Accessibility Client: 
//    Find hwnd for window pointed to by mouse cursor.

GetCursorPos(&pt);
hwnd = WindowFromPoint(pt);

// Look in ROT (running object table) for an object attached to hwnd

hr = StringCchPrintf(szBuff, 10, "%x", hwnd);
if (FAILED(hr))
{
    //
    // TODO: write error handler
    //
}
CreateFileMoniker(szBuf, &pmk);
CreateBindContext(0, &pbc);
pmk->BindToObject(pbc, NULL, IID_ITextDocument, &pDoc);
pbc->Release();

if( pDoc )
{
    pDoc->RangeFromPoint(pt.x, pt.y, &pRange);
    // ...now do whatever with the range pRange
}

来自窗口消息的接口

EM_GETOLEINTERFACE消息提供了另一种方法,用于获取位于给定屏幕位置的对象 IUnknown 接口。 如“运行对象表的接口”中所述,你将获得一个用于屏幕位置的HWND,然后将此消息发送到该HWNDEM_GETOLEINTERFACE 消息专用于富文本编辑器,返回一个指针,该指针指向由 lParam 寻址的变量中的 IRichEditOle 接口。

提示 如果返回指针(请务必在发送消息之前将 lParam 指向的对象设置为 null),则可以调用其 IUnknown::QueryInterface 方法以获取 ITextDocument 接口。 以下代码示例演示了此方法。

    HWND    hwnd;
    ITextDocument *pDoc;
    ITextRange *pRange;
    POINT    pt;
    IUnknown *pUnk = NULL;
    
    GetCursorPos(&pt);
    hwnd = WindowFromPoint(pt);
    SendMessage(hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pUnk);
    if(pUnk && 
        pUnk->QueryInterface(IID_ITextDocument, &pDoc) == NOERROR)
    {
        pDoc->RangeFromPoint(pt.x, pt.y, &pRange);
        //  ... continue with rest of program
    }

面向可访问性的方法

某些 TOM 方法对于在屏幕上导航特别有用,而其他 TOM 方法可增强到达感兴趣的地方时的功能。 下表描述了最有用的方法。

方法 它如何促进可访问性
GetSelection 此方法获取可用于各种面向视图目的的活动选择,例如突出显示文本和滚动。
RangeFromPoint 在活动选择上使用时,此方法可以保证获取与特定视图关联的范围。
展开 扩展文本范围,以确保其中任何部分单位都被完全包含。 例如, Expand(tomWindow) 展开范围以包含区域故事的可见部分。
GetDuplicate 在活动选择上使用时,此方法可以保证获取与特定视图关联的范围。 请参阅 RangeFromPoint 的说明。
GetPoint 获取文本范围中开始或结束字符位置的屏幕坐标。
ScrollIntoView 将文本范围滚动到视图内。
SetPoint 在指定点或向上选择文本。

 

字符匹配集合

ITextRange 中各种 Move* 方法的变体参数(如 MoveWhileMoveUntil)可以采用显式字符串或字符匹配集 32 位索引。 索引由 Unicode 范围或 GetStringTypeEx 字符集定义。 索引 n + (l << 16) + 0x80000000提供从 n 和长度 l (<32768) 开始的 Unicode 范围。 例如,基本希腊文字母由 CR_Greek = 0x805f0370 定义,可打印 ASCII 字符由 CR_ASCIIPrint = 0x805e0020 定义。 此外, MoveWhileMoveUntil 方法允许你快速绕过任何 GetStringTypeEx 字符集中的字符范围,或者在这些字符集中的任何一个字符集中没有的字符范围中。

GetStringTypeEx 集由 Ctype1Ctype2 和 Ctype3 的值指定,定义如下。

Cset 含义
Ctype1 CT_CTYPE1类型的组合。
Ctype2 + tomCType2 任何CT_CTYPE2类型。
Ctype3 + tomCType3 CT_CTYPE3类型的组合。

 

具体而言, Ctype1 可以是以下任意组合。

Ctype1 名称 价值 含义
C1_UPPER 0x0001 大写。
C1_LOWER 0x0002 小写。
C1_DIGIT 0x0004 十进制数字。
C1_SPACE 0x0008 空格字符。
C1_PUNCT 0x0010 标点。
C1_CNTRL 0x0020 控制字符。
C1_BLANK 0x0040 空白字符。
C1_XDIGIT 0x0080 十六进制数字。
C1_ALPHA 0x0100 任何语言字符(字母、音节或象形字)。
C1_DEFINED 0x0200 已定义的字符,但不是其他C1_* 类型之一。

 

Ctype2 类型支持 Unicode 文本的正确布局。 分配方向属性,以便 Unicode 标准化的双向布局算法产生准确的结果。 这些类型是相互排斥的。 有关使用这些属性的详细信息,请参阅 Unicode 标准:全球字符编码、卷 1 和 2、Addison-Wesley 发布公司:1991、1992。

CType2 名称 价值 含义
强:
C2_从左至右 0x1 从左到右。
C2_RIGHTTOLEFT 0x2 从右到左。
弱:
C2_EUROPENUMBER 0x3 欧洲数字,欧洲数字符。
C2_EUROPESEPARATOR 0x4 欧洲数字分隔符。
C2_EUROPETERMINATOR 0x5 欧洲数字终止符。
C2_阿拉伯数字 0x6 阿拉伯语数字。
C2_COMMONSEPARATOR 0x7 通用数值分隔符。
中性:
C2_BLOCKSEPARATOR 0x8 块分隔符。
C2_SEGMENTSEPARATOR 0x9 段分隔符。
C2_WHITESPACE 0xA 空白。
C2_其他中性 0xB 其他中性物。
不適用:
C2_不适用 0x0 无隐式方向。

 

Ctype3 类型旨在用作常规文本处理或标准 C 库函数所需的 POSIX 类型的扩展的占位符。

CType3 名称 价值 含义
C3_NONSPACING 0x1 非间距标记。
C3_DIACRITIC 0x2 非间隔附加音调符号。
C3_VOWELMARK 0x4 元音非间隔符号
C3_SYMBOL 0x8 象征。
C3_KATAKANA 0x10 片假名字符。
C3_HIRAGANA 0x20 平假名字符。
C3_HALFWIDTH 0x40 半角字符。
C3_FULLWIDTH 0x80 全角字符。
C3_表意文字 0x100 象形字字符。
C3_KASHIDA 0x200 阿拉伯文 Kashida(卡什达)字符。
C3_ALPHA 0x8000 所有语言字符(字母、音节和象形字)。
C3_NOTAPPLICABLE 0x0 不適用。

 

编辑开发工具包 (EDK) 可以包括 Unicode 标准中介绍的以下范围的 pVar 索引定义。

字符集 Unicode 范围 字符集 Unicode 范围
ASCII 0x0 - 0x7f ANSI(美国国家标准协会) 0x0 — 0xff
ASCII打印 0x20 — 0x7e Latin1 0x20 — 0xff
Latin1Supp 0xa0 — 0xff LatinXA 0x100 — 0x17f
LatinXB 0x180 — 0x24f IPAX 0x250 — 0x2af
SpaceMod 0x2b0 — 0x2ff 结合 0x300 — 0x36f
希腊语 0x370 - 0x3ff BasicGreek 0x370 — 0x3cf
GreekSymbols 0x3d0 — 0x3ff 西里尔文 0x400 - 0x4ff
亚美尼亚语 0x530 — 0x58f 希伯来语 0x590 — 0x5ff
基础希伯来语 0x5d0 — 0x5ea 希伯来语XA 0x590 — 0x5cf
希伯来语XB 0x5eb — 0x5ff 阿拉伯语 0x600 - 0x6ff
BasicArabic 0x600 — 0x652 ArabicX 0x653 - 0x6ff
Devangari 0x900 — 0x97f 孟加拉语 0x980 — 0x9ff
锡克教文 0xa00 — 0xa7f 古吉拉特语 0xa80 — 0xaff
奥迪亚语 0xb00 — 0xb7f 泰米尔语 0xb80 — 0xbff
Teluga 0xc00 — 0xc7f 卡纳拉语 0xc80 — 0xcff
马拉雅拉姆语 0xd00 — 0xd7f 泰语 0xe00–0xe7f
老挝语 0xe80 — 0xeff 格鲁吉亚语X 0x10a0 - 0xa0cf
BascGeorgian 0x10d0 — 0x10ff Jamo 0x1100 — 0x11ff
LatinXAdd 0x1e00 — 0x1eff GreekX 0x1f00 — 0x1fff
GenPunct 0x2000 — 0x206f 上标 0x2070 — 0x207f
下标 0x2080 — 0x208f SuperSubscript 0x2070 — 0x209f
货币 0x20a0 — 0x20cf CombMarkSym 0x20d0 — 0x20ff
LetterLike 0x2100 — 0x214f NumberForms 0x2150 — 0x218f
箭头 0x2190 — 0x21ff MathOps 0x2200 — 0x22ff
MiscTech 0x2300 — 0x23ff CtrlPictures 0x2400 — 0x243f
光学字符识别 0x2440 — 0x245f EnclAlphaNum 0x2460 — x24ff
框线绘制 0x2500 — 0x257f BlockElement 0x2580 - 0x259f
GeometShapes 0x25a0 — 0x25ff 杂项符号 0x2600 — 0x26ff
丁巴特 0x2700 - 0x27bf CJKSymPunct 0x3000 — 0x303f
平假名 0x3040 - 0x309f 片假名 0x30a0 — 0x30ff
汉语拼音字母 0x3100 — 0x312f HangulJamo 0x3130 — 0x318f
CJLMisc 0x3190 — 0x319f EnclCJK 0x3200 — 0x32ff
CJKCompatibl 0x3300 - 0x33ff 汉语 0x3400 — 0xabff
韩语 0xac00 — 0xd7ff UTF16Lead 0xd800 — 0xdbff
UTF16Trail 0xdc00 — 0xdfff 私人使用 0xe000 — 0xf800
CJKCompIdeog 0xf900 — 0xfaff AlphaPres 0xfb00 — 0xfb4f
ArabicPresA 0xfb50 — 0xfdff CombHalfMark 0xfe20 — 0xfe2f
CJKCompForm 0xfe30 — 0xfe4f SmallFormVar 0xfe50 — 0xfe6f
ArabicPresB 0xfe70 — 0xfefe HalfFullForm 0xff00 — 0xffef
特价 0xfff0 — 0xfffd