% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*readme> xeCJK ===== `xeCJK` is a package written for XeLaTeX which allows users to typeset CJK scripts easily. - Different default fonts for CJK and other characters. - Spaces automatically ignored between CJK characters. - Special effects on full-width CJK punctuation. - Automatic adjustment of the space between CJK and other characters. Contributing ------------ This package is a part of the [ctex-kit](https://github.com/CTeX-org/ctex-kit) project. Issues and pull requests are welcome. Copyright and Licence --------------------- Copyright (C) 2007--2010 by Wenchang Sun Copyright (C) 2009--2022 by Leo Liu Copyright (C) 2012--2022 by Qing Lee ---------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainers of this work are Leo Liu and Qing Lee. This package consists of the files xeCJK.dtx, full-stop.map, fullwidth-stop.map, han-simp.map, han-trad.map, and the derived files xeCJK.pdf, xeCJK.sty, xeCJK.cfg, xeCJK.ins, xeCJKfntef.sty, xeCJK-listings.sty, xunicode-addon.sty, xunicode-extra.def, xeCJK-example-autofake.tex, xeCJK-example-fallback.tex, xeCJK-example-subCJKblock.tex, xeCJK-example-CJKecglue.tex, xeCJK-example-checksingle.tex, xeCJK-example-CJKfntef.tex, xeCJK-example-punctstyle.tex, xeCJK-example-verbatim.tex, xeCJK-example-CM.tex, xeCJK-example-listings.tex, xeCJK-example-mathblock.tex, xunicode-symbols.tex, xunicode-commands.tex, xunicode-combine-marks.tex, xunicode-symbols.pdf, full-stop.tec, fullwidth-stop.tec, han-simp.tec, han-trad.tec, and README.md (this file). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> \input ctxdocstrip % \preamble Copyright (C) 2007--2010 by Wenchang Sun Copyright (C) 2009--2022 by Leo Liu Copyright (C) 2012--2022 by Qing Lee ---------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainers of this work are Leo Liu and Qing Lee. ---------------------------------------------------------------------- \endpreamble \postamble This package consists of the files xeCJK.dtx, full-stop.map, fullwidth-stop.map, han-simp.map, han-trad.map, and the derived files xeCJK.pdf, xeCJK.sty, xeCJK.cfg, xeCJK.ins, xeCJKfntef.sty, xeCJK-listings.sty, xunicode-addon.sty, xunicode-extra.def, xeCJK-example-autofake.tex, xeCJK-example-fallback.tex, xeCJK-example-subCJKblock.tex, xeCJK-example-CJKecglue.tex, xeCJK-example-checksingle.tex, xeCJK-example-CJKfntef.tex, xeCJK-example-punctstyle.tex, xeCJK-example-verbatim.tex, xeCJK-example-CM.tex, xeCJK-example-listings.tex, xeCJK-example-mathblock.tex, xunicode-symbols.tex, xunicode-commands.tex, xunicode-combine-marks.tex, xunicode-symbols.pdf, full-stop.tec, fullwidth-stop.tec, han-simp.tec, han-trad.tec, and README.md. \endpostamble \generate { % %<*internal> \usedir{source/xelatex/xecjk} \file{xeCJK.ins} {\from{\jobname.dtx}{install}} % %<*install> \usedir{tex/xelatex/xecjk} \file{xeCJK.sty} {\from{\jobname.dtx}{package}} \file{xeCJKfntef.sty} {\from{\jobname.dtx}{fntef}} \file{xeCJK-listings.sty} {\from{\jobname.dtx}{listings}} \file{xunicode-addon.sty} {\from{\jobname.dtx}{xunicode}} \file{xunicode-extra.def} {\from{\jobname.dtx}{xunextra}} \usepreamble\emptypreamble \usepostamble\emptypostamble \usedir{tex/xelatex/xecjk/config} \file{xeCJK.cfg} {\from{\jobname.dtx}{config}} \usedir{doc/xelatex/xecjk/example} \file{xeCJK-example-autofake.tex} {\from{\jobname.dtx}{ex-autofake}} \file{xeCJK-example-fallback.tex} {\from{\jobname.dtx}{ex-fallback}} \file{xeCJK-example-subCJKblock.tex} {\from{\jobname.dtx}{ex-block}} \file{xeCJK-example-CJKecglue.tex} {\from{\jobname.dtx}{ex-ecglue}} \file{xeCJK-example-checksingle.tex} {\from{\jobname.dtx}{ex-single}} \file{xeCJK-example-CJKfntef.tex} {\from{\jobname.dtx}{ex-fntef}} \file{xeCJK-example-punctstyle.tex} {\from{\jobname.dtx}{ex-punctstyle}} \file{xeCJK-example-verbatim.tex} {\from{\jobname.dtx}{ex-verb}} \file{xeCJK-example-CM.tex} {\from{\jobname.dtx}{ex-cm}} \file{xeCJK-example-listings.tex} {\from{\jobname.dtx}{ex-listings}} \file{xeCJK-example-mathblock.tex} {\from{\jobname.dtx}{ex-mathblock}} \file{xunicode-symbols.tex} {\from{\jobname.dtx}{xunicode-symbols}} \nopreamble\nopostamble \usedir{doc/xelatex/xecjk} \file{README.md} {\from{\jobname.dtx}{readme}} } \endbatchfile % %<*internal> \fi % %<*package|config|fntef|listings|xunicode|xunextra> %\NeedsTeXFormat{LaTeX2e} %\RequirePackage{expl3} %<+!driver>\GetIdInfo$Id: xeCJK.dtx c4ccfae 2022-08-05 21:02:32 +0800 Qing Lee $ % {Typesetting CJK scripts with XeLaTeX} % {Configuration file for xeCJK package} % {xeCJK font effect} % {xeCJK patch file for listings} % {addon file for xunicode} % {extra definition for xunicode} %\ProvidesExplPackage{\ExplFileName} %\ProvidesExplFile{\ExplFileName.cfg} %\ProvidesExplPackage{xeCJKfntef} %\ProvidesExplPackage{xeCJK-listings} %\ProvidesExplPackage{xunicode-addon} %\ProvidesExplFile{xunicode-extra.def} % {\ExplFileDate}{3.9.1}{\ExplFileDescription} % %<*driver> \documentclass{ctxdoc} \usepackage{xeCJKfntef} \xeCJKDeclareSubCJKBlock{SP} { "2E3A , "301C , "30A0 , "FF65 } \xeCJKDeclareSubCJKBlock{Ext-B} { "20000 -> "2A6DF } \xeCJKDeclareSubCJKBlock{Hangul} { "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } \setCJKmainfont[SP, Language=Chinese Simplified]{Source Han Serif SC} \setCJKmainfont[Ext-B]{SimSun-ExtB} \setCJKmainfont[Hangul, Script=Hangul, Language=Korean]{Source Han Serif K} \newlist{psopt}{description}{3} \setlist[psopt]{% font=\mdseries\ttfamily, align=right, labelsep=.5em, leftmargin=4.5em, labelindent=0pt} \newcommand\PSKeyVal[2]{% \item[#1]\makebox[4em][l]{\meta{#2}}\ignorespaces} \newcommand\tokslink[1]{\hyperlink{#1}{\ding{51}}} \newcommand\ghissue[1]{% \href{https://github.com/CTeX-org/ctex-kit/issues/#1}{\##1}} \AtBeginDocument{\DeleteShortVerb{\"}} \ExplSyntaxOn \NewDocumentCommand \PrintPunctList { O{7} m m } { \par \begingroup \CJKfontspec[Language=Chinese ~ Simplified]{Source ~ Han ~ Serif ~ SC} \tl_clear:N \l_tmpa_tl \int_zero:N \l_tmpa_int \tl_set:Nx \l_tmpb_tl { \tl_to_str:n { c__xeCJK_#2_chars_clist } } \int_set:Nn \l_tmpb_int { \clist_count:c { \l_tmpb_tl } } \clist_map_inline:cn { \l_tmpb_tl } { \int_incr:N \l_tmpa_int \tl_put_right:Nx \l_tmpa_tl { \use_none:n ##1 & \tex_char:D ##1 \scan_stop: \int_compare:nNnF \l_tmpa_int = \l_tmpb_int { \int_compare:nNnTF { \int_mod:nn \l_tmpa_int {#1} } = \c_zero_int { \exp_not:N \\ \scan_stop: } { & } } } } \noindent\hfill\linespread{1}\selectfont \begin{tabular}{|*{#1}{>{\footnotesize\ttfamily U+}c|c|}} \tl_use:N \l_tmpa_tl \end{tabular}\hfill\null \endgroup \par } \ExplSyntaxOff \begin{document} \DocInput{\jobname.dtx} \IndexLayout \PrintChanges \PrintIndex \end{document} % % \fi % % \changes{v3.1.0}{2012/11/13}{放弃对 \tn{outer} 宏的特殊处理。} % \changes{v3.1.1}{2012/12/07}{不再依赖 \pkg{xpatch} 宏包。} % \changes{v3.2.2}{2013/06/01}{修正某些重音不能正确显示的问题。} % \changes{v3.2.3}{2013/06/07}{提供四个 TECkit 映射文件用于句号转换和简繁互换。} % \changes{v3.2.4}{2013/07/02}{遵循 \LaTeXiii{} 变量需要预先声明的原则。} % \changes{v3.2.6}{2013/07/29}{\texttt{case} 类函数的用法与 \LaTeXiii{} 同步。} % \changes{v3.3.2}{2015/05/15}{随 Unicode 7.0.0 更新简繁汉字映射。} % \changes{v3.3.3}{2015/09/25}{更新 \LaTeXiii{} 代码。} % \changes{v3.5.0}{2017/07/19}{常数 \cs{c_minus_one} 已过时。} % \changes{v3.5.0}{2017/07/22}{使用 \texttt{lazy} 函数对 Boolean 表达式 % 进行最小化运算(\LaTeXiii{} 2017/07/19)。} % \changes{v3.6.0}{2018/01/13}{同步 \LaTeXiii{} 2017/12/16。} % \changes{v3.6.1}{2018/02/27}{减少 \texttt{bool} 运算。} % \changes{v3.7.2}{2019/03/23}{同步 \LaTeXiii{} 2019/03/05。} % \changes{v3.8.0}{2020/02/09}{兼容 \LaTeXe\ 2020/02/02 对 \pkg{NFSS} 的修改。} % \changes{v3.8.0}{2020/02/09}{清理过时的兼容性补丁代码。} % \changes{v3.8.3}{2020/04/07}{删除 \texttt{\_nopar}。} % % \CheckSum{11032} % \GetFileId{xeCJK.sty} % % \title{\bfseries\pkg{xeCJK} 宏包} % \author{\href{http://www.ctex.org}{CTEX.ORG}} % \date{\filedate\qquad\fileversion\thanks{\ctexkitrev{\ExplFileVersion}.}} % \maketitle % % \tableofcontents % \vspace{\baselineskip} % % \begin{documentation} % % \section{简介} % % \pkg{xeCJK} 是一个 \XeLaTeX 宏包,用于排版中日韩(CJK)文字。主要功能: % \begin{enumerate} % \item 分别设置 CJK 和英文字体; % \item 自动忽略 CJK 文字间的空格而保留其他空格,允许在非标点汉字和英文 % 字母 (a -- z, A -- Z) 间断行; % \item 提供多种标点处理方式: 全角式、半角式、开明式、行末半角式和 CCT 式; % \item 自动调整中英文间空白。 % \end{enumerate} % % \pkg{xeCJK} 使用了 \XeTeX 的一些最新特性,需要 \XeTeX{} 0.9995.0 (2009/06/29) 以 % 后的版本。\pkg{xeCJK} 依赖 \LaTeXiii{} 项目的宏包套件 % \package{l3kernel} 和 \package{l3packages}。 % \pkg{xeCJK} 还需要通过 \package{fontspec} 宏包来调用系统字体。 % \pkg{xeCJK} 会自动根据需要载入这些宏包。 % % \pkg{xeCJK} 的原始作者是孙文昌,2009 年 5 月起宏包被收入 \ctexkit\ 项目进行 % 维护,目前主要维护者是刘海洋\footnote{\email{leoliu.pku@gmail.com}} 和 % 李清\footnote{\email{sobenlee@gmail.com}}。 % % \section{基本用法} % % 与其他 \LaTeX{} 宏包一样,引入 \pkg{xeCJK} 宏包只要在导言区使用 % \begin{frameverb} % \usepackage{xeCJK} % \end{frameverb} % 在引入 \pkg{xeCJK} 宏包之后,只要设置 CJK 文字的字体,就可以在文档中使用中日 % 韩文字了。 % % 可以在各种文档类中使用 \pkg{xeCJK} 宏包,最简单的示例是: % \begin{ctexexam} % \documentclass{article} % \usepackage{xeCJK} % \setCJKmainfont{SimSun} % % \begin{document} % 中文 \LaTeX 示例。 % \end{document} % \end{ctexexam} % 上述示例设置了中文字体 SimSun(宋体)。运行此示例要求系统安装了设置的字体, % 源文件用 UTF-8 编码保存,使用 \XeLaTeX{} 编译。 % % \pkg{xeCJK} 只提供了字体和标点控制等基本 CJK 语言支持。对于中文文档,可以使 % 用更为高层的 \package{ctex} 宏包或文档类,它将自动调用 \pkg{xeCJK} 并设置好中文 % 字体,同时提供了进一步的本地化支持。详细内容参看 \package{ctex} 宏包套件的说明。 % % \pkg{xeCJK} 提供了大量选项,可以在宏包调用时作为宏包选项或用 \tn{xeCJKsetup} % 命令进行设置,详见 \ref{subsec:opts}~节。除了 \tn{setCJKmainfont} 命令, % \pkg{xeCJK} 还提供了许多其他命令设置和选择中文字体,详见 % \ref{subsec:fontset}~节。其他更详细的功能也都将在下面详细说明。在本文档所在的 % 文件夹的 |example| 目录下面也有一些例子可以参考。 % % \section{用户手册} % % \subsection{宏包选项} % \label{subsec:opts} % % \pkg{xeCJK} 以 \meta{key}|=|\meta{var} 的形式提供宏包选项,你可以在调用宏包 % 的时候直接设置这些选项,也可以在调用宏包之后使用 \tn{xeCJKsetup} 来设置这些选 % 项。\pkg{xeCJK} 内部调用 \pkg{fontspec} 宏包,可以在调用 \pkg{xeCJK} 的时候, % 使用它的宏包选项。\pkg{xeCJK} 会将 \pkg{fontspec} 的选项传递给它。 % % \begin{function}{\xeCJKsetup} % \begin{syntax} % \tn{xeCJKsetup} \{\meta{key_1}=\meta{val_1}, \meta{key_2}=\meta{val_2}, ...\} % \end{syntax} % 其中 \meta{key_1}, \meta{key_2} 是设置选项,而 \meta{val_1}, \meta{val_2} 则是对应选项的 % 设置内容。多个选项可以在一个语句中完成设置。例如 % \begin{ctexexam} % \usepackage[PunctStyle=kaiming]{xeCJK} % \end{ctexexam} % 等价于 % \begin{ctexexam} % \usepackage{xeCJK} % ...... % \xeCJKsetup{PunctStyle=kaiming} % \end{ctexexam} % \end{function} % % 带有 \exptarget\expstar{} 或者 \rexptarget\rexpstar{} 标记的选项或命令 % 只能在导言区中使用,其中 \rexptarget\rexpstar{} 还表示这个选项或命令只 % 影响随后定义的 CJK 字体。其余不带特殊标记的选项或命令,如果没有特别说明, % 则可以在导言区或正文中使用。\textbf{粗体}表示 \pkg{xeCJK} 的默认设置。 % % \begin{function}[EXP,added=2012-11-22]{LocalConfig} % \begin{syntax} % LocalConfig = \Arg{\TTF|name} % \end{syntax} % 是否使用本地配置文件 \texttt{xeCJK-\meta{name}.cfg}。\meta{name} 可以是不包含 % 空格的任意使文件名合法的字符串。如果设置为 |true|,则使用的是 \texttt{xeCJK.cfg}; % 设置为 |false| 则不载入配置文件。可以把将要在下文介绍到的对 \pkg{xeCJK} 的一些 % 设置(例如设置常用 CJK 字体、修改字符范围和定义新的标点输出格式等)保存到文件 % \texttt{xeCJK-\meta{name}.cfg}。然后把这个文件放在本地的 |TDS| 目录下的适当 % 位置。使用 \TeX~Live 的用户,可以新建下列目录,然后再把 % \texttt{xeCJK-\meta{name}.cfg} 放在里面: % \begin{frameverb} % texlive/texmf-local/tex/xelatex/xecjk % \end{frameverb} % 最后还需要在命令行下执行 |mktexlsr|,刷新文件名数据库以便 \TeX 系统能够找到它。 % \end{function} % % 请注意,\pkg{xeCJK} 宏包中只有上述 |LocalConfig| 选项需要在调用 \pkg{xeCJK} 时 % 设置,而不能通过 \tn{xeCJKsetup} 来设置。 % % \begin{function}{xeCJKactive} % \begin{syntax} % xeCJKactive = \meta{\TTF} % \end{syntax} % 打开/关闭对中文的特殊处理。事实上,这个选项会打开/关闭 \XeTeX 的整个字符类机制,依赖 % 这个机制的宏包都会受到影响。 % \end{function} % % \begin{function}{CJKspace} % \begin{syntax} % CJKspace = \meta{\TFF} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 会忽略 CJK 文字之间的空格,使用这一选项来保留它们之间的空格。 % \end{function} % % \begin{function}[EXP,updated=2016-05-04]{CJKmath} % \begin{syntax} % CJKmath = \meta{\TFF} % \end{syntax} % 是否支持在数学环境中直接输入 CJK 字符。使用这个选项后,可以直接在数学环境中 % 输出 CJK 字符。\pkg{url} 宏包将一个 URL 放在一个特殊的数学环境中排版,所以如果在 % \tn{path} 等命令的路径参数中含有汉字,则需要启用这个选项,路径中的汉字才能显示。 % \end{function} % % \begin{function}{CJKglue} % \begin{syntax} % CJKglue = \{\tn{hskip} 0pt plus 0.08\tn{baselineskip}\} % \end{syntax} % 设置 CJK 文字之间插入的 |glue|,上边是 \pkg{xeCJK} 的默认值。一般来说,除非有 % 特殊需要(例如,改变文字间距等),否则不需要设置这个选项,使用默认值即可。如果要设置 % 这个选项,为了行末的对齐,设置的 |glue| 最好有一定的弹性。 % \end{function} % % \begin{function}{CJKecglue} % \begin{syntax} % CJKecglue = \Arg{glue} % \end{syntax} % 设置 CJK 文字与西文、CJK 文字与行内数学公式之间的间距,默认值是一个空格。使用这个 % 选项设置的 \meta{glue} 最好也要用一定的弹性。请注意,这里设置的 \meta{glue} 只影响 % \pkg{xeCJK} 根据需要自动添加的空白,源文件中直接输入的 CJK 文字与西文之间的空格不 % 受影响(直接输出)。有时候 \pkg{xeCJK} 可能不能正确地调整间距,需要手动加空格。 % \end{function} % % \begin{function}{xCJKecglue} % \begin{syntax} % xCJKecglue = \Arg{\TFF|glue} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 不对源文件中直接输入的 CJK 文字与西文之间的空格进行调整,如 % 果需要调整,请使用这个选项。如果使用这个选项,将使用 |CJKecglue| 替换源文件中直接输 % 入的 CJK 文字与西文之间的空格。 % \end{function} % % \begin{function}[updated=2013-06-26]{CheckSingle} % \begin{syntax} % CheckSingle = \meta{\TFF} % \end{syntax} % 是否避免单个 CJK 文字单独占一个段落的最后一行。需要说明的是,这个选项只有在 % 段末的最后一个字是 CJK 文字或者标点符号,并且倒数第二和第三个字都是文字才能 % 正确处理处理孤字的问题。如果这倒数三个字有作为控制序列的参数的情况,那么一般 % 来说也不能正确处理。 % \end{function} % % \begin{function}[added=2015-04-08]{WidowPenalty} % \begin{syntax} % WidowPenalty = \Arg{penalty|(10000)} % \end{syntax} % 使用 \texttt{CheckSingle} 选项后,设置段末三个汉字之间的 penalty。 % 初始值为 \num{10000},即禁止在它们之间折行。 % \end{function} % % \begin{function}[added=2012-12-06]{PlainEquation} % \begin{syntax} % PlainEquation = \meta{\TFF} % \end{syntax} % 如果使用了 |$$...$$| 的形式来输入行间数学公式,就需要启用本选项,以便 % |CheckSingle| 选项能够正确识别。推荐使用 |\[...\]| 的形式来输入行间数学公式。 % \end{function} % % \begin{function}[added=2012-12-04]{NewLineCS,NewLineCS+,NewLineCS-} % \begin{syntax} % NewLineCS = \{ \tn{par} \tn{[} \} % \end{syntax} % 设置造成断行的控制序列,以便 |CheckSingle| 选项能够正确识别。 % 以上是 \pkg{xeCJK} 的初始设置。 % \end{function} % % \begin{function}[added=2012-12-04]{EnvCS,EnvCS+,EnvCS-} % \begin{syntax} % EnvCS = \{ \tn{begin} \tn{end} \} % \end{syntax} % 设置 \LaTeX 环境开始和结束的控制序列,以便 |CheckSingle| 选项能够正确识别。 % 以上是 \pkg{xeCJK} 的初始设置。 % \end{function} % % \begin{function}[updated=2012-12-06]{InlineEnv,InlineEnv+,InlineEnv-} % \begin{syntax} % InlineEnv = \{\meta{env_1}, \meta{env_2}, \meta{env_3}, ...\} % \end{syntax} % 在使用 |CheckSingle| 选项的时候,\pkg{xeCJK} 会将 CJK 文字后接着的 \LaTeX 环境的 % 开始 |\begin{...}| 和结束 |\end{...}| 视为断行的地方,如果有某些特殊 % 的 \LaTeX 环境没有造成断行,可以使用这个选项来声明它,以便 |CheckSingle| 能正确识别。 % \end{function} % % \begin{function}{AutoFallBack} % \begin{syntax} % AutoFallBack = \meta{\TFF} % \end{syntax} % 当文档中有个别生僻字时,可以使用这个选项,自动使用预先设置好的后备字体来输出这些生僻 % 字。后备字体的设置方法将在 \ref{subsec:fontset} 节中介绍。 % \end{function} % % \begin{function}[rEXP]{AutoFakeBold} % \begin{syntax} % AutoFakeBold = \Arg{\TFF|数字} % \end{syntax} % 全局设定当没有声明对应的粗体时,是否使用^^A % \textbf{\CJKfontspec[AutoFakeBold]{FandolSong-Regular.otf}伪粗体}; % 当输入的是数字时,将使用伪粗体,并将使用输入的数字作为伪粗体的默认粗细程度。 % \end{function} % % \begin{function}[rEXP]{AutoFakeSlant} % \begin{syntax} % AutoFakeSlant = \Arg{\TFF|数字} % \end{syntax} % 全局设定当没有声明对应的斜体时,是否使用^^A % \textit{\CJKfontspec[AutoFakeSlant]{FandolSong-Regular.otf}伪斜体}; % 当输入的是数字时,将使用伪斜体,并将使用输入的数字作为伪斜体的默认倾斜程度。 % 倾斜程度的取值范围是 $[-0.999, 0.999]$。 % \end{function} % % \begin{function}[rEXP]{EmboldenFactor} % \begin{syntax} % EmboldenFactor = \Arg{数字|(4)} % \end{syntax} % 设置伪粗体的默认粗细程度。 % \end{function} % % \begin{function}[rEXP]{SlantFactor} % \begin{syntax} % SlantFactor = \Arg{数字|(0.167)} % \end{syntax} % 设置伪斜体的倾斜程度,范围是 $[-0.999, 0.999]$。 % \end{function} % % \begin{function}[updated=2012-11-10]{PunctStyle} % \begin{syntax} % PunctStyle = \Arg{(quanjiao)|banjiao|kaiming|hangmobanjiao|CCT|plain|...} % \end{syntax} % 设置标点处理格式。\pkg{xeCJK} 中预先定义好的格式为 % \begin{optdesc} % \item[quanjiao] 全角式:所有标点占一个汉字宽度,相邻两个标点占 1.5 汉字宽度; % \item[banjiao] 半角式:所有标点占半个汉字宽度; % \item[kaiming] 开明式:句末点号用全角,其他半角; % \item[hangmobanjiao] 行末半角式:所有标点占一个汉字宽度,行首行末对齐; % \item[CCT] CCT 格式:所有标点符号的宽度略小于一个汉字宽度; % \item[plain] 原样(不调整标点间距)。 % \end{optdesc} % 可以使用 \ref{subsec:punctstyle} 中介绍的 \tn{xeCJKDeclarePunctStyle} 定义新的标点 % 格式。 % \end{function} % % \begin{function}[added=2018-01-24]{PunctFamily} % \begin{syntax} % PunctFamily = \Arg{(false)|family} % \end{syntax} % 默认情况下,CJK 标点符号的字体与 CJK 正文一致,\opt{PunctFamily} 用于单独对标点符号设置字体。 % \meta{family} 需要使用随后说明的 \tn{setCJKfamilyfont} 或 \tn{newCJKfontfamily} % 预先定义。\opt{false} 表示取消本选项的作用,让标点符号字体与正文一致。 % \end{function} % % \begin{function}[EXP]{KaiMingPunct,KaiMingPunct+,KaiMingPunct-} % \begin{syntax} % KaiMingPunct = \Arg{( . 。? !)} % \end{syntax} % 设置开明(|kaiming|)标点处理格式时的句末点号,|KaiMingPunct| 后带的 |+| 与 |-| % 分别表示从已有的开明句末点号中增加或减少标点。 % \end{function} % % \begin{function}[EXP]{LongPunct,LongPunct+,LongPunct-} % \begin{syntax} % LongPunct = \Arg{( — ⸺ ‥ … )} % \end{syntax} % 设置长标点,例如破折号“——”与省略号“……”,允许在长标点前后 % 断行,但是禁止在它们之间断行。 % \end{function} % % \begin{function}[EXP]{MiddlePunct,MiddlePunct+,MiddlePunct-} % \begin{syntax} % MiddlePunct = \Arg{( – — ⸺ · · ・ 〜゠~)} % \end{syntax} % 设置居中显示的标点,例如间隔号“\textbf{·}”。对于在 CJK 文字之间的居中标点, % \pkg{xeCJK} 会根据不同的标点处理格式,调整居中标点与前后文字之间的空白,保证 % 其确实居中。对于行末出现的居中标点,允许在其后面断行,但禁止在它前面断行。 % \end{function} % % \begin{function}[EXP]{PunctWidth} % \begin{syntax} % PunctWidth = \Arg{length} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 会根据所选择的标点处理格式自动计算标点所占的宽度,如果对缺 % 省设置不满意,可以通过这一选项来改变它。为了使得标点所占的宽度能够适应字体大小的变化, % 这里设置的 |length| 的单位最好用 |em| 等相对距离单位,而不建议使用诸如 |pt| 之类的 % 绝对距离单位。这里的设置可用于除了 |plain| 以外的所有标点处理格式。同时,这里的 % 设置对所有的 CJK 标点都生效,如果只要设置部分标点,请使用 \ref{subsec:punct}~节的 % \tn{xeCJKsetwidth}。 % \end{function} % % \begin{function}[EXP,added=2013-08-22]{PunctBoundWidth} % \begin{syntax} % PunctBoundWidth = \Arg{length} % \end{syntax} % 与以上选项类似,但设置的是标点符号出现在行首/尾时的宽度。 % \end{function} % % \begin{function}{AllowBreakBetweenPuncts} % \begin{syntax} % AllowBreakBetweenPuncts = \meta{\TFF} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 禁止在相邻 CJK 右标点和 CJK 左标点之间换行,可以使用 % 这一选项改变这一设置。 % \end{function} % % \begin{function}[updated=2016-05-13]{RubberPunctSkip} % \begin{syntax} % RubberPunctSkip = \meta{\TTF|plus|minus} % \end{syntax} % 缺省状态下,标点符号前/后的间距有一定的弹性。可以伸长到原始边界宽度,可以收缩到 % 标点另一侧的边界宽度。将本选项设置为 \texttt{plus},将只允许伸长;设置为 % \texttt{minus} 只允许收缩。设置为 \texttt{false} 将禁用这一特性, % 从而使得前/后的间距为固定值。 % \end{function} % % \begin{function}[added=2012-12-02]{CheckFullRight} % \begin{syntax} % CheckFullRight = \meta{\TFF} % \end{syntax} % 某些控制序列要求不能在它的前面断行。但是在缺省状态下,单个全角右标点的后面总是 % 可以断行的。因此当这些控制序列出现在全角右标点后面时,可能会出现意料之外的断行。 % 此时可以使用这个选项来避免这个情况。 % \end{function} % % \begin{function}[added=2012-12-02]{NoBreakCS,NoBreakCS+,NoBreakCS-} % \begin{syntax} % NoBreakCS = \{ \tn{footnote} \tn{footnotemark} \tn{nobreak} \} % \end{syntax} % 设置不能在全角右标点后断行的控制序列。以上是 \pkg{xeCJK} 的默认设置。如果这些 % 控制序列在文档中只出现少量几次,也可以不必使用 |CheckFullRight| 选项,而是手工 % 在这些控制序列前面加上 \ref{subsec:others}~节介绍的 \tn{xeCJKnobreak}。 % \end{function} % % \begin{function}[updated=2013-11-16]{Verb} % \begin{syntax} % Verb = \meta{\TF|(env)|env+} % \end{syntax} % \texttt{true} 表示在 \tn{verb} 命令或 \texttt{verbatim} 环境里不自动调整中英文 % 之间的间距。\texttt{env} 选项在 \texttt{verbatim} 环境里自动计算中西文间距和中文 % 之间的间距,以便于保持代码的对齐;\texttt{env} 选项不调整 \tn{verb} 里的间距,^^A % \texttt{env+} 选项还将正文里设置的间距应用到 \tn{verb} 里。^^A % 这个选项对使用到 \tn{verbatim@font} 命令的情形均有效,更一般的情况可以使用 % \ref{subsec:others}~节介绍的 \tn{xeCJKVerbAddon}。\texttt{false} 表示不作任何 % 处理。以上选项的值除 \texttt{false} 外,都禁止在汉字之间和汉字与西文之间自动换行。 % \end{function} % % \begin{function}[rEXP,added=2014-03-01]{LoadFandol} % \begin{syntax} % LoadFandol = \meta{\TTF} % \end{syntax} % 当没有在导言区设置 CJK 字体时,是否使用 Fandol 字体。如果启用这个选项,需要 % 安装 \package{Fandol} 字体系列。 % \end{function} % % \subsection{字体设置与选择} % \label{subsec:fontset} % % \begin{function}[EXP,updated=2016-11-18]{\setCJKmainfont} % \begin{syntax} % \tn{setCJKmainfont} \Arg{font name}\oarg{font features} 或\\ % \tn{setCJKmainfont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置正文罗马族的 CJK 字体,影响 \tn{rmfamily} 和 \tn{textrm} 的字体。后面两个 % 参数继承自 \pkg{fontspec} 宏包, \meta{font features} 表示字体属性选项, % \meta{font name} 是字体名。字体名可以是字体族名,也可以是字体的文件名,查 % 找字体名见 \ref{subsubsec:fontsearch}~节;可用的字体属性选项参见 % \pkg{fontspec} 宏包的文档。需要说明的是 \pkg{xeCJK} 修改了 |AutoFakeBold| % 和 |AutoFakeSlant| 选项,以便配合全局伪粗体和伪斜体的设定。 % % 出于兼容性考虑,字体属性可选项可以放在字体名称前面,也可以放在后面。 % 如果可选项放在后面,字体名称与可选项之间不要有空格或者换行。 % \end{function} % % \begin{function}[label = ]{AutoFakeBold,AutoFakeSlant} % \begin{syntax} % AutoFakeBold = \Arg{\TF|数字} % AutoFakeSlant = \Arg{\TF|数字} % \end{syntax} % 局部设置当前字体族的伪粗和伪斜属性。如果没有在局部给出这些选项,将使用全局设定。 % \end{function} % % \begin{function}[added=2013-06-07]{Mapping} % \begin{syntax} % Mapping = \Arg{fullwidth-stop|full-stop|han-trad|han-simp|...} % \end{syntax} % \pkg{xeCJK} 提供了以上四个 \href{http://scripts.sil.org/teckit}{TECKit} 映射 % 文件,可以在设置字体的时候通过 \texttt{Mapping} 选项来使用它们。其中 % \texttt{fullwidth-stop} 用于将正常句号“。”转换成全角实心句号“.”, % \texttt{full-stop} 的作用相反。\texttt{han-trad} 用于将简体中文转换成繁体中文, % \texttt{han-simp} 的作用相反。需要注意的是,简繁互换都是简单机械的字字对译, % 不能做到完全准确,使用时要小心。例如简体的“发挥”和“头发”被转换成繁体的 % “發揮”和“頭發”,显然后者应作“頭髮”。也可以根据实际需要,制作新的映射文件, % 请参考 TECKit 的文档。 % \end{function} % % \begin{function}[EXP,updated=2016-11-18]{\setCJKsansfont} % \begin{syntax} % \tn{setCJKsansfont} \Arg{font name}\oarg{font features} 或\\ % \tn{setCJKsansfont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置正文无衬线族的 CJK 字体,影响 \tn{sffamily} 和 \tn{textsf} 的字体。 % \end{function} % % \begin{function}[EXP,updated=2016-11-18]{\setCJKmonofont} % \begin{syntax} % \tn{setCJKmonofont} \Arg{font name}\oarg{font features} 或\\ % \tn{setCJKmonofont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置正文等宽族的 CJK 字体,影响 \tn{ttfamily} 和 \tn{texttt} 的字体。 % \end{function} % % \begin{function}[EXP,updated=2016-11-18]{\setCJKfamilyfont} % \begin{syntax} % \tn{setCJKfamilyfont} \Arg{family} \Arg{font name}\oarg{font features} 或\\ % \tn{setCJKfamilyfont} \Arg{family} \oarg{font features} \Arg{font name} % \end{syntax} % 声明新的 CJK 字体族 \meta{family} 并指定字体。 % \end{function} % % \begin{function}[updated=2012-10-27]{\CJKfamily} % \begin{syntax} % \tn{CJKfamily} \Arg{family} % \tn{CJKfamily} + \Arg{family} % \tn{CJKfamily} - \Arg{family} % \end{syntax} % 用于在文档中切换 |CJK| 字体族,\meta{family} 必须预先声明。\tn{CJKfamily} 仅对 % CJK 字符类有效,\tn{CJKfamily}|+| 对所有字符类均有效,\tn{CJKfamily}|-| 对非 CJK 字 % 符类有效。当 \tn{CJKfamily}|+| 和 \tn{CJKfamily}|-| 的参数为空时,则使用当前的 |CJK| 字体族。 % \end{function} % % \begin{function}[EXP,updated=2016-11-18]{\newCJKfontfamily} % \begin{syntax} % \tn{newCJKfontfamily} \oarg{family} \cs{\meta{font-switch}} \Arg{font name}\oarg{font features} 或\\ % \tn{newCJKfontfamily} \oarg{family} \cs{\meta{font-switch}} \oarg{font features} \Arg{font name} % \end{syntax} % 声明新的 CJK 字体族 \meta{family} 并指定字体,并定义 \cs{\meta{font-switch}},在 % 文档中可以使用它来切换 CJK 字体族。可以不必指定 \meta{family},这时候 \meta{family} % 将等于 \meta{font-switch}。 % \end{function} % % 事实上,\tn{newCJKfontfamily} 是 \tn{setCJKfamilyfont} 和 % \tn{CJKfamily} 的合并。例如 % \begin{ctexexam} % \newCJKfontfamily[song]\songti{SimSun} % \end{ctexexam} % 等价于 % \begin{ctexexam} % \setCJKfamilyfont{song}{SimSun} % \newcommand*{\songti}{\CJKfamily{song}} % \end{ctexexam} % % \begin{function}[updated=2016-11-18]{\CJKfontspec} % \begin{syntax} % \tn{CJKfontspec} \Arg{font name}\oarg{font features} 或\\ % \tn{CJKfontspec} \oarg{font features} \Arg{font name} % \end{syntax} % 在文档中定义新的 CJK 字体族,并马上使用它。 % \end{function} % % \begin{function}[rEXP]{\defaultCJKfontfeatures} % \begin{syntax} % \tn{defaultCJKfontfeatures} \Arg{font features} % \end{syntax} % 全局设置 CJK 字体族的默认选项。例如,使用 % \begin{ctexexam} % \defaultCJKfontfeatures{Scale=0.962216} % \end{ctexexam} % 可以将全部 CJK 字体缩小为 |0.962216|。\pkg{xeCJK} 宏包的初始化设置是 % \begin{frameverb} % \defaultCJKfontfeatures{Script=CJK} % \end{frameverb} % \end{function} % % \begin{function}[updated=2013-06-30]{\addCJKfontfeatures} % \begin{syntax} % \tn{addCJKfontfeatures} \Arg{font features} % \tn{addCJKfontfeatures} * \Arg{font features} % \tn{addCJKfontfeatures} \oarg{block_1, block_2, ...} \Arg{font features} % \tn{addCJKfontfeatures} * \oarg{block_1, block_2, ...} \Arg{font features} % \end{syntax} % 临时增加当前使用的 CJK 字体的选项。第一条命令,仅对当前 CJK 主分区字体有效; % 第二条对主分区和其他分区的字体都有效;第三条仅对可选参数中指定的分区有效; % 第四条对主分区和可选参数中指定的分区有效。例如,使用 % \begin{ctexexam} % \addCJKfontfeatures{Scale=1.1} % \end{ctexexam} % 可以将文档中当前使用的 CJK 主分区字体放大为 |1.1|。 % \end{function} % % \begin{function}{\CJKrmdefault} % 保存 \tn{textrm} 和 \tn{rmfamily} 所使用的 CJK 字体族,默认值是 |rm|。 % \end{function} % % \begin{function}{\CJKsfdefault} % 保存 \tn{textsf} 和 \tn{sffamily} 所使用的 CJK 字体族,默认值是 |sf|。 % \end{function} % % \begin{function}{\CJKttdefault} % 保存 \tn{texttt} 和 \tn{ttfamily} 所使用的 CJK 字体族,默认值是 |tt|。 % \end{function} % % \begin{function}[updated=2013-01-01]{\CJKfamilydefault} % 保存 \tn{textnormal} 和 \tn{normalfont} 所使用的 CJK 字体族。类似西文字体的 \tn{familydefault}。 % 初始值是 \tn{CJKrmdefault}。如果没有在导言区中修改它,\pkg{xeCJK} 会在导言区 % 结束的时候根据西文字体的情况自动更新 \tn{CJKfamilydefault}。因此,在导言区里使用 % \begin{frameverb} % \renewcommand\familydefault{\sfdefault} % \end{frameverb} % 就可以将全文的 CJK 和西文默认字体都改为无衬线字体族。 % \end{function} % % \begin{function}[EXP,updated=2016-11-18]{\setCJKmathfont} % \begin{syntax} % \tn{setCJKmathfont} \Arg{font name}\oarg{font features} 或\\ % \tn{setCJKmathfont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置数学公式中的 CJK 字体族。如果使用了 |CJKmath| 选项,但是没有使用 % \tn{setCJKmathfont} 设置数学公式中的 CJK 字体,那么将使用 \tn{CJKfamilydefault} % 作为数学公式中的 CJK 字体。 % \end{function} % % \begin{function}[EXP, label=, updated=2016-11-18]{\setCJKfallbackfamilyfont} % \begin{syntax} % \tn{setCJKfallbackfamilyfont} \Arg{family} \Arg{font name}\oarg{font features} 或\\ % \tn{setCJKfallbackfamilyfont} \Arg{family} \oarg{font features} \Arg{font name} % \end{syntax} % 设置 CJK 字体族 \meta{family} 的备用字体。例如,使用 % \begin{ctexexam} % \setCJKmainfont{SimSun} % \setCJKfallbackfamilyfont{\CJKrmdefault}{SimSun-ExtB} % \end{ctexexam} % 可以将 |SimSun-ExtB| 作为 |SimSun| 的备用字体。 % \end{function} % % \begin{function}{FallBack} % \begin{syntax} % FallBack = \{\oarg{font features}\Arg{font name}\} % \end{syntax} % \pkg{xeCJK} 在 \meta{font features} 里增加了 |FallBack| 这个选项。用来在声明主 % 字体的时候,同时设置备用字体。例如,上面的例子等价于: % \begin{ctexexam} % \setCJKmainfont[FallBack=SimSun-ExtB]{SimSun} % \end{ctexexam} % 如果 |FallBack| 的值为空,将设置的是备用字体。例如, % \begin{ctexexam} % \setCJKmainfont[FallBack,AutoFakeBold,Scale=.97]{SimSun-ExtB} % \end{ctexexam} % 等价于 % \begin{ctexexam} % \setCJKfallbackfamilyfont{\CJKrmdefault}[AutoFakeBold,Scale=.97]{SimSun-ExtB} % \end{ctexexam} % \end{function} % % \begin{function}[EXP,updated=2013-06-30]{\setCJKfallbackfamilyfont} % \begin{syntax} % \tn{setCJKfallbackfamilyfont} \Arg{family} % \ \{ % \ \{\oarg{font features_1} \Arg{font name_1}\} , % \ \{\oarg{font features_2} \Arg{font name_2}\} , % \ ...... % \ \}\oarg{common font features} 或\\ % \tn{setCJKfallbackfamilyfont} \Arg{family} \oarg{common font features} % \ \{ % \ \{\oarg{font features_1} \Arg{font name_1}\} , % \ \{\oarg{font features_2} \Arg{font name_2}\} , % \ ...... % \ \} % \end{syntax} % \tn{setCJKfallbackfamilyfont} 还可以用于设置多层的备用字体。例如,使用 % \begin{ctexexam} % \setCJKmainfont[AutoFakeBold,AutoFakeSlant]{KaiTi_GB2312} % \setCJKfallbackfamilyfont{\CJKrmdefault}[AutoFakeSlant] % { [BoldFont=SimHei]{SimSun} , % [AutoFakeBold] {SimSun-ExtB} } % \end{ctexexam} % 之后,就设置了 |SimSun| 是 |KaiTi_GB2312| 的备用字体,而 |SimSun-ExtB| 是 % |SimSun| 的备用字体。若当前字体族缺字,并没有备用字体,则尝试使用 % \tn{CJKfamilydefault} 的备用字体。 % \end{function} % % \subsubsection{\XeTeX 的字体名查找} % \label{subsubsec:fontsearch} % % 由于在 \pkg{fontspec} 宏包文档中缺少关于如何查看 \XeTeX{} 可用字体名的说明, % 这里略作说明。 % % \XeTeX{} 通常使用 fontconfig 库查找和调用字体,因此,可以用 |fc-list| 命令显 % 示可用的字体。在命令行(Windows 的“命令提示符”,Linux 的 Console)下运行以 % 下命令: % \begin{frameverb} % fc-list > fontlist.txt % \end{frameverb} % 可以将系统中所有安装的字体列表存入 \file{fontlist.txt} 文件中(可能很长)。 % % |fc-list| 命令列出的信息很多,而且在安装字体较多的 Windows 系统上的输出将非 % 常庞大,如其中可能包含: % \begin{frameverb} % Times New Roman:style=cursiva,kurzíva,kursiv,Πλάγια,Italic, % Kursivoitu,Italique,Dőlt,Corsivo,Cursief,kursywa,Itálico,Курсив, % İtalik,Poševno,nghiêng,Etzana % Times New Roman:style=Negreta cursiva,tučné kurzíva,fed kursiv, % Fett Kursiv,Έντονα Πλάγια,Bold Italic,Negrita Cursiva, % Lihavoitu Kursivoi,Gras Italique,Félkövér dőlt,Grassetto Corsivo, % Vet Cursief,Halvfet Kursiv,Pogrubiona kursywa,Negrito Itálico, % Полужирный Курсив,Tučná kurzíva,Fet Kursiv,Kalın İtalik, % Krepko poševno,nghiêng đậm,Lodi etzana % Times New Roman:style=Negreta,tučné,fed,Fett,Έντονα,Bold,Negrita, % Lihavoitu,Gras,Félkövér,Grassetto,Vet,Halvfet,Pogrubiona,Negrito, % Полужирный,Fet,Kalın,Krepko,đậm,Lodia % Times New Roman:style=Normal,obyčejné,Standard,Κανονικά,Regular, % Normaali,Normál,Normale,Standaard,Normalny,Обычный,Normálne,Navadno, % thường,Arrunta % 宋体,SimSun:style=Regular % 黑体,SimHei:style=Normal,obyčejné,Standard,Κανονικά,Regular,Normaali, % Normál,Normale,Standaard,Normalny,Обычный,Normálne,Navadno,Arrunta % \end{frameverb} % 在 \pkg{fontspec} 或 \pkg{xeCJK} 中使用的字体族名是上面列表中冒号前的部分。 % 例如可以使用 % \begin{ctexexam} % \setmainfont{Times New Roman} % \setCJKmainfont{SimSun} % 或者 \setCJKmainfont{宋体} % \end{ctexexam} % 来设置字体。 % % 为了方便起见,|fc-list| 命令也可以加上各种选项控制输出格式,例如如果只要列出 % 所有的中文字体的字体族名,可以用命令: % \begin{frameverb} % fc-list -f "%{family}\n" :lang=zh > zhfont.txt % \end{frameverb} % 这样就把字体列表保存在文件 \file{zhfont.txt} 中\footnote{由于汉字编码原因, % Windows 下总需要把字体列表输出的文件中防止乱码。}。这样列出的字体列表就比较 % 简明易用,如 Windows 下预装的中文字体: % \begin{frameverb} % Arial Unicode MS % FangSong,仿宋 % KaiTi,楷体 % Microsoft YaHei,微软雅黑 % MingLiU,細明體 % NSimSun,新宋体 % PMingLiU,新細明體 % SimHei,黑体 % SimSun,宋体 % \end{frameverb} % 要列出日文和韩文的字体,可以把 |:lang=zh| 选项中的 |zh| 改成 |ja| 或 |ko|。 % % \pkg{fontspec} 和 \pkg{xeCJK} 也可以使用字体的文件名访问字体。例如 Windows % 下的宋体也可以使用命令: % \begin{frameverb} % \setCJKmainfont{simsun.ttc} % \end{frameverb} % 来设置。设置字体文件名的相关选项和语法在 \pkg{fontspec} 宏包手册中叙述甚详, % 这里不再赘述。有个别字体名不规范的中文字体,\pkg{xeCJK} 宏包可能无法正确地通 % 过字体名访问,那么也可以使用这种方式设置。 % % \subsection{CJK 分区字体设置} % \label{subsec:block} % % 众所周知,CJK 文字数量极其庞大,单一的字体不可能涵盖所有的 CJK 文字。\pkg{xeCJK} 可 % 以在同一 CJK 字体族下,自动使用不同的字体输出 CJK 字符范围内不同区块里的文字。首先要 % 声明 CJK 子分区。 % % \begin{function}[EXP]{\xeCJKDeclareSubCJKBlock} % \begin{syntax} % \tn{xeCJKDeclareSubCJKBlock} \Arg{block} \Arg{block range} % \tn{xeCJKDeclareSubCJKBlock} * \Arg{block} \Arg{block range} % \end{syntax} % 其中 \meta{block range} 是逗号列表,可以是 CJK 字符的 |Unicode| 范围,也可以是单个字符 % 的 |Unicode|。例如 % \end{function} % \begin{ctexexam} % { `中 -> `文 , "3400 -> "4DBF , "5000 -> "7000 , `汉 , `字 , "3500 } % \end{ctexexam} % 的形式。需要注意的是,这里设置的 \meta{block range} 除非确实需要(例如某些特殊字体使用 % 了 |Unicode| 中的私人使用区的情况),否则不要超出源代码中预设的 % \hyperlink{CJKcharclass}{CJK 文字范围}。使用 % \begin{ctexexam} % \xeCJKDeclareSubCJKBlock{SPUA}{ "E400 -> "E4DA , "E500 -> "E5E8 , "E600 -> "E6CE } % \xeCJKDeclareSubCJKBlock{Ext-B}{ "20000 -> "2A6DF } % \end{ctexexam} % 就声明了 |SPUA| 和 |Ext-B| 这两个个子分区。同时在 \ref{subsec:fontset} 节介绍的 % CJK 字体设置命令的 \meta{font features} 里新建了 |SPUA| 和 |Ext-B| 这两个选项。 % 新建的这两个选项的使用方法跟 \ref{subsec:fontset} 介绍的 |FallBack| 类似。可以 % 通过它们来设置字体。 % % 例如,可以使用 % \begin{ctexexam} % \setCJKmainfont[SPUA=SunmanPUA,Ext-B=SimSun-ExtB]{SimSun} % \end{ctexexam} % 设置文档的主字体是 |SimSun|,|SPUA| 分区的字体是 |SunmanPUA|,而 |Ext-B| 分区 % 的字体是 |SimSun-ExtB|。 % % \tn{xeCJKDeclareSubCJKBlock} 应该在声明所有的 CJK 字体族之前使用。如果有某个 CJK 字 % 体族没有设置 \meta{block} 选项,将使用 \tn{CJKfamilydefault} 的 \meta{block} 选项 % 作为该 CJK 字体族的 \meta{block} 选项。如果希望在使用某 CJK 字体族时,不在 CJK 主 % 分区与 \meta{block} 之间切换字体,可以使用 \meta{block}|=*| 选项。带星号的命令除了 % 设置 CJK 子分区以外,还重置标点符号所属的字符类。 % % \begin{function}{\xeCJKCancelSubCJKBlock} % \begin{syntax} % \tn{xeCJKCancelSubCJKBlock} \Arg{block_1, block_2, ...} % \tn{xeCJKCancelSubCJKBlock} \Arg{block_1, block_2, ...} % \end{syntax} % 在文档中取消对 |CJK| 分区的声明。带星号的命令还重置标点符号所属的字符类。 % \end{function} % % \begin{function}{\xeCJKRestoreSubCJKBlock} % \begin{syntax} % \tn{xeCJKRestoreSubCJKBlock} \Arg{block_1, block_2, ...} % \tn{xeCJKRestoreSubCJKBlock} * \Arg{block_1, block_2, ...} % \end{syntax} % 在文档中恢复对 |CJK| 分区的声明。带星号的命令还重置标点符号所属的字符类。 % \end{function} % % \subsection{设置 CJK 字符范围} % % \begin{function}[EXP]{\xeCJKDeclareCharClass} % \begin{syntax} % \tn{xeCJKDeclareCharClass} \Arg{class} \Arg{class range} % \tn{xeCJKDeclareCharClass} * \Arg{class} \Arg{class range} % \end{syntax} % \meta{class range} 的格式和 \ref{subsec:block} 节的 \meta{block range} 相同。 % \meta{class} 的有效值见源代码(第 \ref{sec:xeCJK-class-set} 节)。\pkg{xeCJK} 已 % 经支持 |Unicode| 中所有 CJK 文字和标点。一般来说,不要轻易改变字符类别。带星号的 % 命令除了设置字符类别以外,为了确保标点处理的正确性,还重置标点符号所属的字符类。 % \end{function} % % \begin{function}[EXP]{\xeCJKResetCharClass} % 用于恢复 \pkg{xeCJK} 对各个字符类别的初始化设置。 % \end{function} % % \begin{function}[EXP]{\xeCJKResetPunctClass} % 用于重置标点符号所属的字符类。 % \end{function} % % \begin{function}{\normalspacedchars} % \begin{syntax} % \tn{normalspacedchars} \Arg{char list} % \end{syntax} % 在 \meta{char list} 中出现的字符两端不自动添加空格,初始设置是 |/|、|\|、 % 和 |-| (|U+002D|)。 % \end{function} % % \subsection{标点符号的处理} % % \pkg{xeCJK} 对标点符号的输出宽度的调整是通过调整其左边或右边的空白宽度来实现的。 % 按照目前的处理方式,对于位于左边的标点符号(如左引号),\pkg{xeCJK} 只能调整它 % 左边的空白;对于位于右边的标点符号(如右引号),\pkg{xeCJK} 只能调整它右边的空 % 白;对于居中的标点符号,则调整其左右空白,以保证其居中。对于标点符号的相关设置, % 只能在导言区中进行。 % % \subsubsection{设置特定标点符号的宽度和间距} % \label{subsec:punct} % % 这里的设置可用于除 |plain| 以外的所有标点处理格式。 % % \begin{function}[EXP,updated=2013-08-22]{\xeCJKsetwidth} % \begin{syntax} % \tn{xeCJKsetwidth} \Arg{标点列表} \Arg{length} % \tn{xeCJKsetwidth} * \Arg{标点列表} \Arg{length} % \end{syntax} % \meta{标点列表}可以是单个标点,也可以是多个标点。例如, % \begin{ctexexam} % \xeCJKsetwidth{。?}{0.7em} % \end{ctexexam} % 将设置句号和问号所占的宽度为 |0.7em|。带星号的命令,设置标点符号出现在行首/尾 % 时的宽度。 % \end{function} % % \begin{function}[EXP]{\xeCJKsetkern} % \begin{syntax} % \tn{xeCJKsetkern} \Arg{前标点} \Arg{后标点} \Arg{length} % \end{syntax} % \pkg{xeCJK} 会根据选定的标点处理格式自动调整相邻的前后两个 |CJK| 标点符号的 % 空白宽度。如果需要对个别情况进行特殊调整,可以使用这个命令。例如, % \begin{ctexexam} % \xeCJKsetkern{:}{“}{0.3em} % \end{ctexexam} % 将设置冒号与左双引号之间的空白宽度为 |0.3em|。 % \end{function} % % \subsubsection{定义标点符号处理格式} % \label{subsec:punctstyle} % % \begin{function}[EXP,updated=2013-08-22]{\xeCJKDeclarePunctStyle} % \begin{syntax} % \tn{xeCJKDeclarePunctStyle} \Arg{style} \Arg{options} % \end{syntax} % 定义新的标点符号处理格式,已经存在的同名格式将被覆盖。可以设置的选项将在下面介绍。 % \end{function} % % \begin{function}[EXP,updated=2013-08-22]{\xeCJKEditPunctStyle} % \begin{syntax} % \tn{xeCJKEditPunctStyle} \Arg{style} \Arg{options} % \end{syntax} % 修改已有的标点符号处理格式。 % \end{function} % % 下面是可以设置的标点符号格式选项。其中左边一栏是选项名称,中间是选项的输入值类 % 型,右边则是相关说明。某些选项之间是互斥的,具有优先级关系。要使下一级的选项有 % 效,则需要先禁用上一级的设置:对于 \meta{boolean} 类型的选项,将其设置为 |false|, % 对于 \meta{length} 类型的选项,将其设置为 \tn{maxdimen},而对于 \meta{real} 类型 % 的选项,将其设置为 |nan|。 % % \begin{psopt} % \PSKeyVal{enabled-global-setting}{boolean} % 是否使用 \tn{xeCJKsetup} 的 |PunctWidth|、|PunctBoundWidth| 选项和 % \tn{xeCJKsetwidth}、\tn{xeCJKsetkern} 的设置。默认值是 |true|。 % \end{psopt} % % \begin{psopt} % \PSKeyVal{fixed-punct-width}{length} % 设置单个标点符号的宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{fixed-punct-ratio}{real} % 设置单个标点符号的输出宽度与实际宽度的比例。默认值是 |1.0|。 % \PSKeyVal{mixed-punct-width}{length} % 设置句末标点符号的宽度。其中句末标点符号通过 \tn{xeCJKsetup} 的 |KaiMingPunct| % 来设置。默认值是与 |fixed-punct-width| 选项的值相同。 % \PSKeyVal{mixed-punct-ratio}{real} % 设置句末标点符号的宽度比例。默认值是与 |fixed-punct-ratio| 选项的值相同。 % \PSKeyVal{middle-punct-width}{length} % 设置居中标点符号的宽度。其中居中标点符号通过 \tn{xeCJKsetup} 的 |MiddlePunct| % 来设置。默认值是与 |fixed-punct-width| 选项的值相同。 % \PSKeyVal{middle-punct-ratio}{real} % 设置居中标点符号的宽度比例。默认值是与 |fixed-punct-ratio| 选项的值相同。 % \end{psopt} % % 以上几个选项设置的是标点的固定宽度或比例,\pkg{xeCJK} 会根据设定的选项计算标点符号 % 左/右的空白宽度。下面的选项设置的是标点符号左/右的空白宽度或比例,因此不同标点符号 % 的宽度可能会不同。为了使下面的选项生效,需要先禁用上面的相应选项。优先级自上而下。 % % \begin{psopt} % \PSKeyVal{fixed-margin-width}{length} % 设置标点的左/右空白宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{fixed-margin-ratio}{real} % 设置标点的左/右空白宽度与字体中该标点的相应实际边界宽度的比例。默认值是~|1.0|。 % \PSKeyVal{mixed-margin-width}{length} % 设置句末标点的左/右空白宽度。默认值是与 |fixed-margin-width| 的值相同。 % \PSKeyVal{mixed-margin-ratio}{real} % 设置句末标点的左/右空白宽度的比例。默认值是与 |fixed-margin-ratio| 的值相同。 % \PSKeyVal{middle-margin-width}{length} % 设置居中标点的两边空白宽度。默认值是与 |fixed-margin-width| 的值相同。 % \PSKeyVal{middle-margin-ratio}{real} % 设置居中标点的两边空白宽度之和与两边实际两边边界宽度之和的比例。 % 默认值是与 |fixed-margin-ratio| 的值相同。 % \end{psopt} % % 下面选项设置标点符号出现在行首或者行尾时的宽度或比例。 % % \begin{psopt} % \PSKeyVal{bound-punct-width}{length} % 设置标点符号出现在行首/尾时的宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{bound-punct-ratio}{real} % 设置标点符号出现在行首/尾时的输出宽度与实际宽度的比例。默认值是 |nan|。 % \PSKeyVal{bound-margin-width}{length} % 设置标点符号出现在行首/尾时的左/右空白宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{bound-margin-ratio}{real} % 设置标点符号出现在行首/尾时的左/右空白宽度与相应实际边界宽度的比例。默认值是 |0|。 % \PSKeyVal{enabled-hanging}{boolean} % 当以上选项的计算结果得到的宽度小于标点符号的实际边界宽度时,是否允许标点符号 % 悬挂出页面边界。默认值是 |false|。 % \end{psopt} % % \begin{psopt} % \PSKeyVal{add-min-bound-to-margin}{boolean} % 是否在以上计算结果的基础上再加上标点的左右实际边界宽度中的最小值。这个选项 % 对居中的标点无效。默认值是 |false|。 % \end{psopt} % % \begin{psopt} % \PSKeyVal{optimize-margin}{boolean} % 使用以上设置空白宽度或比例的选项时,最终输出的标点符号左/右的空白宽度可能大 % 于原来的实际边界宽度。若此时本选项被设置为 |true|,则使用原来的实际边界宽度。 % 而使用 |fixed-punct-width| 选项计算得出的左/右宽度可能小于该标点的另一侧宽 % 度,若此时本选项被启用,则使用该标点的另一侧宽度。默认值为 |false|。 % \end{psopt} % % \begin{psopt} % \PSKeyVal{margin-minimum}{length} % 指定标点符号左/右的最小空白宽度。当经过以上选项设置的空白宽度小于这个选项的值 % 时,则使用这个选项的值。默认值是 |0pt|。 % \end{psopt} % % 下面的选项处理的是前后相邻的两个标点符号之间的空白宽度。这些选项是互斥的,优先级 % 自上而下。 % % \begin{psopt} % \PSKeyVal{enabled-kerning}{boolean} % 是否调整前后相邻的两个标点之间的空白宽度。如果设置为 |false|,则每个标点都按 % 原来的输出宽度输出。默认值是 |true|。 % \PSKeyVal{min-bound-to-kerning}{boolean} % 是否使用当前字体中前面标点实际左右边界的最小值与后面标点实际左右边界的最小值 % 中的最大值作为两个标点之间的空白宽度。默认值是 |false|。 % \PSKeyVal{kerning-total-width}{length} % 设置两个标点的总共宽度。此时 \pkg{xeCJK} 会自动计算两个标点之间的空白宽度。 % 默认值是 \tn{maxdimen}。 % \PSKeyVal{kerning-total-ratio}{real} % 设置两个标点的总共输出宽度与实际宽度的比例。默认值是 |0.75|。 % \PSKeyVal{same-align-margin}{length} % 前后两个标点位于同侧时,它们之间的空白宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{same-align-ratio}{real} % 前后两个标点位于同侧时,它们之间的空白宽度与实际输出宽度的比例。默认值是~|nan|。 % \PSKeyVal{different-align-margin}{length} % 前后两个标点位于异侧时,它们之间的空白宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{different-align-ratio}{real} % 前后两个标点位于异侧时,它们之间的空白宽度与实际输出宽度的比例。默认值是~|nan|。 % \PSKeyVal{kerning-margin-width}{length} % 设置前后两个标点之间的空白宽度。默认值是 \tn{maxdimen}。 % \PSKeyVal{kerning-margin-ratio}{real} % 设置前后两个标点之间的空白宽度与实际输出空白的比例。默认值是 |1.0|。 % \end{psopt} % % \begin{psopt} % \PSKeyVal{optimize-kerning}{boolean} % 使用以上选项计算出两个标点之间的空白宽度可能小于通过 |min-bound-to-kerning| % 选项得出的结果。当出现这一情况时,若此选项被设置为 |true|,则使用该选项的空 % 白宽度。默认值为 |false|。 % \end{psopt} % % \begin{psopt} % \PSKeyVal{kerning-margin-minimum}{length} % 指定两个标点之间的最小空白宽度。当经过以上选项设置的空白宽度小于这个选项的值 % 时,则使用这个选项的值。默认值是 |0pt|。 % \end{psopt} % % 事实上,\pkg{xeCJK} 的默认设置就相当于中文全角(|quanjiao|)格式。可以使用上面 % 说明的选项定义新的标点处理格式。例如,使用 % \begin{ctexexam} % \xeCJKDeclarePunctStyle { mine } % { % fixed-punct-ratio = nan , % fixed-margin-width = 0 pt , % mixed-margin-width = \maxdimen , % mixed-margin-ratio = 0.5 , % middle-margin-width = \maxdimen , % middle-margin-ratio = 0.5 , % add-min-bound-to-margin = true , % bound-punct-width = 0 em , % enabled-hanging = true , % min-bound-to-kerning = true , % kerning-margin-minimum = 0.1 em % } % \end{ctexexam} % 就定义了一个名为 |mine| 的标点处理格式。可以在导言区通过 % \begin{frameverb} % \xeCJKsetup{PunctStyle=mine} % \end{frameverb} % 在文档中使用这个格式。它的意义是:使用标点符号的实际左右边界中的最小值作为其左/右 % 空白的宽度,对于句末标点和居中标点,再加上实际边界空白的一半;当标点出现在行首或 % 行尾时宽度为零,允许悬挂出页面边界;使用相邻两个标点的实际边界中的较小值作为它们 % 之间的空白宽度,并且最小的空白宽度是 |0.1em|。再例如,使用 % \begin{ctexexam} % \xeCJKEditPunctStyle { hangmobanjiao } { enabled-global-setting = false } % \end{ctexexam} % 将使得 \tn{xeCJKsetkern} 等的设置对 |hangmobanjiao| 这一格式无效。 % % \subsection{\pkg{xeCJKfntef} 用法说明} % % \pkg{xeCJK} 包含有一个子宏包 \pkg{xeCJKfntef},可以用它来实现\CJKunderdot{汉字加点}% % 和可断行的下划线等。它是 \pkg{CJKfntef} 宏包在 \XeLaTeX 下的替换版本,基本用法完全一致。 % % \pkg{xeCJKfntef} 基于 \package{ulem} 宏包,除了兼容 \pkg{ulem} 定义的一些命令外, % 还进行了一些扩充: % % \begin{function}[updated=2014-11-04] % {\CJKunderline,\CJKunderdblline,\CJKunderwave,\CJKsout,\CJKxout} % \begin{syntax} % \tn{CJKunderline} [*] [-] \oarg{选项} \Arg{内容} % \end{syntax} % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=6] % \CJKunderline{虚室生白,吉祥止止}\\ % \CJKunderdblline{虚室生白,吉祥止止}\\ % \CJKunderwave{虚室生白,吉祥止止}\\ % \CJKsout{虚室生白,吉祥止止}\\ % \CJKxout{虚室生白,吉祥止止} % \end{SideBySideExample} % \end{function} % % \csappto{NoHighlight@Attributes}{\catcode37=14\relax} % % \begin{Example}[frame=single,numbers=left,gobble=4] % \CJKunderline-{南朝}\CJKunderline-{梁}\CJKunderline-{劉勰}% % \CJKunderwave-{文心雕龍}\CJKunderwave-{養氣}\\ % \CJKunderline*[thickness=1pt, hidden=true]{瞻彼阕者,虚室生白,吉祥止止} % \end{Example} % % \begin{function}[updated=2014-11-04]{\CJKunderdot} % \begin{syntax} % \tn{CJKunderdot} \oarg{选项} \Arg{内容} % \end{syntax} % 在汉字下加点,可以和上述下划线命令嵌套使用。例如\smallskip % % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=6] % \CJKunderline{虚室生白,\CJKunderdot{吉祥}止止}\\ % \CJKunderdot{虚室生白,\CJKunderline{吉祥}止止} % \end{SideBySideExample} % \end{function} % % \bigskip % % 对上述六种对象,\pkg{xeCJKfntef} 提供了一些选项,设置点或线的位置和颜色。可以用 % \tn{xeCJKsetup} 预先统一设置它们,也可以在使用时特别设置。 % % \begin{function}[added=2014-11-04]{skip} % \begin{syntax} % \tn{xeCJKsetup} \{ underline/skip = \meta{\TTF} \} % \tn{xeCJKsetup} \{ underline = \{ skip = \meta{\TTF} , ... \} \} % \end{syntax} % 默认情况下,下划线会自动跳过中文标点符号,可以设置本选项为 \texttt{false}, % 禁用这一功能。相应下划线命令后加上 |*| 号,具有相同的效果。 % \end{function} % % \begin{function}{subtract} % 设置本选项为 \texttt{true},使得下划线的首尾减少一定距离,避免前后的下划线 % 连在一起,适用于古籍标点整理中的专名号和书名号。在相应下划线命令后加上 |-| % 号,具有相同的效果。 % \end{function} % % \begin{function}{hidden} % 设置本选项为 \texttt{true},将隐藏文本内容,只画下划线。 % \end{function} % % \begin{function}{format} % \begin{syntax} % \tn{xeCJKsetup} \{ underline/format = \tn{color}\{red\} \} % \tn{xeCJKsetup} \{ underwave = \{ format = \tn{color}\{red\}, ... \} \} % \end{syntax} % 设置线或点的格式,比如颜色。 % \end{function} % % \begin{function}[added=2016-06-03]{textformat} % 设置下划线或点的正文的格式。例如:\smallskip % \begin{Example}[frame=single,numbers=left,gobble=6] % \CJKunderline[textformat=\color{blue}]{虚室生白,吉祥止止}\\ % \CJKunderdot[textformat=\bfseries, format=\color{red}]{虚室生白,吉祥止止} % \end{Example} % \end{function} % % \begin{function}{symbol} % 设置 \tn{CJKunderwave} 或 \tn{CJKunderdot} 的符号。 % \end{function} % % 例如,波浪线 \tn{CJKunderwave} 的符号不会随字号而变化,在小字号下不好看。我们可以 % 将它改为随字号而变化大小: % % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=4] % % \usepackage{fix-cm} % \xeCJKsetup{% % underwave/symbol= % \fontsize{0.5em}{0pt}% % \fontencoding{U}\fontfamily{lasy}\selectfont % \char 58\relax} % \footnotesize % \CJKunderwave{瞻彼阕者,虚室生白,吉祥止止} % \end{SideBySideExample} % % \begin{function}{thickness} % 设置 \tn{CJKunderline}、\tn{CJKunderdblline} 和 \tn{CJKsout} 的线的厚度。 % 初始值是 \tn{ULthickness}。 % \end{function} % % \begin{function}{depth} % 设置线或点的深度(基线到线或点的顶部的距离)。初始值都是 \texttt{0.2em}。 % \end{function} % % \begin{function}{boxdepth} % \tn{CJKunderdot} 可能会影响到行距,可以设置本选项进行调整。如果不希望 % \tn{CJKunderdot} 影响行距,可以将本选项设置为 \texttt{0pt}。 % \end{function} % % \begin{function}{sep} % 设置 \tn{CJKunderdot} 与 \tn{CJKunderline}、\tn{CJKunderdblline} 或 % \tn{CJKunderwave} 嵌套使用时,点与线或者线与点的距离。 % \end{function} % % \begin{function}{gap} % 设置 \tn{CJKunderdblline} 的两条线之间的距离。初始值是 \texttt{1.1pt}。 % \end{function} % % \begin{function}{height} % 设置删除线 \tn{CJKsout} 的高度(线的中心到基线的距离)。初始值是 \texttt{0.35em}。 % % 例如,我们可以设置 \tn{CJKsout} 的厚度和颜色,让它具有类似高亮的效果:\smallskip % % \begin{Example}[frame=single,numbers=left,gobble=4] % \CJKsout*[thickness=2.5ex, format=\color{yellow}]{瞻彼阕者,虚室生白,吉祥止止} % \end{Example} % \end{function} % % \medskip % % \pkg{xeCJKfntef} 还提供给了自定义下划线和符号的 \tn{CJKunderanyline} 和 % \tn{CJKunderanysymbol}。 % % \begin{function}[updated=2014-11-07]{\CJKunderanyline} % \begin{syntax} % \tn{CJKunderanyline} [*] [-] \oarg{选项} \Arg{深度} \Arg{下划内容} \Arg{文本内容} % \end{syntax} % \pkg{xeCJKfntef} 先将 \meta{下划内容} 放进一个盒子(\tn{xeCJKfntefbox})里,然后 % 向下移动 \meta{深度} 给定的距离,再用于填充。可用的 \meta{选项} 是 \texttt{textformat}、 % \texttt{skip}、\texttt{hidden}、\texttt{subtract}、\texttt{sep} 和 % \texttt{boxdepth}。选项 \texttt{sep} 和 \texttt{boxdepth} 的初始值是空,表示 % 禁用该选项的功能。可以在 \tn{xeCJKsetup} 中通过对象 \texttt{ulem} 来设置。 % \end{function} % % 例如,高亮效果也可以如下实现:\smallskip % % \begin{Example}[frame=single,numbers=left,gobble=4] % \CJKunderanyline*{0.5ex}{\color{yellow}\rule{2pt}{2.5ex}}{虚室生白,吉祥止止} % \end{Example} % % \begin{function}[updated=2014-11-04]{\CJKunderanysymbol} % \begin{syntax} % \tn{CJKunderanysymbol} \oarg{选项} \Arg{深度} \Arg{符号} \Arg{文本内容} % \end{syntax} % \pkg{xeCJKfntef} 将 \meta{符号} 放进一个盒子(\tn{xeCJKfntefbox})里。 % \meta{深度} 参数用于设置盒子顶部的深度(基线到盒子顶部的距离)。 % 可用的 \meta{选项} 是 \texttt{textformat}、\texttt{sep} 和 \texttt{boxdepth},意义与 % \tn{CJKunderdot} 的相同。 % \end{function} % % 例如,给汉字加三角形,可以如下设置:\smallskip % % \begin{Example}[frame=single,numbers=left,gobble=4] % \CJKunderanysymbol[sep=0.1em]{0.2em}{\tiny$\triangle$} % {瞻彼阕者,虚室生白,\CJKunderline{吉祥止止}} % \end{Example} % % \begin{function}[updated=2014-11-07]{\xeCJKfntefon} % \begin{syntax} % \tn{xeCJKfntefon} [*] [-] \oarg{选项} % \end{syntax} % 功能与用法 \pkg{ulem} 宏包的 \tn{ULon} 相同,扩展了可选参数符号 |*| 和 |-|, % 可用的 \meta{选项} 是 \texttt{textformat}、 \texttt{skip}、\texttt{hidden} 和 % \texttt{subtract}。 这四个选项对 \pkg{ulem} 宏包定义的 \tn{uline} 等命令也有效,需要在 % \tn{xeCJKsetup} 中通过对象 \texttt{ulem} 来设置。例如\smallskip % % \begin{Example}[frame=single,numbers=left,gobble=6] % \xeCJKsetup{ulem={textformat=\bfseries\color{red}, skip=true}} % \uline{虚室生白,吉祥止止} % \end{Example} % \end{function} % % \medskip % % 此外,\pkg{xeCJKfntef} 还提供了指定宽度,让汉字分散对齐的的环境 % \env{CJKfilltwosides} 和 \env{CJKfilltwosides*}。 % % \begin{function}[updated=2014-11-04]{CJKfilltwosides} % \begin{syntax} % \tn{begin}\{CJKfilltwosides\} \oarg{位置} \Arg{宽度} % 文本内容\verb=\\= % 文本内容 % \tn{end}\{CJKfilltwosides\} % \end{syntax} % 环境中的内容被放入垂直盒子中,可选参数 \meta{位置} 指定盒子的基线位置。 % 可以使用 \texttt{t}(顶部)、\texttt{c}(居中)和 \texttt{b}(底部),默认是 \texttt{c}。 % \meta{宽度} 参数指定盒子的宽度。 % \env{CJKfilltwosides*} 环境与 \env{CJKfilltwosides} 的区别是,当 \meta{宽度} % 不大于零或者不大于盒子的自然宽度时,就取盒子的自然宽度。例如 % \end{function} % % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.5\linewidth,gobble=4] % \begin{CJKfilltwosides}{.8\linewidth} % 瞻彼阕者,\\ % 虚室生白,吉祥止止 % \end{CJKfilltwosides} % \end{SideBySideExample} % % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.5\linewidth,gobble=4] % \begin{CJKfilltwosides*}{0pt} % 瞻彼阕者,\\ % 虚室生白,吉祥止止 % \end{CJKfilltwosides*} % \end{SideBySideExample} % % \subsection{其他} % \label{subsec:others} % % \begin{function}[updated=2013-11-16]{\xeCJKVerbAddon,\xeCJKOffVerbAddon} % 调整文字间距以便于让 CJK 字符占的宽度等于西文等宽字体中两个空格的宽度。如果这两 % 个空格的宽度小于当前 CJK 正常文字的宽度,将对 CJK 字体进行适当地缩小。这有利于 % 等宽字体的代码对齐等情形。需要注意的是,\tn{xeCJKVerbAddon} 对 \pkg{xeCJK} 的内 % 部进行了比较大的修改,使用它之后,将禁止在 CJK 字符类之间自动换行,这与西文在 % 抄录环境中的情况是一致的。所以不应该单独使用,应该放在分组里限制其作用域,否则 % 是无效的。当然它可以和其他关于代码抄录的宏包配合使用。例如,可以使用于 % \package{fancyvrb} 宏包的 \texttt{formatcom} 选项。此时设置的西文字体应该确实 % 是等宽的以保证对齐。若西文等宽字体发生变动(包括字体大小),则需要在其后面使用 % \tn{xeCJKVerbAddon},重新计算间距的宽度。\tn{xeCJKOffVerbAddon} % 用于在使用 \tn{xeCJKVerbAddon} 的环境中局部取消它的作用。由于 \package{listings} % 宏包有自己的代码对齐机制,所以 \tn{xeCJKVerbAddon} 在由 \pkg{listings} 定义的 % 代码环境中无效。 % \end{function} % % \begin{function}[added=2012-12-03]{\xeCJKnobreak} % \begin{syntax} % ……汉字。\tn{xeCJKnobreak}\tn{footnote}\{脚注\} % \end{syntax} % \tn{xeCJKnobreak} 用在全角标点符号后面,目的是确保不能在此处断行。如果已经启用了 % 前面介绍的 |CheckFullRight| 选项,则不需要再用此命令。 % \end{function} % % \begin{function}[added=2013-11-09]{\xeCJKShipoutHook} % \pkg{xeCJK} 在正文中的一些特殊设置(汉字下加点、在 \env{verbatim} 或 % \env{lstlisting} 环境中分页)可能会影响到 \TeX 的输出例行程序(output routine) % 中的内容(比如页眉和页脚)。\tn{xeCJKShipoutHook} 用于恢复正文中的普通设置。 % \pkg{xeCJK} 已经处理了页眉和页脚的情况,其他的就需要根据情况自行调用。 % 比如若使用 \pkg{eso-pic} 或者 \pkg{atbegshi} 实现文字水印,并且正文中使用了 % 以上所列的特殊形式,就需要在命令 \tn{AtBeginShipout} 的参数的最前面使用 % \tn{xeCJKShipoutHook}。 % \end{function} % % \section{已知问题和兼容性} % % 根据 \pkg{unicode-data} 宏包,\XeTeX 将所有 CJK 表意文字的 \tn{catcode} % 设置为 $11$。因此汉字可以直接用作控制序列的名字,但是当汉字出现在控制序列后面的 % 时候,要用空格分隔开,否则就会出现“\texttt{! Undefined control sequence.}”的错误。 % % \pkg{xeCJK} 使用并重新定义了 \pkg{CJK} 宏包的部分宏命令,如 \tn{CJKfamily}、 % \tn{CJKsymbol} 和 \tn{CJKglue} 等。需要指出,\pkg{xeCJK} 不需要 \pkg{CJK} % 的支持,并且 \pkg{xeCJK} 自动禁止在它之后载入 \pkg{CJK} 宏包。 % 可以在 \pkg{xeCJK} 之\emph{后}载入 \pkg{CJKnumb} 宏包,实现数字的中文化, % 也可以用功能更完善的 \package{zhnumber} 宏包。 % % \pkg{xeCJK} 进行了一些处理,使得在使用 \XeTeX 时 \package{listings} 宏包可以 % 支持 Unicode,因此在 \texttt{listings} 定义的代码环境中可以直接使用中文,不再 % 需要通过 \texttt{escapechar}。 % % 新版本(\texttt{3.x})的 \pkg{xeCJK} 完全使用 \LaTeXiii{} 的语法来编写。 % \LaTeXiii{} 放弃了 \tn{outer} 宏的概念,因此相关工具在 % 遇到 \tn{outer} 宏时可能会存在问题。按照目前 \pkg{xeCJK} 的实现方式,在 CJK 文字 % 后面遇到 \tn{outer} 宏时会出现类似 % \begin{frameverb} % ! Forbidden control sequence found while scanning use of \use_i:nn % \end{frameverb} % 的错误。目前已知的有 \package{cprotect} 宏包提供的 \tn{cprotect}。它的定义是 % \begin{frameverb} % \outer\long\def\cprotect{\icprotect} % \end{frameverb} % 因此,这时可以暂时用 \tn{icprotect} 代替 \tn{cprotect}。事实上,当 \pkg{cprotect} % 被引入时,\pkg{xeCJK} 将使用 % \begin{frameverb} % \let\cprotect\icprotect % \end{frameverb} % 来取消 \tn{cprotect} 的外部宏限制。但由于 \tn{cprotect} 的特殊性,应该只在外部 % 使用它,即不要让它出现在任何宏的参数中。其他 \tn{outer} 宏的情况,可以在它前面 % 加上 \tn{relax} 来回避上面的错误。 % % \pkg{xeCJK} 依赖 \XeTeX 的 \tn{XeTeXinterchartoks} 机制,与使用相同机制的宏包(例如 % \pkg{polyglossia} 和 \pkg{xesearch})可能会存在大小不一的冲突。 % \pkg{xeCJK} 虽然为此作了一些处理,但与它们共同使用时应该小心。 % %\end{documentation} % % % \StopEventually{} % % %\begin{implementation} % % \section{\pkg{xeCJK} 代码实现} % % \begin{macrocode} %<*package> % \end{macrocode} % % \begin{macrocode} %<@@=xeCJK> % \end{macrocode} % % \subsection{运行环境检查} % % \pkg{xeCJK} 必须使用 \XeTeX 引擎的支持。 % \begin{macrocode} \msg_new:nnn { xeCJK } { Require-XeTeX } { The~xeCJK~package~requires~XeTeX~to~function.\\\\ You~must~change~your~typesetting~engine~to~"xelatex" \\ instead~of~plain~"latex"~or~"pdflatex"~or~"lualatex".\\ Loading~xeCJK~will~abort! } \sys_if_engine_xetex:F { \msg_critical:nn { xeCJK } { Require-XeTeX } } % \end{macrocode} % % 应该使用较新版本的 \pkg{expl3} 宏包。 % \begin{macrocode} \msg_new:nnn { xeCJK } { l3-too-old } { Support~package~`#1'~too~old. \\\\ Please~update~an~up~to~date~version~of~the~bundles\\\\ `l3kernel'~and~`l3packages'\\\\ using~your~TeX~package~manager~or~from~CTAN.\\ \str_if_eq:nnT {#1} { expl3 } { Loading~xeCJK~will~abort! } } \@ifpackagelater { expl3 } { 2020/02/08 } { } { \msg_critical:nnn { xeCJK } { l3-too-old } { expl3 } } % \end{macrocode} % % \cs{ctex_disable_package:n} 由 \pkg{ctexhook} 提供。 % \begin{macrocode} \RequirePackage { ctexhook } % \end{macrocode} % % \begin{macro}[pTF,int]{\xeCJK_if_package_loaded:n} % 判断宏包是否被引入,可用于文档正文中。 % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_package_loaded:n #1 { p , T , F , TF } { \tl_if_exist:cTF { ver@ #1 . \c_@@_package_ext_tl } { \prg_return_true: } { \prg_return_false: } } \tl_const:Nx \c_@@_package_ext_tl { \@pkgextension } % \end{macrocode} % \end{macro} % % \changes{v3.8.7}{2021/06/09}{应用 \tn{disable@package@load} 和 % \tn{declare@file@substitution}。} % % 下面这些 \pkg{CJK} 系列宏包不应该被使用。 % \begin{macrocode} \msg_new:nnn { xeCJK } { after-package } { The~`#1'~package~and~xeCJK~are~incompatible.\\\\ Please~load~it~after~xeCJK. } \clist_map_inline:nn { CJKnumb } { \xeCJK_if_package_loaded:nT {#1} { \msg_error:nnn { xeCJK } { after-package } {#1} } } \clist_map_inline:nn { CJKulem , CJKvert , CJKpunct , CJKutf8 , CJK } { \ctex_disable_package:n {#1} } % \end{macrocode} % % \changes{v3.8.7}{2021/06/09}{将 \pkg{CJKfntef} 包替换为 \pkg{xeCJKfntef} 包。} % % 将 \pkg{CJKfntef} 包替换为 \pkg{xeCJKfntef} 包。 % \begin{macrocode} \ctex_if_format_at_least:nTF { 2020/10/01 } { \ctex_replace_package:nn { CJKfntef } { xeCJKfntef } } { \ctex_disable_package:n { CJKfntef } } % \end{macrocode} % % \changes{v3.9.0}{2022/07/08}{不直接依赖 \pkg{xparse} 和 \pkg{l3keys2e}。} % % \begin{macrocode} \cs_if_exist:NF \NewDocumentCommand { \RequirePackage { xparse } } \RequirePackage { xtemplate } % \end{macrocode} % % \subsection{内部工具} % % 分配临时变量。 % \begin{macrocode} \tl_new:N \l_@@_tmp_tl \int_new:N \l_@@_tmp_int \box_new:N \l_@@_tmp_box \dim_new:N \l_@@_tmp_dim \bool_new:N \l_@@_tmp_bool \skip_new:N \l_@@_tmp_skip \clist_new:N \l_@@_tmp_clist % \end{macrocode} % % \begin{macro} % {\@@_msg_new:nn ,\@@_error:n,\@@_error:nx,\@@_warning:nx,\@@_info:nxx} % 各种信息函数的缩略形式。 % \begin{macrocode} \cs_new_protected:Npn \@@_msg_new:nn { \msg_new:nnn { xeCJK } } \cs_new_protected:Npn \@@_msg_new:nnn { \msg_new:nnnn { xeCJK } } \cs_new_protected:Npn \@@_error:n { \msg_error:nn { xeCJK } } \cs_new_protected:Npn \@@_error:nx { \msg_error:nnx { xeCJK } } \cs_new_protected:Npn \@@_warning:n { \msg_warning:nn { xeCJK } } \cs_new_protected:Npn \@@_warning:nx { \msg_warning:nnx { xeCJK } } \cs_new_protected:Npn \@@_warning:nxx { \msg_warning:nnxx { xeCJK } } \cs_new_protected:Npn \@@_warning:nxxx { \msg_warning:nnxxx { xeCJK } } \cs_new_protected:Npn \@@_info:nxx { \msg_info:nnxx { xeCJK } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_allow_break:,\xeCJK_no_break:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_allow_break: { \tex_penalty:D \c_zero_int } \cs_new_protected:Npn \xeCJK_no_break: { \tex_penalty:D \c_@@_nobreak_penalty_int } \int_const:Nn \c_@@_nobreak_penalty_int { 10 000 } % \end{macrocode} % \end{macro} % % \changes{v3.8.3}{2020/04/07}{依赖 \pkg{ctexhook} 宏包。} % % \begin{macro} % {\@@_at_end_preamble:n,\@@_after_preamble:n, % \@@_after_end_preamble:n,\@@_package_hook:nn} % 在 \tn{document} 前后和宏包后加上各种钩子,依赖 \pkg{ctexhook}。 % \begin{macrocode} \AtBeginDocument { \xeCJK@document@hook } \ctex_at_end_preamble:n { \xeCJK@document@left@hook } \ctex_after_end_preamble:n { \xeCJK@document@right@hook } \cs_new_protected:Npn \xeCJK@document@hook { \tl_use:N \g_@@_after_preamble_hook_tl } \cs_new_protected:Npn \xeCJK@document@left@hook { \tl_use:N \g_@@_at_end_preamble_hook_tl } \cs_new_protected:Npn \xeCJK@document@right@hook { \tl_use:N \g_@@_after_end_preamble_hook_tl } \cs_new_protected:Npn \@@_at_end_preamble:n { \tl_gput_right:Nn \g_@@_at_end_preamble_hook_tl } \cs_new_protected:Npn \@@_after_preamble:n { \tl_gput_right:Nn \g_@@_after_preamble_hook_tl } \cs_new_protected:Npn \@@_after_end_preamble:n { \tl_gput_right:Nn \g_@@_after_end_preamble_hook_tl } \cs_new_protected:Npn \@@_package_hook:nn { \ctex_at_end_package:nn } \tl_new:N \g_@@_at_end_preamble_hook_tl \tl_new:N \g_@@_after_preamble_hook_tl \tl_new:N \g_@@_after_end_preamble_hook_tl % \end{macrocode} % \end{macro} % % \changes{v3.2.7}{2013/11/09}{使用 \pkg{everypage} 往 \tn{shipout} 盒子里加钩子。} % \changes{v3.2.16}{2014/12/16}{不再依赖 \pkg{everypage} 宏包。} % % \begin{macro}{\xeCJKShipoutHook} % 在 \tn{shipout} 盒子里加钩子,可以影响到页眉页脚。\tn{AtBeginDvi} 将参数保存在 % 盒子中,而 \pkg{atbegshi} 的 \tn{AtBeginShipout} 在 \tn{shipout} 盒子构建好之后 % 才起作用,所以它们都影响不到页眉页脚。我们通过往 \tn{@begindvi} 里加入钩子来完成。 % 注意,第一次使用 \tn{@begindvi} 之后,它会将自身定义为 \tn{@empty}。 % \begin{macrocode} \@@_after_preamble:n { \tl_put_right:Nn \@begindvi { \xeCJK@first@begindvi } } \cs_new_protected:Npn \xeCJK@first@begindvi { \xeCJKShipoutHook \cs_if_exist:NTF \@begindvi { \tl_gput_right:Nn } { \tl_const:Nn } \@begindvi { \xeCJKShipoutHook } } \NewDocumentCommand \xeCJKShipoutHook { } { \bool_if:NF \l_@@_shipout_hook_bool { \bool_set_true:N \l_@@_shipout_hook_bool \tl_use:N \l_@@_shipout_hook_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_add_to_shipout:n} % \changes{v3.2.11}{2014/03/14}{不再使用内部名字。} % 往 \tn{shipout} 盒子中加入钩子。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_add_to_shipout:n { \tl_put_right:Nn \l_@@_shipout_hook_tl } \tl_new:N \l_@@_shipout_hook_tl \bool_new:N \l_@@_shipout_hook_bool % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_tl_remove_outer_braces:n} % \changes{v3.2.4}{2013/07/02}{去掉外层分组括号时,移除空格,避免死循环。} % 去掉 |#1| 外层的分组括号。 % \begin{macrocode} \cs_new:Npn \xeCJK_tl_remove_outer_braces:n #1 { \exp_last_unbraced:Ne \@@_tl_remove_outer_braces:w { \tl_trim_spaces:n {#1} } \s_stop } \cs_new:Npn \@@_tl_remove_outer_braces:w #1 \s_stop { \tl_if_single:nTF {#1} { \tl_if_head_is_N_type:nTF {#1} { \tl_trim_spaces:n } { \xeCJK_tl_remove_outer_braces:n } } { \tl_trim_spaces:n } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_cs_clear:N,\xeCJK_cs_gclear:N} % 让控制序列的意义为空。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_cs_clear:N #1 { \cs_set_eq:NN #1 \prg_do_nothing: } \cs_new_protected:Npn \xeCJK_cs_gclear:N #1 { \cs_gset_eq:NN #1 \prg_do_nothing: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_swap_cs:NN} % 交换 |#1| 和 |#2| 的意义。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_swap_cs:NN #1#2 { \cs_set_eq:NN \@@_swap_cs_aux:w #1 \cs_set_eq:NN #1 #2 \cs_set_eq:NN #2 \@@_swap_cs_aux:w \cs_undefine:N \@@_swap_cs_aux:w } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_font_gset_to_current:N} % \changes{v3.8.4}{2020/06/04}{不缓存 \tn{nullfont}。} % |#1| 是控制序列的名字,令它等于当前字体命令。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_font_gset_to_current:N { \exp_after:wN \@@_font_gset_to_current_aux:NN \tex_the:D \tex_font:D } \cs_new_protected:Npn \@@_font_gset_to_current_aux:NN #1#2 { \cs_if_eq:NNF #1 \tex_nullfont:D { \cs_gset_eq:NN #2#1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int,pTF]{\xeCJK_glyph_if_exist:N} % \changes{v3.1.0}{2012/11/19}{改进 \pkg{fontspec} 宏包中定义的 % \cs{font_glyph_if_exist:NnTF}。} % 判断当前字体中是否含有字符 |#1|。\pkg{fontspec} 中的类似函数在判断为真的时候, % 会留有一个 \cs{scan_stop:},造成不必要的边界,同时也不完全可展。因此,我们重新 % 定义它。 % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_glyph_if_exist:N #1 { p , T , F , TF } { \tex_iffontchar:D \tex_font:D `#1 \exp_stop_f: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\c_xeCJK_space_skip_tl} % \changes{v3.1.0}{2012/11/18}{字间空格考虑 \tn{spaceskip} 不为零的情况。} % \changes{v3.2.0}{2013/05/22}{字间空格考虑到 \tn{spacefactor} 和 \tn{xspaceskip} 的情况。} % 当前字体状态下,一个字间空格产生的 |glue| 的长度,包括伸展和收缩部分。 % \begin{macrocode} \tl_const:Nn \c_xeCJK_space_skip_tl { \int_compare:nNnTF \g_@@_space_factor_int = { 1000 } { \skip_if_eq:nnTF \tex_spaceskip:D \c_zero_skip { \tex_fontdimen:D 2 ~ \tex_font:D plus \tex_fontdimen:D 3 ~ \tex_font:D minus \tex_fontdimen:D 4 ~ \tex_font:D } { \tex_spaceskip:D } } { \skip_if_eq:nnTF \tex_spaceskip:D \c_zero_skip { \int_compare:nNnTF \g_@@_space_factor_int < { 2000 } { \@@_space_skip_scale:nnn { \tex_fontdimen:D 2 ~ \tex_font:D } } { \skip_if_eq:nnTF \tex_xspaceskip:D \c_zero_skip { \@@_space_skip_scale:nnn { \tex_fontdimen:D 2 ~ \tex_font:D + \tex_fontdimen:D 7 ~ \tex_font:D } } { \tex_xspaceskip:D \use_none:nn } } { \tex_fontdimen:D 3 ~ \tex_font:D } { \tex_fontdimen:D 4 ~ \tex_font:D } } { \int_compare:nNnTF \g_@@_space_factor_int < { 2000 } { \@@_space_skip_scale:nnn { \tex_spaceskip:D } } { \skip_if_eq:nnTF \tex_xspaceskip:D \c_zero_skip { \@@_space_skip_scale:nnn { \tex_spaceskip:D + \tex_fontdimen:D 7 ~ \tex_font:D } } { \tex_xspaceskip:D \use_none:nn } } { \tex_gluestretch:D \tex_spaceskip:D } { \tex_glueshrink:D \tex_spaceskip:D } } } } \cs_new:Npn \@@_space_skip_scale:nnn #1#2#3 { \dim_eval:n {#1} plus \fp_eval:n { \g_@@_space_factor_int / 1000 } #2 minus \int_div_truncate:nn { 1000 * \int_value:w #3 } { \g_@@_space_factor_int } sp } % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\xeCJK_reset_space_factor:} % \begin{variable}[int]{\g_@@_space_factor_int} % 在 \tn{XeTeXinterchartoks} 里,\tn{spacefactor} 已经被重置为 $1000$。 % 我们需要在 Default 类里保存 \tn{spacefactor} 用于计算空格宽度。 % \begin{macrocode} \int_new:N \g_@@_space_factor_int \cs_new_protected:Npn \xeCJK_reset_space_factor: { \int_gset:Nn \g_@@_space_factor_int { 1000 } } \xeCJK_reset_space_factor: % \end{macrocode} % \end{variable} % \end{macro} % % \begin{macro}[int]{\xeCJK_glue_to_skip:nN} % 取得一个 |glue| 的长度,包括伸展和收缩部分。如果参数不是 |glue|,则取其宽度。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_glue_to_skip:nN #1#2 { \group_begin: \hbox_set:Nw \l_@@_tmp_box #1 \scan_stop: \@@_if_last_glue:TF { \exp_args:NNNo \hbox_set_end: \skip_set:Nn #2 { \skip_use:N \tex_lastskip:D } } { \exp_args:NNNo \hbox_set_end: \skip_set:Nn #2 { \dim_use:N \box_wd:N \l_@@_tmp_box } } \exp_args:NNNo \group_end: \skip_set:Nn #2 { \skip_use:N #2 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_int_until_do:nn} % \begin{macro}{\@@_int_until_do:wn} % 由于定义较为简单,可以比 \cs{int_until_do:nNnn} 稍微快一点点。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_int_until_do:nn #1#2 { \@@_int_until_do:wn \use_none:n { \reverse_if:N \if_int_compare:w #1#2 } } \cs_new_protected:Npn \@@_int_until_do:wn \use_none:n #1 { #1 \exp_after:wN \@@_int_until_do:wn \fi: \use_none:n {#1} } \int_new:N \l_@@_begin_int \int_new:N \l_@@_end_int % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\xeCJK_peek_catcode_ignore_spaces:NTF} % \changes{v3.1.1}{2012/12/04}{新增有省略空格标识的 \texttt{peek} 函数。} % 我们在里面设置了一个变量 \cs{l_@@_peek_ignore_spaces_bool} 用于标识后面的空格 % 是否被省略掉了。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NTF #1#2#3 { \cs_set_eq:NN \l_@@_peek_search_token #1 \scan_stop: \cs_set_protected:Npx \@@_peek_catcode_true:w { \exp_not:N \group_align_safe_end: \exp_not:n {#2} } \cs_set_protected:Npx \@@_peek_catcode_false:w { \exp_not:N \group_align_safe_end: \exp_not:n {#3} } \bool_set_false:N \l_@@_peek_ignore_spaces_bool \group_align_safe_begin: \peek_after:Nw \@@_peek_catcode_ignore_spaces_branches:w } \cs_new_protected:Npn \@@_peek_catcode_ignore_spaces_branches:w { \if_meaning:w \l_peek_token \c_space_token \bool_set_true:N \l_@@_peek_ignore_spaces_bool \exp_after:wN \peek_after:Nw \exp_after:wN \@@_peek_catcode_ignore_spaces_branches:w \tex_romannumeral:D 0 \else: \if_catcode:w \exp_not:N \l_peek_token \exp_not:N \l_@@_peek_search_token \exp_after:wN \exp_after:wN \exp_after:wN \@@_peek_catcode_true:w \else: \exp_after:wN \exp_after:wN \exp_after:wN \@@_peek_catcode_false:w \fi: \fi: } \cs_new_eq:NN \l_@@_peek_search_token ? \cs_new_eq:NN \@@_peek_catcode_true:w \prg_do_nothing: \cs_new_eq:NN \@@_peek_catcode_false:w \prg_do_nothing: \bool_new:N \l_@@_peek_ignore_spaces_bool % \end{macrocode} % \end{macro} % % \changes{v3.8.0}{2020/02/10}{应用 \cs{peek_remove_spaces:n}。} % % \begin{macro}[int]{\xeCJK_token_value_class:N} % 用于取得记号 |#1| 所在的 \XeTeX 字符类。|#1| 应为 \tn{catcode} 为 |11| 或 |12| % 的显性或隐性记号。 % \begin{macrocode} \cs_new:Npn \xeCJK_token_value_class:N #1 { \tex_XeTeXcharclass:D \xeCJK_token_value_charcode:N #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_token_value_charcode:N} % \changes{v3.2.4}{2013/06/30}{考虑 \texttt{charcode} 超出 BMP 的情况。} % \changes{v3.3.1}{2015/05/08}{\texttt{0.99992} 版修复了 \tn{meaning} 的 Bug。} % 当记号 |#1| 的 \texttt{charcode} 大于等于 \texttt{0x10000} 时,\XeTeX\ % \texttt{0.9999.0} 版以前的 \tn{meaning} 的返回结果比较特殊\footnote{参见 % \url{http://tug.org/pipermail/xetex/2013-January/023967.html} 和 % \url{http://tex.stackexchange.com/a/64848}。},需要特别处理。 % \texttt{0.9999.0} 版以后的 \XeTeX 的 \tn{meaning} % 对于超出 BMP 的字符,会返回两个字符,分别对应于其 UTF-16 编码的首尾代理^^A % \footnote{参见 \url{http://tug.org/pipermail/xetex/2013-June/024543.html}。}。 % 这一 Bug 在 TeX Live 2015 的 \texttt{0.99992} 版中得到修复^^A % \footnote{参见\url{http://tug.org/pipermail/xetex/2015-May/025941.html}}。 % \begin{macrocode} \cs_new:Npn \xeCJK_token_value_charcode:N #1 { \exp_after:wN \@@_get_charcode:w \token_to_meaning:N #1 \q_stop } \group_begin: \cs_set:Npn \@@_tmp:w #1 ~ #2 ~ #3#4#5 \q_stop { \tl_if_empty:nTF { #4#5 } { \cs_new:Npn \@@_get_charcode:w ##1 ~ ##2 ~ ##3 \q_stop { \int_eval:n { `##3 } } } { \tl_if_empty:nTF {#5} { \cs_new:Npn \@@_get_charcode:w ##1 ~ ##2 ~ ##3##4 \q_stop { \int_eval:n { \tl_if_empty:nTF { ##4 } { `##3 } { ( `##3 - "D800 ) * "400 + ( `##4 - "DC00 ) + "10000 } } } } { \cs_new:Npn \@@_get_charcode:w ##1 ~ ##2 ~ ##3##4 \q_stop { \int_eval:n { \tl_if_empty:nTF { ##4 } { `##3 } { "20000 } } } } } } \exp_after:wN \@@_tmp:w \token_to_meaning:N ^^^^^20000 { } \q_stop \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,int]{\xeCJK_if_CJK_class:N} % 判断字符 |#1| 是否为 CJK 字符类,包括文字和标点符号。 % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_CJK_class:N #1 { p , T , F , TF } { \if_cs_exist:w \@@_CJK_class_tl:n { \xeCJK_token_value_class:N #1 } \cs_end: \prg_return_true: \else: \prg_return_false: \fi: } \cs_new:Npn \@@_CJK_class_tl:n #1 { c_@@_CJK_class_ \int_eval:n {#1} _tl } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,int]{\xeCJK_if_same_class:NN} % 判断两个字符是否同属于一个字符类。 % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_same_class:NN #1#2 { p , T , F , TF } { \if_int_compare:w \xeCJK_token_value_class:N #1 = \xeCJK_token_value_class:N #2 \exp_stop_f: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_make_boundary:} % 利用 \cs{scan_stop:} 结束 CJK 分组,用于恢复字体等。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_make_boundary: { \bool_if:NT \l_@@_CJK_group_bool { \scan_stop: } } % \end{macrocode} % \end{macro} % % \subsection{功能开关} % % \begin{macro}{xeCJKactive} % 事实上,将开启或关闭 \XeTeX 的整个字符类机制。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { xeCJKactive .choice: , xeCJKactive / true .code:n = { \makexeCJKactive } , xeCJKactive / false .code:n = { \makexeCJKinactive } , xeCJKactive .default:n = { true } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\makexeCJKactive, \makexeCJKinactive} % \begin{macrocode} \NewDocumentCommand \makexeCJKactive { } { \tex_XeTeXinterchartokenstate:D = \c_one_int } \NewDocumentCommand \makexeCJKinactive { } { \tex_XeTeXinterchartokenstate:D = \c_zero_int } % \end{macrocode} % \end{macro} % % 抑制 |BOM|。 % \begin{macrocode} \char_set_catcode_ignore:n { "FEFF } % \end{macrocode} % % \subsection{字符类别设定}\label{sec:xeCJK-class-set} % % \begin{variable}{\g_@@_class_seq,\g_@@_new_class_seq} % 分别用于记录在 \pkg{xeCJK} 中使用的字符类别名称和新建的字符类别的编号。 % \begin{macrocode} \seq_new:N \g_@@_class_seq \seq_new:N \g_@@_new_class_seq % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\xeCJK_new_class:n} % 新建一个字符类别。|#1| 是自定义名称。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_new_class:n #1 { \int_if_exist:cTF { \@@_class_csname:n {#1} } { \@@_error:nx { class-already-defined } {#1} } { \exp_args:Nc \newXeTeXintercharclass { \@@_class_csname:n {#1} } \clist_new:c { g_@@_#1_range_clist } \seq_gput_right:Nn \g_@@_class_seq {#1} \seq_gput_right:Nv \g_@@_new_class_seq { \@@_class_csname:n {#1} } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_save_class:nn} % \changes{v3.1.1}{2012/12/06} % {使用 \cs{xeCJK_save_class:nn} 保存 \XeTeX 预定义的字符类别。} % 保存 \XeTeX 预定义的字符类别。|#1| 是自定义名称,|#2| 是编号。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_save_class:nn #1#2 { \int_if_exist:cTF { \@@_class_csname:n {#1} } { \@@_error:nx { class-already-defined } {#1} } { \int_const:cn { \@@_class_csname:n {#1} } {#2} \clist_new:c { g_@@_#1_range_clist } \seq_gput_right:Nn \g_@@_class_seq {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_class_csname:n} % 字符类名称对应的控制序列名字。 % \begin{macrocode} \cs_new:Npn \@@_class_csname:n #1 { c_@@_#1_class_int } \cs_new_eq:cN { \@@_class_csname:n { Others } } \l_@@_tmp_int \@@_msg_new:nn { class-already-defined } { XeTeX~character~class~`#1'~has~been~already~defined.\\\\ Please~take~another~name. \\ } % \end{macrocode} % \end{macro} % % \changes{v3.2.0}{2013/05/20}{增加 \texttt{IVS} 字符类用于处理异体字选择符。} % \changes{v3.3.1}{2015/01/22}{\texttt{IVS} 字符类更名为 \texttt{CM}。} % % \pkg{xeCJK} 需要以下字符类别用于字符输出。其中 |Default|、|CJK|、|FullLeft|、 % |FullRight|、|Boundary| 为 \XeTeX\ 中预定义的类别,\pkg{xeCJK} 新增加了\ % |HalfLeft|、|HalfRight|、|NormalSpace| 和 |CM|。其中异体字选择符 % (Ideographic Variation Selectors)\footnote{\url{http://www.unicode.org/reports/tr37/}} % 需要 \XeTeX\ |0.9999.0| 以上的版本^^A % \footnote{\url{http://tug.org/pipermail/xetex/2013-March/024118.html}}和相关字体的支持。 % \begin{center}\xeCJKsetup{PunctStyle=hangmobanjiao} % \begin{tabular}{cll} % \toprule % 类别 & 说明 & 例子 \\ \midrule % |Default| & 西文一般符号 & abc123 \\ % |CJK| & CJK 表意符号 & 汉字ぁぃぅ \\ % |FullLeft| & 全角左标点 & (《:“ \\ % |FullRight| & 全角右标点 & ,。)》” \\ % |HalfLeft| & 半角左标点 & ( [ \{ \\ % |HalfRight| & 半角右标点 & , . ? ) ] \} \\ % |NormalSpace| & 前后原始间距的符号 & / \\ % |Boundary| & 边界 & 空格 \\ % |CM| & 组合标识 & 异体字选择符\\ % |HangulJamo| & 朝鲜文字母 & |ᄻ||ᆟ||ᇫ|\\ % \bottomrule % \end{tabular} % \end{center} % % \changes{v3.3.3}{2016/01/20}{兼容 \LaTeXe{} 2016/02/01 的字符类设置。} % \changes{v3.3.4}{2016/02/07}{兼容 \XeTeX{} 0.99994 的边界字符类。} % \begin{macro}[int]{Default,CJK,FullLeft,FullRight,Boundary} % \begin{macrocode} \xeCJK_save_class:nn { Default } { 0 } % \end{macrocode} % \XeTeX{} 0.99994 将字符类总数扩大到 $4096$^^A % \footnote{\url{http://tug.org/pipermail/xetex/2016-February/026363.html}}。 % \begin{macrocode} \str_const:Nx \c_@@_xetex_version_str { \int_use:N \tex_XeTeXversion:D \tex_XeTeXrevision:D } \fp_compare:nNnTF { \c_@@_xetex_version_str } > { 0.99993 } { \xeCJK_save_class:nn { Boundary } { 4095 } } { \xeCJK_save_class:nn { Boundary } { 255 } } % \end{macrocode} % \LaTeXe{} 2016/02/01 不再预设置 CJK 字符类。 % \begin{macrocode} \int_compare:nNnTF { \tex_XeTeXcharclass:D "4E00 } = \c_one_int { \xeCJK_save_class:nn { CJK } { 1 } \xeCJK_save_class:nn { FullLeft } { 2 } \xeCJK_save_class:nn { FullRight } { 3 } \int_const:Nn \c_@@_class_begin_int { 3 } } { \xeCJK_new_class:n { CJK } \xeCJK_new_class:n { FullLeft } \xeCJK_new_class:n { FullRight } \int_const:Nn \c_@@_class_begin_int { 0 } } % \end{macrocode} % \end{macro} % % \changes{v3.2.15}{2014/11/10}{增加 \texttt{HangulJamo} 字符类。} % % \begin{macro}[int]{HalfLeft,HalfRight,NormalSpace,CM,HangulJamo} % 新增西文半角左/右标点、前后原始间距的符号和异体字选择符类。 % \begin{macrocode} \xeCJK_new_class:n { HalfLeft } \xeCJK_new_class:n { HalfRight } \xeCJK_new_class:n { NormalSpace } \xeCJK_new_class:n { CM } \xeCJK_new_class:n { HangulJamo } % \end{macrocode} % \end{macro} % % \changes{v3.2.11}{2014/04/10} % {左右角括号 \texttt{U+2329} 和 \texttt{U+232A} 是西文标点符号。} % \changes{v3.2.15}{2014/11/09} % {把 REVERSE SOLIDUS(\texttt{U+005C})、HYPHEN-MINUS(\texttt{U+002D})和 % EN DASH(\texttt{U+2013})归入 \texttt{NormalSpace} 类。} % % \begin{variable} % {\c_@@_HalfLeft_chars_clist,\c_@@_HalfRight_chars_clist,\c_@@_NormalSpace_chars_clist} % \hypertarget{CJKcharclass}{西文半角左/右标点和前后原始间距的字符类。} % \begin{macrocode} \clist_const:Nn \c_@@_HalfLeft_chars_clist { "28 , "5B , "60 , "7B , "2329 } \clist_const:Nn \c_@@_HalfRight_chars_clist { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D , "232A } \clist_const:Nn \c_@@_NormalSpace_chars_clist { "2D , "2F , "5C } % \end{macrocode} % \end{variable} % % 以下对全角标点符号的归类来源于 \XeTeX 的脚本 % \href{http://sourceforge.net/p/xetex/code/ci/master/tree/source/texk/web2c/xetexdir/unicode-char-prep.pl} % {\file{unicode-char-prep.pl}} 和 Unicode 数据库\footnote{\url{http://www.unicode.org/reports/tr14/}}。 % % \changes{v3.2.3}{2013/06/09}{根据 \XeTeX 的脚本重新整理全角标点符号。} % % \begin{variable}{\c_@@_OP_chars_clist} % Open Punctuation (OP) % \PrintPunctList{OP}{Open Punctuation} % 以下代码的第一行是中西文共用的左引号。 % \begin{macrocode} \clist_const:Nn \c_@@_OP_chars_clist { "2018 , "201C , "3008 , "300A , "300C , "300E , "3010 , "3014 , "3016 , "3018 , "301A , "301D , "FE17 , "FE35 , "FE37 , "FE39 , "FE3B , "FE3D , "FE3F , "FE41 , "FE43 , "FE47 , "FE59 , "FE5B , "FE5D , "FF08 , "FF3B , "FF5B , "FF5F , "FF62 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_PR_chars_clist} % \changes{v3.3.0}{2014/12/26}{不把 \texttt{U+20A9} 归入 CJK 的 PR 类。} % Prefix Numeric (PR) % \PrintPunctList{PR}{Prefix Numeric} % \begin{macrocode} \clist_const:Nn \c_@@_PR_chars_clist { "FE69 , "FF04 , "FFE1 , "FFE5 , "FFE6 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_FullLeft_chars_clist} % 以上两类标点符号出现在文字的左边,不应出现在行尾位置。 % \begin{macrocode} \clist_new:N \c_@@_FullLeft_chars_clist \clist_gconcat:NNN \c_@@_FullLeft_chars_clist \c_@@_OP_chars_clist \c_@@_PR_chars_clist % \end{macrocode} % \end{variable} % % \changes{v3.3.3}{2015/12/12} % {把 EN DASH(\texttt{U+2013})作为半字线连接号归入 \texttt{FullRight} 类。} % \changes{v3.3.3}{2015/12/12} % {不再把 \texttt{U+2015} 和 \texttt{U+2500} 归入 \texttt{FullRight} 类。} % \changes{v3.6.0}{2018/01/14} % {把 TWO-EM DASH (\texttt{U+2E3A}) 归入 \texttt{FullRight} 类和设为 % \texttt{LongPunct} 与 \texttt{MiddlePunct}。} % % \begin{variable}{\c_@@_CL_chars_clist} % Close Punctuation (CL) % \PrintPunctList{CL}{Close Punctuation} % 以下代码的第一行是中西文共用的一些标点符号。 % \begin{macrocode} \clist_const:Nn \c_@@_CL_chars_clist { "00B7 , "2019 , "201D , "2013 , "2014 , "2025 , "2026 , "2027 , "2E3A , "3001 , "3002 , "3009 , "300B , "300D , "300F , "3011 , "3015 , "3017 , "3019 , "301B , "301E , "301F , "FE11 , "FE12 , "FE18 , "FE36 , "FE38 , "FE3A , "FE3C , "FE3E , "FE40 , "FE42 , "FE44 , "FE48 , "FE50 , "FE52 , "FE5A , "FE5C , "FE5E , "FF09 , "FF0C , "FF0E , "FF3D , "FF5D , "FF60 , "FF61 , "FF63 , "FF64 } % \end{macrocode} % \end{variable} % % \changes{v3.3.0}{2014/12/26}{不把 NS 类中的一些有禁则的日文归入 \texttt{FullRight} 类。} % \changes{v3.6.0}{2018/01/14} % {将全角浪线 \texttt{U+FF5E} 等连接号归入 \texttt{FullRight} 类和设为 \texttt{MiddlePunct}。} % % \begin{variable}{\c_@@_NS_chars_clist} % Nonstarter (NS) % \PrintPunctList{NS}{Nonstarter} % \noindent Hyphens (cl-03) % \PrintPunctList{hyphens}{Hyphens} % \noindent Iteration marks (cl-09) % \PrintPunctList{iteration_marks}{Iteration marks} % 根据 W3C 的资料\footnote{\url{http://www.w3.org/TR/jlreq/}},\texttt{cl-03} 和 % \texttt{cl-09} 在非常松散的情况下可以没有禁则。我们仅将全角浪线 \texttt{U+FF5E} 等连接号归入 % \texttt{FullRight} 类并在宏包末尾设为 \texttt{MiddlePunct}。 % \begin{macrocode} \clist_const:Nn \c_@@_hyphens_chars_clist { "301C , "30A0 , "FF5E } \clist_const:Nn \c_@@_iteration_marks_chars_clist { "3005 , "303B , "309D , "309E , "30FD , "30FE } \clist_const:Nn \c_@@_NS_chars_clist { "30FB , "FE54 , "FE55 , "FF1A , "FF1B , "FF65 , "16FE0 } \AtEndOfPackage { \cs_set:Npn \@@_tmp:w #1 { \char_generate:nn {#1} { 12 } } \@@_add_special_punct:nn { middle } { \clist_map_function:NN \c_@@_hyphens_chars_clist \@@_tmp:w } \cs_undefine:N \@@_tmp:w } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_EX_chars_clist} % Exclamation/Interrogation (EX) % \PrintPunctList{EX}{Exclamation/Interrogation} % \begin{macrocode} \clist_const:Nn \c_@@_EX_chars_clist { "FE15 , "FE16 , "FE56 , "FE57 , "FF01 , "FF1F } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_IS_chars_clist} % Infix Numeric Separator (IS) % \PrintPunctList{IS}{Infix Numeric Separator} % \begin{macrocode} \clist_const:Nn \c_@@_IS_chars_clist { "FE10 , "FE13 , "FE14 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_CJ_chars_clist} % Conditional Japanese Starter (CJ)。这类字符的禁则是可选的^^A % \footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/165}}, % 为实现的简单计,我们把它们归入 CJK 类,即没有禁则。 % \PrintPunctList{CJ}{Conditional Japanese Starter} % \begin{macrocode} \clist_const:Nn \c_@@_CJ_chars_clist { "3041 , "3043 , "3045 , "3047 , "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "3095 , "3096 , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , "30E5 , "30E7 , "30EE , "30F5 , "30F6 , "30FC , "31F0 , "31F1 , "31F2 , "31F3 , "31F4 , "31F5 , "31F6 , "31F7 , "31F8 , "31F9 , "31FA , "31FB , "31FC , "31FD , "31FE , "31FF , "FF67 , "FF68 , "FF69 , "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_PO_chars_clist} % Postfix Numeric (PO) % \PrintPunctList{PO}{Postfix Numeric} % \begin{macrocode} \clist_const:Nn \c_@@_PO_chars_clist { "FE6A , "FF05 , "FFE0 } % \end{macrocode} % \end{variable} % % \changes{v3.3.0}{2014/12/26}{不把小写日文假名归入 \texttt{FullRight} 类。} % % \begin{variable}{\c_@@_FullRight_chars_clist} % 以上六类标点符号出现在文字的右边,不应出现在行首位置。 % \begin{macrocode} \clist_new:N \c_@@_FullRight_chars_clist \tl_map_inline:nn { \c_@@_CL_chars_clist \c_@@_NS_chars_clist \c_@@_EX_chars_clist \c_@@_IS_chars_clist \c_@@_PO_chars_clist \c_@@_hyphens_chars_clist } { \clist_gconcat:NNN \c_@@_FullRight_chars_clist \c_@@_FullRight_chars_clist #1 } % \end{macrocode} % \end{variable} % % \changes{v3.3.3}{2015/06/25}{补充 Ext-E。} % \changes{v3.4.1}{2016/08/18}{补充 Unicode 9.0.0 的西夏文。} % \changes{v3.5.0}{2017/07/22}{补充 Ext-F。} % \changes{v3.7.3}{2019/04/15}{补充日文假名扩展。} % \changes{v3.8.3}{2020/03/15}{同步 Unicode 13.0.0。} % \changes{v3.8.3}{2020/04/09}{补充 \texttt{U+02EA} 和 \texttt{U+02EB}。} % \changes{v3.8.8}{2021/09/15}{同步 Unicode 14.0.0。} % \changes{v3.8.8}{2021/09/16}{补充女书。} % % \begin{variable}{\c_@@_CJK_chars_clist} % CJK 字符类,包括文字和标点符号。 % \begin{macrocode} \clist_const:Nn \c_@@_CJK_chars_clist { % \end{macrocode} % \begin{itemize}[nosep,leftmargin=0pt] % \item 闽南语、客家话阴去和阳去声调标记 % \begin{macrocode} "02EA -> "02EB , % \end{macrocode} % \item CJK Radicals Supplement (中日韩部首补充) % \begin{macrocode} "2E80 -> "2EFF , % \end{macrocode} % \item Kangxi Radicals (康熙部首) % \begin{macrocode} "2F00 -> "2FDF , % \end{macrocode} % \item Ideographic Description Characters (表意文字描述符) % \begin{macrocode} "2FF0 -> "2FFF , % \end{macrocode} % \item CJK Symbols and Punctuation (中日韩符号和标点) % \begin{macrocode} "3000 -> "303F , % \end{macrocode} % \item Hiragana (日文平假名) % \begin{macrocode} "3040 -> "309F , % \end{macrocode} % \item Katakana (日文片假名) % \begin{macrocode} "30A0 -> "30FF , % \end{macrocode} % \item Bopomofo (注音字母) % \begin{macrocode} "3100 -> "312F , % \end{macrocode} % \item Hangul Compatibility Jamo (谚文兼容字母) % \begin{macrocode} "3130 -> "318F , % \end{macrocode} % \item Kanbun (象形字注释标志) % \begin{macrocode} "3190 -> "319F , % \end{macrocode} % \item Bopomofo Extended (注音字母扩展) % \begin{macrocode} "31A0 -> "31BF , % \end{macrocode} % \item CJK Strokes (中日韩笔画) % \begin{macrocode} "31C0 -> "31EF , % \end{macrocode} % \item Katakana Phonetic Extensions (日文片假名语音扩展) % \begin{macrocode} "31F0 -> "31FF , % \end{macrocode} % \item Enclosed CJK Letters and Months (带圈中日韩字母和月份) % \begin{macrocode} "3200 -> "32FF , % \end{macrocode} % \item CJK Compatibility (中日韩兼容) % \begin{macrocode} "3300 -> "33FF , % \end{macrocode} % \item CJK Unified Ideographs Extension-A (中日韩统一表意文字扩展 A) % \begin{macrocode} "3400 -> "4DBF , % \end{macrocode} % \item Yijing Hexagrams Symbols (易经六十四卦符号) % \begin{macrocode} "4DC0 -> "4DFF , % \end{macrocode} % \item CJK Unified Ideographs (中日韩统一表意文字) % \begin{macrocode} "4E00 -> "9FFF , % \end{macrocode} % \item Yi Syllables (彝文音节) % \begin{macrocode} "A000 -> "A48F , % \end{macrocode} % \item Yi Radicals (彝文字根) % \begin{macrocode} "A490 -> "A4CF , % \end{macrocode} % \item Hangul Syllables (谚文音节) % \begin{macrocode} "AC00 -> "D7AF , % \end{macrocode} % \item CJK Compatibility Ideographs (中日韩兼容表意文字) % \begin{macrocode} "F900 -> "FAFF , % \end{macrocode} % \item Vertical Forms (竖排形式) % \begin{macrocode} "FE10 -> "FE1F , % \end{macrocode} % \item CJK Compatibility Forms (中日韩兼容形式) % \begin{macrocode} "FE30 -> "FE4F , % \end{macrocode} % \item Halfwidth and Fullwidth Forms (半角及全角形式) % \begin{macrocode} "FF00 -> "FFEF , % \end{macrocode} % \item Ideographic Symbols and Punctuation (表意文字符号及标点) % \begin{macrocode} "16FE0 -> "16FFF , % \end{macrocode} % \item Tangut (西夏文) % \begin{macrocode} "17000 -> "187FF , % \end{macrocode} % \item Tangut Components (西夏文部首) % \begin{macrocode} "18800 -> "18AFF , % \end{macrocode} % \item Khitan Small Script (契丹小字) % \begin{macrocode} "18B00 -> "18CFF , % \end{macrocode} % \item Tangut Supplement (西夏文增补) % \begin{macrocode} "18D00 -> "18D7F , % \end{macrocode} % \item Kana Extended-B (日文假名扩展 B) % \begin{macrocode} "1AFF0 -> "1AFFF , % \end{macrocode} % \item Kana Supplement (日文假名增补) % \begin{macrocode} "1B000 -> "1B0FF , % \end{macrocode} % \item Kana Extended-A (日文假名扩展 A) % \begin{macrocode} "1B100 -> "1B12F , % \end{macrocode} % \item Small Kana Extension (小型日文假名扩展) % \begin{macrocode} "1B130 -> "1B16F , % \end{macrocode} % \item Nushu (女书) % \begin{macrocode} "1B170 -> "1B2FF , % \end{macrocode} % \item Enclosed Ideographic Supplement (带圈表意文字增补) % \begin{macrocode} "1F200 -> "1F2FF , % \end{macrocode} % \item CJK Unified Ideographs Extension-B (中日韩统一表意文字扩展 B) % \begin{macrocode} "20000 -> "2A6DF , % \end{macrocode} % \item CJK Unified Ideographs Extension-C (中日韩统一表意文字扩展 C) % \begin{macrocode} "2A700 -> "2B73F , % \end{macrocode} % \item CJK Unified Ideographs Extension-D (中日韩统一表意文字扩展 D) % \begin{macrocode} "2B740 -> "2B81F , % \end{macrocode} % \item CJK Unified Ideographs Extension-E (中日韩统一表意文字扩展 E) % \begin{macrocode} "2B820 -> "2CEAF , % \end{macrocode} % \item CJK Unified Ideographs Extension-F (中日韩统一表意文字扩展 F) % \begin{macrocode} "2CEB0 -> "2EBEF , % \end{macrocode} % \item CJK Compatibility Ideographs Supplement (中日韩兼容表意文字增补) % \begin{macrocode} "2F800 -> "2FA1F , % \end{macrocode} % \item CJK Unified Ideographs Extension-G (中日韩统一表意文字扩展 G) % \begin{macrocode} "30000 -> "3134F % \end{macrocode} % \end{itemize} % \begin{macrocode} } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_CM_chars_clist} % \changes{v3.3.1}{2015/01/22}{补充音调符号。} % 包括日文假名浊点和异体字选择符。组合标识是最好是归入 256 类,即透明类,不会影响 % 状态。但也会产生一定问题。比如下面的例子,位于行尾的“二”造成分组不匹配。 % \begin{verbatim} % \XeTeXinterchartokenstate=1 % \XeTeXcharclass`二=256 % \XeTeXinterchartoks 255 1 = {\bgroup} % \XeTeXinterchartoks 1 255 = {\egroup} % \XeTeXinterchartoks 1 1 = {x} % \font\zhfont="SimSun" % \zhfont % 一二三二 % \bye % \end{verbatim} % \begin{macrocode} \clist_const:Nn \c_@@_CM_chars_clist { % \end{macrocode} % \begin{itemize}[nosep,leftmargin=0pt] % \item Diacritics (音调符号) % \begin{macrocode} "302A -> "302F , % \end{macrocode} % \item 日文假名浊点 % \begin{macrocode} "3099 -> "309A , % \end{macrocode} % \item Variation Selectors (异体字选择符) % \begin{macrocode} "FE00 -> "FE0F , % \end{macrocode} % \item Variation Selectors Supplement (异体字选择符增补) % \begin{macrocode} "E0100 -> "E01EF % \end{macrocode} % \end{itemize} % \begin{macrocode} } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_HangulJamo_chars_clist} % 朝鲜文字母。 % \begin{macrocode} \clist_const:Nn \c_@@_HangulJamo_chars_clist { % \end{macrocode} % \begin{itemize}[nosep,leftmargin=0pt] % \item Hangul Jamo (谚文字母) % \begin{macrocode} "1100 -> "11FF , % \end{macrocode} % \item Hangul Jamo Extended-A (谚文扩展 A) % \begin{macrocode} "A960 -> "A97F , % \end{macrocode} % \item Hangul Jamo Extended-B (谚文扩展 B) % \begin{macrocode} "D7B0 -> "D7FF % \end{macrocode} % \end{itemize} % \begin{macrocode} } % \end{macrocode} % \end{variable} % % \subsection{字符类别处理} % % \begin{macro}[int]{\xeCJK_class_num:n} % |#1| 为字符类别名称,用于取得字符类别对应的编号。 % \begin{macrocode} \cs_new:Npn \xeCJK_class_num:n #1 { \use:c { \@@_class_csname:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKDeclareCharClass} % \begin{macrocode} \NewDocumentCommand \xeCJKDeclareCharClass { s > { \TrimSpaces } m m } { \xeCJK_declare_char_class:nn {#2} {#3} \IfBooleanT {#1} { \xeCJKResetPunctClass } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_declare_char_class:nn,\xeCJK_declare_char_class:nN} % \begin{macro}{\@@_set_char_class_aux:Nnw} % 用于设置字符所属的类别,|#1| 为类别名称,|#2| 为字符的 |Unicode|,相邻字符用 % 半角逗号隔开,支持类似 |"1100 -> "11FF| 起止范围的使用方式。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_declare_char_class:nn #1#2 { \clist_set:Nx \l_@@_tmp_clist {#2} \xeCJK_declare_char_class:nN {#1} \l_@@_tmp_clist } \cs_new_protected:Npn \xeCJK_declare_char_class:nN #1#2 { \clist_gconcat:ccN { g_@@_#1_range_clist } { g_@@_#1_range_clist } #2 \clist_map_inline:Nn #2 { \str_if_eq:nnF {##1} { -> } { \@@_set_char_class_aux:Nnw \xeCJK_set_char_class:nnn {##1} { \xeCJK_class_num:n {#1} } } } \xeCJK_set_char_class:nnn { "3099 } { "309A } { \xeCJK_class_num:n { CM } } } \NewDocumentCommand \@@_set_char_class_aux:Nnw { m > { \SplitArgument { 1 } { -> } } m } { #1 #2 } \cs_generate_variant:Nn \clist_gconcat:NNN { cc } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_check_num_range:nnNN} % \begin{macrocode} \cs_new_protected:Npn \@@_check_num_range:nnNN #1#2#3#4 { \bool_lazy_or:nnTF { \tl_if_blank_p:n {#1} } { \tl_if_blank_p:n {#2} } { \int_set:Nn #3 { \tl_if_blank:nTF {#1} {#2} {#1} } \int_set_eq:NN #3 #4 } { \int_set:Nn #3 { \int_min:nn {#1} { \tl_if_novalue:nTF {#2} {#1} {#2} } } \int_set:Nn #4 { \int_max:nn {#1} { \tl_if_novalue:nTF {#2} {#1} {#2} } } } } % \end{macrocode} % \end{macro} % % \changes{v3.2.3}{2013/06/08}{不再改变 CJK 字符类的 \tn{catcode}。} % \changes{v3.2.7}{2013/08/29}{修正 \file{unicode-letters.tex} 中谚文符号 % \tn{catcode} 不准的问题。} % \begin{macrocode} \token_if_letter:NF ^^^^ac00 { \int_set:Nn \l_@@_begin_int { "AC00 } \int_set:Nn \l_@@_end_int { "D7A3 } \xeCJK_int_until_do:nn { \l_@@_begin_int > \l_@@_end_int } { \char_set_catcode_letter:n { \l_@@_begin_int } \int_incr:N \l_@@_begin_int } } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_set_char_class:nnn} % \changes{v3.1.1}{2012/12/05}{在文档中设置字符类别时不重复设置 \tn{catcode}。} % 设置字符类别,|#1| 和 |#2| 为字符类别起止的 |Unicode|,|#3| 为类别名称对应编号。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_set_char_class:nnn #1#2#3 { \@@_check_num_range:nnNN {#1} {#2} \l_@@_begin_int \l_@@_end_int \int_set:Nn \l_@@_tmp_int {#3} \xeCJK_int_until_do:nn { \l_@@_begin_int > \l_@@_end_int } { \tex_XeTeXcharclass:D \l_@@_begin_int = \l_@@_tmp_int \int_incr:N \l_@@_begin_int } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_char_class_eq:nn} % \changes{v3.1.1}{2012/12/06}{交换参数的顺序。} % 将字符类 |#1| 中的字符全部设置成字符类 |#2|。只适用于 |#1| 的字符类范围为离散的 % 逗号列表的情况。 % \begin{macrocode} \cs_new_protected:Npn \@@_set_char_class_eq:nn #1#2 { \int_set:Nn \l_@@_tmp_int { \xeCJK_class_num:n {#2} } \clist_map_inline:cn { c_@@_#1_chars_clist } { \tex_XeTeXcharclass:D ##1 = \l_@@_tmp_int } } % \end{macrocode} % \end{macro} % % \begin{macro}{\normalspacedchars} % 声明前后不加间距的字符。 % \begin{macrocode} \NewDocumentCommand \normalspacedchars { m } { \tl_map_inline:nn {#1} { \tex_XeTeXcharclass:D `##1 = \xeCJK_class_num:n { NormalSpace } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKResetPunctClass} % 用于重置标点符号所属的字符类。 % \begin{macrocode} \NewDocumentCommand \xeCJKResetPunctClass { } { \clist_gclear:N \g_@@_HalfLeft_range_clist \clist_gclear:N \g_@@_HalfRight_range_clist \clist_gclear:N \g_@@_FullLeft_range_clist \clist_gclear:N \g_@@_FullRight_range_clist \xeCJK_declare_char_class:nN { HalfLeft } \c_@@_HalfLeft_chars_clist \xeCJK_declare_char_class:nN { HalfRight } \c_@@_HalfRight_chars_clist \xeCJK_declare_char_class:nN { FullLeft } \c_@@_FullLeft_chars_clist \xeCJK_declare_char_class:nN { FullRight } \c_@@_FullRight_chars_clist } % \end{macrocode} % \end{macro} % % % \begin{macro}{\xeCJKResetCharClass} % 用于恢复 \pkg{xeCJK} 对字符类别的设置。 % \begin{macrocode} \NewDocumentCommand \xeCJKResetCharClass { } { \clist_gclear:N \g_@@_CJK_range_clist \clist_gclear:N \g_@@_NormalSpace_range_clist \clist_gclear:N \g_@@_CM_range_clist \clist_gclear:N \g_@@_HangulJamo_range_clist \xeCJK_declare_char_class:nN { CJK } \c_@@_CJK_chars_clist \xeCJK_declare_char_class:nN { NormalSpace } \c_@@_NormalSpace_chars_clist \xeCJK_declare_char_class:nN { CM } \c_@@_CM_chars_clist \xeCJK_declare_char_class:nN { HangulJamo } \c_@@_HangulJamo_chars_clist \xeCJKResetPunctClass } % \end{macrocode} % \end{macro} % % 设置字符类别。 % \begin{macrocode} \xeCJKResetCharClass % \end{macrocode} % % \begin{macro}[int]{\xeCJK_inter_class_toks:nnn} % 在相邻类别之间插入内容。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_inter_class_toks:nnn #1#2#3 { \tex_XeTeXinterchartoks:D \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} = {#3} } \cs_generate_variant:Nn \xeCJK_inter_class_toks:nnn { nne } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_get_inter_class_toks:nn} % 取出相邻类别之间的内容。 % \begin{macrocode} \cs_new:Npn \xeCJK_get_inter_class_toks:nn #1#2 { \tex_the:D \tex_XeTeXinterchartoks:D \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_clear_inter_class_toks:nn} % 清除相邻类别之间的内容。注意,直接赋空值可能会导致 \XeTeX 崩溃。例如 % \begin{verbatim} % \XeTeXinterchartokenstate = 1 % \XeTeXcharclass`A=10 % \XeTeXinterchartoks 10 10 = {xx} % \begingroup % \XeTeXinterchartoks 10 10 = {} AA % \endgroup % \bye % \end{verbatim} % 如果把上述例子中的分组 \tn{begingroup} 和 \tn{endgroup} 去掉,则结果正常,甚为怪异。 % 此处 \XeTeX 的 bug 已经在 0.999992 版中修复^^A % \footnote{\url{http://tug.org/svn/texlive?view=revision&revision=53880}}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_clear_inter_class_toks:nn #1#2 { \xeCJK_inter_class_toks:nnn {#1} {#2} { \prg_do_nothing: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_pre_inter_class_toks:nnn} % 在相邻类别之间已有的内容前增加内容。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_pre_inter_class_toks:nnn #1#2#3 { \xeCJK_inter_class_toks:nne {#1} {#2} { \exp_not:n {#3} \xeCJK_get_inter_class_toks:nn {#1} {#2} } } \cs_generate_variant:Nn \xeCJK_pre_inter_class_toks:nnn { nne } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_app_inter_class_toks:nnn} % 在相邻类别之间已有的内容后追加内容。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_app_inter_class_toks:nnn #1#2#3 { \xeCJK_inter_class_toks:nne {#1} {#2} { \xeCJK_get_inter_class_toks:nn {#1} {#2} \exp_not:n {#3} } } \cs_generate_variant:Nn \xeCJK_app_inter_class_toks:nnn { nne } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_copy_inter_class_toks:nnnn} % 将 |#3| 和 |#4| 之间的内容复制到 |#1| 和 |#2| 之间。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_copy_inter_class_toks:nnnn #1#2#3#4 { \tl_set:Nx \l_@@_tmp_tl { \xeCJK_get_inter_class_toks:nn {#3} {#4} } \tl_if_empty:NTF \l_@@_tmp_tl { \tl_set:Nx \l_@@_tmp_tl { \xeCJK_get_inter_class_toks:nn {#1} {#2} } \tl_if_empty:NF \l_@@_tmp_tl { \xeCJK_clear_inter_class_toks:nn {#1} {#2} } } { \xeCJK_inter_class_toks:nne {#1} {#2} { \exp_not:o \l_@@_tmp_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_replace_inter_class_toks:nnnn} % 将 |#1| 和 |#2| 之间出现的 |#3| 用 |#4| 替换。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_replace_inter_class_toks:nnnn #1#2#3#4 { \tl_set:Nx \l_@@_tmp_tl { \xeCJK_get_inter_class_toks:nn {#1} {#2} } \tl_if_empty:NF \l_@@_tmp_tl { \tl_replace_all:Nnn \l_@@_tmp_tl {#3} {#4} \xeCJK_inter_class_toks:nne {#1} {#2} { \exp_not:o \l_@@_tmp_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_clear_Boundary_and_CJK_toks:} % \changes{v3.4.2}{2016/10/19}{提高效率,避免重复循环。} % 清除边界与 CJK 文字、全角左右标点之间的内容。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_clear_Boundary_and_CJK_toks: { } \cs_new_protected:Npn \@@_update_clear_toks:n #1 { \cs_gset_protected:Npx \xeCJK_clear_Boundary_and_CJK_toks: { \exp_not:o { \xeCJK_clear_Boundary_and_CJK_toks: } \tex_XeTeXinterchartoks:D \xeCJK_class_num:n { Boundary } ~ \xeCJK_class_num:n {#1} = { \exp_not:N \prg_do_nothing: } } } % \end{macrocode} % \end{macro} % % \begin{variable} % {\g_@@_base_class_seq,\g_@@_non_CJK_class_seq,\g_@@_CJK_class_seq} % 保存宏包预先定义的字符类。 % \begin{macrocode} \seq_new:N \g_@@_base_class_seq \seq_gset_eq:NN \g_@@_base_class_seq \g_@@_class_seq \seq_new:N \g_@@_non_CJK_class_seq \seq_gset_from_clist:Nn \g_@@_non_CJK_class_seq { Default , HalfLeft , HalfRight , NormalSpace , Boundary } \seq_new:N \g_@@_CJK_class_seq \cs_new_protected:Npn \@@_save_CJK_class:n #1 { \seq_gput_right:Nn \g_@@_CJK_class_seq {#1} \tl_const:cn { \@@_CJK_class_tl:n { \use:c { \@@_class_csname:n {#1} } } } {#1} \@@_update_clear_toks:n {#1} } \clist_map_function:nN { CJK , FullLeft , FullRight , CM , HangulJamo } \@@_save_CJK_class:n % \end{macrocode} % \end{variable} % % \subsection{字符输出规则} % % \begin{center} % \begin{tabular}{l*9c} % \toprule % & |Default| & |CJK| & |FullL| & |FullR| & |HalfL| % & |HalfR| & |Normal| & |Bound| & |CM| \\ \midrule % |Default| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & \tokslink{def-bound} % & \tokslink{def-cm}\\ % |CJK| % & \tokslink{def-cjk} % & \tokslink{cjk-cjk} % & \tokslink{cjk-fl-fr} % & \tokslink{cjk-fl-fr} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{cjk-bound} % &\\ % |FullLeft| % & \tokslink{def-cjk} % & \tokslink{fl-fr-others} % & \tokslink{cjk-fl-fr} % & \tokslink{cjk-fl-fr} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{fl-fr-bound} % & \tokslink{def-cm}\\ % |FullRight| % & \tokslink{def-cjk} % & \tokslink{fl-fr-others} % & \tokslink{cjk-fl-fr} % & \tokslink{cjk-fl-fr} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{fl-fr-bound} % & \tokslink{def-cm}\\ % |HalfLeft| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & % & \tokslink{def-cm}\\ % |HalfRight| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & \tokslink{def-bound} % & \tokslink{def-cm}\\ % |NormalSpace| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & \tokslink{ns-bound} % & \tokslink{def-cm}\\ % |Boundary| % & \tokslink{bound-def} % & \tokslink{bound-cjk} % & \tokslink{bound-fl-fr} % & \tokslink{bound-fl-fr} % & \tokslink{bound-def} % & % & \tokslink{bound-ns} % & % & \tokslink{def-cm}\\ % |CM| % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm} % & \tokslink{def-cm}\\ % \bottomrule % \end{tabular} % \end{center} % % \changes{v3.4.2}{2016/10/19}{避免在破折号之间折行。} % % \begin{macro}[int]{\xeCJK_class_group_begin:,\xeCJK_class_group_end:} % 在 CJK 类开始时,设置 \tn{XeTeXdashbreakstate} 为零,避免破折号之间的折行。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_class_group_begin: { \c_group_begin_token \bool_set_true:N \l_@@_CJK_group_bool \xeCJK_reset_space_factor: \int_zero:N \tex_XeTeXdashbreakstate:D } \bool_new:N \l_@@_CJK_group_bool \cs_new_eq:NN \xeCJK_class_group_end: \c_group_end_token % \end{macrocode} % \end{macro} % % \hypertarget{def-cm}{\texttt{CM}} 字符类与 |CJK| 字符类基本相同,只是从 |CJK| % 转移到 |CM| 时,不加入任何内容。 % \begin{macrocode} \AtEndOfPackage { \seq_map_inline:Nn \g_@@_class_seq { \str_if_eq:nnTF {#1} { CM } { \xeCJK_copy_inter_class_toks:nnnn { CM } {#1} { CJK } { CJK } } { \xeCJK_copy_inter_class_toks:nnnn { CM } {#1} { CJK } {#1} \str_if_eq:nnF {#1} { CJK } { \xeCJK_copy_inter_class_toks:nnnn {#1} { CM } {#1} { CJK } } } } } % \end{macrocode} % % \hypertarget{def-HJ}{\texttt{HangulJamo}} 字符类与 |CJK| 字符类基本相同,只是 % |HangulJamo| 类之间不加入任何内容。 % \begin{macrocode} \AtEndOfPackage { \seq_map_inline:Nn \g_@@_class_seq { \str_if_eq:nnF {#1} { HangulJamo } { \xeCJK_copy_inter_class_toks:nnnn { HangulJamo } {#1} { CJK } {#1} \xeCJK_copy_inter_class_toks:nnnn {#1} { HangulJamo } {#1} { CJK } } } } % \end{macrocode} % % \hypertarget{def-cjk}{} % \begin{macrocode} \clist_map_inline:nn { Default , HalfLeft , HalfRight , NormalSpace } { \xeCJK_inter_class_toks:nnn {#1} { CJK } { \xeCJK_class_group_begin: \xeCJK_select_font: \xeCJK_clear_inter_class_toks:nn {#1} { CJK } \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_fallback_symbol:NN \CJKsymbol } \xeCJK_inter_class_toks:nnn { CJK } {#1} { \xeCJK_class_group_end: } } % \end{macrocode} % % \hypertarget{bound-def}{} % \begin{macrocode} \clist_map_inline:nn { Default , HalfLeft } { \xeCJK_inter_class_toks:nnn { Boundary } {#1} { \xeCJK_Boundary_and_Default: } \xeCJK_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_Boundary_and_Default:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_Boundary_and_Default: { \xeCJK_check_for_ecglue: } \cs_new_protected:Npn \@@_check_for_xecglue: { \@@_if_last_glue:TF { \@@_replace_space: } { \@@_check_for_ecglue: } } \cs_new_protected:Npn \@@_check_for_ecglue: { \xeCJK_if_last_node:nTF { CJK } { \use_i:nn } { \xeCJK_if_last_node:nTF { CJK-widow } } { \xeCJK_remove_node: \CJKecglue } { \xeCJK_if_last_node:nT { CJK-space } { \xeCJK_remove_node: \xeCJK_space_or_xecglue: } } } \cs_new_eq:NN \xeCJK_check_for_ecglue: \@@_check_for_ecglue: % \end{macrocode} % \end{macro} % % \changes{v3.4.0}{2016/05/08}{改进 \texttt{xCJKecglue} 的实现。} % % \begin{macro}{\@@_replace_space:} % 将空格替换为 \tn{CJKecglue}。注意由 \tn{leaders} 等产生的 glue,并不能正确地还回去。 % 好在 \LaTeXe{} 中常用的 \tn{hrulefill} 和 \tn{dotfill} 定义末尾都有 |\kern\z@| 保护。 % \begin{macrocode} \cs_new_protected:Npn \@@_replace_space: { \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D \tex_unskip:D \xeCJK_if_last_node:nTF { CJK-space } { \xeCJK_remove_node: \CJKecglue } { \xeCJK_if_last_node:nTF { CJK } { \skip_if_eq:nnTF { \l_@@_last_skip } { \c_xeCJK_space_skip_tl } { \xeCJK_remove_node: \CJKecglue } { \skip_horizontal:N \l_@@_last_skip } } { \skip_horizontal:N \l_@@_last_skip } } } \skip_new:N \l_@@_last_skip % \end{macrocode} % \end{macro} % % \hypertarget{def-bound}{} % \begin{macrocode} \clist_map_inline:nn { Default , HalfRight } { \xeCJK_inter_class_toks:nnn {#1} { Boundary } { \int_gset_eq:NN \g_@@_space_factor_int \tex_spacefactor:D \peek_meaning_remove:NTF \tex_italiccorrection:D { \tex_italiccorrection:D { \xeCJK_make_node:n { default } } } { \token_if_space:NTF \l_peek_token { \xeCJK_make_space_node: } { { \xeCJK_make_node:n { default } } } } } \xeCJK_pre_inter_class_toks:nnn {#1} { CJK } { \CJKecglue } } % \end{macrocode} % % \changes{v3.2.5}{2013/07/10} % {修正 \texttt{CJK} 和 \texttt{NormalSpace} 字符类之间因为边界造成的间距不正确的问题。} % % \hypertarget{bound-ns}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { Boundary } { NormalSpace } { \xeCJK_Boundary_and_NormalSp: } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_Boundary_and_NormalSp:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_Boundary_and_NormalSp: { \xeCJK_check_for_ecglue_normalsp: } \cs_new_protected:Npn \@@_check_for_xecglue_normalsp: { \@@_if_last_glue:TF { \@@_replace_space: } { \@@_check_for_ecglue_normalsp: } } \cs_new_protected:Npn \@@_check_for_ecglue_normalsp: { \xeCJK_if_last_node:nT { CJK-space } { \xeCJK_remove_node: \xeCJK_space_or_xecglue: } } \cs_new_eq:NN \xeCJK_check_for_ecglue_normalsp: \@@_check_for_ecglue_normalsp: % \end{macrocode} % \end{macro} % % \hypertarget{ns-bound}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { NormalSpace } { Boundary } { \int_gset_eq:NN \g_@@_space_factor_int \tex_spacefactor:D \peek_meaning_remove:NTF \tex_italiccorrection:D { \tex_italiccorrection:D { \xeCJK_make_node:n { normalspace } } } { \token_if_space:NTF \l_peek_token { \xeCJK_make_space_node: } { { \xeCJK_make_node:n { normalspace } } } } } % \end{macrocode} % % \hypertarget{bound-cjk}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_check_for_glue: \xeCJK_class_group_begin: \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_select_font: \xeCJK_fallback_symbol:NN \CJKsymbol } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_check_for_glue:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_for_glue: { \@@_if_last_kern:TF { \@@_check_for_glue_auxi: } { \@@_if_last_math:TF { \xeCJK_remove_node: \CJKecglue } { \@@_check_for_glue_auxii: } } } \cs_new_protected:Npn \@@_check_for_glue_auxi: { \dim_case:nn { \tex_lastkern:D } { { \@@_node:n { CJK } } { \xeCJK_remove_node: \CJKglue } { \@@_node:n { CJK-space } } { \xeCJK_remove_node: \@@_ccglue_or_space: } { \@@_node:n { CJK-widow } } { \xeCJK_remove_node: \xeCJK_widow_penalty: \CJKglue } { \@@_node:n { default } } { \xeCJK_remove_node: \CJKecglue } } } \cs_new_protected:Npn \@@_check_for_glue_auxii: { \xeCJK_if_last_punct:TF { \@@_check_for_glue_auxiii: } { \xeCJK_check_for_xglue: } } \cs_new_protected:Npn \@@_check_for_glue_auxiii: { \bool_if:NT \l_@@_last_penalty_bool { \tex_penalty:D \l_@@_last_penalty_int } \skip_horizontal:N \l_@@_last_skip \tl_if_eq:NNF \l_@@_aligni_tl \c_@@_left_tl { \CJKglue } } \cs_new_eq:NN \xeCJK_check_for_xglue: \prg_do_nothing: \cs_new_protected:Npn \@@_check_for_xglue: { \@@_if_last_glue:TF { \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D \tex_unskip:D \xeCJK_if_last_node:nTF { CJK-space } { \xeCJK_remove_node: \@@_ccglue_or_space: } { \xeCJK_if_last_node:nTF { default-space } { \xeCJK_remove_node: \CJKecglue } { \@@_check_for_xglue_aux: } } } } \cs_new_protected:Npn \@@_check_for_xglue_aux: { \skip_if_eq:nnTF { \l_@@_last_skip } { \c_xeCJK_space_skip_tl } { \xeCJK_if_last_node:nTF { CJK } { \xeCJK_remove_node: \@@_ccglue_or_space: } { \xeCJK_if_last_node:nTF { default } { \xeCJK_remove_node: \CJKecglue } { \@@_if_last_math:TF { \CJKecglue } { \skip_horizontal:N \l_@@_last_skip } } } } { \skip_horizontal:N \l_@@_last_skip } } \cs_new_protected:Npn \@@_ccglue_or_space: { \CJKglue } % \end{macrocode} % \end{macro} % % \changes{v3.9.1}{2022/08/02}{简化部分内部实现。} % % \begin{macro}[TF]{ % \@@_if_last_none:, % \@@_if_last_hlist:, % \@@_if_last_math:, % \@@_if_last_glue:, % \@@_if_last_kern:, % \@@_if_last_penalty:} % 一些 \hologo{eTeX} 结点判定函数。 % \begin{macrocode} \group_begin: \cs_set:Npn \@@_tmp:nn #1 { \exp_args:Ncc \@@_tmp_aux:NNn { @@_if_last_ #1 : } { c_@@_ #1 _node } } \cs_set:Npn \@@_tmp_aux:NNn #1#2#3 { \int_const:Nn #2 {#3} \prg_new_conditional:Npnn #1 { T , F , TF } { \if_int_compare:w \tex_lastnodetype:D = #2 \prg_return_true: \else: \prg_return_false: \fi: } } \@@_tmp:nn { none } { -1 } \@@_tmp:nn { hlist } { 1 } \@@_tmp:nn { math } { 10 } \@@_tmp:nn { glue } { 11 } \@@_tmp:nn { kern } { 12 } \@@_tmp:nn { penalty } { 13 } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,int]{\xeCJK_if_last_node:n} % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_last_node:n #1 { p , T , F , TF } { \if_dim:w \cs_if_exist_use:cTF { c_@@_#1_node_dim } { = \tex_lastkern:D } { \use:c { c_@@_#1_node_skip } = \tex_lastskip:D } \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \changes{v3.1.0}{2012/11/14}{删除多余的 \texttt{default-itcorr} 结点。} % \changes{v3.2.4}{2013/07/03}{尽量移除用作判断标志的 \tn{kern}。} % % \begin{macro}[int]{\xeCJK_declare_node:n,\xeCJK_make_node:n} % 用于判断插入的各种 |kern| 和 |glue|。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_declare_node:n #1 { \int_gincr:N \g_@@_node_int \dim_if_exist:cTF { c_@@_#1_node_dim } { \dim_gset:cn } { \dim_const:cn } { c_@@_#1_node_dim } { \g_@@_node_int sp } } \cs_new_protected:Npn \xeCJK_declare_glue_node:n #1 { \int_gincr:N \g_@@_node_int \skip_if_exist:cTF { c_@@_#1_node_skip } { \skip_gset:cn } { \skip_const:cn } { c_@@_#1_node_skip } { \g_@@_node_int sp } } \int_new:N \g_@@_node_int \int_gset:Nn \g_@@_node_int { 10 } \cs_new_protected:Npn \xeCJK_make_node:n #1 { \exp_args:Nc \@@_make_node:N { c_@@_#1_node_dim } } \cs_new:Npn \@@_node:n #1 { \use:c { c_@@_#1_node_dim } } \cs_new:Npn \@@_gule_node:n #1 { \use:c { c_@@_#1_node_skip } } \cs_new_protected:Npn \@@_make_node:N #1 { \tex_kern:D - #1 \tex_kern:D #1 } \cs_new_protected:Npn \xeCJK_remove_node: { \@@_if_last_kern:TF { \tex_unkern:D \tex_unkern:D } { \@@_if_last_glue:T { \tex_unskip:D \tex_unskip:D } } } \xeCJK_declare_node:n { CJK } \xeCJK_declare_node:n { CJK-space } \xeCJK_declare_node:n { default } \xeCJK_declare_node:n { CJK-widow } \xeCJK_declare_node:n { normalspace } \xeCJK_declare_glue_node:n { default-space } % \end{macrocode} % \end{macro} % % \changes{v3.9.0}{2022/06/06}{修复西文的 character protrusion 功能。} % % \begin{macro}[int]{\xeCJK_make_space_node:} % 用于判断插入空格之前的 node,默认为空,只有用户设置了 \opt{xCJKecglue} 选项才有意义。 % 需要使用 |glue| 来标记,使用 |kern| 会影响 character protrusion 功能。 % \begin{macrocode} \cs_new_eq:NN \xeCJK_make_space_node: \prg_do_nothing: \cs_new_protected:Npx \@@_make_space_node: { \tex_hskip:D - \@@_gule_node:n { default-space } \tex_hskip:D \@@_gule_node:n { default-space } } % \end{macrocode} % \end{macro} % % \begin{macro}{CJKglue} % CJK 文字之间插入的 |glue|。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKglue .code:n = { \cs_set_protected:Npn \CJKglue {#1} \xeCJK_glue_to_skip:nN {#1} \l_@@_ccglue_skip } } \skip_new:N \l_@@_ccglue_skip % \end{macrocode} % \end{macro} % % \changes{v3.2.16}{2014/12/16}{整理 \texttt{xCJKecglue} 的部分代码。} % % \begin{macro}{CJKecglue,xCJKecglue} % CJK 与西文和数学行内数学公式之间自动添加的空白。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKecglue .code:n = { \cs_set_protected:Npn \CJKecglue {#1} \xeCJK_glue_to_skip:nN {#1} \l_@@_ecglue_skip } , xCJKecglue .choice: , xCJKecglue / true .code:n = { \bool_set_true:N \l_@@_xecglue_bool \cs_set_eq:NN \xeCJK_space_or_xecglue: \CJKecglue \cs_set_eq:NN \xeCJK_make_space_node: \@@_make_space_node: \cs_set_eq:NN \xeCJK_check_for_xglue: \@@_check_for_xglue: \cs_set_eq:NN \xeCJK_check_for_ecglue: \@@_check_for_xecglue: \cs_set_eq:NN \xeCJK_check_for_ecglue_normalsp: \@@_check_for_xecglue_normalsp: } , xCJKecglue / false .code:n = { \bool_set_false:N \l_@@_xecglue_bool \cs_set_eq:NN \xeCJK_space_or_xecglue: \xeCJK_space_glue: \xeCJK_cs_clear:N \xeCJK_make_space_node: \xeCJK_cs_clear:N \xeCJK_check_for_xglue: \cs_set_eq:NN \xeCJK_check_for_ecglue: \@@_check_for_ecglue: \cs_set_eq:NN \xeCJK_check_for_ecglue_normalsp: \@@_check_for_ecglue_normalsp: } , xCJKecglue / unknown .code:n = { \bool_set_true:N \l_@@_xecglue_bool \cs_set_protected:Npn \CJKecglue {#1} \xeCJK_glue_to_skip:nN {#1} \l_@@_ecglue_skip \cs_set_eq:NN \xeCJK_space_or_xecglue: \CJKecglue \cs_set_eq:NN \xeCJK_make_space_node: \@@_make_space_node: \cs_set_eq:NN \xeCJK_check_for_xglue: \@@_check_for_xglue: \cs_set_eq:NN \xeCJK_check_for_ecglue: \@@_check_for_xecglue: \cs_set_eq:NN \xeCJK_check_for_ecglue_normalsp: \@@_check_for_xecglue_normalsp: } , xCJKecglue .default:n = { true } } \cs_new_eq:NN \xeCJK_space_glue: \c_space_tl \skip_new:N \l_@@_ecglue_skip \bool_new:N \l_@@_xecglue_bool % \end{macrocode} % \end{macro} % % \changes{v3.4.1}{2016/05/21}{修复 \texttt{CJKspace} 功能失效。} % \changes{v3.7.2}{2019/04/07}{简化 \texttt{CJKspace} 的实现,并修复错误。} % % \begin{macro}{CJKspace} % 是否保留 CJK 文字间的空白,默认不保留。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKspace .choice: , CJKspace / true .code:n = { \bool_set_true:N \l_@@_reserve_space_bool \cs_set_protected:Npn \@@_ccglue_or_space: { \xeCJK_space_glue: } } , CJKspace / false .code:n = { \bool_set_false:N \l_@@_reserve_space_bool \cs_set_protected:Npn \@@_ccglue_or_space: { \CJKglue } } , CJKspace .default:n = { true } , space .meta:n = { CJKspace = true } , nospace .meta:n = { CJKspace = false } } \bool_new:N \l_@@_reserve_space_bool % \end{macrocode} % \end{macro} % % \hypertarget{cjk-bound}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { CJK } { Boundary } { \xeCJK_CJK_and_Boundary:w } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_CJK_and_Boundary:w} % \changes{v3.2.6}{2013/08/05}{更好的处理边界是 \tn{relax} 的情况。} % 当边界是 \tn{relax} 的时候,它可能是由 |\csname ...\endcsname| 的形式产生的, % 这样就可能出现问题\footnote{参见 \url{http://bbs.ctex.org/forum.php?mod=viewthread&tid=71563}。}。 % 原来是都在未定义控制序列前都加上 \cs{exp_not:N},现在是采用分组结束后手工恢复的方式。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_CJK_and_Boundary:w { \xeCJK_peek_catcode_ignore_spaces:NTF \c_math_toggle_token { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \xeCJK_class_group_end: \xeCJK_space_or_xecglue: } { \xeCJK_class_group_end: \CJKecglue } } { \group_align_safe_begin: \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \token_if_macro:NTF \l_peek_token { \@@_boundary_reserve_space: } { \@@_boundary_group_end:n { CJK-space } } } { \token_if_eq_meaning:NNTF \l_peek_token \scan_stop: { \@@_CJK_and_Boundary_relax:N } { \@@_boundary_group_end:n { CJK } } } } } \cs_new_protected:Npn \@@_boundary_reserve_space: { \@@_boundary_group_end:n { CJK-space } \xeCJK_space_or_xecglue: } \cs_new_protected:Npn \@@_CJK_and_Boundary_relax:N #1 { \@@_boundary_group_end:n { CJK } \token_if_eq_meaning:NNTF #1 \scan_stop: {#1} { \cs_set_eq:NN #1 \scan_stop: #1 } } \cs_new_protected:Npn \@@_boundary_group_end:n #1 { \group_align_safe_end: \xeCJK_class_group_end: { \xeCJK_make_node:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_ignore_spaces:w} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_ignore_spaces:w { \xeCJK_peek_catcode_ignore_spaces:NTF \c_math_toggle_token { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \xeCJK_space_or_xecglue: } { \CJKecglue } } { \bool_if:NT \l_@@_peek_ignore_spaces_bool { \dim_case:nn { \tex_lastkern:D } { { \@@_node:n { CJK } } { \xeCJK_remove_node: \xeCJK_make_node:n { CJK-space } } { \@@_node:n { default } } { \xeCJK_remove_node: \xeCJK_make_space_node: } } \group_align_safe_begin: \token_if_macro:NTF \l_peek_token { \@@_reserve_space_aux: } { \group_align_safe_end: } } } } \cs_new_protected:Npn \@@_reserve_space_aux: { \group_align_safe_end: \xeCJK_space_or_xecglue: } % \end{macrocode} % \end{macro} % % \hypertarget{cjk-cjk}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { CJK } { CJK } { \xeCJK_CJK_and_CJK:N } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_CJK_and_CJK:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_CJK_and_CJK:N { \CJKglue \xeCJK_fallback_symbol:NN \CJKsymbol } % \end{macrocode} % \end{macro} % % \hypertarget{fl-fr-others}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { FullLeft } { CJK } { \xeCJK_FullLeft_and_CJK: \xeCJK_fallback_symbol:NN \CJKsymbol } \xeCJK_inter_class_toks:nnn { FullRight } { CJK } { \xeCJK_FullRight_and_CJK: \xeCJK_fallback_symbol:NN \CJKsymbol } \seq_map_inline:Nn \g_@@_non_CJK_class_seq { \clist_map_inline:nn { FullLeft , FullRight } { \xeCJK_inter_class_toks:nne {#1} {##1} { \exp_not:c { xeCJK_Default_and_##1:nN } {#1} } \xeCJK_inter_class_toks:nne {##1} {#1} { \exp_not:c { xeCJK_##1_and_Default: } } } } % \end{macrocode} % % \hypertarget{bound-fl-fr}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { Boundary } { FullLeft } { \xeCJK_Boundary_and_FullLeft:N } \xeCJK_inter_class_toks:nnn { Boundary } { FullRight } { \xeCJK_Boundary_and_FullRight:N } % \end{macrocode} % % \hypertarget{fl-fr-bound}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { FullLeft } { Boundary } { \xeCJK_FullLeft_and_Boundary: } \xeCJK_inter_class_toks:nnn { FullRight } { Boundary } { \xeCJK_FullRight_and_Boundary: } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_FullLeft_and_Boundary:} % \hypertarget{fl-fr-bound}{} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullLeft_and_Boundary: { \@@_punct_if_middle:NTF \g_@@_last_punct_tl { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \exp_after:wN \xeCJK_punct_node:N \g_@@_last_punct_tl \xeCJK_no_break: \@@_punct_glue:NN \c_@@_left_tl \g_@@_last_punct_tl } { \xeCJK_class_group_end: \exp_after:wN \xeCJK_punct_node:N \g_@@_last_punct_tl \@@_nobreak_zero_glue: } \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullRight_and_Boundary:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullRight_and_Boundary: { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \exp_after:wN \xeCJK_punct_node:N \g_@@_last_punct_tl \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_punct_node:N} % 保存标点的当前边界宽度和字符码,通过插入 \tn{kern} 实现。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_punct_node:N #1 { \@@_punct_bound_unitization:NN #1 \l_@@_tmp_dim \@@_make_node:N \l_@@_tmp_dim \dim_set:Nn \l_@@_tmp_dim { `#1 sp } \@@_make_node:N \l_@@_tmp_dim } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_punct_bound_unitization:NN} % 我们不想出现过大的 \tn{kern},因此当边界大于 \SI{1}{pt} 时,以 \cs{c_max_dim} 为标准 % 对其进行“单位化”。 % \begin{macrocode} \cs_new_protected:Npn \@@_punct_bound_unitization:NN #1#2 { \dim_set:Nn #2 { \dim_max:nn { \c_zero_dim } { \@@_use_punct_dim:nNN { bound } \c_@@_right_tl #1 } } \dim_compare:nNnF {#2} < { 1pt } { \dim_set:Nn #2 { -1pt * \dim_ratio:nn {#2} { \c_max_dim } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_punct_bound_kern:N} % \begin{macro}{\@@_punct_bound_kern:NN} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_punct_bound_kern:N #1 { \exp_after:wN \@@_punct_bound_kern:NN \g_@@_last_punct_tl #1 } \cs_new_protected:Npn \@@_punct_bound_kern:NN #1#2 { \xeCJK_get_punct_bounds:NN \l_@@_aligni_tl #1 \xeCJK_get_punct_kerning:NN #1 #2 \@@_punct_bound_unitization:NN #1 \l_@@_tmp_dim \skip_set:Nn \l_@@_punct_kern_skip { \@@_use_dim_or_skip:nNN { bound_kern } #1 #2 } \dim_compare:nNnF \l_@@_tmp_dim = \l_@@_last_bound_dim { \@@_punct_bound_kern_ratio:NN #1 #2 } \bool_if:NTF \l_@@_last_penalty_bool { \tex_penalty:D \l_@@_last_penalty_int \skip_horizontal:N } { \@@_punct_bound_kern_aux:NNN #1 #2 } \l_@@_punct_kern_skip } \skip_new:N \l_@@_punct_kern_skip % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_punct_bound_kern_ratio:NN} % 当标点前后的字体情况不一致时,按一定的比例进行压缩。 % \begin{macrocode} \cs_new_protected:Npn \@@_punct_bound_kern_ratio:NN #1#2 { \dim_set:Nn \l_@@_bound_dim { \@@_use_punct_dim:nNN { bound_width } #1 #2 } \dim_compare:nNnT \l_@@_bound_dim > \c_zero_dim { \dim_compare:nNnF \l_@@_last_bound_dim > \c_zero_dim { \dim_set:Nn \l_@@_last_bound_dim { - \l_@@_last_bound_dim * \dim_ratio:nn { \c_max_dim } { 1pt } } } \@@_punct_bound_kern_ratio_aux:N #2 } } \cs_new_protected:Npn \@@_punct_bound_kern_ratio_aux:N #1 { \skip_set:Nn \l_@@_punct_kern_skip { \l_@@_punct_kern_skip * \dim_ratio:nn { \l_@@_last_bound_dim + \@@_use_punct_dim:nNN { bound } \c_@@_left_tl #1 } { \l_@@_bound_dim } } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_nobreak_hskip:N,\@@_nobreak_hskip:n, % \@@_punct_bound_kern:N, \@@_punct_bound_breakable_kern:N} % \begin{macrocode} \cs_new_protected:Npn \@@_nobreak_hskip:N { \xeCJK_no_break: \skip_horizontal:N } \cs_new_protected:Npn \@@_nobreak_hskip:n { \xeCJK_no_break: \skip_horizontal:n } \cs_new_eq:NN \@@_punct_bound_kern:N \@@_nobreak_hskip:N \cs_new_protected:Npn \@@_punct_bound_breakable_kern:N { \tl_if_eq:NNTF \l_@@_aligni_tl \c_@@_right_tl { \tl_if_eq:NNTF \l_@@_alignii_tl \c_@@_left_tl { \skip_horizontal:N } { \@@_nobreak_hskip:N } } { \@@_nobreak_hskip:N } } \cs_new_protected:Npn \@@_punct_bound_kern_aux:NNN #1#2 { \str_if_eq:nnTF {#1} {#2} { \@@_nobreak_hskip:N } { \@@_punct_if_long:NTF #1 { \skip_horizontal:N } { \@@_punct_if_long:NTF #2 { \skip_horizontal:N } { \@@_punct_bound_kern:N } } } } % \end{macrocode} % \end{macro} % % \hypertarget{cjk-fl-fr}{} % \begin{macrocode} \clist_map_inline:nn { CJK , FullLeft , FullRight } { \clist_map_inline:nn { FullLeft , FullRight } { \xeCJK_inter_class_toks:nne {#1} {##1} { \exp_not:c { xeCJK_#1_and_##1:N } } } } % \end{macrocode} % % \begin{macro}{\@@_punct_bound_rule:NN} % 用于抹去标点符号的全部左/右空白。 % \begin{macrocode} \cs_new_protected:Npn \@@_punct_bound_rule:NN #1#2 { \tex_vrule:D width - \@@_use_punct_dim:nNN { bound } #1 #2 ~ depth \c_zero_dim height \c_zero_dim \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_punct_rule:NN} % 用于减少标点符号的左/右空白。 % \begin{macrocode} \cs_new_protected:Npn \@@_punct_rule:NN #1#2 { \tex_vrule:D width \@@_use_punct_dim:nNN { rule } #1 #2 ~ depth \c_zero_dim height \c_zero_dim \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_punct_glue:NN} % \changes{v3.2.7}{2013/08/23} % {标点符号左/右空白的伸展值不超过原始边界,收缩值不小于另一侧边界。} % 根据所选的标点处理方式在标点符号左/右增加的空白。 % \begin{macrocode} \cs_new_protected:Npn \@@_punct_glue:NN #1#2 { \@@_punct_hskip:n { \@@_use_dim_or_skip:nNN { glue } #1 #2 } } \cs_new_eq:NN \@@_punct_hskip:n \skip_horizontal:n % \end{macrocode} % \end{macro} % % \changes{v3.6.0}{2018/01/23}{总允许长标点与其他标点之间折行。} % \begin{macro}{\xeCJK_punct_kern:NN,\@@_punct_kern:NN} % 相邻两个标点之间的间距,总允许长标点与其他标点之间折行。 % \begin{macrocode} \cs_new_protected:Npn \@@_punct_kern:NN #1#2 { \str_if_eq:eeTF {#1} {#2} { \@@_punct_nobreak_kern:NN } { \@@_punct_if_long:NTF #1 { \@@_punct_breakable_kern:NN } { \@@_punct_if_long:NTF #2 { \@@_punct_breakable_kern:NN } { \@@_punct_nobreak_kern:NN } } } #1 #2 } \cs_new_eq:NN \xeCJK_punct_kern:NN \@@_punct_kern:NN % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_punct_nobreak_kern:NN} % \begin{macrocode} \cs_new_protected:Npn \@@_punct_nobreak_kern:NN #1#2 { \@@_nobreak_hskip:n { \@@_use_dim_or_skip:nNN { kern } #1 #2 } } % \end{macrocode} % \end{macro} % % \changes{v3.2.4}{2013/07/06} % {使用 \texttt{AllowBreakBetweenPuncts} 时,相应标点符号仍能与边界对齐。} % \changes{v3.2.7}{2013/08/23} % {处理 \texttt{AllowBreakBetweenPuncts} 与 \pkg{xeCJKfntef} 的兼容问题。} % % \begin{macro}{\@@_punct_breakable_kern:NN} % \begin{macrocode} \cs_new_protected:Npn \@@_punct_breakable_kern:NN #1#2 { \exp_after:wN \@@_punct_if_right:NT #1 { \@@_punct_rule:NN \c_@@_right_tl #1 } \@@_punct_breakable_kern:n { \@@_use_dim_or_skip:nNN { bound_kern } #1 #2 } \@@_punct_if_right:NF #2 { \@@_punct_rule:NN \c_@@_left_tl #2 } } \cs_new_eq:NN \@@_punct_breakable_kern:n \skip_horizontal:n % \end{macrocode} % \end{macro} % % \begin{variable}{\g_@@_last_punct_tl} % 用于记录当前的标点符号。 % \begin{macrocode} \tl_new:N \g_@@_last_punct_tl % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\xeCJK_FullLeft_and_CJK:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullLeft_and_CJK: { \@@_punct_if_middle:NTF \g_@@_last_punct_tl { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_no_break: \@@_punct_glue:NN \c_@@_left_tl \g_@@_last_punct_tl } { } \@@_select_font: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullLeft_and_Default:} % \changes{v3.2.0}{2013/05/20}{修正 \pkg{xeCJK} 使西文在部分情况下无法断词的问题。} % \changes{v3.7.2}{2018/05/21}{再次修正 FullLeft 类字符与西文连用断词失败的问题。} % \cs{@@_nobreak_zero_glue:} 用于确保 FullLeft 类后的西文单词可以断词。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullLeft_and_Default: { \@@_punct_if_middle:NTF \g_@@_last_punct_tl { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \xeCJK_no_break: \@@_punct_glue:NN \c_@@_left_tl \g_@@_last_punct_tl } { \xeCJK_class_group_end: \@@_nobreak_zero_glue: } } \cs_new_protected:Npn \@@_nobreak_zero_glue: { \tex_penalty:D \c_@@_nobreak_penalty_int \skip_horizontal:N \c_zero_skip } \cs_new_protected:Npn \@@_zero_glue: { \skip_horizontal:N \c_zero_skip } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullRight_and_CJK:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullRight_and_CJK: { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl \@@_select_font: \CJKglue } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullRight_and_Default:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullRight_and_Default: { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_Default_and_FullLeft:nN} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_Default_and_FullLeft:nN #1#2 { \xeCJK_get_punct_bounds:NN \c_@@_left_tl #2 \@@_Default_and_FullLeft_glue:N #2 \xeCJK_class_group_begin: \xeCJK_select_punct_font: \xeCJK_clear_inter_class_toks:nn {#1} { FullLeft } \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nn \g_@@_last_punct_tl {#2} \@@_punct_rule:NN \c_@@_left_tl #2 \xeCJK_fallback_punct_symbol:NN \CJKpunctsymbol #2 } \cs_new_protected:Npn \@@_Default_and_FullLeft_glue:N #1 { \@@_punct_glue:NN \c_@@_left_tl #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_CJK_and_FullLeft:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_CJK_and_FullLeft:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_left_tl #1 \@@_CJK_and_FullLeft_glue:N #1 \tl_gset:Nn \g_@@_last_punct_tl {#1} \@@_punct_rule:NN \c_@@_left_tl #1 \@@_select_punct_font: \xeCJK_fallback_punct_symbol:NN \CJKpunctsymbol #1 } \cs_new_protected:Npn \@@_CJK_and_FullLeft_glue:N #1 { \CJKglue \@@_punct_glue:NN \c_@@_left_tl #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_Boundary_and_FullLeft:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_Boundary_and_FullLeft:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_left_tl #1 \@@_Boundary_and_FullLeft_glue:N #1 \xeCJK_class_group_begin: \xeCJK_select_punct_font: \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nn \g_@@_last_punct_tl {#1} \@@_punct_rule:NN \c_@@_left_tl #1 \xeCJK_fallback_punct_symbol:NN \CJKpunctsymbol #1 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_Boundary_and_FullLeft_glue:N} % \changes{v3.2.0}{2013/05/22}{当全角左标点前面是 \texttt{hlist}、\texttt{none}、 % \texttt{glue} 和 \texttt{penalty} 等节点时,压缩其左空白。} % \changes{v3.2.4}{2013/07/03}{细化边界与全角左标点之间是否压缩空白的判断。} % \changes{v3.2.5}{2013/07/13}{细化全角左标点是否位于段首的判断。} % \changes{v3.2.5}{2013/07/13}{增加对 \pkg{enumitem} 宏包修改的 \tn{item} 的判断。} % 根据 \cs{etex_lastnodetype:D} 的值进行分别处理。 % \begin{macrocode} \cs_new_protected:Npn \@@_Boundary_and_FullLeft_glue:N #1 { \tl_set_eq:NN \l_@@_alignii_tl \c_@@_left_tl \group_begin: \exp_args:NNc \group_end: \cs_if_exist_use:NTF { @@_bound_type_ \int_use:N \tex_lastnodetype:D _glue:Nn } {#1} { \use:n } { \@@_punct_glue:NN \c_@@_left_tl #1 } } \tl_new:N \c_@@_alignii_tl % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_bound_type_-1_glue:Nn} % \cs{etex_lastnodetype:D} 为 $-1$ 表示 empty list,常出现在盒子的起始位置, % 在段落前使用 \tn{noindent} 就是这种情况。 % \begin{macrocode} \cs_new_protected:cpn { @@_bound_type_ -1 _glue:Nn } #1#2 { \@@_zero_glue: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_bound_type_1_glue:Nn} % \changes{v3.8.5}{2020/06/26}{增加盒子高度判断。} % \changes{v3.8.9}{2022/05/26}{增加位于段首的支架盒子判断。} % $1$ 表示 hlist node,在这里用来判断是否位于段首。基于正常情况下,\TeX 会在段落开头插入宽度为 % \tn{parindent} 的水平盒子用于缩进。 % \begin{macrocode} \cs_new_protected:cpn { @@_bound_type_ 1 _glue:Nn } #1 { \int_do_while:nNnn \tex_lastnodetype:D = \c_@@_hlist_node { \@@_bound_hbox_auxi: } \@@_if_last_none:TF { \dim_case:nnF { \box_wd:N \l_@@_indent_box } { { \tex_parindent:D } { \@@_bound_hbox_auxii:nn } { \c_zero_dim } { \use_i:nn } } { \use:nn } } { \use:nn } { \hbox_unpack_drop:N \l_@@_indent_box } } \cs_new_protected:Npn \@@_bound_hbox_auxi: { \box_set_to_last:N \l_@@_tmp_box \hbox_set:Nn \l_@@_indent_box { \box_use:N \l_@@_tmp_box \hbox_unpack:N \l_@@_indent_box } } \cs_new_protected:Npn \@@_bound_hbox_auxii:nn { \dim_compare:nNnTF { \box_ht:N \l__xeCJK_tmp_box } = \c_zero_dim { \use_i:nn } { \use:nn } } \box_new:N \l_@@_indent_box % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_bound_type_11_glue:Nn} % $11$ 表示 glue node,这里判断的目的是当全角左标点出现在 \LaTeX 表格的非 \texttt{p} 列行首时, % 能够对齐到单元格的边界。判断基于标准 \LaTeX 表格的列格式(\tn{@tabclassz})定义中, % 在 \texttt{l} 列和 \texttt{r} 列前为了防止 \tn{tabcolsep} 被无意 \tn{unskip} 掉, % 都加了 |\hskip1sp|,而 \texttt{c} 列前则有 \tn{hfil}。\package{enumitem} 宏包修改了 % \env{description} 环境中使用的 \tn{item}(\tn{enit@postlabel@i}), % 在这里起到影响作用的是 |\penalty\z@ \hskip\labelsep|。 % \begin{macrocode} \cs_new_protected:cpn { @@_bound_type_ 11 _glue:Nn } #1#2 { \skip_if_finite:nTF { \tex_lastskip:D } { \@@_bound_glue_auxi:Nn #1 {#2} } { \@@_zero_glue: } } \cs_new_protected:Npn \@@_bound_glue_auxi:Nn #1#2 { \@@_if_last_punct_glue:TF { \xeCJK_punct_bound_kern:N #1 } { \@@_bound_glue_auxii:n {#2} } } \cs_new_protected:Npn \@@_bound_glue_auxii:n #1 { \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D \skip_if_eq:nnTF { \l_@@_last_skip } { 1sp } { \@@_zero_glue: } { \skip_if_eq:nnTF { \l_@@_last_skip } { \labelsep } { \tex_unskip:D \@@_if_last_penalty:TF { \int_compare:nNnTF \tex_lastpenalty:D = \c_zero_int { \skip_horizontal:N \l_@@_last_skip } { \skip_horizontal:N \l_@@_last_skip #1 } } { \skip_horizontal:N \l_@@_last_skip #1 } } {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_bound_type_12_glue:Nn} % $12$ 表示 kern node,用于判断之前的字符是否是 CJK 类,如果是,则插入 \tn{CJKglue}。 % \begin{macrocode} \cs_new_protected:cpn { @@_bound_type_ 12 _glue:Nn } #1#2 { \xeCJK_if_last_node:nF { CJK } { \xeCJK_if_last_node:nF { CJK-space } { \use_none:nn } } \xeCJK_remove_node: \CJKglue #2 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_bound_type_13_glue:n} % $13$ 表示 penalty node,这里判断的目的是全角左标点出现在 \LaTeX 列表环境的 \tn{item} 后面时, % 能对齐到边界。判断基于 \tn{item} 的内部定义 \tn{@item} 对 \tn{everypar} 进行了修改,在这里起 % 到影响作用的是 |\box\@labels \penalty\z@|。以上判断都比较粗略,暂时也没有想起更好的办法。 % \begin{macrocode} \cs_new_protected:cpn { @@_bound_type_ 13 _glue:Nn } #1#2 { \@@_if_last_punct_penalty:TF { \xeCJK_punct_bound_kern:N #1 } { \int_compare:nNnTF \tex_lastpenalty:D = \c_zero_int { \tex_unpenalty:D \@@_if_last_hlist:TF { \tex_penalty:D \c_zero_int } { \tex_penalty:D \c_zero_int #2 } } {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_Default_and_FullRight:nN} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_Default_and_FullRight:nN #1#2 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl #2 \@@_Default_and_FullRight_glue:N #2 \xeCJK_class_group_begin: \xeCJK_select_punct_font: \xeCJK_clear_inter_class_toks:nn {#1} { FullRight } \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nn \g_@@_last_punct_tl {#2} \xeCJK_FullRight_symbol:N #2 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_Boundary_and_FullRight:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_Boundary_and_FullRight:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl #1 \xeCJK_if_last_punct:TF { \tl_set_eq:NN \l_@@_alignii_tl \c_@@_right_tl \xeCJK_punct_bound_kern:N } { \@@_Default_and_FullRight_glue:N } #1 \xeCJK_class_group_begin: \xeCJK_select_punct_font: \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nn \g_@@_last_punct_tl {#1} \xeCJK_FullRight_symbol:N #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_CJK_and_FullRight:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_CJK_and_FullRight:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl #1 \@@_CJK_and_FullRight_glue:N #1 \tl_gset:Nn \g_@@_last_punct_tl {#1} \@@_select_punct_font: \xeCJK_FullRight_symbol:N #1 } % \end{macrocode} % \end{macro} % % \changes{v3.6.0}{2018/01/23}{解决标点中间被隔开的禁则与压缩问题。} % \changes{v3.7.3}{2019/04/15}{修复 penalty 数值错误。} % \changes{v3.8.3}{2020/04/27}{修复 \opt{xCJKecglue} 选项。} % \changes{v3.8.6}{2020/10/18}{正确还原标点符号后的 penalty 状态。} % % \begin{macro}{\xeCJK_if_last_punct:TF} % \changes{v3.6.1}{2018/02/25}{细化判断。} % 判断之前是否是一个标点符号。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_if_last_punct:TF { \bool_set_false:N \l_@@_last_penalty_bool \@@_if_last_glue:TF { \@@_if_last_punct_glue:TF } { \@@_if_last_penalty:TF { \@@_if_last_punct_penalty:TF } { \use_ii:nn } } } \cs_new_protected:Npn \@@_if_last_punct_glue:TF { \prop_get:NoNTF \g_@@_punct_skip_prop { \skip_use:N \tex_lastskip:D } \l_@@_tmp_tl { \@@_if_last_punct_glue_auxi:TF } { \@@_if_last_punct_glue_auxii:TF } } \cs_new_protected:Npn \@@_if_last_punct_glue_auxi:TF { \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D \tex_unskip:D \int_compare:nNnTF \tex_lastpenalty:D = \c_@@_nobreak_penalty_int { \@@_if_last_punct_auxi:TF { \use_i:nn } } { \xeCJK_if_last_node:TF { \@@_if_last_punct_auxii:TF { \use_i:nn } } { \use:n } } { \skip_horizontal:N \l_@@_last_skip \use_ii:nn } } \cs_new_protected:Npn \@@_if_last_punct_glue_auxii:TF { \group_begin: \g_@@_space_factor_int \tex_spacefactor:D \skip_if_eq:nnTF { \tex_lastskip:D } { \c_xeCJK_space_skip_tl } { \group_end: \@@_if_last_punct_glue_auxiii:TF } { \group_end: \use_ii:nn } } \cs_new_protected:Npn \@@_if_last_punct_glue_auxiii:TF { \skip_set_eq:NN \l_@@_tmp_skip \tex_lastskip:D \tex_unskip:D \@@_if_last_glue:TF { \prop_get:NoNTF \g_@@_punct_skip_prop { \skip_use:N \tex_lastskip:D } \l_@@_tmp_tl { \@@_if_last_punct_glue_auxi:TF { \use_i:nn } } { \use:n } } { \use:n } { \skip_horizontal:N \l_@@_tmp_skip \use_ii:nn } } \cs_new_protected:Npn \@@_if_last_punct_penalty:TF { \int_set_eq:NN \l_@@_last_penalty_int \tex_lastpenalty:D \tex_unpenalty:D \bool_set_true:N \l_@@_last_penalty_bool \@@_if_last_glue:TF { \@@_if_last_punct_glue:TF { \use_i:nn } } { \use:n } { \@@_last_punct_penalty_false:nn } } \cs_new_protected:Npn \@@_last_punct_penalty_false:nn #1#2 { \bool_set_false:N \l_@@_last_penalty_bool \tex_penalty:D \l_@@_last_penalty_int #2 } \cs_new_protected:Npn \@@_if_last_punct_auxi:TF { \tex_unpenalty:D \bool_if:NF \l_@@_last_penalty_bool { \bool_set_true:N \l_@@_last_penalty_bool \int_set_eq:NN \l_@@_last_penalty_int \c_@@_nobreak_penalty_int } \xeCJK_if_last_node:TF { \@@_if_last_punct_auxii:TF { \use_i:nn } } { \use:n } { \xeCJK_no_break: \use_ii:nn } } \cs_new_protected:Npn \@@_if_last_punct_auxii:TF { \dim_compare:nNnTF \l_@@_last_kern_dim > \c_zero_dim { \@@_if_last_punct_auxiii:TF } { \@@_make_node:N \l_@@_last_kern_dim \use_ii:nn } } \cs_new_protected:Npn \@@_if_last_punct_auxiii:TF { \int_case:nnTF { \tex_XeTeXcharclass:D \l_@@_last_kern_dim } { { \xeCJK_class_num:n { FullRight } } { \tl_set_eq:NN \l_@@_aligni_tl \c_@@_right_tl } { \xeCJK_class_num:n { FullLeft } } { \tl_set_eq:NN \l_@@_aligni_tl \c_@@_left_tl } } { \@@_if_last_punct_auxiv:TF } { \use_ii:nn } } \cs_new_protected:Npn \@@_if_last_punct_auxiv:TF { \dim_set_eq:NN \l_@@_tmp_dim \l_@@_last_kern_dim \xeCJK_if_last_node:TF { \tl_gset:Nx \g_@@_last_punct_tl { \tex_Uchar:D \l_@@_tmp_dim } \dim_set_eq:NN \l_@@_last_bound_dim \l_@@_last_kern_dim \use_i:nn } { \@@_make_node:N \l_@@_tmp_dim \use_ii:nn } } \tl_new:N \l_@@_aligni_tl \tl_new:N \l_@@_alignii_tl \int_new:N \l_@@_last_penalty_int \dim_new:N \l_@@_last_bound_dim \bool_new:N \l_@@_last_penalty_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJK_if_last_node:TF} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_if_last_node:TF #1#2 { \@@_if_last_kern:TF { \dim_set_eq:NN \l_@@_last_kern_dim \tex_lastkern:D \tex_unkern:D \@@_if_last_kern:TF { \dim_compare:nNnTF \tex_lastkern:D = { - \l_@@_last_kern_dim } { \tex_unkern:D #1 } { \tex_kern:D \l_@@_last_kern_dim #2 } } { \tex_kern:D \l_@@_last_kern_dim #2 } } {#2} } \dim_new:N \l_@@_last_kern_dim % \end{macrocode} % \end{macro} % % \changes{v3.6.0}{2018/01/14} % {修正标点同为 \texttt{LongPunct} 与 \texttt{MiddlePunct} 时的实现错误。} % \changes{v3.6.0}{2018/01/14} % {\texttt{Default} 类与 \texttt{MiddlePunct} 之间不应该有 \tn{CJKglue}。} % % \begin{macro} % {\@@_CJK_and_FullRight_glue:N,\@@_Default_and_FullRight_glue:N} % \begin{macrocode} \cs_new_protected:Npn \@@_CJK_and_FullRight_glue:N #1 { \@@_punct_if_long:NTF #1 { \xeCJK_allow_break: } { \xeCJK_no_break: } \@@_punct_if_middle:NT #1 { \CJKglue \@@_punct_glue:NN \c_@@_right_tl #1 \@@_punct_rule:NN \c_@@_left_tl #1 } } \cs_new_protected:Npn \@@_Default_and_FullRight_glue:N #1 { \@@_punct_if_long:NTF #1 { \xeCJK_allow_break: } { \xeCJK_no_break: } \@@_punct_if_middle:NT #1 { \@@_punct_glue:NN \c_@@_right_tl #1 \@@_punct_rule:NN \c_@@_left_tl #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullLeft_and_FullLeft:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullLeft_and_FullLeft:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_left_tl #1 \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl #1 \@@_punct_kern:NN \g_@@_last_punct_tl #1 \tl_gset:Nn \g_@@_last_punct_tl {#1} \xeCJK_fallback_punct_symbol:NN \CJKpunctsymbol #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullLeft_and_FullRight:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullLeft_and_FullRight:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl #1 \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl #1 \@@_punct_kern:NN \g_@@_last_punct_tl #1 \tl_gset:Nn \g_@@_last_punct_tl {#1} \xeCJK_FullRight_symbol:N #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullRight_and_FullLeft:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullRight_and_FullLeft:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_left_tl #1 \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl #1 \xeCJK_punct_kern:NN \g_@@_last_punct_tl #1 \tl_gset:Nn \g_@@_last_punct_tl {#1} \xeCJK_fallback_punct_symbol:NN \CJKpunctsymbol #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullRight_and_FullRight:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullRight_and_FullRight:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl #1 \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl #1 \@@_punct_kern:NN \g_@@_last_punct_tl #1 \tl_gset:Nn \g_@@_last_punct_tl {#1} \xeCJK_FullRight_symbol:N #1 } % \end{macrocode} % \end{macro} % % \subsection{全角右标点后的断行} % % \begin{macro}{CheckFullRight} % \changes{v3.1.1}{2012/12/02}{处理全角右标点之后的断行问题。} % 选项设置。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CheckFullRight .choice: , CheckFullRight / true .code:n = { \cs_if_eq:NNF \xeCJK_FullRight_and_Boundary: \xeCJK_check_FullRight: { \cs_set_eq:NN \@@_save_FullRight_check: \xeCJK_FullRight_and_Boundary: \cs_set_eq:NN \@@_save_FullRight_symbol:N \xeCJK_FullRight_symbol:N \cs_set_eq:NN \xeCJK_FullRight_and_Boundary: \xeCJK_check_FullRight: \cs_set_eq:NN \xeCJK_FullRight_symbol:N \xeCJK_check_FullRight_symbol:Nw } } , CheckFullRight / false .code:n = { \cs_if_eq:NNT \xeCJK_FullRight_and_Boundary: \xeCJK_check_FullRight: { \cs_set_eq:NN \xeCJK_FullRight_and_Boundary: \@@_save_FullRight_check: \cs_set_eq:NN \xeCJK_FullRight_symbol:N \@@_save_FullRight_symbol:N } } , CheckFullRight .default:n = { true } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_FullRight_symbol:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_FullRight_symbol:N { \xeCJK_fallback_punct_symbol:NN \CJKpunctsymbol } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_check_FullRight:} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_FullRight: { \xeCJK_get_punct_bounds:No \c_@@_right_tl \g_@@_last_punct_tl \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \group_align_safe_begin: \token_case_meaning:NoTF \l_peek_token { \l_@@_no_break_cs_case_tl } { \group_align_safe_end: \xeCJK_no_break: \group_insert_after:N \xeCJK_no_break: } { \group_align_safe_end: } \exp_after:wN \xeCJK_punct_node:N \g_@@_last_punct_tl \xeCJK_class_group_end: \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl } \prg_generate_conditional_variant:Nnn \token_case_meaning:Nn { No } { TF , F } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_check_FullRight_symbol:Nw} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_FullRight_symbol:Nw #1 { \peek_remove_spaces:n { \@@_save_FullRight_symbol:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_cs_case_keys_define:nNNnn} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_cs_case_keys_define:nNNnn #1#2#3#4#5 { \tl_new:N #2 \seq_new:N #3 \keys_define:nn { xeCJK / options } { #1 .code:n = { \seq_set_split:Nnn #3 { } {##1} \@@_update_cs_case_tl:NNnn #2#3 {#4} {#5} } , #1+ .code:n = { \tl_map_inline:nn {##1} { \seq_if_in:NnF #3 {####1} { \seq_put_right:Nn #3 {####1} } } \@@_update_cs_case_tl:NNnn #2#3 {#4} {#5} } , #1- .code:n = { \tl_map_inline:nn {##1} { \seq_remove_all:Nn #3 {####1} } \@@_update_cs_case_tl:NNnn #2#3 {#4} {#5} } } } \cs_new_protected:Npn \@@_update_cs_case_tl:NNnn #1#2#3#4 { \tl_clear:N #1 \seq_map_inline:Nn #2 { \tl_put_right:Nn #1 { {##1} {#3} } } #4 } % \end{macrocode} % \end{macro} % % \begin{macro}{NoBreakCS} % 设置不能在全角右标点之后断行的控制序列。 % \begin{macrocode} \xeCJK_cs_case_keys_define:nNNnn { NoBreakCS } \l_@@_no_break_cs_case_tl \l_@@_no_break_cs_seq { } { } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKnobreak} % \changes{v3.1.1}{2012/12/03}{增加 \tn{nobreak} 的 \pkg{xeCJK} 版本。} % 为保险起见,我们在这里用了一个循环。 % \begin{macrocode} \NewDocumentCommand \xeCJKnobreak { } { \bool_set_true:N \l_@@_tmp_bool \int_while_do:nNnn \tex_lastnodetype:D = \c_@@_glue_node { \bool_if:NTF \l_@@_tmp_bool { \bool_set_false:N \l_@@_tmp_bool \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D } { \skip_add:Nn \l_@@_last_skip \tex_lastskip:D } \tex_unskip:D } \xeCJK_if_last_node:TF { \dim_set_eq:NN \l_@@_tmp_dim \l_@@_last_kern_dim \xeCJK_if_last_node:TF { \@@_if_last_glue:TF { \exp_args:NNNo \tex_unskip:D \xeCJK_no_break: \skip_horizontal:n { \skip_use:N \tex_lastskip:D } } \@@_make_node:N \l_@@_last_kern_dim } { } \@@_make_node:N \l_@@_tmp_dim } { } \xeCJK_no_break: \bool_if:NF \l_@@_tmp_bool { \skip_horizontal:N \l_@@_last_skip } } % \end{macrocode} % \end{macro} % % \subsection{段末孤字处理} % % \begin{macro}{CheckSingle} % 孤字处理功能选项。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CheckSingle .choice: , CheckSingle / true .code:n = { \cs_if_eq:NNF \xeCJK_CJK_and_CJK:N \xeCJK_check_single:Nw { \cs_set_eq:NN \@@_check_single_save:N \xeCJK_CJK_and_CJK:N \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_check_single:Nw } } , CheckSingle / false .code:n = { \cs_if_eq:NNT \xeCJK_CJK_and_CJK:N \xeCJK_check_single:Nw { \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \@@_check_single_save:N } } , CheckSingle .default:n = { true } , CJKchecksingle .meta:n = { CheckSingle = true } } % \end{macrocode} % \end{macro} % % \changes{v3.3.1}{2015/04/08}{新选项 \texttt{WidowPenalty}。} % % \begin{macro}{WidowPenalty} % 设置段末汉字的 penalty,默认值是 \num{10000}。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { WidowPenalty .int_set:N = \l_@@_widow_penalty_int , WidowPenalty .default:n = { 10 000 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_widow_penalty:} % 预防段末孤字而插入的 penalty,值为 \cs{l_@@_widow_penalty_int}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_widow_penalty: { \tex_penalty:D \l_@@_widow_penalty_int } % \end{macrocode} % \end{macro} % % \changes{v3.4.7}{2017/03/20}{简化 \texttt{CheckSingle} 的实现,不再展开宏。} % % \begin{macro}[int]{\xeCJK_check_single:Nw} % \begin{macro}{\@@_check_single_end:N} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_single:Nw #1 { \group_align_safe_begin: \peek_catcode:NTF \c_catcode_letter_token { \xeCJK_check_single:NNw #1 } { \token_if_other:NTF \l_peek_token { \xeCJK_check_single:NNw } { \@@_check_single_end:N } #1 } } \cs_new_protected:Npn \@@_check_single_end:N { \group_align_safe_end: \@@_check_single_save:N } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\xeCJK_check_single:NNw} % \begin{macro}{\@@_check_single_aux:nNNw} % \changes{v3.1.1}{2012/12/04}{改进定义,减少使用 \texttt{peek} 函数的次数。} % \changes{v3.2.7}{2013/08/30}{与 \tn{CJKspace} 兼容。} % 使用 \cs{group_align_safe_begin:} 和 \cs{group_align_safe_end:} 是为了防止在表格 % 里面报错。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_single:NNw #1#2 { \xeCJK_peek_catcode_ignore_spaces:NTF \c_catcode_letter_token { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \bool_if:NTF \l_@@_reserve_space_bool { \@@_check_single_end:N #1 #2 ~ } { \@@_check_single_space:NN #1#2 } } { \@@_check_single_end:N #1 #2 } } { \token_if_other:NTF \l_peek_token { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \@@_check_single_space:NN } { \@@_check_single_end:N } } { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \@@_check_single_aux:nNNw { ~ } } { \@@_check_single_aux:nNNw { } } } #1 #2 } } \cs_new_protected:Npn \@@_check_single_aux:nNNw #1#2#3 { \token_if_cs:NTF \l_peek_token { \xeCJK_check_single_cs:NNn } { \xeCJK_check_single_end:NNnw } #2 #3 {#1} } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\xeCJK_check_single_end:NNnw} % \begin{macro}{\@@_check_single_end_aux:NNn,\@@_check_single_end_equation:NNnw} % \begin{macrocode} \cs_new_protected:Npn \@@_check_single_end_aux:NNn #1#2#3 { \@@_check_single_end:N #1 #2 #3 } \cs_new_eq:NN \xeCJK_check_single_end:NNnw \@@_check_single_end_aux:NNn \cs_new_protected:Npn \@@_check_single_end_equation:NNnw { \token_if_math_toggle:NTF \l_peek_token { \xeCJK_check_single_equation:NNnNw } { \@@_check_single_end_aux:NNn } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{PlainEquation} % \changes{v3.1.1}{2012/12/06}{增加 \texttt{PlainEquation} 选项。} % \begin{macrocode} \keys_define:nn { xeCJK / options } { PlainEquation .choice: , PlainEquation / true .code:n = { \cs_set_eq:NN \xeCJK_check_single_end:NNnw \@@_check_single_end_equation:NNnw } , PlainEquation / false .code:n = { \cs_set_eq:NN \xeCJK_check_single_end:NNnw \@@_check_single_end_aux:NNn } , PlainEquation .default:n = { true } , } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_check_single_space:NN} % \changes{v3.1.1}{2012/12/13} % {\texttt{CheckSingle} 支持段末“汉字$+$汉字$+$空格$+$汉字/标点”的形式。} % \changes{v3.1.2}{2012/12/27} % {使用 \cs{xeCJK_if_CJK_class:NTF} 来代替 \cs{int_case:nnn} 判断是否是 CJK 字符类。} % \begin{macrocode} \cs_new_protected:Npn \@@_check_single_space:NN #1#2 { \xeCJK_if_CJK_class:NTF #2 { \xeCJK_if_CJK_class:NTF \l_peek_token { \@@_check_single_end:N #1 #2 } { \@@_check_single_end:N #1 #2 ~ } } { \@@_check_single_end:N #1 #2 ~ } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_check_single_equation:NNnNw} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_single_equation:NNnNw #1#2#3#4 { \peek_catcode:NTF \c_math_toggle_token { \xeCJK_widow_penalty: \@@_check_single_end:N #1 \xeCJK_make_node:n { CJK-widow } #2 #4 } { \@@_check_single_end:N #1 #2#3#4 } } % \end{macrocode} % \end{macro} % % \changes{v3.2.3}{2013/06/11} % {解决 \texttt{CheckSingle} 选项与 \pkg{tablists} 宏包的冲突。} % \changes{v3.2.4}{2013/06/26} % {解决使用 \texttt{CheckSingle} 时,某些 \tn{CJKglue} 不能被正确加入的问题。} % % \begin{macro}[int]{\xeCJK_check_single_cs:NNn} % \changes{v3.3.1}{2015/04/06}{补充可能遗漏的空格。} % 在使用 \texttt{CheckSingle} 选项时,在 \package{tablists} 宏包定义的 % \env{tabenum} 环境中会出现下面的错误: % \begin{verbatim} % ! Forbidden control sequence found while scanning use of \use_ii:nn. % % \par % l.10 \item % \end{verbatim} % 原因在于 \env{tabenum} 实际上是一个 \TeX 对齐环境(\tn{halign}),\tn{par} 在 % 其中被重定义为 \tn{cr}。而在下面 \cs{token_case_meaning:NnF} 的分支里有对 \tn{par} 的 % \tn{ifx} 判断。解决办法是将判断用 \cs{group_align_safe_begin:} 和 % \cs{group_align_safe_end:} 包起来。或者改用原语 \cs{tex_par:D} 作为判断条件。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_single_cs:NNn #1#2#3 { \token_case_meaning:NoF \l_peek_token { \l_@@_check_single_cs_case_tl } { \use_iii:nnn } { \xeCJK_check_single_env:nnNn } { \xeCJK_widow_penalty: \@@_check_single_end:N #1 \xeCJK_make_node:n { CJK-widow } #2#3 } { \@@_check_single_end:N #1 #2#3 } } \tl_new:N \l_@@_check_single_cs_case_tl % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_check_single_env:nnNn} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_check_single_env:nnNn #1#2#3#4 { \str_case_e:noTF {#4} { \l_@@_inline_env_case_tl } {#2} {#1} #3 {#4} } \prg_generate_conditional_variant:Nnn \str_case_e:nn { no } { TF } % \end{macrocode} % \end{macro} % % \changes{v3.1.1}{2012/12/04}{增加 \texttt{NewLineCS} 和 \texttt{EnvCS} 选项。} % % \begin{macro}{NewLineCS} % \begin{macrocode} \xeCJK_cs_case_keys_define:nNNnn { NewLineCS } \l_@@_new_line_cs_case_tl \l_@@_new_line_cs_seq { \use_ii:nnn } { \tl_concat:NNN \l_@@_check_single_cs_case_tl \l_@@_new_line_cs_case_tl \l_@@_env_cs_case_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{EnvCS} % \begin{macrocode} \xeCJK_cs_case_keys_define:nNNnn { EnvCS } \l_@@_env_cs_case_tl \l_@@_env_cs_seq { \use:n } { \tl_concat:NNN \l_@@_check_single_cs_case_tl \l_@@_new_line_cs_case_tl \l_@@_env_cs_case_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{InlineEnv} % \changes{v3.1.1}{2012/12/05}{改变行内环境的设置方式,从而使用 \cs{str_case_x:nnn} % 代替原来的 \cs{clist_if_in:NnTF} 来判断是否是行内环境。} % \begin{macrocode} \keys_define:nn { xeCJK / options } { InlineEnv .code:n = { \seq_set_from_clist:Nn \l_@@_inline_env_seq {#1} \@@_update_inline_env_case_tl: } , InlineEnv+ .code:n = { \clist_map_inline:nn {#1} { \seq_if_in:NnF \l_@@_inline_env_seq {##1} { \seq_put_right:Nn \l_@@_inline_env_seq {##1} } } \@@_update_inline_env_case_tl: } , InlineEnv- .code:n = { \clist_map_inline:nn {#1} { \seq_remove_all:Nn \l_@@_inline_env_seq {##1} } \@@_update_inline_env_case_tl: } } \seq_new:N \l_@@_inline_env_seq % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_update_inline_env_case_tl:} % \begin{macrocode} \cs_new_protected:Npn \@@_update_inline_env_case_tl: { \tl_clear:N \l_@@_inline_env_case_tl \seq_map_inline:Nn \l_@@_inline_env_seq { \tl_put_right:Nn \l_@@_inline_env_case_tl { {##1} { } } } } \tl_new:N \l_@@_inline_env_case_tl % \end{macrocode} % \end{macro} % % \subsection{增加 CJK 子分区} % % \begin{variable}{\g_@@_CJK_sub_class_seq} % \begin{macrocode} \seq_new:N \g_@@_CJK_sub_class_seq % \end{macrocode} % \end{variable} % % \begin{macro}{\xeCJKDeclareSubCJKBlock} % 声明 CJK 子区范围,|#1| 为自定义名称,|#2| 为子区的 |Unicode| 范围。 % \begin{macrocode} \NewDocumentCommand \xeCJKDeclareSubCJKBlock { s > { \TrimSpaces } m m } { \xeCJK_declare_sub_char_class:nen { CJK } {#2} {#3} \IfBooleanT {#1} { \xeCJKResetPunctClass } } \@onlypreamble \xeCJKDeclareSubCJKBlock % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKCancelSubCJKBlock,\xeCJKRestoreSubCJKBlock} % 取消和恢复对 CJK 子区的声明。 % \begin{macrocode} \bool_new:N \l_@@_sub_cancel_bool \NewDocumentCommand \xeCJKCancelSubCJKBlock { s m } { \bool_if:NF \l_@@_sub_cancel_bool { \bool_set_true:N \l_@@_sub_cancel_bool \@@_sub_restore_or_cancel:e {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } \NewDocumentCommand \xeCJKRestoreSubCJKBlock { s m } { \bool_if:NT \l_@@_sub_cancel_bool { \bool_set_false:N \l_@@_sub_cancel_bool \@@_sub_restore_or_cancel:e {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_sub_restore_or_cancel:n} % \begin{macrocode} \cs_new_protected:Npn \@@_sub_restore_or_cancel:n #1 { \clist_map_inline:nn {#1} { \int_if_exist:cTF { \@@_class_csname:n { CJK/##1 } } { \xeCJK_declare_char_class:nn { CJK \bool_if:NF \l_@@_sub_cancel_bool { /##1 } } { \use:c { g_@@_CJK/##1_range_clist } } } { \@@_error:nx { SubBlock-undefined } {##1} } } } \cs_generate_variant:Nn \@@_sub_restore_or_cancel:n { e } \@@_msg_new:nn { SubBlock-undefined } { The~CJK~sub~block~`#1'~is~undefined.\\\\ Try~to~use~\token_to_str:N \xeCJKDeclareSubCJKBlock \ to~declare~it. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_declare_sub_char_class:nnn} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_declare_sub_char_class:nnn #1#2#3 { \int_if_exist:cF { \@@_class_csname:n { #1/#2 } } { \xeCJK_new_class:n { #1/#2 } \@@_set_sub_class_toks:nn {#1} {#2} \xeCJK_new_sub_key:n {#2} } \xeCJK_declare_char_class:nn { #1/#2 } {#3} } \cs_generate_variant:Nn \xeCJK_declare_sub_char_class:nnn { ne } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_sub_class_toks:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_set_sub_class_toks:nn #1#2 { \seq_map_inline:Nn \g_@@_base_class_seq { \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } {##1} {#1} {##1} \xeCJK_copy_inter_class_toks:nnnn {##1} { #1/#2 } {##1} {#1} \str_if_eq:nnTF {##1} { CJK } { \xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } { \@@_switch_font:nn {#1} {#2} } } { \xeCJK_replace_inter_class_toks:nnnn {##1} { #1/#2 } { \xeCJK_fallback_symbol:NN } { \@@_switch_font:nn {#1} {#2} \xeCJK_fallback_symbol:NN } } } \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/#2 } {#1} {#1} \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/##1 } {#1} {#1} \xeCJK_copy_inter_class_toks:nnnn { #1/##1 } { #1/#2 } {#1} {#1} \xeCJK_pre_inter_class_toks:nnn { #1/#2 } { #1/##1 } { \@@_switch_font:nn {#2} {##1} } \xeCJK_pre_inter_class_toks:nnn { #1/##1 } { #1/#2 } { \@@_switch_font:nn {##1} {#2} } } \seq_gput_right:Nn \g_@@_CJK_sub_class_seq {#2} \@@_save_CJK_class:n { #1/#2 } \clist_map_inline:nn { CJK , FullLeft , FullRight , HangulJamo } { \xeCJK_pre_inter_class_toks:nnn { #1/#2 } {##1} { \@@_switch_font:nn {#2} {#1} } } } % \end{macrocode} % \end{macro} % % \subsection{标点处理} % % \changes{v3.2.7}{2013/08/22}{实现自定义行首/尾标点符号宽度功能。} % \changes{v3.7.4}{2019/05/31}{简化行首/尾标点符号宽度的实现。} % % \tn{XeTeXglyphbounds} 可以得到一个字符的左右边距,用于标点压缩。如果它不可用,则 % 在文档中只能使用 |plain| 这一标点格式原样输出标点。 % \begin{macrocode} \cs_if_exist:NF \tex_XeTeXglyphbounds:D { \@@_msg_new:nn { XeTeX-too-old } { \token_to_str:N \tex_XeTeXglyphbounds:D \ is~not~defined.\\ CJK~punctuation~kerning~will~not~be~available.\\\\ You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. } \@@_error:n { XeTeX-too-old } \AtEndOfPackage { \keys_define:nn { xeCJK / options } { PunctStyle .code:n = { \@@_error:nx { punct-style-unknown } {#1} } } \seq_gclear:N \g_@@_punct_style_seq \@@_set_punct_style:n { plain } } } % \end{macrocode} % % \begin{macro}{\xeCJKsetwidth} % 手动设置参数中的标点符号的宽度。 % \begin{macrocode} \NewDocumentCommand \xeCJKsetwidth { s m m } { \IfBooleanTF {#1} { \tl_map_inline:en {#2} { \tl_gset:cn { g_@@_punct_bound_width/##1/tl } {#3} } } { \tl_map_inline:en {#2} { \tl_gset:cn { g_@@_punct_width/##1/tl } {#3} } } } \@onlypreamble \xeCJKsetwidth \cs_generate_variant:Nn \tl_map_inline:nn { e } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKsetkern} % 手动设置相邻标点的距离。 % \begin{macrocode} \NewDocumentCommand \xeCJKsetkern { m m m } { \tl_gset:cn { g_@@_punct/kern/#1/#2/tl } {#3} } \@onlypreamble \xeCJKsetkern % \end{macrocode} % \end{macro} % % \begin{variable}{\c_@@_left_tl,\c_@@_right_tl} % \begin{macrocode} \tl_const:Nn \c_@@_left_tl { left } \tl_const:Nn \c_@@_right_tl { right } % \end{macrocode} % \end{variable} % % \changes{v3.2.12}{2014/05/12}{新增 \texttt{RubberPunctSkip} 选项。} % \changes{v3.4.0}{2016/05/13}{\texttt{RubberPunctSkip} 选项有新的值 \texttt{plus} 和 \texttt{minus}。} % % \begin{macro} % {AllowBreakBetweenPuncts,KaiMingPunct,LongPunct, % MiddlePunct,PunctWidth,PunctBoundWidth,RubberPunctSkip} % 相关选项声明。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { AllowBreakBetweenPuncts .choice: , AllowBreakBetweenPuncts / true .code:n = { \bool_set_true:N \l_@@_punct_breakable_bool \cs_set_eq:NN \xeCJK_punct_kern:NN \@@_punct_breakable_kern:NN \cs_set_eq:NN \@@_punct_bound_kern:N \@@_punct_bound_breakable_kern:N } , AllowBreakBetweenPuncts / false .code:n = { \bool_set_false:N \l_@@_punct_breakable_bool \cs_set_eq:NN \xeCJK_punct_kern:NN \@@_punct_kern:NN \cs_set_eq:NN \@@_punct_bound_kern:N \@@_nobreak_hskip:N } , AllowBreakBetweenPuncts .default:n = { true } , KaiMingPunct .code:n = { \@@_set_special_punct:nn { mixed_width } {#1} } , KaiMingPunct+ .code:n = { \@@_add_special_punct:nn { mixed_width } {#1} } , KaiMingPunct- .code:n = { \@@_sub_special_punct:nn { mixed_width } {#1} } , LongPunct .code:n = { \@@_set_special_punct:nn { long } {#1} } , LongPunct+ .code:n = { \@@_add_special_punct:nn { long } {#1} } , LongPunct- .code:n = { \@@_sub_special_punct:nn { long } {#1} } , MiddlePunct .code:n = { \@@_set_special_punct:nn { middle } {#1} } , MiddlePunct+ .code:n = { \@@_add_special_punct:nn { middle } {#1} } , MiddlePunct- .code:n = { \@@_sub_special_punct:nn { middle } {#1} } , PunctWidth .tl_gset:N = \g_@@_punct_width_tl , PunctBoundWidth .tl_gset:N = \g_@@_punct_bound_width_tl , PunctWidth .value_required:n = true , PunctBoundWidth .value_required:n = true , RubberPunctSkip .choice: , RubberPunctSkip .default:n = { true } , RubberPunctSkip / true .code:n = { \cs_set_eq:NN \@@_use_dim_or_skip:nNN \@@_use_punct_skip:nNN } , RubberPunctSkip / plus .code:n = { \cs_set_eq:NN \@@_use_dim_or_skip:nNN \@@_use_punct_skip_plus:nNN } , RubberPunctSkip / minus .code:n = { \cs_set_eq:NN \@@_use_dim_or_skip:nNN \@@_use_punct_skip_minus:nNN } , RubberPunctSkip / false .code:n = { \cs_set_eq:NN \@@_use_dim_or_skip:nNN \@@_use_punct_dim:nNN } } \bool_new:N \l_@@_punct_breakable_bool % \end{macrocode} % \end{macro} % % 相关选项定义的辅助函数。 % \begin{macrocode} \clist_new:N \g_@@_special_punct_clist \clist_gset:Nn \g_@@_special_punct_clist { mixed_width , long , middle } \cs_new:Npn \@@_special_punct_seq:n #1 { g_@@_special_punct_#1_seq } \cs_new:Npn \@@_special_punct_tl:nN #1#2 { g_@@_special_punct_#1_#2_tl } \clist_map_inline:Nn \g_@@_special_punct_clist { \seq_new:c { \@@_special_punct_seq:n {#1} } } \cs_new_protected:Npn \@@_set_special_punct:nn #1#2 { \seq_map_inline:cn { \@@_special_punct_seq:n {#1} } { \cs_undefine:c { \@@_special_punct_tl:nN {#1} {##1} } } \seq_gclear:c { \@@_special_punct_seq:n {#1} } \tl_map_inline:en {#2} { \tl_new:c { \@@_special_punct_tl:nN {#1} {##1} } \seq_gput_right:cn { \@@_special_punct_seq:n {#1} } {##1} } } \cs_new_protected:Npn \@@_add_special_punct:nn #1#2 { \tl_map_inline:en {#2} { \seq_if_in:cnF { \@@_special_punct_seq:n {#1} } {##1} { \tl_new:c { \@@_special_punct_tl:nN {#1} {##1} } \seq_gput_right:cn { \@@_special_punct_seq:n {#1} } {##1} } } } \cs_new_protected:Npn \@@_sub_special_punct:nn #1#2 { \tl_map_inline:en {#2} { \cs_undefine:c { \@@_special_punct_tl:nN {#1} {##1} } \seq_gremove_all:cn { \@@_special_punct_seq:n {#1} } {##1} } } % \end{macrocode} % % 判断一个标点符号是否为全角右标点和长标点符号。 % \begin{macrocode} \prg_new_conditional:Npnn \@@_punct_if_right:N #1 { p , T , F , TF } { \if_int_compare:w \xeCJK_token_value_class:N #1 = \xeCJK_class_num:n { FullRight } \prg_return_true: \else: \prg_return_false: \fi: } \clist_map_inline:Nn \g_@@_special_punct_clist { \exp_args:Nc \prg_new_conditional:Npnn { @@_punct_if_#1:N } ##1 { p , T , F , TF } { \if_cs_exist:w \@@_special_punct_tl:nN {#1} {##1} \cs_end: \prg_return_true: \else: \prg_return_false: \fi: } } % \end{macrocode} % % 一些用于记录的辅助函数。 % \begin{macrocode} \cs_new:Npn \@@_punct_csname:n #1 { c_@@_\l_xeCJK_current_punct_font_tl/\l_xeCJK_punct_style_tl/#1/tl } \cs_new:Npn \@@_use_punct_dim:nN #1#2 { \use:c { \@@_punct_csname:n { dim/#1/#2 } } } \cs_new:Npn \@@_use_punct_dim:nNN #1#2#3 { \use:c { \@@_punct_csname:n { dim/#1/#2/#3 } } } \cs_new:Npn \@@_use_punct_skip:nNN #1#2#3 { \use:c { \@@_punct_csname:n { skip/#1/#2/#3 } } } \cs_new:Npn \@@_use_punct_skip_plus:nNN #1#2#3 { \use:c { \@@_punct_csname:n { skip/plus/#1/#2/#3 } } } \cs_new:Npn \@@_use_punct_skip_minus:nNN #1#2#3 { \use:c { \@@_punct_csname:n { skip/minus/#1/#2/#3 } } } \cs_new_protected:Npn \@@_save_punct_dim:nNn #1#2 { \@@_save_punct_width_aux:nnnn { dim } {#1} { #1/#2 } } \cs_new_protected:Npn \@@_save_punct_dim:nNNn #1#2#3 { \@@_save_punct_width_aux:nnnn { dim } {#1} { #1/#2/#3 } } \cs_new_protected:Npn \@@_save_punct_skip:nNNn #1#2#3#4 { \@@_save_punct_width_aux:nnnn { skip } {#1} { #1/#2/#3 } {#4} \@@_save_punct_width_aux:nnnn { skip } {#1} { plus/#1/#2/#3 } {#4} \@@_save_punct_width_aux:nnnn { skip } {#1} { minus/#1/#2/#3 } {#4} } \cs_new_protected:Npn \@@_save_punct_skip:nNNnnn #1#2#3#4#5#6 { \exp_last_unbraced:Ne \@@_save_punct_skip_aux:nnnnn { {#1} { #1/#2/#3 } { \dim_eval:n {#4} } { \dim_max:nn { \c_zero_dim } {#5} } { \dim_max:nn { \c_zero_dim } {#6} } } } \cs_new_protected:Npn \@@_save_punct_skip_aux:nnnnn #1#2#3#4#5 { \@@_save_punct_width_aux:nnnn { skip } {#1} {#2} { #3 ~ plus ~ #4 ~ minus ~ #5 ~ } \@@_save_punct_width_aux:nnnn { skip } {#1} { plus/#2 } { #3 ~ plus ~ #4 ~ } \@@_save_punct_width_aux:nnnn { skip } {#1} { minus/#2 } { #3 ~ minus ~ #5 ~ } } \cs_new_protected:Npn \@@_save_punct_width_aux:nnnn #1#2#3#4 { \@@_save_punct_width_aux:cen { \@@_punct_csname:n { #1/#3 } } { \use:c { #1_eval:n } {#4} } {#2} } \cs_new_protected:Npn \@@_save_punct_width_aux:Nnn #1#2#3 { \tl_const:Nn #1 {#2} \str_if_eq:nnT {#3} { glue } { \prop_gput:Nnn \g_@@_punct_skip_prop {#2} { } } } \prop_new:N \g_@@_punct_skip_prop \prop_gput:Non \g_@@_punct_skip_prop { \skip_use:N \c_zero_skip } { } \cs_generate_variant:Nn \@@_save_punct_width_aux:Nnn { ce } \cs_new_eq:NN \@@_use_dim_or_skip:nNN \@@_use_punct_skip:nNN % \end{macrocode} % % \changes{v3.1.0}{2012/11/14}{使用 \pkg{xtemplate} 宏包的机制来组织标点符号的处理。} % % 定义标点处理模板。 % \begin{macrocode} \DeclareObjectType { xeCJK / punctuation } { 0 } % \end{macrocode} % % \begin{macrocode} \DeclareTemplateInterface { xeCJK / punctuation } { basic } { 0 } { enabled-global-setting : boolean = true , fixed-punct-width : length = \c_max_dim , fixed-punct-ratio : real = \c_one_fp , mixed-punct-width : length = \KeyValue { fixed-punct-width } , mixed-punct-ratio : real = \KeyValue { fixed-punct-ratio } , middle-punct-width : length = \KeyValue { fixed-punct-width } , middle-punct-ratio : real = \KeyValue { fixed-punct-ratio } , fixed-margin-width : length = \c_max_dim , fixed-margin-ratio : real = \c_one_fp , mixed-margin-width : length = \KeyValue { fixed-margin-width } , mixed-margin-ratio : real = \KeyValue { fixed-margin-ratio } , middle-margin-width : length = \KeyValue { fixed-margin-width } , middle-margin-ratio : real = \KeyValue { fixed-margin-ratio } , bound-punct-width : length = \c_max_dim , bound-punct-ratio : real = \c_nan_fp , bound-margin-width : length = \c_max_dim , bound-margin-ratio : real = \c_zero_fp , enabled-hanging : boolean = false , add-min-bound-to-margin : boolean = false , optimize-margin : boolean = false , margin-minimum : length = \c_zero_dim , enabled-kerning : boolean = true , min-bound-to-kerning : boolean = false , kerning-total-width : length = \c_max_dim , kerning-total-ratio : real = 0.75 , optimize-kerning : boolean = false , same-align-margin : length = \c_max_dim , same-align-ratio : real = \c_nan_fp , different-align-margin : length = \c_max_dim , different-align-ratio : real = \c_nan_fp , kerning-margin-width : length = \c_max_dim , kerning-margin-ratio : real = \c_one_fp , kerning-margin-minimum : length = \c_zero_dim } % \end{macrocode} % % \begin{macrocode} \DeclareTemplateCode { xeCJK / punctuation } { basic } { 0 } { enabled-global-setting = \l_@@_enabled_global_setting_bool , fixed-punct-width = \l_@@_fixed_punct_width_dim , fixed-punct-ratio = \l_@@_fixed_punct_ratio_fp , mixed-punct-width = \l_@@_mixed_punct_width_dim , mixed-punct-ratio = \l_@@_mixed_punct_ratio_fp , middle-punct-width = \l_@@_middle_punct_width_dim , middle-punct-ratio = \l_@@_middle_punct_ratio_fp , fixed-margin-width = \l_@@_fixed_margin_width_dim , fixed-margin-ratio = \l_@@_fixed_margin_ratio_fp , mixed-margin-width = \l_@@_mixed_margin_width_dim , mixed-margin-ratio = \l_@@_mixed_margin_ratio_fp , middle-margin-width = \l_@@_middle_margin_width_dim , middle-margin-ratio = \l_@@_middle_margin_ratio_fp , bound-punct-width = \l_@@_bound_punct_width_dim , bound-punct-ratio = \l_@@_bound_punct_ratio_fp , bound-margin-width = \l_@@_bound_margin_width_dim , bound-margin-ratio = \l_@@_bound_margin_ratio_fp , enabled-hanging = \l_@@_enabled_hanging_bool , add-min-bound-to-margin = \l_@@_add_min_bound_to_margin_bool , optimize-margin = \l_@@_optimize_margin_bool , margin-minimum = \l_@@_margin_minimum_dim , enabled-kerning = \l_@@_enabled_kerning_bool , min-bound-to-kerning = \l_@@_min_bound_to_kerning_bool , kerning-total-width = \l_@@_kerning_total_width_dim , kerning-total-ratio = \l_@@_kerning_total_ratio_fp , optimize-kerning = \l_@@_optimize_kerning_bool , same-align-margin = \l_@@_same_align_margin_dim , same-align-ratio = \l_@@_same_align_ratio_fp , different-align-margin = \l_@@_different_align_margin_dim , different-align-ratio = \l_@@_different_align_ratio_fp , kerning-margin-width = \l_@@_kerning_margin_width_dim , kerning-margin-ratio = \l_@@_kerning_margin_ratio_fp , kerning-margin-minimum = \l_@@_kerning_margin_minimum_dim } { \AssignTemplateKeys } % \end{macrocode} % % \begin{macro}[int]{\xeCJK_get_punct_bounds:NN} % |#1| 为 \cs{c_@@_left_tl} 或 \cs{c_@@_right_tl},|#2| 为标点符号。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_get_punct_bounds:NN #1#2 { \tl_if_exist:cF { \@@_punct_csname:n { dim/glue/#1/#2 } } { \@@_get_punct_bounds_aux:NN #1 #2 } } \cs_new_protected:Npn \@@_get_punct_bounds_aux:NN { \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl { \@@_save_punct_margin_plain:NN } { \@@_save_punct_margin:NN } } \cs_new_protected:Npn \xeCJK_get_punct_bounds:No { \exp_last_unbraced:NNo \xeCJK_get_punct_bounds:NN } \cs_new_protected:Npn \@@_save_punct_margin_plain:NN #1#2 { \@@_save_punct_dim:nNNn { glue } #1 #2 { \c_zero_dim } \@@_save_punct_dim:nNNn { offset } #1 #2 { \c_zero_dim } \@@_save_punct_dim:nNNn { margin } #1 #2 { \c_zero_dim } \@@_save_punct_dim:nNNn { rule } \c_@@_left_tl {#2} { \c_zero_dim } \@@_save_punct_dim:nNNn { rule } \c_@@_right_tl {#2} { \c_zero_dim } \@@_save_punct_dim:nNNn { bound } \c_@@_left_tl {#2} { \c_zero_dim } \@@_save_punct_dim:nNNn { bound } \c_@@_right_tl {#2} { \c_zero_dim } \@@_save_punct_skip:nNNn { glue } #1 #2 { \c_zero_skip } } \cs_new_protected:Npn \@@_save_punct_margin:NN #1#2 { \group_begin: \xeCJK_select_punct_font: \xeCJK_fallback_punct_symbol:NN \xeCJK_calc_punct_dimen:N #2 \group_end: \dim_set:Nn \l_@@_bound_dim { \@@_use_punct_dim:nNN { bound } #1 #2 } \tl_if_eq:NNTF #1 \c_@@_right_tl { \tl_set_eq:NN \l_@@_reverse_tl \c_@@_left_tl } { \tl_set_eq:NN \l_@@_reverse_tl \c_@@_right_tl } \dim_set:Nn \l_@@_reverse_bound_dim { \@@_use_punct_dim:nNN { bound } \l_@@_reverse_tl #2 } \UseInstance { xeCJK / punctuation } { \l_xeCJK_punct_style_tl } \xeCJK_punct_margin_process:NN #1 #2 \xeCJK_punct_offset_process:NN #1 #2 \@@_punct_if_long:NT #2 { \@@_long_punct_kerning:N #2 } } \tl_new:N \l_@@_reverse_tl \dim_new:N \l_@@_bound_dim \dim_new:N \l_@@_reverse_bound_dim % \end{macrocode} % \end{macro} % % \changes{v3.7.0}{2018/03/12}{修正长标点被隔开时的压缩处理错误。} % % \begin{macro}[int]{\@@_long_punct_kerning:N} % \changes{v3.4.3}{2016/10/27}{考虑破折号边界为负值的情况。} % 相同长标点压缩。对于破折号,计算两标点之间的空白,保证它中间不被断开。 % 注意,破折号的边界可能为负值(比如方正新书宋),此时不必压缩。 % \begin{macrocode} \cs_new_protected:Npn \@@_long_punct_kerning:N #1 { \dim_set:Nn \l_@@_tmp_dim { \dim_max:nn { \l_@@_bound_dim + \l_@@_reverse_bound_dim } { \c_zero_dim } } \@@_save_punct_dim:nNNn { bound_width } #1 #1 { \l_@@_tmp_dim } \dim_set:Nn \l_@@_tmp_dim { \str_case:nnTF {#1} { { ^^^^2025 } { } { ^^^^2026 } { } } { \c_zero_dim } { -\l_@@_tmp_dim } } \@@_save_punct_dim:nNNn { kern } #1 #1 { \l_@@_tmp_dim } \@@_save_punct_skip:nNNn { kern } #1 #1 { \l_@@_tmp_dim } \dim_add:Nn \l_@@_tmp_dim { \dim_max:nn { \l_@@_bound_dim } { \c_zero_dim } } \@@_save_punct_dim:nNNn { bound_kern } #1 #1 { \l_@@_tmp_dim } \@@_save_punct_skip:nNNn { bound_kern } #1 #1 { \l_@@_tmp_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_get_punct_kerning:NN} % 标点压缩。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_get_punct_kerning:NN #1#2 { \tl_if_exist:cF { \@@_punct_csname:n { dim/kern/#1/#2 } } { \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl { \@@_save_punct_kerning_plain:NN } { \@@_save_punct_kerning:NN } #1 #2 } } \cs_new_protected:Npn \xeCJK_get_punct_kerning:oN { \exp_after:wN \xeCJK_get_punct_kerning:NN } \cs_new_protected:Npn \@@_save_punct_kerning_plain:NN #1#2 { \@@_save_punct_dim:nNNn { kern } #1 #2 { \c_zero_dim } \@@_save_punct_dim:nNNn { bound_kern } #1 #2 { \c_zero_dim } \@@_save_punct_dim:nNNn { bound_width } #1 #2 { \c_zero_dim } \@@_save_punct_skip:nNNn { kern } #1 #2 { \c_zero_skip } \@@_save_punct_skip:nNNn { bound_kern } #1 #2 { \c_zero_skip } } \cs_new_protected:Npn \@@_save_punct_kerning:NN { \UseInstance { xeCJK / punctuation } { \l_xeCJK_punct_style_tl } \xeCJK_punct_kerning_process:NN } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_punct_margin_process:NN} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_punct_margin_process:NN #1#2 { \dim_set:Nn \l_@@_tmp_dim { \bool_if:NTF \l_@@_enabled_global_setting_bool { \cs_if_exist_use:cF { g_@@_punct_width/#2/tl } { \tl_if_empty:NTF \g_@@_punct_width_tl { \@@_calc_punct_width:N #2 } { \g_@@_punct_width_tl } } } { \@@_calc_punct_width:N #2 } } \dim_set:Nn \l_@@_margin_dim { \dim_max:nn { \l_@@_margin_minimum_dim } { \dim_compare:nNnTF \l_@@_tmp_dim < \c_max_dim { \@@_punct_if_middle:NTF #2 { ( \l_@@_tmp_dim - ( \@@_use_punct_dim:nN { dimen } #2 ) ) / 2 } { \bool_if:NTF \l_@@_optimize_margin_bool { \dim_max:nn { \dim_min:nn { \l_@@_bound_dim } { \l_@@_reverse_bound_dim } } } { \use:n } { \l_@@_tmp_dim - \l_@@_reverse_bound_dim - ( \@@_use_punct_dim:nN { dimen } #2 ) } } } { \bool_if:NTF \l_@@_optimize_margin_bool { \dim_min:nn { \l_@@_bound_dim } } { \use:n } { \@@_calc_margin_width:N #2 } } } } \@@_save_punct_dim:nNNn { margin } #1 #2 { \l_@@_margin_dim } } \dim_new:N \l_@@_margin_dim % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_calc_punct_width:N} % \begin{macrocode} \cs_new:Npn \@@_calc_punct_width:N #1 { \@@_punct_if_middle:NTF #1 { \@@_punct_width_or_ratio:nN { middle } } { \@@_punct_if_mixed_width:NTF #1 { \@@_punct_width_or_ratio:nN { mixed } } { \@@_punct_width_or_ratio:nN { fixed } } } #1 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_calc_margin_width:N} % \begin{macrocode} \cs_new:Npn \@@_calc_margin_width:N #1 { \@@_punct_if_middle:NTF #1 { \dim_compare:nNnTF \l_@@_middle_margin_width_dim < \c_max_dim { \l_@@_middle_margin_width_dim } { \@@_dim_ratio:Nn \l_@@_middle_margin_ratio_fp { ( \l_@@_bound_dim + \l_@@_reverse_bound_dim ) / 2 } } } { \@@_punct_if_mixed_width:NTF #1 { \@@_margin_width_or_ratio:n { mixed } } { \@@_margin_width_or_ratio:n { fixed } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_dim_ratio:Nn} % \begin{macrocode} \cs_new:Npn \@@_dim_ratio:Nn #1#2 { \fp_to_dim:n { #1 \dim_to_fp:n {#2} } } \cs_generate_variant:Nn \@@_dim_ratio:Nn { c } % \end{macrocode} % \end{macro} % % \changes{v3.8.9}{2022/05/26}{修正居中标点悬挂错误。} % % \begin{macro}[int]{\xeCJK_punct_offset_process:NN} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_punct_offset_process:NN #1#2 { \dim_set:Nn \l_@@_tmp_dim { \bool_if:NTF \l_@@_enabled_global_setting_bool { \cs_if_exist_use:cF { g_@@_punct_bound_width/#2/tl } { \tl_if_empty:NTF \g_@@_punct_bound_width_tl { \@@_punct_width_or_ratio:nN { bound } #2 } { \g_@@_punct_bound_width_tl } } } { \@@_punct_width_or_ratio:nN { bound } #2 } } \dim_set:Nn \l_@@_tmp_dim { \bool_if:NTF \l_@@_enabled_hanging_bool { \use:n } { \dim_max:nn { \l_@@_margin_minimum_dim } } { \dim_compare:nNnTF \l_@@_tmp_dim < \c_max_dim { \@@_punct_if_middle:NTF #2 { \l_@@_tmp_dim - \l_@@_margin_dim - ( \@@_use_punct_dim:nN { dimen } #2 ) } { \l_@@_tmp_dim - \l_@@_reverse_bound_dim - ( \@@_use_punct_dim:nN { dimen } #2 ) } } { \bool_if:NTF \l_@@_optimize_margin_bool { \dim_min:nn { \l_@@_bound_dim } } { \use:n } { \@@_margin_width_or_ratio:n { bound } } } } } \@@_save_punct_dim:nNNn { offset } #1 #2 { \l_@@_tmp_dim } \@@_save_punct_dim:nNNn { rule } #1 #2 { \l_@@_tmp_dim - \l_@@_bound_dim } \@@_save_punct_dim:nNNn { rule } \l_@@_reverse_tl #2 { \l_@@_tmp_dim - \l_@@_reverse_bound_dim } \@@_save_punct_dim:nNNn { glue } #1 #2 { \l_@@_margin_dim - \l_@@_tmp_dim } \@@_save_punct_skip:nNNnnn { glue } #1 #2 { \l_@@_margin_dim - \l_@@_tmp_dim } { \@@_punct_if_middle:NTF #2 { ( \@@_use_punct_dim:nN { width } #2 - \@@_use_punct_dim:nN { dimen } #2 ) / 2 - \l_@@_margin_dim } { \l_@@_bound_dim - \l_@@_margin_dim } } { \@@_punct_if_middle:NTF #2 { \l_@@_margin_dim / 2 } { \l_@@_margin_dim - \l_@@_reverse_bound_dim } } } % \end{macrocode} % \end{macro} % % \changes{v3.2.7}{2013/08/25}{标点宽度设置禁用比例选项的值改为 \texttt{nan}。} % \changes{v3.8.0}{2020/02/10}{应用 \cs{fp_if_nan:nTF}。} % % \begin{macro}{\@@_punct_width_or_ratio:nN} % \begin{macrocode} \cs_new:Npn \@@_punct_width_or_ratio:nN #1#2 { \dim_compare:nNnTF { \use:c { l_@@_#1_punct_width_dim } } < \c_max_dim { \use:c { l_@@_#1_punct_width_dim } } { \fp_if_nan:nTF { \use:c { l_@@_#1_punct_ratio_fp } } { \c_max_dim } { \@@_dim_ratio:cn { l_@@_#1_punct_ratio_fp } { \@@_use_punct_dim:nN { width } #2 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_margin_width_or_ratio:n} % \begin{macrocode} \cs_new:Npn \@@_margin_width_or_ratio:n #1 { \dim_compare:nNnTF { \use:c { l_@@_#1_margin_width_dim } } < \c_max_dim { \use:c { l_@@_#1_margin_width_dim } } { \@@_dim_ratio:cn { l_@@_#1_margin_ratio_fp } { \l_@@_bound_dim } } \bool_if:NT \l_@@_add_min_bound_to_margin_bool { + \dim_min:nn \l_@@_bound_dim \l_@@_reverse_bound_dim } } % \end{macrocode} % \end{macro} % % \changes{v3.4.4}{2016/11/30}{不压缩长标点与其他标点的间距。} % % \begin{macro}[int]{\xeCJK_punct_kerning_process:NN} % 当标点之一为长标点时,不必进行压缩。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_punct_kerning_process:NN #1#2 { \dim_set:Nn \l_@@_margin_dim { \@@_original_kerning_margin:NN #1 #2 } \dim_set:Nn \l_@@_minimum_bound_dim { \@@_punct_min_bound:NN #1 #2 } \@@_punct_if_long:NTF #1 { \bool_set_false:N \l_@@_enabled_kerning_bool } { \@@_punct_if_long:NT #2 { \bool_set_false:N \l_@@_enabled_kerning_bool } } \dim_set:Nn \l_@@_kerning_margin_dim { \bool_if:NTF \l_@@_enabled_global_setting_bool { \cs_if_exist_use:cF { g_@@_punct/kern/#1/#2/tl } { \@@_punct_kerning_process_aux:NN #1 #2 } } { \@@_punct_kerning_process_aux:NN #1 #2 } } \@@_save_kerning:nnNN { kern } { bound } #1 #2 \@@_save_punct_dim:nNNn { bound_width } #1 #2 { \l_@@_kerning_margin_dim - \l_@@_tmp_dim } \@@_punct_if_right:NTF #1 { \@@_punct_if_right:NTF #2 { \@@_save_kerning:nnnNN { bound_kern } { offset } { bound } } { \@@_save_kerning:nnNN { bound_kern } { offset } } } { \@@_punct_if_right:NTF #2 { \@@_save_kerning:nnNN { bound_kern } { bound } } { \@@_save_kerning:nnnNN { bound_kern } { bound } { offset } } } #1 #2 } \cs_new:Npn \@@_punct_kerning_process_aux:NN #1#2 { \bool_if:NTF \l_@@_enabled_kerning_bool { \@@_calc_kerning_margin:NN #1 #2 } { \l_@@_margin_dim } } \dim_new:N \l_@@_minimum_bound_dim \dim_new:N \l_@@_kerning_margin_dim % \end{macrocode} % \end{macro} % % \changes{v3.4.0}{2016/05/12}{标点符号的压缩量能伸长到原始空白,能收缩到较小边距。} % % \begin{macro}{\@@_save_kerning:nnNN} % 相邻两个标点符号的间距能伸长到原始空白(未压缩时的状态),能收缩到较小边距。 % \begin{macrocode} \cs_new_protected:Npn \@@_save_kerning:nnNN #1#2 { \@@_save_kerning:nnnNN {#1} {#2} {#2} } \cs_new_protected:Npn \@@_save_kerning:nnnNN #1#2#3#4#5 { \dim_set:Nn \l_@@_tmp_dim { \l_@@_kerning_margin_dim - ( \@@_use_punct_dim:nNN {#2} \c_@@_right_tl #4 ) - ( \@@_use_punct_dim:nNN {#3} \c_@@_left_tl #5 ) } \@@_save_punct_dim:nNNn {#1} #4 #5 { \l_@@_tmp_dim } \@@_save_punct_skip:nNNnnn {#1} #4 #5 { \l_@@_tmp_dim } { \l_@@_margin_dim - \l_@@_kerning_margin_dim } { \l_@@_kerning_margin_dim - \l_@@_minimum_bound_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_original_kerning_margin:NN} % 相邻两个标点符号之间的本来空白宽度。 % \begin{macrocode} \cs_new:Npn \@@_original_kerning_margin:NN #1#2 { \dim_eval:n { \@@_use_punct_dim:nNN { \@@_punct_if_right:NTF #1 { margin } { bound } } \c_@@_right_tl #1 + \@@_use_punct_dim:nNN { \@@_punct_if_right:NTF #2 { bound } { margin } } \c_@@_left_tl #2 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_calc_kerning_margin:NN,\@@_calc_kerning_margin_aux:NN} % \begin{macrocode} \cs_new:Npn \@@_calc_kerning_margin:NN #1#2 { \dim_max:nn { \l_@@_kerning_margin_minimum_dim } { \bool_if:NTF \l_@@_min_bound_to_kerning_bool { \l_@@_minimum_bound_dim } { \bool_if:NTF \l_@@_optimize_kerning_bool { \dim_max:nn { \l_@@_minimum_bound_dim } } { \use:n } { \@@_calc_kerning_margin_aux:NN #1 #2 } } } } \cs_new:Npn \@@_calc_kerning_margin_aux:NN #1#2 { \dim_compare:nNnTF \l_@@_kerning_total_width_dim < \c_max_dim { \@@_calc_kerning_margin:nNN \l_@@_kerning_total_width_dim } { \fp_if_nan:nTF { \l_@@_kerning_total_ratio_fp } { \xeCJK_if_same_class:NNTF #1 #2 { \@@_kerning_width_or_ratio:nNN { same } } { \@@_kerning_width_or_ratio:nNN { different } } } { \@@_calc_kerning_margin:nNN { \@@_dim_ratio:Nn \l_@@_kerning_total_ratio_fp { \@@_use_punct_dim:nN { width } #1 + \@@_use_punct_dim:nN { width } #2 } } } } #1 #2 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_kerning_width_or_ratio:nNN} % \begin{macrocode} \cs_new:Npn \@@_kerning_width_or_ratio:nNN #1#2#3 { \dim_compare:nNnTF { \use:c { l_@@_#1_align_margin_dim } } < \c_max_dim { \use:c { l_@@_#1_align_margin_dim } } { \fp_if_nan:nTF { \use:c { l_@@_#1_align_ratio_fp } } { \dim_compare:nNnTF \l_@@_kerning_margin_width_dim < \c_max_dim { \l_@@_kerning_margin_width_dim \use_none:n } { \@@_dim_ratio:Nn \l_@@_kerning_margin_ratio_fp } } { \@@_dim_ratio:cn { l_@@_#1_align_ratio_fp } } { \l_@@_margin_dim } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_punct_min_bound:NN} % \begin{macrocode} \cs_new:Npn \@@_punct_min_bound:NN #1#2 { \dim_max:nn { \dim_min:nn { \@@_use_punct_dim:nNN { bound } \c_@@_left_tl #1 } { \@@_use_punct_dim:nNN { bound } \c_@@_right_tl #1 } } { \dim_min:nn { \@@_use_punct_dim:nNN { bound } \c_@@_left_tl #2 } { \@@_use_punct_dim:nNN { bound } \c_@@_right_tl #2 } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_calc_kerning_margin:nNN} % |#2| 和 |#3| 为相邻的两个标点,|#1| 为要确定的相邻两个标点总共占的宽度。 % \begin{macrocode} \cs_new:Npn \@@_calc_kerning_margin:nNN #1#2#3 { \dim_eval:n { (#1) - ( \@@_use_punct_dim:nNN { \@@_punct_if_right:NTF #2 { bound } { margin } } \c_@@_left_tl #2 ) - ( \@@_use_punct_dim:nNN { \@@_punct_if_right:NTF #3 { margin } { bound } } \c_@@_right_tl #3 ) - ( \@@_use_punct_dim:nN { dimen } #2 ) - ( \@@_use_punct_dim:nN { dimen } #3 ) } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_calc_punct_dimen:N} % 计算标点的左右实际边距和实际尺寸。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_calc_punct_dimen:N #1 { \@@_save_punct_dim:nNNn { bound } \c_@@_left_tl #1 { \xeCJK_glyph_bounds:NN 1 #1 } \@@_save_punct_dim:nNNn { bound } \c_@@_right_tl #1 { \xeCJK_glyph_bounds:NN 3 #1 } \@@_save_punct_dim:nNn { width } #1 { \tex_fontcharwd:D \tex_font:D `#1 } \@@_save_punct_dim:nNn { dimen } #1 { ( \@@_use_punct_dim:nN { width } #1 ) - ( \@@_use_punct_dim:nNN { bound } \c_@@_left_tl #1 ) - ( \@@_use_punct_dim:nNN { bound } \c_@@_right_tl #1 ) } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_glyph_bounds:NN} % 用 \tn{XeTeXglyphbounds} 取得标点符号的上下左右空白。 % \begin{macrocode} \cs_new:Npn \xeCJK_glyph_bounds:NN #1#2 { \tex_XeTeXglyphbounds:D #1 ~ \tex_XeTeXcharglyph:D `#2 \exp_stop_f: } % \end{macrocode} % \end{macro} % % \changes{v3.8.3}{2020/04/09}{重构 \opt{PunctStyle} 选项,完全展开参数。} % % \begin{macro}{PunctStyle} % \begin{macrocode} \keys_define:nn { xeCJK / options } { PunctStyle .code:n = \exp_args:Nx \@@_set_punct_style:n {#1} } \cs_new_protected:Npn \@@_set_punct_style:n #1 { \IfInstanceExistTF { xeCJK / punctuation } {#1} { \tl_set:Nn \l_xeCJK_punct_style_tl {#1} } { \prop_get:NnNF \c_@@_punct_style_alias_prop {#1} \l_xeCJK_punct_style_tl { \@@_error:nx { punct-style-unknown } {#1} } } } \prop_const_from_keyval:Nn \c_@@_punct_style_alias_prop { halfwidth = banjiao , fullwidth = quanjiao , mixedwidth = kaiming , marginkerning = hangmobanjiao , plain = plain } \tl_new:N \l_xeCJK_punct_style_tl \tl_const:Nn \c_@@_punct_style_plain_tl { plain } \@@_msg_new:nn { punct-style-unknown } { Punctuation~style~"#1"~is~unknown. \\\\ The~available~styles~are~listed~as~follow.\\\\ "plain,~\seq_use:Nnnn \g_@@_punct_style_seq { ~and~ } { ,~ } { ,~and~ }".\\ } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_trim_spaces:n} % \pkg{xparse} 处理函数,先完全展开参数再删除两边空格。 % \begin{macrocode} \cs_new_protected:Npn \@@_trim_spaces:n #1 { \tl_set:Nx \ProcessedArgument { \exp_args:Ne \tl_trim_spaces:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKDeclarePunctStyle} % 定义新的标点处理风格,已经存在的同名风格将被覆盖。 % \begin{macrocode} \NewDocumentCommand \xeCJKDeclarePunctStyle { > { \@@_trim_spaces:n } m m } { \IfInstanceExistTF { xeCJK / punctuation } {#1} { \@@_warning:nx { punct-style-already-defined } {#1} } { \seq_gput_right:Nn \g_@@_punct_style_seq {#1} } \DeclareInstance { xeCJK / punctuation } {#1} { basic } {#2} } \seq_new:N \g_@@_punct_style_seq \@@_msg_new:nn { punct-style-already-defined } { Punctuation~style~"#1"~is~already~defined!. \\\\ The~existing~style~of~"#1"~will~be~overwritten.\\ } \@onlypreamble \xeCJKDeclarePunctStyle % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKEditPunctStyle} % 对已有的标点处理风格进行修改。 % \begin{macrocode} \NewDocumentCommand \xeCJKEditPunctStyle { > { \@@_trim_spaces:n } m m } { \IfInstanceExistTF { xeCJK / punctuation } {#1} { \EditInstance { xeCJK / punctuation } {#1} {#2} } { \@@_error:nx { punct-style-unknown } {#1} } } \@onlypreamble \xeCJKEditPunctStyle % \end{macrocode} % \end{macro} % % 默认设置即为全角格式。 % \begin{macrocode} \xeCJKDeclarePunctStyle { quanjiao } { } % \end{macrocode} % % \begin{macrocode} \xeCJKDeclarePunctStyle { hangmobanjiao } { enabled-kerning = false } % \end{macrocode} % % \begin{macrocode} \xeCJKDeclarePunctStyle { banjiao } { fixed-punct-ratio = 0.5 , optimize-margin = true , kerning-total-ratio = 0.5 , optimize-kerning = true } % \end{macrocode} % % \begin{macrocode} \xeCJKDeclarePunctStyle { kaiming } { fixed-punct-ratio = 0.5 , mixed-punct-ratio = 0.8 , optimize-margin = true , kerning-total-ratio = 0.5 , optimize-kerning = true } % \end{macrocode} % % \begin{macrocode} \xeCJKDeclarePunctStyle { CCT } { fixed-punct-ratio = 0.7 , optimize-margin = true , kerning-total-ratio = 0.6 , optimize-kerning = true } % \end{macrocode} % % \subsection{后备字体} % % \changes{v3.8.4}{2020/05/31}{重构后备字体的实现,修正标点符号无后备字体的问题。} % % \begin{macro}{AutoFallBack} % 后备字体的宏包选项声明。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { AutoFallBack .choice: , AutoFallBack / true .code:n = { \cs_set_eq:NN \xeCJK_fallback_symbol:NN \@@_fallback_symbol:NN \cs_set_eq:NN \xeCJK_fallback_punct_symbol:NN \@@_fallback_punct_symbol:NN \cs_set_eq:NN \xeCJK_clear_fallback_font: \@@_clear_fallback_font: } , AutoFallBack / false .code:n = { \xeCJK_cs_clear:N \xeCJK_fallback_symbol:NN \xeCJK_cs_clear:N \xeCJK_fallback_punct_symbol:NN \xeCJK_cs_clear:N \xeCJK_clear_fallback_font: } , AutoFallBack .default:n = { true } , fallback .meta:n = { AutoFallBack = true } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_fallback_symbol:NN,\xeCJK_fallback_punct_symbol:NN} % 测试当前字体中是否存在当前字符,如存在则直接输出,否则启用后备字体。 % \begin{macrocode} \cs_new_protected:Npn \@@_fallback_symbol:NN #1#2 { \xeCJK_reset_fallback_font: \xeCJK_glyph_if_exist:NF #2 { \@@_fallback_symbol_aux:NN } #1#2 } \cs_new_protected:Npn \@@_fallback_punct_symbol:NN #1#2 { \xeCJK_reset_fallback_font: \xeCJK_glyph_if_exist:NF #2 { \@@_fallback_punct_symbol_aux:NN } #1#2 } \cs_new_eq:NN \xeCJK_fallback_symbol:NN \prg_do_nothing: \cs_new_eq:NN \xeCJK_fallback_punct_symbol:NN \prg_do_nothing: \cs_new_protected:Npn \@@_fallback_symbol_aux:NN { \@@_fallback_symbol_aux:nnNN { \CJK@family } { \l_xeCJK_family_tl } } \cs_new_protected:Npn \@@_fallback_punct_symbol_aux:NN { \@@_fallback_symbol_aux:nnNN { \CJK@punctfamily } { \l_xeCJK_punct_family_tl } } \cs_new_protected:Npn \@@_fallback_symbol_aux:nnNN { \cs_set_protected:Npx \xeCJK_reset_fallback_font: { \tex_the:D \tex_font:D \xeCJK_clear_fallback_font: } \exp_args:Nee \@@_fallback_loop:nnNN } \cs_new_protected:Npn \@@_clear_fallback_font: { \cs_set_eq:NN \xeCJK_reset_fallback_font: \prg_do_nothing: } \cs_new_eq:NN \xeCJK_reset_fallback_font: \prg_do_nothing: \cs_new_eq:NN \xeCJK_clear_fallback_font: \prg_do_nothing: % \end{macrocode} % \end{macro} % % \changes{v3.5.1}{2017/11/16}{修正 fallback 字体后无法忽略空格的错误。} % \changes{v3.2.12}{2014/05/12}{更新 \cs{int_to_Hex:n}。} % % \begin{macro}[int]{\@@_fallback_loop:nnNN} % \changes{v3.1.0}{2012/11/19}{调整备用字体的循环方式。} % \changes{v3.2.4}{2013/06/30} % {使 \tn{CJKfamilydefault} 的 \texttt{FallBack} 设置全局可用。} % 循环测试后备字体是否包含字符 |#1|。若后备字体中存在该字符或者再没有后备字体,则 % 结束循环。当前字体族没有备用字体时,使用 \tn{CJKfamilydefault} 的设置。 % \begin{macrocode} \cs_new_protected:Npn \@@_fallback_loop:nnNN { \cs_set_eq:NN \@@_fallback_loop:TF \use_i:nn \@@_fallback_loop:nnnNN { FallBack } } \cs_new_protected:Npn \@@_fallback_loop:nnnNN #1#2#3 { \xeCJK_select_fallback_font:nnn {#1} {#2} {#3} \@@_fallback_loop:TF { \@@_fallback_loop_aux:nnnNN } { \@@_fallback_missing_glyph:nnnNN } {#1} {#2} {#3} } \cs_new_protected:Npn \@@_fallback_loop_aux:nnnNN #1#2#3#4#5 { \xeCJK_glyph_if_exist:NF #5 { \@@_fallback_loop:nnnNN { #1/FallBack } {#2} {#3} } #4#5 } \cs_new_protected:Npn \@@_fallback_missing_glyph:nnnNN #1#2#3#4#5 { \@@_warning:nxxx { missing-glyph } {#1} {#2} {#5} #4#5 } \cs_new_protected:Npn \xeCJK_select_fallback_font:nnn #1#2 { \@@_select_fallback_font:cnnn { \@@_font_csname:n { #2/#1 } } {#1} {#2} } \cs_new_protected:Npn \@@_select_fallback_font:Nnnn #1 { \cs_if_exist:NF #1 { \@@_fallback_font_initial:NNnnn } #1 \use_none:nnn } \cs_generate_variant:Nn \@@_select_fallback_font:Nnnn { c } \cs_new_protected:Npn \@@_fallback_font_initial:NNnnn #1#2#3#4#5 { \xeCJK_family_if_exist:nTF { #5/#3 } { \@@_font_initial:Nn #1 { #5/#3 } } { \@@_fallback_font_initial_auxi:Nnnn #1 {#5} {#3} {#4} } #1 } \cs_new_protected:Npn \@@_fallback_font_initial_auxi:Nnnn #1 { \exp_args:NNe \@@_fallback_font_initial_auxii:Nnnnn #1 { \CJKfamilydefault } } \cs_new_protected:Npn \@@_fallback_font_initial_auxii:Nnnnn #1#2#3 { \str_if_eq:nnTF {#2} {#3} { \@@_fallback_loop_end:Nnnn } { \@@_fallback_font_initial_auxiii:Nnnn } #1 {#2} } \cs_new_protected:Npn \@@_fallback_font_initial_auxiii:Nnnn #1#2 { \xeCJK_family_if_exist:nTF {#2} { \@@_fallback_font_initial_auxiv:Nnnn } { \@@_fallback_loop_end:Nnnn } #1 {#2} } \cs_new_protected:Npn \@@_fallback_font_initial_auxiv:Nnnn #1#2#3#4 { \@@_font_initial:Nn #1 {#2} \exp_args:Nc \@@_fallback_font_initial_auxiii:Nnnn { \@@_font_csname:n { #4/#3/FallBack } } { #2/FallBack } { #3/FallBack } {#4} } \cs_new_eq:NN \@@_fallback_loop:TF \use_i:nn \cs_new_protected:Npn \@@_fallback_loop_end:Nnnn #1#2#3#4 { \cs_gset_eq:NN #1 \@@_fallback_loop_end: } \cs_new_protected:Npn \@@_fallback_loop_end: { \cs_set_eq:NN \@@_fallback_loop:TF \use_ii:nn } \@@_msg_new:nn { missing-glyph } { CJKfamily~`\@@_msg_family_map:n {#2}'~(#1)~ does~not~contain~glyph~`#3'~ ( U + \int_to_Hex:n { `#3 } )~\msg_line_context:. } % \end{macrocode} % \end{macro} % % \begin{macro}{\setCJKfallbackfamilyfont} % \changes{v3.4.3}{2016/11/18}{允许字体属性可选项在后的新语法。} % \begin{macrocode} \NewDocumentCommand \setCJKfallbackfamilyfont { m o m } { \@@_pass_args:nnnn { \xeCJK_set_family_fallback:nnn {#1} } {#2} {#3} { } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_set_family_fallback:nnn} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_set_family_fallback:nnn #1#2#3 { \group_begin: \tl_set:Nn \l_@@_fallback_family_tl {#1} \prop_get:NoNF \g_@@_family_font_name_prop \l_@@_fallback_family_tl \l_@@_font_name_tl { \tl_clear:N \l_@@_font_name_tl } \clist_set:Nn \l_@@_public_options_clist {#2} \clist_map_function:nN {#3} \@@_set_family_fallback:n \group_end: } \cs_new_protected:Npn \@@_set_family_fallback:n #1 { \tl_put_right:Nn \l_@@_fallback_family_tl { /FallBack } \@@_get_sub_features:on \l_@@_fallback_family_tl {#1} \clist_concat:NNN \l_@@_sub_font_options_clist \l_@@_public_options_clist \l_@@_sub_font_options_clist \exp_args:Nooo \xeCJK_set_family:nnn \l_@@_fallback_family_tl \l_@@_sub_font_options_clist \l_@@_sub_font_name_tl } \tl_new:N \l_@@_fallback_family_tl \clist_new:N \l_@@_public_options_clist % \end{macrocode} % \end{macro} % % % \subsection{CJK 字体族声明方式} % % \begin{macrocode} \bool_new:N \g_@@_auto_fake_bold_bool \bool_new:N \g_@@_auto_fake_slant_bool \fp_new:N \g_@@_embolden_factor_fp \fp_new:N \g_@@_slant_factor_fp % \end{macrocode} % % \begin{macro}{AutoFakeBold, AutoFakeSlant,EmboldenFactor,SlantFactor} % 伪粗体和伪斜体的宏包选项声明。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { AutoFakeBold .choices:nn = { true , false } { \use:c { bool_gset_ \l_keys_choice_tl :N } \g_@@_auto_fake_bold_bool } , AutoFakeBold / unknown .code:n = { \bool_gset_true:N \g_@@_auto_fake_bold_bool \fp_gset:Nn \g_@@_embolden_factor_fp { \l_keys_value_tl } } , AutoFakeBold .default:n = { true } , AutoFakeSlant .choices:nn = { true , false } { \use:c { bool_gset_ \l_keys_choice_tl :N } \g_@@_auto_fake_slant_bool } , AutoFakeSlant / unknown .code:n = { \bool_gset_true:N \g_@@_auto_fake_slant_bool \fp_gset:Nn \g_@@_slant_factor_fp { \l_keys_value_tl } } , AutoFakeSlant .default:n = { true } , EmboldenFactor .fp_gset:N = \g_@@_embolden_factor_fp , SlantFactor .fp_gset:N = \g_@@_slant_factor_fp , BoldFont .meta:n = { AutoFakeBold = true } , boldfont .meta:n = { AutoFakeBold = true } , SlantFont .meta:n = { AutoFakeSlant = true } , slantfont .meta:n = { AutoFakeSlant = true } } % \end{macrocode} % \end{macro} % % \changes{v3.2.4}{2013/07/02}{内部调整分区字体的设置方法。} % % \begin{macro}[int]{\xeCJK_new_sub_key:n} % \begin{variable}{\g_@@_sub_key_seq} % 用于定义 CJK 子区字体和备用字体的选项。 % \begin{macrocode} \seq_new:N \g_@@_sub_key_seq \cs_new_protected:Npn \xeCJK_new_sub_key:n #1 { \seq_gput_right:Nn \g_@@_sub_key_seq {#1} \keys_define:nn { xeCJK / features } { #1 .code:n = { \tl_if_blank:nTF {##1} { \prop_clear:N \l_@@_sub_key_prop \tl_set:Nx \l_@@_sub_family_name_tl { \l_@@_family_name_tl /#1 } \clist_remove_all:Nn \l_@@_font_options_clist {#1} } { \tl_clear:N \l_@@_sub_family_name_tl \str_if_eq:nnTF {##1} { * } { \prop_put:Nnn \l_@@_sub_key_prop {#1} { \q_no_value } } { \@@_get_sub_features:nn {#1} {##1} } } } , #1 .default:n = { } } } % \end{macrocode} % \end{variable} % \end{macro} % % \changes{v3.2.4}{2013/07/02}{改进获取分区字体属性的办法。} % % \begin{macro}{\@@_get_sub_features:nn,\@@_get_sub_features:w} % \begin{macrocode} \cs_new_protected:Npn \@@_get_sub_features:nn #1#2 { \tl_set:Nx \l_@@_tmp_tl { \xeCJK_tl_remove_outer_braces:n {#2} } \clist_clear:N \l_@@_sub_font_options_clist \exp_after:wN \@@_get_sub_features:w \l_@@_tmp_tl \q_mark [ \q_nil ] \q_mark \q_stop \tl_if_empty:NTF \l_@@_sub_font_name_tl { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_font_name_tl } { \tl_replace_all:Nno \l_@@_sub_font_name_tl { * } \l_@@_font_name_tl } \prop_put:Nne \l_@@_sub_key_prop {#1} { { \exp_not:o \l_@@_sub_font_options_clist } { \exp_not:o \l_@@_sub_font_name_tl } } } \cs_new_protected:Npn \@@_get_sub_features:w #1 [#2] #3 \q_mark #4 \q_stop { \quark_if_nil:nTF {#2} { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_tmp_tl } { \tl_set:Nx \l_@@_sub_font_name_tl { \xeCJK_tl_remove_outer_braces:n {#3} } \tl_if_empty:NTF \l_@@_sub_font_name_tl { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_tmp_tl } { \clist_set:Nn \l_@@_sub_font_options_clist {#2} } } } \tl_new:N \l_@@_sub_family_name_tl \tl_new:N \l_@@_sub_font_name_tl \clist_new:N \l_@@_sub_font_options_clist \cs_generate_variant:Nn \@@_get_sub_features:nn { o } \cs_generate_variant:Nn \tl_replace_all:Nnn { Nno } % \end{macrocode} % \end{macro} % % \begin{macro}{FallBack} % \begin{macrocode} \xeCJK_new_sub_key:n { FallBack } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{BoldFont,ItalicFont} % 调用字体的属性声明,同 \pkg{fontspec} 宏包。 % \begin{macrocode} \keys_define:nn { xeCJK / features } { BoldFont .tl_set:N = \l_@@_font_name_bf_tl , ItalicFont .tl_set:N = \l_@@_font_name_it_tl } % \end{macrocode} % \end{macro} % % \changes{v3.2.6}{2013/07/31}{\texttt{AutoFakeBold} 和 \texttt{AutoFakeSlant} % 选项直接使用 \pkg{fontspec} 的设置,修正不能调用相应实际字体的问题。} % % \begin{macro}[int]{AutoFakeBold, AutoFakeSlant} % \begin{macrocode} \keys_define:nn { xeCJK / features } { AutoFakeBold .choice: , AutoFakeBold / true .code:n = { \bool_set_true:N \l_@@_auto_fake_bold_bool \fp_set_eq:NN \l_@@_embolden_factor_fp \g_@@_embolden_factor_fp } , AutoFakeBold / false .code:n = { \bool_set_false:N \l_@@_auto_fake_bold_bool } , AutoFakeBold / unknown .code:n = { \bool_set_true:N \l_@@_auto_fake_bold_bool \fp_set:Nn \l_@@_embolden_factor_fp { \l_keys_value_tl } } , AutoFakeBold .default:n = { true } , AutoFakeSlant .choice: , AutoFakeSlant / true .code:n = { \bool_set_true:N \l_@@_auto_fake_slant_bool \fp_set_eq:NN \l_@@_slant_factor_fp \g_@@_slant_factor_fp } , AutoFakeSlant / false .code:n = { \bool_set_false:N \l_@@_auto_fake_slant_bool } , AutoFakeSlant / unknown .code:n = { \bool_set_true:N \l_@@_auto_fake_slant_bool \fp_set:Nn \l_@@_slant_factor_fp { \l_keys_value_tl } } , AutoFakeSlant .default:n = { true } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_family_initial:} % \begin{macrocode} \cs_new_protected:Npn \@@_set_family_initial: { \int_gincr:N \g_@@_family_int \prop_clear:N \l_@@_sub_key_prop \tl_clear:N \l_@@_font_name_bf_tl \tl_clear:N \l_@@_font_name_it_tl \tl_clear:N \l_@@_sub_family_name_tl \clist_clear:N \l_@@_fontspec_options_clist \bool_set_eq:NN \l_@@_auto_fake_bold_bool \g_@@_auto_fake_bold_bool \bool_set_eq:NN \l_@@_auto_fake_slant_bool \g_@@_auto_fake_slant_bool \fp_set_eq:NN \l_@@_embolden_factor_fp \g_@@_embolden_factor_fp \fp_set_eq:NN \l_@@_slant_factor_fp \g_@@_slant_factor_fp } \int_new:N \g_@@_family_int \prop_new:N \l_@@_sub_key_prop \clist_new:N \l_@@_fontspec_options_clist \bool_new:N \l_@@_auto_fake_bold_bool \bool_new:N \l_@@_auto_fake_slant_bool \fp_new:N \l_@@_embolden_factor_fp \fp_new:N \l_@@_slant_factor_fp % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_set_family:nnn} % 设置一个 CJK 新字体族,与 \tn{newfontfamily} 类似,增加 |FallBack| 选项。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_set_family:nnn #1#2#3 { \group_begin: \@@_set_family_initial: \tl_set:Nn \l_@@_family_name_tl {#1} \clist_set:Nn \l_@@_font_options_clist {#2} \tl_set:Nn \l_@@_font_name_tl {#3} \clist_concat:NNN \l_@@_font_options_clist \g_@@_default_features_clist \l_@@_font_options_clist \keys_set_known:noN { xeCJK / features } \l_@@_font_options_clist \l_@@_fontspec_options_clist \@@_binding_sub_family: \@@_parse_font_shape: \@@_check_family:o \l_@@_family_name_tl \@@_gset_family_cs:n { \l_@@_family_name_tl } \@@_save_family_info: \@@_set_sub_block_family: \group_end: } \tl_new:N \l_@@_family_name_tl \tl_new:N \l_@@_font_name_tl \clist_new:N \l_@@_font_options_clist \cs_generate_variant:Nn \xeCJK_set_family:nnn { e , o } % \end{macrocode} % \end{macro} % % \changes{v3.7.2}{2019/03/27}{删除定义新字体族时过滤重复选项的功能。} % % \begin{macro}{\@@_binding_sub_family:} % \begin{macrocode} \cs_new_protected:Npn \@@_binding_sub_family: { \tl_if_empty:NF \l_@@_sub_family_name_tl { \tl_set_eq:NN \l_@@_family_name_tl \l_@@_sub_family_name_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_gset_family_cs:n} % \begin{macrocode} \cs_new_protected:Npn \@@_gset_family_cs:n #1 { \cs_gset_protected:cpx { \@@_family_csname:n {#1} } { \group_begin: \exp_not:n { \cs_set_eq:NN \xeCJK@fontfamily \use_none:n } \exp_not:n { \fontspec_gset_family:Nnn \g_@@_fontspec_family_tl } { \exp_not:o \l_@@_fontspec_options_clist } { \exp_not:o \l_@@_font_name_tl } \@@_gset_family_nfss_cs:no {#1} { \exp_not:N \g_@@_fontspec_family_tl } \group_end: \tl_set_eq:NN \exp_not:N \l_@@_fontspec_family_tl \exp_not:N \g_@@_fontspec_family_tl } } \tl_new:N \g_@@_fontspec_family_tl \tl_new:N \l_@@_fontspec_family_tl % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_check_family:n} % \begin{macrocode} \cs_new_protected:Npn \@@_check_family:n #1 { \prop_gpop:NnNT \g_@@_family_font_name_prop {#1} \l_@@_tmp_tl { \prop_gpop:NnNT \g_@@_family_name_prop {#1} \l_@@_tmp_tl { \cs_undefine:c { \@@_family_csname:n {#1} } \cs_undefine:c { \@@_family_nfss_csname:n {#1} } } \@@_warning:nxx { CJKfamily-redef } {#1} { \l_@@_tmp_tl } } } \cs_generate_variant:Nn \@@_check_family:n { o } \@@_msg_new:nn { CJKfamily-redef } { Redefining~CJKfamily~`\@@_msg_family_map:n {#1}'~(#2). } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_font_shape:} % \begin{macrocode} \cs_new_protected:Npn \@@_parse_font_shape: { \tl_if_blank:oTF \l_@@_font_name_bf_tl { \bool_if:NT \l_@@_auto_fake_bold_bool { \clist_put_right:Nx \l_@@_fontspec_options_clist { AutoFakeBold = { \fp_use:N \l_@@_embolden_factor_fp } } } } { \clist_put_right:Nx \l_@@_fontspec_options_clist { BoldFont = { \exp_not:o \l_@@_font_name_bf_tl } } } \tl_if_blank:oTF \l_@@_font_name_it_tl { \bool_if:NT \l_@@_auto_fake_slant_bool { \clist_put_right:Nx \l_@@_fontspec_options_clist { AutoFakeSlant = { \fp_use:N \l_@@_slant_factor_fp } } } } { \clist_put_right:Nx \l_@@_fontspec_options_clist { ItalicFont = { \exp_not:o \l_@@_font_name_it_tl } } } } % \end{macrocode} % \end{macro} % % \begin{variable} % {\g_@@_family_name_prop,\g_@@_family_font_name_prop,\g_@@_family_font_options_prop} % \begin{macrocode} \prop_new:N \g_@@_family_name_prop \prop_new:N \g_@@_family_font_name_prop \prop_new:N \g_@@_family_font_options_prop % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_save_family_info:} % \begin{macrocode} \cs_new_protected:Npn \@@_save_family_info: { \exp_args:Nooo \@@_save_family_info:nnn \l_@@_family_name_tl \l_@@_font_name_tl \l_@@_font_options_clist } \cs_new_protected:Npn \@@_save_family_info:nnn #1#2#3 { \prop_gput:Nnn \g_@@_family_font_name_prop {#1} {#2} \prop_gput:Nnn \g_@@_family_font_options_prop {#1} {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_sub_block_family:} % \begin{macrocode} \cs_new_protected:Npn \@@_set_sub_block_family: { \prop_if_empty:NF \l_@@_sub_key_prop { \prop_map_function:NN \l_@@_sub_key_prop \@@_set_sub_block_family:nn } } \cs_new_protected:Npn \@@_set_sub_block_family:nn #1#2 { \tl_set:Nx \l_@@_sub_family_name_tl { \l_@@_family_name_tl/#1 } \quark_if_no_value:nTF {#2} { \@@_copy_sub_family:n {#1} } { \xeCJK_set_family:onn \l_@@_sub_family_name_tl #2 } } \cs_new_protected:Npn \@@_copy_sub_family:n #1 { \@@_check_family:o \l_@@_sub_family_name_tl \prop_get:NoNT \g_@@_family_font_name_prop \l_@@_family_name_tl \l_@@_sub_font_name_tl { \prop_gput:Noo \g_@@_family_font_name_prop \l_@@_sub_family_name_tl \l_@@_sub_font_name_tl } \prop_get:NoNT \g_@@_family_font_options_prop \l_@@_family_name_tl \l_@@_sub_font_options_clist { \clist_remove_all:Nn \l_@@_sub_font_options_clist { #1 = * } \prop_gput:Noo \g_@@_family_font_options_prop \l_@@_sub_family_name_tl \l_@@_sub_font_options_clist } \cs_gset_protected:cpx { \@@_family_csname:n { \l_@@_sub_family_name_tl } } { \xeCJK_family_if_exist:eT { \l_@@_family_name_tl } { \@@_gset_family_nfss_cs:no { \l_@@_sub_family_name_tl } { \exp_not:N \l_@@_fontspec_family_tl } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_copy_family:nn,\@@_copy_family:ee} % \begin{macrocode} \cs_new_protected:Npn \@@_copy_family:nn #1#2 { \xeCJK_family_if_exist:nT {#2} { \prop_gput:Nno \g_@@_family_name_prop {#1} \l_@@_fontspec_family_tl \tl_map_inline:nn { \g_@@_family_font_name_prop \g_@@_family_font_options_prop } { \prop_get:NnNT ##1 {#2} \l_@@_tmp_tl { \prop_gput:Nno ##1 {#1} \l_@@_tmp_tl } } \cs_gset_eq:cc { \@@_family_nfss_csname:n {#1} } { \@@_family_nfss_csname:n {#2} } } } \cs_generate_variant:Nn \@@_copy_family:nn { ee } % \end{macrocode} % \end{macro} % % \subsection{字体切换} % % \begin{macro}[int]{\xeCJK_select_font:} % \begin{variable}[int]{\l_xeCJK_current_font_tl} % 缓存当前字体的原始格式,以加速编译。 % \begin{macrocode} \cs_new:Npn \@@_font_csname:n #1 { xeCJK/#1/\f@series/\f@shape/\f@size } \tl_new:N \l_xeCJK_current_font_tl \tl_set:No \l_xeCJK_current_font_tl { \@@_font_csname:n { \CJK@family } } \cs_new_protected:Npn \xeCJK_select_font: { \@@_select_font:cn { \l_xeCJK_current_font_tl } { \l_xeCJK_family_tl } } \cs_new_protected:Npn \@@_select_font:Nn #1#2 { \xeCJK_clear_fallback_font: \cs_if_exist:NF #1 { \@@_font_initial:Nn #1 {#2} } #1 } \cs_generate_variant:Nn \@@_select_font:Nn { c } \tl_new:N \l_@@_current_coor_tl \cs_new_eq:NN \xeCJK@setfont \xeCJK_select_font: % \end{macrocode} % \end{variable} % \end{macro} % % \changes{v3.8.1}{2020/02/14}{修复 \cs{l_xeCJK_current_font_tl} 标记错误。} % % \begin{macro}{\@@_font_initial:Nn} % 注意要将 \tn{selectfont} 放在分组中调用,防止 \tn{f@series} 等字体参数被修改, % 导致 \cs{l_xeCJK_current_font_tl} 标记前后不一致,引发错误(见~\ghissue{486})。 % \begin{macrocode} \cs_new_protected:Npn \@@_font_initial:Nn #1#2 { \group_begin: \@@_font_initial_hook: \@@_family_use:n {#2} \xeCJK_font_gset_to_current:N #1 \group_end: } \cs_new_protected:Npn \@@_font_initial_hook: { \tl_use:N \g_@@_font_initial_hook_tl } \cs_new_protected:Npn \@@_gadd_font_initial_hook:n { \tl_gput_right:Nn \g_@@_font_initial_hook_tl } \tl_new:N \g_@@_font_initial_hook_tl % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_select_punct_font:} % \begin{variable}[int]{\l_xeCJK_current_punct_font_tl} % 切换标点符号字体。 % \begin{macrocode} \cs_new_eq:NN \xeCJK_select_punct_font: \xeCJK_select_font: \cs_new_protected:Npn \@@_select_punct_font_aux: { \@@_select_font:cn { \l_xeCJK_current_punct_font_tl } { \l_xeCJK_punct_family_tl } } \tl_new:N \CJK@punctfamily \tl_new:N \l_xeCJK_punct_family_tl \tl_new:N \l_xeCJK_current_punct_font_tl \tl_set:Nn \CJK@punctfamily { \CJK@family } \tl_set:Nn \l_xeCJK_punct_family_tl { \l_xeCJK_family_tl } \tl_set:No \l_xeCJK_current_punct_font_tl { \@@_font_csname:n { \CJK@punctfamily } } \cs_new_eq:NN \@@_select_font: \prg_do_nothing: \cs_new_eq:NN \@@_select_punct_font: \prg_do_nothing: % \end{macrocode} % \end{variable} % \end{macro} % % \begin{macro}{\@@_switch_font:nn} % \changes{v3.1.0}{2012/11/18}{改进定义,加快切换速度。} % 两个 CJK 分区之间的字体切换。 % \begin{macrocode} \cs_new_protected:Npn \@@_switch_font:nn #1#2 { \str_if_eq:nnF {#1} {#2} { \@@_info:nxx { CJK-block } {#1} {#2} \str_if_eq:nnTF {#2} { CJK } { \xeCJK_select_font: } { \xeCJK_select_font:n {#2} } } } \@@_msg_new:nn { CJK-block } { Switch~from~block~`#1'~to~`#2'. } % \end{macrocode} % \end{macro} % % \changes{v3.8.2}{2020/02/17}{修复分区字体错误。} % % \begin{macro}[int]{\xeCJK_select_font:n,\xeCJK_block_family:nn} % 若当前 CJK 字体族没有定义子分区 |#1| 的字体,则使用 \tn{CJKfamilydefault} 的对应 % 分区字体;若 \tn{CJKfamilydefault} 也没有定义该分区字体,则使用当前 CJK 字体族的 % 主分区字体。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_select_font:n #1 { \@@_select_font:cnn { \@@_font_csname:n { \CJK@family/#1 } } { \l_xeCJK_family_tl } {#1} } \cs_new_protected:Npn \@@_select_font:Nnn #1#2#3 { \xeCJK_clear_fallback_font: \cs_if_exist:NF #1 { \@@_block_font_initial:Nnn #1 {#2} {#3} } #1 } \cs_generate_variant:Nn \@@_select_font:Nnn { c } \cs_new_protected:Npn \@@_block_font_initial:Nnn #1#2#3 { \xeCJK_block_family:nn {#2} {#3} \@@_font_initial:Nn #1 { #2/#3 } } \cs_new_protected:Npn \xeCJK_block_family:nn #1#2 { \xeCJK_family_if_exist:eF { #1/#2 } { \@@_copy_family:ee { #1/#2 } { \cs_if_exist:cTF { \@@_family_csname:n { \CJKfamilydefault/#2 } } { \CJKfamilydefault/#2 } {#1} } } } % \end{macrocode} % \end{macro} % % \begin{macro} % {\@@_family_csname:n,\@@_family_nfss_csname:n, % \@@_family_use:n,\@@_gset_family_nfss_cs:nn} % \begin{macrocode} \cs_new:Npn \@@_family_csname:n #1 { xeCJK/family/#1 } \cs_new:Npn \@@_family_nfss_csname:n #1 { xeCJK/family/nfss/#1 } \cs_new_protected:Npn \@@_family_use:n #1 { \use:c { \@@_family_nfss_csname:n {#1} } } \cs_new_protected:Npn \@@_gset_family_nfss_cs:nn #1#2 { \prop_gput:Nnn \g_@@_family_name_prop {#1} {#2} \cs_gset_protected:cpx { \@@_family_nfss_csname:n {#1} } { \@@_nfss_family:nn { \c_@@_encoding_tl } {#2} } } \cs_generate_variant:Nn \@@_gset_family_nfss_cs:nn { no } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_nfss_family:n} % 用于处理 \LaTeXe\ 2020/02/02 中 \tn{bfseries@rm} 等与 \tn{bfdefault} 不一致可能导致的问题。 % \begin{macrocode} \cs_if_exist:NTF \fontseriesforce { \cs_new_protected:Npn \@@_nfss_family:nn #1#2 { \fontencoding {#1} \str_if_eq:eeF { \f@series } { \bfdefault } { \str_case_e:nn { \f@family } { { \rmdefault } { \@@_nfss_series:n { rm } } { \sfdefault } { \@@_nfss_series:n { sf } } { \ttdefault } { \@@_nfss_series:n { tt } } } } \fontfamily {#2} \selectfont } \cs_new_protected:Npn \@@_nfss_series:n #1 { \str_if_eq:eeT { \f@series } { \use:c { bfseries@#1 } } { \fontseriesforce { \bfdefault } } } } { \cs_new_protected:Npn \@@_nfss_family:nn #1#2 { \fontencoding {#1} \tl_set:Nn \f@family {#2} \selectfont } } % \end{macrocode} % \end{macro} % % \begin{macro}[TF,int]{\xeCJK_family_if_exist:n} % \begin{macrocode} \prg_new_protected_conditional:Npnn \xeCJK_family_if_exist:n #1 { T , F , TF } { \prop_get:NnNTF \g_@@_family_name_prop {#1} \l_@@_fontspec_family_tl { \prg_return_true: } { \exp_args:Ne \cs_if_exist_use:cTF { \@@_family_csname:n {#1} } { \prg_return_true: } { \prg_return_false: } } } \prg_generate_conditional_variant:Nnn \xeCJK_family_if_exist:n { e } { T , F , TF } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKfamily} % 用于切换 CJK 字体族。 % \begin{macrocode} \NewDocumentCommand \CJKfamily { t+ t- m } { \xeCJK_family:NNe #1 #2 {#3} \tex_ignorespaces:D } \cs_new_protected:Npn \xeCJK_family:NNn #1#2#3 { \tl_if_blank:nTF {#3} { \bool_if:NF #1 { \bool_if:NF #2 { \use_none:nn } } \xeCJK_family_if_exist_use:e { \l_xeCJK_family_tl } } { \bool_if:NTF #2 { \xeCJK_family_if_exist_use:n {#3} } { \xeCJK_family_if_exist:nTF {#3} { \tl_set:Nn \l_xeCJK_family_tl {#3} \tl_set_eq:NN \CJK@family \l_@@_fontspec_family_tl \bool_if:NT #1 { \@@_family_use:n {#3} } } { \@@_family_unknown_warning:n {#3} } } } } \cs_generate_variant:Nn \xeCJK_family:NNn { NNe } \cs_new_protected:Npn \xeCJK_switch_family:n #1 { \xeCJK_family_if_exist:nTF {#1} { \tl_set:Nn \l_xeCJK_family_tl {#1} \tl_set_eq:NN \CJK@family \l_@@_fontspec_family_tl } { \@@_family_unknown_warning:n {#1} } } \cs_generate_variant:Nn \xeCJK_switch_family:n { e , o } % \end{macrocode} % \end{macro} % % \changes{v3.6.0}{2018/01/24}{新增 \opt{PunctFamily} 选项支持对汉字标点单独切换字体。} % % \begin{macro}{PunctFamily} % 设置汉字标点符号的字体。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { PunctFamily .choice: , PunctFamily .value_required:n = { true } , PunctFamily / false .code:n = { \tl_set:Nn \CJK@punctfamily { \CJK@family } \tl_set:Nn \l_xeCJK_punct_family_tl { \l_xeCJK_family_tl } \xeCJK_cs_clear:N \@@_select_font: \xeCJK_cs_clear:N \@@_select_punct_font: \cs_set_eq:NN \xeCJK_select_punct_font: \xeCJK_select_font: } , PunctFamily / unknown .code:n = { \xeCJK_punct_family:e {#1} } , } \cs_new_protected:Npn \xeCJK_punct_family:n #1 { \xeCJK_family_if_exist:nTF {#1} { \tl_set:Nn \l_xeCJK_punct_family_tl {#1} \tl_set_eq:NN \CJK@punctfamily \l_@@_fontspec_family_tl \cs_set_eq:NN \@@_select_font: \xeCJK_select_font: \cs_set_eq:NN \@@_select_punct_font: \@@_select_punct_font_aux: \cs_set_eq:NN \xeCJK_select_punct_font: \@@_select_punct_font: } { \@@_family_unknown_warning:n {#1} } } \cs_generate_variant:Nn \xeCJK_punct_family:n { e } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\l_xeCJK_family_tl} % 用于保存文档当前正在使用的 CJK 字体族。 % \changes{v3.2.0}{2013/04/14}{不将其初始化为 \tn{CJKfamilydefault}。} % \begin{macrocode} \tl_new:N \l_xeCJK_family_tl % \end{macrocode} % \end{variable} % % \begin{variable}{\CJK@family} % 用于保存实际的字体族名称。 % \changes{v3.2.11}{2014/03/29}{引入 \tn{CJK@family} 保存实际的字体族名。} % \begin{macrocode} \tl_new:N \CJK@family % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_gobble_CJKfamily:} % \begin{macrocode} \cs_new_protected:Npn \@@_gobble_CJKfamily: { \cs_set_eq:NN \CJKfamily \@@_gobble_CJKfamily:wn } \NewExpandableDocumentCommand \@@_gobble_CJKfamily:wn { t+ t- m } { } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_family_if_exist_use:n} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_family_if_exist_use:n #1 { \xeCJK_family_if_exist:nTF {#1} { \@@_family_use:n {#1} } { \@@_family_unknown_warning:n {#1} } } \cs_generate_variant:Nn \xeCJK_family_if_exist_use:n { e } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_family_unknown_warning:n} % \changes{v3.1.2}{2013/01/01} % {在没有定义任何 CJK 字体的情况下,不再重复给出字体没有定义的警告。} % \begin{macrocode} \cs_new_protected:Npn \@@_family_unknown_warning:n #1 { \prop_if_empty:NF \g_@@_family_font_name_prop { \seq_if_in:NnF \g_@@_unknown_family_seq {#1} { \seq_gput_right:Nn \g_@@_unknown_family_seq {#1} \@@_warning:nx { CJKfamily-Unknown } {#1} } } } \seq_new:N \g_@@_unknown_family_seq \@@_msg_new:nn { CJKfamily-Unknown } { Unknown~CJK~family~`\@@_msg_family_map:n {#1}'~is~being~ignored.\\\\ Try~to~use~`\@@_msg_def_family_map:n {#1}'~to~define~it. } \cs_new:Npn \@@_msg_def_family_map:n #1 { \str_case_e:nnF {#1} { \CJKrmdefault { \token_to_str:N \setCJKmainfont } \CJKsfdefault { \token_to_str:N \setCJKsansfont } \CJKttdefault { \token_to_str:N \setCJKmonofont } } { \token_to_str:N \setCJKfamilyfont \{ #1 \} } [<...>]\{<...>\} } \cs_new:Npn \@@_msg_family_map:n #1 { \str_case_e:nnF {#1} { \CJKrmdefault { \token_to_str:N \CJKrmdefault } \CJKsfdefault { \token_to_str:N \CJKsfdefault } \CJKttdefault { \token_to_str:N \CJKttdefault } } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_pass_args:nnnn} % 为了支持字体属性可选项在前在后两种语法,给出两个辅助工具,类似 % \package{fontspec} 的实现。自带展开功能,额外参数 |#4| 用于后处理。 % \begin{macrocode} \cs_new_protected:Npn \@@_pass_args:nnnn #1#2#3#4 { \tl_if_novalue:nTF {#2} { \@@_post_arg:w {#1} {#3} {#4} } { \use:e { #1 {#2} {#3} } #4 } } \NewDocumentCommand \@@_post_arg:w { m m m O { } } { \use:e { #1 {#4} {#2} } #3 } % \end{macrocode} % \end{macro} % % \begin{macro}{\setCJKmainfont,\setCJKsansfont,\setCJKmonofont} % 设置文档的 CJK 普通字体、无衬线和等宽字体。 % \changes{v3.2.0}{2013/04/14}{定义中加入 \tn{normalfont}。} % \changes{v3.4.3}{2016/11/18}{允许字体属性可选项在后的新语法。} % \begin{macrocode} \NewDocumentCommand \setCJKmainfont { o m } { \@@_pass_args:nnnn { \xeCJK_set_family:nnn { \CJKrmdefault } } {#1} {#2} { \@@_preamble_family:n { \CJKrmdefault } } } \cs_new_eq:NN \setCJKromanfont \setCJKmainfont \NewDocumentCommand \setCJKsansfont { o m } { \@@_pass_args:nnnn { \xeCJK_set_family:nnn { \CJKsfdefault } } {#1} {#2} { \@@_preamble_family:n { \CJKsfdefault } } } \NewDocumentCommand \setCJKmonofont { o m } { \@@_pass_args:nnnn { \xeCJK_set_family:nnn { \CJKttdefault } } {#1} {#2} { \@@_preamble_family:n { \CJKttdefault } } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \@onlypreamble \setCJKmainfont \@onlypreamble \setCJKmathfont \@onlypreamble \setCJKsansfont \@onlypreamble \setCJKmonofont \@onlypreamble \setCJKromanfont % \end{macrocode} % % \changes{v3.8.2}{2020/02/17}{避免导言区字体警告。} % % \begin{macro}{\@@_preamble_family:n} % 用在 \tn{setCJKmainfont} 等主要命令之后,确保导言区有 CJK 字体可用。 % \begin{macrocode} \cs_new_protected:Npn \@@_preamble_family:n #1 { \str_if_eq:eeT {#1} { \CJKfamilydefault } { \normalfont } } % \end{macrocode} % \end{macro} % % \begin{macro}{\setCJKfamilyfont, \newCJKfontfamily, \CJKfontspec} % \changes{v3.4.3}{2016/11/18}{允许字体属性可选项在后的新语法。} % 分别用于预声明 CJK 字体族和声明并马上调用 CJK 字体族。 % \begin{macrocode} \NewDocumentCommand \setCJKfamilyfont { m o m } { \@@_pass_args:nnnn { \xeCJK_set_family:nnn {#1} } {#2} {#3} { } } \NewDocumentCommand \newCJKfontfamily { o m o m } { \tl_set:Nx \l_@@_tmp_tl { \tl_if_novalue:nTF {#1} { \cs_to_str:N #2 } {#1} } \cs_new_protected:Npx #2 { \xeCJK_switch_family:n { \l_@@_tmp_tl } } \@@_pass_args:nnnn { \xeCJK_set_family:nnn { \l_@@_tmp_tl } } {#3} {#4} { } } \NewDocumentCommand \CJKfontspec { o m } { \@@_pass_args:nnnn { \xeCJK_fontspec:nn } {#1} {#2} { \tex_ignorespaces:D } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_fontspec:nn} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_fontspec:nn #1#2 { \prop_get:NnNTF \g_@@_fontspec_prop { CJKfontspec/#1/#2/id } \l_xeCJK_family_tl { \xeCJK_switch_family:o { \l_xeCJK_family_tl } } { \@@_fontspec:enn { CJKfontspec ( \int_eval:n { \g_@@_family_int + 1 } ) } {#1} {#2} } } \cs_new_protected:Npn \@@_fontspec:nnn #1#2#3 { \prop_gput:Nnn \g_@@_fontspec_prop { CJKfontspec/#2/#3/id } {#1} \xeCJK_set_family:nnn {#1} {#2} {#3} \xeCJK_switch_family:n {#1} } \cs_generate_variant:Nn \xeCJK_fontspec:nn { oo } \cs_generate_variant:Nn \@@_fontspec:nnn { e } \prop_new:N \g_@@_fontspec_prop % \end{macrocode} % \end{macro} % % \begin{macro}{\defaultCJKfontfeatures, \addCJKfontfeatures} % \changes{v3.2.4}{2013/06/30}{可以单独增加当前各个分区字体的属性。} % 分别用于设置 CJK 字体的默认属性和增加当前 CJK 字体的属性。 % \begin{macrocode} \clist_new:N \g_@@_default_features_clist \NewDocumentCommand \defaultCJKfontfeatures { m } { \clist_gset:Nn \g_@@_default_features_clist {#1} } \@onlypreamble \defaultCJKfontfeatures \NewDocumentCommand \addCJKfontfeatures { s O { } m } { \xeCJK_add_font_features:Nee #1 {#2} {#3} \tex_ignorespaces:D } \cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_add_font_features:Nnn} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_add_font_features:Nnn #1#2#3 { \prop_get:NoNTF \g_@@_family_font_name_prop \l_xeCJK_family_tl \l_@@_font_name_tl { \clist_set:Nn \l_@@_add_font_features_clist {#3} \seq_map_inline:Nn \g_@@_sub_key_seq { \clist_remove_all:Nn \l_@@_add_font_features_clist {##1} } \seq_clear:N \l_@@_sub_key_seq \clist_clear:N \l_@@_add_block_features_clist \clist_map_function:nN {#2} \@@_add_sub_features:n \bool_lazy_and:nnT {#1} { \seq_if_empty_p:N \l_@@_sub_key_seq } { \seq_map_function:NN \g_@@_sub_key_seq \@@_add_sub_class_features:n } \prop_get:NoNT \g_@@_family_font_options_prop \l_xeCJK_family_tl \l_@@_font_options_clist { \bool_lazy_or:nnT { \seq_if_empty_p:N \l_@@_sub_key_seq } {#1} { \clist_concat:NNN \l_@@_font_options_clist \l_@@_font_options_clist \l_@@_add_font_features_clist } \clist_concat:NNN \l_@@_font_options_clist \l_@@_font_options_clist \l_@@_add_block_features_clist } \xeCJK_fontspec:oo \l_@@_font_options_clist \l_@@_font_name_tl } { \@@_warning:n { addCJKfontfeature-ignored } } } \cs_new_protected:Npn \@@_add_sub_features:n #1 { \seq_if_in:NnTF \g_@@_sub_key_seq {#1} { \seq_put_right:Nn \l_@@_sub_key_seq {#1} \@@_add_sub_class_features:n {#1} } { \@@_warning:nx { SubBlock-undefined } {#1} } } \clist_new:N \l_@@_add_font_features_clist \clist_new:N \l_@@_add_block_features_clist \cs_generate_variant:Nn \xeCJK_add_font_features:Nnn { Nee , Nne } \@@_msg_new:nn { addCJKfontfeature-ignored } { \token_to_str:N \addCJKfontfeature (s)~ignored.\\\\ It~cannot~be~used~with~a~font~that~wasn't~selected~by~xeCJK. } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_sub_class_features:n} % \begin{macrocode} \cs_new_protected:Npn \@@_add_sub_class_features:n #1 { \prop_get:NoNTF \g_@@_family_font_name_prop { \l_xeCJK_family_tl/#1 } \l_@@_sub_font_name_tl { \prop_get:NoN \g_@@_family_font_options_prop { \l_xeCJK_family_tl/#1 } \l_@@_sub_font_options_clist } { \prop_get:NeNTF \g_@@_family_font_name_prop { \CJKfamilydefault/#1 } \l_@@_sub_font_name_tl { \prop_get:NeN \g_@@_family_font_options_prop { \CJKfamilydefault/#1 } \l_@@_sub_font_options_clist } { \prop_get:NoN \g_@@_family_font_options_prop \l_xeCJK_family_tl \l_@@_sub_font_options_clist \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_font_name_tl } } \clist_concat:NNN \l_@@_sub_font_options_clist \l_@@_sub_font_options_clist \l_@@_add_font_features_clist \clist_put_right:Nx \l_@@_add_block_features_clist { #1 = { [ \exp_not:o \l_@@_sub_font_options_clist ] { \exp_not:o \l_@@_sub_font_name_tl } } } } \cs_generate_variant:Nn \prop_get:NnN { Ne } \prg_generate_conditional_variant:Nnn \prop_get:NnN { Ne } { T , TF } % \end{macrocode} % \end{macro} % % \begin{macro}{LoadFandol} % \changes{v3.2.10}{2014/03/01}{当没有设置字体时,使用 Fandol 字体系列。} % \changes{v3.3.1}{2015/04/08}{为方便 MacTeX 用户,Fandol 字体改用文件名。} % \begin{macrocode} \keys_define:nn { xeCJK / options } { LoadFandol .bool_gset:N = \g_@@_fandol_bool } \cs_new_protected:Npn \@@_load_fandol: { \xeCJK_set_family:enn { \CJKrmdefault } { Extension = .otf , BoldFont = FandolSong-Bold , ItalicFont = FandolKai-Regular } { FandolSong-Regular } \xeCJK_set_family:enn { \CJKsfdefault } { Extension = .otf , BoldFont = FandolHei-Bold } { FandolHei-Regular } \xeCJK_set_family:enn { \CJKttdefault } { Extension = .otf } { FandolFang-Regular } } % \end{macrocode} % \end{macro} % % \changes{v3.1.2}{2013/01/01}{修正重定义 \tn{CJKfamilydefault} 无效的问题,恢复容错能力。} % \changes{v3.2.13}{2014/06/02}{自动调整 \tn{CJKfamilydefault} 时,只将 \tn{familydefault} 展开一次。} % % 在导言区结束的时候,若没有声明 CJK 字体,则给出一个警告。如果 \tn{CJKfamilydefault} % 没有被更改,则在此时根据西文字体的情况更新 \tn{CJKfamilydefault}。 % 如果 \tn{CJKfamilydefault} 对应的字体族没有定义,则使用 \tn{CJKrmdefault} 作为 % 默认字体族。若 \tn{CJKrmdefault} 也没有定义,则使用在导言区设置的第一个 CJK 字体 % 作为默认字体族。最后设置数学字体。 % \begin{macrocode} \@@_at_end_preamble:n { \tl_if_eq:NNT \CJKfamilydefault \l_@@_family_default_init_tl { \group_begin: \cs_set_eq:NN \@@_family_default_wrap:n \exp_not:n \tl_gset:Nx \CJKfamilydefault { \str_case:onF { \familydefault } { { \rmdefault } { \exp_not:N \CJKrmdefault } { \sfdefault } { \exp_not:N \CJKsfdefault } { \ttdefault } { \exp_not:N \CJKttdefault } } { \CJKfamilydefault } } \group_end: } \prop_if_empty:NTF \g_@@_family_font_name_prop { \bool_if:NTF \g_@@_fandol_bool { \@@_warning:n { fandol } \@@_load_fandol: \xeCJK_ensure_default_family: } { \@@_warning:nx { no-CJKfamily } { \CJKfamilydefault } } } { \xeCJK_ensure_default_family: } } \cs_new_protected:Npn \xeCJK_ensure_default_family: { \xeCJK_family_if_exist:eF { \CJKfamilydefault } { \tl_set_eq:NN \l_@@_tmp_tl \CJKfamilydefault \str_if_eq:eeTF { \CJKfamilydefault } { \CJKrmdefault } { \use:n } { \xeCJK_family_if_exist:eTF { \CJKrmdefault } { \tl_gset:Nn \CJKfamilydefault { \CJKrmdefault } } } { \prop_map_inline:Nn \g_@@_family_font_name_prop { \prop_map_break:n { \tl_gset_rescan:Nnn \CJKfamilydefault { } { ##1 } } } } \@@_warning:nxx { CJKfamilydefault-undefined } { \l_@@_tmp_tl } { \CJKfamilydefault } } \xeCJK_switch_family:e { \CJKfamilydefault } \bool_if:NT \g_@@_math_bool { \xeCJK_set_mathfont: } } \@@_msg_new:nn { no-CJKfamily } { It~seems~that~you~have~not~declare~a~CJKfamily.\\ If~you~want~to~use~xeCJK~in~the~right~way,~you~should~use\\\\ `\@@_msg_def_family_map:n {#1}'\\\\ in~the~preamble~to~declare~the~default~CJKfamily.\\ } \@@_msg_new:nn { CJKfamilydefault-undefined } { Undefined~CJK~default~family~`\@@_msg_family_map:n {#1}'~ has~been~replaced~by~`\@@_msg_family_map:n {#2}'.\\\\ Try~to~use~`\@@_msg_def_family_map:n {#1}'~to~define~it. } \@@_msg_new:nn { fandol } { Fandol~is~being~set~as~the~default~font~for~CJK~text.\\ Please~make~sure~it~has~been~properly~installed. } % \end{macrocode} % % \subsection{数学字体设置} % % \begin{macro}{CJKmath} % 是否启用 CJK 数学字体的宏包选项。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKmath .bool_gset:N = \g_@@_math_bool } % \end{macrocode} % \end{macro} % % \begin{macro}{\setCJKmathfont} % \changes{v3.4.3}{2016/11/18}{允许字体属性可选项在后的新语法。} % 设置 CJK 数学字体。 % \begin{macrocode} \NewDocumentCommand \setCJKmathfont { o m } { \@@_pass_args:nnnn { \xeCJK_set_family:nnn { \c_@@_math_tl } } {#1} {#2} { } } \tl_const:Nn \c_@@_math_tl { CJKmath } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_set_mathfont:} % \changes{v3.2.6}{2013/08/01}{设置粗体时先检查对应字体是否存在。} % \changes{v3.2.7}{2013/11/09}{将 CJK 字符的数学归类由 $7$ 改为 $0$,解决汉字路径的问题。} % \changes{v3.2.13}{2014/06/20}{修复参数类型错误。} % \changes{v3.4.0}{2016/05/01}{CJKmath 的字符范围遵从 \tn{xeCJKDeclareCharClass} 的设置。} % 当没有设置 CJK 数学字体时,使用 \tn{CJKfamilydefault} 作为数学字体。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_set_mathfont: { \cs_if_exist_use:N \@@_save_um_char: \xeCJK_family_if_exist:eTF { \c_@@_math_tl } { \@@_set_mathfont_aux: } { \xeCJK_family_if_exist:eT { \CJKfamilydefault } { \@@_copy_family:ee { \c_@@_math_tl } { \CJKfamilydefault } \@@_set_mathfont_aux: } } \cs_if_exist_use:N \@@_restore_um_char: } \cs_new_protected:Npn \@@_set_mathfont_aux: { \tl_const:Nx \c_@@_math_family_tl { \l_@@_fontspec_family_tl } \xeCJK_declare_mathfont:ee { \c_@@_math_tl } { \c_@@_math_family_tl } \int_const:Nn \c_xeCJK_math_fam_int { \use:c { sym \c_@@_math_tl } } \clist_gconcat:NNN \g_@@_math_chars_clist \g_@@_CJK_range_clist \g_@@_FullLeft_range_clist \clist_gconcat:NNN \g_@@_math_chars_clist \g_@@_math_chars_clist \g_@@_FullRight_range_clist \xeCJK_gset_mathcode:Nn \g_@@_math_chars_clist { \c_xeCJK_math_fam_int } \xeCJK_set_mathfont_block: } \clist_new:N \g_@@_math_chars_clist \prop_new:N \g_@@_fam_prop % \end{macrocode} % \end{macro} % % \changes{v3.4.0}{2016/05/04}{CJKmath 功能也支持分区字体。} % % \begin{macro}[int]{\xeCJK_set_mathfont_block:} % 分区数学字体。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_set_mathfont_block: { \seq_if_empty:NF \g_@@_CJK_sub_class_seq { \seq_map_function:NN \g_@@_CJK_sub_class_seq \xeCJK_set_mathfont_block:n } } \cs_new_protected:Npn \xeCJK_set_mathfont_block:n #1 { \xeCJK_block_family:nn { \c_@@_math_tl } {#1} \prop_get:NoNTF \g_@@_fam_prop \l_@@_fontspec_family_tl \l_@@_tmp_tl { \int_set:Nn \l_@@_fam_int { \l_@@_tmp_tl } } { \xeCJK_declare_mathfont:ee { \c_@@_math_tl / #1 } { \l_@@_fontspec_family_tl } \@@_set_mathfont_block_aux:cn { sym \c_@@_math_tl / #1 } {#1} } \xeCJK_gset_mathcode:cn { g_@@_CJK/#1_range_clist } { \l_@@_fam_int } } \cs_new_protected:Npn \@@_set_mathfont_block_aux:Nn #1#2 { \int_set_eq:NN \l_@@_fam_int #1 \prop_gput:Nnn \g_@@_block_fam_prop {#2} {#1} } \int_new:N \l_@@_fam_int \prop_new:N \g_@@_block_fam_prop \cs_generate_variant:Nn \@@_set_mathfont_block_aux:Nn { c } % \end{macrocode} % \end{macro} % % \changes{v3.8.1}{2020/02/14}{应用 \tn{shapedefault}。} % % \begin{macro}[int]{\xeCJK_declare_mathfont:nn} % 注意从 \LaTeXe\ 2020/02/02 开始,\tn{shapedefault} 初始值是 \texttt{n}, % 而 \tn{updefault} 初始值是 \texttt{up},两者并不一致。 % \pkg{fontspec} 包定义字体使用的是 \tn{shapedefault}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_declare_mathfont:nn #1#2 { \xeCJK_declare_symbol_font:nnnnn {#1} { \c_@@_encoding_tl } {#2} { \mddefault } { \shapedefault } \cs_if_free:cF { \c_@@_encoding_tl/#2/\bfdefault/\shapedefault } { \SetSymbolFont {#1} { bold } { \c_@@_encoding_tl } {#2} { \bfdefault } { \shapedefault } } \prop_gput:Nne \g_@@_fam_prop {#2} { \exp_not:c { sym #1 } } } \cs_generate_variant:Nn \prop_put:Nnn { Nne } \cs_generate_variant:Nn \prop_gput:Nnn { Nne } \cs_generate_variant:Nn \xeCJK_declare_mathfont:nn { ee } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_declare_symbol_font:nnnnn} % 主要功能同 \tn{DeclareSymbolFont},不带编码和重复定义检查。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_declare_symbol_font:nnnnn #1 { \@@_declare_symbol_font:cnnnn { sym #1 } } \cs_new_protected:Npn \@@_declare_symbol_font:Nnnnn #1 { \xeCJK_new_fam:N #1 \xeCJK_new_symbol_font:Nnnnn #1 } \cs_generate_variant:Nn \@@_declare_symbol_font:Nnnnn { c } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_new_fam:N} % 我们从 $255$ 往下分配 \tn{fam},|\count18| 是 \LaTeXe{} 记录最后分配的 \tn{fam} 编号, % 作为我们的分配器的下限。事实上,还应该相应地减小 \tn{e@mathgroup@top} 才合理,但这可能会有不利影响, % 我们暂未处理。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_new_fam:N #1 { \int_compare:nNnTF { \g_@@_fam_allocation_int } > { \g_@@_fam_bottom_int } { \int_set_eq:NN \allocationnumber \g_@@_fam_allocation_int \int_const:Nn #1 { \allocationnumber } \iow_log:x { \token_to_str:N #1 = \token_to_str:N \mathgroup \int_use:N \allocationnumber } \int_gdecr:N \g_@@_fam_allocation_int } { \@@_error:n { fam-exhausted } } } \tex_countdef:D \g_@@_fam_bottom_int = 18 ~ \int_new:N \g_@@_fam_allocation_int \int_gset:Nn \g_@@_fam_allocation_int { 255 } \@@_msg_new:nn { fam-exhausted } { No~room~for~a~new~fam. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_new_symbol_font:Nnnnn} % \begin{macro}{\@@_new_symbol_font:NN} % 功能同 \tn{new@symbolfont},但我们不增加 \tn{c@mv@normal} 和 \tn{c@mv@bold} 之类的计数器。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_new_symbol_font:Nnnnn #1#2#3#4#5 { \@@_new_symbol_font:Nc #1 { #2/#3/#4/#5 } } \cs_new_protected:Npn \@@_new_symbol_font:NN #1#2 { \tl_put_right:Nn \group@list { \group@elt #1 #2 } \cs_set:Npn \version@elt ##1 { \tl_put_right:Nn ##1 { \getanddefine@fonts #1 #2 } } \version@list } \cs_generate_variant:Nn \@@_new_symbol_font:NN { Nc } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\xeCJK_gset_mathcode:Nn, % \xeCJK_gset_mathcode:Nnn,\xeCJK_gset_mathcode:nnnn} % CJK 字符的数学类别固定为 $0$(\tn{mathord})。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_gset_mathcode:Nn #1#2 { \clist_map_inline:Nn #1 { \@@_set_char_class_aux:Nnw \xeCJK_gset_mathcode:nnnn { ##1 } { 0 } {#2} } } \cs_generate_variant:Nn \xeCJK_gset_mathcode:Nn { c } \cs_new_protected:Npn \xeCJK_gset_mathcode:nnnn #1#2#3#4 { \@@_check_num_range:nnNN {#1} {#2} \l_@@_begin_int \l_@@_end_int \xeCJK_int_until_do:nn { \l_@@_begin_int > \l_@@_end_int } { \xeCJK_gset_mathcode:Nnn \l_@@_begin_int {#3} {#4} \int_incr:N \l_@@_begin_int } } \cs_new_protected:Npn \xeCJK_gset_mathcode:Nnn #1#2#3 { \tex_global:D \tex_Umathcode:D #1 = #2 ~ #3 ~ #1 } % \end{macrocode} % \end{macro} % % % \subsection{抄录环境中的间距调整} % % \changes{v3.1.0}{2012/11/19}{放弃使用放缩字体大小的方式,而只采用调整间距的方式 % 与西文等宽字体对齐。并且只适用于与抄录环境下。} % \changes{v3.2.0}{2013/04/15}{增加 \texttt{Verb} 选项。} % \changes{v3.2.1}{2013/05/29}{调整 \texttt{Verb} 选项:在命令 \tn{verb} 里使用时, % 不破坏标点禁则,增加值 \texttt{env+}。} % % \begin{macro}{Verb} % \changes{v3.2.5}{2013/07/25}{微调定义。} % 如果设置为 \texttt{env},则只在 \LaTeX 的抄录环境里使用 \tn{xeCJKVerbAddon},^^A % 而不包括 \tn{verb}。对当前使用环境的判断基于在标准 \LaTeX 的坏境定义里使用 % \tn{begingroup} 和 \tn{endgroup} 来分组。 % \begin{macrocode} \int_new:N \l_@@_verb_case_int \keys_define:nn { xeCJK / options } { Verb .choices:nn = { true , env+ , env , false } { \int_set_eq:NN \l_@@_verb_case_int \l_keys_choice_int } , Verb .default:n = { env } } \cs_new_protected:Npn \@@_verb_font_hook: { \if_case:w \l_@@_verb_case_int \or: \@@_nobreak_skip_zero: \or: \int_compare:nNnTF \tex_currentgrouptype:D = { 14 } { \xeCJKVerbAddon } { \@@_nobreak_skip: } \or: \int_compare:nNnTF \tex_currentgrouptype:D = { 14 } { \xeCJKVerbAddon } { \@@_nobreak_skip_zero: } \fi: } \@@_after_preamble:n { \cs_set_protected:Npx \verbatim@font { \exp_not:o { \verbatim@font } \@@_verb_font_hook: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_nobreak_skip_zero:,\@@_nobreak_skip:} % \changes{v3.2.8}{2013/11/16}{禁止在 \tn{verb} 中断行。} % \begin{macrocode} \cs_new_protected:Npn \@@_nobreak_skip_zero: { \@@_reset_shipout_skip: \cs_set_eq:NN \@@_shipout_check_for_glue: \xeCJK_check_for_glue: \cs_set_eq:NN \@@_shipout_boundary:w \xeCJK_CJK_and_Boundary:w \tl_put_right:Nn \l_@@_reset_shipout_skip_hook_tl { \cs_set_eq:NN \xeCJK_check_for_glue: \@@_shipout_check_for_glue: \cs_set_eq:NN \xeCJK_CJK_and_Boundary:w \@@_shipout_boundary:w } \xeCJK_cs_clear:N \CJKglue \xeCJK_cs_clear:N \CJKecglue \xeCJK_cs_clear:N \xeCJK_check_for_glue: \cs_set_eq:NN \xeCJK_CJK_and_Boundary:w \xeCJK_class_group_end: \cs_set_eq:NN \@@_punct_hskip:n \@@_nobreak_hskip:n \cs_set_eq:NN \@@_punct_breakable_kern:n \@@_nobreak_hskip:n } \cs_new_protected:Npn \@@_nobreak_skip: { \@@_reset_shipout_skip: \xeCJK_glue_to_skip:nN { \CJKglue } \l_@@_ccglue_skip \skip_if_eq:nnTF { \l_@@_ccglue_skip } { \c_zero_skip } { \xeCJK_cs_clear:N \CJKglue } { \cs_set_eq:NN \CJKglue \@@_nobreak_ccglue: } \xeCJK_glue_to_skip:nN { \CJKecglue } \l_@@_ecglue_skip \skip_if_eq:nnTF { \l_@@_ecglue_skip } { \c_zero_skip } { \xeCJK_cs_clear:N \CJKecglue } { \cs_set_eq:NN \CJKecglue \@@_nobreak_ecglue: } \cs_set_eq:NN \@@_punct_hskip:n \@@_nobreak_hskip:n \cs_set_eq:NN \@@_punct_breakable_kern:n \@@_nobreak_hskip:n } \cs_new_protected:Npn \@@_nobreak_ccglue: { \xeCJK_no_break: \skip_horizontal:N \l_@@_ccglue_skip } \cs_new_protected:Npn \@@_nobreak_ecglue: { \xeCJK_no_break: \skip_horizontal:N \l_@@_ecglue_skip } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_reset_shipout_skip:} % \begin{macrocode} \cs_new_protected:Npn \@@_reset_shipout_skip: { \cs_set_eq:NN \@@_shipout_CJKglue: \CJKglue \cs_set_eq:NN \@@_shipout_CJKecglue: \CJKecglue \cs_set_eq:NN \@@_shipout_punct_hskip:n \@@_punct_hskip:n \cs_set_eq:NN \@@_shipout_punct_breakable_kern:n \@@_punct_breakable_kern:n \tl_set:Nx \l_@@_off_verb_addon_tl { \bool_if:NTF \l_@@_xecglue_bool { \keys_set:nn { xeCJK / options } { xCJKecglue = true } } { \keys_set:nn { xeCJK / options } { xCJKecglue = false } } \exp_not:n { \cs_set_eq:NN \CJKglue \@@_shipout_CJKglue: \cs_set_eq:NN \CJKecglue \@@_shipout_CJKecglue: \cs_set_eq:NN \@@_punct_hskip:n \@@_shipout_punct_hskip:n \cs_set_eq:NN \@@_punct_breakable_kern:n \@@_shipout_punct_breakable_kern:n \l_@@_reset_shipout_skip_hook_tl } } \xeCJK_add_to_shipout:n { \l_@@_off_verb_addon_tl } \keys_set:nn { xeCJK / options } { xCJKecglue = false } } \tl_new:N \l_@@_reset_shipout_skip_hook_tl % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKOffVerbAddon,\xeCJKVerbAddon} % \changes{v3.1.0}{2012/11/19}{新增 \tn{xeCJKVerbAddon} 用于抄录环境中的间距调整。} % \changes{v3.2.3}{2013/06/04} % {新增 \tn{xeCJKOffVerbAddon} 用于局部取消 \tn{xeCJKOffVerbAddon} 的影响;并解决 % 跨页使用时影响到页眉页脚的问题。} % \changes{v3.2.5}{2013/07/13}{禁止自动换行,与西文一致。} % \changes{v3.2.8}{2013/11/16}{增加是否是等宽字体的判断。} % \tn{xeCJKVerbAddon} 进行了比较大的调整,应该只在分组环境里使用。为了方便调整间距 % 以利于对齐,这里只把字符分成了两类,并且在 CJK 类与边界(空格)之间也插入 % \tn{CJKecglue}。以字母“M”的宽度是否等于 \tn{fontdimen2} 来判断当前字体是否是 % 等宽字体。如果不是等宽字体,则设置间距为零或正文间距。 % \begin{macrocode} \NewDocumentCommand \xeCJKVerbAddon { } { \int_compare:nNnF \tex_currentgrouplevel:D = \c_zero_int { \bool_if:NF \l_@@_listings_env_bool { \dim_compare:nNnTF { \tex_fontdimen:D 2 ~ \tex_font:D } = { \tex_fontcharwd:D \tex_font:D \c_@@_mono_letter_int } { \@@_set_verb_exspace: \@@_verb_addon: } { \int_if_odd:nTF { \l_@@_verb_case_int } { \@@_nobreak_skip_zero: } { \@@_nobreak_skip: } } } } } \int_const:Nn \c_@@_mono_letter_int { 77 } \bool_new:N \l_@@_listings_env_bool \NewDocumentCommand \xeCJKOffVerbAddon { } { \tl_use:N \l_@@_off_verb_addon_tl } \tl_new:N \l_@@_off_verb_addon_tl \cs_new_protected:Npn \@@_verb_addon: { \bool_if:NF \l_@@_verb_addon_bool { \@@_verb_addon_action: } \skip_if_eq:nnTF { \l_@@_verb_exspace_skip } { \c_zero_skip } { \xeCJK_cs_clear:N \CJKglue \xeCJK_cs_clear:N \CJKecglue } { \skip_set_eq:NN \l_@@_ccglue_skip \l_@@_verb_exspace_skip \skip_set:Nn \l_@@_ecglue_skip { \l_@@_verb_exspace_skip / 2 } \cs_set_eq:NN \CJKglue \@@_nobreak_ccglue: \cs_set_eq:NN \CJKecglue \@@_nobreak_ecglue: } \cs_set_eq:NN \xeCJK_check_for_glue: \CJKecglue \cs_set_eq:NN \xeCJK_CJK_and_Boundary:w \@@_verb_CJK_and_Boundary:w } \cs_new_protected:Npn \@@_verb_addon_action: { \bool_set_true:N \l_@@_verb_addon_bool \@@_set_char_class_eq:nn { FullLeft } { CJK } \@@_set_char_class_eq:nn { FullRight } { CJK } \@@_set_char_class_eq:nn { HalfLeft } { Default } \@@_set_char_class_eq:nn { HalfRight } { Default } \@@_set_char_class_eq:nn { NormalSpace } { Default } \cs_set_eq:NN \@@_shipout_CJKglue: \CJKglue \cs_set_eq:NN \@@_shipout_CJKecglue: \CJKecglue \cs_set_eq:NN \@@_shipout_check_for_glue: \xeCJK_check_for_glue: \cs_set_eq:NN \@@_shipout_boundary:w \xeCJK_CJK_and_Boundary:w \cs_set_protected:Npx \xeCJKOffVerbAddon { \@@_reset_char_class:n { FullLeft } \@@_reset_char_class:n { FullRight } \@@_reset_char_class:n { HalfLeft } \@@_reset_char_class:n { HalfLeft } \@@_reset_char_class:n { NormalSpace } \bool_if:NTF \l_@@_xecglue_bool { \keys_set:nn { xeCJK / options } { xCJKecglue = true } } { \keys_set:nn { xeCJK / options } { xCJKecglue = false } } \exp_not:n { \cs_set_eq:NN \CJKglue \@@_shipout_CJKglue: \cs_set_eq:NN \CJKecglue \@@_shipout_CJKecglue: \cs_set_eq:NN \xeCJK_check_for_glue: \@@_shipout_check_for_glue: \cs_set_eq:NN \xeCJK_CJK_and_Boundary:w \@@_shipout_boundary:w } } \xeCJK_add_to_shipout:n { \xeCJKOffVerbAddon } \keys_set:nn { xeCJK / options } { xCJKecglue = false } } \cs_new_protected:Npn \@@_verb_CJK_and_Boundary:w { \xeCJK_class_group_end: \CJKecglue } \cs_new_protected:Npn \@@_reset_char_class:n #1 { \int_set:Nn \l_@@_tmp_int { \xeCJK_class_num:n {#1} } \clist_map_inline:cn { c_@@_#1_chars_clist } { \tex_XeTeXcharclass:D ##1 = \l_@@_tmp_int } } \bool_new:N \l_@@_verb_addon_bool \cs_new_eq:NN \CJKfixedspacing \xeCJKVerbAddon % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_verb_exspace:} % \changes{v3.1.1}{2012/12/08}{调整间距的计算方法。} % \changes{v3.2.4}{2013/06/29}{当计算得出的间距为负时,缩小 CJK 字体。} % 在抄录环境中,CJK 文字之间的间距为当前西文字体两个空格的宽度与当前字体大小之差, % 而与西文和空格的间距为 CJK 文字之间的间距的一半。 % \begin{macrocode} \cs_new_protected:Npn \@@_set_verb_exspace: { \tl_if_exist:cTF { xeCJK/verb/\CJK@family/\curr@fontshape/\f@size } { \skip_set:Nn \l_@@_verb_exspace_skip { \use:c { xeCJK/verb/\CJK@family/\curr@fontshape/\f@size } } } { \tl_set:Nx \l_@@_current_coor_tl { \CJK@family/\curr@fontshape } \prop_get:NoNTF \g_@@_scale_family_prop \l_@@_current_coor_tl \l_xeCJK_family_tl { \xeCJK_switch_family:o { \l_xeCJK_family_tl } \skip_zero:N \l_@@_verb_exspace_skip } { \group_begin: \xeCJK_select_font: \exp_args:NNo \group_end: \@@_set_verb_exspace:n { \dim_use:N \tex_fontcharwd:D \tex_font:D "4E00 ~ } } } } \skip_new:N \l_@@_verb_exspace_skip % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_verb_exspace:n} % 当两个西文空格的宽度小于一个 CJK 文字的宽度时,对目前使用的 CJK 字体进行适当缩小。 % \begin{macrocode} \cs_new_protected:Npn \@@_set_verb_exspace:n #1 { \skip_set:Nn \l_@@_verb_exspace_skip { 2 \tex_fontdimen:D 2 ~ \tex_font:D - #1 } \dim_compare:nNnTF \l_@@_verb_exspace_skip < \c_zero_dim { \skip_zero:N \l_@@_verb_exspace_skip \exp_args:Nee \@@_set_verb_scale:nn { \dim_to_fp:n { 2 \tex_fontdimen:D 2 ~ \tex_font:D } } { \dim_to_fp:n {#1} } } { \tl_const:cx { xeCJK/verb/\CJK@family/\curr@fontshape/\f@size } { \skip_use:N \l_@@_verb_exspace_skip } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_verb_scale:nn} % 缩小 CJK 字体,并保存相关信息。 % \begin{macrocode} \cs_new_protected:Npn \@@_set_verb_scale:nn #1#2 { \fp_set:Nn \l_@@_scale_factor_fp { #1 / #2 } \@@_warning:nxx { scale-factor } { \fp_eval:n { trunc ( \l_@@_scale_factor_fp , 4 ) } } { \fp_eval:n { ceil ( #2 / #1 , 4 ) } } \xeCJK_add_font_features:Nne \c_true_bool { } { Scale = { \fp_use:N \l_@@_scale_factor_fp } } \prop_gput:Noo \g_@@_scale_family_prop \l_@@_current_coor_tl \l_xeCJK_family_tl } \@@_msg_new:nn { scale-factor } { `\token_to_str:N \xeCJKVerbAddon'~may~not~work~properly.\\\\ You~may~set~`Scale=#1'~to~CJKfamily~ `\@@_msg_family_map:n { \l_xeCJK_family_tl }',\\ or~set~`Scale=#2'~to~family~ `\str_if_eq:eeTF \f@family \ttdefault { \token_to_str:N \ttdefault } { \f@family }'. } \fp_new:N \l_@@_scale_factor_fp \prop_new:N \g_@@_scale_family_prop % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_visible_space:} % \begin{macro}[int]{\@setupverbvisiblespace} % \changes{v3.2.5}{2013/07/13}{可视空格考虑传统 \TeX 字体的情况。} % \changes{v3.8.0}{2020/02/09}{更新可视空格补丁。} % 如果文档不使用 \texttt{EU1} 作为默认字体编码,那么默认的打字机字体族很可能是 % 传统的 \TeX 字体,这时可视空格按照 \texttt{OT1} 编码传统一般就是字体中的 |\char32|。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_setup_visible_space: { \xeCJK_make_boundary: \xeCJK_glyph_if_exist:NTF { ^^^^2423 } { \tl_set:Nn \l_@@_visible_space_tl { ^^^^2423 } } { \int_compare:nNnTF { \tex_XeTeXfonttype:D \tex_font:D } = \c_zero_int { \tl_set:Nx \l_@@_visible_space_tl { \str_if_eq:eeTF { \f@family } { \ttdefault } { \c_catcode_other_space_tl } { \exp_not:N \textvisiblespace } } } { \@@_visible_space_fallback: } } \cs_set_eq:NN \@xobeysp \l_@@_visible_space_tl } \tl_new:N \l_@@_visible_space_tl \cs_set_eq:NN \@setupverbvisiblespace \xeCJK_setup_visible_space: % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_visible_space_fallback:} % 我们使用 |lmtt| 字体中的可视空格符号(|U+2423|)作为当前字体中相应符号 % 的后备,但是 |lmtt| 的字体大小未必与当前字体匹配。因此,这里需要做一些调整,以 % 保证使用后备可视空格符号时,也能保证对齐。 % \begin{macrocode} \cs_new_protected:Npn \@@_visible_space_fallback: { \exp_args:Nc \@@_visible_space_fallback_auxi:N { xeCJK/space/\curr@fontshape/\f@size } } \cs_new_protected:Npn \@@_visible_space_fallback_auxi:N #1 { \cs_if_exist:NF #1 { \@@_visible_space_fallback_auxii:N #1 } \tl_set:Nn \l_@@_visible_space_tl {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_visible_space_fallback_auxii:N} % 当前字体空格的宽度与后备字体 |lmtt| 不一样时,就对 \tn{textvisiblespace} 的字体尺寸 % 按相应的比例放缩。 % \begin{macrocode} \cs_new_protected:Npn \@@_visible_space_fallback_auxii:N #1 { \group_begin: \exp_args:No \@@_set_visible_space_size:n { \dim_use:N \tex_fontdimen:D 2 ~ \tex_font:D } \cs_new_protected:Npx #1 { \group_begin: \tex_the:D \tex_font:D ^^^^2423 \group_end: } \group_end: } \cs_new_protected:Npn \@@_set_visible_space_size:n #1 { \fontencoding { \UnicodeEncodingName } \tl_set:Nn \f@family { lmtt } \selectfont \dim_compare:nNnF {#1} = { \tex_fontdimen:D 2 ~ \tex_font:D } { \fontsize { \dim_eval:n { \f@size pt * \dim_ratio:nn {#1} { \tex_fontdimen:D 2 ~ \tex_font:D } } } { \f@baselineskip } \selectfont } } % \end{macrocode} % \end{macro} % % \subsection{\pkg{xeCJK} 其他选项} % % \begin{macro}{LocalConfig} % \changes{v3.1.0}{2012/11/20}{增加 \texttt{LocalConfig} 选项用于载入本地配置文件。} % 声明载入本地配置文件的选项。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { LocalConfig .choice: , LocalConfig / false .code:n = { \bool_gset_false:N \g_@@_config_bool } , LocalConfig / true .code:n = { \bool_gset_true:N \g_@@_config_bool \tl_gset:Nn \g_@@_config_name_tl { xeCJK } } , LocalConfig / unknown .code:n = { \bool_gset_true:N \g_@@_config_bool \tl_gset:Nx \g_@@_config_name_tl { xeCJK - \l_keys_value_tl } } , LocalConfig .default:n = { true } } \tl_new:N \g_@@_config_name_tl \bool_new:N \g_@@_config_bool % \end{macrocode} % \end{macro} % % \begin{macro}[int]{CJKnumber,indentfirst} % \changes{v3.2.11}{2014/03/14}{放弃 \texttt{indentfirst} 和 \texttt{CJKnumber} 选项。} % \texttt{CJKnumber} 和 \texttt{indentfirst} 是过时选项。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKnumber .code:n = { \@@_warning:nxx { option-deprecated } { \l_keys_key_tl } { CJKnumb } } , indentfirst .code:n = { \@@_warning:nxx { option-deprecated } { \l_keys_key_tl } { indentfirst } } , normalindentfirst .code:n = { \@@_warning:nxx { option-deprecated } { \l_keys_key_tl } { } } } \@@_msg_new:nn { option-deprecated } { The~`#1'~option~is~deprecated.\\ \tl_if_empty:nF {#2} { You~may~load~the~package~`#2'~after~xeCJK~to~use~its~function.\\ } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{quiet,silent} % 将调用 \pkg{xeCJK} 时使用的未知的选项传递给 \pkg{fontspec} 宏包。 % 对 \pkg{fontspec} 的 |quiet| 和 |silent| 选项进行修改,使其适用于 \pkg{xeCJK}。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { quiet .code:n = { \msg_redirect_module:nnn { xeCJK } { warning } { info } \msg_redirect_module:nnn { xeCJK } { info } { none } \xeCJK_if_package_loaded:nF { fontspec } { \PassOptionsToPackage { quiet } { fontspec } } } , silent .code:n = { \msg_redirect_module:nnn { xeCJK } { warning } { none } \msg_redirect_module:nnn { xeCJK } { info } { none } \xeCJK_if_package_loaded:nF { fontspec } { \PassOptionsToPackage { silent } { fontspec } } } , unknown .code:n = { \xeCJK_if_package_loaded:nTF { fontspec } { \@@_error:nx { key-unknown } { \l_keys_key_tl } } { \PassOptionsToPackage { \l_keys_key_tl } { fontspec } } } } \@@_msg_new:nn { key-unknown } { Sorry,~but~xeCJK/options~does~not~have~a~key~called~`#1'.\\\\ The~key~`#1'~is~being~ignored. } % \end{macrocode} % \end{macro} % % \subsection{\pkg{xeCJK} 初始化设置} % % \begin{macro}[int]{\CJKsymbol, \CJKpunctsymbol} % \begin{macrocode} \cs_new_eq:NN \CJKsymbol \use:n \cs_new_eq:NN \CJKpunctsymbol \use:n % \end{macrocode} % \end{macro} % % \pkg{xeCJK} 宏包的初始化设置。 % % \begin{macrocode} \keys_set:nn { xeCJK / options } { CJKglue = { \skip_horizontal:n { \c_zero_dim plus 0.08 \tex_baselineskip:D } } , CJKecglue = { ~ } , xCJKecglue = false , CheckSingle = false , PlainEquation = false , CheckFullRight = false , CJKspace = false , CJKmath = false , xeCJKactive = true , LocalConfig = true , LoadFandol = true , RubberPunctSkip = true , Verb = env , EmboldenFactor = 4 , SlantFactor = 0.167 , PunctStyle = quanjiao , NewLineCS = { \par \[ } , EnvCS = { \begin \end } , WidowPenalty = { 10 000 } , NoBreakCS = { \footnote \footnotemark \nobreak } , KaiMingPunct = { ^^^^3002 ^^^^ff0e ^^^^ff1f ^^^^ff01 } , LongPunct = { ^^^^2014 ^^^^2e3a ^^^^2025 ^^^^2026 } , MiddlePunct = { ^^^^2013 ^^^^2014 ^^^^2e3a ^^^^2027 ^^^^00b7 ^^^^30fb ^^^^ff65 } , AllowBreakBetweenPuncts = false } \defaultCJKfontfeatures { Script = CJK } % \end{macrocode} % % 半字线连接号\footnote{见\href{http://www.moe.gov.cn/ewebeditor/uploadfile/2015/01/13/20150113092346124.pdf} % {《夹用英文的中文文本的标点符号用法(草案)》5.13 节。}}应为半角宽度。 % \begin{macrocode} \xeCJKsetwidth { ^^^^2013 } { 0.5 em } % \end{macrocode} % % \changes{v3.7.0}{2018/03/16}{不再默认引入 \pkg{xunicode} 宏包。} % % 执行宏包选项,并载入 \pkg{fontspec} 宏包。 % \begin{macrocode} \cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions [ xeCJK / options ] } { \RequirePackage { l3keys2e } \ProcessKeysOptions { xeCJK / options } } \RequirePackage { fontspec } [ 2020/02/03 ] % \end{macrocode} % % \begin{variable}{\c_@@_encoding_tl} % 保存 \pkg{fontspec} 声明字体时使用的字体编码。 % \begin{macrocode} \tl_const:Nx \c_@@_encoding_tl { \g_fontspec_encoding_tl } % \end{macrocode} % \end{variable} % % \changes{v3.1.0}{2012/11/21}{改用 \pkg{indentfirst} 宏包处理缩进的问题。} % % 对不能通过 \tn{xeCJKsetup} 设置的选项给出警告。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { LocalConfig .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } } \@@_msg_new:nn { option-invalid } { The~`#1'~option~can~only~be~set~in~the~optional~argument~to~the\\ \token_to_str:N \usepackage \ command~when~xeCJK~is~being~loaded.\\\\ Please~do~not~set~it~via~the~\token_to_str:N \xeCJKsetup \ command. } % \end{macrocode} % % \begin{variable}{\CJKrmdefault,\CJKsfdefault,\CJKttdefault,\CJKfamilydefault} % \begin{macrocode} \tl_if_exist:NF \CJKrmdefault { \tl_gset:Nn \CJKrmdefault { rm } } \tl_if_exist:NF \CJKsfdefault { \tl_gset:Nn \CJKsfdefault { sf } } \tl_if_exist:NF \CJKttdefault { \tl_gset:Nn \CJKttdefault { tt } } \tl_new:N \l_@@_family_default_init_tl \cs_new_eq:NN \@@_family_default_wrap:n \use:n \tl_set:Nx \l_@@_family_default_init_tl { \exp_not:N \@@_family_default_wrap:n { \tl_if_exist:NTF \CJKfamilydefault { \exp_not:o \CJKfamilydefault } { \exp_not:N \CJKrmdefault } } } \tl_gset_eq:NN \CJKfamilydefault \l_@@_family_default_init_tl % \end{macrocode} % \end{variable} % % \begin{macro}{\xeCJKsetup} % 在导言区或文档中设置 \pkg{xeCJK} 的接口。 % \begin{macrocode} \NewDocumentCommand \xeCJKsetup { +m } { \keys_set:nn { xeCJK / options } {#1} \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJKsetemboldenfactor, \xeCJKsetslantfactor} % \begin{macrocode} \NewDocumentCommand \xeCJKsetemboldenfactor { m } { \xeCJKsetup { EmboldenFactor = {#1} } } \NewDocumentCommand \xeCJKsetslantfactor { m } { \xeCJKsetup { SlantFactor = {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\punctstyle, \xeCJKplainchr} % \begin{macrocode} \NewDocumentCommand \punctstyle { m } { \xeCJKsetup { PunctStyle = {#1} } } \NewDocumentCommand \xeCJKplainchr { } { \xeCJKsetup { PunctStyle = plain } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKsetecglue} % \begin{macrocode} \NewDocumentCommand \CJKsetecglue { m } { \xeCJKsetup { CJKecglue = {#1} } } \cs_new_eq:NN \xeCJKsetecglue \CJKsetecglue % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKspace,\CJKnospace} % \begin{macrocode} \NewDocumentCommand \CJKspace { } { \xeCJKsetup { CJKspace = true } } \NewDocumentCommand \CJKnospace { } { \xeCJKsetup { CJKspace = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJKallowbreakbetweenpuncts, \xeCJKnobreakbetweenpuncts} % \begin{macrocode} \NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } { \xeCJKsetup { AllowBreakBetweenPuncts = true } } \NewDocumentCommand \xeCJKnobreakbetweenpuncts { } { \xeCJKsetup { AllowBreakBetweenPuncts = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJKenablefallback, \xeCJKdisablefallback} % \begin{macrocode} \NewDocumentCommand \xeCJKenablefallback { } { \xeCJKsetup { AutoFallBack = true } } \NewDocumentCommand \xeCJKdisablefallback { } { \xeCJKsetup { AutoFallBack = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJKsetcharclass} % \begin{macrocode} \NewDocumentCommand \xeCJKsetcharclass { m m m } { \xeCJK_set_char_class:nnn {#1} {#2} {#3} \xeCJKResetPunctClass } % \end{macrocode} % \end{macro} % % \subsection{兼容性修补} % % \changes{v3.2.16}{2014/11/20}{修复 \tn{hbar}。} % \changes{v3.8.0}{2020/02/09}{删除 \tn{hbar} 补丁。} % % \begin{macro}[int]{\xeCJK@update@fam,\Url@MathSetup} % \changes{v3.2.7}{2013/11/09}{使通过 \tn{UrlFont} 等命令设置的 CJK 字体生效。} % 使通过 \tn{urlstyle} 或者 \tn{UrlFont} 设置的路径中使用的 CJK 字体生效。 % 使用 \tn{everymath} 钩子中数学模式中重定义 CJK 数学字体,以确保我们的设置在 % \tn{check@mathfonts} 之后生效,不会被它覆盖。 % 更合理的方式是定义一个新的 \tn{mathversion} 来切换。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK@update@fam { \addto@hook \everymath { \@@_update_main_fam: \@@_update_block_fam: } } \cs_new_protected:Npn \@@_update_main_fam: { \group_begin: \xeCJK_select_font: \exp_last_unbraced:NNNo \group_end: \tex_textfont:D \c_xeCJK_math_fam_int \tex_the:D \tex_font:D } \cs_new_protected:Npn \@@_update_block_fam: { \prop_if_empty:NF \g_@@_block_fam_prop { \prop_map_function:NN \g_@@_block_fam_prop \@@_update_block_fam:nn } } \cs_new_protected:Npn \@@_update_block_fam:nn #1#2 { \int_set:Nn \l_@@_fam_int {#2} \group_begin: \xeCJK_select_font:n {#1} \exp_last_unbraced:NNNo \group_end: \tex_textfont:D \l_@@_fam_int \tex_the:D \tex_font:D } \@@_after_end_preamble:n { \bool_lazy_and:nnT { \g_@@_math_bool } { \cs_if_exist_p:N \Url@MathSetup } { \tl_put_right:Nn \Url@MathSetup { \xeCJK@update@fam } } } % \end{macrocode} % \end{macro} % % \changes{v3.2.6}{2013/08/02}{为 \tn{mathrm} 减少一个可能的数学字体族。} % \changes{v3.8.0}{2020/02/09}{删除 \tn{mathrm} 补丁。} % % \changes{v3.4.5}{2017/01/02}{更新 \LaTeXiii{} 的过时用法。} % % \begin{macro}[int]{\(,\),\math,\endmath,\ensuremath} % \begin{macro}{\@@_math_robust:N} % \changes{v3.2.5}{2013/07/25} % {解决汉字后紧跟 \tn{(}\texttt{...}\tn{)} 形式的行内数学公式时,不能加入间距的问题。} % \changes{v3.2.6}{2013/08/03}{考虑 \pkg{ulem} 对 \tn{MakeRobust} 的不当定义。} % \changes{v3.2.6}{2013/08/03}{考虑 \tn{math} 和 \tn{ensuremath}。} % \changes{v3.3.1}{2015/04/14}{兼容 \LaTeXe{} 2015。} % \tn{(} 的在 \LaTeXe 中的定义是 % \begin{verbatim} % \def\({\relax\ifmmode\@badmath\else$\fi} % \end{verbatim} % 这个定义最开始的 \tn{relax} 是为了防止 \tn{(} 出现在表格单元格的开始位置时,模式 % 判断不正确(因为 \TeX 会先看单元格中第一个不可展的非空格记号是否是 \tn{omit} 或 % \tn{noalign})。但是它会造成一个边界,使 \pkg{xeCJK} 不能看到 \tn{relax} 后面出现的 % |$|,从而不能加入间距\footnote{\url{http://tex.stackexchange.com/q/124773}}。使用 % \hologo{eTeX} 的 \tn{protected} 来定义它,可以不需要 \tn{relax},或者将 \tn{relax} % 改成 \cs{scan_align_safe_stop:},都可以避免这些情况。同时 \pkg{fixltx2e} 中还使用了 % |\MakeRobust\(|,我们需要小心处理。另外 \pkg{ulem} 也定义了一个 \tn{MakeRobust}, % 如果它被放在 \pkg{fixltx2e} 之前载入,那么 \pkg{fixltx2e} 的定义就会失效(因为 % \pkg{fixltx2e} 使用 \tn{providecommand}|*| 来定义 \tn{MakeRobust})。但是 \pkg{ulem} % 的定义并不完全正确,没有考虑 \TeX 不会略去控制符号后面的空格的情况。 % \begin{macrocode} \cs_new_protected:Npn \@@_math_robust:N #1 { \group_begin: \exp_args:NcNc \group_end: { @@_math_robust_aux:NN } #1 { \cs_to_str:N #1 ~ } } \cs_new_protected:Npn \@@_math_robust_aux:NN #1#2 { \exp_args:Ne \str_case:nnTF { \cs_replacement_spec:N #1 } { { \x@protect #1 \protect #2 } { } { \protect #2 } { } } { \@@_math_robust:NN #1#2 } { \@@_math_robust:NN #1#1 } } \cs_new_protected:Npn \@@_math_robust:NN #1#2 { \str_if_eq:eeTF { \cs_argument_spec:N #2 } { } { \exp_args:No \tl_if_head_eq_meaning:nNTF {#2} \scan_stop: { \cs_gset_protected:Npx #1 { \tl_tail:N #2 } } { \cs_if_eq:NNTF #1 \ensuremath { \cs_gset_protected:Npx #1 { \exp_not:o {#2} } } { \@@_warning:nxx { robust-failure } { \token_to_str:N #1 } { \token_to_meaning:N #2 } } } } { \@@_warning:nxx { robust-failure } { \token_to_str:N #1 } { \token_to_meaning:N #2 } } } \@@_msg_new:nnn { robust-failure } { xeCJK~can~not~make~`#1'~robust. } { The~current~meaning~of~`#1'~is:\\ \iow_indent:n {#2} } \cs_if_eq:NNTF \( \math { \@@_math_robust:N \( \cs_set_eq:NN \math \( } { \@@_math_robust:N \( \@@_math_robust:N \math } \cs_if_eq:NNTF \) \endmath { \@@_math_robust:N \) \cs_set_eq:NN \endmath \) } { \@@_math_robust:N \) \@@_math_robust:N \endmath } \@@_math_robust:N \ensuremath % \end{macrocode} % \end{macro} % \end{macro} % % \changes{v3.2.5}{2013/07/25}{解决 \pkg{fixltx2e} 和 \pkg{amsthm} 的冲突。} % \changes{v3.3.1}{2015/04/15}{删去 \pkg{fixltx2e} 和 \pkg{amsthm} 的冲突补丁。} % % \changes{v3.1.2}{2013/01/01} % {修正非 \tn{UTFencname} 编码下面 \pkg{xunicode} 重定义的 \tn{nobreakspace} 会失效的问题。} % \changes{v3.2.5}{2013/07/18}{恢复 \tn{nobreakspace} 的原始定义。} % \changes{v3.7.0}{2018/03/18}{对 \tn{nobreakspace} 的恢复放到 \pkg{xunicode-addon} 中处理。} % % \changes{v3.1.1}{2012/12/13}{对于与 \pkg{xltxtra} 的冲突给出错误警告。} % \changes{v3.8.0}{2020/02/09}{删除 \pkg{realscripts} 补丁。} % % \changes{v3.8.6}{2020/10/17}{兼容 \LaTeX\ 2020/10/01 的 \pkg{NFSS} 钩子机制。} % % \begin{macro}[int]{\fontfamily} % \begin{macro}[int]{\xeCJK@fontfamily,\xeCJK@family} % \changes{v3.1.1}{2012/12/06}{修改主要 \texttt{CJK} 字体族的自动更新方式。} % \changes{v3.1.2}{2013/01/01}{不将参数完全展开。} % \changes{v3.4.6}{2017/02/23} % {将族名参数完全展开,以解决与 \pkg{fontspec} 2017/01/24 v2.5d 的兼容问题。} % 对于 \LaTeXe\ 2020/02/02 之前的版本,修改 \tn{fontfamily}, % 使主要 |CJK| 字体族能随西文主要字体更新,之后的版本可以使用 \tn{@rmfamilyhook} 等新钩子处理。 % \LaTeXe\ 2020/10/01 提供了新的的 \pkg{NFSS} 钩子。 % \begin{macrocode} \ctex_if_format_at_least:nTF { 2020/10/01 } { \cs_set_eq:NN \xeCJK@family \xeCJK_switch_family:e \ctex_gadd_ltxhook:nn { rmfamily } { \xeCJK@family { \CJKrmdefault } } \ctex_gadd_ltxhook:nn { sffamily } { \xeCJK@family { \CJKsfdefault } } \ctex_gadd_ltxhook:nn { ttfamily } { \xeCJK@family { \CJKttdefault } } \ctex_gadd_ltxhook:nn { normalfont } { \xeCJK@family { \CJKfamilydefault } } } { \cs_if_exist:NTF \@rmfamilyhook { \cs_set_eq:NN \xeCJK@family \xeCJK_switch_family:e \g@addto@macro \@rmfamilyhook { \xeCJK@family { \CJKrmdefault } } \g@addto@macro \@sffamilyhook { \xeCJK@family { \CJKsfdefault } } \g@addto@macro \@ttfamilyhook { \xeCJK@family { \CJKttdefault } } \exp_args:Nc \g@addto@macro { \cs_if_exist:NTF \@defaultfamilyhook { @defaultfamilyhook } { normalfont ~ } } { \xeCJK@family { \CJKfamilydefault } } } { \RenewDocumentCommand \fontfamily { m } { \tl_set:Nx \f@family {#1} \xeCJK@fontfamily {#1} } \cs_new_protected:Npn \xeCJK@fontfamily #1 { \str_if_eq:nnTF {#1} { \familydefault } { \xeCJK_switch_family:e { \CJKfamilydefault } } { \@@_update_family_aux: } } \cs_new_protected:Npn \@@_update_family_aux: { \str_case_e:nn { \f@family } { { \rmdefault } { \xeCJK_switch_family:e { \CJKrmdefault } } { \sfdefault } { \xeCJK_switch_family:e { \CJKsfdefault } } { \ttdefault } { \xeCJK_switch_family:e { \CJKttdefault } } { \familydefault } { \xeCJK_switch_family:e { \CJKfamilydefault } } } } } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \begin{macro}[int]{\xeCJK@fix@penalty} % \changes{v3.1.0}{2012/11/13}{采用通过不修改原语 \tn{/} 的方式对修复倾斜校正。} % 对 \LaTeXe 内核中的 \tn{fix@penalty} 被用于诸如 \tn{textit} 之类的文档 % 字体转换命令的定义之中。这里对它进行补丁的目的是修复其中的倾斜校正,并使得这些 % 文档命令与紧随其后的汉字之间可以正确的插入 \tn{CJKecglue} 或者忽略其中的空格。 % 例如 \verb*|这是 \emph{强调} 文本|,第二个空格可以被忽略掉。如果使用 |xCJKecglue| % 选项,第一个空格也可以被省略。事实上,在 \tn{sw@slant} 的定义中,\tn{@@italiccorr} % 前面的 \tn{lastskip} 和 \tn{lastpenalty} 有四种情况,这里只对它们都为零的情况进行 % 处理。 % \begin{macrocode} \cs_new_eq:NN \xeCJK@fix@penalty \fix@penalty \tl_replace_once:Nnn \xeCJK@fix@penalty { \@@italiccorr } { \xeCJK@italiccorr } \tl_replace_once:Nnn \sw@slant { \fix@penalty } { \xeCJK@fix@penalty } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK@italiccorr} % 修复倾斜校正,并处理汉字后面的空格。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK@italiccorr { \int_compare:nNnTF \tex_XeTeXinterchartokenstate:D > \c_zero_int { \xeCJK_italic_correction: } { \@@italiccorr } } % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=xeCJK> % \end{macrocode} % % \begin{macro}[int]{\xeCJK_italic_correction:} % 修复倾斜校正,并处理汉字后面的空格。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_italic_correction: { \@@_if_last_kern:T { \@@_italic_correction: } } \cs_new_protected:Npn \@@_italic_correction: { \dim_case:nnF { \tex_lastkern:D } { { \@@_node:n { default } } { \xeCJK_remove_node: \tex_italiccorrection:D \xeCJK_make_node:n { default } } { \@@_node:n { CJK } } { \xeCJK_remove_node: \tex_italiccorrection:D \xeCJK_make_node:n { CJK } \@@_italic_correction_aux: } { \@@_node:n { CJK-space } } { \xeCJK_remove_node: \tex_italiccorrection:D \xeCJK_make_node:n { CJK-space } \@@_italic_correction_aux: } } { \tex_italiccorrection:D } } % \end{macrocode} % \cs{xeCJK_ignore_spaces:w} 里面用到 |peek| 函数来判断后面是不是空格,而此时它 % 后面还有 $4$ 个 \tn{fi} 或者 |\else...\fi| 没有被展开,将影响 |peek| 函数的 % 判断。因此我们需要用 $2^4-1=15$ 个 \cs{exp_after:wN} 来展开它们。 % 显然,这里用 \cs{exp_last_unbraced:Nf} 会比较方便,但是它会吃掉 % \verb*|\textit{...} | 等后面原来存在的空格作为完全展开的结束。要正确使用它还 % 需要另外的处理(使用 \cs{exp_stop_f:})。 % \begin{macrocode} \cs_new_protected:Npn \@@_italic_correction_aux: { \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \xeCJK_ignore_spaces:w } % \end{macrocode} % \end{macro} % % \begin{variable}{\g_@@_xetex_allocator_int} % \changes{v3.3.1}{2015/04/14}{兼容 \LaTeXe{} 2015。} % \changes{v3.3.2}{2015/05/15}{\tn{xe@alloc@intercharclass} 总是有定义的。} % \LaTeXe{} 2015/01/01 接管了 \tn{newXeTeXintercharclass}。 % \begin{macrocode} \cs_new_eq:NN \g_@@_xetex_allocator_int \xe@alloc@intercharclass % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_set_others_toks:n} % 简单处理与同样使用 \tn{XeTeXinterchartoks} 机制的宏包的兼容问题。 % \begin{macrocode} \@@_after_end_preamble:n { \int_compare:nNnF { \c_@@_class_begin_int + \seq_count:N \g_@@_new_class_seq } = { \g_@@_xetex_allocator_int } { \int_step_inline:nnn { \c_@@_class_begin_int + 1 } { \g_@@_xetex_allocator_int } { \seq_if_in:NnF \g_@@_new_class_seq {#1} { \@@_set_others_toks:n {#1} } } } } \cs_new_protected:Npn \@@_set_others_toks:n #1 { \int_set:cn { \@@_class_csname:n { Others } } {#1} \seq_map_inline:Nn \g_@@_CJK_class_seq { \xeCJK_copy_inter_class_toks:nnnn {##1} { Others } {##1} { NormalSpace } \xeCJK_copy_inter_class_toks:nnnn { Others } {##1} { NormalSpace } {##1} \xeCJK_app_inter_class_toks:nne {##1} { Others } { \xeCJK_get_inter_class_toks:nn { Default } { Others } } \xeCJK_pre_inter_class_toks:nne { Others } {##1} { \xeCJK_get_inter_class_toks:nn { Others } { Default } } \tl_if_blank:eT { \xeCJK_get_inter_class_toks:nn { Others } { Boundary } } { \xeCJK_copy_inter_class_toks:nnnn { Others } { Boundary } { Default } { Boundary } } \tl_if_blank:eT { \xeCJK_get_inter_class_toks:nn { Boundary } { Others } } { \xeCJK_copy_inter_class_toks:nnnn { Boundary } { Others } { Boundary } { Default } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_inactive_group_begin:,\@@_inactive_group_end:} % 用于保护下面歧义宽度标点的分组。 % \begin{macrocode} \cs_new_protected:Npn \@@_inactive_group_begin: { \group_begin: \makexeCJKinactive } \cs_new_eq:NN \@@_inactive_group_end: \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_patch_text_command:} % \begin{variable}{\c_@@_ambiguous_char_prop} % 单独处理宽度有分歧的几个标点:包括省略号、破折号、间隔号、引号等中西文混用的 % 符号, 保证其命令形式输出的是西文字体。 % 如果 \pkg{xunicode} 宏包被载入,则通过 \pkg{xunicode-addon} 处理。 % \begin{macrocode} \prop_const_from_keyval:Nn \c_@@_ambiguous_char_prop { "00B7 = \textperiodcentered \textcentereddot \textcdot , "2013 = \textendash , "2014 = \textemdash , "2018 = \textquoteleft \textgrq , "2019 = \textquoteright , "201C = \textquotedblleft \textgrqq , "201D = \textquotedblright , "2025 = \texthdotfor , "2026 = \textellipsis , "2027 = \texthyphenationpoint , "2E3A = \texttwoemdash } \@@_at_end_preamble:n { \@@_patch_text_command: } \cs_new_protected:Npn \@@_patch_text_command: { \xeCJK_if_package_loaded:nTF { xunicode } { \@@_patch_xunicode_ambiguous_char: } { \exp_args:Ne \@@_patch_tuenc_ambiguous_char:n { \UnicodeEncodingName } \@@_patch_tuenc_accent: \@@_patch_tuenc_composite: } } \cs_new_protected:Npn \@@_patch_xunicode_ambiguous_char: { \RequirePackage { xunicode-addon } \prop_map_inline:Nn \c_@@_ambiguous_char_prop { \tl_map_inline:nn { ##2 } { \xunadd_set_begin_hook:nn { ####1 } { \@@_inactive_group_begin: } \xunadd_set_end_hook:nn { ####1 } { \@@_inactive_group_end: } } } \xunadd_append_begin_hook:n { \xeCJK_make_boundary: } } \cs_new_protected:Npn \@@_patch_tuenc_ambiguous_char:n #1 { \prop_map_inline:Nn \c_@@_ambiguous_char_prop { \tl_map_inline:nn { ##2 } { \cs_if_exist:NF ####1 { \DeclareTextSymbol ####1 {#1} { ##1 } } \@@_patch_ambiguous_char:nN {#1} ####1 } } } \cs_new_protected:Npn \@@_patch_ambiguous_char:nN #1#2 { \exp_args:Ne \@@_patch_ambiguous_char:nn { #1 \token_to_str:N #2 } { #1 - #2 } } \cs_new_protected:Npx \@@_patch_ambiguous_char:nNn #1#2#3 { \exp_not:N \exp_args:Ne \exp_not:N \@@_patch_ambiguous_char:nn { \c_backslash_str #1 \exp_not:N \token_to_str:N #2 - \exp_not:N \token_to_str:N #3 } { #1 - #2#3 } } \cs_new_protected:Npn \@@_patch_ambiguous_char:nn #1#2 { \cs_if_free:cF {#1} { \exp_args:Nc \@@_patch_ambiguous_char:Nn {#1} {#2} } } \cs_new_protected:Npn \@@_patch_ambiguous_char:Nn #1#2 { \token_if_chardef:NTF #1 { \prop_gput:Nne \c_@@_ambiguous_slot_prop {#2} { \int_eval:n {#1} } \cs_set_protected:Npx #1 { \@@_ambiguous_char:n { \tex_Uchar:D #1 } } } { \prop_gput:Nne \c_@@_ambiguous_slot_prop {#2} { \int_eval:n { \exp_after:wN ` #1 } } \cs_set_protected:Npx #1 { \@@_ambiguous_char:n { \exp_not:o {#1} } } } } \cs_new_protected:Npn \@@_ambiguous_char:n #1 { \int_compare:nNnTF \tex_XeTeXinterchartokenstate:D > \c_zero_int { \@@_inactive_group_begin: #1 \@@_inactive_group_end: } {#1} } \prop_new:N \c_@@_ambiguous_slot_prop % \end{macrocode} % \end{variable} % \end{macro} % % \begin{macro}{\@@_patch_tuenc_composite:} % \changes{v3.7.2}{2018/05/02}{修复补丁错误。} % \tn{DeclareUnicodeComposite} 具有检查字符是否存在的功能, % 当符号命令紧跟在 CJK 字符类后面时,需要使字体回到西文状态 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_text_composite_patch: { \str_if_eq:eeT { \f@encoding } { \UnicodeEncodingName } { \xeCJK_make_boundary: } } % \end{macrocode} % 注意 \cs{xeCJK_text_composite_patch:} 可能会结束分组,从而导致 |##1| 没有定义时是 % \tn{undefined} 而不是 \tn{relax},所以不能将它与 \tn{relax} 作比较。 % \begin{macrocode} \cs_new_protected:Npn \@@_patch_tuenc_composite: { \cs_set_nopar:Npn \@text@composite@x { \xeCJK_text_composite_patch: \cs_if_exist_use:NF } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_patch_tuenc_accent:} % \tn{add@unicode@accent} 定义最后用于截断数字展开的 \tn{relax} 会造成边界,可能会影响组合标记。 % \begin{macrocode} \group_begin: \char_set_catcode_other:n { "A0 } \cs_new_protected:Npn \@@_patch_tuenc_accent: { \cs_set_protected_nopar:Npn \add@unicode@accent ##1 ##2 { \tl_if_blank:nTF { ##2 } { ^^a0 } { ##2 } \tex_Uchar:D \tex_numexpr:D ##1 \scan_stop: } } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_patch_middle_dot:} % \begin{variable}{\c_@@_middle_dot_prop} % \changes{v3.2.9}{2013/12/08} % {完整处理 \file{encguide.pdf} 的编码符号表中,与旧编码的 \texttt{U+00B7} 冲突。} % 常被用作中文间隔号的 \texttt{U+00B7} 与 T1 等旧字体编码下定义的符号命令冲突。 % 在 \file{encguide.pdf} 的编码符号表中,如下定义有冲突。 % \begin{verbatim} % \DeclareTextComposite{\r}{T1}{u}{183} % \DeclareTextSymbol{\cyrchvcrs}{T2A}{183} % \DeclareTextSymbol{\cyrchldsc}{T2B}{183} % \DeclareTextSymbol{\cyrabhha}{T2C}{183} % \DeclareTextSymbol\textvibyy{T3}{183} % \DeclareTextComposite{\B}{T4}{t}{183} % \DeclareTextComposite{\`}{T5}{\ecircumflex}{183} % \DeclareTextDoubleComposite{\`}{T5}{\^}{e}{183} % \DeclareTextSymbol{\textperiodcentered}{TS1}{183} % \DeclareTextSymbol{\cyrchldsc}{X2}{183} % \DeclareTextSymbol{\textperiodcentered}{LY1}{183} % \end{verbatim} % LGR 编码的符号表有 \texttt{183} 号字符,但在 \file{lgrenc.def} 中未找到相应的 % 符号命令。 % \begin{macrocode} \prop_const_from_keyval:Nn \c_@@_middle_dot_prop { T2A = \cyrchvcrs , T2B = \cyrchldsc , T2C = \cyrabhha , X2 = \cyrchldsc , TS1 = \textperiodcentered , LY1 = \textperiodcentered , T1 = \r u , T4 = \B t , T5 = \` \ecircumflex } \@@_at_end_preamble:n { \@@_patch_middle_dot: } \cs_new_protected:Npn \@@_patch_middle_dot: { \prop_map_inline:Nn \c_@@_middle_dot_prop { \@@_patch_middle_dot:nw { ##1 } ##2 \q_stop } \@@_patch_ambiguous_char:nNn { T5 } \` { \^ - e } } \cs_new_protected:Npn \@@_patch_middle_dot:nw #1#2#3 \q_stop { \tl_if_empty:nTF {#3} { \@@_patch_ambiguous_char:nN {#1} #2 } { \@@_patch_ambiguous_char:nNn {#1} #2 {#3} } } % \end{macrocode} % \pkg{pifont} 宏包的符号 |\ding{183}| 也有冲突。 % \begin{macrocode} \@@_package_hook:nn { pifont } { \RenewDocumentCommand \Pifont { m } { \makexeCJKinactive \usefont { U } {#1} { m } { n } } } % \end{macrocode} % \end{variable} % \end{macro} % % \changes{v3.8.3}{2020/04/09}{兼容 \pkg{unicode-math} 和 \opt{CJKmath} 选项。} % % \begin{macro}{\@@_save_um_char:, \@@_save_um_char:} % 兼容 \pkg{unicode-math} 和 \opt{CJKmath} 选项, % 避免将一些中西文混用的标点设置为 CJK 字体。 % \begin{macrocode} \@@_package_hook:nn { unicode-math } { \prop_const_from_keyval:Nn \c_@@_um_ambiguous_char_prop { "00B7 = \cdotp , "2025 = \enleadertwodots , "2026 = \unicodeellipsis } \cs_new_protected:Npn \@@_save_um_char: { \cs_set_protected:Npx \@@_restore_um_char: { \prop_map_function:NN \c_@@_um_ambiguous_char_prop \@@_restore_um_char_aux:nn } } \cs_new_eq:NN \@@_restore_um_char: \prg_do_nothing: \cs_new:Npn \@@_restore_um_char_aux:nn #1#2 { \@@_gset_mathcodenum:nn { \int_value:w #1 } { \int_value:w \tex_Umathcodenum:D #1 } } \cs_new_protected:Npn \@@_gset_mathcodenum:nn #1#2 { \int_compare:nNnF { \tex_Umathcodenum:D #1 } = {#2} { \tex_global:D \tex_Umathcodenum:D #1 = #2 ~ } } } % \end{macrocode} % \end{macro} % % \changes{v3.8.5}{2020/06/25}{进一步兼容 \pkg{microtype}。} % % \begin{macro}{\@@_patch_microtype_get_slot:} % 兼容 \pkg{microtype}。 % \begin{macrocode} \cs_new_protected:Npn \@@_patch_microtype_get_slot: { \cs_new_eq:NN \xeCJK@original@get@slot \MT@get@slot@ \cs_set_eq:NN \MT@get@slot@ \xeCJK@microtype@get@slot \cs_set_eq:NN \MT@warn@unknown@once \use_none:n } \cs_new_protected_nopar:Npn \xeCJK@microtype@get@slot { \int_compare:nNnT \MT@char < \c_zero_int { \@@_get_ambiguous_slot: } \xeCJK@original@get@slot } \cs_new_protected:Npn \@@_get_ambiguous_slot: { \prop_get:NeNT \c_@@_ambiguous_slot_prop { \MT@encoding - \tex_the:D \MT@toks } \l_@@_tmp_tl { \cs_set_eq:NN \MT@char \l_@@_tmp_tl } } \cs_new_protected:Npn \xeCJK@microtype@restore@pickupfont { \@@_gadd_font_initial_hook:n { \MT@ltx@pickupfont } } \@@_package_hook:nn { microtype } { \cs_if_free:NF \MT@get@slot@ { \@@_patch_microtype_get_slot: } \MT@addto@setup { \xeCJK@microtype@restore@pickupfont } } % \end{macrocode} % \end{macro} % % 简单处理与 \pkg{hyperref} 宏包的兼容问题。 % \begin{macrocode} \@@_package_hook:nn { hyperref } { \pdfstringdefDisableCommands { \@@_gobble_CJKfamily: \xeCJK_cs_clear:N \@@_inactive_group_begin: \xeCJK_cs_clear:N \@@_inactive_group_end: \xeCJK_cs_clear:N \makexeCJKinactive \xeCJK_cs_clear:N \xeCJK_text_composite_patch: } } % \end{macrocode} % % \changes{v3.1.0}{2012/11/13}{取消 \tn{cprotect} 的外部宏限制。} % 当探测到 \pkg{cprotect} 宏包被引入时,则取消 \tn{cprotect} 宏的 \tn{outer} 定义。 % \begin{macrocode} \@@_package_hook:nn { cprotect } { \cs_if_free:NF \icprotect { \exp_after:wN \tex_let:D \cs:w cprotect \cs_end: \icprotect } } % \end{macrocode} % % \changes{v3.2.11}{2014/03/14}{删除 \tn{xeCJKcaption}。} % \changes{v3.8.0}{2020/02/09}{删除 \pkg{CJKfntef} 补丁。} % % 在 \pkg{listings} 宏包后自动载入 \pkg{xeCJK-listings}。 % \begin{macrocode} \@@_package_hook:nn { listings } { \RequirePackage { xeCJK-listings } } % \end{macrocode} % % % \changes{v3.3.3}{2015/12/12}{解决与 \pkg{microtype} 宏包的兼容问题。} % 由于 \pkg{xeCJK} 假装 \pkg{CJK} 已经被引入了,这会可能导致旧版本的 \pkg{everysel} 包判断错误。 % 需要在它们判断之前取消定义。 % \begin{macrocode} \@@_package_hook:nn { everysel } { \cs_if_exist:NF \@EverySelectfont@Legacy { \cs_undefine:c { ver@CJK . \c_@@_package_ext_tl } } } % \end{macrocode} % % \changes{v3.2.4}{2013/06/25}{不再使用 \texttt{CJKnumber} 选项,可以在 % \pkg{xeCJK} 之后直接使用 \pkg{CJKnumb} 宏包得到中文数字。} % \changes{v3.8.7}{2021/06/04}{更好地兼容 \pkg{CJKnumb}。} % % \begin{macro}[int]{\CJKaddEncHook} % 为使用 \pkg{CJKnumb} 宏包而作一些处理。另外 \pkg{CJKnumb} 使用的是传统汉字“萬” % 和“億”,我们在这里把它们修正为简体字。 % \changes{v3.2.10}{2014/03/01}{使用 \pkg{CJKnumb} 时,让 \tn{Unicode} 有定义。} % \changes{v3.3.1}{2015/05/08}{应用 \texttt{0.99992} 版的新原语 \tn{Ucharcat}。} % \begin{macrocode} \ctex_at_begin_package:nn { CJKnumb } { \tl_new:N \l_@@_CJK_version_tl \tl_set_eq:Nc \l_@@_CJK_version_tl { ver@CJK . \c_@@_package_ext_tl } \tl_set:cn { ver@CJK . \c_@@_package_ext_tl } { 9999/99/99 } \cs_new_protected:Npn \CJKaddEncHook #1#2 { \str_if_eq:nnT {#1} { \CJK@UnicodeEnc } { \group_begin: \cs_set_eq:NN \Unicode \xeCJK_unicode_char:nn \cs_set_eq:NN \def \xdef #2 \group_end: \str_gset:Nn \CJK@tenthousand { ^^^^4e07 } \str_gset:Nn \CJK@hundredmillion { ^^^^4ebf } \tl_if_exist:NF \CJK@UnicodeEnc { \tl_const:Nn \CJK@UnicodeEnc { UTF8 } } \cs_if_exist:NF \Unicode { \cs_new_eq:NN \Unicode \xeCJK_unicode_char:nn } } } \cs_new:Npn \xeCJK_unicode_char:nn #1#2 { \tex_Uchar:D \tex_numexpr:D (#1) * 256 + (#2) \scan_stop: } } \ctex_at_end_package:nn { CJKnumb } { \tl_set_eq:cN { ver@CJK . \c_@@_package_ext_tl } \l_@@_CJK_version_tl } % \end{macrocode} % \end{macro} % % 最后引入本地配置文件。 % \begin{macrocode} \bool_if:NT \g_@@_config_bool { \ExplSyntaxOff \file_input:n { \g_@@_config_name_tl .cfg } \ExplSyntaxOn } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJKfntef}} % % \changes{v3.1.1}{2012/12/08}{增加小宏包 \pkg{xeCJKfntef},用于处理下划线的问题。} % \changes{v3.2.4}{2013/06/23}{修正 \pkg{xeCJKfntef} 与 \pkg{natbib} 等的冲突。} % \changes{v3.2.14}{2014/10/31}{完善 \tn{varCJKunderline} 的实现。} % \changes{v3.2.14}{2014/10/31}{解决下划线前后没有 \tn{CJKglue} 或 \tn{CJKecglue} 的问题。} % \changes{v3.2.14}{2014/11/03}{\pkg{xeCJKfntef} 不再依赖 \pkg{CJKfntef}。} % \changes{v3.2.15}{2014/11/07}{\pkg{xeCJKfntef} 增加 \texttt{hidden} 选项。} % % \begin{macrocode} %<*fntef> % \end{macrocode} % % \begin{macrocode} \PassOptionsToPackage { normalem } { ulem } \DeclareOption* { \PassOptionsToPackage { \CurrentOption } { ulem } } \ProcessOptions \scan_stop: % \end{macrocode} % % \begin{macrocode} \RequirePackage { xeCJK } \RequirePackage { ulem } % \end{macrocode} % % \begin{macrocode} \addto@hook \UL@hook { \xeCJK_hook_for_ulem: } % \end{macrocode} % % \changes{v3.4.1}{2016/06/03}{新的下划线选项 \texttt{textformat}。} % % \begin{macro}[int]{\xeCJK_hook_for_ulem:} % \changes{v3.1.0}{2012/11/16}{简化对 \pkg{ulem} 宏包的兼容补丁。} % \changes{v3.1.1}{2012/12/08}{完全处理下划线里的标点符号的有关问题。} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_hook_for_ulem: { \xeCJK_ulem_detect_node: \l_@@_ulem_text_format_tl \bool_if:NF \l_@@_ulem_hook_used_bool { \bool_set_true:N \l_@@_ulem_hook_used_bool \@@_ulem_hook: } \xeCJK_ulem_begin_node: } \cs_new_protected:Npn \@@_ulem_hook: { \@@_ulem_initial: \bool_if:NT \l_@@_ulem_subtract_bool { \xeCJK_swap_cs:NN \UL@leaders \xeCJK_ulem_leaders: \cs_set_eq:NN \@@_ulem_var_leaders: \xeCJK_ulem_var_leaders: \cs_set_eq:NN \xeCJK_ulem_right_skip: \@@_ulem_right_skip: } \bool_if:NT \l_@@_ulem_hidden_bool { \cs_set_eq:NN \UL@putbox \@@_ulem_hidden_box: } \bool_if:NTF \l_@@_ulem_skip_bool { \cs_set_eq:NN \@@_ulem_putbox: \UL@putbox \cs_set_eq:NN \@@_ulem_hskip_aux:n \xeCJK_ulem_hskip:n } { \xeCJK_swap_cs:NN \@@_punct_hskip:n \@@_ulem_punct_hskip:n \xeCJK_cs_clear:N \@@_ulem_skip_punct_begin: \xeCJK_cs_clear:N \@@_ulem_skip_punct_end: } \xeCJK_glue_to_skip:nN { \cs_set_eq:NN \ \tex_space:D \cs_set_eq:NN \penalty \tex_penalty:D \cs_set_eq:NN \hskip \skip_horizontal:N \CJKglue } \l_@@_ccglue_skip \xeCJK_glue_to_skip:nN { \cs_set_eq:NN \ \tex_space:D \cs_set_eq:NN \penalty \tex_penalty:D \cs_set_eq:NN \hskip \skip_horizontal:N \CJKecglue } \l_@@_ecglue_skip \xeCJK_glue_to_skip:nN { \xeCJK_space_glue: } \l_@@_space_skip \cs_set_protected:Npn \CJKglue { \@@_ulem_glue:n \l_@@_ccglue_skip } \cs_set_protected:Npn \CJKecglue { \@@_ulem_glue:n \l_@@_ecglue_skip } \cs_set_protected:Npn \xeCJK_space_glue: { \@@_ulem_glue:n \l_@@_space_skip } \cs_set_eq:NN \xeCJK_punct_node:N \use_none:n \cs_set_eq:NN \xeCJK_if_last_punct:TF \use_ii:nn \keys_set:nn { xeCJK / options } { CheckFullRight = false , xCJKecglue = false } } \skip_new:N \l_@@_space_skip \bool_new:N \l_@@_ulem_hook_used_bool % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\UL@word,\xeCJK_ulem_word:nw} % 修改 \tn{UL@word},目的是取得分组中的 \tn{UL@leadtype},以便加入 \cs{xeCJK_ulem_right_skip:}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_ulem_word:nw #1 ~ { \@@_ulem_start:w #1 ~ \exp_after:wN \if_meaning:w \exp_after:wN \UL@end #1 \exp_after:wN \@@_ulem_end: \else: \exp_after:wN \@@_ulem_loop:nw \fi: } \cs_new_protected:Npn \@@_ulem_end: { \c_group_end_token \c_group_end_token \tex_unskip:D \tex_unskip:D \tex_unskip:D \xeCJK_ulem_right_skip: \xeCJK_ulem_group_end: \xeCJK_ulem_right_node: \int_set:Nn \tex_spacefactor:D { \UL@spfactor } } \cs_new_protected:Npn \@@_ulem_loop:nw { \reverse_if:N \if_mode_math: \reverse_if:N \if_dim:w \tex_lastskip:D = \c_zero_dim \skip_gset_eq:NN \UL@skip \tex_lastskip:D \tex_unskip:D \UL@stop \UL@leaders \fi: \fi: \xeCJK_ulem_word:nw \prg_do_nothing: } \cs_new_protected:Npn \@@_ulem_start:w { \exp_after:wN \UL@start } \cs_set_eq:NN \UL@word \xeCJK_ulem_word:nw % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_ulem_left:, \xeCJK_ulem_detect_node:} % 在下划线开始之前探测之前的 \texttt{node},以便随后插入 \tn{CJKglue} 或 \tn{CJKecglue}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_ulem_left: { \xeCJK_ulem_left_node: \xeCJK_make_group_tag: } \cs_new_eq:NN \xeCJK_ulem_left_node: \prg_do_nothing: \cs_new_protected:Npn \xeCJK_ulem_detect_node: { \scan_stop: \dim_compare:nNnTF \tex_lastkern:D = \c_zero_dim { \xeCJK_cs_clear:N \xeCJK_ulem_left_node: \xeCJK_cs_clear:N \xeCJK_ulem_begin_node: \cs_set_eq:NN \@@_ulem_hskip:n \xeCJK_ulem_hskip:n } { \dim_set_eq:NN \l_@@_tmp_dim \tex_lastkern:D \tex_unkern:D \dim_compare:nNnTF \tex_lastkern:D = { - \l_@@_tmp_dim } { \tex_unkern:D \cs_set_protected:Npx \xeCJK_ulem_left_node: { \tex_kern:D - \dim_use:N \l_@@_tmp_dim \exp_stop_f: \tex_kern:D \dim_use:N \l_@@_tmp_dim \exp_stop_f: } \cs_set_protected:Npn \xeCJK_ulem_begin_node: { { \xeCJK_make_node:n { ulem-begin } } } \cs_set_eq:NN \@@_ulem_hskip:n \@@_ulem_hskip_first:n } { \tex_kern:D \l_@@_tmp_dim \xeCJK_cs_clear:N \xeCJK_ulem_left_node: \xeCJK_cs_clear:N \xeCJK_ulem_begin_node: \cs_set_eq:NN \@@_ulem_hskip:n \xeCJK_ulem_hskip:n } } } \xeCJK_declare_node:n { ulem-begin } \cs_new_eq:NN \xeCJK_ulem_begin_node: \prg_do_nothing: % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_hskip_first:n, \xeCJK_ulem_hskip:n} % 如果第一次调用的 \tn{CJKglue} 或 \tn{CJKecglue} 由下划线中的第一个文字和之前的 % 内容产生,就不用画下划线。 % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_hskip_first:n #1 { \xeCJK_if_last_node:nTF { ulem-begin } { \xeCJK_remove_node: \skip_horizontal:n {#1} } { \xeCJK_ulem_hskip:n {#1} } \cs_set_eq:NN \@@_ulem_hskip:n \xeCJK_ulem_hskip:n } \cs_new_eq:NN \@@_ulem_hskip:n \@@_ulem_hskip_first:n \cs_new_protected:Npn \xeCJK_ulem_hskip:n #1 { { \skip_set:Nn \UL@skip {#1} \UL@leaders } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_ulem_right:, \xeCJK_ulem_right_node:} % 在下划线最后的位置保存 \texttt{node}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_ulem_right: { \scan_stop: \dim_compare:nNnTF \tex_lastkern:D = \c_zero_dim { \xeCJK_cs_gclear:N \xeCJK_ulem_right_node: } { \dim_compare:nNnTF \tex_lastkern:D = { 3sp } { \xeCJK_cs_gclear:N \xeCJK_ulem_right_node: } { \exp_args:NNo \tex_unkern:D \@@_ulem_right_aux:n { \dim_use:N \tex_lastkern:D } } } } \cs_new_protected:Npn \@@_ulem_right_aux:n #1 { \dim_compare:nNnTF \tex_lastkern:D = { - #1 } { \tex_unkern:D \cs_gset_protected:Npn \xeCJK_ulem_right_node: { \tex_kern:D - #1 \exp_stop_f: \tex_kern:D #1 \exp_stop_f: } \tl_gset:Nx \UL@spfactor { \int_use:N \tex_spacefactor:D } } { \tex_kern:D #1 \exp_stop_f: \xeCJK_cs_gclear:N \xeCJK_ulem_right_node: } } \cs_new_eq:NN \xeCJK_ulem_right_node: \prg_do_nothing: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_ulem_var_leaders:} % 第一次画下划线时,不需要向左平移 \tn{UL@pixel},让左侧有间距。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_ulem_leaders: { \@@_ulem_var_leaders: } \cs_new_protected:Npn \xeCJK_ulem_var_leaders: { \scan_stop: \skip_if_eq:nnF { \UL@skip } { \c_zero_skip } { \UL@leadtype \skip_horizontal:n { \UL@skip + \UL@pixel } \skip_horizontal:n { - \UL@pixel } \cs_gset_eq:NN \@@_ulem_var_leaders: \xeCJK_ulem_leaders: } } \cs_new_eq:NN \@@_ulem_var_leaders: \xeCJK_ulem_var_leaders: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_ulem_right_skip:} % 在下划线完全画好之后,我们检测最后的情况。用 \tn{unskip} 去掉最后一个下划线,再 % 重新画一个减少 \tn{UL@pixel} 的。 % \begin{macrocode} \cs_new_eq:NN \xeCJK_ulem_right_skip: \prg_do_nothing: \cs_new_protected:Npn \@@_ulem_right_skip: { \int_case:nn { \tex_lastnodetype:D } { { \c_@@_hlist_node } { \@@_ulem_right_skip_hbox: } { \c_@@_glue_node } { \@@_ulem_right_skip_glue: } { \c_@@_penalty_node } { \@@_ulem_right_skip_penalty: } } } \cs_new_protected:Npn \@@_ulem_right_skip_hbox: { \box_set_to_last:N \l_@@_tmp_box \@@_if_last_kern:TF { \@@_ulem_right_skip_kern: } { \@@_ulem_right_skip_glue: } \box_use_drop:N \l_@@_tmp_box } \cs_new_protected:Npn \@@_ulem_right_skip_kern: { \dim_set:Nn \l_@@_tmp_dim { - \box_wd:N \l_@@_tmp_box } \dim_compare:nNnT \tex_lastkern:D = \l_@@_tmp_dim { \tex_unkern:D \@@_ulem_right_skip_glue: \tex_kern:D \l_@@_tmp_dim } } \cs_new_protected:Npn \@@_ulem_right_skip_glue: { \skip_if_eq:nnT { \tex_lastskip:D } { - \UL@pixel } { \tex_unskip:D \skip_set:Nn \l_@@_tmp_skip { \tex_lastskip:D - \UL@pixel } \tex_unskip:D \UL@leadtype \skip_horizontal:N \l_@@_tmp_skip } } \cs_new_protected:Npn \@@_ulem_right_skip_penalty: { \int_set_eq:NN \l_@@_tmp_int \tex_lastpenalty:D \tex_unpenalty:D \@@_if_last_hlist:T { \@@_ulem_right_skip_hbox: } \tex_penalty:D \l_@@_tmp_int } % \end{macrocode} % \end{macro} % % \changes{v3.8.3}{2020/04/23}{\opt{hidden} 选项保留原内容的高度和深度。} % % \begin{macro}{\@@_ulem_hidden_box:} % 只画线,不输出盒子。 % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_hidden_box: { \tl_if_empty:NF \UL@start { \box_set_ht:Nn \l_@@_hidden_box { \box_ht:N \UL@box } \box_set_dp:Nn \l_@@_hidden_box { \box_dp:N \UL@box } \box_use:N \l_@@_hidden_box \xeCJK_no_break: \xeCJK_ulem_hskip:n { \box_wd:N \UL@box } \box_use:N \l_@@_hidden_box } } \box_new:N \l_@@_hidden_box \hbox_set:Nn \l_@@_hidden_box { } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_skip_punct_begin:,\@@_ulem_skip_punct_end:} % 让下划线跳过标点符号的设置。 % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_skip_punct_begin: { \cs_set_eq:NN \UL@putbox \@@_ulem_skip_putbox: \cs_set_eq:NN \xeCJK_ulem_hskip:n \skip_horizontal:n } \cs_new_protected:Npn \@@_ulem_skip_punct_end: { \cs_set_eq:NN \UL@putbox \@@_ulem_putbox: \cs_set_eq:NN \xeCJK_ulem_hskip:n \@@_ulem_hskip_aux:n } \cs_new_eq:NN \@@_ulem_putbox: \UL@putbox \cs_new_protected:Npn \@@_ulem_skip_putbox: { \tl_if_empty:NF \UL@start { \box_use_drop:N \UL@box } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_initial:} % 这里的设置是为了在下划线状态下,下划线可以自动跳过全角标点符号和正确的在它们 % 前/后断行,并且与行首行末对齐。 % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_initial: { \@@_ulem_swap_cs:NN \xeCJK_FullLeft_and_Default: \@@_ulem_FullLeft_and_Default: \xeCJK_FullLeft_and_CJK: \@@_ulem_FullLeft_and_CJK: \xeCJK_FullLeft_and_Boundary: \@@_ulem_FullLeft_and_Boundary: \xeCJK_FullRight_and_Default: \@@_ulem_FullRight_and_Default: \xeCJK_FullRight_and_CJK: \@@_ulem_FullRight_and_CJK: \xeCJK_FullRight_and_Boundary: \@@_ulem_FullRight_and_Boundary: \xeCJK_CJK_and_CJK:N \@@_ulem_CJK_and_CJK:N \xeCJK_CJK_and_Boundary:w \@@_ulem_CJK_and_Boundary:w \xeCJK@fix@penalty \@@_ulem_fix_penalty: \@@_punct_breakable_kern:n \@@_ulem_punct_breakable_kern:n \@@_Default_and_FullLeft_glue:N \@@_ulem_Default_and_FullLeft_glue:N \@@_Default_and_FullRight_glue:N \@@_ulem_Default_and_FullRight_glue:N \@@_CJK_and_FullLeft_glue:N \@@_ulem_CJK_and_FullLeft_glue:N \@@_CJK_and_FullRight_glue:N \@@_ulem_CJK_and_FullRight_glue:N \@@_Boundary_and_FullLeft_glue:N \@@_ulem_Boundary_and_FullLeft_glue:N \q_recursion_tail \q_nil \q_recursion_stop \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { \str_if_eq:nnTF {##1} {####1} { \xeCJK_inter_class_toks:nnn { CJK } { CJK/##1 } { \@@_ulem_between_CJK_blocks:nnN { CJK } {##1} } \xeCJK_inter_class_toks:nnn { CJK/##1 } { CJK/##1 } { \@@_ulem_between_CJK_blocks:nnN { CJK } {##1} } } { \xeCJK_inter_class_toks:nnn { CJK/##1 } { CJK/####1 } { \@@_ulem_between_CJK_blocks:nnN {##1} {####1} } } } } } \cs_new_protected:Npn \@@_ulem_swap_cs:NN #1#2 { \quark_if_recursion_tail_stop:N #1 \xeCJK_swap_cs:NN #1#2 \@@_ulem_swap_cs:NN } % \end{macrocode} % \end{macro} % % \changes{v3.1.2}{2012/12/27}{解决在下划线状态下使用 \tn{makebox} 时的错误。} % % \begin{macro}[int]{\xeCJK_if_ulem_patch:TF} % 在下划线状态下,\pkg{ulem} 宏包在数学模式或者盒子中使用 \tn{UL@hrest} 恢复 % \verb*|\ | 等的定义,此时不需要使用 \tn{UL@stop} 和 \tn{UL@start} 来断开下划线而 % 产生断点。 % \begin{macrocode} \cs_new:Npn \xeCJK_if_ulem_patch:TF { \if_meaning:w \ \LA@space \exp_after:wN \use_ii:nn \else: \exp_after:wN \use_i:nn \fi: } % \end{macrocode} % \end{macro} % % \changes{v3.9.1}{2022/07/28}{修复下划线中数学公式的错误处理。} % % \begin{macro}{\@@_ulem_CJK_and_Boundary:w} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_CJK_and_Boundary:w { \xeCJK_if_ulem_patch:TF { \xeCJK_peek_catcode_ignore_spaces:NTF \c_math_toggle_token { \xeCJK_class_group_end: \CJKecglue } { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \@@_ulem_peek_math:w } { \@@_ulem_group_end:n { CJK } } } } { \@@_ulem_CJK_and_Boundary:w } } \cs_new_protected:Npn \@@_ulem_group_end:n #1 { \xeCJK_class_group_end: \UL@stop \UL@start { \xeCJK_make_node:n {#1} } \xeCJK_make_group_tag: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_peek_math:w} % 用于处理下划线中,汉字与 |$| 之间有空格的情况^^A % \footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/614}}。 % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_peek_math:w { \cs_set_eq:NN \@@_ulem_start:w \@@_ulem_exp_stop:w \exp_after:wN \peek_after:Nw \exp_after:wN \@@_ulem_peek_math_branches:w \exp:w \exp_end_continue_f:w } \cs_new_protected:Npn \@@_ulem_peek_math_branches:w { \token_if_math_toggle:NTF \l_peek_token { \xeCJK_class_group_end: \CJKecglue } { \@@_ulem_group_end:n { CJK-space } } } \cs_new_protected:Npn \@@_ulem_exp_stop:w { \cs_if_eq:NNTF \UL@start \@empty { \exp_after:wN \exp_stop_f: } { \exp_after:wN \UL@start } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_fix_penalty:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_fix_penalty: { \xeCJK_if_ulem_patch:TF { \fix@penalty } { \@@_ulem_fix_penalty: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_CJK_and_CJK:N} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_CJK_and_CJK:N { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \UL@stop \@@_ulem_ccglue: \UL@start \@@_ulem_class_group_begin: \xeCJK_select_font: \xeCJK_fallback_symbol:NN \CJKsymbol } { \@@_ulem_CJK_and_CJK:N } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_class_group_begin:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_class_group_begin: { \xeCJK_class_group_begin: \xeCJK_clear_Boundary_and_CJK_toks: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_between_CJK_blocks:nnN} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_between_CJK_blocks:nnN #1#2 { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \UL@stop \@@_ulem_ccglue: \UL@start \xeCJK_class_group_begin: \xeCJK_clear_Boundary_and_CJK_toks: \@@_switch_font:nn {#1} {#2} \xeCJK_fallback_symbol:NN \CJKsymbol } { \skip_horizontal:N \l_@@_ccglue_skip \@@_switch_font:nn {#1} {#2} \xeCJK_fallback_symbol:NN \CJKsymbol } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_Default_and_FullLeft_glue:N} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_Default_and_FullLeft_glue:N #1 { \xeCJK_if_ulem_patch:TF { \UL@stop \@@_ulem_skip_punct_begin: \@@_punct_glue:NN \c_@@_left_tl #1 \UL@start } { \@@_ulem_Default_and_FullLeft_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_Boundary_and_FullLeft_glue:N} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_Boundary_and_FullLeft_glue:N #1 { \xeCJK_if_ulem_patch:TF { \UL@stop \@@_ulem_skip_punct_begin: \@@_punct_glue:NN \c_@@_left_tl #1 \UL@start } { \@@_ulem_Boundary_and_FullLeft_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_CJK_and_FullLeft_glue:N} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_CJK_and_FullLeft_glue:N #1 { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \UL@stop \@@_ulem_skip_punct_begin: \@@_ulem_punct_ccglue: \@@_punct_glue:NN \c_@@_left_tl #1 \UL@start \@@_ulem_class_group_begin: \xeCJK_select_punct_font: } { \@@_ulem_CJK_and_FullLeft_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_Default_and_FullRight_glue:N} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_Default_and_FullRight_glue:N #1 { \xeCJK_if_ulem_patch:TF { \UL@stop \@@_ulem_skip_punct_begin: \@@_punct_if_long:NTF #1 { \xeCJK_allow_break: } { \xeCJK_no_break: } \@@_punct_if_middle:NT #1 { \@@_punct_glue:NN \c_@@_right_tl #1 \@@_punct_rule:NN \c_@@_left_tl #1 } \UL@start } { \@@_ulem_Default_and_FullRight_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_CJK_and_FullRight_glue:N} % \changes{v3.2.2}{2013/05/30}{修正下划线不能跳过全角右标点的问题。} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_CJK_and_FullRight_glue:N #1 { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \UL@stop \@@_ulem_skip_punct_begin: \@@_punct_if_long:NTF #1 { \xeCJK_allow_break: } { \xeCJK_no_break: } \@@_punct_if_middle:NT #1 { \@@_ulem_punct_ccglue: \@@_punct_glue:NN \c_@@_right_tl #1 \@@_punct_rule:NN \c_@@_left_tl #1 } \UL@start \@@_ulem_class_group_begin: \xeCJK_select_punct_font: } { \@@_ulem_CJK_and_FullRight_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_FullLeft_and_Default:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_FullLeft_and_Default: { \xeCJK_if_ulem_patch:TF { \@@_punct_if_middle:NTF \g_@@_last_punct_tl { \xeCJK_get_punct_bounds:No \c_@@_left_tl \g_@@_last_punct_tl \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \UL@stop \xeCJK_no_break: \@@_punct_glue:NN \c_@@_left_tl \g_@@_last_punct_tl } { \xeCJK_class_group_end: \UL@stop } \@@_ulem_skip_punct_end: \xeCJK_no_break: \UL@start } { \@@_ulem_FullLeft_and_Default: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_FullLeft_and_Boundary:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_FullLeft_and_Boundary: { \xeCJK_if_ulem_patch:TF { \@@_punct_if_middle:NTF \g_@@_last_punct_tl { \xeCJK_get_punct_bounds:No \c_@@_left_tl \g_@@_last_punct_tl \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \UL@stop \xeCJK_no_break: \@@_punct_glue:NN \c_@@_left_tl \g_@@_last_punct_tl } { \xeCJK_class_group_end: \UL@stop } \@@_ulem_skip_punct_end: \xeCJK_no_break: \UL@start \tex_ignorespaces:D } { \@@_ulem_FullLeft_and_Boundary: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_FullLeft_and_CJK:} % \changes{v3.2.3}{2013/06/04} % {修正全角左标点后下划线与 \tn{CJKunderdot} 连用时结果不正常的问题。} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_FullLeft_and_CJK: { \xeCJK_if_ulem_patch:TF { \xeCJK_FullLeft_and_Default: \@@_ulem_class_group_begin: \xeCJK_select_font: } { \@@_ulem_FullLeft_and_CJK: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_FullRight_and_Default:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_FullRight_and_Default: { \xeCJK_if_ulem_patch:TF { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \UL@stop \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl \@@_ulem_skip_punct_end: \UL@start } { \@@_ulem_FullRight_and_Default: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_FullRight_and_Boundary:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_FullRight_and_Boundary: { \xeCJK_if_ulem_patch:TF { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \UL@stop \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl \@@_ulem_skip_punct_end: \UL@start \tex_ignorespaces:D } { \@@_ulem_FullRight_and_Boundary: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_FullRight_and_CJK:} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_FullRight_and_CJK: { \xeCJK_if_ulem_patch:TF { \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: \UL@stop \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl \@@_ulem_punct_ccglue: \@@_ulem_skip_punct_end: \UL@start \@@_ulem_class_group_begin: \xeCJK_select_font: } { \@@_ulem_FullRight_and_CJK: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_punct_hskip:n} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_punct_hskip:n { \xeCJK_if_ulem_patch:TF { \xeCJK_ulem_hskip:n } { \@@_ulem_punct_hskip:n } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_punct_breakable_kern:n} % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_punct_breakable_kern:n #1 { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \UL@stop \xeCJK_ulem_hskip:n {#1} \UL@start \@@_ulem_class_group_begin: \xeCJK_select_punct_font: } { \@@_ulem_punct_breakable_kern:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ulem_glue:n,\@@_ulem_ccglue:,\@@_ulem_punct_ccglue:} % 在下划线状态下的分别代替 \tn{CJKglue} 等。 % \begin{macrocode} \cs_new_protected:Npn \@@_ulem_glue:n #1 { \xeCJK_if_ulem_patch:TF { \tl_if_empty:NTF \l_@@_group_tag_tl { \UL@stop \@@_ulem_hskip:n {#1} \UL@start } { \str_if_eq:eeTF { \l_@@_group_tag_tl } { \c_@@_group_tag_tl } { \UL@stop \@@_ulem_hskip:n {#1} \UL@start } { \skip_horizontal:n {#1} } } } { \skip_horizontal:n {#1} } } \cs_new_protected:Npn \xeCJK_make_group_tag: { \tl_set:Nx \l_@@_group_tag_tl { \c_@@_group_tag_tl } } \tl_new:N \l_@@_group_tag_tl \tl_const:Nn \c_@@_group_tag_tl { T \int_use:N \tex_currentgrouptype:D L \int_use:N \tex_currentgrouplevel:D } \cs_new_protected:Npn \@@_ulem_ccglue: { { \skip_set_eq:NN \UL@skip \l_@@_ccglue_skip \UL@leaders } } \cs_new_protected:Npn \@@_ulem_punct_ccglue: { \@@_punct_hskip:n { \l_@@_ccglue_skip } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_ulem_group_begin:,\xeCJK_ulem_group_end:,\xeCJK_ulem_on:n} % \begin{macrocode} \cs_new_protected:Npn \xeCJK_ulem_group_begin: { \mode_leave_vertical: \c_group_begin_token } \cs_new_protected:Npn \xeCJK_ulem_group_end: { \c_group_end_token } \cs_new_protected:Npn \xeCJK_ulem_on:n { \ULon } \cs_new_eq:NN \@@_ulem_on:n \UL@on \cs_set_protected:Npn \UL@on #1 { \@@_ulem_on:n { \xeCJK_ulem_left: #1 \xeCJK_ulem_right: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKfntefon} % \changes{v3.2.15}{2014/11/07}{完善选项。} % 扩展 \tn{ULon} 的参数。 % \begin{macrocode} \NewDocumentCommand \xeCJKfntefon { s t- s o } { \mode_leave_vertical: \xeCJK_ulem_boot:NNNn #1#2#3 {#4} \xeCJK_ulem_on:n } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKunderline} % \begin{macrocode} \NewDocumentCommand \CJKunderline { s t- s o } { \xeCJK_ulem_group_begin: \xeCJK_fntef_boot:nnNNNn { underline } { uline } #1#2#3 {#4} \xeCJK_fntef_initial:nnn { \l_@@_uline_depth_tl } { \l_@@_uline_sep_tl } { \l_@@_uline_format_tl \tex_vrule:D height \dim_eval:n { \l_@@_uline_thickness_tl } depth \c_zero_dim width .2em } \xeCJK_ulem_on:n } \NewDocumentCommand \varCJKunderline { } { \CJKunderline - } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKunderwave} % \begin{macrocode} \NewDocumentCommand \CJKunderwave { s t- s o } { \xeCJK_ulem_group_begin: \xeCJK_fntef_boot:nnNNNn { underwave } { uwave } #1#2#3 {#4} \xeCJK_fntef_initial:nnn { \l_@@_uwave_depth_tl } { \l_@@_uwave_sep_tl } { \l_@@_uwave_format_tl \l_@@_uwave_symbol_tl } \xeCJK_ulem_on:n } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKunderdblline} % \begin{macrocode} \NewDocumentCommand \CJKunderdblline { s t- s o } { \xeCJK_ulem_group_begin: \xeCJK_fntef_boot:nnNNNn { underdblline } { udbline } #1#2#3 {#4} \xeCJK_fntef_initial:nnn { \l_@@_udbline_depth_tl } { \l_@@_udbline_sep_tl } { \l_@@_udbline_format_tl \vbox_top:n { \tex_hrule:D height \dim_eval:n { \l_@@_udbline_thickness_tl } depth \c_zero_dim width .2em \tex_kern:D \dim_eval:n { \l_@@_udbline_gap_tl } \tex_hrule:D height \dim_eval:n { \l_@@_udbline_thickness_tl } depth \c_zero_dim width .2em } } \xeCJK_ulem_on:n } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKsout} % \begin{macrocode} \NewDocumentCommand \CJKsout { s t- s o } { \xeCJK_ulem_group_begin: \xeCJK_fntef_boot:nnNNNn { sout } { sout } #1#2#3 {#4} \xeCJK_fntef_initial:nn { \l_@@_sout_format_tl \tex_vrule:D height \dim_eval:n { \l_@@_sout_thickness_tl } depth \c_zero_dim width .2em } { \box_move_up:nn { \l_@@_sout_height_tl - \box_ht:N \l_@@_fntef_box / 2 } { \box_use:N \l_@@_fntef_box } } \xeCJK_ulem_on:n } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKxout} % \begin{macrocode} \NewDocumentCommand \CJKxout { s t- s o } { \xeCJK_ulem_group_begin: \xeCJK_fntef_boot:nnNNNn { xout } { xout } #1#2#3 {#4} \xeCJK_fntef_initial:nn { \l_@@_xout_format_tl \tex_kern:D -.1 em $/$ \tex_kern:D -.1 em } { \box_move_up:nn { \box_dp:N \l_@@_fntef_box / 2 } { \box_use:N \l_@@_fntef_box } } \xeCJK_ulem_on:n } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKunderanyline} % \changes{v3.2.15}{2014/11/07}{完善选项。} % \begin{macrocode} \NewDocumentCommand \CJKunderanyline { s t- s o m m } { \xeCJK_ulem_group_begin: \xeCJK_ulem_boot:NNNn #1#2#3 {#4} \xeCJK_fntef_initial:nn {#6} { \box_move_down:nn {#5} { \box_use:N \l_@@_fntef_box } } \tl_if_empty:NF \l_@@_ulem_boxdepth_tl { \box_set_dp:Nn \ULC@box { \l_@@_ulem_boxdepth_tl } } \tl_if_empty:NF \l_@@_ulem_sep_tl { \bool_set_true:N \l_@@_fntef_bool \dim_set:Nn \l_@@_fntef_dim { \l_@@_ulem_sep_tl + \box_dp:N \ULC@box } } \xeCJK_ulem_on:n } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_fntef_boot:nnNNNn} % 处理参数问题。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_fntef_boot:nnNNNn #1#2#3#4#5#6 { \bool_lazy_or:nnT {#3} {#5} { \bool_set_false:c { l_@@_#2_skip_bool } } \bool_if:NT #4 { \bool_set_true:c { l_@@_#2_subtract_bool } } \tl_if_novalue:nF {#6} { \keys_set:nn { xeCJK / options / #1 } {#6} } \bool_set_eq:Nc \l_@@_ulem_skip_bool { l_@@_#2_skip_bool } \bool_set_eq:Nc \l_@@_ulem_hidden_bool { l_@@_#2_hidden_bool } \bool_set_eq:Nc \l_@@_ulem_subtract_bool { l_@@_#2_subtract_bool } \tl_set_eq:Nc \l_@@_ulem_text_format_tl { l_@@_#2_text_format_tl } } \cs_new_protected:Npn \xeCJK_ulem_boot:NNNn #1#2#3#4 { \bool_lazy_or:nnT {#1} {#3} { \bool_set_false:N \l_@@_ulem_skip_bool } \bool_if:NT #2 { \bool_set_true:N \l_@@_ulem_subtract_bool } \tl_if_novalue:nF {#4} { \keys_set:nn { xeCJK / options / ulem } {#4} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_fntef_initial:n} % 不支持下划线的嵌套使用。下划线嵌套使用时,里层的下划线会被放在盒子里,不能折行。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_fntef_initial:n { \bool_if:NTF \l_@@_nest_bool { \@@_warning:n { fntef-nesting } } { \bool_set_true:N \l_@@_nest_bool \@@_restore_shipout_fntef: } \xeCJK_fntef_sbox:n } \cs_new_protected:Npn \xeCJK_fntef_initial:nn #1 { \xeCJK_fntef_initial:n {#1} \bool_if:NF \l_@@_fntef_bool { \dim_zero:N \l_@@_fntef_dim } \markoverwith } \cs_new_protected:Npn \xeCJK_fntef_initial:nnn #1#2#3 { \xeCJK_fntef_initial:n {#3} \bool_if:NF \l_@@_fntef_bool { \bool_set_true:N \l_@@_fntef_bool \dim_set:Nn \l_@@_fntef_dim {#1} } \markoverwith { \box_move_down:nn { \l_@@_fntef_dim + \box_ht:N \l_@@_fntef_box } { \box_use:N \l_@@_fntef_box } } \dim_set:Nn \l_@@_fntef_dim { #2 + \box_dp:N \ULC@box } } \box_new:N \l_@@_fntef_box \cs_new_eq:NN \xeCJKfntefbox \l_@@_fntef_box \bool_new:N \l_@@_nest_bool \bool_new:N \l_@@_fntef_bool \@@_msg_new:nn { fntef-nesting } { Nesting~is~not~supported. } % \end{macrocode} % \end{macro} % % \begin{variable}{\l_@@_fntef_dim} % 记录下划线或者下划符号的深度,以便它们嵌套使用时能自动调整好距离。 % \tn{ULdepth} 被 \pkg{ulem} 初始化为 \tn{maxdimen}。下划线嵌套时,\pkg{ulem} % 要使用它作计算,可能会溢出。为简便起见,\cs{l_@@_fntef_dim} 与 \tn{ULdepth} % 共用一个寄存器。 % \begin{macrocode} \cs_new_eq:NN \l_@@_fntef_dim \ULdepth % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\xeCJK_fntef_sbox:n} % 与 \cs{hcoffin_set:Nn} 和 \LaTeXe{} 的 \tn{sbox} 功能类似,确保颜色的正确。 % 虽然 \texttt{coffin} 可以更方便的操作盒子,但速度要慢一点。并且,我们的需求 % 也比较简单,就不用它了。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_fntef_sbox:n #1 { \hbox_set:Nn \l_@@_fntef_box { \color_ensure_current: #1 } } % \end{macrocode} % \end{macro} % % 最合适的是用 \pkg{xtemplate} 宏包来实现,但是比较难于用 \tn{xeCJKsetup} 来统一 % 设置,所以这里还是用土办法。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { underdot / symbol .tl_set:N = \l_@@_udot_symbol_tl , underdot / depth .tl_set:N = \l_@@_udot_depth_tl , underdot / sep .tl_set:N = \l_@@_udot_sep_tl , underdot / format .tl_set:N = \l_@@_udot_format_tl , underdot / textformat .tl_set:N = \l_@@_udot_text_format_tl , underdot / boxdepth .tl_set:N = \l_@@_udot_boxdepth_tl , symbol / sep .tl_set:N = \l_@@_symbol_sep_tl , symbol / boxdepth .tl_set:N = \l_@@_symbol_boxdepth_tl , symbol / textformat .tl_set:N = \l_@@_symbol_text_format_tl , underline / skip .bool_set:N = \l_@@_uline_skip_bool , underline / hidden .bool_set:N = \l_@@_uline_hidden_bool , underline / subtract .bool_set:N = \l_@@_uline_subtract_bool , underline / thickness .tl_set:N = \l_@@_uline_thickness_tl , underline / depth .tl_set:N = \l_@@_uline_depth_tl , underline / sep .tl_set:N = \l_@@_uline_sep_tl , underline / format .tl_set:N = \l_@@_uline_format_tl , underline / textformat .tl_set:N = \l_@@_uline_text_format_tl , underdblline / skip .bool_set:N = \l_@@_udbline_skip_bool , underdblline / hidden .bool_set:N = \l_@@_udbline_hidden_bool , underdblline / subtract .bool_set:N = \l_@@_udbline_subtract_bool , underdblline / thickness .tl_set:N = \l_@@_udbline_thickness_tl , underdblline / depth .tl_set:N = \l_@@_udbline_depth_tl , underdblline / sep .tl_set:N = \l_@@_udbline_sep_tl , underdblline / format .tl_set:N = \l_@@_udbline_format_tl , underdblline / textformat .tl_set:N = \l_@@_udbline_text_format_tl , underdblline / gap .tl_set:N = \l_@@_udbline_gap_tl , underwave / skip .bool_set:N = \l_@@_uwave_skip_bool , underwave / hidden .bool_set:N = \l_@@_uwave_hidden_bool , underwave / subtract .bool_set:N = \l_@@_uwave_subtract_bool , underwave / symbol .tl_set:N = \l_@@_uwave_symbol_tl , underwave / depth .tl_set:N = \l_@@_uwave_depth_tl , underwave / sep .tl_set:N = \l_@@_uwave_sep_tl , underwave / format .tl_set:N = \l_@@_uwave_format_tl , underwave / textformat .tl_set:N = \l_@@_uwave_text_format_tl , sout / skip .bool_set:N = \l_@@_sout_skip_bool , sout / hidden .bool_set:N = \l_@@_sout_hidden_bool , sout / subtract .bool_set:N = \l_@@_sout_subtract_bool , sout / thickness .tl_set:N = \l_@@_sout_thickness_tl , sout / height .tl_set:N = \l_@@_sout_height_tl , sout / format .tl_set:N = \l_@@_sout_format_tl , sout / textformat .tl_set:N = \l_@@_sout_text_format_tl , xout / skip .bool_set:N = \l_@@_xout_skip_bool , xout / hidden .bool_set:N = \l_@@_xout_hidden_bool , xout / subtract .bool_set:N = \l_@@_xout_subtract_bool , xout / format .tl_set:N = \l_@@_xout_format_tl , xout / textformat .tl_set:N = \l_@@_xout_text_format_tl , ulem / skip .bool_set:N = \l_@@_ulem_skip_bool , ulem / hidden .bool_set:N = \l_@@_ulem_hidden_bool , ulem / subtract .bool_set:N = \l_@@_ulem_subtract_bool , ulem / sep .tl_set:N = \l_@@_ulem_sep_tl , ulem / boxdepth .tl_set:N = \l_@@_ulem_boxdepth_tl , ulem / textformat .tl_set:N = \l_@@_ulem_text_format_tl } \clist_map_inline:nn { underdot , underline , underdblline , underwave , sout , xout , ulem } { \keys_define:nn { xeCJK / options } { #1 .meta:nn = { xeCJK / options / #1 } { ##1 } } } \keys_set:nn { xeCJK / options } { underdot / symbol = \normalfont . , underdot / depth = 0.20 em , underdot / sep = 0.04 em , symbol / sep = \c_zero_dim , underline / skip = true , underline / thickness = \ULthickness , underline / depth = 0.20 em , underline / sep = 0.07 em , underdblline / skip = true , underdblline / thickness = \ULthickness , underdblline / depth = 0.20 em , underdblline / sep = 0.17 em , underdblline / gap = 1.1 pt , underwave / skip = true , underwave / symbol = \sixly \tex_char:D 58 \exp_stop_f: , underwave / depth = 0.20 em , underwave / sep = 0.00 em , sout / skip = true , sout / thickness = \ULthickness , sout / height = 0.35 em , xout / skip = true } % \end{macrocode} % % \changes{v3.8.3}{2020/04/07}{取消 \pkg{xeCJKfntef} 的初始彩色设置。} % % \begin{macro}{\CJKunderanysymbol} % \begin{macrocode} \NewDocumentCommand \CJKunderanysymbol { o m m m } { \xeCJK_under_symbol:nnnnnn { symbol } { symbol } {#1} {#2} {#3} {#4} \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKunderdot} % \tn{CJKunderdot} 是 \tn{CJKunderanysymbol} 的特殊情况。\pkg{CJKfntef} 原来使用 % 的是数学符号 \tn{cdot},这里改成更合适的 |.|。 % \begin{macrocode} \NewDocumentCommand \CJKunderdot { o m } { \xeCJK_under_symbol:nnnnnn { underdot } { udot } {#1} { \l_@@_udot_depth_tl } { \l_@@_udot_format_tl \l_@@_udot_symbol_tl } {#2} \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_under_symbol:nnnnnn} % 当处在下划线中时,我们先断开下划线,在分组外设置下划符号。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_under_symbol:nnnnnn { \xeCJK_if_ulem_patch:TF { \@@_under_symbol_auxi:nnnnnn } { \@@_under_symbol_auxii:nnnnnn } } \cs_new_protected:Npn \@@_under_symbol_auxi:nnnnnn #1#2#3#4#5#6 { \xeCJK_ulem_right: \UL@stop \group_begin: \xeCJK_under_symbol_initial:nnnnn {#1} {#2} {#3} {#4} {#5} \use:c { l_@@_#2_text_format_tl } \UL@start \xeCJK_ulem_right_node: #6 \xeCJK_ulem_right: \UL@stop \group_end: \UL@start \xeCJK_ulem_right_node: } \cs_new_protected:Npn \@@_under_symbol_auxii:nnnnnn #1#2#3#4#5#6 { \mode_leave_vertical: \group_begin: \xeCJK_under_symbol_initial:nnnnn {#1} {#2} {#3} {#4} {#5} \@@_under_symbol_text_format:c { l_@@_#2_text_format_tl } #6 \xeCJK_ulem_right: \group_end: \xeCJK_ulem_right_node: } \cs_new_protected:Npn \xeCJK_under_symbol_initial:nnnnn #1#2#3#4#5 { \tl_if_novalue:nF {#3} { \keys_set:nn { xeCJK / options / #1 } {#3} } \xeCJK_fntef_sbox:n {#5} \bool_if:NTF \l_@@_fntef_bool { \xeCJK_make_under_symbol:n { \l_@@_fntef_dim } } { \bool_set_true:N \l_@@_fntef_bool \xeCJK_make_under_symbol:n {#4} } \tl_if_empty:cF { l_@@_#2_boxdepth_tl } { \box_set_dp:Nn \l_@@_under_symbol_box { \use:c { l_@@_#2_boxdepth_tl } } } \dim_set:Nn \l_@@_fntef_dim { \use:c { l_@@_#2_sep_tl } + \box_dp:N \l_@@_under_symbol_box } \xeCJK_swap_cs:NN \CJKsymbol \@@_under_CJKsymbol:N \@@_restore_shipout_CJKsymbol: } \cs_new_protected:Npn \@@_under_symbol_text_format:N #1 { \tl_if_empty:NF #1 { \xeCJK_ulem_right: #1 \xeCJK_ulem_right_node: } } \cs_generate_variant:Nn \@@_under_symbol_text_format:N { c } \box_new:N \l_@@_under_symbol_box % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_make_under_symbol:n} % 我们量取“一”的宽度作为汉字的宽度。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_make_under_symbol:n #1 { \hbox_set:Nn \l_@@_under_symbol_box { \box_move_down:nn { #1 + \box_ht:N \l_@@_fntef_box } { \hbox_to_zero:n { \xeCJK_select_font: \tex_kern:D \tex_fontcharwd:D \tex_font:D "4E00 \exp_stop_f: \tex_hss:D \box_use:N \l_@@_fntef_box \tex_hss:D } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_restore_shipout_CJKsymbol:} % \changes{v3.2.3}{2013/06/04}{解决 \tn{CJKunderdot} 跨页使用时影响到页眉页脚的问题。} % \tn{CJKunderdot} 中对 \tn{CJKsymbol} 的修改会影响到页眉和页脚,需要小心处理。 % \begin{macrocode} \cs_new_protected:Npn \@@_restore_shipout_CJKsymbol: { \tl_put_right:Nn \l_@@_fntef_shipout_tl { \xeCJK_swap_cs:NN \CJKsymbol \@@_under_CJKsymbol:N } \@@_restore_shipout_fntef: \xeCJK_cs_clear:N \@@_restore_shipout_CJKsymbol: } \cs_new_protected:Npn \@@_restore_shipout_fntef: { \tl_put_right:Nn \l_@@_fntef_shipout_tl { \bool_set_false:N \l_@@_fntef_bool \dim_zero:N \l_@@_fntef_dim } \xeCJK_cs_clear:N \@@_restore_shipout_fntef: } \tl_new:N \l_@@_fntef_shipout_tl \xeCJK_add_to_shipout:n { \l_@@_fntef_shipout_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_under_CJKsymbol:N} % 盒子放在汉字的左侧,比较容易处理状态转移的问题。 % \begin{macrocode} \cs_new_protected:Npn \@@_under_CJKsymbol:N { \box_use:N \l_@@_under_symbol_box \xeCJK_no_break: \@@_under_CJKsymbol:N } % \end{macrocode} % \end{macro} % % \changes{v3.7.2}{2019/03/24}{改用 \pkg{xparse} 的新参数类型 \texttt{b} % 定义 \env{CJKfilltwosides*} 环境,不再依赖 \pkg{environ} 包。} % % \begin{macro}{CJKfilltwosides} % \changes{v3.2.4}{2013/06/26}{改用 \texttt{minipage} 和 \LaTeX 表格(\texttt{tabular})来实现。} % \changes{v3.3.3}{2015/05/30}{确保进入水平模式。} % 使用 \texttt{minipage} 和 \LaTeX 表格(\texttt{tabular})来定义 |CJKfilltwosides| 环境。 % 可选参数 |#1| 表示环境的垂直对齐位置,默认居中;参数 |#2| 表示环境的宽度。 % 带星号的环境,如果 |#2| 不大于零或者不大于环境最长文本行的宽度,则取环境的自然宽度。 % \begin{macrocode} \NewDocumentEnvironment { CJKfilltwosides } { O { c } m } { \use:e { \exp_not:N \minipage [#1] { \dim_eval:n {#2} } } \cs_set_eq:NN \CJKglue \xeCJK_fntef_hfilll: } { \endminipage \ignorespacesafterend } \NewDocumentEnvironment { CJKfilltwosides* } { O { c } m +b } { \mode_leave_vertical: \cs_set_eq:NN \CJKglue \xeCJK_fntef_hfilll: \tl_set:Nn \arraystretch { 1 } \cs_if_free:NF \extrarowheight { \cs_set_eq:NN \extrarowheight \c_zero_dim } \use:e { \@@_fill_two_sides:nnn {#1} { \dim_eval:n {#2} } } {#3} } { \ignorespacesafterend } \cs_new_protected:Npn \@@_fill_two_sides:nnn #1#2#3 { \dim_compare:nNnTF {#2} > \c_zero_dim { \hbox_set:Nn \l_@@_tmp_box { \tabular [#1] { @ { } c @ { } } #3 \endtabular } \dim_compare:nNnTF {#2} > { \box_wd:N \l_@@_tmp_box } { \tabular [#1] { @ { } p {#2} @ { } } #3 \endtabular } { \box_use:N \l_@@_tmp_box } } { \tabular [#1] { @ { } c @ { } } #3 \endtabular } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xeCJK_fntef_hfilll:} % \pkg{colortbl} 将表格 |c| 列用于填充的 \tn{hfil} 改为了更高阶的 \texttt{fill}, % 影响到了 \env{CJKfilltwosides*}。因此,我们也要用高阶的 \texttt{filll}。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_fntef_hfilll: { \skip_horizontal:N \c_@@_filll_skip } \skip_const:Nn \c_@@_filll_skip { \c_zero_dim plus 1 filll } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-listings}} % % \changes{v3.2.2}{2013/06/04}{增加小宏包 \pkg{xeCJK-listings},用于支持 \pkg{listings} 宏包。} % \changes{v3.2.3}{2013/06/06}{完善对 \pkg{listings} 宏包的支持。} % % 仿照 \package{luatexja} 宏包中 \pkg{lltjp-listings} 的处理,支持 \package{listings} 宏包。 % % \begin{macrocode} %<*listings> % \end{macrocode} % % \begin{macrocode} \DeclareOption* { \PassOptionsToPackage { \CurrentOption } { xeCJK } } \ProcessOptions \scan_stop: % \end{macrocode} % % \begin{macrocode} \RequirePackage { xeCJK } \RequirePackage { listings } % \end{macrocode} % % \begin{macrocode} \lst@AddToHook { Init } { \@@_listings_initial_hook: } \lst@AddToHook { SelectCharTable } { \@@_listings_toks_hook: } \lst@AddToHook { OutputBox } { \tl_set_eq:NN \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl \l_@@_restore_listings_toks_tl \@@_listings_output_CM: } \lst@AddToHook { PreSet } { \bool_set_true:N \l_@@_listings_env_bool } % \end{macrocode} % % \begin{macro}{\@@_listings_initial_hook:} % \changes{v3.2.3}{2013/06/04} % {解决 \texttt{listings} 坏境中代码行号输出不正确的问题,并解决在其中跨页时对页眉 % 和页脚的影响。} % \changes{v3.2.15}{2014/11/10}{修正 \texttt{breaklines} 无效的问题。} % \changes{v3.3.1}{2015/04/20} % {解决 \texttt{prebreak} 和 \texttt{postbreak} 功能失效的问题。} % 为使代码行号结果正确,需要在 \tn{lst@numberstyle} 中恢复 \tn{XeTeXinterchartoks}。 % 在 \texttt{listings} 环境中换页时,对 \tn{XeTeXinterchartoks} 的修改会影响到 % 页眉和页脚,需要在 \tn{shipout} 盒子中恢复成正常定义。加入 \cs{tex_noindent:D} % 是为了进入水平模式,防止汉字出现在首行的时候可能会产生额外空行。 % \tn{lst@prebreak} 和 \tn{lst@postbreak} 是在 \tn{discretionary} 中直接输出的, % 应该恢复正常的 \tn{XeTeXinterchartoks}。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_initial_hook: { \tex_noindent:D \bool_gset_false:N \g_@@_listings_CM_bool \tl_put_left:Nn \lst@numberstyle { \l_@@_restore_listings_toks_tl } \xeCJK_add_to_shipout:n { \l_@@_restore_listings_toks_tl } \lst@ifbreaklines \cs_set_eq:NN \@@_listings_CJK_toks_hook: \@@_listings_breaklines_toks: \tl_if_empty:NF \lst@prebreak { \tl_put_left:Nn \lst@prebreak { \l_@@_restore_listings_toks_tl } } \tl_if_empty:NF \lst@postbreak { \tl_put_left:Nn \lst@postbreak { \l_@@_restore_listings_toks_tl } } \fi: \int_set:Nn \l_@@_listings_max_char_int { \lst@ifec 255 \else: 127 \fi: } } \int_new:N \l_@@_listings_max_char_int % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_toks_hook:} % 采用不同的 \tn{XeTeXinterchartoks} 处理方式,输入的时候是将汉字加入到 \pkg{listings} % 的输出队列,实际输出的时候是普通文字。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_toks_hook: { \tl_clear:N \l_@@_restore_listings_toks_tl \seq_map_function:NN \g_@@_class_seq \@@_backup_inter_class_toks:n \seq_map_inline:Nn \g_@@_non_CJK_class_seq { \str_if_eq:nnF { ##1 } { Boundary } { \xeCJK_inter_class_toks:nnn { Boundary } { ##1 } { \@@_listings_process_Default:nN { ##1 } } } } \xeCJK_inter_class_toks:nnn { Boundary } { CM } { \@@_listings_process_CM:nN { 0 } } \@@_listings_CJK_toks_hook: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_backup_inter_class_toks:n} % 注意,给 \tn{XeTeXinterchartoks} 赋空值,会导致 \XeTeX 崩溃! % \begin{macrocode} \cs_new_protected:Npn \@@_backup_inter_class_toks:n #1 { \tl_set:Nx \l_@@_tmp_tl { \xeCJK_get_inter_class_toks:nn { Boundary } {#1} } \tl_put_right:Nx \l_@@_restore_listings_toks_tl { \xeCJK_inter_class_toks:nnn { Boundary } {#1} { \tl_if_empty:NTF \l_@@_tmp_tl { \exp_not:N \prg_do_nothing: } { \exp_not:o \l_@@_tmp_tl } } } } \tl_new:N \l_@@_restore_listings_toks_tl % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_CJK_toks_hook:,\@@_listings_breaklines_toks:} % 根据 \texttt{breaklines} 选项的使用与否,选择不同的处理方式。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_CJK_toks_hook: { \xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \@@_listings_process_CJK:nN { 2 } } \xeCJK_inter_class_toks:nnn { Boundary } { FullLeft } { \@@_listings_process_CJK:nN { 2 } } \xeCJK_inter_class_toks:nnn { Boundary } { FullRight } { \@@_listings_process_CJK:nN { 2 } } \xeCJK_inter_class_toks:nnn { Boundary } { HangulJamo } { \@@_listings_process_CJK:nN { 2 } } \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { \xeCJK_inter_class_toks:nnn { Boundary } { CJK/##1 } { \@@_listings_process_CJK:nN { 2 } } } } \cs_new_protected:Npn \@@_listings_breaklines_toks: { \xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \@@_listings_process_breaklines_CJK:nN { 2 } } \xeCJK_inter_class_toks:nnn { Boundary } { HangulJamo } { \@@_listings_process_breaklines_CJK:nN { 2 } } \xeCJK_inter_class_toks:nnn { Boundary } { FullLeft } { \@@_listings_process_FullLeft:nN { 2 } } \xeCJK_inter_class_toks:nnn { Boundary } { FullRight } { \@@_listings_process_FullRight:nN { 2 } } \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { \xeCJK_inter_class_toks:nnn { Boundary } { CJK/##1 } { \@@_listings_process_breaklines_CJK:nN { 2 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_process_Default:nN} % \changes{v3.2.3}{2013/06/08}{在 \texttt{listings} 坏境中对 \tn{charcode} 大于 % $255$ 的字符根据其 \tn{catcode} 区分 \texttt{letter} 和 \texttt{other}。} % \changes{v3.3.1}{2015/01/27}{对 \pkg{listings} 的字符扩展不影响到其符号表中的 % 七位或八位字符。} % 对于 \tn{charcode} 大于 $255$ 的字符,根据 \tn{catcode} 进行处理。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_process_Default:nN #1#2 { \int_compare:nNnTF { \xeCJK_token_value_charcode:N #2 } > \l_@@_listings_max_char_int { \token_if_letter:NTF #2 { \lst@ProcessLetter #2 } { \lst@ProcessOther #2 } } { \@@_listings_output_Default:nN {#1} #2 } } % \end{macrocode} % 输出时,要注意把对应的 \tn{XeTeXinterchartoks} 清空掉,否则会造成死循环。 % \cs{scan_stop:} 是造边界,输出 \cs{group_end:}。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_output_Default:nN #1#2 { \group_begin: \xeCJK_clear_inter_class_toks:nn { Boundary } {#1} \xeCJK_inter_class_toks:nnn {#1} { Boundary } { \group_end: } #2 \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_process_CJK:nN} % 对 CJK 字符类的处理。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_process_CJK:nN #1#2 { \token_if_letter:NTF #2 { \@@_listings_process_letter:nN {#1} #2 } { \@@_listings_process_other:nN {#1} #2 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_append:nN} % 普通 CJK 字符的宽度为一般基本宽度的两倍,CM 类不增加宽度。这里有一个问题, % 对 CJK 字符类中的一些半角字符(例如半角日文假名)没有区分开。\pkg{listings} 通过 % 重定义 \tn{lst@Append} 将代码写入外部文件,因此需要保留。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_append:nN #1#2 { \int_add:Nn \lst@length { #1 - 1 } \lst@Append #2 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_process_letter:nN,\@@_listings_process_other:nN} % 在 \texttt{letter} 类中区分汉字和西文字母。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_process_letter:nN { \lst@whitespacefalse \bool_if:NTF \l_@@_listings_letter_bool { \lst@lettertrue } { \lst@ifletter \lst@Output \else: \lst@OutputOther \lst@lettertrue \fi: \bool_set_true:N \l_@@_listings_letter_bool } \@@_listings_append:nN } \bool_new:N \l_@@_listings_letter_bool \cs_new_protected:Npn \@@_listings_process_other:nN #1#2 { \lst@whitespacefalse \bool_if:NTF \l_@@_listings_letter_bool { \lst@Output \lst@letterfalse \bool_set_false:N \l_@@_listings_letter_bool } { \lst@ifletter \lst@Output \lst@letterfalse \fi: } \cs_set_eq:NN \lst@lastother #2 \@@_listings_append:nN {#1} #2 } % \end{macrocode} % \end{macro} % % \changes{v3.2.4}{2013/07/05} % {使 \pkg{listings} 的 \texttt{breaklines} 选项对 CJK 字符类可用,并保持标点符号的禁则。} % % \begin{macro} % {\@@_listings_process_breaklines_CJK:nN, % \@@_listings_process_FullLeft:nN, % \@@_listings_process_FullRight:nN} % 当使用 \texttt{breaklines} 选项时,立即输出之前的单个文字,以便于断行。并将标点 % 与它前/后的 CJK 文字放在同一个盒子中,以保持禁则。但是不能区分 letter 和 other。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_process_breaklines_CJK:nN { \lst@whitespacefalse \bool_if:NTF \l_@@_listings_letter_bool { \int_compare:nNnF \l_@@_listings_flag_int = 2 { \lst@Output } \lst@lettertrue } { \lst@ifletter \lst@Output \else: \lst@OutputOther \lst@lettertrue \fi: \bool_set_true:N \l_@@_listings_letter_bool } \int_set_eq:NN \l_@@_listings_flag_int \c_one_int \@@_listings_append:nN } \cs_new_protected:Npn \@@_listings_process_FullLeft:nN #1#2 { \lst@whitespacefalse \bool_if:NTF \l_@@_listings_letter_bool { \int_compare:nNnF \l_@@_listings_flag_int = 2 { \int_compare:nNnTF \l_@@_listings_flag_int = 3 { \bool_if:NT \l_@@_punct_breakable_bool { \lst@Output } } { \lst@Output } } \lst@lettertrue } { \lst@ifletter \lst@Output \else: \lst@OutputOther \lst@lettertrue \fi: \bool_set_true:N \l_@@_listings_letter_bool } \int_set:Nn \l_@@_listings_flag_int { 2 } \@@_listings_append:nN {#1} #2 } \cs_new_protected:Npn \@@_listings_process_FullRight:nN #1#2 { \lst@whitespacefalse \bool_if:NTF \l_@@_listings_letter_bool { \int_compare:nNnT \l_@@_listings_flag_int < 2 { \@@_punct_if_long:NT #2 { \lst@Output } } \lst@lettertrue } { \lst@ifletter \lst@Output \else: \lst@OutputOther \lst@lettertrue \fi: \bool_set_true:N \l_@@_listings_letter_bool } \int_set:Nn \l_@@_listings_flag_int { 3 } \@@_listings_append:nN {#1} #2 } \int_new:N \l_@@_listings_flag_int % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\lst@AppendLetter,\lst@AppendOther} % \begin{macrocode} \cs_set_protected:Npn \lst@AppendLetter { \bool_if:NTF \l_@@_listings_letter_bool { \lst@Output \lst@lettertrue \bool_set_false:N \l_@@_listings_letter_bool } { \reverse_if:N \lst@ifletter \lst@OutputOther \lst@lettertrue \fi: } \lst@ifbreaklines \int_zero:N \l_@@_listings_flag_int \fi: \lst@Append } \cs_set_protected:Npn \lst@AppendOther { \bool_if:NTF \l_@@_listings_letter_bool { \lst@Output \lst@letterfalse \bool_set_false:N \l_@@_listings_letter_bool } { \lst@ifletter \lst@Output \lst@letterfalse \fi: } \lst@ifbreaklines \int_zero:N \l_@@_listings_flag_int \fi: \tex_futurelet:D \lst@lastother \lst@Append } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_process_CM:nN} % \texttt{CM} 类作为 \texttt{letter} 处理,不用增加 \tn{lst@length}。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_process_CM:nN { \reverse_if:N \lst@ifflexible \bool_gset_true:N \g_@@_listings_CM_bool \fi: \@@_listings_process_letter:nN } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_output_CM:} % 在使用 \texttt{columns=fixed} 选项时,\pkg{listings} 会在输出盒子里的每个字符 % 之间加入 \tn{hss},这就破坏了 \XeTeX 将基本字和组合标识正确的组合起来。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_output_CM: { \reverse_if:N \lst@ifflexible \bool_if:NT \g_@@_listings_CM_bool { \bool_gset_false:N \g_@@_listings_CM_bool \xeCJK_cs_clear:N \lst@FillOutputBox \cs_set_eq:NN \CJKglue \tex_hss:D } \fi: } \bool_new:N \g_@@_listings_CM_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_peek_active_loop:TF} % \tn{lstinline} 通过判断参数中第一个字符是否是 \texttt{active} 类来区分 % 它是否被用在其他宏的参数之中。如果这第一个字符不在 \pkg{listings} 预定义的 % 符号表中,判断就会出问题。我们在这里通过一个循环跳过这些字符。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_peek_active_loop:TF #1#2#3 { \token_if_active:NTF #3 { #1#3 } { \token_if_cs:NTF #3 { #2#3 } { \int_compare:nNnTF { `#3 } > { \l_@@_listings_max_char_int } { \@@_listings_peek_active_loop:TF { #1#3 } { #2#3 } } { #2#3 } } } } \cs_set_eq:NN \lst@IfNextCharActive \@@_listings_peek_active_loop:TF % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_rescan:Nn, % \@@_listings_inside_convert:nw,\@@_listings_inline_group:w} % 当 \tn{lstinline} 被使用在参数中时,\pkg{listings} 会使用一个循环逐个将 % \tn{lstinline} 参数中的字符设置为活动字符。我们可以通过 \cs{tl_set_rescan:Nnn} % 来完成这里的 \tn{catcode} 转换,避免将 \tn{charcode} 超过 $255$ 的字符都设置为 % 活动字符。 % \begin{macrocode} \cs_new_protected:Npn \@@_listings_rescan:Nn #1#2 { \@@_listings_set_escape: \tl_set:Nn \l_@@_tmp_tl {#2} \@@_listings_escape_backslash: \tl_set_rescan:Nno #1 { } { \l_@@_tmp_tl } } \cs_new_protected:Npn \@@_listings_inside_convert:nw #1 ~ \@empty { \@@_listings_rescan:Nn \l_@@_tmp_tl {#1} \tl_put_right:No \lst@arg { \l_@@_tmp_tl } } \cs_set_eq:NN \lst@InsideConvert@ \@@_listings_inside_convert:nw \cs_new_protected:Npn \@@_listings_inline_group:w { \exp_after:wN \@@_listings_inline_group:n \exp_after:wN { \if_int_compare:w `} = \c_zero_int \fi: } \cs_set_eq:NN \lst@InlineGJ \@@_listings_inline_group:w \cs_new_protected:Npn \@@_listings_inline_group:n #1 { \@@_listings_rescan:Nn \lst@arg {#1} \lst@InlineGJEnd } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_listings_set_escape:} % 由于我们在上面的修改,需要保留 |\| 用于转义 \tn{lstinline} 参数中的某些 \TeX % 特殊字符,与原来宏包一致。 % \begin{macrocode} \group_begin: \cs_set:Npn \@@_tmp:w #1 { \group_end: \cs_new_protected:Npn \@@_listings_set_escape: { \xeCJK_swap_cs:NN #1 \@@_listings_escape:N } \cs_new_protected:Npn \@@_listings_escape:N ##1 { \cs_if_eq:NNTF #1 ##1 { \@@_listings_escape:N } {##1} } } \use:n { \char_set_catcode_active:N \\ \@@_tmp:w } { \ } % \end{macrocode} % \end{macro} % % % \changes{v3.4.8}{2017/05/15}{转义 \tn{lstinline} 参数中的 $\texttt{\textbackslash}_{12}$。} % \begin{macro}{\@@_listings_escape_backslash:} % \tn{catcode} 为 $12$ 的 |\| 需要双写转义。 % \begin{macrocode} \cs_new_protected:Npx \@@_listings_escape_backslash: { \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl { \c_backslash_str } { \c_backslash_str \c_backslash_str } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<@@=xunadd> % \end{macrocode} % % \subsection{\pkg{xunicode-addon}} % % \changes{v3.2.5}{2013/07/18} % {增加小宏包 \pkg{xunicode-addon},为 \pkg{xunicode} 提供判断字符是否存在的功能。} % \changes{v3.2.9}{2013/12/08} % {文档部分增加 \pkg{xunicode} 定义的符号表。} % % \begin{macrocode} %<*xunicode> % \end{macrocode} % % \pkg{xunicode} 对编码相关的符号命令的定义中用的是诸如 |\char"0022\relax| 的形式。 % 例如 \tn{textbar} 被展开为 |\char"007C\relax|。并且诸如下述的定义是无效的: % \begin{verbatim} % \DeclareUTFcomposite[\UTFencname]{x1EBF}{\'}{\^e} % \end{verbatim} % 我们在这里做的修改是把符号命令定义为实际的字符并且使上述定义生效。另外在使用 % 这些符号命令的时候,先判断当前字体中是否存在对应的字符,如果不存在,则使用这 % 些符号命令的默认设置。 % % \begin{macrocode} \bool_lazy_or:nnF { \sys_if_engine_xetex_p: } { \sys_if_engine_luatex_p: } { \msg_new:nnnn { xunicode-addon } { xetex-luatex } { This~package~requires~either~XeTeX~or~LuaTeX~to~function.} { You~must~change~your~typesetting~engine~to,~e.g.,\\ "xelatex"~or~"lualatex"~instead~of~plain~"latex"~or~"pdflatex". } \msg_critical:nn { xunicode-addon } { xetex-luatex } } \RequirePackage { xparse } % \end{macrocode} % % 宏包选项是编码的名字。 % % \begin{macrocode} \clist_new:N \g_@@_encname_clist \tl_if_exist:NT \UTFencname { \clist_gput_right:Nx \g_@@_encname_clist { \UTFencname } } \DeclareOption* { \clist_gput_right:No \g_@@_encname_clist \CurrentOption } \ProcessOptions \scan_stop: % \end{macrocode} % % 若 \pkg{xunicode} 已经被调用,则在宏包结束的时候,重新设置 \tn{UTFencname} % 对应的编码命令。否则设置 \tn{UTFencname},如果使用的是 \hologo{LuaLaTeX},则 % 需要作一些设置,使得 \pkg{xunicode} 可用。 % % \changes{v3.3.3}{2016/02/01}{使用新的 Unicode 编码名称 \texttt{TU}。} % % \begin{macrocode} \@ifpackageloaded { xunicode } { } { \clist_get:NNF \g_@@_encname_clist \UTFencname { \cs_if_exist:NTF \UnicodeEncodingName { \tl_set:Nx \UTFencname { \UnicodeEncodingName } } { \sys_if_engine_xetex:TF { \tl_set:Nn \UTFencname { EU1 } } { \tl_set:Nn \UTFencname { EU2 } } } \clist_gset_eq:NN \g_@@_encname_clist \UTFencname } \sys_if_engine_xetex:TF { \RequirePackage { xunicode } } { \cs_set_eq:NN \@@_tmp:w \XeTeXpicfile \cs_set_eq:NN \XeTeXpicfile \prg_do_nothing: \RequirePackage { xunicode } \cs_set_eq:NN \XeTeXpicfile \@@_tmp:w } } \AtEndOfPackage { \@@_reload:N \g_@@_encname_clist } % \end{macrocode} % % \begin{macro}[int]{\ReloadXunicode} % 参数可以是多个编码,设置这些编码对应的命令。如果编码没有预先声明,则给出 % 一个错误警告。 % \begin{macrocode} \RenewDocumentCommand \ReloadXunicode { m } { \clist_set:Nx \l_@@_encname_clist {#1} \@@_reload:N \l_@@_encname_clist } \cs_new_protected:Npn \@@_reload:N #1 { \cs_set_eq:NN \@@_tmp:w \iftipaonetoken \cs_set_eq:NN \iftipaonetoken \scan_stop: \use:e { \ExplSyntaxOff \char_set_catcode_letter:n { 64 } \exp_not:N \clist_map_function:NN \exp_not:N #1 \@@_reload_aux:n \bool_if:NTF \l__kernel_expl_bool { \ExplSyntaxOn } { \ExplSyntaxOff } \char_set_catcode:nn { 64 } { \char_value_catcode:n { 64 } } } \cs_set_eq:NN \iftipaonetoken \@@_tmp:w } \cs_new_protected:Npn \@@_reload_aux:n #1 { \cs_if_exist:cTF { T@ #1 } { \tl_set:Nn \UTFencname {#1} \clist_if_in:NnF \g_@@_encname_clist {#1} { \clist_gput_right:Nn \g_@@_encname_clist {#1} } \file_input:n { xunicode.sty } \file_input:n { xunicode-extra.def } } { \msg_error:nnn { xunicode-addon } { encoding-unknown } {#1} } } \clist_new:N \l_@@_encname_clist \msg_new:nnnn { xunicode-addon } { encoding-unknown } { Encoding~scheme~"#1"~unknown. } { You~may~use \\\\ \token_to_str:N \usepackage [ #1 , \encodingdefault ] \{fontenc\} \\\\ before~xunicode-addon~or~xunicode. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFmathsymbols} % \changes{v3.2.8}{2013/12/04}{修正 \tn{UseMathAsText} 的功能,恢复 \tn{hbar} % 和增加以 \texttt{text} 打头的文本符号命令。} % 将文本符号定义为 \tn{protected} 宏后,为了与 \pkg{hyperref} 的书签功能兼容 % 需要作一点额外处理。 % \begin{macrocode} \RenewDocumentCommand \DeclareUTFmathsymbols { m } { \bool_if:NT \l_@@_math_as_UTF_text_bool { \seq_map_inline:Nn \l_@@_math_as_UTF_text_seq { \@@_declare_math_as_UTF_text:n {##1} } \bool_set_false:N \l_@@_math_as_UTF_text_bool } } \seq_new:N \l_@@_math_as_UTF_text_seq \seq_set_from_clist:Nn \l_@@_math_as_UTF_text_seq { hbar , Finv , aleph , beth , gimel , daleth , Game } \bool_new:N \l_@@_math_as_UTF_text_bool \RenewDocumentCommand \UseMathAsText { } { \math@s@text@true \bool_set_true:N \l_@@_math_as_UTF_text_bool } \@onlypreamble \UseMathAsText \cs_new_protected:Npn \@@_declare_math_as_UTF_text:n #1 { \cs_if_exist:cTF {#1} { \cs_new_eq:cc { keepmathUTF #1 } {#1} \cs_gset_protected:cpx {#1} { \exp_not:N \mode_if_math:TF { \exp_not:c { keepmathUTF #1 } } { \exp_not:c { text #1 } } } \tl_put_right:Nx \l_@@_hyperref_hook_tl { \cs_set_eq:NN \exp_not:c {#1} \exp_not:c { text #1 } } } { \cs_new:cpx {#1} { \exp_not:c { text #1 } } } } \tl_new:N \l_@@_hyperref_hook_tl \AtBeginDocument { \cs_if_free:NF \pdfstringdefDisableCommands { \pdfstringdefDisableCommands { \l_@@_hyperref_hook_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF]{\@@_glyph_if_exist:n} % 判断字符在当前字体中是否存在。 % \begin{macrocode} \prg_new_conditional:Npnn \@@_glyph_if_exist:n #1 { p , T , F , TF } { \tex_iffontchar:D \tex_font:D \tex_numexpr:D #1 \scan_stop: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\UndeclareUTFcharacter} % 取消编码 |#1| 下的符号命令 |#3|。 % \begin{macrocode} \RenewDocumentCommand \UndeclareUTFcharacter { O { \UTFencname } m m } { \@@_if_csname:nTF {#3} { \UndeclareTextCommand {#3} } { \exp_args:Nc \UndeclareTextCommand { \tl_to_str:n {#3} } } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\UndeclareUTFcomposite} % 取消编码 |#1| 下的复合符号命令 |#3{#4}|。 % \begin{macrocode} \RenewDocumentCommand \UndeclareUTFcomposite { O { \UTFencname } m m m } { \@@_if_csname:nTF {#3} { \@@_undeclare_composite:Nnnn #3 } { \exp_args:Nc \@@_undeclare_composite:Nnnn { \tl_to_str:n {#3} } } {#1} {#4} {#2} } \cs_new_protected:Npn \@@_undeclare_composite:Nnnn #1#2#3#4 { \cs_undefine:c { \@@_composite_cs:Nnn #1 {#2} {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_composite_cs:Nnn,\@@_composite_cs:nnn} % \begin{macrocode} \cs_new:Npx \@@_composite_cs:Nnn #1#2#3 { \c_backslash_str #2 \exp_not:N \token_to_str:N #1 - \exp_not:N \tl_to_str:n {#3} } \cs_new:Npx \@@_composite_cs:nnn #1#2#3 { \c_backslash_str #2 #1 - \exp_not:N \tl_to_str:n {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_if_csname:nTF} % 判断 |#1| 是否可以作为控制序列的名字。这是因为 \pkg{xunicide} 使用了下面的定义。 % \begin{verbatim} % \DeclareUTFcharacter[\UTFencname]{x0149}{'n} % \end{verbatim} % \begin{macrocode} \prg_new_conditional:Npnn \@@_if_csname:n #1 { TF } { \tl_if_single_token:nTF {#1} { \token_if_cs:NTF #1 { \prg_return_true: } { \token_if_active:NTF #1 { \prg_return_true: } { \prg_return_false: } } } { \prg_return_false: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFcharacter} % 定义编码 |#1| 下的符号命令 |#3|,其对应符号的 Unicode 是 |#2|。 % \begin{macrocode} \RenewDocumentCommand \DeclareUTFcharacter { O { \UTFencname } m m } { \cs_if_exist_use:cF { @@_restore_ \tl_to_str:n {#3} : } { \@@_if_csname:nTF {#3} { \@@_declare_character:Nnn #3 } { \@@_declare_character:cnn { \tl_to_str:n {#3} } } {#1} {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_restore_cmd:N} % 恢复 \tn{hbar} 和 \tn{nobreakspace} 为原本定义。 % \begin{macrocode} \cs_new_protected:cpn { @@_restore_ \tl_to_str:n { \hbar } : } { \@@_restore_cmd:N \hbar } \cs_new_protected:cpn { @@_restore_ \tl_to_str:n { \nobreakspace } : } { \@@_restore_cmd:N \nobreakspace } \cs_new_protected:Npn \@@_restore_cmd:N #1 { \@@_restore_cmd:Ne #1 { ? - \token_to_str:N #1 } } \cs_new_protected:Npn \@@_restore_cmd:Nn #1#2 { \cs_if_free:cF {#2} { \@@_restore_cmd:Nc #1 {#2} } } \cs_new_protected:Npn \@@_restore_cmd:NN #1#2 { \cs_gset_eq:NN #1 #2 \cs_undefine:N #2 } \cs_generate_variant:Nn \@@_restore_cmd:Nn { Ne } \cs_generate_variant:Nn \@@_restore_cmd:NN { Nc } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_declare_character:Nnn} % 通过 \cs{tex_Uchar:D} 直接由 Unicode |#3| 得到编码 |#2| 下的符号命令 % |#1| 对应的实际字符。\tn{DeclareUTFSymbol} 的参数格式与 \tn{DeclareTextSymbol} % 完全一致。 % \begin{macrocode} \cs_new_protected:Npn \@@_declare_character:Nnn #1#2#3 { \@@_provide_text_command_default:N #1 \exp_after:wN \@@_declare_character:NNen \tex_Uchar:D \@@_check_slot:n {#3} \exp_stop_f: #1 { \token_to_str:N #1 } {#2} } \cs_generate_variant:Nn \@@_declare_character:Nnn { c } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFSymbol,\DeclareUTFCommand} % \tn{DeclareUTFCommand} 只能用于定义不带参数的符号命令。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFSymbol { m O { \UTFencname } m } { \@@_declare_character:Nnn #1 {#2} {#3} } \NewDocumentCommand \DeclareUTFCommand { m O { \UTFencname } m } { \@@_text_command:Nonn #1 { \token_to_str:N #1 } {#2} {#3} } \cs_new_protected:Npn \@@_text_command:Nnnn #1#2#3#4 { \DeclareTextCommand #1 {#3} { \@@_text_command:nn {#2} {#4} } } \cs_generate_variant:Nn \@@_text_command:Nnnn { No } \cs_new_protected:Npn \@@_text_command:nn #1#2 { \@@_begin_hook:nn {#1} {#2} #2 \@@_end_hook:nn {#1} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_provide_text_command_default:N} % 如果控制序列 |#1| 已经存在,但不是符号命令,\pkg{xunicode} 会将它定义为 % \tn{UTFencname} 编码下的符号命令。但是编码被转换之后,再使用这些控制序列, % \pkg{NFSS} 就会报错。为此需要给出这些符号命令的默认定义,与原来的意义相同。 % 这些命令包括 % \begin{verbatim} % \nobreakspace macro:->\protect \nobreakspace % \copyright macro:->\protect \copyright % \AA macro:->\r A % \aa macro:->\r a % \textrhookopeno \long macro:->\textrethookbelow {\textopeno } % \hbar macro:->{\mathchar '26\mkern -9muh} % \textaolig macro:->{a\kern -.25em o} % \end{verbatim} % 影响比较大的是 \tn{nobreakspace}、\tn{copyright} 和 \tn{hbar}。 % \begin{macrocode} \cs_new_protected:Npn \@@_provide_text_command_default:N #1 { \cs_if_exist:cF { ? \token_to_str:N #1 } { \cs_if_free:cF { ? - \token_to_str:N #1 } { \exp_args:NNv \ProvideTextCommandDefault #1 { ? - \token_to_str:N #1 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_declare_character:NNnn} % 使用编码 |#4| 下的符号命令 |#2| 的时候先判断它对应的实际字符 |#1| 在当前字体中 % 是否存在。如果不存在则转换到 \tn{DeclareTextSymbolDefault} 中设置的编码或者使用 % \cs{Declare\-Text\-Command\-Default} 中设置的命令。 % \begin{macrocode} \cs_new_protected:Npn \@@_declare_character:NNnn #1#2#3#4 { \DeclareTextCommand #2 {#4} { \@@_text_character:nN {#3} {#1} } } \cs_new_protected:Npn \@@_text_character:nN #1#2 { \@@_begin_hook:nn {#1} {#2} \@@_glyph_if_exist:nTF { `#2 } {#2} { \cs_if_exist_use:cF { ? #1 } {#2} } \@@_end_hook:nn {#1} {#2} } \cs_generate_variant:Nn \@@_declare_character:NNnn { NNe } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_check_slot:n} % \pkg{xunicode} 中使用的 Unicode 格式是诸如 |x0022| 的形式,这就需要一些转换。 % \begin{macrocode} \cs_new:Npn \@@_check_slot:n #1 { \int_eval:n { \tl_if_head_eq_charcode:nNTF {#1} x { " \use_none:n #1 } {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFcomposite} % 设置编码 |#1| 下的符号命令 |#3| 与它的参数 |#4| 的复合对应的符号的 Unicode 是 |#2|。 % \begin{macrocode} \RenewDocumentCommand \DeclareUTFcomposite { O { \UTFencname } m m m } { \@@_if_csname:nTF {#3} { \@@_declare_composite:Nnnn #3 } { \@@_declare_composite:cnnn { \tl_to_str:n {#3} } } {#1} {#4} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_declare_composite:Nnnn} % 这里使用 \cs{tex_afterassignment:D} 是因为 \pkg{xunicode} 有如下的定义。 % \begin{verbatim} % \DeclareUTFcomposite[\UTFencname]{x02E8\char"02E5}{\tonebar}{25} % \DeclareUTFcomposite[\UTFencname]{x02E5\char"02E8}{\tonebar}{52} % \end{verbatim} % 对复合符号命令的定义用的是 \tn{chardef},这有利于下面字符是否存在的判断。 % \begin{macrocode} \cs_new_protected:Npn \@@_declare_composite:Nnnn #1#2#3#4 { \tex_afterassignment:D \use_none_delimit_by_q_stop:w \@@_chardef:cn { \@@_composite_cs:Nnn #1 {#2} {#3} } { \@@_check_slot:n {#4} } \q_stop } \cs_new_protected:Npn \@@_chardef:Nn #1#2 { \tex_chardef:D #1 = \tex_numexpr:D #2 \scan_stop: } \cs_generate_variant:Nn \@@_chardef:Nn { c } \cs_generate_variant:Nn \@@_declare_composite:Nnnn { c } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFCompositeCommand} % 设置编码 |#2| 下的符号命令 |#1| 与它的参数 |#3| 的复合对应结果是 |#4|。不能直接用 % \cs{Declare\-Text\-Composite\-Command} 来定义,它与我们的机制冲突。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFCompositeCommand { m O { \UTFencname } m m } { \cs_set_protected:cpn { \@@_composite_cs:Nnn #1 {#2} {#3} } {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFCompositeSymbol} % 设置编码 |#2| 下的符号命令 |#1| 与它的参数 |#3| 的复合对应结果是 |#4|。不能直接用 % \cs{Declare\-Text\-Composite} 来定义,它与我们的机制冲突。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFCompositeSymbol { m O { \UTFencname } m m } { \@@_chardef:cn { \@@_composite_cs:Nnn #1 {#2} {#3} } { \@@_check_slot:n {#4} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFComposite} % 将 |#1| 设置为编码 |#2| 下的带一个参数的复合符号命令。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFComposite { m O { \UTFencname } } { \use:e { \@@_declare_composite:Nnn \exp_not:N #1 { \token_to_str:N #1 } {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFEncodedAccent} % |#1| 是重音命令,|#2| 是编码,|#3| 是组合重音符号的 Unicode,|#4| 是基本重音符号 % 的 Unicode。当 |#1| 的参数为空时,输出 |#4|,否则是 |#1| 的参数与 |#3| 的组合。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFEncodedAccent { m O { \UTFencname } m m } { \@@_declare_encoded:NNnnn \@@_combine_accent:nnNNn #1 {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFEncodedAccents} % |#1| 是重音命令,|#2| 是编码,|#3| 和 |#4| 都是组合重音符号的 Unicode。 % 输出 |#1| 与 |#3|、|#4| 的组合。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFEncodedAccents { m O { \UTFencname } m m } { \@@_declare_encoded:NNnnn \@@_combine_accents:nnNNn #1 {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFEncodedSymbol} % |#1| 是带参数的符号命令,|#2| 是编码,|#3| 是组合符号的 Unicode,|#4| 是基本符号的 % Unicode。当 |#1| 的参数为空时,输出 |#4|,否则是 |#1| 的参数与 |#3| 的组合。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFEncodedSymbol { m O { \UTFencname } m m } { \@@_declare_encoded:NNnnn \@@_combine_symbol:nnNNn #1 {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFEncodedCircle} % |#1| 是带参数的圆圈符号命令,|#2| 是编码,|#3| 是组合圆圈符号的 Unicode,|#4| % 是圆圈符号的 Unicode。当 |#1| 的参数为空时,输出 |#4|,否则是 |#1| 的参数与 |#4| 的组合。 % \begin{macrocode} \NewDocumentCommand \DeclareUTFEncodedCircle { m O { \UTFencname } m m } { \@@_declare_encoded:NNnnn \@@_combine_circle:nnNNn #1 {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareEncodedCompositeCharacter} % \begin{macrocode} \RenewDocumentCommand \DeclareEncodedCompositeCharacter { m m m m } { \DeclareUTFEncodedSymbol #2 [#1] { "#3 } { "0#4 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareEncodedCompositeAccents} % \changes{v3.2.9}{2013/12/07}{修正 \pkg{xunicode} 中的错误定义。} % \begin{macrocode} \RenewDocumentCommand \DeclareEncodedCompositeAccents { m m m m } { \DeclareUTFEncodedAccents #2 [#1] { "#4 } { "#3 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFDoubleEncodedAccent} % \changes{v3.2.10}{2014/02/20}{改进 \tn{t} 等的定义方式。} % \begin{macrocode} \NewDocumentCommand \DeclareUTFDoubleEncodedAccent { m O { \UTFencname } m m } { \@@_declare_encoded:NNnnn \@@_combine_double_accent:nnNNn #1 {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFDoubleEncodedSymbol} % \changes{v3.2.10}{2014/02/21}{改进 \tn{sliding} 等的定义方式。} % \begin{macrocode} \NewDocumentCommand \DeclareUTFDoubleEncodedSymbol { m O { \UTFencname } m m } { \@@_declare_encoded:NNnnn \@@_combine_double_symbol:nnNNn #1 {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_declare_composite:Nnn} % 通过 \texttt{lowercase} 技巧,直接由重音符号的 Unicode 得到实际字符。 % \begin{macrocode} \cs_new_protected:Npn \@@_declare_composite:Nnn #1#2#3 { \DeclareTextCommand #1 {#3} { \@@_text_composite:nnn {#2} {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_text_composite:nnn} % \begin{macrocode} \cs_new_protected:Npn \@@_text_composite:nnn #1#2#3 { \@@_begin_hook:nn {#1} {#3} \cs_if_exist:cTF { \@@_composite_cs:nnn {#1} {#2} {#3} } { \@@_text_composite:cnn { \@@_composite_cs:nnn {#1} {#2} {#3} } {#1} {#3} } { \cs_if_exist_use:cTF { ? #1 } { {#3} } {#3} } \@@_end_hook:nn {#1} {#3} } \cs_new_protected:Npn \@@_text_composite:Nnn #1#2#3 { \token_if_chardef:NTF #1 { \@@_glyph_if_exist:nTF {#1} {#1} { \cs_if_exist_use:cTF { ? #2 } { {#3} } {#3} } } {#1} } \cs_generate_variant:Nn \@@_text_composite:Nnn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_declare_encoded:NNnnn} % 通过 \cs{tex_Uchar:D} 直接由重音符号的 Unicode 得到实际字符。 % \begin{macrocode} \cs_new_protected:Npn \@@_declare_encoded:NNnnn #1#2#3#4#5 { \exp_after:wN \@@_declare_encoded:NNNNee \tex_Uchar:D \@@_check_slot:n {#4} \exp_after:wN \exp_stop_f: \tex_Uchar:D \@@_check_slot:n {#5} \exp_stop_f: #1 #2 { \token_to_str:N #2 } {#3} } \cs_new_protected:Npn \@@_declare_encoded:NNNNnn #1#2#3#4#5#6 { \DeclareTextCommand #4 {#6} { #3 {#5} {#6} {#1} {#2} } } \cs_generate_variant:Nn \@@_declare_encoded:NNnnn { c } \cs_generate_variant:Nn \@@_declare_encoded:NNNNnn { NNNNee } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_text_combine:NnnNNn} % 若重音命令 |#2| 与它的参数 |#6| 的复合已经由 \tn{DeclareUTFcomposite} 设置, % 并且在当前字体中存在该字符,则直接使用。否则使用组合命令。 % \begin{macrocode} \cs_new_protected:Npn \@@_text_combine:NnnNNn #1#2#3#4#5#6 { \@@_begin_hook:nn {#2} {#6} \cs_if_exist:cTF { \@@_composite_cs:nnn {#2} {#3} {#6} } { \@@_text_combine:cNnNNn { \@@_composite_cs:nnn {#2} {#3} {#6} } #1 {#2} {#4} {#5} {#6} } { #1 {#6} {#2} {#4} {#5} } \@@_end_hook:nn {#2} {#6} } \cs_new_protected:Npn \@@_text_combine:NNnNNn #1#2#3#4#5#6 { \token_if_chardef:NTF #1 { \@@_glyph_if_exist:nTF {#1} {#1} { #2 {#6} {#3} {#4} {#5} } } {#1} } \cs_generate_variant:Nn \@@_text_combine:NNnNNn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_combine_symbol:nnNNn} % \begin{macrocode} \cs_new_protected:Npn \@@_combine_symbol:nnNNn { \@@_text_combine:NnnNNn \@@_add_symbol:nnNN } \cs_new_protected:Npn \@@_add_symbol:nnNN #1#2#3#4 { \tl_if_blank:nTF {#1} { \@@_glyph_if_exist:nTF { `#4 } {#4} { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#4} } } { \@@_glyph_if_exist:nTF { `#3 } { #1#3 } { \cs_if_exist_use:cTF { ? #2 } { {#1} } { #1#3 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_combine_accent:nnNNn,\@@_add_accent:nnNN} % 若组合重音符号的 |#3| 和基本重音符号 |#4| 在当前字体中都不存在,则转换到 % \cs{Declare\-Text\-Accent\-Default} 设置的编码或者使用 % \tn{DeclareTextCommandDefault} 中设置的命令。\texttt{0.9999} 版以前的 \XeTeX % 需要设置 \tn{XeTeXinputnormalization} 为 $1$,才能使用字体中由基础字符和组合符号 % 对应的实际字符;而 \texttt{0.9999} 版以后的 \XeTeX 默认就启用这个功能,^^A % \tn{XeTeXinputnormalization} 似乎是无效的,怀疑是使用 HarfBuzz 库替代 ICU 进行 % 字体排版的缘故\footnote{\url{http://tug.org/pipermail/xetex/2013-July/024579.html}}。 % \begin{macrocode} \cs_new_protected:Npn \@@_combine_accent:nnNNn { \@@_text_combine:NnnNNn \@@_add_accent:nnNN } \cs_new_protected:Npn \@@_add_accent:nnNN #1#2#3#4 { \tl_if_blank:nTF {#1} { \@@_glyph_if_exist:nTF { `#4 } {#4} { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#4} } } { \@@_glyph_if_exist:nTF { `#3 } { #1#3 } { \@@_glyph_if_exist:nTF { `#4 } { \add@accent { `#4 } {#1} } { \cs_if_exist_use:cTF { ? #2 } { {#1} } { #1#3 } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_combine_accents:nnNNn,\@@_add_accents:nnNN} % \begin{macrocode} \cs_new_protected:Npn \@@_combine_accents:nnNNn { \@@_text_combine:NnnNNn \@@_add_accents:nnNN } \cs_new_protected:Npn \@@_add_accents:nnNN #1#2#3#4 { \tl_if_blank:nTF {#1} { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#1} } { \@@_glyph_if_exist:nTF { `#3 } { \@@_glyph_if_exist:nTF { `#4 } } { \use_ii:nn } { #1#3#4 } { \cs_if_exist_use:cTF { ? #2 } { {#1} } { #1#3#4 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_combine_circle:nnNNn,\@@_add_circle:nnNN,\@@_add_circle:nN} % 对圆圈中的数字或者字母适当缩小,以适合圆圈的大小。只有字体中存在 % \texttt{U+25EF} 时,才使用这里的设置,否则还还是 \LaTeX\ 中的设置。 % \begin{macrocode} \cs_new_protected:Npn \@@_combine_circle:nnNNn { \@@_text_combine:NnnNNn \@@_add_circle:nnNN } \cs_new_protected:Npn \@@_add_circle:nnNN #1#2#3#4 { \tl_if_blank:nTF {#1} { \@@_glyph_if_exist:nTF { `#4 } {#4} { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#4} } } { \@@_glyph_if_exist:nTF { `#4 } { \@@_add_circle:nN {#1} #4 } { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#1} } } } \cs_new_protected:Npn \@@_add_circle:nN #1#2 { \hcoffin_set:Nn \l_@@_tmp_coffin {#1} \hcoffin_set:Nn \l_@@_circle_coffin {#2} \fp_set:Nn \l_@@_circle_scale_fp { \dim_to_decimal_in_unit:nn { \fp_use:N \l_@@_circle_ratio_fp \coffin_wd:N \l_@@_circle_coffin } { \coffin_wd:N \l_@@_tmp_coffin } } \coffin_scale:Nnn \l_@@_tmp_coffin { \l_@@_circle_scale_fp } { \l_@@_circle_scale_fp } \coffin_attach:NnnNnnnn \l_@@_circle_coffin { hc } { vc } \l_@@_tmp_coffin { hc } { vc } { \c_zero_dim } { \c_zero_dim } \coffin_typeset:Nnnnn \l_@@_circle_coffin { H } { l } { \c_zero_dim } { \c_zero_dim } } \fp_new:N \l_@@_circle_scale_fp \coffin_new:N \l_@@_tmp_coffin \coffin_new:N \l_@@_circle_coffin % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\settextcircledratio} % 设置圆圈中文字的宽度与圆圈宽度的比例,预设为 \texttt{0.7}。 % \begin{macrocode} \NewDocumentCommand \settextcircledratio { m } { \fp_set:Nn \l_@@_circle_ratio_fp {#1} } \fp_new:N \l_@@_circle_ratio_fp \settextcircledratio { 0.7 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_combine_double_accent:nnNNn} % 使 \tn{t} 等组合重音符号放在参数的第一个字母的右边。 % \begin{macrocode} \cs_new_protected:Npn \@@_combine_double_accent:nnNNn { \@@_text_combine:NnnNNn \@@_add_double_accent:nnNN } \cs_new_protected:Npn \@@_add_double_accent:nnNN #1#2#3#4 { \tl_if_blank:nTF {#1} { \@@_glyph_if_exist:nTF { `#4 } {#4} { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#4} } } { \@@_glyph_if_exist:nTF { `#3 } { \@@_add_double_symbol:nN {#1} #3 } { \@@_glyph_if_exist:nTF { `#4 } { \add@accent { `#4 } {#1} } { \cs_if_exist_use:cTF { ? #2 } { {#1} } { #1#3 } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_combine_double_symbol:nnNNn} % 使 \tn{sliding} 等组合重音符号放在参数的第一个字母的右边。 % \begin{macrocode} \cs_new_protected:Npn \@@_combine_double_symbol:nnNNn { \@@_text_combine:NnnNNn \@@_add_double_symbol:nnNN } \cs_new_protected:Npn \@@_add_double_symbol:nnNN #1#2#3#4 { \tl_if_blank:nTF {#1} { \@@_glyph_if_exist:nTF { `#4 } {#4} { \cs_if_exist_use:cTF { ? #2 } { {#1} } {#4} } } { \@@_glyph_if_exist:nTF { `#3 } { \@@_add_double_symbol:nN {#1} #3 } { \cs_if_exist_use:cTF { ? #2 } { {#1} } { #1#3 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_double_symbol:nN} % 如果参数的第一个记号是字母类、其他符号类或者由 \tn{chardef} 定义,则将组合符号 % 放在它的右边,否则不作处理。 % \begin{macrocode} \cs_new_protected:Npn \@@_add_double_symbol:nN #1#2 { \tl_if_head_is_N_type:nTF {#1} { \exp_after:wN \exp_after:wN \exp_after:wN \@@_add_double_symbol_aux:NnN \exp_after:wN \exp_after:wN \tl_head:w #1 \q_stop \exp_after:wN { \use_none:n #1 } #2 } { #1#2 } } \cs_new_protected:Npn \@@_add_double_symbol_aux:NnN #1#2#3 { \bool_lazy_any:nTF { { \token_if_letter_p:N #1 } { \token_if_other_p:N #1 } { \token_if_chardef_p:N #1 } } { #1#3#2 } { #1#2#3 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\AtBeginUTFCommand,\AtEndUTFCommand} % 设置在符号命令前后使用的钩子,可选参数用于指定单个符号命名。可以用 |#1| % 引用带参数的组合符号命令的参数或者符号命令对应的符号。 % \changes{v3.2.6}{2013/08/15}{可以指定特定符号命令使用的钩子。} % \changes{v3.7.1}{2018/04/30}{修复代码重构而引入的新错误。} % \begin{macrocode} \NewDocumentCommand \AtBeginUTFCommand { s O { } +m } { \tl_if_blank:nTF {#2} { \IfBooleanTF {#1} { \xunadd_set_begin_hook:n } { \xunadd_append_begin_hook:n } } { \xunadd_set_begin_hook:nn {#2} } {#3} } \NewDocumentCommand \AtEndUTFCommand { s O { } +m } { \tl_if_blank:nTF {#2} { \IfBooleanTF {#1} { \xunadd_set_end_hook:n } { \xunadd_append_end_hook:n } } { \xunadd_set_end_hook:nn {#2} } {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xunadd_set_begin_hook:n,\xunadd_set_end_hook:n} % \begin{macrocode} \cs_new_protected:Npn \xunadd_set_begin_hook:n { \tl_set:Nn \l_@@_begin_hook_tl } \cs_new_protected:Npn \xunadd_append_begin_hook:n { \tl_put_right:Nn \l_@@_begin_hook_tl } \cs_new_protected:Npn \xunadd_set_end_hook:n { \tl_set:Nn \l_@@_end_hook_tl } \cs_new_protected:Npn \xunadd_append_end_hook:n { \tl_put_right:Nn \l_@@_end_hook_tl } \cs_new_protected:Npn \xunadd_set_begin_hook:nn { \@@_set_cmd_hook:nnn { begin } } \cs_new_protected:Npn \xunadd_set_end_hook:nn { \@@_set_cmd_hook:nnn { end } } \cs_new_protected:Npn \@@_set_cmd_hook:nnn #1#2#3 { \cs_set_protected:cpn { \tl_if_single:nTF {#2} { \use:c { @@_#1_csname:n } { \token_to_str:N #2 } } { \@@_set_cmd_hook_aux:Nnwn #2 \q_stop {#1} } } ##1 {#3} } \cs_new:Npn \@@_set_cmd_hook_aux:Nnwn #1#2 \q_stop #3 { \use:c { @@_#3_csname:n } { \token_to_str:N #1 - \tl_to_str:n {#2} } } \cs_new:Npn \@@_begin_csname:n #1 { @@_begin_#1_hook:n } \cs_new:Npn \@@_end_csname:n #1 { @@_end_#1_hook:n } \tl_new:N \l_@@_begin_hook_tl \tl_new:N \l_@@_end_hook_tl % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_begin_hook:nn,\@@_end_hook:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_begin_hook:nn #1#2 { \tl_use:N \l_@@_begin_hook_tl \cs_if_exist_use:cF { \@@_begin_csname:n { #1 - \tl_to_str:n {#2} } } { \cs_if_exist_use:cF { \@@_begin_csname:n {#1} } { \use_none:n } } {#2} } \cs_new_protected:Npn \@@_end_hook:nn #1#2 { \cs_if_exist_use:cF { \@@_end_csname:n { #1 - \tl_to_str:n {#2} } } { \cs_if_exist_use:cF { \@@_end_csname:n {#1} } { \use_none:n } } {#2} \tl_use:N \l_@@_end_hook_tl } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareUTFTIPACommand} % \changes{v3.2.10}{2014/02/20}{检查 \tn{t} 和 \tn{sliding} 的参数是否以 \tn{textipa} 开头。} % \begin{macrocode} \NewDocumentCommand \DeclareUTFTIPACommand { O { \UTFencname } m } { \use:e { \@@_text_tipa_command:Nnn \exp_not:N #2 { \token_to_str:N #2 } {#1} } } \cs_new_protected:Npn \@@_text_tipa_command:Nnn #1#2#3 { \cs_set_eq:cc { UTF/#3#2 } { #3#2 } \DeclareTextCommand #1 {#3} { \@@_text_tipa_command:nnn {#3} {#2} } } \cs_new_protected:Npn \@@_text_tipa_command:nnn #1#2#3 { \exp_args:Ncc \@@_check_for_tipa:NNn { \use_none:n #2 } { UTF/#1#2 } {#3} } \cs_new_protected:Npn \@@_check_for_tipa:NNn #1#2#3 { \tl_if_head_eq_meaning:nNTF {#3} \textipa { \exp_after:wN \tipacatchonechar \exp_after:wN { \exp_after:wN #1 \use_none:n #3 } } { #2 {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\xunadd_get_slot:nn} % |#1| 是编码,|#2| 是诸如 \tn{textendash} 或 |\v C| 等形式的文本命令,取得他们对应的字符编码。 % \begin{macrocode} \cs_new_protected:Npn \xunadd_get_slot:nn #1#2 { \@@_get_slot:wn #2 \q_nil \q_stop {#1} } \cs_new_protected:Npn \@@_get_slot:wn #1#2#3 \q_stop #4 { \int_set:Nn \l_xunadd_slot_int { -1 } \bool_set_false:N \l_xunadd_rest_bool \group_begin: \exp_args:Nccc \group_end: { @@_get_slot:NNnn } { #4 \token_to_str:N #1 } { \@@_composite_cs:Nnn #1 {#4} {#2} } {#2} {#3} } \int_new:N \l_xunadd_slot_int \bool_new:N \l_xunadd_rest_bool \cs_new_protected:Npn \@@_get_slot:NNnn #1#2#3#4 { \cs_if_free:NF #1 { \cs_if_exist:NTF #2 { \@@_get_composite_slot:Nn #2 {#4} } { \@@_get_character_slot:Nn #1 { #3 #4 } } } } \cs_new_protected:Npn \@@_get_composite_slot:Nn #1#2 { \token_if_chardef:NT #1 { \int_set:Nn \l_xunadd_slot_int {#1} \quark_if_nil:nF {#2} { \bool_set_true:N \l_xunadd_rest_bool } } } \cs_new_protected:Npn \@@_get_character_slot:Nn #1 { \exp_after:wN \@@_get_character_slot_aux:wn #1 \@@_text_character:nN \q_nil \q_nil \q_stop } \cs_new_protected:Npn \@@_get_character_slot_aux:wn #1 \@@_text_character:nN #2#3#4 \q_stop #5 { \quark_if_nil:nF {#2} { \int_set:Nn \l_xunadd_slot_int { `#3 } \quark_if_nil:nF {#5} { \bool_set_true:N \l_xunadd_rest_bool } } } % \end{macrocode} % \end{macro} % % \changes{v3.7.2}{2018/05/12}{解决与 \pkg{microtype} 宏包的兼容问题。} % % \begin{macro}[int]{\xunadd@microtype@is@charx} % \pkg{microtype} 宏包中使用的函数,我们通过对 \tn{MT@is@charx} 打补丁来实现功能。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xunadd@microtype@is@charx #1 \relax { \use:e { \xunadd_get_slot:nn { \MT@encoding } { \tex_the:D \MT@toks } } \int_compare:nNnTF \l_xunadd_slot_int < \c_zero_int { \xunadd@original@is@charx #1 \relax } { \cs_set_nopar:Npx \MT@char@ { \int_use:N \l_xunadd_slot_int } \bool_if:NT \l_xunadd_rest_bool { \MT@norestfalse } } } \cs_new_protected_nopar:Npn \xunadd@microtype@hook { \cs_if_free:NF \MT@is@charx { \cs_new_eq:NN \xunadd@original@is@charx \MT@is@charx \cs_set_eq:NN \MT@is@charx \xunadd@microtype@is@charx \cs_set_eq:NN \MT@warn@unknown@once \use_none:n } } \@ifpackageloaded { microtype } { \use:n } { \AtBeginDocument } { \xunadd@microtype@hook } % \end{macrocode} % \end{macro} % % \changes{v3.2.8}{2013/12/05}{启用 \pkg{xunicode} 中的带圈数字和字母设置。} % % \begin{macrocode} % %<*xunextra> % \end{macrocode} % % \changes{v3.7.0}{2018/03/16}{补充定义 \tn{texthyphenationpoint} 和 \tn{texttwoemdash}。} % % 我们补充定义 HYPHENATION POINT 和 TWO-EM DASH,他们默认被归入 CJK 标点符号。 % \begin{macrocode} \DeclareUTFSymbol\texthyphenationpoint{"2027} \DeclareUTFSymbol\texttwoemdash{"2E3A} % \end{macrocode} % % 以下内容选自 \pkg{xunicode},并做了适当修改。 % \begin{macrocode} \DeclareUTFComposite\textsuperscript \DeclareUTFComposite\textsubscript \DeclareUTFEncodedAccent\textsbleftarrow{"20EE}{"20FF} \DeclareUTFEncodedAccent\`{"0300}{"02CB} \DeclareUTFEncodedAccent\capitalgrave{"0300}{"02CB} \DeclareUTFEncodedAccent\'{"0301}{"02CA} \DeclareUTFEncodedAccent\capitalacute{"0301}{"02CA} \DeclareUTFEncodedAccent\^{"0302}{"02C6} \DeclareUTFEncodedAccent\capitalcircumflex{"0302}{"02C6} \DeclareUTFEncodedAccent\~{"0303}{"02DC} \DeclareUTFEncodedAccent\capitaltilde{"0303}{"02DC} \DeclareUTFEncodedAccent\={"0304}{"02C9} \DeclareUTFEncodedAccent\capitalmacron{"0304}{"02C9} \DeclareUTFEncodedAccent\textoverline{"0305}{"203E} \DeclareUTFEncodedAccent\u{"0306}{"02D8} \DeclareUTFEncodedAccent\capitalbreve{"0306}{"02D8} \DeclareUTFEncodedAccent\.{"0307}{"02D9} \DeclareUTFEncodedAccent\capitaldotaccent{"0307}{"02D9} \DeclareUTFEncodedAccent\"{"0308}{"00A8} \DeclareUTFEncodedAccent\capitaldieresis{"0308}{"00A8} \DeclareUTFEncodedAccent\m{"0309}{"0309} \DeclareUTFEncodedAccent\texthookabove{"0309}{"0309} \DeclareUTFEncodedAccent\r{"030A}{"02DA} \DeclareUTFEncodedAccent\capitalring{"030A}{"02DA} \DeclareUTFEncodedAccent\H{"030B}{"02DD} \DeclareUTFEncodedAccent\capitalhungarumlaut{"030B}{"02DD} \DeclareUTFEncodedAccent\v{"030C}{"02C7} \DeclareUTFEncodedAccent\capitalcaron{"030C}{"02C7} \DeclareUTFEncodedAccent\textvbaraccent{"030D}{"02C8} \DeclareUTFEncodedAccent\textdoublevbaraccent{"030E}{"0022} \DeclareUTFEncodedAccent\U{"030E}{"0022} \DeclareUTFEncodedAccent\textdoublegrave{"030F}{"02F5} \DeclareUTFEncodedAccent\G{"030F}{"02F5} \DeclareUTFEncodedAccent\textdotbreve{"0310}{"0310} \DeclareUTFEncodedAccent\textroundcap{"0311}{"0311} \DeclareUTFEncodedAccent\newtie{"0311}{"0311} \DeclareUTFEncodedAccent\capitalnewtie{"0311}{"0311} \DeclareUTFEncodedAccent\textturncommaabove{"0312}{"02BB} \DeclareUTFEncodedAccent\textcommaabove{"0313}{"02BC} \DeclareUTFEncodedAccent\textrevcommaabove{"0314}{"02BD} \DeclareUTFEncodedAccent\overbridge{"0346}{"0346} \DeclareUTFEncodedAccent\crtilde{"034A}{"034A} \DeclareUTFEncodedAccent\dottedtilde{"034B}{"034B} \DeclareUTFEncodedAccent\doubletilde{"034C}{"034C} \DeclareUTFEncodedAccent\textrightarrowhead{"0350}{"02C3} \DeclareUTFEncodedAccent\textlefthalfring{"0351}{"02D3} \DeclareUTFEncodedAccent\textrighthalfring{"0357}{"02D2} \DeclareUTFDoubleEncodedSymbol\textdoublebrevebelow{"035C}{"035C} \DeclareUTFDoubleEncodedAccent\textdoublebreve{"035D}{"035D} \DeclareUTFDoubleEncodedAccent\textdoublemacron{"035E}{"035E} \DeclareUTFDoubleEncodedSymbol\textdoublemacronbelow{"035F}{"035F} \DeclareUTFDoubleEncodedAccent\textdoubletilde{"0360}{"0360} \DeclareUTFDoubleEncodedAccent\t{"0361}{"0361} \DeclareUTFDoubleEncodedAccent\capitaltie{"0361}{"0361} \DeclareUTFDoubleEncodedAccent\texttoptiebar{"0361}{"0361} \DeclareUTFDoubleEncodedSymbol\sliding{"0362}{"0362} \DeclareUTFTIPACommand\t \DeclareUTFTIPACommand\capitaltie \DeclareUTFTIPACommand\texttoptiebar \DeclareUTFTIPACommand\sliding \DeclareUTFEncodedAccent\texthighrise{"1DC4}{"1DC4} \DeclareUTFEncodedAccent\textlowrise{"1DC5}{"1DC5} \DeclareUTFEncodedAccent\textrisefall{"1DC8}{"1DC8} \DeclareUTFEncodedAccent\textfallrise{"1DC9}{"1DC9} \DeclareUTFEncodedAccent\textaolig{"1DD5}{"1DD5} \DeclareUTFCompositeSymbol\textundertie{H}{"1E2A} \DeclareUTFCompositeSymbol\textundertie{h}{"1E2B} \DeclareUTFEncodedAccents\textcircumgrave{"0302}{"0301} \DeclareUTFSymbol\textFinv{"2132} \DeclareUTFSymbol\textaleph{"2135} \DeclareUTFSymbol\textbeth{"2136} \DeclareUTFSymbol\textgimel{"2137} \DeclareUTFSymbol\textdaleth{"2138} \DeclareUTFSymbol\textGame{"2141} \DeclareUTFCompositeCommand\tonebar{25}{\tonebar{2}\tonebar{5}} \DeclareUTFCompositeCommand\tonebar{52}{\tonebar{5}\tonebar{2}} \DeclareUTFSymbol\textbigcircle{"25EF} \DeclareUTFEncodedCircle\textcircled{"20DD}{"25EF} \DeclareUTFCompositeSymbol\textcircled{0}{"24EA} \DeclareUTFCompositeSymbol\textcircled{1}{"2460} \DeclareUTFCompositeSymbol\textcircled{2}{"2461} \DeclareUTFCompositeSymbol\textcircled{3}{"2462} \DeclareUTFCompositeSymbol\textcircled{4}{"2463} \DeclareUTFCompositeSymbol\textcircled{5}{"2464} \DeclareUTFCompositeSymbol\textcircled{6}{"2465} \DeclareUTFCompositeSymbol\textcircled{7}{"2466} \DeclareUTFCompositeSymbol\textcircled{8}{"2467} \DeclareUTFCompositeSymbol\textcircled{9}{"2468} \DeclareUTFCompositeSymbol\textcircled{10}{"2469} \DeclareUTFCompositeSymbol\textcircled{11}{"246A} \DeclareUTFCompositeSymbol\textcircled{12}{"246B} \DeclareUTFCompositeSymbol\textcircled{13}{"246C} \DeclareUTFCompositeSymbol\textcircled{14}{"246D} \DeclareUTFCompositeSymbol\textcircled{15}{"246E} \DeclareUTFCompositeSymbol\textcircled{16}{"246F} \DeclareUTFCompositeSymbol\textcircled{17}{"2470} \DeclareUTFCompositeSymbol\textcircled{18}{"2471} \DeclareUTFCompositeSymbol\textcircled{19}{"2472} \DeclareUTFCompositeSymbol\textcircled{20}{"2473} \DeclareUTFCompositeSymbol\textcircled{21}{"3251} \DeclareUTFCompositeSymbol\textcircled{22}{"3252} \DeclareUTFCompositeSymbol\textcircled{23}{"3253} \DeclareUTFCompositeSymbol\textcircled{24}{"3254} \DeclareUTFCompositeSymbol\textcircled{25}{"3255} \DeclareUTFCompositeSymbol\textcircled{26}{"3256} \DeclareUTFCompositeSymbol\textcircled{27}{"3257} \DeclareUTFCompositeSymbol\textcircled{28}{"3258} \DeclareUTFCompositeSymbol\textcircled{29}{"3259} \DeclareUTFCompositeSymbol\textcircled{30}{"325A} \DeclareUTFCompositeSymbol\textcircled{31}{"325B} \DeclareUTFCompositeSymbol\textcircled{32}{"325C} \DeclareUTFCompositeSymbol\textcircled{33}{"325D} \DeclareUTFCompositeSymbol\textcircled{34}{"325E} \DeclareUTFCompositeSymbol\textcircled{35}{"325F} \DeclareUTFCompositeSymbol\textcircled{36}{"32B1} \DeclareUTFCompositeSymbol\textcircled{37}{"32B2} \DeclareUTFCompositeSymbol\textcircled{38}{"32B3} \DeclareUTFCompositeSymbol\textcircled{39}{"32B4} \DeclareUTFCompositeSymbol\textcircled{40}{"32B5} \DeclareUTFCompositeSymbol\textcircled{41}{"32B6} \DeclareUTFCompositeSymbol\textcircled{42}{"32B7} \DeclareUTFCompositeSymbol\textcircled{43}{"32B8} \DeclareUTFCompositeSymbol\textcircled{44}{"32B9} \DeclareUTFCompositeSymbol\textcircled{45}{"32BA} \DeclareUTFCompositeSymbol\textcircled{46}{"32BB} \DeclareUTFCompositeSymbol\textcircled{47}{"32BC} \DeclareUTFCompositeSymbol\textcircled{48}{"32BD} \DeclareUTFCompositeSymbol\textcircled{49}{"32BE} \DeclareUTFCompositeSymbol\textcircled{50}{"32BF} \DeclareUTFCompositeSymbol\textcircled{A}{"24B6} \DeclareUTFCompositeSymbol\textcircled{B}{"24B7} \DeclareUTFCompositeSymbol\textcircled{C}{"24B8} \DeclareUTFCompositeSymbol\textcircled{D}{"24B9} \DeclareUTFCompositeSymbol\textcircled{E}{"24BA} \DeclareUTFCompositeSymbol\textcircled{F}{"24BB} \DeclareUTFCompositeSymbol\textcircled{G}{"24BC} \DeclareUTFCompositeSymbol\textcircled{H}{"24BD} \DeclareUTFCompositeSymbol\textcircled{I}{"24BE} \DeclareUTFCompositeSymbol\textcircled{J}{"24BF} \DeclareUTFCompositeSymbol\textcircled{K}{"24C0} \DeclareUTFCompositeSymbol\textcircled{L}{"24C1} \DeclareUTFCompositeSymbol\textcircled{M}{"24C2} \DeclareUTFCompositeSymbol\textcircled{N}{"24C3} \DeclareUTFCompositeSymbol\textcircled{O}{"24C4} \DeclareUTFCompositeSymbol\textcircled{P}{"24C5} \DeclareUTFCompositeSymbol\textcircled{Q}{"24C6} \DeclareUTFCompositeSymbol\textcircled{R}{"24C7} \DeclareUTFCompositeSymbol\textcircled{S}{"24C8} \DeclareUTFCompositeSymbol\textcircled{T}{"24C9} \DeclareUTFCompositeSymbol\textcircled{U}{"24CA} \DeclareUTFCompositeSymbol\textcircled{V}{"24CB} \DeclareUTFCompositeSymbol\textcircled{W}{"24CC} \DeclareUTFCompositeSymbol\textcircled{X}{"24CD} \DeclareUTFCompositeSymbol\textcircled{Y}{"24CE} \DeclareUTFCompositeSymbol\textcircled{Z}{"24CF} \DeclareUTFCompositeSymbol\textcircled{a}{"24D0} \DeclareUTFCompositeSymbol\textcircled{b}{"24D1} \DeclareUTFCompositeSymbol\textcircled{c}{"24D2} \DeclareUTFCompositeSymbol\textcircled{d}{"24D3} \DeclareUTFCompositeSymbol\textcircled{e}{"24D4} \DeclareUTFCompositeSymbol\textcircled{f}{"24D5} \DeclareUTFCompositeSymbol\textcircled{g}{"24D6} \DeclareUTFCompositeSymbol\textcircled{h}{"24D7} \DeclareUTFCompositeSymbol\textcircled{i}{"24D8} \DeclareUTFCompositeSymbol\textcircled{j}{"24D9} \DeclareUTFCompositeSymbol\textcircled{k}{"24DA} \DeclareUTFCompositeSymbol\textcircled{l}{"24DB} \DeclareUTFCompositeSymbol\textcircled{m}{"24DC} \DeclareUTFCompositeSymbol\textcircled{n}{"24DD} \DeclareUTFCompositeSymbol\textcircled{o}{"24DE} \DeclareUTFCompositeSymbol\textcircled{p}{"24DF} \DeclareUTFCompositeSymbol\textcircled{q}{"24E0} \DeclareUTFCompositeSymbol\textcircled{r}{"24E1} \DeclareUTFCompositeSymbol\textcircled{s}{"24E2} \DeclareUTFCompositeSymbol\textcircled{t}{"24E3} \DeclareUTFCompositeSymbol\textcircled{u}{"24E4} \DeclareUTFCompositeSymbol\textcircled{v}{"24E5} \DeclareUTFCompositeSymbol\textcircled{w}{"24E6} \DeclareUTFCompositeSymbol\textcircled{x}{"24E7} \DeclareUTFCompositeSymbol\textcircled{y}{"24E8} \DeclareUTFCompositeSymbol\textcircled{z}{"24E9} \DeclareUTFCompositeSymbol\textsuperscript{h}{"02B0} \DeclareUTFCompositeSymbol\textsuperscript{\texthth}{"02B1} \DeclareUTFCompositeSymbol\textsuperscript{j}{"02B2} \DeclareUTFCompositeSymbol\textsuperscript{r}{"02B3} \DeclareUTFCompositeSymbol\textsuperscript{\textturnr}{"02B4} \DeclareUTFCompositeSymbol\textsuperscript{\textturnrrtail}{"02B5} \DeclareUTFCompositeSymbol\textsuperscript{\textinvscr}{"02B6} \DeclareUTFCompositeSymbol\textsuperscript{w}{"02B7} \DeclareUTFCompositeSymbol\textsuperscript{y}{"02B8} \DeclareUTFCompositeSymbol\textsuperscript{\textbabygamma}{"02E0} \DeclareUTFCompositeSymbol\textsuperscript{\textgammalatinsmall}{"02E0} \DeclareUTFCompositeSymbol\textsuperscript{l}{"02E1} \DeclareUTFCompositeSymbol\textsuperscript{s}{"02E2} \DeclareUTFCompositeSymbol\textsuperscript{x}{"02E3} \DeclareUTFCompositeSymbol\textsuperscript{\textrevglotstop}{"02E4} \DeclareUTFCompositeSymbol\textsuperscript{\textrevepsilon}{"1D4C} \DeclareUTFCompositeSymbol\textsuperscript{\cyrn}{"1D78} \DeclareUTFCompositeSymbol\textsuperscript{\textbarsci}{"1DA7} \DeclareUTFCompositeSymbol\textsuperscript{V}{"2C7D} \DeclareUTFCompositeSymbol\textsuperscript{\textHbar}{"A7F8} \DeclareUTFCompositeSymbol\textsuperscript{\textHslash}{"A7F8} \DeclareUTFCompositeSymbol\textsuperscript{\oe}{"A7F9} \DeclareUTFCompositeSymbol\textsubscript{h}{"2095} \DeclareUTFCompositeSymbol\textsubscript{k}{"2096} \DeclareUTFCompositeSymbol\textsubscript{l}{"2097} \DeclareUTFCompositeSymbol\textsubscript{m}{"2098} \DeclareUTFCompositeSymbol\textsubscript{n}{"2099} \DeclareUTFCompositeSymbol\textsubscript{p}{"209A} \DeclareUTFCompositeSymbol\textsubscript{s}{"209B} \DeclareUTFCompositeSymbol\textsubscript{t}{"209C} % \end{macrocode} % % \changes{v3.2.9}{2013/12/07} % {增加 \file{xunicode-extra.def} 中,用于加入 \file{puenc.def} 中的符号定义。} % % 以下定义取自 \pkg{hyperref} 的 \file{puenc.def}。 % \begin{macrocode} \DeclareUTFEncodedAccent\textinvbreve{"0311}{"0311} \DeclareUTFEncodedSymbol\textsubbreve{"032E}{"203F} \DeclareUTFSymbol\textHT{"0009} \DeclareUTFSymbol\textLF{"000A} \DeclareUTFSymbol\textCR{"000D} \DeclareUTFSymbol\textnumbersign{"0023} \DeclareUTFSymbol\textparenleft{"0028} \DeclareUTFSymbol\textparenright{"0029} \DeclareUTFSymbol\textMVPlus{"002B} \DeclareUTFSymbol\textMVComma{"002C} \DeclareUTFSymbol\textMVMinus{"002D} \DeclareUTFSymbol\textMVPeriod{"002E} \DeclareUTFSymbol\textMVDivision{"002F} \DeclareUTFSymbol\textMVZero{"0030} \DeclareUTFSymbol\textMVOne{"0031} \DeclareUTFSymbol\textMVTwo{"0032} \DeclareUTFSymbol\textMVThree{"0033} \DeclareUTFSymbol\textMVFour{"0034} \DeclareUTFSymbol\textMVFive{"0035} \DeclareUTFSymbol\textMVSix{"0036} \DeclareUTFSymbol\textMVSeven{"0037} \DeclareUTFSymbol\textMVEight{"0038} \DeclareUTFSymbol\textMVNine{"0039} \DeclareUTFSymbol\textMVAt{"0040} \DeclareUTFCompositeCommand\.{\i}{i} \DeclareUTFCompositeCommand\.{i}{i} \DeclareUTFSymbol\textlnot{"00AC} \DeclareUTFSymbol\textplusminus{"00B1} \DeclareUTFSymbol\textcedilla{"00B8} \DeclareUTFSymbol\textmultiply{"00D7} \DeclareUTFSymbol\textThorn{"00DE} \DeclareUTFSymbol\textdivide{"00F7} \DeclareUTFSymbol\textHslash{"0126} \DeclareUTFCompositeSymbol\k{\i}{"012F} \DeclareUTFCompositeSymbol\.{L}{"013F} \DeclareUTFCompositeSymbol\.{l}{"0140} \DeclareUTFSymbol\textnapostrophe{"0149} \DeclareUTFSymbol\textTslash{"0166} \DeclareUTFSymbol\texttslash{"0167} \DeclareUTFSymbol\textlongs{"017F} \DeclareUTFSymbol\texthausaB{"0181} \DeclareUTFSymbol\texthausaD{"018A} \DeclareUTFSymbol\textrevE{"018E} \DeclareUTFSymbol\texthausaK{"0198} \DeclareUTFSymbol\textPUnrleg{"019E} \DeclareUTFSymbol\textinve{"01DD} \DeclareUTFSymbol\textGslash{"01E4} \DeclareUTFSymbol\textgslash{"01E5} \DeclareUTFCompositeSymbol\textinvbreve{E}{"0206} \DeclareUTFCompositeSymbol\textinvbreve{e}{"0207} \DeclareUTFCompositeSymbol\textinvbreve{I}{"020A} \DeclareUTFCompositeSymbol\textinvbreve{i}{"020B} \DeclareUTFCompositeSymbol\textinvbreve{\i}{"020B} \DeclareUTFCompositeSymbol\textinvbreve{O}{"020E} \DeclareUTFCompositeSymbol\textinvbreve{o}{"020F} \DeclareUTFCompositeSymbol\textinvbreve{U}{"0216} \DeclareUTFCompositeSymbol\textinvbreve{u}{"0217} \DeclareUTFSymbol\j{"0237} \DeclareUTFSymbol\textPUdblig{"0238} \DeclareUTFSymbol\textPUqplig{"0239} \DeclareUTFSymbol\textslashc{"023C} \DeclareUTFSymbol\textniepsilon{"025B} \DeclareUTFSymbol\textipagamma{"0263} \DeclareUTFSymbol\textniiota{"0269} \DeclareUTFSymbol\textniphi{"0278} \DeclareUTFSymbol\textniupsilon{"028A} \DeclareUTFSymbol\textring{"02DA} \DeclareUTFSymbol\texttilde{"02DC} \DeclareUTFSymbol\texthungarumlaut{"02DD} \DeclareUTFSymbol\textringlow{"02F3} \DeclareUTFSymbol\texttildelow{"02F7} \DeclareUTFCommand\textnewtie{\textinvbreve\ } \DeclareUTFCommand\textdotbelow{\d\ } \DeclareUTFSymbol\textmacronbelow{"02CD} \DeclareUTFCommand\texttie{\t\ } \DeclareUTFSymbol\textnumeralsigngreek{"0374} \DeclareUTFSymbol\textnumeralsignlowergreek{"0375} \DeclareUTFCompositeSymbol\'{\textAlpha}{"0386} \DeclareUTFCompositeSymbol\'{\textEpsilon}{"0388} \DeclareUTFCompositeSymbol\'{\textEta}{"0389} \DeclareUTFCompositeSymbol\'{\textIota}{"038A} \DeclareUTFCompositeSymbol\'{\textOmicron}{"038C} \DeclareUTFCompositeSymbol\'{\textUpsilon}{"038E} \DeclareUTFCompositeSymbol\'{\textOmega}{"038F} \DeclareUTFCompositeSymbol\'{\textIotadieresis}{"0390} \DeclareUTFSymbol\textIotadieresis{"03AA} \DeclareUTFCompositeSymbol\"{\textIota}{"03AA} \DeclareUTFCompositeSymbol\"{\textUpsilon}{"03AB} \DeclareUTFCompositeSymbol\'{\textalpha}{"03AC} \DeclareUTFCompositeSymbol\'{\textepsilon}{"03AD} \DeclareUTFCompositeSymbol\'{\texteta}{"03AE} \DeclareUTFCompositeSymbol\'{\textiota}{"03AF} \DeclareUTFCompositeSymbol\"{\textupsilonacute}{"03B0} \DeclareUTFSymbol\textmugreek{"03BC} \DeclareUTFSymbol\textvarsigma{"03C2} \DeclareUTFCompositeSymbol\"{\textiota}{"03CA} \DeclareUTFCompositeSymbol\"{\textupsilon}{"03CB} \DeclareUTFCompositeSymbol\'{\textomicron}{"03CC} \DeclareUTFSymbol\textupsilonacute{"03CD} \DeclareUTFCompositeSymbol\'{\textupsilon}{"03CD} \DeclareUTFCompositeSymbol\'{\textomega}{"03CE} \DeclareUTFSymbol\textStigmagreek{"03DA} \DeclareUTFSymbol\textstigmagreek{"03DB} \DeclareUTFSymbol\textDigammagreek{"03DC} \DeclareUTFSymbol\textdigammagreek{"03DD} \DeclareUTFSymbol\textKoppagreek{"03DE} \DeclareUTFSymbol\textkoppagreek{"03DF} \DeclareUTFSymbol\textSampigreek{"03E0} \DeclareUTFSymbol\textsampigreek{"03E1} \DeclareUTFSymbol\textbackepsilon{"03F6} \DeclareUTFCompositeSymbol\`{\CYRE}{"0400} \DeclareUTFSymbol\CYRYO{"0401} \DeclareUTFCompositeSymbol\"{\CYRE}{"0401} \DeclareUTFSymbol\CYRDJE{"0402} \DeclareUTFCompositeSymbol\'{\CYRG}{"0403} \DeclareUTFSymbol\CYRIE{"0404} \DeclareUTFSymbol\CYRDZE{"0405} \DeclareUTFSymbol\CYRII{"0406} \DeclareUTFSymbol\CYRYI{"0407} \DeclareUTFCompositeSymbol\"{\CYRII}{"0407} \DeclareUTFSymbol\CYRJE{"0408} \DeclareUTFSymbol\CYRLJE{"0409} \DeclareUTFSymbol\CYRNJE{"040A} \DeclareUTFSymbol\CYRTSHE{"040B} \DeclareUTFCompositeSymbol\'{\CYRK}{"040C} \DeclareUTFCompositeSymbol\`{\CYRI}{"040D} \DeclareUTFSymbol\CYRUSHRT{"040E} \DeclareUTFCompositeSymbol\U{\CYRU}{"040E} \DeclareUTFSymbol\CYRDZHE{"040F} \DeclareUTFSymbol\CYRA{"0410} \DeclareUTFSymbol\CYRB{"0411} \DeclareUTFSymbol\CYRV{"0412} \DeclareUTFSymbol\CYRG{"0413} \DeclareUTFSymbol\CYRD{"0414} \DeclareUTFSymbol\CYRE{"0415} \DeclareUTFSymbol\CYRZH{"0416} \DeclareUTFSymbol\CYRZ{"0417} \DeclareUTFSymbol\CYRI{"0418} \DeclareUTFSymbol\CYRISHRT{"0419} \DeclareUTFCompositeSymbol\U{\CYRI}{"0419} \DeclareUTFSymbol\CYRK{"041A} \DeclareUTFSymbol\CYRL{"041B} \DeclareUTFSymbol\CYRM{"041C} \DeclareUTFSymbol\CYRN{"041D} \DeclareUTFSymbol\CYRO{"041E} \DeclareUTFSymbol\CYRP{"041F} \DeclareUTFSymbol\CYRR{"0420} \DeclareUTFSymbol\CYRS{"0421} \DeclareUTFSymbol\CYRT{"0422} \DeclareUTFSymbol\CYRU{"0423} \DeclareUTFSymbol\CYRF{"0424} \DeclareUTFSymbol\CYRH{"0425} \DeclareUTFSymbol\CYRC{"0426} \DeclareUTFSymbol\CYRCH{"0427} \DeclareUTFSymbol\CYRSH{"0428} \DeclareUTFSymbol\CYRSHCH{"0429} \DeclareUTFSymbol\CYRHRDSN{"042A} \DeclareUTFSymbol\CYRERY{"042B} \DeclareUTFSymbol\CYRSFTSN{"042C} \DeclareUTFSymbol\CYREREV{"042D} \DeclareUTFSymbol\CYRYU{"042E} \DeclareUTFSymbol\CYRYA{"042F} \DeclareUTFSymbol\cyra{"0430} \DeclareUTFSymbol\cyrb{"0431} \DeclareUTFSymbol\cyrv{"0432} \DeclareUTFSymbol\cyrg{"0433} \DeclareUTFSymbol\cyrd{"0434} \DeclareUTFSymbol\cyre{"0435} \DeclareUTFSymbol\cyrzh{"0436} \DeclareUTFSymbol\cyrz{"0437} \DeclareUTFSymbol\cyri{"0438} \DeclareUTFSymbol\cyrishrt{"0439} \DeclareUTFCompositeSymbol\U{\cyri}{"0439} \DeclareUTFSymbol\cyrk{"043A} \DeclareUTFSymbol\cyrl{"043B} \DeclareUTFSymbol\cyrm{"043C} \DeclareUTFSymbol\cyrn{"043D} \DeclareUTFSymbol\cyro{"043E} \DeclareUTFSymbol\cyrp{"043F} \DeclareUTFSymbol\cyrr{"0440} \DeclareUTFSymbol\cyrs{"0441} \DeclareUTFSymbol\cyrt{"0442} \DeclareUTFSymbol\cyru{"0443} \DeclareUTFSymbol\cyrf{"0444} \DeclareUTFSymbol\cyrh{"0445} \DeclareUTFSymbol\cyrc{"0446} \DeclareUTFSymbol\cyrch{"0447} \DeclareUTFSymbol\cyrsh{"0448} \DeclareUTFSymbol\cyrshch{"0449} \DeclareUTFSymbol\cyrhrdsn{"044A} \DeclareUTFSymbol\cyrery{"044B} \DeclareUTFSymbol\cyrsftsn{"044C} \DeclareUTFSymbol\cyrerev{"044D} \DeclareUTFSymbol\cyryu{"044E} \DeclareUTFSymbol\cyrya{"044F} \DeclareUTFCompositeSymbol\`{\cyre}{"0450} \DeclareUTFSymbol\cyryo{"0451} \DeclareUTFCompositeSymbol\"{\cyre}{"0451} \DeclareUTFSymbol\cyrdje{"0452} \DeclareUTFCompositeSymbol\'{\cyrg}{"0453} \DeclareUTFSymbol\cyrie{"0454} \DeclareUTFSymbol\cyrdze{"0455} \DeclareUTFSymbol\cyrii{"0456} \DeclareUTFSymbol\cyryi{"0457} \DeclareUTFCompositeSymbol\"{\cyrii}{"0457} \DeclareUTFSymbol\cyrje{"0458} \DeclareUTFSymbol\cyrlje{"0459} \DeclareUTFSymbol\cyrnje{"045A} \DeclareUTFSymbol\cyrtshe{"045B} \DeclareUTFCompositeSymbol\'{\cyrk}{"045C} \DeclareUTFCompositeSymbol\`{\cyri}{"045D} \DeclareUTFSymbol\cyrushrt{"045E} \DeclareUTFCompositeSymbol\U{\curu}{"045E} \DeclareUTFSymbol\cyrdzhe{"045F} \DeclareUTFSymbol\CYROMEGA{"0460} \DeclareUTFSymbol\cyromega{"0461} \DeclareUTFSymbol\CYRYAT{"0462} \DeclareUTFSymbol\cyryat{"0463} \DeclareUTFSymbol\CYRIOTE{"0464} \DeclareUTFSymbol\cyriote{"0465} \DeclareUTFSymbol\CYRLYUS{"0466} \DeclareUTFSymbol\cyrlyus{"0467} \DeclareUTFSymbol\CYRIOTLYUS{"0468} \DeclareUTFSymbol\cyriotlyus{"0469} \DeclareUTFSymbol\CYRBYUS{"046A} \DeclareUTFSymbol\cyrbyus{"046B} \DeclareUTFSymbol\CYRIOTBYUS{"046C} \DeclareUTFSymbol\cyriotbyus{"046D} \DeclareUTFSymbol\CYRKSI{"046E} \DeclareUTFSymbol\cyrksi{"046F} \DeclareUTFSymbol\CYRPSI{"0470} \DeclareUTFSymbol\cyrpsi{"0471} \DeclareUTFSymbol\CYRFITA{"0472} \DeclareUTFSymbol\cyrfita{"0473} \DeclareUTFSymbol\CYRIZH{"0474} \DeclareUTFSymbol\cyrizh{"0475} \DeclareUTFCompositeSymbol\C{\CYRIZH}{"0476} \DeclareUTFCompositeSymbol\C{\cyrizh}{"0477} \DeclareUTFSymbol\CYRUK{"0478} \DeclareUTFSymbol\cyruk{"0479} \DeclareUTFSymbol\CYROMEGARND{"047A} \DeclareUTFSymbol\cyromegarnd{"047B} \DeclareUTFSymbol\CYROMEGATITLO{"047C} \DeclareUTFSymbol\cyromegatitlo{"047D} \DeclareUTFSymbol\CYROT{"047E} \DeclareUTFSymbol\cyrot{"047F} \DeclareUTFSymbol\CYRKOPPA{"0480} \DeclareUTFSymbol\cyrkoppa{"0481} \DeclareUTFSymbol\cyrthousands{"0482} \DeclareUTFSymbol\CYRISHRTDSC{"048A} \DeclareUTFSymbol\cyrishrtdsc{"048B} \DeclareUTFSymbol\CYRSEMISFTSN{"048C} \DeclareUTFSymbol\cyrsemisftsn{"048D} \DeclareUTFSymbol\CYRRTICK{"048E} \DeclareUTFSymbol\cyrrtick{"048F} \DeclareUTFSymbol\CYRGUP{"0490} \DeclareUTFSymbol\cyrgup{"0491} \DeclareUTFSymbol\CYRGHCRS{"0492} \DeclareUTFSymbol\cyrghcrs{"0493} \DeclareUTFSymbol\CYRGHK{"0494} \DeclareUTFSymbol\cyrghk{"0495} \DeclareUTFSymbol\CYRZHDSC{"0496} \DeclareUTFSymbol\cyrzhdsc{"0497} \DeclareUTFSymbol\CYRZDSC{"0498} \DeclareUTFCompositeSymbol\c{\CYRZ}{"0498} \DeclareUTFSymbol\cyrzdsc{"0499} \DeclareUTFCompositeSymbol\c{\cyrz}{"0499} \DeclareUTFSymbol\CYRKDSC{"049A} \DeclareUTFSymbol\cyrkdsc{"049B} \DeclareUTFSymbol\CYRKVCRS{"049C} \DeclareUTFSymbol\cyrkvcrs{"049D} \DeclareUTFSymbol\CYRKHCRS{"049E} \DeclareUTFSymbol\cyrkhcrs{"049F} \DeclareUTFSymbol\CYRKBEAK{"04A0} \DeclareUTFSymbol\cyrkbeak{"04A1} \DeclareUTFSymbol\CYRNDSC{"04A2} \DeclareUTFSymbol\cyrndsc{"04A3} \DeclareUTFSymbol\CYRNG{"04A4} \DeclareUTFSymbol\cyrng{"04A5} \DeclareUTFSymbol\CYRPHK{"04A6} \DeclareUTFSymbol\cyrphk{"04A7} \DeclareUTFSymbol\CYRABHHA{"04A8} \DeclareUTFSymbol\cyrabhha{"04A9} \DeclareUTFSymbol\CYRSDSC{"04AA} \DeclareUTFCompositeSymbol\CYRSDSC{\CYRS}{"04AA} \DeclareUTFSymbol\cyrsdsc{"04AB} \DeclareUTFCompositeSymbol\k{\cyrs}{"04AB} \DeclareUTFSymbol\CYRTDSC{"04AC} \DeclareUTFSymbol\cyrtdsc{"04AD} \DeclareUTFSymbol\CYRY{"04AE} \DeclareUTFSymbol\cyry{"04AF} \DeclareUTFSymbol\CYRYHCRS{"04B0} \DeclareUTFSymbol\cyryhcrs{"04B1} \DeclareUTFSymbol\CYRHDSC{"04B2} \DeclareUTFSymbol\cyrhdsc{"04B3} \DeclareUTFSymbol\CYRTETSE{"04B4} \DeclareUTFSymbol\cyrtetse{"04B5} \DeclareUTFSymbol\CYRCHRDSC{"04B6} \DeclareUTFSymbol\cyrchrdsc{"04B7} \DeclareUTFSymbol\CYRCHVCRS{"04B8} \DeclareUTFSymbol\cyrchvcrs{"04B9} \DeclareUTFSymbol\CYRSHHA{"04BA} \DeclareUTFSymbol\cyrshha{"04BB} \DeclareUTFSymbol\CYRABHCH{"04BC} \DeclareUTFSymbol\cyrabhch{"04BD} \DeclareUTFSymbol\CYRABHCHDSC{"04BE} \DeclareUTFCompositeSymbol\k{\CYRABHCH}{"04BE} \DeclareUTFSymbol\cyrabhchdsc{"04BF} \DeclareUTFCompositeSymbol\k{\cyrabhch}{"04BF} \DeclareUTFSymbol\CYRpalochka{"04C0} \DeclareUTFCompositeSymbol\U{\CYRZH}{"04C1} \DeclareUTFCompositeSymbol\U{\cyrzh}{"04C2} \DeclareUTFSymbol\CYRKHK{"04C3} \DeclareUTFSymbol\cyrkhk{"04C4} \DeclareUTFSymbol\CYRLDSC{"04C5} \DeclareUTFSymbol\cyrldsc{"04C6} \DeclareUTFSymbol\CYRNHK{"04C7} \DeclareUTFSymbol\cyrnhk{"04C8} \DeclareUTFSymbol\CYRCHLDSC{"04CB} \DeclareUTFSymbol\cyrchldsc{"04CC} \DeclareUTFSymbol\CYRMDSC{"04CD} \DeclareUTFSymbol\cyrmdsc{"04CE} \DeclareUTFCompositeSymbol\U{\CYRA}{"04D0} \DeclareUTFCompositeSymbol\U{\cyra}{"04D1} \DeclareUTFCompositeSymbol\"{\CYRA}{"04D2} \DeclareUTFCompositeSymbol\"{\cyra}{"04D3} \DeclareUTFSymbol\CYRAE{"04D4} \DeclareUTFSymbol\cyrae{"04D5} \DeclareUTFCompositeSymbol\U{\CYRE}{"04D6} \DeclareUTFCompositeSymbol\U{\cyre}{"04D7} \DeclareUTFSymbol\CYRSCHWA{"04D8} \DeclareUTFSymbol\cyrschwa{"04D9} \DeclareUTFCompositeSymbol\"{\CYRSCHWA}{"04DA} \DeclareUTFCompositeSymbol\"{\cyrschwa}{"04DB} \DeclareUTFCompositeSymbol\"{\CYRZH}{"04DC} \DeclareUTFCompositeSymbol\"{\cyrzh}{"04DD} \DeclareUTFCompositeSymbol\"{\CYRZ}{"04DE} \DeclareUTFCompositeSymbol\"{\cyrz}{"04DF} \DeclareUTFSymbol\CYRABHDZE{"04E0} \DeclareUTFSymbol\cyrabhdze{"04E1} \DeclareUTFCompositeSymbol\={\CYRI}{"04E2} \DeclareUTFCompositeSymbol\={\cyri}{"04E3} \DeclareUTFCompositeSymbol\"{\CYRI}{"04E4} \DeclareUTFCompositeSymbol\"{\cyri}{"04E5} \DeclareUTFCompositeSymbol\"{\CYRO}{"04E6} \DeclareUTFCompositeSymbol\"{\cyro}{"04E7} \DeclareUTFSymbol\CYROTLD{"04E8} \DeclareUTFSymbol\cyrotld{"04E9} \DeclareUTFCompositeSymbol\"{\CYROTLD}{"04EA} \DeclareUTFCompositeSymbol\"{\cyrotld}{"04EB} \DeclareUTFCompositeSymbol\"{\CYREREV}{"04EC} \DeclareUTFCompositeSymbol\"{\cyreref}{"04ED} \DeclareUTFCompositeSymbol\={\CYRU}{"04EE} \DeclareUTFCompositeSymbol\={\cyru}{"04EF} \DeclareUTFCompositeSymbol\"{\CYRU}{"04F0} \DeclareUTFCompositeSymbol\"{\cyru}{"04F1} \DeclareUTFCompositeSymbol\H{\CYRU}{"04F2} \DeclareUTFCompositeSymbol\H{\cyru}{"04F3} \DeclareUTFCompositeSymbol\"{\CYRCH}{"04F4} \DeclareUTFCompositeSymbol\"{\cyrch}{"04F5} \DeclareUTFSymbol\CYRGDSC{"04F6} \DeclareUTFSymbol\cyrgdsc{"04F7} \DeclareUTFCompositeSymbol\"{\CYRERY}{"04F8} \DeclareUTFCompositeSymbol\"{\cyrery}{"04F9} \DeclareUTFSymbol\CYRHHK{"04FC} \DeclareUTFSymbol\cyrhhk{"04FD} \DeclareUTFSymbol\sofpasuq{"05C3} \DeclareUTFSymbol\hebalef{"05D0} \DeclareUTFSymbol\hebbet{"05D1} \DeclareUTFSymbol\hebgimel{"05D2} \DeclareUTFSymbol\hebdalet{"05D3} \DeclareUTFSymbol\hebhe{"05D4} \DeclareUTFSymbol\hebvav{"05D5} \DeclareUTFSymbol\hebzayin{"05D6} \DeclareUTFSymbol\hebhet{"05D7} \DeclareUTFSymbol\hebtet{"05D8} \DeclareUTFSymbol\hebyod{"05D9} \DeclareUTFSymbol\hebfinalkaf{"05DA} \DeclareUTFSymbol\hebkaf{"05DB} \DeclareUTFSymbol\heblamed{"05DC} \DeclareUTFSymbol\hebfinalmem{"05DD} \DeclareUTFSymbol\hebmem{"05DE} \DeclareUTFSymbol\hebfinalnun{"05DF} \DeclareUTFSymbol\hebnun{"05E0} \DeclareUTFSymbol\hebsamekh{"05E1} \DeclareUTFSymbol\hebayin{"05E2} \DeclareUTFSymbol\hebfinalpe{"05E3} \DeclareUTFSymbol\hebpe{"05E4} \DeclareUTFSymbol\hebfinaltsadi{"05E5} \DeclareUTFSymbol\hebtsadi{"05E6} \DeclareUTFSymbol\hebqof{"05E7} \DeclareUTFSymbol\hebresh{"05E8} \DeclareUTFSymbol\hebshin{"05E9} \DeclareUTFSymbol\hebtav{"05EA} \DeclareUTFSymbol\doublevav{"05F0} \DeclareUTFSymbol\vavyod{"05F1} \DeclareUTFSymbol\doubleyod{"05F2} \DeclareUTFSymbol\textscd{"1D05} \DeclareUTFSymbol\textPUsck{"1D0B} \DeclareUTFSymbol\textPUscm{"1D0D} \DeclareUTFSymbol\textPUscp{"1D18} \DeclareUTFSymbol\textPUrevscr{"1D19} \DeclareUTFSymbol\textiinferior{"1D62} \DeclareUTFSymbol\textrinferior{"1D63} \DeclareUTFSymbol\textuinferior{"1D64} \DeclareUTFSymbol\textvinferior{"1D65} \DeclareUTFSymbol\textbetainferior{"1D66} \DeclareUTFSymbol\textgammainferior{"1D67} \DeclareUTFSymbol\textrhoinferior{"1D68} \DeclareUTFSymbol\textphiinferior{"1D69} \DeclareUTFSymbol\textchiinferior{"1D6A} \DeclareUTFSymbol\textbarsci{"1D7B} \DeclareUTFSymbol\textbarp{"1D7D} \DeclareUTFSymbol\textbarscu{"1D7E} \DeclareUTFSymbol\textPUrhooka{"1D8F} \DeclareUTFSymbol\textPUrhooke{"1D92} \DeclareUTFSymbol\textPUrhookepsilon{"1D93} \DeclareUTFSymbol\textPUrhookopeno{"1D97} \DeclareUTFCompositeSymbol\textsubbreve{H}{"1E2A} \DeclareUTFCompositeSymbol\textsubbreve{h}{"1E2B} \DeclareUTFCompositeSymbol\.{\textlongs}{"1E9B} \DeclareUTFSymbol\textcompwordmark{"200C} \DeclareUTFSymbol\texthdotfor{"2025} \DeclareUTFSymbol\textprime{"2032} \DeclareUTFSymbol\textsecond{"2033} \DeclareUTFSymbol\textthird{"2034} \DeclareUTFSymbol\textbackprime{"2035} \DeclareUTFSymbol\textlefttherefore{"2056} \DeclareUTFSymbol\textfourth{"2057} \DeclareUTFSymbol\textdiamonddots{"2058} \DeclareUTFSymbol\textzerosuperior{"2070} \DeclareUTFSymbol\textisuperior{"2071} \DeclareUTFSymbol\textfoursuperior{"2074} \DeclareUTFSymbol\textfivesuperior{"2075} \DeclareUTFSymbol\textsixsuperior{"2076} \DeclareUTFSymbol\textsevensuperior{"2077} \DeclareUTFSymbol\texteightsuperior{"2078} \DeclareUTFSymbol\textninesuperior{"2079} \DeclareUTFSymbol\textplussuperior{"207A} \DeclareUTFSymbol\textminussuperior{"207B} \DeclareUTFSymbol\textequalsuperior{"207C} \DeclareUTFSymbol\textparenleftsuperior{"207D} \DeclareUTFSymbol\textparenrightsuperior{"207E} \DeclareUTFSymbol\textnsuperior{"207F} \DeclareUTFSymbol\textzeroinferior{"2080} \DeclareUTFSymbol\textoneinferior{"2081} \DeclareUTFSymbol\texttwoinferior{"2082} \DeclareUTFSymbol\textthreeinferior{"2083} \DeclareUTFSymbol\textfourinferior{"2084} \DeclareUTFSymbol\textfiveinferior{"2085} \DeclareUTFSymbol\textsixinferior{"2086} \DeclareUTFSymbol\textseveninferior{"2087} \DeclareUTFSymbol\texteightinferior{"2088} \DeclareUTFSymbol\textnineinferior{"2089} \DeclareUTFSymbol\textplusinferior{"208A} \DeclareUTFSymbol\textminusinferior{"208B} \DeclareUTFSymbol\textequalsinferior{"208C} \DeclareUTFSymbol\textparenleftinferior{"208D} \DeclareUTFSymbol\textparenrightinferior{"208E} \DeclareUTFSymbol\textainferior{"2090} \DeclareUTFSymbol\texteinferior{"2091} \DeclareUTFSymbol\textoinferior{"2092} \DeclareUTFSymbol\textxinferior{"2093} \DeclareUTFSymbol\textschwainferior{"2094} \DeclareUTFSymbol\texthinferior{"2095} \DeclareUTFSymbol\textkinferior{"2096} \DeclareUTFSymbol\textlinferior{"2097} \DeclareUTFSymbol\textminferior{"2098} \DeclareUTFSymbol\textninferior{"2099} \DeclareUTFSymbol\textpinferior{"209A} \DeclareUTFSymbol\textsinferior{"209B} \DeclareUTFSymbol\texttinferior{"209C} \DeclareUTFSymbol\textpeseta{"20A7} \DeclareUTFSymbol\textDeleatur{"20B0} \DeclareUTFSymbol\textguarani{"20B2} \DeclareUTFSymbol\texthslash{"210F} \DeclareUTFSymbol\textIm{"2111} \DeclareUTFSymbol\textell{"2113} \DeclareUTFSymbol\textwp{"2118} \DeclareUTFSymbol\textRe{"211C} \DeclareUTFSymbol\textriota{"2129} \DeclareUTFSymbol\textangstrom{"212B} \DeclareUTFSymbol\textfax{"213B} \DeclareUTFSymbol\textinvamp{"214B} \DeclareUTFSymbol\textoneseventh{"2150} \DeclareUTFSymbol\textoneninth{"2151} \DeclareUTFSymbol\textonetenth{"2152} \DeclareUTFSymbol\textonethird{"2153} \DeclareUTFSymbol\texttwothirds{"2154} \DeclareUTFSymbol\textonefifth{"2155} \DeclareUTFSymbol\texttwofifths{"2156} \DeclareUTFSymbol\textthreefifths{"2157} \DeclareUTFSymbol\textfourfifths{"2158} \DeclareUTFSymbol\textonesixth{"2159} \DeclareUTFSymbol\textfivesixths{"215A} \DeclareUTFSymbol\textoneeighth{"215B} \DeclareUTFSymbol\textthreeeighths{"215C} \DeclareUTFSymbol\textfiveeighths{"215D} \DeclareUTFSymbol\textseveneighths{"215E} \DeclareUTFSymbol\textrevc{"2184} \DeclareUTFSymbol\textzerothirds{"2189} \DeclareUTFSymbol\textnleftarrow{"219A} \DeclareUTFSymbol\textnrightarrow{"219B} \DeclareUTFSymbol\texttwoheadleftarrow{"219E} \DeclareUTFCommand\textntwoheadleftarrow{\textlstrikethru\texttwoheadleftarrow} \DeclareUTFSymbol\texttwoheaduparrow{"219F} \DeclareUTFSymbol\texttwoheadrightarrow{"21A0} \DeclareUTFCommand\textntwoheadrightarrow{\textlstrikethru\texttwoheadrightarrow} \DeclareUTFSymbol\texttwoheaddownarrow{"21A1} \DeclareUTFSymbol\textleftarrowtail{"21A2} \DeclareUTFSymbol\textrightarrowtail{"21A3} \DeclareUTFSymbol\textmapsto{"21A6} \DeclareUTFSymbol\texthookleftarrow{"21A9} \DeclareUTFSymbol\texthookrightarrow{"21AA} \DeclareUTFSymbol\textlooparrowleft{"21AB} \DeclareUTFSymbol\textlooparrowright{"21AC} \DeclareUTFSymbol\textnleftrightarrow{"21AE} \DeclareUTFSymbol\textlightning{"21AF} \DeclareUTFSymbol\textdlsh{"21B5} \DeclareUTFSymbol\textcurvearrowleft{"21B6} \DeclareUTFSymbol\textcurvearrowright{"21B7} \DeclareUTFSymbol\textleftharpoonup{"21BC} \DeclareUTFSymbol\textleftharpoondown{"21BD} \DeclareUTFSymbol\textupharpoonright{"21BE} \DeclareUTFSymbol\textupharpoonleft{"21BF} \DeclareUTFSymbol\textrightharpoonup{"21C0} \DeclareUTFSymbol\textrightharpoondown{"21C1} \DeclareUTFSymbol\textdownharpoonright{"21C2} \DeclareUTFSymbol\textdownharpoonleft{"21C3} \DeclareUTFSymbol\textrightleftarrows{"21C4} \DeclareUTFSymbol\textupdownarrows{"21C5} \DeclareUTFSymbol\textleftrightarrows{"21C6} \DeclareUTFSymbol\textleftleftarrows{"21C7} \DeclareUTFSymbol\textupuparrows{"21C8} \DeclareUTFSymbol\textrightrightarrows{"21C9} \DeclareUTFSymbol\textdowndownarrows{"21CA} \DeclareUTFSymbol\textleftrightharpoons{"21CB} \DeclareUTFSymbol\textrightleftharpoons{"21CC} \DeclareUTFSymbol\textnLeftarrow{"21CD} \DeclareUTFSymbol\textnLeftrightarrow{"21CE} \DeclareUTFSymbol\textnRightarrow{"21CF} \DeclareUTFSymbol\textLeftarrow{"21D0} \DeclareUTFSymbol\textUparrow{"21D1} \DeclareUTFSymbol\textRightarrow{"21D2} \DeclareUTFSymbol\textDownarrow{"21D3} \DeclareUTFSymbol\textLeftrightarrow{"21D4} \DeclareUTFSymbol\textUpdownarrow{"21D5} \DeclareUTFSymbol\textNwarrow{"21D6} \DeclareUTFSymbol\textNearrow{"21D7} \DeclareUTFSymbol\textSearrow{"21D8} \DeclareUTFSymbol\textSwarrow{"21D9} \DeclareUTFSymbol\textLleftarrow{"21DA} \DeclareUTFSymbol\textRrightarrow{"21DB} \DeclareUTFSymbol\textleftsquigarrow{"21DC} \DeclareUTFSymbol\textrightsquigarrow{"21DD} \DeclareUTFSymbol\textdashleftarrow{"21E0} \DeclareUTFSymbol\textdasheduparrow{"21E1} \DeclareUTFSymbol\textdashrightarrow{"21E2} \DeclareUTFSymbol\textdasheddownarrow{"21E3} \DeclareUTFSymbol\textpointer{"21E8} \DeclareUTFSymbol\textdownuparrows{"21F5} \DeclareUTFSymbol\textleftarrowtriangle{"21FD} \DeclareUTFSymbol\textrightarrowtriangle{"21FE} \DeclareUTFSymbol\textleftrightarrowtriangle{"21FF} \DeclareUTFSymbol\textforall{"2200} \DeclareUTFSymbol\textcomplement{"2201} \DeclareUTFSymbol\textpartial{"2202} \DeclareUTFSymbol\textexists{"2203} \DeclareUTFSymbol\textnexists{"2204} \DeclareUTFSymbol\textemptyset{"2205} \DeclareUTFSymbol\texttriangle{"2206} \DeclareUTFSymbol\textnabla{"2207} \DeclareUTFSymbol\textin{"2208} \DeclareUTFSymbol\textnotin{"2209} \DeclareUTFSymbol\textsmallin{"220A} \DeclareUTFSymbol\textni{"220B} \DeclareUTFSymbol\textnotowner{"220C} \DeclareUTFSymbol\textsmallowns{"220D} \DeclareUTFSymbol\textprod{"220F} \DeclareUTFSymbol\textamalg{"2210} \DeclareUTFSymbol\textsum{"2211} \DeclareUTFSymbol\textmp{"2213} \DeclareUTFSymbol\textdotplus{"2214} \DeclareUTFSymbol\textDivides{"2215} \DeclareUTFSymbol\textsetminus{"2216} \DeclareUTFSymbol\textast{"2217} \DeclareUTFSymbol\textcirc{"2218} \DeclareUTFSymbol\textbulletoperator{"2219} \DeclareUTFSymbol\textpropto{"221D} \DeclareUTFSymbol\textinfty{"221E} \DeclareUTFSymbol\textangle{"2220} \DeclareUTFSymbol\textmeasuredangle{"2221} \DeclareUTFSymbol\textsphericalangle{"2222} \DeclareUTFSymbol\textmid{"2223} \DeclareUTFSymbol\textnmid{"2224} \DeclareUTFSymbol\textparallel{"2225} \DeclareUTFSymbol\textnparallel{"2226} \DeclareUTFSymbol\textwedge{"2227} \DeclareUTFCommand\textowedge{\textcircled\textwedge} \DeclareUTFSymbol\textvee{"2228} \DeclareUTFCommand\textovee{\textcircled\textvee} \DeclareUTFSymbol\textcap{"2229} \DeclareUTFSymbol\textcup{"222A} \DeclareUTFSymbol\textint{"222B} \DeclareUTFSymbol\textiint{"222C} \DeclareUTFSymbol\textiiint{"222D} \DeclareUTFSymbol\textoint{"222E} \DeclareUTFSymbol\textoiint{"222F} \DeclareUTFSymbol\textointclockwise{"2232} \DeclareUTFSymbol\textointctrclockwise{"2233} \DeclareUTFSymbol\texttherefore{"2234} \DeclareUTFSymbol\textbecause{"2235} \DeclareUTFSymbol\textvdotdot{"2236} \DeclareUTFSymbol\textsquaredots{"2237} \DeclareUTFSymbol\textdotminus{"2238} \DeclareUTFSymbol\texteqcolon{"2239} \DeclareUTFSymbol\textsim{"223C} \DeclareUTFSymbol\textbacksim{"223D} \DeclareUTFCommand\textnbacksim{\textlstrikethru\textnbacksim} \DeclareUTFSymbol\textwr{"2240} \DeclareUTFSymbol\textnsim{"2241} \DeclareUTFSymbol\texteqsim{"2242} \DeclareUTFCommand\textneqsim{\textlstrikethru\texteqsim} \DeclareUTFSymbol\textsimeq{"2243} \DeclareUTFSymbol\textnsimeq{"2244} \DeclareUTFSymbol\textcong{"2245} \DeclareUTFSymbol\textncong{"2247} \DeclareUTFSymbol\textapprox{"2248} \DeclareUTFSymbol\textnapprox{"2249} \DeclareUTFSymbol\textapproxeq{"224A} \DeclareUTFCommand\textnapproxeq{\textlstrikethru\textapproxeq} \DeclareUTFSymbol\texttriplesim{"224B} \DeclareUTFCommand\textntriplesim{\textlstrikethru\texttriplesim} \DeclareUTFSymbol\textbackcong{"224C} \DeclareUTFCommand\textnbackcong{\textlstrikethru\textbackcong} \DeclareUTFSymbol\textasymp{"224D} \DeclareUTFCommand\textnasymp{\textlstrikethru\textasymp} \DeclareUTFSymbol\textBumpeq{"224E} \DeclareUTFCommand\textnBumpeq{\textlstrikethru\textBumpeq} \DeclareUTFSymbol\textbumpeq{"224F} \DeclareUTFCommand\textnbumpeq{\textlstrikethru\textbumpeq} \DeclareUTFSymbol\textdoteq{"2250} \DeclareUTFCommand\textndoteq{\textlstrikethru\textdoteq} \DeclareUTFSymbol\textdoteqdot{"2251} \DeclareUTFCommand\textnDoteq{\textlstrikethru\textdoteqdot} \DeclareUTFSymbol\textfallingdoteq{"2252} \DeclareUTFCommand\textnfallingdoteq{\textlstrikethru\textfallingdoteq} \DeclareUTFSymbol\textrisingdoteq{"2253} \DeclareUTFCommand\textnrisingdoteq{\textlstrikethru\textrisingdoteq} \DeclareUTFSymbol\textcolonequals{"2254} \DeclareUTFSymbol\textequalscolon{"2255} \DeclareUTFSymbol\texteqcirc{"2256} \DeclareUTFCommand\textneqcirc{\textlstrikethru\texteqcirc} \DeclareUTFSymbol\textcirceq{"2257} \DeclareUTFCommand\textncirceq{\textlstrikethru\textcirceq} \DeclareUTFSymbol\texthateq{"2259} \DeclareUTFCommand\textnhateq{\textlstrikethru\texthateq} \DeclareUTFSymbol\texttriangleeq{"225C} \DeclareUTFSymbol\textneq{"2260} \DeclareUTFSymbol\textne{"2260} \DeclareUTFSymbol\textequiv{"2261} \DeclareUTFSymbol\textnequiv{"2262} \DeclareUTFSymbol\textleq{"2264} \DeclareUTFSymbol\textle{"2264} \DeclareUTFSymbol\textgeq{"2265} \DeclareUTFSymbol\textge{"2265} \DeclareUTFSymbol\textleqq{"2266} \DeclareUTFCommand\textnleqq{\textlstrikethru\textleqq} \DeclareUTFSymbol\textgeqq{"2267} \DeclareUTFCommand\textngeqq{\textlstrikethru\textgeqq} \DeclareUTFSymbol\textlneqq{"2268} \DeclareUTFSymbol\textgneqq{"2269} \DeclareUTFSymbol\textll{"226A} \DeclareUTFCommand\textnll{\textlstrikethru\textll} \DeclareUTFSymbol\textgg{"226B} \DeclareUTFCommand\textngg{\textlstrikethru\textgg} \DeclareUTFSymbol\textbetween{"226C} \DeclareUTFSymbol\textnless{"226E} \DeclareUTFSymbol\textngtr{"226F} \DeclareUTFSymbol\textnleq{"2270} \DeclareUTFSymbol\textngeq{"2271} \DeclareUTFSymbol\textlesssim{"2272} \DeclareUTFSymbol\textgtrsim{"2273} \DeclareUTFSymbol\textnlesssim{"2274} \DeclareUTFSymbol\textngtrsim{"2275} \DeclareUTFSymbol\textlessgtr{"2276} \DeclareUTFSymbol\textgtrless{"2277} \DeclareUTFSymbol\textngtrless{"2278} \DeclareUTFSymbol\textnlessgtr{"2279} \DeclareUTFSymbol\textprec{"227A} \DeclareUTFSymbol\textsucc{"227B} \DeclareUTFSymbol\textpreccurlyeq{"227C} \DeclareUTFSymbol\textsucccurlyeq{"227D} \DeclareUTFSymbol\textprecsim{"227E} \DeclareUTFCommand\textnprecsim{\textlstrikethru\textprecsim} \DeclareUTFSymbol\textsuccsim{"227F} \DeclareUTFCommand\textnsuccsim{\textlstrikethru\textsuccsim} \DeclareUTFSymbol\textnprec{"2280} \DeclareUTFSymbol\textnsucc{"2281} \DeclareUTFSymbol\textsubset{"2282} \DeclareUTFSymbol\textsupset{"2283} \DeclareUTFSymbol\textnsubset{"2284} \DeclareUTFSymbol\textnsupset{"2285} \DeclareUTFSymbol\textsubseteq{"2286} \DeclareUTFSymbol\textsupseteq{"2287} \DeclareUTFSymbol\textnsubseteq{"2288} \DeclareUTFSymbol\textnsupseteq{"2289} \DeclareUTFSymbol\textsubsetneq{"228A} \DeclareUTFSymbol\textsupsetneq{"228B} \DeclareUTFSymbol\textcupdot{"228D} \DeclareUTFSymbol\textcupplus{"228E} \DeclareUTFSymbol\textsqsubset{"228F} \DeclareUTFCommand\textnsqsubset{\textlstrikethru\textsqsubset} \DeclareUTFSymbol\textsqsupset{"2290} \DeclareUTFCommand\textnsqsupset{\textlstrikethru\textsqsupset} \DeclareUTFSymbol\textsqsubseteq{"2291} \DeclareUTFCommand\textnsqsubseteq{\textlstrikethru\textsqsubseteq} \DeclareUTFSymbol\textsqsupseteq{"2292} \DeclareUTFCommand\textnsqsupseteq{\textlstrikethru\textsqsupseteq} \DeclareUTFSymbol\textsqcap{"2293} \DeclareUTFSymbol\textsqcup{"2294} \DeclareUTFSymbol\textoplus{"2295} \DeclareUTFSymbol\textominus{"2296} \DeclareUTFSymbol\textotimes{"2297} \DeclareUTFSymbol\textoslash{"2298} \DeclareUTFSymbol\textodot{"2299} \DeclareUTFSymbol\textcircledcirc{"229A} \DeclareUTFSymbol\textcircledast{"229B} \DeclareUTFSymbol\textcircleddash{"229D} \DeclareUTFSymbol\textboxplus{"229E} \DeclareUTFSymbol\textboxminus{"229F} \DeclareUTFSymbol\textboxtimes{"22A0} \DeclareUTFSymbol\textboxdot{"22A1} \DeclareUTFSymbol\textvdash{"22A2} \DeclareUTFSymbol\textdashv{"22A3} \DeclareUTFCommand\textndashv{\textlstrikethru\textdashv} \DeclareUTFSymbol\texttop{"22A4} \DeclareUTFCommand\textndownvdash{\textlstrikethru\texttop} \DeclareUTFSymbol\textbot{"22A5} \DeclareUTFCommand\textnupvdash{\textlstrikethru\textbot} \DeclareUTFSymbol\textvDash{"22A8} \DeclareUTFSymbol\textVdash{"22A9} \DeclareUTFSymbol\textVvdash{"22AA} \DeclareUTFCommand\textnVvash{\textlstrikethru\textVvdash} \DeclareUTFSymbol\textVDash{"22AB} \DeclareUTFSymbol\textnvdash{"22AC} \DeclareUTFSymbol\textnvDash{"22AD} \DeclareUTFSymbol\textnVdash{"22AE} \DeclareUTFSymbol\textnVDash{"22AF} \DeclareUTFSymbol\textlhd{"22B2} \DeclareUTFSymbol\textrhd{"22B3} \DeclareUTFSymbol\textunlhd{"22B4} \DeclareUTFSymbol\textunrhd{"22B5} \DeclareUTFSymbol\textmultimapdotbothA{"22B6} \DeclareUTFSymbol\textmultimapdotbothB{"22B7} \DeclareUTFSymbol\textmultimap{"22B8} \DeclareUTFSymbol\textveebar{"22BB} \DeclareUTFSymbol\textbarwedge{"22BC} \DeclareUTFSymbol\textstar{"22C6} \DeclareUTFSymbol\textdivideontimes{"22C7} \DeclareUTFSymbol\textbowtie{"22C8} \DeclareUTFSymbol\textltimes{"22C9} \DeclareUTFSymbol\textrtimes{"22CA} \DeclareUTFSymbol\textleftthreetimes{"22CB} \DeclareUTFSymbol\textrightthreetimes{"22CC} \DeclareUTFSymbol\textbacksimeq{"22CD} \DeclareUTFCommand\textnbacksimeq{\textlstrikethru\textbacksimeq} \DeclareUTFSymbol\textcurlyvee{"22CE} \DeclareUTFSymbol\textcurlywedge{"22CF} \DeclareUTFSymbol\textSubset{"22D0} \DeclareUTFCommand\textnSubset{\textlstrikethru\textSubset} \DeclareUTFSymbol\textSupset{"22D1} \DeclareUTFCommand\textnSupset{\textlstrikethru\textSupset} \DeclareUTFSymbol\textCap{"22D2} \DeclareUTFSymbol\textCup{"22D3} \DeclareUTFSymbol\textpitchfork{"22D4} \DeclareUTFSymbol\textlessdot{"22D6} \DeclareUTFSymbol\textgtrdot{"22D7} \DeclareUTFSymbol\textlll{"22D8} \DeclareUTFSymbol\textggg{"22D9} \DeclareUTFSymbol\textlesseqgtr{"22DA} \DeclareUTFSymbol\textgtreqless{"22DB} \DeclareUTFSymbol\textcurlyeqprec{"22DE} \DeclareUTFCommand\textncurlyeqprec{\textlstrikethru\textcurlyeqprec} \DeclareUTFSymbol\textcurlyeqsucc{"22DF} \DeclareUTFCommand\textncurlyeqsucc{\textlstrikethru\textcurlyeqsucc} \DeclareUTFSymbol\textnpreccurlyeq{"22E0} \DeclareUTFSymbol\textnsucccurlyeq{"22E1} \DeclareUTFSymbol\textnqsubseteq{"22E2} \DeclareUTFSymbol\textnqsupseteq{"22E3} \DeclareUTFSymbol\textsqsubsetneq{"22E4} \DeclareUTFSymbol\textsqsupsetneq{"22E5} \DeclareUTFSymbol\textlnsim{"22E6} \DeclareUTFSymbol\textgnsim{"22E7} \DeclareUTFSymbol\textprecnsim{"22E8} \DeclareUTFSymbol\textsuccnsim{"22E9} \DeclareUTFSymbol\textntriangleleft{"22EA} \DeclareUTFSymbol\textntriangleright{"22EB} \DeclareUTFSymbol\textntrianglelefteq{"22EC} \DeclareUTFSymbol\textntrianglerighteq{"22ED} \DeclareUTFSymbol\textvdots{"22EE} \DeclareUTFSymbol\textcdots{"22EF} \DeclareUTFSymbol\textudots{"22F0} \DeclareUTFSymbol\textddots{"22F1} \DeclareUTFSymbol\textbarin{"22F6} \DeclareUTFSymbol\textdiameter{"2300} \DeclareUTFSymbol\textbackneg{"2310} \DeclareUTFSymbol\textwasylozenge{"2311} \DeclareUTFSymbol\textinvbackneg{"2319} \DeclareUTFSymbol\textclock{"231A} \DeclareUTFSymbol\textulcorner{"231C} \DeclareUTFSymbol\texturcorner{"231D} \DeclareUTFSymbol\textllcorner{"231E} \DeclareUTFSymbol\textlrcorner{"231F} \DeclareUTFSymbol\textfrown{"2322} \DeclareUTFSymbol\textsmile{"2323} \DeclareUTFSymbol\textKeyboard{"2328} \DeclareUTFSymbol\textlangle{"2329} \DeclareUTFSymbol\textrangle{"232A} \DeclareUTFSymbol\textAPLinv{"2339} \DeclareUTFSymbol\textTumbler{"233C} \DeclareUTFSymbol\textstmaryrdbaro{"233D} \DeclareUTFSymbol\textnotslash{"233F} \DeclareUTFSymbol\textnotbackslash{"2340} \DeclareUTFSymbol\textboxbackslash{"2342} \DeclareUTFSymbol\textAPLleftarrowbox{"2347} \DeclareUTFSymbol\textAPLrightarrowbox{"2348} \DeclareUTFSymbol\textAPLuparrowbox{"2350} \DeclareUTFSymbol\textAPLdownarrowbox{"2357} \DeclareUTFSymbol\textAPLinput{"235E} \DeclareUTFSymbol\textRequest{"2370} \DeclareUTFSymbol\textBeam{"2393} \DeclareUTFSymbol\texthexagon{"2394} \DeclareUTFSymbol\textAPLbox{"2395} \DeclareUTFSymbol\textForwardToIndex{"23ED} \DeclareUTFSymbol\textRewindToIndex{"23EE} \DeclareUTFSymbol\textbbslash{"244A} \DeclareUTFSymbol\textCircledA{"24B6} \DeclareUTFSymbol\textCleaningF{"24BB} \DeclareUTFCommand\textCleaningFF{\b\textCleaningF} \DeclareUTFSymbol\textCleaningP{"24C5} \DeclareUTFCommand\textCleaningPP{\b\textCleaningP} \DeclareUTFSymbol\textCuttingLine{"2504} \DeclareUTFSymbol\textUParrow{"25B2} \DeclareUTFSymbol\textbigtriangleup{"25B3} \DeclareUTFSymbol\textForward{"25B6} \DeclareUTFSymbol\texttriangleright{"25B7} \DeclareUTFSymbol\textRHD{"25BA} \DeclareUTFSymbol\textDOWNarrow{"25BC} \DeclareUTFSymbol\textbigtriangledown{"25BD} \DeclareUTFSymbol\textRewind{"25C0} \DeclareUTFSymbol\texttriangleleft{"25C1} \DeclareUTFSymbol\textLHD{"25C4} \DeclareUTFSymbol\textdiamond{"25C7} \DeclareUTFSymbol\textlozenge{"25CA} \DeclareUTFSymbol\textLEFTCIRCLE{"25D6} \DeclareUTFSymbol\textRIGHTCIRCLE{"25D7} \DeclareUTFSymbol\textboxbar{"25EB} \DeclareUTFSymbol\textCloud{"2601} \DeclareUTFSymbol\textFiveStar{"2605} \DeclareUTFSymbol\textFiveStarOpen{"2606} \DeclareUTFSymbol\textPhone{"260E} \DeclareUTFSymbol\textboxempty{"2610} \DeclareUTFSymbol\textCheckedbox{"2611} \DeclareUTFSymbol\textCrossedbox{"2612} \DeclareUTFSymbol\textCoffeecup{"2615} \DeclareUTFSymbol\textHandCuffLeft{"261A} \DeclareUTFSymbol\textHandCuffRight{"261B} \DeclareUTFSymbol\textHandLeft{"261C} \DeclareUTFSymbol\textHandRight{"261E} \DeclareUTFSymbol\textRadioactivity{"2622} \DeclareUTFSymbol\textBiohazard{"2623} \DeclareUTFSymbol\textAnkh{"2625} \DeclareUTFSymbol\textYinYang{"262F} \DeclareUTFSymbol\textfrownie{"2639} \DeclareUTFSymbol\textsmiley{"263A} \DeclareUTFSymbol\textblacksmiley{"263B} \DeclareUTFSymbol\textsun{"263C} \DeclareUTFSymbol\textleftmoon{"263D} \DeclareUTFSymbol\textrightmoon{"263E} \DeclareUTFSymbol\textmercury{"263F} \DeclareUTFSymbol\textPUfemale{"2640} \DeclareUTFSymbol\textearth{"2641} \DeclareUTFSymbol\textmale{"2642} \DeclareUTFSymbol\textjupiter{"2643} \DeclareUTFSymbol\textsaturn{"2644} \DeclareUTFSymbol\texturanus{"2645} \DeclareUTFSymbol\textneptune{"2646} \DeclareUTFSymbol\textpluto{"2647} \DeclareUTFSymbol\textaries{"2648} \DeclareUTFSymbol\texttaurus{"2649} \DeclareUTFSymbol\textgemini{"264A} \DeclareUTFSymbol\textcancer{"264B} \DeclareUTFSymbol\textleo{"264C} \DeclareUTFSymbol\textvirgo{"264D} \DeclareUTFSymbol\textlibra{"264E} \DeclareUTFSymbol\textscorpio{"264F} \DeclareUTFSymbol\textsagittarius{"2650} \DeclareUTFSymbol\textcapricornus{"2651} \DeclareUTFSymbol\textaquarius{"2652} \DeclareUTFSymbol\textpisces{"2653} \DeclareUTFSymbol\textspadesuitblack{"2660} \DeclareUTFSymbol\textheartsuitwhite{"2661} \DeclareUTFSymbol\textdiamondsuitwhite{"2662} \DeclareUTFSymbol\textclubsuitblack{"2663} \DeclareUTFSymbol\textspadesuitwhite{"2664} \DeclareUTFSymbol\textheartsuitblack{"2665} \DeclareUTFSymbol\textdiamondsuitblack{"2666} \DeclareUTFSymbol\textclubsuitwhite{"2667} \DeclareUTFSymbol\textquarternote{"2669} \DeclareUTFSymbol\texttwonotes{"266B} \DeclareUTFSymbol\textsixteenthnote{"266C} \DeclareUTFSymbol\textflat{"266D} \DeclareUTFSymbol\textnatural{"266E} \DeclareUTFSymbol\textsharp{"266F} \DeclareUTFSymbol\textrecycle{"2672} \DeclareUTFSymbol\textWheelchair{"267F} \DeclareUTFSymbol\textFlag{"2691} \DeclareUTFSymbol\textMineSign{"2692} \DeclareUTFSymbol\textdsmilitary{"2694} \DeclareUTFSymbol\textdsmedical{"2695} \DeclareUTFSymbol\textdsjuridical{"2696} \DeclareUTFSymbol\textdschemical{"2697} \DeclareUTFSymbol\textdsbiological{"2698} \DeclareUTFSymbol\textdscommercial{"269A} \DeclareUTFSymbol\textmanstar{"269D} \DeclareUTFSymbol\textdanger{"26A0} \DeclareUTFSymbol\textFemaleFemale{"26A2} \DeclareUTFSymbol\textMaleMale{"26A3} \DeclareUTFSymbol\textFemaleMale{"26A4} \DeclareUTFSymbol\textHermaphrodite{"26A5} \DeclareUTFSymbol\textNeutral{"26AA} \DeclareUTFSymbol\textPUuncrfemale{"26B2} \DeclareUTFSymbol\texthexstar{"26B9} \DeclareUTFSymbol\textSoccerBall{"26BD} \DeclareUTFSymbol\textSunCload{"26C5} \DeclareUTFSymbol\textRain{"26C6} \DeclareUTFSymbol\textnoway{"26D4} \DeclareUTFSymbol\textMountain{"26F0} \DeclareUTFSymbol\textTent{"26FA} \DeclareUTFSymbol\textScissorRightBrokenBottom{"2701} \DeclareUTFSymbol\textScissorRight{"2702} \DeclareUTFSymbol\textScissorRightBrokenTop{"2703} \DeclareUTFSymbol\textScissorHollowRight{"2704} \DeclareUTFSymbol\textPhoneHandset{"2706} \DeclareUTFSymbol\textTape{"2707} \DeclareUTFSymbol\textPlane{"2708} \DeclareUTFSymbol\textEnvelope{"2709} \DeclareUTFSymbol\textPeace{"270C} \DeclareUTFSymbol\textWritingHand{"270D} \DeclareUTFSymbol\textPencilRightDown{"270E} \DeclareUTFSymbol\textPencilRight{"270F} \DeclareUTFSymbol\textPencilRightUp{"2710} \DeclareUTFSymbol\textNibRight{"2711} \DeclareUTFSymbol\textNibSolidRight{"2712} \DeclareUTFSymbol\textCheckmark{"2713} \DeclareUTFSymbol\textCheckmarkBold{"2714} \DeclareUTFSymbol\textXSolid{"2715} \DeclareUTFSymbol\textXSolidBold{"2716} \DeclareUTFSymbol\textXSolidBrush{"2717} \DeclareUTFSymbol\textPlusOutline{"2719} \DeclareUTFSymbol\textPlus{"271A} \DeclareUTFSymbol\textPlusThinCenterOpen{"271B} \DeclareUTFSymbol\textPlusCenterOpen{"271C} \DeclareUTFSymbol\textCross{"271D} \DeclareUTFSymbol\textCrossOpenShadow{"271E} \DeclareUTFSymbol\textCrossOutline{"271F} \DeclareUTFSymbol\textCrossMaltese{"2720} \DeclareUTFSymbol\textDavidStar{"2721} \DeclareUTFSymbol\textFourAsterisk{"2722} \DeclareUTFSymbol\textJackStar{"2723} \DeclareUTFSymbol\textJackStarBold{"2724} \DeclareUTFSymbol\textClowerTips{"2725} \DeclareUTFSymbol\textFourStar{"2726} \DeclareUTFSymbol\textFourStarOpen{"2727} \DeclareUTFSymbol\textFiveStarOpenCircled{"272A} \DeclareUTFSymbol\textFiveStarCenterOpen{"272B} \DeclareUTFSymbol\textFiveStarOpenDotted{"272C} \DeclareUTFSymbol\textFiveStarOutline{"272D} \DeclareUTFSymbol\textFiveStarOutlineHeavy{"272E} \DeclareUTFSymbol\textFiveStarConvex{"272F} \DeclareUTFSymbol\textFiveStarShadow{"2730} \DeclareUTFSymbol\textAsteriskBold{"2731} \DeclareUTFSymbol\textAsteriskCenterOpen{"2732} \DeclareUTFSymbol\textEightStarTaper{"2734} \DeclareUTFSymbol\textEightStarConvex{"2735} \DeclareUTFSymbol\textSixStar{"2736} \DeclareUTFSymbol\textEightStar{"2737} \DeclareUTFSymbol\textEightStarBold{"2738} \DeclareUTFSymbol\textTwelveStar{"2739} \DeclareUTFSymbol\textSixteenStarLight{"273A} \DeclareUTFSymbol\textSixFlowerPetalRemoved{"273B} \DeclareUTFSymbol\textSixFlowerOpenCenter{"273C} \DeclareUTFSymbol\textAsterisk{"273D} \DeclareUTFSymbol\textSixFlowerAlternate{"273E} \DeclareUTFSymbol\textFiveFlowerPetal{"273F} \DeclareUTFSymbol\textFiveFlowerOpen{"2740} \DeclareUTFSymbol\textEightFlowerPetal{"2741} \DeclareUTFSymbol\textSunshineOpenCircled{"2742} \DeclareUTFSymbol\textSixFlowerAltPetal{"2743} \DeclareUTFSymbol\textSnowflakeChevron{"2744} \DeclareUTFSymbol\textSnowflake{"2745} \DeclareUTFSymbol\textSnowflakeChevronBold{"2746} \DeclareUTFSymbol\textSparkle{"2747} \DeclareUTFSymbol\textSparkleBold{"2748} \DeclareUTFSymbol\textAsteriskRoundedEnds{"2749} \DeclareUTFSymbol\textEightFlowerPetalRemoved{"274A} \DeclareUTFSymbol\textEightAsterisk{"274B} \DeclareUTFSymbol\textCircleShadow{"274D} \DeclareUTFSymbol\textSquareShadowBottomRight{"274F} \DeclareUTFSymbol\textSquareTopRight{"2750} \DeclareUTFSymbol\textSquareCastShadowBottomRight{"2751} \DeclareUTFSymbol\textSquareCastShadowTopRight{"2752} \DeclareUTFSymbol\textDiamandSolid{"2756} \DeclareUTFSymbol\textRectangleThin{"2758} \DeclareUTFSymbol\textRectangle{"2759} \DeclareUTFSymbol\textRectangleBold{"275A} \DeclareUTFSymbol\textperp{"27C2} \DeclareUTFCommand\textnotperp{\textlstrikethru\textperp} \DeclareUTFSymbol\textveedot{"27C7} \DeclareUTFSymbol\textwedgedot{"27D1} \DeclareUTFSymbol\textleftspoon{"27DC} \DeclareUTFSymbol\textlbrackdbl{"27E6} \DeclareUTFSymbol\textrbrackdbl{"27E7} \DeclareUTFSymbol\textcirclearrowleft{"27F2} \DeclareUTFSymbol\textcirclearrowright{"27F3} \DeclareUTFSymbol\textlongleftarrow{"27F5} \DeclareUTFSymbol\textlongrightarrow{"27F6} \DeclareUTFSymbol\textlongleftrightarrow{"27F7} \DeclareUTFSymbol\textLongleftarrow{"27F8} \DeclareUTFSymbol\textLongrightarrow{"27F9} \DeclareUTFSymbol\textLongleftrightarrow{"27FA} \DeclareUTFSymbol\textlongmapsto{"27FC} \DeclareUTFSymbol\textLongmapsfrom{"27FD} \DeclareUTFSymbol\textLongmapsto{"27FE} \DeclareUTFSymbol\textnwsearrow{"2921} \DeclareUTFSymbol\textneswarrow{"2922} \DeclareUTFSymbol\textlhooknwarrow{"2923} \DeclareUTFSymbol\textrhooknearrow{"2924} \DeclareUTFSymbol\textlhooksearrow{"2925} \DeclareUTFSymbol\textrhookswarrow{"2926} \DeclareUTFSymbol\textleadsto{"2933} \DeclareUTFSymbol\textrcurvearrowne{"2934} \DeclareUTFSymbol\textlcurvearrowse{"2935} \DeclareUTFSymbol\textlcurvearrowsw{"2936} \DeclareUTFSymbol\textrcurvearrowse{"2937} \DeclareUTFSymbol\textlcurvearrowdown{"2938} \DeclareUTFSymbol\textrcurvearrowdown{"2939} \DeclareUTFSymbol\textrcurvearrowleft{"293A} \DeclareUTFSymbol\textrcurvearrowright{"293B} \DeclareUTFSymbol\textleftrightharpoon{"294A} \DeclareUTFSymbol\textrightleftharpoon{"294B} \DeclareUTFSymbol\textupdownharpoonrightleft{"294C} \DeclareUTFSymbol\textupdownharpoonleftright{"294D} \DeclareUTFSymbol\textleftleftharpoons{"2962} \DeclareUTFSymbol\textupupharpoons{"2963} \DeclareUTFSymbol\textrightrightharpoons{"2964} \DeclareUTFSymbol\textdowndownharpoons{"2965} \DeclareUTFSymbol\textleftbarharpoon{"296A} \DeclareUTFSymbol\textbarleftharpoon{"296B} \DeclareUTFSymbol\textrightbarharpoon{"296C} \DeclareUTFSymbol\textbarrightharpoon{"296D} \DeclareUTFSymbol\textupdownharpoons{"296E} \DeclareUTFSymbol\textdownupharpoons{"296F} \DeclareUTFSymbol\textllparenthesis{"2987} \DeclareUTFSymbol\textrrparenthesis{"2988} \DeclareUTFSymbol\textinvdiameter{"29B0} \DeclareUTFSymbol\textobar{"29B6} \DeclareUTFSymbol\textobslash{"29B8} \DeclareUTFSymbol\textobot{"29BA} \DeclareUTFSymbol\textNoChemicalCleaning{"29BB} \DeclareUTFSymbol\textolessthan{"29C0} \DeclareUTFSymbol\textogreaterthan{"29C1} \DeclareUTFSymbol\textboxslash{"29C4} \DeclareUTFSymbol\textboxbslash{"29C5} \DeclareUTFSymbol\textboxast{"29C6} \DeclareUTFSymbol\textboxcircle{"29C7} \DeclareUTFSymbol\textboxbox{"29C8} \DeclareUTFSymbol\textValve{"29D3} \DeclareUTFSymbol\textmultimapboth{"29DF} \DeclareUTFSymbol\textshuffle{"29E2} \DeclareUTFSymbol\textuplus{"2A04} \DeclareUTFSymbol\textbigdoublewedge{"2A07} \DeclareUTFSymbol\textbigdoublevee{"2A08} \DeclareUTFSymbol\textJoin{"2A1D} \DeclareUTFSymbol\textfatsemi{"2A1F} \DeclareUTFSymbol\textcircplus{"2A22} \DeclareUTFSymbol\textminusdot{"2A2A} \DeclareUTFSymbol\textdottimes{"2A30} \DeclareUTFSymbol\textdtimes{"2A32} \DeclareUTFSymbol\textodiv{"2A38} \DeclareUTFSymbol\textinvneg{"2A3C} \DeclareUTFSymbol\textsqdoublecap{"2A4E} \DeclareUTFSymbol\textcapdot{"2A40} \DeclareUTFSymbol\textsqdoublecup{"2A4F} \DeclareUTFSymbol\textdoublewedge{"2A55} \DeclareUTFSymbol\textdoublevee{"2A56} \DeclareUTFSymbol\textdoublebarwedge{"2A5E} \DeclareUTFSymbol\textveedoublebar{"2A63} \DeclareUTFSymbol\texteqdot{"2A66} \DeclareUTFCommand\textneqdot{\textlstrikethru\texteqdot} \DeclareUTFSymbol\textcoloncolonequals{"2A74} \DeclareUTFSymbol\textleqslant{"2A7D} \DeclareUTFCommand\textnleqslant{\textlstrikethrux\textleqslant} \DeclareUTFSymbol\textgeqslant{"2A7E} \DeclareUTFCommand\textngeqslant{\textlstrikethru\textgeqslant} \DeclareUTFSymbol\textlessapprox{"2A85} \DeclareUTFCommand\textnlessapprox{\textlstrikethru\textnlessapprox} \DeclareUTFSymbol\textgtrapprox{"2A86} \DeclareUTFCommand\textngtrapprox{\textlstrikethru\textgtrapprox} \DeclareUTFSymbol\textlneq{"2A87} \DeclareUTFSymbol\textgneq{"2A88} \DeclareUTFSymbol\textlnapprox{"2A89} \DeclareUTFSymbol\textgnapprox{"2A8A} \DeclareUTFSymbol\textlesseqqgtr{"2A8B} \DeclareUTFSymbol\textgtreqqless{"2A8C} \DeclareUTFSymbol\texteqslantless{"2A95} \DeclareUTFSymbol\texteqslantgtr{"2A96} \DeclareUTFSymbol\textleftslice{"2AA6} \DeclareUTFSymbol\textrightslice{"2AA7} \DeclareUTFSymbol\textpreceq{"2AAF} \DeclareUTFCommand\textnpreceq{\textlstrikethru\textpreceq} \DeclareUTFSymbol\textsucceq{"2AB0} \DeclareUTFCommand\textnsucceq{\textlstrikethru\textsucceq} \DeclareUTFSymbol\textprecneq{"2AB1} \DeclareUTFSymbol\textsuccneq{"2AB2} \DeclareUTFSymbol\textpreceqq{"2AB3} \DeclareUTFCommand\textnpreceqq{\textlstrikethru\textpreceqq} \DeclareUTFSymbol\textsucceqq{"2AB4} \DeclareUTFCommand\textnsucceqq{\textlstrikethru\textsucceqq} \DeclareUTFSymbol\textprecneqq{"2AB5} \DeclareUTFSymbol\textsuccneqq{"2AB6} \DeclareUTFSymbol\textprecapprox{"2AB7} \DeclareUTFCommand\textnprecapprox{\textlstrikethru\textprecapprox} \DeclareUTFSymbol\textsuccapprox{"2AB8} \DeclareUTFCommand\textnsuccapprox{\textlstrikethru\textsuccapprox} \DeclareUTFSymbol\textprecnapprox{"2AB9} \DeclareUTFSymbol\textsuccnapprox{"2ABA} \DeclareUTFSymbol\textsubseteqq{"2AC5} \DeclareUTFCommand\textnsubseteqq{\textlstrikethru\textsubseteqq} \DeclareUTFSymbol\textsupseteqq{"2AC6} \DeclareUTFCommand\textnsupseteqq{\textlstrikethru\textsupseteqq} \DeclareUTFSymbol\textdashV{"2AE3} \DeclareUTFCommand\textndashV{\textlstrikethru\textdashV} \DeclareUTFSymbol\textDashv{"2AE4} \DeclareUTFCommand\textnDashv{\textlstrikethru\textDashv} \DeclareUTFSymbol\textDashV{"2AE5} \DeclareUTFCommand\textnDashV{\textlstrikethru\textDashV} \DeclareUTFSymbol\textdownmodels{"2AEA} \DeclareUTFCommand\textndownmodels{\textlstrikethru\textdownmodels} \DeclareUTFSymbol\textupmodels{"2AEB} \DeclareUTFCommand\textnupmodels{\textlstrikethru\textupmodels} \DeclareUTFSymbol\textupspoon{"2AEF} \DeclareUTFSymbol\textinterleave{"2AF4} \DeclareUTFSymbol\textsslash{"2AFD} \DeclareUTFSymbol\textpentagon{"2B20} \DeclareUTFSymbol\textvarhexagon{"2B21} \DeclareUTFSymbol\textjinferior{"2C7C} \DeclareUTFSymbol\textslashdiv{"2E13} \DeclareUTFSymbol\textinterrobangdown{"2E18} \DeclareUTFSymbol\textfivedots{"2E2D} \DeclareUTFSymbol\textPUheng{"A727} \DeclareUTFSymbol\textPUlhookfour{"A72C} \DeclareUTFSymbol\textPUscf{"A730} \DeclareUTFSymbol\textPUaolig{"A735} \DeclareUTFSymbol\textoo{"A74F} \DeclareUTFSymbol\textcircumlow{"A788} \DeclareUTFSymbol\textfi{"FB01} \DeclareUTFSymbol\textfl{"FB02} \DeclareUTFSymbol\textGaPa{"1D13B} \DeclareUTFSymbol\textHaPa{"1D13C} \DeclareUTFSymbol\textViPa{"1D13D} \DeclareUTFSymbol\textAcPa{"1D13E} \DeclareUTFSymbol\textSePa{"1D13F} \DeclareUTFSymbol\textZwPa{"1D140} \DeclareUTFSymbol\textfullnote{"1D15D} \DeclareUTFSymbol\texthalfnote{"1D15E} \DeclareUTFSymbol\textVier{"1D15F} \DeclareUTFSymbol\textAcht{"1D160} \DeclareUTFSymbol\textSech{"1D161} \DeclareUTFSymbol\textZwdr{"1D162} \DeclareUTFSymbol\textMundus{"1F30D} \DeclareUTFSymbol\textMoon{"1F319} \DeclareUTFSymbol\textManFace{"1F468} \DeclareUTFSymbol\textWomanFace{"1F469} \DeclareUTFSymbol\textFax{"1F4E0} \DeclareUTFSymbol\textFire{"1F525} \DeclareUTFSymbol\textBicycle{"1F6B2} \DeclareUTFSymbol\textGentsroom{"1F6B9} \DeclareUTFSymbol\textLadiesroom{"1F6BA} \DeclareUTFCommand\textcopyleft{\textcircled\textrevc} \DeclareUTFCommand\textccsa{\textcircled\textcirclearrowleft} \DeclareUTFSymbol\textglqq{"201E} \DeclareUTFSymbol\textgrqq{"201C} \DeclareUTFSymbol\textglq{"201A} \DeclareUTFSymbol\textgrq{"2018} \DeclareUTFSymbol\textflqq{"00AB} \DeclareUTFSymbol\textfrqq{"00BB} \DeclareUTFSymbol\textflq{"2039} \DeclareUTFSymbol\textfrq{"203A} \DeclareUTFSymbol\textneg{"00AC} \DeclareUTFSymbol\textcdot{"00B7} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \begin{macrocode} %<@@=xeCJK> % \end{macrocode} % % \subsection{\pkg{xeCJK.cfg}} % % \begin{macrocode} %<*config> % \end{macrocode} % % 预设的配置文件 \file{xeCJK.cfg} 为一个空文件。可以在里面增加设置,然后保存到 % 本地目录下面。 % \begin{macrocode} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \Finale % % \endinput % % \DisableImplementation % % \begin{implementation} % % \makeatletter % \let\special@index\@gobble % \makeatother % % \section{例子} % % \subsection{\pkg{xeCJK-example-autofake.tex}} % % \begin{macrocode} %<*ex-autofake> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage[AutoFakeBold,AutoFakeSlant]{xeCJK} \setCJKmainfont[BoldFont=simhei.ttf, SlantedFont=simkai.ttf]{simsun.ttc} \setCJKsansfont[AutoFakeSlant=false, BoldFont=simhei.ttf, SlantedFont=simkai.ttf]{simsun.ttc} \setCJKmonofont[ItalicFont=simkai.ttf]{simsun.ttc} \begin{document} \centering \begin{tabular}{lllll} \hline {\bf rm} & md & up & \verb|\rmfamily\mdseries\upshape| & {\rmfamily\mdseries\upshape English 中文字体} \\ & md & it & \verb|\rmfamily\mdseries\itshape| & {\rmfamily\mdseries\itshape English 中文字体} \\ & md & sl & \verb|\rmfamily\mdseries\slshape| & {\rmfamily\mdseries\slshape English 中文字体} \\ \cline{2-5} & bf & up & \verb|\rmfamily\bfseries\upshape| & {\rmfamily\bfseries\upshape English 中文字体} \\ & bf & it & \verb|\rmfamily\bfseries\itshape| & {\rmfamily\bfseries\itshape English 中文字体} \\ & bf & sl & \verb|\rmfamily\bfseries\slshape| & {\rmfamily\bfseries\slshape English 中文字体} \\ \hline {\bf sf} & md & up & \verb|\sffamily\mdseries\upshape| & {\sffamily\mdseries\upshape English 中文字体} \\ & md & it & \verb|\sffamily\mdseries\itshape| & {\sffamily\mdseries\itshape English 中文字体} \\ & md & sl & \verb|\sffamily\mdseries\slshape| & {\sffamily\mdseries\slshape English 中文字体} \\ \cline{2-5} & bf & up & \verb|\sffamily\bfseries\upshape| & {\sffamily\bfseries\upshape English 中文字体} \\ & bf & it & \verb|\sffamily\bfseries\itshape| & {\sffamily\bfseries\itshape English 中文字体} \\ & bf & sl & \verb|\sffamily\bfseries\slshape| & {\sffamily\bfseries\slshape English 中文字体} \\ \hline {\bf tt} & md & up & \verb|\ttfamily\mdseries\upshape| & {\ttfamily\mdseries\upshape English 中文字体} \\ & md & it & \verb|\ttfamily\mdseries\itshape| & {\ttfamily\mdseries\itshape English 中文字体} \\ & md & sl & \verb|\ttfamily\mdseries\slshape| & {\ttfamily\mdseries\slshape English 中文字体} \\ \cline{2-5} & bf & up & \verb|\ttfamily\bfseries\upshape| & {\ttfamily\bfseries\upshape English 中文字体} \\ & bf & it & \verb|\ttfamily\bfseries\itshape| & {\ttfamily\bfseries\itshape English 中文字体} \\ & bf & sl & \verb|\ttfamily\bfseries\slshape| & {\ttfamily\bfseries\slshape English 中文字体} \\ \hline \end{tabular} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-fallback.tex}} % % \begin{macrocode} %<*ex-fallback> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage[AutoFallBack]{xeCJK} \usepackage{xeCJKfntef} \usepackage{array} \setCJKmainfont[AutoFakeBold,AutoFakeSlant]{KaiTi_GB2312} \setCJKfallbackfamilyfont{\CJKrmdefault}[BoldFont=SimHei] { [SlantedFont=FangSong]{SimSun} , [BoldFont=*] {SimSun-ExtB} } \begin{document} 漢字源𣴑考 \textbf{漢字源𣴑考} \textsl{漢字源𣴑考} \CJKunderwave{漢字源𣴑考} \begin{table}[ht] \caption{生僻字测试} \medskip\centering \begin{tabular}{*4{|c>{\ttfamily U+}l}|} 㐀 & 3400 & 㐁 & 3401 & 㐂 & 3402 & 㐃 & 3403 \\ 㐄 & 3404 & 㐅 & 3405 & 㐆 & 3406 & 㐇 & 3407 \\ 㐈 & 3408 & 㐉 & 3409 & 㐊 & 340A & 㐋 & 340B \\ 㐌 & 340C & 㐍 & 340D & 㐎 & 340E & 㐏 & 341F \\ 㐐 & 3410 & 㐑 & 3411 & 㐒 & 3412 & 㐓 & 3413 \\ 㐔 & 3414 & 㐕 & 3415 & 㐖 & 3416 & 㐗 & 3417 \\ 㐘 & 3418 & 㐙 & 3419 & 㐚 & 341A & 㐛 & 341B \\ 㐜 & 341C & 㐝 & 341D & 㐞 & 341E & 㐟 & 341F \\[1ex] 𠀀 & 20000 & 𠀁 & 20001 & 𠀂 & 20002 & 𠀃 & 20003 \\ 𠀄 & 20004 & 𠀅 & 20005 & 𠀆 & 20006 & 𠀇 & 20007 \\ 𠀈 & 20008 & 𠀉 & 20009 & 𠀊 & 2000A & 𠀋 & 2000B \\ 𠀌 & 2000C & 𠀍 & 2000D & 𠀎 & 2000E & 𠀏 & 2000F \\ 𠀐 & 20010 & 𠀑 & 20011 & 𠀒 & 20012 & 𠀓 & 20013 \\ 𠀔 & 20014 & 𠀕 & 20015 & 𠀖 & 20016 & 𠀗 & 20017 \\ 𠀘 & 20018 & 𠀙 & 20019 & 𠀚 & 2001A & 𠀛 & 2001B \\ 𠀜 & 2001C & 𠀝 & 2001D & 𠀞 & 2001E & 𠀟 & 2001F \\ \end{tabular} \end{table} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-subCJKblock.tex}} % % \begin{macrocode} %<*ex-block> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage{xeCJK} \usepackage{array} \xeCJKDeclareSubCJKBlock{Ext-A} { "3400 -> "4DBF } \xeCJKDeclareSubCJKBlock{Ext-B} { "20000 -> "2A6DF } \xeCJKDeclareSubCJKBlock{Kana} { "3040 -> "309F, "30A0 -> "30FF, "31F0 -> "31FF, } \xeCJKDeclareSubCJKBlock{Hangul}{ "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } \setCJKmainfont[Ext-A=SimHei,Ext-B=SimSun-ExtB]{SimSun} \setCJKmainfont[Kana]{Meiryo} \setCJKmainfont[Hangul]{Malgun Gothic} \parindent=2em \begin{document} \long\def\showtext{% 中日韩越统一表意文字(英语:CJKV Unified Ideographs),旧称中日韩统一表意文字(英语:CJK Unified Ideographs),也称统一汉字(英语:Unihan),目的是要把分别来自中文、日文、韩文、越文、壮文中,对于相同起源、本义相同、形状一样或稍异的表意文字(主要为汉字,但也有仿汉字如:方块壮字、日文汉字(かんじ / kanji)、韩文汉字(한자 / hanja)、越南的喃字(Chữ Nôm)与越文汉字(Chữ Nho,在越南也称作儒字),应赋予其在ISO 10646及统一码标准中有相同编码。此计划原本只包含中文、日文及韩文中所使用的汉字,是以旧称中日韩统一表意文字(CJK)。后来,此计划加入了越文的喃字,所以合称中日韩越统一表意文字(CJKV)。 CJK統合漢字(シージェーケーとうごうかんじ、CJK Unified Ideographs)は、ISO/IEC 10646 (Universal Multiple-Octet Coded Character Set, 略称 UCS) および Unicodeにて採用されている符号化用漢字集合およびその符号表である。CJK統合漢字の名称は、中国語(Chinese)、日本語(Japanese)、韓国語(Korean)で使われている漢字をひとまとめにしたことからきている。CJK統合漢字の初版である Unified Repertoire and Ordering (URO) 第二版は1992年に制定されたが、1994年にベトナムで使われていた漢字も含めることにしたため、CJKVと呼ばれる事もある。CJKVは、中国語・日本語・韓国語・ベトナム語 (英語: Chinese-Japanese-Korean-Vietnamese) の略。特に、その4言語で共通して使われる、または使われていた文字体系である漢字(チュノムを含む)のこと。ソフトウェアの国際化、中でも文字コードに関する分野で用いられる。 \CJKspace 한중일월 통합 한자(또는 한중일 통합 한자)는 유니코드에 담겨 있는 한자들의 집합으로, 한국, 중국, 일본에서 쓰이는 한자를 묶은 것이기 때문에 머리 글자를 따서 한중일(CJK) 통합 한자라고 불렀는데, 최근에는 베트남에서 쓰이는 한자도 추가되었기에 한중일월(CJKV) 통합 한자로 부르게 되었다. 처음에 유니코드에는 65,536($=2^{16}$)자만 들어갈 수 있었기 때문에, 가장 많은 문자가 배당되는 한자를 위해서 한국, 중국, 일본에서 사용하는 한자 중에 모양이 유사하며 그 뜻이 같은 글자를 같은 코드로 통합했다. 따라서 문자 코드만으로 그 한자가 사용되는 언어를 알아 낼 수 없는데, 다만 중국의 간체자나 번체자, 일본의 구자체나 신자체 등 분명하게 모양이 다른 글자는 별도의 부호를 할당하고 있다. 이런 문자 할당 정책에 반발하여 TRON과 같은 인코딩이 만들어지기도 했으나, 실제로 통합된 한자의 차이가 별로 크지 않기 때문에 문제가 되지 않는다는 의견도 있다. \CJKnospace} \showtext \bigskip \xeCJKCancelSubCJKBlock{Kana,Hangul} \showtext \bigskip \xeCJKRestoreSubCJKBlock{Hangul} \showtext \begin{table}[ht] \caption{生僻字测试} \medskip\centering \begin{tabular}{*4{|c>{\ttfamily U+}l}|} 㐀 & 3400 & 㐁 & 3401 & 㐂 & 3402 & 㐃 & 3403 \\ 㐄 & 3404 & 㐅 & 3405 & 㐆 & 3406 & 㐇 & 3407 \\ 㐈 & 3408 & 㐉 & 3409 & 㐊 & 340A & 㐋 & 340B \\ 㐌 & 340C & 㐍 & 340D & 㐎 & 340E & 㐏 & 341F \\ 㐐 & 3410 & 㐑 & 3411 & 㐒 & 3412 & 㐓 & 3413 \\ 㐔 & 3414 & 㐕 & 3415 & 㐖 & 3416 & 㐗 & 3417 \\ 㐘 & 3418 & 㐙 & 3419 & 㐚 & 341A & 㐛 & 341B \\ 㐜 & 341C & 㐝 & 341D & 㐞 & 341E & 㐟 & 341F \\[1ex] 𠀀 & 20000 & 𠀁 & 20001 & 𠀂 & 20002 & 𠀃 & 20003 \\ 𠀄 & 20004 & 𠀅 & 20005 & 𠀆 & 20006 & 𠀇 & 20007 \\ 𠀈 & 20008 & 𠀉 & 20009 & 𠀊 & 2000A & 𠀋 & 2000B \\ 𠀌 & 2000C & 𠀍 & 2000D & 𠀎 & 2000E & 𠀏 & 2000F \\ 𠀐 & 20010 & 𠀑 & 20011 & 𠀒 & 20012 & 𠀓 & 20013 \\ 𠀔 & 20014 & 𠀕 & 20015 & 𠀖 & 20016 & 𠀗 & 20017 \\ 𠀘 & 20018 & 𠀙 & 20019 & 𠀚 & 2001A & 𠀛 & 2001B \\ 𠀜 & 2001C & 𠀝 & 2001D & 𠀞 & 2001E & 𠀟 & 2001F \\ \end{tabular} \end{table} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % % \subsection{\pkg{xeCJK-example-CJKecglue.tex}} % % \begin{macrocode} %<*ex-ecglue> % \end{macrocode} % % \begin{macrocode} \documentclass{minimal} \usepackage{xeCJK} \setCJKmainfont[BoldFont=SimHei]{SimSun} \long\def\showtext{% 这是 English 中文 {\itshape Chinese} 中文 \TeX\ 间隔 \textit{Italic} 中文\textbf{字体} a 数学 $b$ 数学 $c$ $d$\par 这是English中文{\itshape Chinese}中文\TeX\ 间隔\textit{Italic}中文\textbf{字体}a数学$b$数学$c$ $d$\par This is an example. 这是一个例子} \begin{document} \showtext \hrulefill\bigskip \xeCJKsetup{xCJKecglue=\quad} \showtext \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-checksingle.tex}} % % \begin{macrocode} %<*ex-single> % \end{macrocode} % % \begin{macrocode} \documentclass{minimal} \usepackage{xeCJK} \setCJKmainfont{SimSun} \long\def\showtext{一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十。 \[x^2+y^2\] 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十。 $$x^2+y^2$$ 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十。 \begin{equation} x^2+y^2 \end{equation} 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十。} \begin{document} \hsize=30em \parindent=0pt \showtext \hrulefill\bigskip \xeCJKsetup{CheckSingle} \showtext \hrulefill\bigskip \xeCJKsetup{PlainEquation} \showtext \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-CJKfntef.tex}} % % \begin{macrocode} %<*ex-fntef> % \end{macrocode} % % \begin{macrocode} \documentclass{ctexart} \usepackage{xcolor} \usepackage{xeCJKfntef} \xeCJKDeclareSubCJKBlock{test}{ `殆 , `已 } \setCJKmainfont[test=SimHei]{SimSun} \def\showtext{% 庄子曰:“吾生也有涯,而知也无涯。以有涯随无涯,殆已!已而为知者,殆而已矣!% 为善无近名,为恶无近刑,缘督以为经,可以保身,可以全生,可以养亲,可以尽年。”} \newcommand\CJKfntef[1]{% \csname#1\endcsname{\showtext}\par \csname#1\endcsname*{\showtext}\par \CJKunderdot{\showtext\csname#1\endcsname{\showtext}}\par \CJKunderdot{\showtext\csname#1\endcsname*{\showtext}}\par \csname#1\endcsname{\showtext\CJKunderdot{\showtext}}\par \csname#1\endcsname*{\showtext\CJKunderdot{\showtext}}\par\bigskip} \begin{document} \section{\textsf{xeCJKfntef} 的\CJKunderdot{简单测试文件}} \CJKunderline{汉 字}\CJKunderline{加下划线} \varCJKunderline{汉字}\varCJKunderline{加下划线} \CJKunderanyline{0.5em}{\sixly \kern-.021em\char58 \kern-.021em}{自定义下划线} \CJKunderanyline{0.2em}{\kern-.03em\vtop{\kern.2ex\hrule width.2em\kern 0.11em \hrule height 0.1em}\kern-.03em}{自定义下划线} \CJKunderanyline{0.5em}{-}{\showtext} \CJKunderanysymbol{0.2em}{-}{\showtext} \CJKunderdot{\showtext} \hrule depth \dp\strutbox width 0 pt \relax \begin{CJKfilltwosides}{40mm} 两端分散对齐\\ 分散对齐\\ \CJKunderdot{汉字可加点}\\ \CJKunderline{汉字可加下划线} \end{CJKfilltwosides} \hrule depth \dp\strutbox width 0 pt \relax \CJKfntef{CJKunderline} \CJKfntef{CJKunderwave} \CJKfntef{CJKunderdblline} \CJKfntef{CJKsout} \CJKfntef{CJKxout} \def\Book{\CJKunderwave-} \def\Noun{\CJKunderline-} 如上所述,\Book{中國文學史}原是\Noun{復旦大學出版社}出版的,\Book{中國文學史新著}則由\Noun{上海文藝出版社}出版。現承\Noun{復旦大學出版社}\Noun{賀聖遂}先生的盛情和\Noun{上海文藝出版總社}\Noun{楊益萍}、\Noun{何承偉}先生以及有關負責人\Noun{陳鳴華}先生的高誼,此書增訂本改由兩社聯合出版。\Noun{賀聖遂}先生並與\Noun{杜榮根}副社長、\Noun{韓結根}編審共同擔任此書的責任編輯。對上述諸位先生謹在這裡表示衷心的感謝。對\Book{中國文學史新著}原版的責任編輯\Noun{戴俊}先生(現為\Noun{上海三聯書店}副總經理)也在此一併致謝。 \Noun{與文學史的}\Noun{應有任務}\Noun{對文學發展過程}\Noun{的內在聯繫的描述}\Noun{還有很大的距離}\Noun{至於距離的所在}\Noun{本書原已有說明}\Book{此不贅述}\Book{為了對學術負責}\Book{我們決定重寫一部並迅即出版} \Noun{南朝}\Noun{梁}\Noun{劉勰}\Book{文心雕龍}\Book{養氣} \Noun{鎌池和馬}\Book{魔法禁書目錄}\Book{某科學的超電磁砲} \Noun{西尾維新}\Book{化物語}\Book{偽物語}\Book{貓物語}% \Book{傾物语}\Book{囤物語}\Book{鬼物語}\Book{戀物語}\Book{花物語} \Noun{岡田麿里}\Book{我們仍未知道那天所看見的花的名字。}\Book{絕園的暴風雨} \Noun{虚淵玄}\Book{Fate/Zero}\Book{PSYCHO-PASS}\Book{ALDNOAH.ZERO} \Noun{劉海洋}\Book{\LaTeX 入門} \def\NAME{% \x{御坂美琴}\x{白井黑子}\x{戰場原緋多木}\x{阿良良木歷}% \x{宿海仁太}\x{本間芽衣子}\x{瀧川吉野}\x{鎖部葉風}% \x{衛宮切嗣}\x{言峰綺禮}\x{常守朱}\x{狡嚙慎也}% \x{界塚伊奈帆}\x*{艾瑟依拉姆·沃斯·艾莉歐斯亞}} \let\x\Noun\NAME \let\x\Book\NAME \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-punctstyle.tex}} % % \begin{macrocode} %<*ex-punctstyle> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage[draft,columns=1,margin=false,headings=false]{typogrid} \usepackage{xeCJK} \usepackage{xeCJKfntef} \setCJKmainfont{SimSun} \xeCJKsetup{AllowBreakBetweenPuncts} \xeCJKDeclarePunctStyle { mine } { fixed-punct-ratio = nan , fixed-margin-width = 0 pt , mixed-margin-width = \maxdimen , mixed-margin-ratio = 0.5 , middle-margin-width = \maxdimen , middle-margin-ratio = 0.5 , add-min-bound-to-margin = true , min-bound-to-kerning = true , kerning-margin-minimum = 0.1 em , bound-punct-width = 0 em , enabled-hanging = true } \xeCJKDeclarePunctStyle { JIS } { bound-punct-ratio = .5 } \begin{document} \setlength\parindent{2em} \newcommand\showexample[1]{% \texttt{------ #1 ------}\par\xeCJKsetup{PunctStyle=#1}\showtexts\par} \newcommand\showtexts{% 《第一回\quad 甄士隐梦幻识通灵\quad 贾雨村风尘怀闺秀》\\ 《第一回\quad 甄士隐梦幻识通灵\quad 贾雨村风尘怀闺秀》 列位看官:你道此书从何而来?说起根由,虽近荒唐,细按则深有趣味。待在下将此来历注明,方使阅者了然不惑。 \CJKunderline*{原来女娲氏炼石补天之时,于大荒山无稽崖炼成高经十二丈、方经二十四丈顽石三万六千五百零一块。娲皇氏只用了三万六千五百块,只单单剩了一块未用,便弃在此山青埂峰下。谁知此石自经煆炼之后,灵性已通,因见众石俱得补天,独自己无材不堪入选,遂自怨自叹,日夜悲号惭愧。} 一日,正当嗟悼之际,俄见一僧一道远远而来,生得骨格不凡,丰神迥别,说说笑笑,来至峰下,坐于石边,高谈快论:先是说些云山雾海、神仙玄幻之事,后便说到红尘中荣华富贵。此石听了,不觉打动凡心,也想要到人间去享一享这荣华富贵,但自恨粗蠢,不得已,便口吐人言,向那僧道说道:“大师,弟子蠢物,不能见礼了!适闻二位谈那人世间荣耀繁华,心切慕之。弟子质虽粗蠢,性却稍通,况见二师仙形道体,定非凡品,必有补天济世之材,利物济人之德。如蒙发一点慈心,携带弟子得入红尘,在那富贵场中,温柔乡里受享几年,自当永佩洪恩,万劫不忘也!”二仙师听毕,齐憨笑道:“善哉,善哉!那红尘中有却有些乐事,但不能永远依恃;况又有‘美中不足,好事多磨’八个字紧相连属,瞬息间则又乐极悲生,人非物换,究竟是到头一梦,万境归空,倒不如不去的好。”这石凡心已炽,那里听得进这话去,乃复苦求再四。二仙知不可强制,乃叹道:“此亦静极思动,无中生有之数也!既如此,我们便携你去受享受享,只是到不得意时,切莫后悔!”石道:“自然,自然。”那僧又道:“若说你性灵,却又如此质蠢,并更无奇贵之处。如此也只好踮脚而已。也罢!我如今大施佛法,助你助,待劫终之日,复还本质,以了此案。你道好否?”石头听了,感谢不尽。那僧便念咒书符,大展幻术,将一块大石登时变成一块鲜明莹洁的美玉,且又缩成扇坠大小的可佩可拿。那僧托于掌上,笑道:“形体倒也是个宝物了!还只没有实在的好处,须得再镌上数字,使人一见便知是奇物方妙。然后好携你到那昌明隆盛之邦、诗礼簪缨之族、花柳繁华地、温柔富贵乡去安身乐业。”石头听了,喜不能禁,乃问:“不知赐了弟子那哪几件奇处?又不知携了弟子到何地方?望乞明示,使弟子不惑。”那僧笑道:“你且莫问,日后自然明白的。”说着,便袖了这石,同那道人飘然而去,竟不知投奔何方何舍。 \hfill ——曹雪芹《红楼梦》\unskip\unkern} \showexample{mine} \showexample{quanjiao} \showexample{JIS} \showexample{banjiao} \showexample{CCT} \showexample{kaiming} \showexample{hangmobanjiao} \showexample{plain} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-verbatim.tex}} % % \begin{macrocode} %<*ex-verb> % \end{macrocode} % % \begin{macrocode} \documentclass[a4paper]{article} \usepackage{xeCJK} \usepackage{fullpage} \xeCJKDeclareSubCJKBlock{Hangul} { "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } \setCJKmainfont{Adobe Song Std} \setCJKmainfont[Hangul]{Adobe Myungjo Std} %%\setmonofont{Inconsolata} %%\setmonofont{Source Code Pro} %%\setCJKmonofont{Adobe Kaiti Std} \setmonofont{TeX Gyre Cursor} \setCJKmonofont{Adobe Fangsong Std} \begin{document} \begin{verbatim} ************************************************************* * * * 精致甲版红楼梦 - 精致工作室特别奉献(2010年9月) * * * * GBK简体、GBK繁体、Big5繁体、PDF简体、PDF繁体 * * * * 为 GBK、Big5 特别度身订制,并经反复修订,方便纯文本阅读 * * * * 精致甲、乙版红楼梦下载专页 * * http://www.speedy7.com/cn/stguru/gb2312/redmansions.htm * * http://www.speedy7.com/cn/stguru/big5/redmansions.htm * * * * 此电子文件可随意传播、发布、下载。 * * 传播时建议保留此版本说明供查阅与识别。 * * 未经修订者同意,不得将此版本用于商业用途。 * * 如您对红楼梦不具深入了解,请勿随便修改其中的内容。 * * * ************************************************************* \end{verbatim} \verb|a 汉 字 b| \verb*|a 汉 字 b| \begin{verbatim} lang_set = { ["English"] = lang.en, ["Français"] = lang.fr, ["Español"] = lang.es, ["中文"] = lang.zh, ["日本語"] = lang.ja, ["한국어"] = lang.ko, } \end{verbatim} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-CM.tex}} % % \begin{macrocode} %<*ex-cm> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage{xeCJK} \usepackage{hologo} \setCJKmainfont{HanaMinA} %% http://fonts.jp/hanazono/ \begin{document} \hologo{XeTeX} でIVSを使うテスト。 消󠄀化󠄀器󠄂 / 消󠄁火器󠄃 / 消󠄂化󠄁器󠄄 消󠄃火器󠄅 / 消化󠄂器󠄆 / 消火器󠄇 消化󠄃器󠄈 / 消火器󠄉 / 辻󠄂辻󠄃辻󠄄辻󠄅  \CJKfontspec{Meiryo} か がか゚ ぼぽ ぼぽ ばぱ ばぱ \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-listings.tex}} % % \begin{macrocode} %<*ex-listings> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage[margin=1in]{geometry} \usepackage{listings,xcolor} \usepackage{showexpl} \usepackage{xeCJK} \setCJKmainfont{HanaMinA} \setCJKmonofont{SimSun} \xeCJKDeclareSubCJKBlock{Kana} { "3040 -> "309F, "30A0 -> "30FF, "31F0 -> "31FF } \setCJKmonofont[Kana]{Meiryo} \setmonofont{Latin Modern Mono Light} \makeatletter \lstset{% basicstyle=\small\ttfamily,breakindent=4\lst@width, numbers=left,numberstyle=\tiny\color{gray}, commentstyle=\color{green!50!black},keywordstyle=\color{blue}\bfseries, identifierstyle=\color{violet},stringstyle=\color{brown}, escapebegin=\normalfont} \lstnewenvironment{cppcode}[1][] {\lstset{language=C++,#1}} {} \makeatother \begin{document} \section{\lstinline{\\lstinline} 测试} \section{\lstinline|甲*乙| 测试} \lstinline|abc汉字abc| \lstinline|甲*乙| \lstinline[mathescape]|数学公式$x^2+y^2$| \section{\lstinline{lstlisting} 环境测试} \begin{lstlisting}[basicstyle=\rmfamily] 纯文字text测试 纯文字text测试 文字+文字 文字(符号)文字 辻󠄂辻󠄃辻󠄄辻󠄅 かがか゚ \end{lstlisting} \begin{lstlisting} text纯文字测试 \end{lstlisting} \begin{lstlisting} text 纯文字测试 \end{lstlisting} \begin{lstlisting} text,纯文字测试 \end{lstlisting} \section{自定义环境测试} \begin{LTXexample}[pos=t,varwidth,numbersep=5pt,columns=fixed] \begin{cppcode}[escapechar=`,morekeywords=返回] #define 返回 return #include /* * 块注释 * `逃逸字符,测试$f(x)$` */ int main() { // 行注释 const char *欢迎 = "hello 世界(ワールド)"; std::cout << 欢迎 << std::endl; 返回 0; } \end{cppcode} \end{LTXexample} \section{\texttt{breaklines} 测试} \begin{lstlisting}[linewidth=10em,frame=single,rulecolor=\color{black},breaklines] 断行文字text测试,断行文字text测试,断行文字text测试,断行文字text测试 断行文字text测试,断行文字text测试,断行文字text测试,断行文字text测试 \end{lstlisting} \section{\lstinline|\\lstinputlisting| 测试} \lstinputlisting[language={[AlLaTeX]TeX}]{\jobname} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK-example-mathblock.tex}} % % \begin{macrocode} %<*ex-mathblock> % \end{macrocode} % % \begin{macrocode} \documentclass{article} \usepackage{url} \usepackage[CJKmath]{xeCJK} \setCJKmainfont[BoldFont=SimHei]{SimSun} \setCJKmonofont{KaiTi} \ExplSyntaxOn \tl_const:Nn \c_test_text_tl { 天地玄黃宇宙洪荒日月盈昃辰宿列張寒來暑往秋收冬藏閏餘成歲律呂調陽 } \cs_new:Npn \test_color:n #1 { \exp_args:No \str_range:nnn { \mdfivesum {#1} } { 1 } { 6 } } \tl_map_inline:Nn \c_test_text_tl { \xeCJKDeclareSubCJKBlock {#1} { `#1 } \setCJKmainfont [ #1 , Color = \test_color:n {#1} , BoldFont = SimHei ] { SimSun } \setCJKmonofont [ #1 ] { KaiTi } } \cs_new_protected:Npn \TEST { \exp_args:No \path { \c_test_text_tl } \par \c_test_text_tl \par $ \c_test_text_tl $ } \ExplSyntaxOff \begin{document} \TEST \bigskip \bfseries\mathversion{bold}\TEST \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xunicode-symbols.tex}} % % \begin{macrocode} %<*xunicode-symbols> % \end{macrocode} % % \begin{macrocode} %<@@=xunsym> % \end{macrocode} % % \begin{macrocode} \documentclass[a4paper]{article} \usepackage[margin=2cm]{geometry} \usepackage{fontspec} \usepackage{xunicode-addon} \usepackage{array,longtable,booktabs} \usepackage{zref-base} \setmainfont{FreeSerif} \newfontfamily\falllbackfont{Segoe UI Symbol} \makeatletter \ExplSyntaxOn \cs_new_protected:Npx \@@_restore_catcode: { \char_set_catcode:nn { 0 } { \char_value_catcode:n { 0 } } } \file_if_exist:nTF { xunicode-commands.tex } { \char_set_catcode_comment:n { 0 } } { \char_set_catcode_ignore:n { 0 } } ^^@ \tl_new:N \l_@@_command_tl ^^@ \int_new:N \l_@@_command_int ^^@ \iow_new:N \g_@@_command_iow ^^@ \iow_new:N \g_@@_combine_mark_iow ^^@ \ior_new:N \g_@@_unicode_ior ^^@ \prop_new:N \l_@@_command_prop ^^@ \prop_new:N \l_@@_combine_mark_prop ^^@ \prop_new:N \l_@@_combine_marks_prop ^^@ \cs_new_protected:Npn \SaveUTFCommands ^^@ { ^^@ \group_begin: ^^@ \@@_restore_catcode: ^^@ \cs_set_eq:NN \DeclareTextAccent \use_none:nnn ^^@ \cs_set_eq:NN \DeclareUTFComposite \use_none:n ^^@ \cs_set_eq:NN \DeclareUTFEncodedAccent \use_none:nnn ^^@ \cs_set_eq:NN \DeclareUTFDoubleEncodedAccent \use_none:nnn ^^@ \cs_set_eq:NN \DeclareUTFDoubleEncodedSymbol \use_none:nnn ^^@ \cs_set_eq:NN \DeclareUTFCommand \use_none:nn ^^@ \cs_set_eq:NN \DeclareUTFTIPACommand \use_none:n ^^@ \cs_set_eq:NN \DeclareUTFCompositeCommand \use_none:nnn ^^@ \cs_set_eq:NN \DeclareUTFSymbol \@@_save_UTF_command:Nn ^^@ \cs_set_eq:NN \DeclareUTFCompositeSymbol \@@_save_UTF_command:Nnn ^^@ \cs_set_eq:NN \DeclareEncodedCompositeCharacter \@@_save_combine_mark:nnnn ^^@ \cs_set_eq:NN \DeclareEncodedCompositeAccents \@@_save_combine_marks:nnnn ^^@ \DeclareDocumentCommand \DeclareUTFcharacter { O { \UTFencname } m m } ^^@ { \@@_save_UTF_command:NNn \l_@@_command_prop {##3} {##2} } ^^@ \DeclareDocumentCommand \DeclareUTFcomposite { O { \UTFencname } m m m } ^^@ { \@@_save_UTF_command:NNnn \l_@@_command_prop {##3} {##4} {##2} } ^^@ \ReloadXunicode { \UTFencname } ^^@ \ior_open:NnTF \g_@@_unicode_ior { UnicodeData.txt } ^^@ { ^^@ \iow_open:Nn \g_@@_command_iow { xunicode-commands.tex } ^^@ \iow_open:Nn \g_@@_combine_mark_iow { xunicode-combine-marks.tex } ^^@ \ior_map_inline:Nn \g_@@_unicode_ior { \@@_make_table:w ##1 \q_stop } ^^@ \@@_write_combine_marks: ^^@ \ior_close:N \g_@@_unicode_ior ^^@ \iow_close:N \g_@@_command_iow ^^@ \iow_close:N \g_@@_combine_mark_iow ^^@ \group_end: ^^@ } ^^@ { ^^@ \group_end: ^^@ \msg_fatal:nn { @@ } { UnicodeData } ^^@ } ^^@ } ^^@ \msg_new:nnn { @@ } { UnicodeData } ^^@ { File~`UnicodeData.txt`~not~found. } ^^@ \cs_new_protected:Npn \@@_save_UTF_command:Nn ^^@ { \@@_save_UTF_command:NNn \l_@@_command_prop } ^^@ \cs_new_protected:Npn \@@_save_UTF_command:Nnn ^^@ { \@@_save_UTF_command:NNnn \l_@@_command_prop } ^^@ \cs_new_protected:Npn \@@_save_UTF_command:NNn #1#2#3 ^^@ { \@@_save_UTF_text_command:Nxx #1 { \use_none:n #3 } { \token_to_str:N #2 } } ^^@ \cs_new_protected:Npn \@@_save_UTF_command:NNnn #1#2#3#4 ^^@ { ^^@ \@@_save_UTF_text_command:Nxx #1 { \use_none:n #4 } ^^@ { ^^@ \token_to_str:N #2 \c_left_brace_str ^^@ \tl_if_single:nTF {#3} { \token_to_str:N #3 } { \tl_to_str:n {#3} } ^^@ \c_right_brace_str ^^@ } ^^@ } ^^@ \cs_new_protected:Npn \@@_save_combine_mark:nnnn #1#2#3#4 ^^@ { \@@_save_UTF_text_command:Nxx \l_@@_combine_mark_prop {#3} { \token_to_str:N #2 } } ^^@ \cs_new_protected:Npn \@@_save_combine_marks:nnnn #1#2#3#4 ^^@ { \@@_save_UTF_text_command:Nxx \l_@@_combine_marks_prop { { "#4 } { "#3 } } { \token_to_str:N #2 } } ^^@ \cs_new_protected:Npn \@@_save_UTF_text_command:Nxx #1#2#3 ^^@ { \use:e { \@@_save_UTF_text_command:Nnn \exp_not:N #1 {#2} {#3} } } ^^@ \cs_new_protected:Npn \@@_save_UTF_text_command:Nnn #1#2#3 ^^@ { ^^@ \prop_get:NnNTF #1 {#2} \l_@@_command_tl ^^@ { \prop_put:Nno #1 {#2} { \l_@@_command_tl , #3 } } ^^@ { \prop_put:Nnn #1 {#2} {#3} } ^^@ } ^^@ \cs_new_protected:Npn \@@_make_table:w #1 ; #2 ; #3 \q_stop ^^@ { ^^@ \prop_get:NnNT \l_@@_command_prop {#1} \l_@@_command_tl ^^@ { ^^@ \iow_now:Nx \g_@@_command_iow ^^@ { \token_to_str:N \UnicodeTextSymbol { "#1 } { \l_@@_command_tl } {#2} } ^^@ } ^^@ \prop_get:NnNT \l_@@_combine_mark_prop {#1} \l_@@_command_tl ^^@ { ^^@ \iow_now:Nx \g_@@_combine_mark_iow ^^@ { \token_to_str:N \UnicodeCombineMark { "#1 } { \l_@@_command_tl } {#2} } ^^@ } ^^@ } ^^@ \cs_new_protected:Npn \@@_write_combine_marks: ^^@ { ^^@ \prop_map_inline:Nn \l_@@_combine_marks_prop ^^@ { ^^@ \iow_now:Nx \g_@@_combine_mark_iow ^^@ { \token_to_str:N \UnicodeCombineMarks ##1 {##2} } ^^@ } ^^@ } ^^@ \ExplSyntaxOff ^^@ \SaveUTFCommands ^^@ \ExplSyntaxOn \@@_restore_catcode: \int_new:N \g_@@_symbol_int \int_new:N \g_@@_table_int \DeclareDocumentCommand \UnicodeTextSymbol { m v m } { \int_gincr:N \g_@@_symbol_int \use_none:n #1 & \scan_stop: \reverse_if:N \tex_iffontchar:D \tex_font:D #1 \exp_stop_f: \falllbackfont \fi: \tex_char:D #1 \exp_stop_f: & \tl_set:Nn \l_tmpa_clist {#2} \clist_use:Nn \l_tmpa_clist { \par } \strut & #3 \\ } \cs_set_eq:NN \UnicodeCombineMark \UnicodeTextSymbol \DeclareDocumentCommand \UnicodeCombineMarks { m m v } { \int_gincr:N \g_@@_symbol_int \use_none:n #1 ~ \use_none:n #2 & \tex_char:D #1 \exp_stop_f: \tex_char:D #2 \exp_stop_f: & \tl_set:Nn \l_tmpa_clist {#3} \clist_use:Nn \l_tmpa_clist { \par } \strut \\ } \DeclareDocumentCommand \UTFTABLE { m m } { \int_gincr:N \g_@@_table_int \exp_args:Nx \@@_make_table:nnn { UTFTABLE - \int_use:N \g_@@_table_int } {#1} {#2} } \cs_new_protected:Npn \@@_make_table:nnn #1#2#3 { \section{#2~(\zref@extractdefault{#1}{default}{0})} \zref@refused{#1} \noindent \begin{longtable}[c]{>{\ttfamily\footnotesize}rc>{\ttfamily\footnotesize}p{55mm}>{\tiny}l} \toprule \multicolumn1c{\normalfont\normalsize USV} & \normalfont\normalsize Symbol & \normalfont\normalsize Macro(s) & \normalfont\normalsize Description \\ \midrule \endhead \bottomrule \endfoot \int_gzero:N \g_@@_symbol_int \input{#3} \end{longtable} \group_begin: \zref@setcurrent{default}{\int_use:N\g_@@_symbol_int} \zref@wrapper@immediate{\zref@labelbyprops{#1}{default}} \group_end: } \cs_generate_variant:Nn \@@_make_table:nnn { x } \ExplSyntaxOff \begin{document} \UTFTABLE{Symbols}{xunicode-commands.tex} \UTFTABLE{Combining Marks}{xunicode-combine-marks.tex} \end{document} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % \endinput