% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*readme> 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; and - automatic adjustment of the space between CJK and other characters. This package is licensed in LPPL. This package consists of the file xeCJK.dtx and the derived files xeCJK.pdf, xeCJK.sty, xeCJK.cfg, xeCJK.ins, xeCJKfntef.sty, 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, and README.txt. (this file). If you are interested in the process of development you may observe http://code.google.com/p/ctex-kit/updates/list Author: Wenchang Sun Current Maintainers: Leo Liu Qing Lee Installation ------------ The package is supplied in dtx format and as a pre-extracted zip file, xecjk.tds.zip. The later is most convenient for most users: simply unzip this in your local texmf directory and run texhash to update the database of file locations. If you want to unpack the dtx yourself, running "xetex xeCJK.dtx" will extract the package whereas "xelatex xeCJK.dtx" will typeset the documentation. The package requires LaTeX3 support as provided in the l3kernel and l3packages bundles and the fontspec package. All of these are available on CTAN as ready-to-install zip files. Suitable versions are available in the latest version of MiKTeX and TeX Live (updating the relevant packages online may be necessary). To compile the documentation without error, you will need some specific CJK scripts fonts (TrueType or OpenType). % %<*internal> \fi \begingroup \edef\tempa{\fmtname} \edef\tempb{plain} \expandafter\endgroup \ifx\tempa\tempb \csname fi\endcsname % %<*install> \input l3docstrip.tex \keepsilent \askforoverwritefalse \preamble $Id: xeCJK.dtx 418 2013-05-29 06:41:21Z sobenlee $ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ ----------------------------------------------------------------- Author: Wenchang Sun Current Maintainers: Leo Liu Qing Lee Copyright (C) 2007--2013 Wenchang Sun (C) 2009--2013 Leo Liu (C) 2012--2013 Qing Lee This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) any later version. 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 Maintainer of this work are Leo Liu and Qing Lee. ----------------------------------------------------------------- \endpreamble \postamble This package consists of the file xeCJK.dtx and the derived files xeCJK.pdf, xeCJK.sty, xeCJK.cfg, xeCJK.ins, xeCJKfntef.sty, 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, and README.txt. \endpostamble \declarepreamble\emptypreamble \endpreamble \declarepostamble\emptypostamble \endpostamble \generate{ \usedir{source/xelatex/xecjk} \file{\jobname.ins}{\from{\jobname.dtx}{install}} \usedir{tex/xelatex/xecjk} \file{\jobname.sty}{\from{\jobname.dtx}{package}} \file{xeCJKfntef.sty}{\from{\jobname.dtx}{fntef}} \usepreamble\emptypreamble \usepostamble\emptypostamble \usedir{tex/xelatex/xecjk/config} \file{\jobname.cfg}{\from{\jobname.dtx}{config}} \usedir{doc/xelatex/xecjk/example} \file{\jobname-example-autofake.tex}{\from{\jobname.dtx}{ex-autofake}} \file{\jobname-example-fallback.tex}{\from{\jobname.dtx}{ex-fallback}} \file{\jobname-example-subCJKblock.tex}{\from{\jobname.dtx}{ex-block}} \file{\jobname-example-CJKecglue.tex}{\from{\jobname.dtx}{ex-ecglue}} \file{\jobname-example-checksingle.tex}{\from{\jobname.dtx}{ex-single}} \file{\jobname-example-CJKfntef.tex}{\from{\jobname.dtx}{ex-fntef}} \file{\jobname-example-punctstyle.tex}{\from{\jobname.dtx}{ex-punctstyle}} \file{\jobname-example-verbatim.tex}{\from{\jobname.dtx}{ex-verb}} \file{\jobname-example-IVS.tex}{\from{\jobname.dtx}{ex-IVS}} \nopreamble\nopostamble \usedir{doc/xelatex/xecjk} \file{README.txt}{\from{\jobname.dtx}{readme}} } \endbatchfile % %<*internal> \fi % %<*driver|package|config|fntef> %<*!config> \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} % \GetIdInfo$Id: xeCJK.dtx 418 2013-05-29 06:41:21Z sobenlee $ %<*!config&!fntef> {Typesetting CJK scripts with XeLaTeX} % % {Configuration file for xeCJK package} % {xeCJK patch file for ulem/CJKfntef} %<*!package&!fntef> \ProvidesExplFile % %<*driver> {\ExplFileName.\ExplFileExtension} % % {\ExplFileName.cfg} %\ProvidesExplPackage % {\ExplFileName} % {xeCJKfntef} {\ExplFileDate}{3.2.1}{\ExplFileDescription} %<*driver> \def\xeCJKversion{3.2.1} \let\xeCJKdate\ExplFileDate \let\xeCJKrevnum\ExplFileVersion \ExplSyntaxOff % % % %<*driver> \expandafter\let\csname ver@thumbpdf.sty\endcsname\empty \documentclass[numbered,a4paper,full]{l3doc} \hypersetup{pdfstartview=FitH} \usepackage{xeCJK} \usepackage{xeCJKfntef} \usepackage{geometry} \usepackage[toc]{multitoc} \fvset{formatcom=\xeCJKVerbAddon} \linespread{1.1} \setlist{noitemsep,topsep=1ex} \newlist{optiondesc}{description}{3} \setlist[optiondesc]{font=\mdseries\ttfamily,align=right,labelsep=.5em,leftmargin=4.5em} \def\PSKeyVal#1#2{\item[#1]\makebox[4em][l]{\meta{#2}}\ignorespaces} \setmainfont[Ligatures=TeX]{TeX Gyre Pagella} \setmonofont{Inconsolata} \setCJKmainfont[BoldFont=Adobe Heiti Std,ItalicFont=Adobe Kaiti Std]{Adobe Song Std} \setCJKmonofont{Adobe Kaiti Std} \xeCJKDeclareSubCJKBlock{HKMD} { "FF65 } \xeCJKDeclareSubCJKBlock{Ext-B} { "20000 -> "2A6DF } \xeCJKDeclareSubCJKBlock{Hangul}{ "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } \setCJKmainfont[HKMD]{Microsoft YaHei} \setCJKmainfont[Ext-B]{SimSun-ExtB} \setCJKmainfont[Hangul]{Adobe Myungjo Std} \xeCJKsetup{PunctStyle=kaiming,KaiMingPunct+={:;}} \def\MacroFont{\small\normalfont\ttfamily\xeCJKVerbAddon} \def\XeTeX{\hologo{XeTeX}} \def\XeLaTeX{\hologo{XeLaTeX}} \def\LaTeX{\hologo{LaTeX}} \def\LaTeXe{\hologo{LaTeX2e}} \parindent=2em \AtBeginDocument{\DeleteShortVerb{\"}\MakeShortVerb{\|}} \def\contentsname{目录} \DeclareUrlCommand\email{\def\UrlLeft##1\UrlRight{\href{mailto:##1}{##1}}} \def\ctexkit{\href{http://code.google.com/p/ctex-kit/}{\texttt{ctex-kit}}} \def\ctexkitrev#1{% \href{http://code.google.com/p/ctex-kit/source/detail?r=#1} {\texttt{ctex-kit} rev#1}} \ExplSyntaxOn \cs_new_nopar:Npn \package #1 { \href { http://mirrors.ctan.org/help/Catalogue/entries/ \tl_expandable_lowercase:n {#1} .html } { \pkg {#1} } } \ExplSyntaxOff \geometry{includemp,hmargin={0mm,15mm},vmargin=15mm,footskip=7mm} \makeatletter \appto\GlossaryParms{% \def\@idxitem{\par\hangindent 2em}% \def\subitem{\@idxitem\hspace*{1em}}% \def\subsubitem{\@idxitem\hspace*{2em}}} \patchcmd\changes@{\space}{\lbrack}{}{} \patchcmd\@wrglossary{hdpindex}{hdclindex{\the\c@HD@hypercount}}{}{} \let\orig@meta\meta \def\meta#1{% \orig@meta{\mbox{\normalfont\itshape\xeCJKsetup{PunctStyle=plain,CJKecglue}#1}}} \def\TF{true\orvar{}false} \def\TTF{\defaultvar{true}\orvar{}false} \def\TFF{true\orvar\defaultvar{false}} \chardef\orvar`\| \let\defaultvar\textbf \@addtoreset{CodelineNo}{section} \def\tokslink#1{\hyperlink{#1}{\ding{51}}} \makeatother \def\indexname{代码索引} \def\glossaryname{版本历史} \GlossaryPrologue{% \addtocounter{secnumdepth}{-10}% \section{\glossaryname}} \IndexPrologue{% \section{\indexname}% 斜体的数字表示对应项说明所在的页码,下划线的数字表示定义所在的代码行号,而直立体的 数字表示对应项使用时所在的行号。} \begin{document} \DocInput{\jobname.dtx} \newgeometry{margin=15mm,footskip=7mm} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{4034} % \changes{v3.1.0}{2012/11/13}{放弃对 \cs{outer} 宏的特殊处理。} % \changes{v3.1.1}{2012/12/07}{不再依赖 \pkg{xpatch} 宏包。} % % % \title{\bfseries\pkg{xeCJK} 宏包} % \author{\href{http://www.ctex.org}{ctex.org}} % \date{\xeCJKdate\qquad\xeCJKversion\thanks{\ctexkitrev{\xeCJKrevnum}.}} % \maketitle % % \tableofcontents % \vspace{\baselineskip} % % \begin{documentation} % % \section{简介} % % \pkg{xeCJK} 是一个 \XeLaTeX 宏包,用于排版中日韩(CJK)文字。主要功能: % \begin{enumerate}[labelindent=\parindent,leftmargin=*] % \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} 依赖 \hologo{LaTeX3} 项目的宏包套件 \package{l3kernel} 和 % \package{l3packages}。\pkg{xeCJK} 还需要通过 \package{fontspec} 宏包来调用系统字 % 体。将在 \ref{subsec:opts}~节介绍的功能选项 |CJKnumber| 需要 \package{CJK} 宏包套 % 件中的 \pkg{CJKnumb} 的支持;|indentfirst| 选项需要 \package{indentfirst} 宏包。 % \pkg{xeCJK} 会自动根据需要载入这些宏包。 % % \pkg{xeCJK} 的原始作者是孙文昌,2009 年 5 月起宏包被收入 \ctexkit\ 项目进行 % 维护,目前主要维护者是刘海洋\footnote{\email{leoliu.pku@gmail.com}} 和 % 李清\footnote{\email{sobenlee@gmail.com}}。 % % \section{基本用法} % % 与其他 \LaTeX{} 宏包一样,引入 \pkg{xeCJK} 宏包只要在导言区使用 % \begin{verbatim} % \usepackage{xeCJK} % \end{verbatim} % 在引入 \pkg{xeCJK} 宏包之后,只要设置 CJK 文字的字体,就可以在文档中使用中日 % 韩文字了。 % % 可以在各种文档类中使用 \pkg{xeCJK} 宏包,最简单的示例是: % \begin{verbatim} % \documentclass{article} % \usepackage{xeCJK} % \setCJKmainfont{SimSun} % % \begin{document} % 中文 \LaTeX 示例。 % \end{document} % \end{verbatim} % 上述示例设置了中文字体 SimSun(宋体)。运行此示例要求系统安装了设置的字体, % 源文件用 UTF-8 编码保存,使用 \XeLaTeX{} 编译。 % % \pkg{xeCJK} 只提供了字体和标点控制等基本 CJK 语言支持。对于中文文档,可以使 % 用更为高层的 \package{ctex} 宏包或文档类,它将自动调用 \pkg{xeCJK} 并设置好中文 % 字体,同时提供了进一步的本地化支持。详细内容参看 \package{ctex} 宏包套件的说明。 % % \pkg{xeCJK} 提供了大量选项,可以在宏包调用时作为宏包选项或用 \cs{xeCJKsetup} % 命令进行设置,详见 \ref{subsec:opts}~节。除了 \cs{setCJKmainfont} 命令, % \pkg{xeCJK} 还提供了许多其他命令设置和选择中文字体,详见 % \ref{subsec:fontset}~节。其他更详细的功能也都将在下面详细说明。在本文档所在的 % 文件夹的 |example| 目录下面也有一些例子可以参考。 % % \section{用户手册} % % \subsection{宏包选项} % \label{subsec:opts} % % \pkg{xeCJK} 以 \meta{key}|=|\meta{var} 的形式提供宏包选项,你可以在调用宏包 % 的时候直接设置这些选项,也可以在调用宏包之后使用 \cs{xeCJKsetup} 来设置这些选 % 项。\pkg{xeCJK} 内部调用 \pkg{fontspec} 宏包,可以在调用 \pkg{xeCJK} 的时候, % 使用它的宏包选项。\pkg{xeCJK} 会将 \pkg{fontspec} 的选项传递给它。 % % \begin{function}{\xeCJKsetup} % \begin{syntax} % \cs{xeCJKsetup} \{\meta{key_1}=\meta{var_1}, \meta{key_2}=\meta{var_2}, ...\} % \end{syntax} % 其中 \meta{key_1}, \meta{key_2} 是设置选项,而 \meta{val_1}, \meta{val_2} 则是对应选项的 % 设置内容。多个选项可以在一个语句中完成设置。例如 % \begin{verbatim} % \usepackage[PunctStyle=kaiming]{xeCJK} % \end{verbatim} % 等价于 % \begin{verbatim} % \usepackage{xeCJK} % ...... % \xeCJKsetup{PunctStyle=kaiming} % \end{verbatim} % \end{function} % % 有些选项或命令后面带有 \hypertarget{expstar}{\hyperlink{expstar}{$\star$}} 号,这表示这 % 个选项或命令只能在导言区中使用,而 \hypertarget{rexpstar}{\hyperlink{rexpstar}{\ding{73}}} % 号则表示这个选项或命令只能在导言区使用,并且只影响随后定义的 CJK 字体。其余不带特殊标记的 % 选项或命令,如果没有特别说明,可以在导言区或正文中使用。% % 使用粗体来表示 \pkg{xeCJK} 的默认设置。 % % \begin{function}[EXP,added=2012-11-22]{LocalConfig} % \begin{syntax} % LocalConfig = \marg{\TTF\orvar{}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{verbatim} % texlive/texmf-local/tex/xelatex/xecjk % \end{verbatim} % 最后还需要在命令行下执行 |mktexlsr|,刷新文件名数据库以便 \TeX 系统能够找到它。 % \end{function} % % \begin{function}[EXP]{CJKnumber} % \begin{syntax} % CJKnumber = \meta{\TFF} % \end{syntax} % 为了与 \pkg{CJKnumb} 宏包兼容,\pkg{xeCJK} 作了一些特别处理。因此,如果需要使用 % 到 \pkg{CJKnumb},请通过这个选项调用它。 % \end{function} % % \begin{function}[EXP,updated=2012-11-22]{indentfirst} % \begin{syntax} % indentfirst = \meta{\TTF} % \end{syntax} % 是否使用 \pkg{indentfirst} 宏包,使得跟在章节标题后面的第一段首行也缩进。\bigskip % \end{function} % % 请注意,\pkg{xeCJK} 宏包中只有上述 |LocalConfig|、|CJKnumber| 和 |indentfirst| % 这三个选项需要在调用 \pkg{xeCJK} 时设置,而不能通过 \cs{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]{CJKmath} % \begin{syntax} % CJKmath = \meta{\TFF} % \end{syntax} % 是否支持在数学环境中直接输入 CJK 字符。使用这个选项后,可以直接在数学环境中 % 输出 CJK 字符。 % \end{function} % % \begin{function}{CJKglue} % \begin{syntax} % CJKglue = \{\cs{hskip} 0pt plus 0.08\cs{baselineskip}\} % \end{syntax} % 设置 CJK 文字之间插入的 |glue|,上边是 \pkg{xeCJK} 的默认值。一般来说,除非有 % 特殊需要(例如,改变文字间距等),否则不需要设置这个选项,使用默认值即可。如果要设置 % 这个选项,为了行末的对齐,设置的 |glue| 最好有一定的弹性。 % \end{function} % % \begin{function}{CJKecglue} % \begin{syntax} % CJKecglue = \Arg{glue} % \end{syntax} % 设置 CJK 文字与西文、CJK 文字与行内数学公式之间的间距,默认值是一个空格。使用这个 % 选项设置的 |glue| 最好也要用一定的弹性。请注意,这里设置的 |glue| 只影响 % \pkg{xeCJK} 根据需要自动添加的空白,源文件中直接输入的 CJK 文字与西文之间的空格不 % 受影响(直接输出)。有时候 \pkg{xeCJK} 可能不能正确地调整间距,需要手动加空格。 % \end{function} % % \begin{function}{xCJKecglue} % \begin{syntax} % xCJKecglue = \marg{\TFF\orvar{}glue} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 不对源文件中直接输入的 CJK 文字与西文之间的空格进行调整,如 % 果需要调整,请使用这个选项。如果使用这个选项,将使用 |CJKecglue| 替换源文件中直接输 % 入的 CJK 文字与西文之间的空格。 % \end{function} % % \begin{function}[updated=2012-12-06]{CheckSingle} % \begin{syntax} % CheckSingle = \meta{\TFF} % \end{syntax} % 是否避免单个 CJK 文字单独占一个段落的最后一行。需要说明的是,这个选项只有在 % 段末的最后一个字是 CJK 文字或者标点符号,并且倒数第二和第三个字都是文字才能 % 正确处理处理孤字的问题。如果这倒数三个字有作为控制序列的参数的情况,那么一般 % 来说也不能正确处理。 % \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 = \{ \cs{par} \cs{[} \} % \end{syntax} % 设置造成断行的控制序列,以便 |CheckSingle| 选项能够正确识别。 % 以上是 \pkg{xeCJK} 的初始设置。 % \end{function} % % \begin{function}[added=2012-12-04]{EnvCS,EnvCS+,EnvCS-} % \begin{syntax} % EnvCS = \{ \cs{begin} \cs{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 = \marg{\TFF\orvar{}数字} % \end{syntax} % 全局设定当没有声明对应的粗体时,是否使用\textbf{\CJKfontspec[AutoFakeBold]{Adobe Song Std}伪粗体}; % 当输入的是数字时,将使用伪粗体,并将使用输入的数字作为伪粗体的默认粗细程度。 % \end{function} % % \begin{function}[rEXP]{AutoFakeSlant} % \begin{syntax} % AutoFakeSlant = \marg{\TFF\orvar{}数字} % \end{syntax} % 全局设定当没有声明对应的斜体时,是否使用\textit{\CJKfontspec[AutoFakeSlant]{Adobe Song Std}伪斜体}; % 当输入的是数字时,将使用伪斜体,并将使用输入的数字作为伪斜体的默认倾斜程度。 % \end{function} % % \begin{function}[rEXP]{EmboldenFactor} % \begin{syntax} % EmboldenFactor = \marg{数字\orvar\defaultvar{4}} % \end{syntax} % 设置伪粗体的默认粗细程度。 % \end{function} % % \begin{function}[rEXP]{SlantFactor} % \begin{syntax} % SlantFactor = \marg{数字\orvar\defaultvar{0.167}} % \end{syntax} % 设置伪斜体的粗细程度,范围是 $-0.999 \sim 0.999$。 % \end{function} % % \begin{function}[updated=2012-11-10]{PunctStyle} % \begin{syntax} % PunctStyle = \marg{\defaultvar{quanjiao}\orvar{}banjiao\orvar{}kaiming\orvar{}hangmobanjiao\orvar{}CCT\orvar{}plain\orvar{}...} % \end{syntax} % 设置标点处理格式。\pkg{xeCJK} 中预先定义好的格式为 % \begin{description}[font=\mdseries\ttfamily,align=right,labelsep=1em,labelindent=2em,leftmargin=*] % \item[quanjiao] 全角式:所有标点占一个汉字宽度,相邻两个标点占 1.5 汉字宽度; % \item[banjiao] 半角式:所有标点占半个汉字宽度; % \item[kaiming] 开明式:句末点号用全角,其他半角; % \item[hangmobanjiao] 行末半角式:所有标点占一个汉字宽度,行首行末对齐; % \item[CCT] CCT 格式; % \item[plain] 原样(不调整标点间距)。 % \end{description} % 可以使用 \ref{subsec:punctstyle} 中介绍的 \cs{xeCJKDeclarePunctStyle} 定义新的标点 % 格式。 % \end{function} % % \begin{function}[EXP]{KaiMingPunct,KaiMingPunct+,KaiMingPunct-} % \begin{syntax} % KaiMingPunct = \marg{\defaultvar{ . 。? !}} % \end{syntax} % 设置开明(|kaiming|)标点处理格式时的句末点号,|KaiMingPunct| 后带的 |+| 与 |-| % 分别表示从已有的开明句末点号中增加或减少标点。 % \end{function} % % \begin{function}[EXP]{LongPunct,LongPunct+,LongPunct-} % \begin{syntax} % LongPunct = \marg{\defaultvar{ — ― ─ ‥ … }} % \end{syntax} % 设置长标点,例如破折号“——”与省略号“……”,允许在长标点前后 % 断行,但是禁止在它们之间断行。 % \end{function} % % \begin{function}[EXP]{MiddlePunct,MiddlePunct+,MiddlePunct-} % \begin{syntax} % MiddlePunct = \marg{\defaultvar{ — ― ─ · · ・ }} % \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}~节的 % \cs{xeCJKsetwidth}。 % \end{function} % % \begin{function}{AllowBreakBetweenPuncts} % \begin{syntax} % AllowBreakBetweenPuncts = \meta{\TFF} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 禁止在相邻 CJK 右标点和 CJK 左标点之间换行,可以使用 % 这一选项改变这一设置。 % \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 = \{ \cs{footnote} \cs{footnotemark} \cs{nobreak} \} % \end{syntax} % 设置不能在全角右标点后断行的控制序列。以上是 \pkg{xeCJK} 的默认设置。如果这些 % 控制序列在文档中只出现少量几次,也可以不必使用 |CheckFullRight| 选项,而是手工 % 在这些控制序列前面加上 \ref{subsec:others}~节介绍的 \cs{xeCJKnobreak}。 % \end{function} % % \begin{function}[updated=2013-05-29]{Verb} % \begin{syntax} % Verb = \meta{\TF\orvar\defaultvar{env}\orvar{}env+} % \end{syntax} % \texttt{true} 表示在 \cs{verb} 命令或 \texttt{verbatim} 环境里不自动调整中英文 % 之间的间距。\texttt{env} 选项在 \texttt{verbatim} 环境里自动计算中西文间距和中文 % 之间的间距,以便于保持代码的对齐;\texttt{env} 选项不调整 \cs{verb} 里的间距,^^A % \texttt{env+} 选项还将正文里设置的间距应用到 \cs{verb} 里。^^A % 这个选项对使用到 \cs{verbatim@font} 命令的情形均有效,更一般的情况可以使用 % \ref{subsec:others}~节介绍的 \cs{xeCJKVerbAddon}。 % \end{function} % % \subsection{字体设置与选择} % \label{subsec:fontset} % % \begin{function}[EXP]{\setCJKmainfont} % \begin{syntax} % \cs{setCJKmainfont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置正文罗马族的 CJK 字体,影响 \cs{rmfamily} 和 \cs{textrm} 的字体。后面两个 % 参数继承自 \pkg{fontspec} 宏包, \meta{font features} 表示字体属性选项, % \meta{font name} 是字体名。字体名可以是字体族名,也可以是字体的文件名,查 % 找字体名见 \ref{subsubsec:fontsearch}~节;可用的字体属性选项参见 % \pkg{fontspec} 宏包的文档。需要说明的是 \pkg{xeCJK} 修改了 |AutoFakeBold| % 和 |AutoFakeSlant| 选项,以便配合全局伪粗体和伪斜体的设定。 % \end{function} % % \begin{function}{AutoFakeBold,AutoFakeSlant} % \begin{syntax} % AutoFakeBold = \marg{\TF\orvar{}数字} % AutoFakeSlant = \marg{\TF\orvar{}数字} % \end{syntax} % 局部设置当前字体族的伪粗和伪斜属性。如果没有在局部给出这些选项,将使用全局设定。 % \end{function} % % \begin{function}[EXP]{\setCJKsansfont} % \begin{syntax} % \cs{setCJKsansfont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置正文无衬线族的 CJK 字体,影响 \cs{sffamily} 和 \cs{textsf} 的字体。 % \end{function} % % \begin{function}[EXP]{\setCJKmonofont} % \begin{syntax} % \cs{setCJKmonofont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置正文等宽族的 CJK 字体,影响 \cs{ttfamily} 和 \cs{texttt} 的字体。 % \end{function} % % \begin{function}[EXP]{\setCJKfamilyfont} % \begin{syntax} % \cs{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} % \cs{CJKfamily} \Arg{family} % \cs{CJKfamily+} \Arg{family} % \cs{CJKfamily-} \Arg{family} % \end{syntax} % 用于在文档中切换 |CJK| 字体族,\meta{family} 必须预先声明。\cs{CJKfamily} 仅对 % CJK 字符类有效,\cs{CJKfamily+} 对所有字符类均有效,\cs{CJKfamily-} 对非 CJK 字 % 符类有效。当 \cs{CJKfamily+} 和 \cs{CJKfamily-} 的参数为空时,则使用当前的 |CJK| 字体族。 % \end{function} % % \begin{function}[EXP]{\newCJKfontfamily} % \begin{syntax} % \cs{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}。事实上,\cs{newCJKfontfamily} 是 \cs{setCJKfamilyfont} 和 % \cs{CJKfamily} 的合并。例如 % \begin{verbatim} % \newCJKfontfamily[song]\songti{SimSun} % \end{verbatim} % 等价于 % \begin{verbatim} % \setCJKfamilyfont{song}{SimSun} % \newcommand*{\songti}{\CJKfamily{song}} % \end{verbatim} % \end{function} % % \begin{function}{\CJKfontspec} % \begin{syntax} % \cs{CJKfontspec} \oarg{font features} \Arg{font name} % \end{syntax} % 在文档中随机定义新的 CJK 字体族,并马上使用它。 % \end{function} % % \begin{function}[rEXP]{\defaultCJKfontfeatures} % \begin{syntax} % \cs{defaultCJKfontfeatures} \Arg{font features} % \end{syntax} % 全局设置 CJK 字体族的默认选项。例如,使用 % \begin{verbatim} % \defaultCJKfontfeatures{Scale=0.962216} % \end{verbatim} % 可以将全部 CJK 字体缩小为 |0.962216|。\pkg{xeCJK} 宏包的初始化设置是 % \begin{verbatim} % \defaultCJKfontfeatures{Script=CJK} % \end{verbatim} % \end{function} % % \begin{function}{\addCJKfontfeatures} % \begin{syntax} % \cs{addCJKfontfeatures} \Arg{font features} % \end{syntax} % 临时增加当前使用的 CJK 字体的选项。例如,使用 % \begin{verbatim} % \addCJKfontfeatures{Scale=1.1} % \end{verbatim} % 可以将文档中当前使用的 CJK 字体放大为 |1.1|。 % \end{function} % % \begin{function}{\CJKrmdefault} % 保存 \cs{textrm} 和 \cs{rmfamily} 所使用的 CJK 字体族,默认值是 |rm|。 % 类似西文字体的 \cs{rmdefault}。 % \end{function} % % \begin{function}{\CJKsfdefault} % 保存 \cs{textsf} 和 \cs{sffamily} 所使用的 CJK 字体族,默认值是 |sf|。 % 类似西文字体的 \cs{sfdefault}。 % \end{function} % % \begin{function}{\CJKttdefault} % 保存 \cs{texttt} 和 \cs{ttfamily} 所使用的 CJK 字体族,默认值是 |tt|。 % 类似西文字体的 \cs{ttdefault}。 % \end{function} % % \begin{function}[updated=2013-01-01]{\CJKfamilydefault} % 保存 \cs{textnormal} 和 \cs{normalfont} 所使用的 CJK 字体族。类似西文字体的 \cs{familydefault}。 % 初始值是 \cs{CJKrmdefault}。如果没有在导言区中修改它,\pkg{xeCJK} 会在导言区 % 结束的时候根据西文字体的情况自动更新 \cs{CJKfamilydefault}。因此,在导言区里使用 % \begin{verbatim} % \renewcommand\familydefault{\sfdefault} % \end{verbatim} % 就可以将全文的 CJK 和西文默认字体都改为无衬线字体族。 % \end{function} % % \begin{function}[EXP]{\setCJKmathfont} % \begin{syntax} % \cs{setCJKmathfont} \oarg{font features} \Arg{font name} % \end{syntax} % 设置数学公式中的 CJK 字体族。如果使用了 |CJKmath| 选项,但是没有使用 % \cs{setCJKmathfont} 设置数学公式中的 CJK 字体,那么将使用 \cs{CJKfamilydefault} % 作为数学公式中的 CJK 字体。 % \end{function} % % \begin{function}[EXP]{\setCJKfallbackfamilyfont} % \begin{syntax} % \cs{setCJKfallbackfamilyfont} \Arg{family} \oarg{font features} \Arg{font name} % \end{syntax} % 设置 CJK 字体族 \meta{family} 的备用字体。例如,使用 % \begin{verbatim} % \setCJKmainfont{SimSun} % \setCJKfallbackfamilyfont{\CJKrmdefault}{SimSun-ExtB} % \end{verbatim} % 可以将 |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{verbatim} % \setCJKmainfont[FallBack=SimSun-ExtB]{SimSun} % \end{verbatim} % 如果 |FallBack| 的值为空,将设置的是备用字体。例如, % \begin{verbatim} % \setCJKmainfont[FallBack,AutoFakeBold,Scale=.97]{SimSun-ExtB} % \end{verbatim} % 等价于 % \begin{verbatim} % \setCJKfallbackfamilyfont{\CJKrmdefault}[AutoFakeBold,Scale=.97]{SimSun-ExtB} % \end{verbatim} % \end{function} % % \begin{function}[EXP]{\setCJKfallbackfamilyfont} % \begin{syntax} % \cs{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} % \cs{setCJKfallbackfamilyfont} 还可以用于设置多层的备用字体。例如,使用 % \begin{verbatim} % \setCJKmainfont[AutoFakeBold,AutoFakeSlant]{KaiTi_GB2312} % \setCJKfallbackfamilyfont{\CJKrmdefault}[AutoFakeSlant] % { [BoldFont=SimHei]{SimSun} , % [AutoFakeBold] {SimSun-ExtB} } % \end{verbatim} % 之后,就设置了 |SimSun| 是 |KaiTi_GB2312| 的备用字体,而 |SimSun-ExtB| 是 % |SimSun| 的备用字体。 % \end{function} % % \subsubsection{\XeTeX 的字体名查找} % \label{subsubsec:fontsearch} % % 由于在 \pkg{fontspec} 宏包文档中缺少关于如何查看 \XeTeX{} 可用字体名的说明, % 这里略作说明。 % % \XeTeX{} 通常使用 fontconfig 库查找和调用字体,因此,可以用 |fc-list| 命令显 % 示可用的字体。在命令行(Windows 的“命令提示符”,Linux 的 Console)下运行以 % 下命令: % \begin{verbatim} % fc-list > fontlist.txt % \end{verbatim} % 可以将系统中所有安装的字体列表存入 \file{fontlist.txt} 文件中(可能很长)。 % % |fc-list| 命令列出的信息很多,而且在安装字体较多的 Windows 系统上的输出将非 % 常庞大,如其中可能包含: % \begin{verbatim}[formatcom=\fontspec{CMU Typewriter Text}\xeCJKVerbAddon] % 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{verbatim} % 在 \pkg{fontspec} 或 \pkg{xeCJK} 中使用的字体族名是上面列表中冒号前的部分。 % 例如可以使用 % \begin{verbatim} % \setmainfont{Times New Roman} % \setCJKmainfont{SimSun} % 或者 \setCJKmainfont{宋体} % \end{verbatim} % 来设置字体。 % % 为了方便起见,|fc-list| 命令也可以加上各种选项控制输出格式,例如如果只要列出 % 所有的中文字体的字体族名,可以用命令: % \begin{verbatim} % fc-list -f "%{family}\n" :lang=zh > zhfont.txt % \end{verbatim} % 这样就把字体列表保存在文件 \file{zhfont.txt} 中\footnote{由于汉字编码原因, % Windows 下总需要把字体列表输出的文件中防止乱码。}。这样列出的字体列表就比较 % 简明易用,如 Windows 下预装的中文字体: % \begin{verbatim} % Arial Unicode MS % FangSong,仿宋 % KaiTi,楷体 % Microsoft YaHei,微软雅黑 % MingLiU,細明體 % NSimSun,新宋体 % PMingLiU,新細明體 % SimHei,黑体 % SimSun,宋体 % \end{verbatim} % 要列出日文和韩文的字体,可以把 |:lang=zh| 选项中的 |zh| 改成 |ja| 或 |ko|。 % % \pkg{fontspec} 和 \pkg{xeCJK} 也可以使用字体的文件名访问字体。例如 Windows % 下的宋体也可以使用命令: % \begin{verbatim} % \setCJKmainfont{simsun.ttc} % \end{verbatim} % 来设置。设置字体文件名的相关选项和语法在 \pkg{fontspec} 宏包手册中叙述甚详, % 这里不再赘述。有个别字体名不规范的中文字体,\pkg{xeCJK} 宏包可能无法正确地通 % 过字体名访问,那么也可以使用这种方式设置。 % % \subsection{CJK 分区字体设置} % \label{subsec:block} % % 众所周知,CJK 文字数量极其庞大,单一的字体不可能涵盖所有的 CJK 文字。\pkg{xeCJK} 可 % 以在同一 CJK 字体族下,自动使用不同的字体输出 CJK 字符范围内不同区块里的文字。首先要 % 声明 CJK 子分区。 % % \begin{function}[EXP]{\xeCJKDeclareSubCJKBlock} % \begin{syntax} % \cs{xeCJKDeclareSubCJKBlock} \Arg{block} \Arg{block range} % \cs{xeCJKDeclareSubCJKBlock*} \Arg{block} \Arg{block range} % \end{syntax} % 其中 \meta{block range} 是逗号列表,可以是 CJK 字符的 |Unicode| 范围,也可以是单个字符 % 的 |Unicode|。例如 % \begin{verbatim} % { `中 -> `文 , "3400 -> "4DBF , "5000 -> "7000 , `汉 , `字 , "3500 } % \end{verbatim} % 的形式。需要注意的是,这里设置的 \meta{block range} 除非确实需要(例如某些特殊字体使用 % 了 |Unicode| 中的私人使用区的情况),否则不要超出源代码中预设的 % \hyperlink{CJKcharclass}{CJK 文字范围}。使用 % \begin{verbatim} % \xeCJKDeclareSubCJKBlock{SPUA}{ "E400 -> "E4DA , "E500 -> "E5E8 , "E600 -> "E6CE } % \xeCJKDeclareSubCJKBlock{Ext-B}{ "20000 -> "2A6DF } % \end{verbatim} % 就声明了 |SPUA| 和 |Ext-B| 这两个个子分区。同时在 \ref{subsec:fontset} 节介绍的 % CJK 字体设置命令的 \meta{font features} 里新建了 |SPUA| 和 |Ext-B| 这两个选项。 % 新建的这两个选项的使用方法跟 \ref{subsec:fontset} 介绍的 |FallBack| 类似。可以 % 通过它们来设置字体。\strut % \end{function} % % 例如,可以使用 % \begin{verbatim} % \setCJKmainfont[SPUA=SunmanPUA,Ext-B=SimSun-ExtB]{SimSun} % \end{verbatim} % 设置文档的主字体是 |SimSun|,|SPUA| 分区的字体是 |SunmanPUA|,而 |Ext-B| 分区 % 的字体是 |SimSun-ExtB|。 % % \cs{xeCJKDeclareSubCJKBlock} 应该在声明所有的 CJK 字体族之前使用。如果有某个 CJK 字 % 体族没有设置 \meta{block} 选项,将使用 \cs{CJKfamilydefault} 的 \meta{block} 选项 % 作为该 CJK 字体族的 \meta{block} 选项。如果希望在使用某 CJK 字体族时,不在 CJK 主 % 分区与 \meta{block} 之间切换字体,可以使用 \meta{block}|=*| 选项。带星号的命令除了 % 设置 CJK 子分区以外,还重置标点符号所属的字符类。 % % \begin{function}{\xeCJKCancelSubCJKBlock} % \begin{syntax} % \cs{xeCJKCancelSubCJKBlock} \Arg{block_1, block_2, ...} % \cs{xeCJKCancelSubCJKBlock*} \Arg{block_1, block_2, ...} % \end{syntax} % 在文档中取消对 |CJK| 分区的声明。带星号的命令还重置标点符号所属的字符类。 % \end{function} % % \begin{function}{\xeCJKRestoreSubCJKBlock} % \begin{syntax} % \cs{xeCJKRestoreSubCJKBlock} \Arg{block_1, block_2, ...} % \cs{xeCJKRestoreSubCJKBlock*} \Arg{block_1, block_2, ...} % \end{syntax} % 在文档中恢复对 |CJK| 分区的声明。带星号的命令还重置标点符号所属的字符类。 % \end{function} % % \subsection{设置 CJK 字符范围} % % \begin{function}[EXP]{\xeCJKDeclareCharClass} % \begin{syntax} % \cs{xeCJKDeclareCharClass} \Arg{class} \Arg{class range} % \cs{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} % \begin{syntax} % \cs{xeCJKResetCharClass} % \end{syntax} % 用于恢复 \pkg{xeCJK} 对各个字符类别的初始化设置。 % \end{function} % % \begin{function}[EXP]{\xeCJKResetPunctClass} % \begin{syntax} % \cs{xeCJKResetPunctClass} % \end{syntax} % 用于重置标点符号所属的字符类。 % \end{function} % % \begin{function}{\normalspacedchars} % \begin{syntax} % \cs{normalspacedchars} \Arg{char list} % \end{syntax} % 在 \meta{char list} 中出现的字符两端不自动添加空格,初始设置是 |/|。 % \end{function} % % \subsection{标点符号的处理} % % \pkg{xeCJK} 对标点符号的输出宽度的调整是通过调整其左边或右边的空白宽度来实现的。 % 按照目前的处理方式,对于位于左边的标点符号(如左引号),\pkg{xeCJK} 只能调整它 % 左边的空白;对于位于右边的标点符号(如右引号),\pkg{xeCJK} 只能调整它右边的空 % 白;对于居中的标点符号,则调整其左右空白,以保证其居中。 % % \subsubsection{设置特定标点符号的宽度和间距} % \label{subsec:punct} % % 这里的设置可用于除 |plain| 以外的所有标点处理格式。 % % \begin{function}[EXP]{\xeCJKsetwidth} % \begin{syntax} % \cs{xeCJKsetwidth} \Arg{标点列表} \Arg{length} % \end{syntax} % \meta{标点列表}可以是单个标点,也可以是多个标点。例如, % \begin{verbatim} % \xeCJKsetwidth{。?}{0.7em} % \end{verbatim} % 将设置句号和问号所占的宽度为 |0.7 em|。 % \end{function} % % \begin{function}[EXP]{\xeCJKsetkern} % \begin{syntax} % \cs{xeCJKsetkern} \Arg{前标点} \Arg{后标点} \Arg{length} % \end{syntax} % \pkg{xeCJK} 会根据选定的标点处理格式自动调整相邻的前后两个 |CJK| 标点符号的 % 空白宽度。如果需要对个别情况进行特殊调整,可以使用这个命令。例如, % \begin{verbatim} % \xeCJKsetkern{:}{“}{0.3em} % \end{verbatim} % 将设置冒号与左双引号之间的空白宽度为 |0.3 em|。 % \end{function} % % \subsubsection{定义标点符号处理格式} % \label{subsec:punctstyle} % % \begin{function}[EXP,added=2012-11-10]{\xeCJKDeclarePunctStyle} % \begin{syntax} % \cs{xeCJKDeclarePunctStyle} \Arg{style} \Arg{options} % \end{syntax} % 定义新的标点符号处理格式,已经存在的同名格式将被覆盖。可以设置的选项将在下面介绍。 % \end{function} % % \begin{function}[EXP,added=2012-11-10]{\xeCJKEditPunctStyle} % \begin{syntax} % \cs{xeCJKEditPunctStyle} \Arg{style} \Arg{options} % \end{syntax} % 修改已有的标点符号处理格式。\strut % \end{function} % % 下面是可以设置的标点符号格式选项。其中左边一栏是选项名称,中间是选项的输入值类 % 型,右边则是相关说明。某些选项之间是互斥的,具有优先级关系。要使下一级的选项有 % 效,则需要先禁用上一级的设置:对于 \meta{boolean} 类型的选项,将其设置为 |false|, % 对于 \meta{length} 类型的选项,将其设置为 \cs{maxdimen},而对于 \meta{real} 类型 % 的选项,将其设置为 |0|。 % % \begin{optiondesc} % \PSKeyVal{enabled-global-setting}{boolean} % 是否使用 \cs{xeCJKsetup} 的 |PunctWidth| 选项和 \cs{xeCJKsetwidth}、 % \cs{xeCJKsetkern} 的设置。默认值是 |true|。 % \end{optiondesc} % % \begin{optiondesc} % \PSKeyVal{fixed-punct-width}{length} % 设置单个标点符号的宽度。默认值是 \cs{maxdimen}。 % \PSKeyVal{fixed-punct-ratio}{real} % 设置单个标点符号的输出宽度与实际宽度的比例。默认值是 |1.0|。 % \PSKeyVal{mixed-punct-width}{length} % 设置句末标点符号的宽度。其中句末标点符号通过 \cs{xeCJKsetup} 的 |KaiMingPunct| % 来设置。默认值是与 |fixed-punct-width| 选项的值相同。 % \PSKeyVal{mixed-punct-width}{real} % 设置句末标点符号的宽度比例。默认值是与 |fixed-punct-ratio| 选项的值相同。 % \PSKeyVal{middle-punct-width}{length} % 设置居中标点符号的宽度。其中居中标点符号通过 \cs{xeCJKsetup} 的 |MiddlePunct| % 来设置。默认值是与 |fixed-punct-width| 选项的值相同。 % \PSKeyVal{middle-punct-width}{real} % 设置居中标点符号的宽度比例。默认值是与 |fixed-punct-ratio| 选项的值相同。 % \end{optiondesc} % % 以上三个选项设置的是标点的固定宽度或比例,\pkg{xeCJK} 会根据设定的选项计算标点符号 % 左/右的空白宽度。下面的选项设置的是标点符号左/右的空白宽度或比例,因此不同标点符号 % 的宽度可能会不同。为了使下面的选项生效,需要先禁用上面的相应选项。优先级自上而下。 % % \begin{optiondesc} % \PSKeyVal{fixed-margin-width}{length} % 设置标点的左/右空白宽度。默认值是 \cs{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{optiondesc} % % \begin{optiondesc} % \PSKeyVal{add-min-bound-to-margin}{boolean} % 是否在以上计算结果的基础上再加上标点的左右实际边界宽度中的最小值。这个选项 % 对居中的标点无效。默认值是 |false|。 % \end{optiondesc} % % \begin{optiondesc} % \PSKeyVal{optimize-margin}{boolean} % 使用以上设置空白宽度或比例的选项时,最终输出的标点符号左/右的空白宽度可能大 % 于原来的实际边界宽度。若此时本选项被设置为 |true|,则使用原来的实际边界宽度。 % 而使用 |fixed-punct-width| 选项计算得出的左/右宽度可能小于该标点的另一侧宽 % 度,若此时本选项被启用,则使用该标点的另一侧宽度。默认值为 |false|。 % \end{optiondesc} % % \begin{optiondesc} % \PSKeyVal{margin-minimum}{length} % 指定标点符号左/右的最小空白宽度。当经过以上选项设置的空白宽度小于这个选项的值 % 时,则使用这个选项的值。默认值是 |0 pt|。 % \end{optiondesc} % % 下面的选项处理的是前后相邻的两个标点符号之间的空白宽度。这些选项是互斥的,优先级 % 自上而下。 % % \begin{optiondesc} % \PSKeyVal{enabled-kerning}{boolean} % 是否调整前后相邻的两个标点之间的空白宽度。如果设置为 |false|,则每个标点都按 % 原来的输出宽度输出。默认值是 |true|。 % \PSKeyVal{min-bound-to-kerning}{boolean} % 是否使用当前字体中前面标点实际左右边界的最小值与后面标点实际左右边界的最小值 % 中的最大值作为两个标点之间的空白宽度。默认值是 |false|。 % \PSKeyVal{kerning-total-width}{length} % 设置两个标点的总共宽度。此时 \pkg{xeCJK} 会自动计算两个标点之间的空白宽度。 % 默认值是 \cs{maxdimen}。 % \PSKeyVal{kerning-total-ratio}{real} % 设置两个标点的总共输出宽度与实际宽度的比例。默认值是 |0.75|。 % \PSKeyVal{same-align-margin}{length} % 当前后两个标点位于同侧时,它们之间的空白宽度。默认值是 \cs{maxdimen}。 % \PSKeyVal{same-align-ratio}{real} % 当前后两个标点位于同侧时,它们之间的空白宽度与实际输出宽度的比例。默认值是 |0|。 % \PSKeyVal{different-align-margin}{length} % 当前后两个标点位于异侧时,它们之间的空白宽度。默认值是 \cs{maxdimen}。 % \PSKeyVal{different-align-ratio}{real} % 当前后两个标点位于异侧时,它们之间的空白宽度与实际输出宽度的比例。默认值是 |0|。 % \PSKeyVal{kerning-margin-width}{length} % 设置前后两个标点之间的空白宽度。默认值是 \cs{maxdimen}。 % \PSKeyVal{kerning-margin-ratio}{real} % 设置前后两个标点之间的空白宽度与实际输出空白的比例。默认值是 |1.0|。 % \end{optiondesc} % % \begin{optiondesc} % \PSKeyVal{optimize-kerning}{boolean} % 使用以上选项计算出两个标点之间的空白宽度可能小于通过 |min-bound-to-kerning| % 选项得出的结果。当出现这一情况时,若此选项被设置为 |true|,则使用该选项的空 % 白宽度。默认值为 |false|。 % \end{optiondesc} % % \begin{optiondesc} % \PSKeyVal{kerning-margin-minimum}{length} % 指定两个标点之间的最小空白宽度。当经过以上选项设置的空白宽度小于这个选项的值 % 时,则使用这个选项的值。默认值是 |0 pt|。 % \end{optiondesc} % % 事实上,\pkg{xeCJK} 的默认设置就相当于中文全角(|quanjiao|)格式。可以使用上面 % 说明的选项定义新的标点处理格式。例如,使用 % \begin{verbatim} % \xeCJKDeclarePunctStyle { mine } % { % fixed-punct-ratio = 0 , % 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 % } % \end{verbatim} % 就定义了一个名为 |mine| 的标点处理格式。可以在通过 % \begin{verbatim} % \xeCJKsetup{PunctStyle=mine} % \end{verbatim} % 在文档中使用这个格式。它的意义是:使用标点符号的实际左右边界中的最小值作为其左/右 % 空白的宽度,对于句末标点和居中标点,再加上实际边界空白的一半;使用相邻两个标点的 % 实际边界中的较小值作为它们之间的空白宽度,并且最小的空白宽度是 |0.1 em|。 % 再例如,使用 % \begin{verbatim} % \xeCJKEditPunctStyle { hangmobanjiao } { enabled-global-setting = false } % \end{verbatim} % 将使得 \cs{xeCJKsetkern} 等的设置对 |hangmobanjiao| 这一格式无效。 % % \subsection{其它} % \label{subsec:others} % % \begin{function}[added=2012-11-19]{\xeCJKVerbAddon} % \begin{syntax} % \cs{xeCJKVerbAddon} % \end{syntax} % 调整文字间距以便于让 CJK 字符占的宽度等于西文等宽字体中两个空格的宽度。这有利于 % 等宽字体的代码对齐等情形。需要注意的是,\cs{xeCJKVerbAddon} 对 \pkg{xeCJK} 的内 % 部进行了比较大的修改,使用它之后,关于标点符号的禁则将会丢失。所以不能单独使用,^^A % 应该放在分组里限制其作用域,否则是无效的。当然它可以和其它关于代码抄录的宏包配 % 合使用。例如,可以使用于 \package{fancyvrb} 宏包的 |formatcom| 选项。此时设置的 % 西文字体应该确实是等宽的以保证对齐。若西文等宽字体发生变动(包括字体大小),则 % 需要在其后面使用 \cs{xeCJKVerbAddon},重新计算间距的宽度。 % \end{function} % % \begin{function}[added=2012-12-03]{\xeCJKnobreak} % \begin{syntax} % ……汉字。\cs{xeCJKnobreak}\cs{footnote}\{脚注\} % \end{syntax} % \cs{xeCJKnobreak} 用在全角标点符号后面,目的是确保不能在此处断行。如果已经启用了 % 前面介绍的 |CheckFullRight| 选项,则不需要再用此命令。 % \end{function} % % \section{已知问题和兼容性} % % \pkg{xeCJK} 使用并重新定义了 \pkg{CJK} 宏包的部分宏命令,如 \cs{CJKfamily}、 % \cs{CJKsymbol} 和 \cs{CJKglue} 等。需要指出,\pkg{xeCJK} 不需要 \pkg{CJK} % 的支持,并且 \pkg{xeCJK} 自动禁止在它之后载入 \pkg{CJK} 宏包。 % % \CJKunderline{\pkg{xeCJK} 包含有一个子宏包 \pkg{xeCJKfntef},可以用它来实现% % \CJKunderdot{汉字加点}和可断行的下划线等。它是 \pkg{CJKfntef} 宏包在 \XeLaTeX % 下的替换版本,基本用法完全一致,在 \pkg{CJKfntef} 的源文件\ \file{CJKfntef.sty} % 的注解部分里有说明。} % % 新版本(\texttt{3.x})的 \pkg{xeCJK} 完全使用 \hologo{LaTeX3} 的语法来编写。 % \hologo{LaTeX3} 放弃了 \cs{outer} 宏的概念,因此相关工具在 % 遇到 \cs{outer} 宏时可能会存在问题。按照目前 \pkg{xeCJK} 的实现方式,在 CJK 文字 % 后面遇到 \cs{outer} 宏时会出现类似 % \begin{verbatim} % ! Forbidden control sequence found while scanning use of \use_i:nn % \end{verbatim} % 的错误。目前已知的有 \package{cprotect} 宏包提供的 \cs{cprotect}。它的定义是 % \begin{verbatim} % \outer\long\def\cprotect{\icprotect} % \end{verbatim} % 因此,这时可以暂时用 \cs{icprotect} 代替 \cs{cprotect}。事实上,当 \pkg{cprotect} % 被引入时,\pkg{xeCJK} 将使用 % \begin{verbatim} % \let\cprotect\icprotect % \end{verbatim} % 来取消 \cs{cprotect} 的外部宏限制。但由于 \cs{cprotect} 的特殊性,应该只在外部 % 使用它,即不要让它出现在任何宏的参数中。其它 \cs{outer} 宏的情况,可以在它前面 % 加上 \cs{relax} 来回避上面的错误。 % % \pkg{xeCJK} 依赖 \XeTeX 的 \cs{XeTeXinterchartoks} 机制,与使用相同机制的宏包(例如 % \pkg{polyglossia})可能会存在大小不一的冲突。\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! } \xetex_if_engine: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 } { 2012/11/10 } { } { \msg_critical:nnn { xeCJK } { l3-too-old } { expl3 } } % \end{macrocode} % % 以下日期以前的 \pkg{xtemplate} 宏包关于 \cs{KeyValue} 的 Bug 会影响到后面 % 标点符号的处理。 % \begin{macrocode} \RequirePackage { xtemplate } \@ifpackagelater { xtemplate } { 2012/11/10 } { } { \msg_error:nnn { xeCJK } { l3-too-old } { xtemplate } } % \end{macrocode} % % \begin{macrocode} \RequirePackage { xparse , l3keys2e } % \end{macrocode} % % \subsection{内部工具} % % 分配临时变量。 % \begin{macrocode} \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl \int_new:N \l_@@_tmpa_int \int_new:N \l_@@_tmpb_int \int_new:N \l_@@_tmpc_int \box_new:N \l_@@_tmp_box \dim_new:N \l_@@_tmp_dim \skip_new:N \l_@@_tmp_skip \prop_new:N \l_@@_tmp_prop \clist_new:N \l_@@_tmpa_clist \clist_new:N \l_@@_tmpb_clist % \end{macrocode} % % \begin{macro}[internal] % {\@@_msg_new:nn ,\@@_error:n,\@@_error:nx,\@@_warning:nx,\@@_info:nx,\@@_info:nxx} % 各种信息函数的缩略形式。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_msg_new:nn { \msg_new:nnn { xeCJK } } \cs_new_protected_nopar:Npn \@@_error:n { \msg_error:nn { xeCJK } } \cs_new_protected_nopar:Npn \@@_error:nx { \msg_error:nnx { xeCJK } } \cs_new_protected_nopar:Npn \@@_warning:n { \msg_warning:nn { xeCJK } } \cs_new_protected_nopar:Npn \@@_warning:nx { \msg_warning:nnx { xeCJK } } \cs_new_protected_nopar:Npn \@@_warning:nxx { \msg_warning:nnxx { xeCJK } } \cs_new_protected_nopar:Npn \@@_info:nx { \msg_info:nnx { xeCJK } } \cs_new_protected_nopar:Npn \@@_info:nxx { \msg_info:nnxx { xeCJK } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_allow_break:,\xeCJK_no_break:} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_allow_break: { \tex_penalty:D \c_zero } \cs_new_protected_nopar:Npn \xeCJK_no_break: { \tex_penalty:D \c_ten_thousand } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\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} % % \begin{macro}[internal] % {\@@_at_end_preamble:n,\@@_after_preamble:n,\@@_after_end_preamble:n} % 在 \cs{document} 前后加上各种钩子。 % \begin{macrocode} \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 \cs_new_protected:Npn \@@_at_end_preamble:n #1 { \tl_gput_right:Nn \g_@@_at_end_preamble_hook_tl {#1} } \cs_new_protected:Npn \@@_after_preamble:n #1 { \tl_gput_right:Nn \g_@@_after_preamble_hook_tl {#1} } \cs_new_protected:Npn \@@_after_end_preamble:n #1 { \tl_gput_right:Nn \g_@@_after_end_preamble_hook_tl {#1} } \xeCJK_if_package_loaded:nTF { etoolbox } { \AtEndPreamble { \g_@@_at_end_preamble_hook_tl } \AfterPreamble { \g_@@_after_preamble_hook_tl } \AfterEndPreamble { \g_@@_after_end_preamble_hook_tl } } { \AtBeginDocument { \g_@@_after_preamble_hook_tl } \cs_new_protected_nopar:Npn \@@_document_left_hook: { \group_end: \g_@@_at_end_preamble_hook_tl \group_begin: } \cs_new_protected_nopar:Npn \@@_document_right_hook: { \scan_stop: \g_@@_after_end_preamble_hook_tl \tex_ignorespaces:D } \cs_gset_nopar:Npx \document { \@@_document_left_hook: \exp_not:o { \document } \@@_document_right_hook: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_reverse:nnn} % |#1| 为 |#2| 或 |#3|,若 |#1| 和 |#2| 相等,则返回 |#3|,否则返回 |#2|。 % \begin{macrocode} \cs_new_nopar:Npn \xeCJK_reverse:nnn #1#2#3 { \str_if_eq_x:nnTF {#1} {#2} {#3} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal] % {\xeCJK_tl_remove_outer_braces:N,\xeCJK_tl_remove_outer_braces:n} % 去掉 |#1| 外层的分组括号。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_tl_remove_outer_braces:N #1 { \tl_set:Nx #1 { \exp_args:NV \xeCJK_tl_remove_outer_braces:n #1 } } \cs_new:Npn \xeCJK_tl_remove_outer_braces:n #1 { \@@_tl_remove_outer_braces:w #1 \q_stop } \cs_new:Npn \@@_tl_remove_outer_braces:w #1 \q_stop { \bool_if:nTF { \tl_if_single_p:n {#1} && \tl_if_head_is_group_p:n {#1} } { \@@_tl_remove_outer_braces:w #1 \q_stop } { \tl_trim_spaces:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_cs_clear:N,\xeCJK_cs_gclear:N} % 让控制序列的意义为空。 % \begin{macrocode} \cs_new_eq:NN \xeCJK_cs_clear:N \tl_clear:N \cs_new_eq:NN \xeCJK_cs_gclear:N \tl_gclear:N % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\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}[internal]{\xeCJK_font_gset_to_current:c} % |#1| 是控制序列的名字,令它等于当前字体命令。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_font_gset_to_current:c #1 { \exp_after:wN \cs_gset_eq:NN \cs:w #1 \exp_after:wN \cs_end: \tex_the:D \tex_font:D } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,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 } { \etex_iffontchar:D \tex_font:D `#1 \exp_stop_f: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var]{\c_xeCJK_space_skip_tl} % \changes{v3.1.0}{2012/11/18}{字间空格考虑 \cs{spaceskip} 不为零的情况。} % \changes{v3.2.0}{2013/05/22}{字间空格考虑到 \cs{spacefactor} 和 \cs{xspaceskip} 的情况。} % 当前字体状态下,一个字间空格产生的 |glue| 的长度,包括伸展和收缩部分。 % \begin{macrocode} \tl_const:Nn \c_xeCJK_space_skip_tl { \int_compare:nNnTF \g_@@_spacefactor_int = \c_one_thousand { \skip_if_eq:nnTF \tex_spaceskip:D \c_zero_skip { \tex_fontdimen:D \c_two \tex_font:D plus \tex_fontdimen:D \c_three \tex_font:D minus \tex_fontdimen:D \c_four \tex_font:D } { \tex_spaceskip:D } } { \skip_if_eq:nnTF \tex_spaceskip:D \c_zero_skip { \int_compare:nNnTF \g_@@_spacefactor_int < { 2000 } { \_@@_space_skip_scale:nnn { \tex_fontdimen:D \c_two \tex_font:D } } { \skip_if_eq:nnTF \tex_xspaceskip:D \c_zero_skip { \_@@_space_skip_scale:nnn { \tex_fontdimen:D \c_two \tex_font:D + \tex_fontdimen:D \c_seven \tex_font:D } } { \tex_xspaceskip:D \use_none:nn } } { \tex_fontdimen:D \c_three \tex_font:D } { \tex_fontdimen:D \c_four \tex_font:D } } { \int_compare:nNnTF \g_@@_spacefactor_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 \c_seven \tex_font:D } } { \tex_xspaceskip:D \use_none:nn } } { \etex_gluestretch:D \tex_spaceskip:D } { \etex_glueshrink:D \tex_spaceskip:D } } } } \cs_new_nopar:Npn \_@@_space_skip_scale:nnn #1#2#3 { \dim_eval:n {#1} plus \fp_eval:n { \g_@@_spacefactor_int / 1000 } #2 minus \int_div_truncate:nn { 1000 * \tex_number:D #3 } { \g_@@_spacefactor_int } sp } \int_new:N \g_@@_spacefactor_int \int_gset_eq:NN \g_@@_spacefactor_int \c_one_thousand % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_glue_to_skip:nN} % 取得一个 |glue| 的长度,包括伸展和收缩部分。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_glue_to_skip:nN #1#2 { \hbox_set:Nn \l_@@_tmp_box { #1 \scan_stop: \exp_after:wN } \exp_after:wN \skip_set:Nn \exp_after:wN #2 \exp_after:wN { \skip_use:N \tex_lastskip:D } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\xeCJK_if_blank_x:n} % 判断是否为空或者仅含一个空格。 % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_blank_x:n #1 { p , T , F , TF } { \if_case:w \pdftex_strcmp:D { } {#1} \exp_stop_f: \prg_return_true: \else: \if_case:w \pdftex_strcmp:D { ~ } {#1} \exp_stop_f: \prg_return_true: \else: \prg_return_false: \fi: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_int_until_do:nn,\@@_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} } % \end{macrocode} % % \end{macro} % % \begin{macro}[internal]{\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: \tl_set:Nn \@@_peek_catcode_true:w { \group_align_safe_end: #2 } \tl_set:Nn \@@_peek_catcode_false:w { \group_align_safe_end: #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_nopar: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: } \bool_new:N \l_@@_peek_ignore_spaces_bool % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_peek_after_ignore_spaces:nw} % 与 \cs{@ifnextchar} 和 \cs{futurenonspacelet} 类似,会省略掉后面的空格。 % \begin{macrocode} \cs_new_protected:Npn \xeCJK_peek_after_ignore_spaces:nw #1 { \tl_set:Nn \@@_peek_after_do:w { \group_align_safe_end: #1 } \group_align_safe_begin: \peek_after:Nw \@@_peek_ignore_spaces_branches:w } \cs_new_protected_nopar:Npn \@@_peek_ignore_spaces_branches:w { \if_meaning:w \l_peek_token \c_space_token \exp_after:wN \peek_after:Nw \exp_after:wN \@@_peek_ignore_spaces_branches:w \tex_romannumeral:D 0 \else: \exp_after:wN \@@_peek_after_do:w \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_token_value_class:N} % 用于取得记号 |#1| 所在的 \XeTeX 字符类。|#1| 应为 \cs{catcode} 为 |11| 或 |12| % 的显性或隐性记号。 % \begin{macrocode} \cs_new_nopar:Npn \xeCJK_token_value_class:N #1 { \XeTeXcharclass \xeCJK_token_value_charcode:N #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_token_value_charcode:N} % \changes{v3.1.2}{2013/01/08}{考虑 \texttt{charcode} 大于等于 \texttt{0x10000} 的情况。} % 当记号 |#1| 的 \texttt{charcode} 大于等于 \texttt{0x10000} 时,\XeTeX\ % \texttt{0.9999.0} 版以前的 \cs{meaning} 的返回结果比较特殊\footnote{参见 % \url{http://tug.org/pipermail/xetex/2013-January/023967.html} 和 % \url{http://tex.stackexchange.com/a/64848}。},需要特别处理。同时使用较新版本中 % 提供的原语设置 \texttt{mathcode}。 % \begin{macrocode} \cs_new_nopar:Npn \xeCJK_token_value_charcode:N #1 { \exp_after:wN \@@_token_value_charcode:w \token_to_meaning:N #1 \q_stop } \str_if_eq_x:nnTF { \token_to_str:N \Umathcode } { \token_to_meaning:N \Umathcode } { \cs_new_nopar:Npn \@@_token_value_charcode:w #1 ~ #2 ~ #3 \q_stop { `#3 } \cs_new_eq:NN \xeCJK_xetex_mathcode:w \Umathcode } { \cs_new_nopar:Npn \@@_token_value_charcode:w #1 ~ #2 ~ #3#4 \q_stop { \tl_if_empty:nTF {#4} { `#3 } { "20000 } } \cs_new_eq:NN \xeCJK_xetex_mathcode:w \XeTeXmathcode } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\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_nopar:Npn \@@_CJK_class_tl:n #1 { c_@@_CJK_class_ \int_eval:n {#1} _tl } \cs_generate_variant:Nn \@@_CJK_class_tl:n { c } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\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} % % \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}[internal]{\makexeCJKactive, \makexeCJKinactive} % \begin{macrocode} \NewDocumentCommand \makexeCJKactive { } { \XeTeXinterchartokenstate = \c_one } \NewDocumentCommand \makexeCJKinactive { } { \XeTeXinterchartokenstate = \c_zero } % \end{macrocode} % \end{macro} % % 抑制 |BOM|。 % \begin{macrocode} \char_set_catcode_ignore:n { "FEFF } % \end{macrocode} % % \subsection{字符类别设定}\label{sec:xeCJK-class-set} % % \begin{macro}[internal,var]{\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{macro} % % \begin{macro}[internal]{\xeCJK_new_class:n} % 新建一个字符类别。|#1| 是自定义名称。 % \begin{macrocode} \cs_new_protected_nopar: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}[internal]{\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_nopar: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}[internal]{\@@_class_csname:n} % 字符类名称对应的控制序列名字。 % \begin{macrocode} \cs_new_nopar:Npn \@@_class_csname:n #1 { c_@@_#1_class_int } \cs_new_eq:cN { \@@_class_csname:n { Others } } \l_@@_tmpa_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} 字符类用于处理异体字选择符。} % % \pkg{xeCJK} 需要以下字符类别用于字符输出。其中 |Default|、|CJK|、|FullLeft|、 % |FullRight|、|Boundary| 为 \XeTeX\ 中预定义的类别,\pkg{xeCJK} 新增加了\ % |HalfLeft|、|HalfRight|、|NormalSpace| 和 |IVS|。其中异体字选择符 % (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=plain} % \begin{tabular}{cll} % \toprule % 类别 & 说明 & 例子 \\ \midrule % |Default| & 西文一般符号 & abc123 \\ % |CJK| & CJK 表意符号 & 汉字ぁぃぅ \\ % |FullLeft| & 全角左标点 & (《:“ \\ % |FullRight| & 全角右标点 & ,。)》” \\ % |HalfLeft| & 半角左标点 & ( [ \{ \\ % |HalfRight| & 半角右标点 & , . ? ) ] \} \\ % |NormalSpace| & 前后原始间距的符号 & / \\ % |Boundary| & 边界 & 空格 \\ % |IVS| & 异体字选择符 & “回字有四样写法”\\ % \bottomrule % \end{tabular} % \end{center} % % \begin{macro}[internal]{Default,CJK,FullLeft,FullRight,Boundary} % 这五类是 \XeTeX\ 预定义的类别。 % \begin{macrocode} \xeCJK_save_class:nn { Default } { \c_zero } \xeCJK_save_class:nn { CJK } { \c_one } \xeCJK_save_class:nn { FullLeft } { \c_two } \xeCJK_save_class:nn { FullRight } { \c_three } \xeCJK_save_class:nn { Boundary } { \c_two_hundred_fifty_five } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{HalfLeft,HalfRight,NormalSpace,IVS} % 新增西文半角左/右标点、前后原始间距的符号和异体字选择符类。 % \begin{macrocode} \xeCJK_new_class:n { HalfLeft } \xeCJK_new_class:n { HalfRight } \xeCJK_new_class:n { NormalSpace } \xeCJK_new_class:n { IVS } % \end{macrocode} % \end{macro} % % \begin{macro}[var,internal] % {\c_@@_HalfLeft_chars_clist,\c_@@_HalfRight_chars_clist,\c_@@_NormalSpace_chars_clist, % \c_@@_FullLeft_chars_clist,\c_@@_FullRight_chars_clist,\c_@@_CJK_chars_clist, % \c_@@_IVS_chars_clist} % \hypertarget{CJKcharclass}{\pkg{xeCJK} 设置的基本字符类的默认范围。} % \begin{macrocode} \clist_const:Nn \c_@@_HalfLeft_chars_clist { "28 , "2D , "5B , "60 , "7B } \clist_const:Nn \c_@@_HalfRight_chars_clist { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D } \clist_const:Nn \c_@@_NormalSpace_chars_clist { "2F } \clist_const:Nn \c_@@_FullLeft_chars_clist { "2018 , "201C , "3008 , "300A , "300C , "300E , "3010 , "3012 , "3014 , "3016 , "3018 , "301A , "301D , "3036 , "FE59 , "FE5B , "FE5D , "FE5F , "FE60 , "FE69 , "FE6B , "FF03 , "FF04 , "FF08 , "FF20 , "FF3B , "FF5B , "FFE0 , "FFE1 , "FFE5 , "FFE6 } \clist_const:Nn \c_@@_FullRight_chars_clist { "00B7 , "2019 , "201D , "2014 , "2015 , "2025 , "2026 , "2027 , "2500 , "3001 , "3002 , "3005 , "3006 , "3009 , "300B , "300D , "300F , "3011 , "3015 , "3017 , "3019 , "301B , "301E , "301F , "3041 , "3043 , "3045 , "3047 , "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "309B , "309C , "309D , "309E , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , "30E5 , "30E7 , "30EE , "30F5 , "30F6 , "30FB , "30FC , "30FD , "30FE , "FE50 , "FE51 , "FE52 , "FE54 , "FE55 , "FE56 , "FE57 , "FE5A , "FE5C , "FE5E , "FE6A , "FF01 , "FF05 , "FF09 , "FF0C , "FF0E , "FF1A , "FF1B , "FF1F , "FF3D , "FF5D , "FF61 , "FF63 , "FF64 , "FF65 , "FF67 , "FF68 , "FF69 , "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 , "FF9E , "FF9F } \clist_const:Nn \c_@@_CJK_chars_clist { % \end{macrocode} % \begin{itemize}[nosep,leftmargin=0pt] % \item Hangul Jamo (谚文字母) % \begin{macrocode} "1100 -> "11FF , % \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 Jamo Extended-A (谚文扩展 A) % \begin{macrocode} "A960 -> "A97F , % \end{macrocode} % \item Hangul Syllables (谚文音节) % \begin{macrocode} "AC00 -> "D7AF , % \end{macrocode} % \item Hangul Jamo Extended-B (谚文扩展 B) % \begin{macrocode} "D7B0 -> "D7FF , % \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 Kana Supplement (日文假名增补) % \begin{macrocode} "1B000 -> "1B0FF , % \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 Compatibility Ideographs Supplement (中日韩兼容表意文字增补) % \begin{macrocode} "2F800 -> "2FA1F % \end{macrocode} % \end{itemize} % \begin{macrocode} } \clist_const:Nn \c_@@_IVS_chars_clist { % \end{macrocode} % \begin{itemize}[nosep,leftmargin=0pt] % \item COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK % \begin{macrocode} "3099 , % \end{macrocode} % \item COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK % \begin{macrocode} "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{macro} % % \subsection{字符类别处理} % % \begin{macro}[internal,var] % {\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_nopar:Npn \@@_save_CJK_class:n #1 { \seq_gput_right:Nn \g_@@_CJK_class_seq {#1} \tl_const:cn { \@@_CJK_class_tl:c { \@@_class_csname:n {#1} } } {#1} } \clist_map_function:nN { CJK , FullLeft , FullRight , IVS } \@@_save_CJK_class:n % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_class_num:n} % |#1| 为字符类别名称,用于取得字符类别对应的编号。 % \begin{macrocode} \cs_new_nopar: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:nx {#2} {#3} \IfBooleanT {#1} { \xeCJKResetPunctClass } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_declare_char_class:nn,\@@_set_char_class_aux:Nnw} % 用于设置字符所属的类别,|#1| 为类别名称,|#2| 为字符的 |Unicode|,相邻字符用 % 半角逗号隔开,支持类似 |"1100 -> "11FF| 起止范围的使用方式。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_declare_char_class:nn #1#2 { \clist_set:Nn \l_@@_tmpa_clist {#2} \clist_gconcat:ccN { g_@@_#1_range_clist } { g_@@_#1_range_clist } \l_@@_tmpa_clist \clist_map_inline:Nn \l_@@_tmpa_clist { \str_if_eq:nnF {##1} { -> } { \@@_set_char_class_aux:Nnw \xeCJK_set_char_class:nnn {##1} { \xeCJK_class_num:n {#1} } } } } \NewDocumentCommand \@@_set_char_class_aux:Nnw { m > { \SplitArgument { 1 } { -> } } m } { #1 #2 } \cs_generate_variant:Nn \clist_gconcat:NNN { cc } \cs_generate_variant:Nn \xeCJK_declare_char_class:nn { nx , nV } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_char_class_catcode:nnn} % 设置字符类别的同时,设置所有 |CJK| 字符的 \cs{catcode} 为 |12|。\XeTeX 的配置文件 % \file{unicode-letters.tex} 将所有 |CJK| 表意文字的 \cs{catcode} 设置为 |11|。我们 % 在作出改变的目的是方便 |CheckSingle| 的判断。事实上,|CheckSingle| 的判断也可以不 % 依赖 \cs{catcode},而改为判断 \cs{XeTeXcharclass}。但是判读一个隐性记号 % (\cs{l_peek_token})的 \cs{XeTeXcharclass} 比直接判断它的 \cs{catcode} 要低效得多。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_char_class_catcode:nnn #1#2#3 { \@@_check_num_range:nnNN {#1} {#2} \l_@@_tmpa_int \l_@@_tmpb_int \int_set:Nn \l_@@_tmpc_int {#3} \int_compare:nNnTF { \use:c { \@@_class_csname:n { CJK } } } = \l_@@_tmpc_int { \cs_set_eq:NN \@@_set_char_catcode:n \char_set_catcode_other:n } { \cs_set_eq:NN \@@_set_char_catcode:n \use_none:n } \xeCJK_int_until_do:nn { \l_@@_tmpa_int > \l_@@_tmpb_int } { \@@_set_char_catcode:n { \l_@@_tmpa_int } \XeTeXcharclass \l_@@_tmpa_int = \l_@@_tmpc_int \int_incr:N \l_@@_tmpa_int } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_char_class:nnn} % 只设置字符类别,而不改变 \cs{catcode}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_char_class:nnn #1#2#3 { \@@_check_num_range:nnNN {#1} {#2} \l_@@_tmpa_int \l_@@_tmpb_int \int_set:Nn \l_@@_tmpc_int {#3} \xeCJK_int_until_do:nn { \l_@@_tmpa_int > \l_@@_tmpb_int } { \XeTeXcharclass \l_@@_tmpa_int = \l_@@_tmpc_int \int_incr:N \l_@@_tmpa_int } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_check_num_range:nnNN} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_check_num_range:nnNN #1#2#3#4 { \bool_if:nTF { \xeCJK_if_blank_x_p:n {#1} || \xeCJK_if_blank_x_p:n {#2} } { \int_set:Nn #3 { \xeCJK_if_blank_x:nTF {#1} {#2} {#1} } \int_set_eq:NN #3 #4 } { \int_set:Nn #3 { \int_min:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } \int_set:Nn #4 { \int_max:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_set_char_class:nnn} % \changes{v3.1.1}{2012/12/05}{在文档中设置字符类别时不重复设置 \cs{catcode}。} % |#1| 和 |#2| 为字符类别起止的 |Unicode|,|#3| 为类别名称对应编号。在宏包内部使用 % 时,设置 |CJK| 字符的 \cs{catcode},而在文档中使用时不设置。 % \begin{macrocode} \cs_new_eq:NN \xeCJK_set_char_class:nnn \@@_set_char_class_catcode:nnn \AtEndOfPackage { \cs_set_eq:NN \xeCJK_set_char_class:nnn \@@_set_char_class:nnn } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_char_class_eq:nn} % \changes{v3.1.1}{2012/12/06}{交换参数的顺序。} % 将字符类 |#1| 中的字符全部设置成字符类 |#2|。只适用于 |#1| 的字符类范围为离散的 % 逗号列表的情况。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_char_class_eq:nn #1#2 { \int_set:Nn \l_@@_tmpa_int { \xeCJK_class_num:n {#2} } \clist_map_inline:cn { c_@@_#1_chars_clist } { \XeTeXcharclass ##1 = \l_@@_tmpa_int } } % \end{macrocode} % \end{macro} % % \begin{macro}{\normalspacedchars} % 声明前后不加间距的字符。 % \begin{macrocode} \NewDocumentCommand \normalspacedchars { m } { \tl_map_inline:nn {#1} { \XeTeXcharclass `##1 = \xeCJK_class_num:n { NormalSpace } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKResetPunctClass} % 用于重置标点符号所属的字符类。 % \begin{macrocode} \NewDocumentCommand \xeCJKResetPunctClass { } { \xeCJK_declare_char_class:nV { HalfLeft } \c_@@_HalfLeft_chars_clist \xeCJK_declare_char_class:nV { HalfRight } \c_@@_HalfRight_chars_clist \xeCJK_declare_char_class:nV { FullLeft } \c_@@_FullLeft_chars_clist \xeCJK_declare_char_class:nV { FullRight } \c_@@_FullRight_chars_clist } % \end{macrocode} % \end{macro} % % % \begin{macro}{\xeCJKResetCharClass} % 用于恢复 \pkg{xeCJK} 对字符类别的设置。 % \begin{macrocode} \NewDocumentCommand \xeCJKResetCharClass { } { \xeCJK_declare_char_class:nV { CJK } \c_@@_CJK_chars_clist \xeCJK_declare_char_class:nV { NormalSpace } \c_@@_NormalSpace_chars_clist \xeCJK_declare_char_class:nV { IVS } \c_@@_IVS_chars_clist \xeCJKResetPunctClass } % \end{macrocode} % \end{macro} % % 设置字符类别。 % \begin{macrocode} \xeCJKResetCharClass % \end{macrocode} % % \begin{macro}[internal]{\xeCJK_inter_class_toks:nnn} % 在相邻类别之间插入内容。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_inter_class_toks:nnn #1#2#3 { \XeTeXinterchartoks \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} = {#3} } \cs_generate_variant:Nn \xeCJK_inter_class_toks:nnn { nnc , nnx } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_get_inter_class_toks:nn} % 取出相邻类别之间的内容。 % \begin{macrocode} \cs_new_nopar:Npn \xeCJK_get_inter_class_toks:nn #1#2 { \tex_the:D \XeTeXinterchartoks \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_clear_inter_class_toks:nn} % 清除相邻类别之间的内容。 % \begin{macrocode} \cs_new_protected_nopar: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}[internal]{\xeCJK_pre_inter_class_toks:nnn} % 在相邻类别之间已有的内容前增加内容。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_pre_inter_class_toks:nnn #1#2#3 { \xeCJK_inter_class_toks:nnx {#1} {#2} { \exp_not:n {#3} \xeCJK_get_inter_class_toks:nn {#1} {#2} } } \cs_generate_variant:Nn \xeCJK_pre_inter_class_toks:nnn { nnx } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_app_inter_class_toks:nnn} % 在相邻类别之间已有的内容后追加内容。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_app_inter_class_toks:nnn #1#2#3 { \xeCJK_inter_class_toks:nnx {#1} {#2} { \xeCJK_get_inter_class_toks:nn {#1} {#2} \exp_not:n {#3} } } \cs_generate_variant:Nn \xeCJK_app_inter_class_toks:nnn { nnc , nnx } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_copy_inter_class_toks:nnnn} % 将 |#3| 和 |#4| 之间的内容复制到 |#1| 和 |#2| 之间。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_copy_inter_class_toks:nnnn #1#2#3#4 { \tl_set:Nx \l_@@_tmpa_tl { \xeCJK_get_inter_class_toks:nn {#3} {#4} } \tl_if_empty:NF \l_@@_tmpa_tl { \xeCJK_inter_class_toks:nnx {#1} {#2} { \exp_not:V \l_@@_tmpa_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_replace_inter_class_toks:nnnn} % 将 |#1| 和 |#2| 之间出现的 |#3| 用 |#4| 替换。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_replace_inter_class_toks:nnnn #1#2#3#4 { \tl_set:Nx \l_@@_tmpa_tl { \xeCJK_get_inter_class_toks:nn {#1} {#2} } \tl_if_empty:NF \l_@@_tmpa_tl { \tl_replace_all:Nnn \l_@@_tmpa_tl {#3} {#4} \xeCJK_inter_class_toks:nnx {#1} {#2} { \exp_not:V \l_@@_tmpa_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_clear_Boundary_and_CJK_toks:} % 清除边界与 CJK 文字、全角左右标点之间的内容。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_clear_Boundary_and_CJK_toks: { \seq_map_function:NN \g_@@_CJK_class_seq \@@_clear_Boundary_and_CJK_toks:n } \cs_new_protected_nopar:Npn \@@_clear_Boundary_and_CJK_toks:n #1 { \xeCJK_clear_inter_class_toks:nn { Boundary } {#1} } % \end{macrocode} % \end{macro} % % \subsection{字符输出规则} % % \begin{center} % \begin{tabular}{l*9c} % \toprule % & |Default| & |CJK| & |FullL| & |FullR| & |HalfL| % & |HalfR| & |Normal| & |Bound| & |IVS| \\ \midrule % |Default| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & \tokslink{def-bound} % & \tokslink{def-IVS}\\ % |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-IVS}\\ % |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-IVS}\\ % |HalfLeft| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & % & \tokslink{def-IVS}\\ % |HalfRight| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & \tokslink{def-bound} % & \tokslink{def-IVS}\\ % |NormalSpace| % & % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & % & % & % & \tokslink{def-bound} % & \tokslink{def-IVS}\\ % |Boundary| % & \tokslink{bound-def} % & \tokslink{bound-cjk} % & \tokslink{bound-fl-fr} % & \tokslink{bound-fl-fr} % & \tokslink{bound-def} % & % & \tokslink{bound-def} % & % & \tokslink{def-IVS}\\ % |IVS| % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS} % & \tokslink{def-IVS}\\ % \bottomrule % \end{tabular} % \end{center} % % \begin{macro}[internal]{\xeCJK_class_group_begin:,\xeCJK_class_group_end:} % \begin{macrocode} \cs_new_eq:NN \xeCJK_class_group_begin: \c_group_begin_token \cs_new_eq:NN \xeCJK_class_group_end: \c_group_end_token % \end{macrocode} % \end{macro} % % \hypertarget{def-IVS}{\texttt{IVS}} 字符类与 |CJK| 字符类基本相同,只是从 |CJK| % 转移到 |IVS| 时,不加入任何内容。 % \begin{macrocode} \AtEndOfPackage { \seq_map_inline:Nn \g_@@_class_seq { \str_if_eq:nnTF {#1} { IVS } { \xeCJK_copy_inter_class_toks:nnnn { IVS } {#1} { CJK } { CJK } } { \xeCJK_copy_inter_class_toks:nnnn { IVS } {#1} { CJK } {#1} \str_if_eq:nnF {#1} { CJK } { \xeCJK_copy_inter_class_toks:nnnn {#1} { IVS } {#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: \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 , NormalSpace } { \xeCJK_inter_class_toks:nnn { Boundary } {#1} { \bool_if:nTF { \l_@@_xecglue_bool && \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && \skip_if_eq_p:nn \tex_lastskip:D \c_xeCJK_space_skip_tl } { \tex_unskip:D \bool_if:nTF { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK-space } } { \CJKecglue } { ~ } } { \xeCJK_if_last_node:nTF { CJK } { \CJKecglue } { \xeCJK_if_last_node:nT { CJK-space } { \@@_space_or_xecglue: } } } } \str_if_eq:nnF {#1} { NormalSpace } { \xeCJK_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } } % \end{macrocode} % % \hypertarget{def-bound}{} % \begin{macrocode} \clist_map_inline:nn { Default , HalfRight , NormalSpace } { \xeCJK_inter_class_toks:nnn {#1} { Boundary } { \int_gset_eq:NN \g_@@_spacefactor_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_node:n { default-space } } } { { \xeCJK_make_node:n { default } } } } } \str_if_eq:nnF {#1} { NormalSpace } { \xeCJK_pre_inter_class_toks:nnn {#1} { CJK } { \CJKecglue } } } % \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: \CJKsymbol } % \end{macrocode} % % \begin{macro}[internal]{\xeCJK_check_for_glue:} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_for_glue: { \bool_if:nTF { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK-space } } { \CJKglue } { \bool_if:nTF { \xeCJK_if_last_node_p:n { default } || \int_compare_p:nNn \etex_lastnodetype:D = \c_ten } { \CJKecglue } { \bool_if:nT { \l_@@_xecglue_bool && \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && ( \skip_if_eq_p:nn \tex_lastskip:D \c_xeCJK_space_skip_tl || \skip_if_eq_p:nn \tex_lastskip:D \l_@@_ecglue_skip ) } { \tex_unskip:D \bool_if:nTF { \xeCJK_if_last_node_p:n { default-space } || \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || \xeCJK_if_last_node_p:n { default } } { \CJKecglue } { \bool_if:nTF { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK-space } } { \bool_if:NTF \l_@@_reserve_space_bool { ~ } { \CJKglue } } { ~ } } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\xeCJK_if_last_node:n} % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_last_node:n #1 { p , T , F , TF } { \if_dim:w \use:c { c_@@_#1_node_dim } = \tex_lastkern:D \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \changes{v3.1.0}{2012/11/14}{删除多余的 \texttt{default-itcorr} 结点。} % % \begin{macro}[internal]{\xeCJK_def_node:nn,\xeCJK_make_node:n} % 用于判断插入的各种 |kern|。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_def_node:nn #1#2 { \dim_if_exist:cTF { c_@@_#1_node_dim } { \dim_gset:cn } { \dim_const:cn } { c_@@_#1_node_dim } {#2} } \cs_new_protected_nopar:Npn \xeCJK_make_node:n #1 { \tex_kern:D - \use:c { c_@@_#1_node_dim } \tex_kern:D \use:c { c_@@_#1_node_dim } } \xeCJK_def_node:nn { CJK } { 11 sp } \xeCJK_def_node:nn { CJK-space } { 12 sp } \xeCJK_def_node:nn { default } { 13 sp } \xeCJK_def_node:nn { default-space } { 14 sp } % \end{macrocode} % \end{macro} % % \begin{macro}{CJKglue} % CJK 文字之间插入的 |glue|。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKglue .code:n = { \cs_set_protected_nopar:Npn \CJKglue {#1} \xeCJK_glue_to_skip:nN {#1} \l_@@_ccglue_skip } } \skip_new:N \l_@@_ccglue_skip % \end{macrocode} % \end{macro} % % \begin{macro}{CJKecglue,xCJKecglue} % CJK 与西文和数学行内数学公式之间自动添加的空白。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKecglue .code:n = { \cs_set_protected_nopar: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 \@@_space_or_xecglue: \CJKecglue } , xCJKecglue / false .code:n = { \bool_set_false:N \l_@@_xecglue_bool \cs_set_eq:NN \@@_space_or_xecglue: \c_space_tl } , xCJKecglue / unknown .code:n = { \bool_set_true:N \l_@@_xecglue_bool \cs_set_protected_nopar:Npn \CJKecglue {#1} \xeCJK_glue_to_skip:nN {#1} \l_@@_ecglue_skip \cs_set_eq:NN \@@_space_or_xecglue: \CJKecglue } , xCJKecglue .default:n = { true } } \skip_new:N \l_@@_ecglue_skip \bool_new:N \l_@@_xecglue_bool % \end{macrocode} % \end{macro} % % \begin{macro}{CJKspace} % 是否保留 CJK 文字间的空白,默认不保留。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKspace .bool_set:N = \l_@@_reserve_space_bool , space .meta:n = { CJKspace = true } , nospace .meta:n = { CJKspace = false } } % \end{macrocode} % \end{macro} % % \hypertarget{cjk-bound}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { CJK } { Boundary } { \xeCJK_class_group_end: { \xeCJK_make_node:n { CJK } } \xeCJK_ignore_spaces:w } % \end{macrocode} % % \begin{macro}[internal]{\xeCJK_ignore_spaces:w} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_ignore_spaces:w { \xeCJK_peek_catcode_ignore_spaces:NTF \c_math_toggle_token { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \@@_space_or_xecglue: } { \CJKecglue } } { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK-space } } \bool_if:nT { \token_if_macro_p:N \l_peek_token || ( \l_@@_reserve_space_bool && \token_if_other_p:N \l_peek_token ) } { \@@_space_or_xecglue: } } { \cs_if_exist:NF \l_peek_token \exp_not:N } } } % \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}[internal]{\xeCJK_CJK_and_CJK:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_CJK_and_CJK:N #1 { \CJKglue \CJKsymbol {#1} } % \end{macrocode} % \end{macro} % % \hypertarget{fl-fr-others}{} % \begin{macrocode} \xeCJK_inter_class_toks:nnn { FullLeft } { CJK } { \xeCJK_FullLeft_and_CJK: \CJKsymbol } \xeCJK_inter_class_toks:nnn { FullRight } { CJK } { \xeCJK_FullRight_and_CJK: \CJKsymbol } \seq_map_inline:Nn \g_@@_non_CJK_class_seq { \clist_map_inline:nn { FullLeft , FullRight } { \xeCJK_inter_class_toks:nnx {#1} {##1} { \exp_not:c { xeCJK_Default_and_##1:nN } {#1} } \xeCJK_inter_class_toks:nnc {##1} {#1} { 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} % % \begin{macro}[internal]{\xeCJK_FullRight_and_Boundary:} % \hypertarget{fl-fr-bound}{} % \begin{macrocode} \xeCJK_app_inter_class_toks:nnn { FullLeft } { Boundary } { \tex_ignorespaces:D } \xeCJK_inter_class_toks:nnn { FullRight } { Boundary } { \xeCJK_FullRight_and_Boundary: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullRight_and_Boundary:} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_FullRight_and_Boundary: { \xeCJK_FullRight_and_Default: \tex_ignorespaces:D } % \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:nnc {#1} {##1} { xeCJK_#1_and_##1:N } } } % \end{macrocode} % % \begin{macro}[internal]{\@@_punct_rule:NN} % 用于抹去标点符号的左/右空白。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_punct_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}[internal]{\@@_punct_glue:NN} % 根据所选的标点处理方式在标点符号左/右增加的空白。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_punct_glue:NN #1#2 { \@@_punct_hskip:n { \@@_use_punct_dim:nnn { glue } {#1} {#2} minus \dim_eval:n { ( \@@_use_punct_dim:nnn { glue } {#1} {#2} ) / \c_two } } } \cs_new_eq:NN \@@_punct_hskip:n \skip_horizontal:n % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_punct_kern:NN} % 相邻两个标点之间的间距。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_punct_kern:NN #1#2 { \tex_kern:D \@@_use_punct_dim:nnn { kern } {#1} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var]{\g_@@_last_punct_tl} % 用于记录当前的标点符号。 % \begin{macrocode} \tl_new:N \g_@@_last_punct_tl % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullLeft_and_CJK:} % \begin{macrocode} \cs_new_protected_nopar: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 } { \xeCJK_no_break: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullLeft_and_Default:} % \changes{v3.2.0}{2013/05/20}{修正 \pkg{xeCJK} 使西文在部分情况下无法断词的问题。} % \begin{macrocode} \cs_new_protected_nopar: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: \xeCJK_no_break: \@@_zero_glue: } } \cs_new_protected_nopar:Npn \@@_zero_glue: { \skip_horizontal:N \c_zero_skip } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullRight_and_CJK:} % \begin{macrocode} \cs_new_protected_nopar: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 \CJKglue } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullRight_and_Default:} % \begin{macrocode} \cs_new_protected_nopar: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}[internal]{\xeCJK_Default_and_FullLeft:nN} % \begin{macrocode} \cs_new_protected_nopar: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_font: \xeCJK_clear_inter_class_toks:nn {#1} { FullLeft } \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nx \g_@@_last_punct_tl {#2} \@@_punct_rule:NN \c_@@_left_tl {#2} \CJKpunctsymbol {#2} } \cs_new_protected_nopar:Npn \@@_Default_and_FullLeft_glue:N #1 { \@@_punct_glue:NN \c_@@_left_tl {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_CJK_and_FullLeft:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_CJK_and_FullLeft:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_left_tl {#1} \@@_CJK_and_FullLeft_glue:N {#1} \tl_gset:Nx \g_@@_last_punct_tl {#1} \@@_punct_rule:NN \c_@@_left_tl {#1} \CJKpunctsymbol {#1} } \cs_new_protected_nopar:Npn \@@_CJK_and_FullLeft_glue:N #1 { \CJKglue \@@_punct_glue:NN \c_@@_left_tl {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_Boundary_and_FullLeft:N} % \changes{v3.2.0}{2013/05/22}{当全角左标点前面是 \texttt{hlist}、\texttt{none}、 % \texttt{glue} 和 \texttt{penalty} 等节点时,压缩其左空白。} % \begin{macrocode} \cs_new_protected_nopar: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_font: \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nx \g_@@_last_punct_tl {#1} \@@_punct_rule:NN \c_@@_left_tl {#1} \CJKpunctsymbol {#1} } \cs_new_protected_nopar:Npn \@@_Boundary_and_FullLeft_glue:N #1 { \int_case:nnn { \etex_lastnodetype:D } { { \c_one } { \@@_zero_glue: } { \c_minus_one } { } { \c_eleven } { } { \c_thirteen } { } } { \@@_punct_glue:NN \c_@@_left_tl {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_Default_and_FullRight:nN} % \begin{macrocode} \cs_new_protected_nopar: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_font: \xeCJK_clear_inter_class_toks:nn {#1} { FullRight } \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nx \g_@@_last_punct_tl {#2} \@@_punct_if_middle:NT {#2} { \@@_punct_rule:NN \c_@@_left_tl {#2} } \xeCJK_FullRight_symbol:N {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_Boundary_and_FullRight:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_Boundary_and_FullRight:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl {#1} \@@_Default_and_FullRight_glue:N {#1} \xeCJK_class_group_begin: \xeCJK_select_font: \xeCJK_clear_Boundary_and_CJK_toks: \tl_gset:Nx \g_@@_last_punct_tl {#1} \@@_punct_if_middle:NT {#1} { \@@_punct_rule:NN \c_@@_left_tl {#1} } \xeCJK_FullRight_symbol:N {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_CJK_and_FullRight:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_CJK_and_FullRight:N #1 { \xeCJK_get_punct_bounds:NN \c_@@_right_tl {#1} \@@_CJK_and_FullRight_glue:N {#1} \tl_gset:Nx \g_@@_last_punct_tl {#1} \@@_punct_if_middle:NT {#1} { \@@_punct_rule:NN \c_@@_left_tl {#1} } \xeCJK_FullRight_symbol:N {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal] % {\@@_CJK_and_FullRight_glue:N,\@@_Default_and_FullRight_glue:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_CJK_and_FullRight_glue:N #1 { \@@_punct_if_long:NTF {#1} { \CJKglue } { \@@_punct_if_middle:NTF {#1} { \xeCJK_no_break: \@@_punct_glue:NN \c_@@_right_tl {#1} } { \xeCJK_no_break: \@@_zero_glue: } } } \cs_new_eq:NN \@@_Default_and_FullRight_glue:N \@@_CJK_and_FullRight_glue:N % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullLeft_and_FullLeft:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_FullLeft_and_FullLeft:N #1 { \xeCJK_no_break: \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:Nx \g_@@_last_punct_tl {#1} \CJKpunctsymbol {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullLeft_and_FullRight:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_FullLeft_and_FullRight:N #1 { \xeCJK_no_break: \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:Nx \g_@@_last_punct_tl {#1} \xeCJK_no_break: \xeCJK_FullRight_symbol:N {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullRight_and_FullLeft:N} % \begin{macrocode} \cs_new_protected_nopar: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} \@@_punct_kern:NN \g_@@_last_punct_tl {#1} \tl_gset:Nx \g_@@_last_punct_tl {#1} \@@_punct_break: \CJKpunctsymbol {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_FullRight_and_FullRight:N} % \begin{macrocode} \cs_new_protected_nopar: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:Nx \g_@@_last_punct_tl {#1} \xeCJK_no_break: \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}[internal]{\xeCJK_FullRight_symbol:N} % \begin{macrocode} \cs_new_nopar:Npn \xeCJK_FullRight_symbol:N { \CJKpunctsymbol } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_check_FullRight:} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_FullRight: { \xeCJK_get_punct_bounds:NN \c_@@_right_tl \g_@@_last_punct_tl \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl \tl_case:Non \l_peek_token { \l_@@_no_break_cs_case_tl } { } \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl \xeCJK_class_group_end: } \cs_generate_variant:Nn \tl_case:Nnn { No } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_check_FullRight_symbol:Nw} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_FullRight_symbol:Nw #1 { \xeCJK_peek_after_ignore_spaces:nw { \@@_save_FullRight_symbol:N {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\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 #2 {####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 { \xeCJK_no_break: } { } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKnobreak} % \changes{v3.1.1}{2012/12/03}{增加 \cs{nobreak} 的 \pkg{xeCJK} 版本。} % 为保险起见,我们在这里用了一个循环。 % \begin{macrocode} \NewDocumentCommand \xeCJKnobreak { } { \int_zero:N \l_@@_tmpa_int \int_while_do:nNnn \etex_lastnodetype:D = \c_eleven { \int_if_even:nTF \l_@@_tmpa_int { \int_incr:N \l_@@_tmpa_int \skip_set_eq:NN \l_@@_tmp_skip \tex_lastskip:D } { \skip_add:Nn \l_@@_tmp_skip \tex_lastskip:D } \tex_unskip:D } \xeCJK_no_break: \int_if_even:nF \l_@@_tmpa_int { \skip_horizontal:N \l_@@_tmp_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} % % \begin{macro}[internal]{\xeCJK_check_single:Nw} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_single:Nw #1 { \peek_catcode:NTF \c_catcode_other_token { \xeCJK_check_single:NNw #1 } { \bool_if:nTF { \xeCJK_if_blank_x_p:n { \token_get_arg_spec:N \l_peek_token } && \exp_args:No \tl_if_single_token_p:n \l_peek_token && \exp_after:wN \token_if_other_p:N \l_peek_token } { \exp_after:wN \xeCJK_check_single:NNw \exp_after:wN #1 } { \@@_check_single_save:N #1 } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_check_single:NNw} % \changes{v3.1.1}{2012/12/04}{改进定义,减少使用 \texttt{peek} 函数的次数。} % 使用 \cs{group_align_safe_begin:} 和 \cs{group_align_safe_end:} 是为了防止在表格 % 里面报错。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_single:NNw #1#2 { \xeCJK_peek_catcode_ignore_spaces:NTF \c_catcode_other_token { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \@@_check_single_space:NN #1#2 } { \@@_check_single_save:N #1 #2 } } { \group_align_safe_begin: \token_if_cs:NTF \l_peek_token { \group_align_safe_end: \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \xeCJK_check_single_cs:NNn #1#2 { ~ } } { \xeCJK_check_single_cs:NNn #1#2 { } } } { \group_align_safe_end: \bool_if:nTF { \l_@@_plain_equation_bool && \token_if_math_toggle_p:N \l_peek_token } { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \xeCJK_check_single_equation:NNnNw #1 #2 { ~ } } { \xeCJK_check_single_equation:NNnNw #1 #2 { } } } { \bool_if:NTF \l_@@_peek_ignore_spaces_bool { \@@_check_single_save:N #1 #2 ~ } { \@@_check_single_save:N #1 #2 } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_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_nopar:Npn \@@_check_single_space:NN #1#2 { \xeCJK_if_CJK_class:NTF #2 { \xeCJK_if_CJK_class:NTF \l_peek_token { \@@_check_single_save:N #1 #2 } { \@@_check_single_save:N #1 #2 ~ } } { \@@_check_single_save:N #1 #2 ~ } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_check_single_equation:NNnNw} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_single_equation:NNnNw #1#2#3#4 { \peek_catcode:NTF \c_math_toggle_token { \xeCJK_no_break: \@@_check_single_save:N #1 \xeCJK_no_break: #2 #4 } { \@@_check_single_save:N #1 #2#3#4 } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_check_single_cs:NNn} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_single_cs:NNn #1#2#3 { \tl_case:Non \l_peek_token { \l_@@_check_single_cs_case_tl } { \use_iii:nnn } { \xeCJK_check_single_env:nnNn } { \xeCJK_no_break: \@@_check_single_save:N #1 \xeCJK_no_break: #2 } { \@@_check_single_save:N #1 #2#3 } } \tl_new:N \l_@@_check_single_cs_case_tl % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_check_single_env:nnNn} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_check_single_env:nnNn #1#2#3#4 { \str_case_x:non {#4} { \l_@@_inline_env_case_tl } { \use_i:nn } {#1} {#2} \scan_stop: #3 {#4} } \cs_generate_variant:Nn \str_case_x:nnn { no } % \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}[internal]{\@@_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} { \use_ii:nn } } } } \tl_new:N \l_@@_inline_env_case_tl % \end{macrocode} % \end{macro} % % \begin{macro}{PlainEquation} % \changes{v3.1.1}{2012/12/06}{增加 \texttt{PlainEquation} 选项。} % \begin{macrocode} \keys_define:nn { xeCJK / options } { PlainEquation .bool_set:N = \l_@@_plain_equation_bool } % \end{macrocode} % \end{macro} % % \subsection{增加 CJK 子分区} % % \begin{macro}[internal]{\g_@@_CJK_sub_class_seq} % \begin{macrocode} \seq_new:N \g_@@_CJK_sub_class_seq % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKDeclareSubCJKBlock} % 声明 CJK 子区范围,|#1| 为自定义名称,|#2| 为子区的 |Unicode| 范围。 % \begin{macrocode} \NewDocumentCommand \xeCJKDeclareSubCJKBlock { s > { \TrimSpaces } m > { \TrimSpaces } m } { \xeCJK_declare_sub_char_class:nxx { 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:x {#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:x {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_sub_restore_or_cancel:n} % \begin{macrocode} \cs_new_protected_nopar: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:nx { CJK \bool_if:NF \l_@@_sub_cancel_bool { /##1 } } { \tl_use:c { g_@@_CJK/##1_range_clist } } } { \@@_error:nx { SubBlock-undefined } {##1} } } } \cs_generate_variant:Nn \@@_sub_restore_or_cancel:n { x } \@@_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}[internal]{\xeCJK_declare_sub_char_class:nnn} % \begin{macrocode} \cs_new_protected_nopar: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 { nxx } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_sub_class_toks:nn} % \begin{macrocode} \cs_new_protected_nopar: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 } { \CJKsymbol } { \@@_switch_font:nn {#1} {#2} \CJKsymbol } } } \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 } { \xeCJK_pre_inter_class_toks:nnn { #1/#2 } {##1} { \@@_switch_font:nn {#2} {#1} } } } % \end{macrocode} % \end{macro} % % \subsection{标点处理} % % \cs{XeTeXglyphbouds} 可以得到一个字符的左右边距,用于标点压缩。如果它不可用,则 % 在文档中只能使用 |plain| 这一标点格式原样输出标点。 % \begin{macrocode} \@@_msg_new:nn { XeTeX-too-old } { \token_to_str:N \XeTeXglyphbounds \ is~not~defined.\\ CJK~punctuation~kerning~will~not~be~available.\\\\ You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. } \cs_if_exist:NF \XeTeXglyphbounds { \@@_error:n { XeTeX-too-old } \@@_after_end_preamble:n { \xeCJKsetup { PunctStyle = plain } } } % \end{macrocode} % % \begin{macro}{\xeCJKsetwidth} % 手动设置参数中的标点符号的宽度。 % \begin{macrocode} \NewDocumentCommand \xeCJKsetwidth { m m } { \tl_map_inline:xn {#1} { \tl_gset:cn { g_@@_punct_width/##1/tl } {#2} } } \cs_generate_variant:Nn \tl_map_inline:nn { x } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKsetkern} % 手动设置相邻标点的距离。 % \begin{macrocode} \NewDocumentCommand \xeCJKsetkern { m m m } { \tl_gset:cn { g_@@_punct/kern/#1/#2/tl } {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var]{\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{macro} % % \begin{macro} % {AllowBreakBetweenPuncts, KaiMingPunct, LongPunct, MiddlePunct,PunctWidth} % 相关选项声明。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { AllowBreakBetweenPuncts .choice: , AllowBreakBetweenPuncts / true .code:n = { \cs_set_eq:NN \@@_punct_break: \xeCJK_allow_break: } , AllowBreakBetweenPuncts / false .code:n = { \cs_set_eq:NN \@@_punct_break: \xeCJK_no_break: } , 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 } % \end{macrocode} % \end{macro} % % \begin{macro}[internal] % {\g_@@_special_punct_clist,\@@_set_special_punct:nn, % \@@_add_special_punct:nn, \@@_sub_special_punct:nn} % \begin{macrocode} \clist_new:N \g_@@_special_punct_clist \clist_gset:Nn \g_@@_special_punct_clist { mixed_width , long , middle } \cs_new_nopar:Npn \@@_special_punct_seq:n #1 { g_@@_special_punct_#1_seq } \cs_new_nopar: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_nopar: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:xn {#2} { \tl_new:c { \@@_special_punct_tl:nN {#1} {##1} } \seq_gput_right:cn { \@@_special_punct_seq:n {#1} } {##1} } } \cs_new_protected_nopar:Npn \@@_add_special_punct:nn #1#2 { \tl_map_inline:xn {#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_nopar:Npn \@@_sub_special_punct:nn #1#2 { \tl_map_inline:xn {#2} { \cs_undefine:c { \@@_special_punct_tl:nN {#1} {##1} } \seq_gremove_all:cn { \@@_special_punct_seq:n {#1} } {##1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal] % {\@@_punct_if_right:N,\@@_punct_if_long:N, % \@@_punct_if_middle:N,\@@_punct_if_mixed_width:N} % \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} % \end{macro} % % \begin{macro}[internal] % {\@@_punct_dim_csname:nn,\@@_punct_dim_csname:nnn,\@@_punct_dim_csname:nnnn, % \@@_use_punct_dim:nnn,\@@_use_punct_dim:nn, % \@@_gset_punct_dim:nnx,\@@_gset_punct_dim:nnnx,\@@_gset_punct_dim:nnnnx} % 一些用于记录的辅助函数。 % \begin{macrocode} \cs_new_nopar:Npn \@@_punct_dim_csname:nn #1#2 { g__\l_xeCJK_current_font_tl/\l_xeCJK_punct_style_tl/#1/#2/tl } \cs_new_nopar:Npn \@@_punct_dim_csname:nnn { \@@_punct_dim_csname:nnnn { \l_xeCJK_punct_style_tl } } \cs_new_nopar:Npn \@@_punct_dim_csname:nnnn #1#2#3#4 { g__\l_xeCJK_current_font_tl/#1/#2/#3/#4/tl } \cs_new_nopar:Npn \@@_use_punct_dim:nn #1#2 { \tl_use:c { \@@_punct_dim_csname:nn {#1} {#2} } } \cs_new_nopar:Npn \@@_use_punct_dim:nnn #1#2#3 { \tl_use:c { \@@_punct_dim_csname:nnn {#1} {#2} {#3} } } \cs_new_protected_nopar:Npn \@@_gset_punct_dim:nnx #1#2#3 { \tl_gset:cx { \@@_punct_dim_csname:nn {#1} {#2} } {#3} } \cs_new_protected_nopar:Npn \@@_gset_punct_dim:nnnx #1#2#3#4 { \tl_gset:cx { \@@_punct_dim_csname:nnn {#1} {#2} {#3} } {#4} } \cs_new_protected_nopar:Npn \@@_gset_punct_dim:nnnnx #1#2#3#4#5 { \tl_gset:cx { \@@_punct_dim_csname:nnnn {#1} {#2} {#3} {#4} } {#5} } % \end{macrocode} % \end{macro} % % \changes{v3.1.0}{2012/11/14}{使用 \pkg{xtemplate} 宏包的机制来组织标点符号的处理。} % % 定义标点处理模板。 % \begin{macrocode} \DeclareObjectType { xeCJK / punctuation } { \c_three } % \end{macrocode} % % \begin{macrocode} \DeclareTemplateInterface { xeCJK / punctuation } { basic } { \c_three } { 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 } , 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_zero_fp , different-align-margin : length = \c_max_dim , different-align-ratio : real = \c_zero_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 } { \c_three } { 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 , 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 \tl_if_blank:nTF {#3} { \xeCJK_punct_margin_process:NN {#1} {#2} } { \xeCJK_punct_kerning_process:NN {#2} {#3} } } % \end{macrocode} % % \begin{macro}[internal]{\xeCJK_punct_margin_process:NN} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_punct_margin_process:NN #1#2 { \tl_set:Nx \l_@@_tmpa_tl { \@@_use_punct_dim:nnn { bound } {#1} {#2} } \tl_set:Nx \l_@@_tmpb_tl { \@@_use_punct_dim:nnn { bound } { \xeCJK_reverse:nnn {#1} \c_@@_left_tl \c_@@_right_tl } {#2} } \dim_set:Nn \l_@@_tmp_dim { \bool_if:NTF \l_@@_enabled_global_setting_bool { \cs_if_exist_use:cTF { g_@@_punct_width/#2/tl } { \use_none:n } { \xeCJK_if_blank_x:nTF \g_@@_punct_width_tl { \use:n } { \g_@@_punct_width_tl \use_none:n } } } { \use:n } { \@@_punct_if_middle:NTF {#2} { \@@_punct_width_or_ratio:nN { middle } {#2} } { \@@_punct_if_mixed_width:NTF {#2} { \@@_punct_width_or_ratio:nN { mixed } {#2} } { \@@_punct_width_or_ratio:nN { fixed } {#2} } } } } \@@_gset_punct_dim:nnnx { glue } {#1} {#2} { \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} ) ) / \c_two } { \bool_if:NTF \l_@@_optimize_margin_bool { \dim_max:nn { \dim_min:nn \l_@@_tmpa_tl \l_@@_tmpb_tl } } { \use:n } { \l_@@_tmp_dim - ( \l_@@_tmpb_tl ) - ( \@@_use_punct_dim:nn { dimen } {#2} ) } } } { \bool_if:NTF \l_@@_optimize_margin_bool { \dim_min:nn { \l_@@_tmpa_tl } } { \use:n } { \@@_punct_if_middle:NTF {#2} { \dim_compare:nNnTF \l_@@_middle_margin_width_dim < \c_max_dim { \l_@@_middle_margin_width_dim } { \fp_use:N \l_@@_middle_margin_ratio_fp \etex_dimexpr:D ( \l_@@_tmpa_tl + \l_@@_tmpb_tl ) / \c_two \scan_stop: } } { \@@_punct_if_mixed_width:NTF {#2} { \@@_margin_width_or_ratio:n { mixed } } { \@@_margin_width_or_ratio:n { fixed } } } } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_punct_width_or_ratio:nN} % \begin{macrocode} \cs_new_nopar: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_compare:nNnTF { \use:c { l_@@_#1_punct_ratio_fp } } = \c_zero_fp { \c_max_dim } { \fp_use:c { l_@@_#1_punct_ratio_fp } \etex_dimexpr:D \@@_use_punct_dim:nn { width } {#2} \scan_stop: } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_margin_width_or_ratio:n} % \begin{macrocode} \cs_new_nopar: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 } } { \fp_use:c { l_@@_#1_margin_ratio_fp } \etex_dimexpr:D \l_@@_tmpa_tl \scan_stop: } \bool_if:NT \l_@@_add_min_bound_to_margin_bool { + \dim_min:nn \l_@@_tmpa_tl \l_@@_tmpb_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_punct_kerning_process:NN} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_punct_kerning_process:NN #1#2 { \@@_gset_punct_dim:nnnx { kern } {#1} {#2} { \dim_eval:n { \bool_if:nTF { \l_@@_enabled_global_setting_bool && \tl_if_exist_p:c { g_@@_punct/kern/#1/#2/tl } } { \tl_use:c { g_@@_punct/kern/#1/#2/tl } } { \bool_if:NTF \l_@@_enabled_kerning_bool { \@@_calc_kerning_margin:NN {#1} {#2} } { \@@_original_kerning_margin:NN {#1} {#2} } } - ( \@@_use_punct_dim:nnn { bound } \c_@@_right_tl {#1} ) - ( \@@_use_punct_dim:nnn { bound } \c_@@_left_tl {#2} ) } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_original_kerning_margin:NN} % 相邻两个标点符号之间的本来空白宽度。 % \begin{macrocode} \cs_new_nopar:Npn \@@_original_kerning_margin:NN #1#2 { \dim_eval:n { \@@_use_punct_dim:nnn { \@@_punct_if_right:NTF {#1} { glue } { bound } } { \c_@@_right_tl } {#1} + \@@_use_punct_dim:nnn { \@@_punct_if_right:NTF {#2} { bound } { glue } } { \c_@@_left_tl } {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_calc_kerning_margin:NN} % \begin{macrocode} \cs_new_nopar:Npn \@@_calc_kerning_margin:NN #1#2 { \dim_max:nn { \l_@@_kerning_margin_minimum_dim } { \bool_if:NTF \l_@@_min_bound_to_kerning_bool { \@@_punct_min_bound:NN {#1} {#2} } { \bool_if:NTF \l_@@_optimize_kerning_bool { \dim_max:nn { \@@_punct_min_bound:NN {#1} {#2} } } { \use:n } { \dim_compare:nNnTF \l_@@_kerning_total_width_dim < \c_max_dim { \@@_calc_kerning_margin:nNN \l_@@_kerning_total_width_dim } { \fp_compare:nNnTF \l_@@_kerning_total_ratio_fp = \c_zero_fp { \xeCJK_if_same_class:NNTF {#1} {#2} { \@@_kerning_width_or_ratio:nNN { same } } { \@@_kerning_width_or_ratio:nNN { different } } } { \@@_calc_kerning_margin:nNN { \fp_use:N \l_@@_kerning_total_ratio_fp \etex_dimexpr:D \@@_use_punct_dim:nn { width } {#1} + \@@_use_punct_dim:nn { width } {#2} \scan_stop: } } } {#1} {#2} } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_kerning_width_or_ratio:nNN} % \begin{macrocode} \cs_new_nopar: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 } \use_none:nn } { \fp_compare:nNnTF { \use:c { l_@@_#1_align_ratio_fp } } = \c_zero_fp { \use:n } { \fp_use:c { l_@@_#1_align_ratio_fp } \use_ii:nn } } { \dim_compare:nNnTF \l_@@_kerning_margin_width_dim < \c_max_dim { \l_@@_kerning_margin_width_dim \use_none:n } { \fp_use:N \l_@@_kerning_margin_ratio_fp \use:n } } { \etex_dimexpr:D \@@_original_kerning_margin:NN {#2} {#3} \scan_stop: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_punct_min_bound:NN} % \begin{macrocode} \cs_new_nopar: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}[internal]{\@@_calc_kerning_margin:nNN} % |#2| 和 |#3| 为相邻的两个标点,|#1| 为要确定的相邻两个标点总共占的宽度。 % \begin{macrocode} \cs_new_nopar:Npn \@@_calc_kerning_margin:nNN #1#2#3 { \dim_eval:n { (#1) - ( \@@_use_punct_dim:nnn { \@@_punct_if_right:NTF {#2} { bound } { glue } } { \c_@@_left_tl } {#2} ) - ( \@@_use_punct_dim:nnn { \@@_punct_if_right:NTF {#3} { glue } { bound } } { \c_@@_right_tl } {#3} ) - ( \@@_use_punct_dim:nn { dimen } {#2} ) - ( \@@_use_punct_dim:nn { dimen } {#3} ) } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_get_punct_bounds:NN} % |#1| 为 \cs{c_@@_left_tl} 或 \cs{c_@@_right_tl},|#2| 为标点符号。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_get_punct_bounds:NN #1#2 { \tl_if_exist:cF { \@@_punct_dim_csname:nnn { glue } {#1} {#2} } { \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl { \@@_gset_punct_dim:nnnx { glue } {#1} {#2} { \c_zero_dim } \@@_gset_punct_dim:nnnx { bound } \c_@@_left_tl {#2} { \c_zero_dim } \@@_gset_punct_dim:nnnx { bound } \c_@@_right_tl {#2} { \c_zero_dim } } { { \xeCJK_select_font: \xeCJK_calc_punct_dimen:f {#2} } \@@_punct_if_long:NTF {#2} { \@@_gset_punct_dim:nnnx { glue } {#1} {#2} { \c_zero_dim } } { \UseInstance { xeCJK / punctuation } { \l_xeCJK_punct_style_tl } {#1} {#2} { } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_calc_punct_dimen:N} % 计算标点的左右实际边距和实际尺寸。对于破折号,计算两标点之间的空白,保证它中间 % 不被断开。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_calc_punct_dimen:N #1 { \@@_gset_punct_dim:nnnx { bound } \c_@@_left_tl {#1} { \xeCJK_glyph_bounds:NN \c_one {#1} } \@@_gset_punct_dim:nnnx { bound } \c_@@_right_tl {#1} { \xeCJK_glyph_bounds:NN \c_three {#1} } \dim_set:Nn \l_@@_tmp_dim { ( \@@_use_punct_dim:nnn { bound } \c_@@_left_tl {#1} ) + ( \@@_use_punct_dim:nnn { bound } \c_@@_right_tl {#1} ) } \@@_gset_punct_dim:nnx { width } {#1} { \dim_use:N \etex_fontcharwd:D \tex_font:D \xeCJK_token_value_charcode:N #1 } \@@_gset_punct_dim:nnx { dimen } {#1} { \dim_eval:n { \@@_use_punct_dim:nn { width } {#1} - \l_@@_tmp_dim } } \@@_punct_if_long:NT {#1} { \seq_map_inline:Nn \g_@@_punct_style_seq { \@@_gset_punct_dim:nnnnx {##1} { kern } {#1} {#1} { \bool_if:nTF { \str_if_eq_p:nn {#1} { ^^^^2025 } || \str_if_eq_p:nn {#1} { ^^^^2026 } } { \c_zero_dim } { - \dim_use:N \l_@@_tmp_dim } } } } } \cs_generate_variant:Nn \xeCJK_calc_punct_dimen:N { f } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_glyph_bounds:NN} % 用 \cs{XeTeXglyphbounds} 取得标点符号的上下左右空白。 % \begin{macrocode} \cs_new_nopar:Npn \xeCJK_glyph_bounds:NN #1#2 { \dim_use:N \XeTeXglyphbounds #1 ~ \XeTeXcharglyph \xeCJK_token_value_charcode:N #2 \exp_stop_f: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_get_punct_kerning:NN} % 标点挤压。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_get_punct_kerning:NN #1#2 { \tl_if_exist:cF { \@@_punct_dim_csname:nnn { kern } {#1} {#2} } { \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl { \@@_gset_punct_dim:nnnx { kern } {#1} {#2} { \c_zero_dim } } { \UseInstance { xeCJK / punctuation } { \l_xeCJK_punct_style_tl } { } {#1} {#2} } } } \cs_generate_variant:Nn \xeCJK_get_punct_kerning:NN { o } % \end{macrocode} % \end{macro} % % \begin{macro}{PunctStyle} % \begin{macrocode} \keys_define:nn { xeCJK / options } { PunctStyle .choice: , PunctStyle .default:n = { quanjiao } , PunctStyle / halfwidth .meta:n = { PunctStyle = banjiao } , PunctStyle / fullwidth .meta:n = { PunctStyle = quanjiao } , PunctStyle / mixedwidth .meta:n = { PunctStyle = kaiming } , PunctStyle / marginkerning .meta:n = { PunctStyle = hangmobanjiao } , PunctStyle / plain .code:n = { \tl_set_eq:NN \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl } , PunctStyle / unknown .code:n = { \IfInstanceExistTF { xeCJK / punctuation } { \l_keys_value_tl } { \tl_set:Nx \l_xeCJK_punct_style_tl { \l_keys_value_tl } } { \@@_error:nx { punct-style-unknown } { \l_keys_value_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}{\xeCJKDeclarePunctStyle} % 定义新的标点处理风格,已经存在的同名风格将被覆盖。 % \begin{macrocode} \NewDocumentCommand \xeCJKDeclarePunctStyle { > { \TrimSpaces } 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 { > { \TrimSpaces } 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{后备字体} % % \begin{macro}{AutoFallBack} % 后备字体的宏包选项声明。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { AutoFallBack .choice: , AutoFallBack / true .code:n = { \cs_if_eq:NNF \CJKsymbol \xeCJK_fallback_test_glyph:N { \cs_set_eq:NN \@@_fallback_save_CJKsymbol:N \CJKsymbol \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_test_glyph:N } } , AutoFallBack / false .code:n = { \cs_if_eq:NNT \CJKsymbol \xeCJK_fallback_test_glyph:N { \cs_set_eq:NN \CJKsymbol \@@_fallback_save_CJKsymbol:N } } , AutoFallBack .default:n = { true } , fallback .meta:n = { AutoFallBack = true } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_fallback_test_glyph:N} % 测试当前字体中是否存在当前字符,如存在则直接输出,否则启用后备字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_fallback_test_glyph:N #1 { \xeCJK_glyph_if_exist:NTF {#1} { \@@_fallback_save_CJKsymbol:N {#1} } { { \xeCJK_fallback_loop:Nn {#1} { \l_xeCJK_family_tl/FallBack } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_fallback_loop:Nn} % \changes{v3.1.0}{2012/11/19}{调整备用字体的循环方式。} % \changes{v3.1.1}{2012/12/02}{修正备用字体的不正确警告。} % 循环测试后备字体是否包含字符 |#1|。若后备字体中存在该字符或者再没有后备字体,则 % 结束循环。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_fallback_loop:Nn #1#2 { \xeCJK_family_if_exist:xTF {#2} { \xeCJK_select_font:x {#2} \xeCJK_glyph_if_exist:NTF {#1} { \@@_fallback_save_CJKsymbol:N {#1} } { \xeCJK_fallback_loop:Nn {#1} { #2/FallBack } } } { \xeCJK_family_if_exist:xT { \l_xeCJK_family_tl/FallBack } { \@@_warning:nxx { fallback } {#1} {#2} } \@@_fallback_save_CJKsymbol:N {#1} } } \@@_msg_new:nn { fallback } { CJKfamily~`#2'~ ( \prop_get:No \g_@@_family_font_name_prop {#2} )~ does~not~contain~glyph~`#1'~(U+\int_to_hexadecimal:n {`#1}).\\ } \bool_new:N \l_@@_fallback_first_bool \cs_generate_variant:Nn \prop_get:Nn { No } % \end{macrocode} % \end{macro} % % \begin{macro}{\setCJKfallbackfamilyfont} % \begin{macrocode} \NewDocumentCommand \setCJKfallbackfamilyfont { m O{} m } { \clist_set:Nx \l_@@_tmpa_clist {#3} \int_compare:nNnTF { \clist_count:N \l_@@_tmpa_clist } > \c_one { \xeCJK_set_family_fallback:xxN {#1} {#2} \l_@@_tmpa_clist } { \xeCJK_set_family:xxx { #1/FallBack } {#2} {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_set_family_fallback:nnN} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_set_family_fallback:nnN #1#2#3 { \group_begin: \tl_set:Nn \l_@@_fallback_family_tl {#1} \prop_get:NVNF \g_@@_family_font_name_prop \l_@@_fallback_family_tl \l_@@_font_name_tl { \tl_clear:N \l_@@_font_name_tl } \clist_map_inline:Nn #3 { \tl_put_right:Nn \l_@@_fallback_family_tl { /FallBack } \@@_get_sub_features:Vn \l_@@_fallback_family_tl {##1} \clist_put_left:cn { l_@@_ \l_@@_fallback_family_tl _font_options_clist } {#2} \xeCJK_set_family:Vvv \l_@@_fallback_family_tl { l_@@_ \l_@@_fallback_family_tl _font_options_clist } { l_@@_ \l_@@_fallback_family_tl _font_name_tl } } \group_end: } \cs_generate_variant:Nn \xeCJK_set_family_fallback:nnN { xx } % \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} % % \begin{macro}[internal]{\xeCJK_new_sub_key:n,\g_@@_sub_key_seq} % 用于定义 CJK 子区字体和备用字体的选项。 % \begin{macrocode} \seq_new:N \g_@@_sub_key_seq \cs_new_protected_nopar: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} { \bool_set_false:c { l_@@_copy_#1_bool } \bool_set_false:c { l_@@_add_#1_bool } \tl_put_right:Nn \l_@@_family_name_tl { /#1 } } { \seq_put_right:Nn \l_@@_sub_key_seq {#1} \str_if_eq:nnTF {##1} { * } { \bool_set_true:c { l_@@_copy_#1_bool } \bool_set_false:c { l_@@_add_#1_bool } } { \bool_set_false:c { l_@@_copy_#1_bool } \bool_set_true:c { l_@@_add_#1_bool } \@@_get_sub_features:nn {#1} {##1} } } } , #1 .default:n = { } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_get_sub_features:nn,\@@_get_sub_features:wn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_get_sub_features:nn #1#2 { \tl_set:Nx \l_@@_tmpa_tl { \xeCJK_tl_remove_outer_braces:n {#2} } \clist_clear:N \l_@@_sub_font_options_clist \tl_if_head_eq_meaning:VNTF \l_@@_tmpa_tl [ % ] { \exp_after:wN \@@_get_sub_features:wn \l_@@_tmpa_tl \c_empty_tl \tl_if_blank:VT \l_@@_sub_font_name_tl { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_tmpa_tl \clist_clear:N \l_@@_sub_font_options_clist } } { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_tmpa_tl } \tl_if_blank:VTF \l_@@_sub_font_name_tl { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_font_name_tl } { \tl_replace_all:NnV \l_@@_sub_font_name_tl { * } \l_@@_font_name_tl } \clist_set_eq:cN { l_@@_#1_font_options_clist } \l_@@_sub_font_options_clist \tl_set_eq:cN { l_@@_#1_font_name_tl } \l_@@_sub_font_name_tl } \cs_new_protected_nopar:Npn \@@_get_sub_features:wn [#1] #2 { \clist_set:Nn \l_@@_sub_font_options_clist {#1} \str_if_eq:nnTF {#2} { \c_empty_tl } { \tl_set_eq:NN \l_@@_sub_font_name_tl \c_empty_tl } { \tl_set:Nn \l_@@_sub_font_name_tl {#2} } } \cs_generate_variant:Nn \@@_get_sub_features:nn { V } \cs_generate_variant:Nn \tl_if_head_eq_meaning:nNTF { V } \cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } % \end{macrocode} % \end{macro} % % \begin{macro}{FallBack} % \begin{macrocode} \xeCJK_new_sub_key:n { FallBack } % \end{macrocode} % \end{macro} % % \begin{macro}[internal] % {\g_@@_features_id_prop, BoldFont, ItalicFont, BoldItalicFont, % SlantedFont, BoldSlantedFont,BoldFeatures, ItalicFeatures, % BoldItalicFeatures, SlantedFeatures, BoldSlantedFeatures} % 调用字体的属性声明,同 \pkg{fontspec} 宏包。 % \begin{macrocode} \prop_new:N \g_@@_features_id_prop \prop_put:Nnn \g_@@_features_id_prop { bf } { Bold } \prop_put:Nnn \g_@@_features_id_prop { it } { Italic } \prop_put:Nnn \g_@@_features_id_prop { bfit } { BoldItalic } \prop_put:Nnn \g_@@_features_id_prop { sl } { Slanted } \prop_put:Nnn \g_@@_features_id_prop { bfsl } { BoldSlanted } \prop_map_inline:Nn \g_@@_features_id_prop { \keys_define:nn { xeCJK / features } { #2Font .tl_set:c = { l_@@_font_name_#1_tl } , #2Features .clist_set:c = { l_@@_font_feat_#1_clist } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{AutoFakeBold, AutoFakeSlant} % \begin{macrocode} \keys_define:nn { xeCJK / features } { AutoFakeBold .choice: , 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 = { \g_@@_embolden_factor_fp } , AutoFakeSlant .choice: , 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 = { \g_@@_slant_factor_fp } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_family_initial:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_family_initial: { \int_gincr:N \g_@@_family_int \prop_clear:N \l_@@_add_font_prop \prop_map_inline:Nn \g_@@_features_id_prop { \tl_clear:c { l_@@_font_name_##1_tl } \clist_clear:c { l_@@_font_feat_##1_clist } } \clist_clear:N \l_@@_fontspec_options_clist \seq_clear:N \l_@@_sub_key_seq \seq_map_inline:Nn \g_@@_sub_key_seq { \bool_set_false:c { l_@@_copy_##1_bool } \bool_set_false:c { l_@@_add_##1_bool } } \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 % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_set_family:nnn} % 设置一个 CJK 新字体族,与 \cs{newfontfamily} 类似,增加 |FallBack| 选项。 % \begin{macrocode} \cs_new_protected_nopar: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_features_clist \g_@@_default_features_clist \l_@@_font_options_clist \@@_remove_duplicate_keys:N \l_@@_font_features_clist \keys_set_known:nVN { xeCJK / features } \l_@@_font_features_clist \l_@@_fontspec_options_clist \@@_parse_features: \@@_pass_features: \@@_check_family:V \l_@@_family_name_tl \@@_gset_family_cs:x { \l_@@_family_name_tl } \@@_save_family_info: \@@_set_sub_block_family: \group_end: } \cs_generate_variant:Nn \xeCJK_set_family:nnn { Vnn , xxx , Vvv } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_remove_duplicate_keys:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_remove_duplicate_keys:N #1 { \prop_clear:N \l_@@_tmp_prop \keyval_parse:NNV \@@_prop_put_aux:n \@@_prop_put_aux:nn #1 \clist_clear:N #1 \prop_map_inline:Nn \l_@@_tmp_prop { \tl_if_blank:nTF {##2} { \clist_put_right:Nn #1 {##1} } { \clist_put_right:Nn #1 { ##1 = {##2} } } } } \cs_generate_variant:Nn \keyval_parse:NNn { NNV } \cs_new_protected_nopar:Npn \@@_prop_put_aux:n #1 { \prop_put:Nnn \l_@@_tmp_prop {#1} { } } \cs_new_protected_nopar:Npn \@@_prop_put_aux:nn #1#2 { \prop_put:Nnn \l_@@_tmp_prop {#1} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_gset_family_cs:x} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_gset_family_cs:x #1 { \cs_gset_protected_nopar:cpx { \@@_family_csname:n {#1} } { \group_begin: \exp_not:n { \cs_set_eq:NN \@@_update_family:n \use_none:n } \exp_not:n { \fontspec_set_family:Nnn \l_@@_fontspec_family_tl } { \exp_not:V \l_@@_fontspec_options_clist } { \exp_not:V \l_@@_font_name_tl } \@@_gset_family_nfss_cs:xx {#1} { \exp_not:N \l_@@_fontspec_family_tl } \group_end: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_check_family:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_check_family:n #1 { \prop_get:NnNT \g_@@_family_font_name_prop {#1} \l_@@_tmpa_tl { \prop_gpop:NnNT \g_@@_family_name_prop {#1} \l_@@_tmpa_tl { \cs_undefine:c { \@@_family_nfss_csname:n {#1} } } \@@_warning:nxx { CJKfamily-redef } {#1} { \l_@@_tmpa_tl } } } \cs_generate_variant:Nn \@@_check_family:n { V } \@@_msg_new:nn { CJKfamily-redef } { Redefining~CJKfamily~`\@@_msg_family_map:n {#1}'~(#2). } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_add_font:nn,\@@_add_font_if_new:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_font:nn #1#2 { \prop_put:Nnn \l_@@_add_font_prop { #1 Font } {#2} } \cs_new_protected_nopar:Npn \@@_add_font_if_new:nn #1#2 { \prop_put_if_new:Nnn \l_@@_add_font_prop { #1 Font } {#2} } \cs_generate_variant:Nn \@@_add_font:nn { nx , nV , nv } \cs_generate_variant:Nn \@@_add_font_if_new:nn { nx , nV , nv } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_add_fake_bold:n,\@@_add_fake_slant:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_fake_bold:n #1 { \clist_put_left:cx { l_@@_font_feat_#1_clist } { FakeBold = { \fp_use:N \l_@@_embolden_factor_fp } } } \cs_new_protected_nopar:Npn \@@_add_fake_slant:n #1 { \clist_put_left:cx { l_@@_font_feat_#1_clist } { FakeSlant = { \fp_use:N \l_@@_slant_factor_fp } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_parse_features:,\@@_parse_features:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_parse_features: { \prop_map_function:NN \g_@@_features_id_prop \@@_parse_features:nn } \cs_new_protected_nopar:Npn \@@_parse_features:nn #1#2 { \@@_if_font_select:nTF {#1} { \@@_add_font:nv {#2} { l_@@_font_name_#1_tl } \@@_if_it_or_sl:nTF {#1} { \@@_if_font_select:nF { bf #1 } { \@@_add_font_if_new:nv {#2} { l_@@_font_name_#1_tl } } } { \str_if_eq:nnT {#1} { bf } { \@@_if_font_select:nF { bfit } { \@@_add_font:nV { BoldItalic } \l_@@_font_name_bf_tl } \@@_if_font_select:nF { bfsl } { \@@_add_font:nV { BoldSlanted } \l_@@_font_name_bf_tl } } } } { \@@_set_fake_font:nn {#1} {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\@@_if_font_select:n,\@@_if_it_or_sl:n} % \begin{macrocode} \prg_new_conditional:Npnn \@@_if_font_select:n #1 { p , T , F , TF } { \tl_if_blank:vTF { l_@@_font_name_#1_tl } { \prg_return_false: } { \prg_return_true: } } \prg_new_conditional:Npnn \@@_if_it_or_sl:n #1 { p , T , F , TF } { \if_predicate:w \bool_if_p:n { \str_if_eq_p:nn { it } {#1} || \str_if_eq_p:nn { sl } {#1} } \prg_return_true: \else: \prg_return_false: \fi: } \cs_generate_variant:Nn \tl_if_blank:nTF { v } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_fake_font:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_fake_font:nn #1#2 { \str_if_eq:nnTF {#1} { bf } { \bool_if:NT \l_@@_auto_fake_bold_bool { \@@_add_fake_bold:n {#1} } } { \bool_if:NTF \l_@@_auto_fake_slant_bool { \bool_if:nT { \@@_if_it_or_sl_p:n {#1} || ( \str_if_eq_p:nn {#1} { bfit } && ! ( \@@_if_font_select_p:n { it } ) ) || ( \str_if_eq_p:nn {#1} { bfsl } && ! ( \@@_if_font_select_p:n { sl } ) ) } { \@@_add_fake_slant:n {#1} } } { \@@_if_it_or_sl:nT {#1} { \@@_map_it_sl:nn {#1} {#2} } } \bool_if:nT { \l_@@_auto_fake_bold_bool && ! ( \@@_if_it_or_sl_p:n {#1} ) && ! ( \@@_if_font_select_p:n { bf } ) } { \@@_add_fake_bold:n {#1} } } \@@_add_font_if_new:nn {#2} { * } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_map_it_sl:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_map_it_sl:nn #1#2 { \@@_if_map_font_select:nT {#1} { \@@_add_font:nx {#2} { \@@_get_map_font:n {#1} } \@@_if_font_select:nF { bf #1 } { \@@_add_font_if_new:nx { Bold #2 } { \@@_get_map_font:n {#1} } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_get_map_font:n} % \begin{macrocode} \cs_new_nopar:Npn \@@_get_map_font:n #1 { \exp_not:v { l_@@_font_name_ \xeCJK_reverse:nnn {#1} { it } { sl } _tl } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\@@_if_map_font_select:n} % \begin{macrocode} \prg_new_conditional:Npnn \@@_if_map_font_select:n #1 { p , T , F , TF } { \xeCJK_if_blank_x:nTF { \@@_get_map_font:n {#1} } { \prg_return_false: } { \prg_return_true: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_pass_features:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_pass_features: { \prop_map_inline:Nn \g_@@_features_id_prop { \clist_if_empty:cF { l_@@_font_feat_##1_clist } { \clist_put_right:Nx \l_@@_fontspec_options_clist { ##2Features = { \exp_not:v { l_@@_font_feat_##1_clist } } } } } \prop_map_inline:Nn \l_@@_add_font_prop { \clist_put_right:Nn \l_@@_fontspec_options_clist { ##1 = {##2} } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var] % {\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{macro} % % \begin{macro}[internal]{\@@_save_family_info:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_save_family_info: { \group_begin: \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { \clist_remove_all:Nn \l_@@_font_options_clist {##1} } \prop_gput:NVV \g_@@_family_font_name_prop \l_@@_family_name_tl \l_@@_font_name_tl \prop_gput:NVV \g_@@_family_font_options_prop \l_@@_family_name_tl \l_@@_font_options_clist \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_sub_block_family:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_sub_block_family: { \seq_map_inline:Nn \l_@@_sub_key_seq { \tl_set:Nx \l_@@_sub_family_tl { \l_@@_family_name_tl/##1 } \bool_if:cT { l_@@_copy_##1_bool } { \@@_copy_sub_family:n {##1} } \bool_if:cT { l_@@_add_##1_bool } { \xeCJK_set_family:Vvv \l_@@_sub_family_tl { l_@@_##1_font_options_clist } { l_@@_##1_font_name_tl } } } } \cs_new_protected_nopar:Npn \@@_copy_sub_family:n #1 { \@@_check_family:V \l_@@_sub_family_tl \prop_get:NVNT \g_@@_family_font_name_prop \l_@@_family_name_tl \l_@@_tmpa_tl { \prop_gput:NVV \g_@@_family_font_name_prop \l_@@_sub_family_tl \l_@@_tmpa_tl } \prop_get:NVNT \g_@@_family_font_options_prop \l_@@_family_name_tl \l_@@_tmpa_clist { \clist_remove_all:Nn \l_@@_tmpa_clist { #1 = * } \prop_gput:NVV \g_@@_family_font_options_prop \l_@@_sub_family_tl \l_@@_tmpa_clist } \cs_gset_protected_nopar:cpx { \@@_family_csname:n { \l_@@_sub_family_tl } } { \xeCJK_family_if_exist:xT { \l_@@_family_name_tl } { \prop_get:NnNT \exp_not:N \g_@@_family_name_prop { \l_@@_family_name_tl } \exp_not:N \l_@@_tmpa_tl { \@@_gset_family_nfss_cs:xx { \l_@@_sub_family_tl } { \exp_not:N \l_@@_tmpa_tl } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_copy_family:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_copy_family:nn #1#2 { \xeCJK_family_if_exist:xT {#2} { \tl_map_inline:nn { \g_@@_family_name_prop \g_@@_family_font_name_prop \g_@@_family_font_options_prop } { \prop_get:NnNT ##1 {#2} \l_@@_tmpa_tl { \prop_gput:NnV ##1 {#1} \l_@@_tmpa_tl } } \cs_gset_eq:cc { \@@_family_nfss_csname:n {#1} } { \@@_family_nfss_csname:n {#2} } } } \cs_generate_variant:Nn \@@_copy_family:nn { xx } % \end{macrocode} % \end{macro} % % \subsection{字体切换} % % \begin{macro}[internal]{\l_xeCJK_current_font_tl,\xeCJK_select_font:,\xeCJK_select_font:x} % 缓存当前字体的原始格式,以加速编译。 % \begin{macrocode} \tl_new:N \l_xeCJK_current_font_tl \tl_set:Nn \l_xeCJK_current_font_tl { \@@_font_csname:n { \l_xeCJK_family_tl } } \cs_new_nopar:Npn \@@_font_csname:n #1 { xeCJK/#1/\f@series/\f@shape/\f@size } \cs_new_protected_nopar:Npn \xeCJK_select_font: { \cs_if_exist_use:cF { \l_xeCJK_current_font_tl } { \tl_set:Nx \l_@@_current_coor_tl { \l_xeCJK_current_font_tl } \@@_family_use:x { \l_xeCJK_family_tl } \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } } \cs_new_protected_nopar:Npn \xeCJK_select_font:x #1 { \cs_if_exist_use:cF { \@@_font_csname:n {#1} } { \tl_set:Nx \l_@@_current_coor_tl { \@@_font_csname:n {#1} } \@@_family_use:x {#1} \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } } \cs_new_eq:NN \xeCJK@setfont \xeCJK_select_font: % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_switch_font:nn} % \changes{v3.1.0}{2012/11/18}{改进定义,加快切换速度。} % 两个 CJK 分区之间的字体切换。 % \begin{macrocode} \cs_new_protected_nopar: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: } { \@@_block_select_font:n {#2} } } } \@@_msg_new:nn { CJK-block } { Switch~from~block~`#1'~to~`#2'. } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_block_select_font:n} % 若当前 CJK 字体族没有定义子分区 |#1| 的字体,则使用 \cs{CJKfamilydefault} 的对应 % 分区字体;若 \cs{CJKfamilydefault} 也没有定义该分区字体,则使用当前 CJK 字体族的 % 主分区字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_block_select_font:n #1 { \cs_if_exist_use:cF { \@@_font_csname:n { \l_xeCJK_family_tl/#1 } } { \tl_set:Nx \l_@@_current_coor_tl { \@@_font_csname:n { \l_xeCJK_family_tl/#1 } } \xeCJK_family_if_exist:xF { \l_xeCJK_family_tl/#1 } { \@@_copy_family:xx { \l_xeCJK_family_tl/#1 } { \cs_if_exist:cTF { \@@_family_csname:n { \CJKfamilydefault/#1 } } { \CJKfamilydefault/#1 } { \l_xeCJK_family_tl } } } \@@_family_use:x { \l_xeCJK_family_tl/#1 } \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal] % {\@@_family_csname:n,\@@_family_nfss_csname:n, % \@@_family_use:x,\@@_gset_family_nfss_cs:xx} % \begin{macrocode} \cs_new_nopar:Npn \@@_family_csname:n #1 { xeCJK/family/#1 } \cs_new_nopar:Npn \@@_family_nfss_csname:n #1 { xeCJK/family/nfss/#1 } \cs_new_nopar:Npn \@@_family_use:x #1 { \use:c { \@@_family_nfss_csname:n {#1} } } \cs_new_protected_nopar:Npn \@@_gset_family_nfss_cs:xx #1#2 { \prop_gput:Nxx \g_@@_family_name_prop {#1} {#2} \cs_gset_protected_nopar:cpx { \@@_family_nfss_csname:n {#1} } { \tl_set:Nx \exp_not:N \f@encoding { \c_@@_encoding_tl } \tl_set:Nx \exp_not:N \f@family {#2} \exp_not:N \selectfont } } \cs_generate_variant:Nn \prop_gput:Nnn { Nxx } % \end{macrocode} % \end{macro} % % \begin{macro}[TF,internal]{\xeCJK_family_if_exist:x} % \begin{macrocode} \prg_new_protected_conditional:Npnn \xeCJK_family_if_exist:x #1 { T , F , TF } { \cs_if_exist:cTF { \@@_family_nfss_csname:n {#1} } { \use_i:nn } { \cs_if_exist_use:cTF { \@@_family_csname:n {#1} } } { \prg_return_true: } { \prg_return_false: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\CJKfamily} % 用于切换 CJK 字体族。 % \begin{macrocode} \NewDocumentCommand \CJKfamily { t+ t- m } { \xeCJK_if_blank_x:nTF {#3} { \IfBooleanF {#1} { \IfBooleanF {#2} { \use_none:nn } } \xeCJK_family_if_exist_use:x { \l_xeCJK_family_tl } } { \IfBooleanTF {#2} { \xeCJK_family_if_exist_use:x {#3} } { \xeCJK_family_if_exist:xTF {#3} { \tl_set:Nx \l_xeCJK_family_tl {#3} \tl_set_eq:NN \xeCJK@family \l_xeCJK_family_tl \IfBooleanT {#1} { \@@_family_use:x {#3} } } { \@@_family_unknown_warning:x {#3} } } } \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[var,internal]{\l_xeCJK_family_tl} % 用于保存文档当前正在使用的 CJK 字体族。 % \changes{v3.2.0}{2013/04/14}{不将其初始化为 \cs{CJKfamilydefault}。} % \begin{macrocode} \tl_new:N \l_xeCJK_family_tl % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_gobble_CJKfamily:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_gobble_CJKfamily: { \cs_set_eq:NN \CJKfamily \@@_gobble_CJKfamily:wn } \DeclareExpandableDocumentCommand \@@_gobble_CJKfamily:wn { t+ t- m } { } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_family_if_exist_use:x} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_family_if_exist_use:x #1 { \xeCJK_family_if_exist:xTF {#1} { \@@_family_use:x {#1} } { \@@_family_unknown_warning:x {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_family_unknown_warning:n} % \changes{v3.1.2}{2013/01/01} % {在没有定义任何 CJK 字体的情况下,不再重复给出字体没有定义的警告。} % \begin{macrocode} \cs_new_protected_nopar: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} } } } \cs_generate_variant:Nn \@@_family_unknown_warning:n { x } \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_nopar:Npn \@@_msg_def_family_map:n #1 { \str_case_x:nnn {#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_nopar:Npn \@@_msg_family_map:n #1 { \str_case_x:nnn {#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}{\setCJKmainfont,\setCJKsansfont,\setCJKmonofont} % 设置文档的 CJK 普通字体、无衬线和等宽字体。 % \changes{v3.2.0}{2013/04/14}{定义中加入 \cs{normalfont}。} % \begin{macrocode} \NewDocumentCommand \setCJKmainfont { O{} m } { \xeCJK_set_family:xxx { \CJKrmdefault } {#1} {#2} \normalfont } \cs_new_eq:NN \setCJKromanfont \setCJKmainfont \NewDocumentCommand \setCJKsansfont { O{} m } { \xeCJK_set_family:xxx { \CJKsfdefault } {#1} {#2} \normalfont } \NewDocumentCommand \setCJKmonofont { O{} m } { \xeCJK_set_family:xxx { \CJKttdefault } {#1} {#2} \normalfont } % \end{macrocode} % \end{macro} % % \begin{macrocode} \@onlypreamble \setCJKmainfont \@onlypreamble \setCJKmathfont \@onlypreamble \setCJKsansfont \@onlypreamble \setCJKmonofont \@onlypreamble \setCJKromanfont % \end{macrocode} % % \begin{macro}{\setCJKfamilyfont, \newCJKfontfamily, \CJKfontspec} % 分别用于预声明 CJK 字体和随机调用 CJK 字体。 % \begin{macrocode} \NewDocumentCommand \setCJKfamilyfont { m O{} m } { \xeCJK_set_family:xxx {#1} {#2} {#3} } \NewDocumentCommand \newCJKfontfamily { o m O{} m } { \tl_set:Nx \l_@@_tmpa_tl { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } \cs_new_protected_nopar:Npx #2 { \CJKfamily { \l_@@_tmpa_tl } } \xeCJK_set_family:xxx { \l_@@_tmpa_tl } {#3} {#4} } \NewDocumentCommand \CJKfontspec { O{} m } { \xeCJK_fontspec:xx {#1} {#2} \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_fontspec:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_fontspec:nn #1#2 { \tl_set:Nx \l_@@_tmpa_tl { \tl_to_str:n { CJKfontspec/#1/#2/id } } \tl_if_exist:cF { \l_@@_tmpa_tl } { \tl_set:Nx \l_@@_tmpb_tl { CJKfontspec ( \int_eval:n { \g_@@_family_int + \c_one } ) } \tl_gset_eq:cN { \l_@@_tmpa_tl } \l_@@_tmpb_tl \xeCJK_set_family:Vnn \l_@@_tmpb_tl {#1} {#2} } \exp_args:Nc \CJKfamily { \l_@@_tmpa_tl } } \cs_generate_variant:Nn \xeCJK_fontspec:nn { VV , xx } % \end{macrocode} % \end{macro} % % \begin{macro}{\defaultCJKfontfeatures, \addCJKfontfeatures} % 分别用于设置 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 { m } { \xeCJK_add_font_features:x {#1} \tex_ignorespaces:D } \cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_add_font_features:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_add_font_features:n #1 { \prop_get:NVNTF \g_@@_family_font_name_prop \l_xeCJK_family_tl \l_@@_tmpa_tl { \clist_set:Nn \l_@@_tmpa_clist {#1} \seq_map_function:NN \g_@@_CJK_sub_class_seq \@@_parse_sub_class_features:n \prop_get:NVNT \g_@@_family_font_options_prop \l_xeCJK_family_tl \l_@@_tmpb_clist { \clist_concat:NNN \l_@@_tmpa_clist \l_@@_tmpb_clist \l_@@_tmpa_clist } \xeCJK_fontspec:VV \l_@@_tmpa_clist \l_@@_tmpa_tl } { \@@_warning:n { addCJKfontfeature-ignored } } } \cs_generate_variant:Nn \xeCJK_add_font_features:n { x } \@@_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}[internal]{\@@_parse_sub_class_features:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_parse_sub_class_features:n #1 { \clist_if_in:NnT \l_@@_tmpa_clist {#1} { \clist_remove_all:Nn \l_@@_tmpa_clist {#1} \prop_get:NoNF \g_@@_family_font_name_prop { \l_xeCJK_family_tl/#1 } \l_@@_tmpb_tl { \prop_get:NxNF \g_@@_family_font_name_prop { \CJKfamilydefault/#1 } \l_@@_tmpb_tl { \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpa_tl } } \clist_set:Nx \l_@@_tmpa_clist { #1 = { [ \exp_not:V \l_@@_tmpa_clist ] { \exp_not:V \l_@@_tmpb_tl } } } \clist_map_break: } } \cs_generate_variant:Nn \prop_get:NnNF { Nx } % \end{macrocode} % \end{macro} % % \changes{v3.1.2}{2013/01/01}{修正重定义 \cs{CJKfamilydefault} 无效的问题,恢复容错能力。} % % 在导言区结束的时候,若没有声明 CJK 字体,则给出一个警告。如果 \cs{CJKfamilydefault} % 没有被更改,则在此时根据西文字体的情况更新 \cs{CJKfamilydefault}。 % 如果 \cs{CJKfamilydefault} 对应的字体族没有定义,则使用 \cs{CJKrmdefault} 作为 % 默认字体族。若 \cs{CJKrmdefault} 也没有定义,则使用在导言区设置的第一个 CJK 字体 % 作为默认字体族。最后设置数学字体。 % \begin{macrocode} \@@_at_end_preamble:n { \cs_set_eq:NN \@@_family_default_wrap:n \exp_not:n \tl_if_eq:NNT \CJKfamilydefault \l_@@_family_default_init_tl { \tl_gset:Nx \CJKfamilydefault { \str_case_x:nnn { \familydefault } { { \rmdefault } { \exp_not:N \CJKrmdefault } { \sfdefault } { \exp_not:N \CJKsfdefault } { \ttdefault } { \exp_not:N \CJKttdefault } } { \CJKfamilydefault } } } \cs_undefine:N \@@_family_default_wrap:n \prop_if_empty:NTF \g_@@_family_font_name_prop { \@@_warning:nx { no-CJKfamily } { \CJKfamilydefault } } { \xeCJK_family_if_exist:xF { \CJKfamilydefault } { \tl_set_eq:NN \l_@@_tmpa_tl \CJKfamilydefault \str_if_eq_x:nnTF { \CJKfamilydefault } { \CJKrmdefault } { \use:n } { \xeCJK_family_if_exist:xTF { \CJKrmdefault } { \tl_gset:Nn \CJKfamilydefault { \CJKrmdefault } } } { \prop_map_inline:Nn \g_@@_family_font_name_prop { \prop_map_break:n { \tl_gset:Nn \CJKfamilydefault {#1} } } } \@@_warning:nxx { CJKfamilydefault-undefined } { \l_@@_tmpa_tl } { \CJKfamilydefault } } \CJKfamily { \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. } % \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} % 设置 CJK 数学字体。 % \begin{macrocode} \NewDocumentCommand \setCJKmathfont { O{} m } { \xeCJK_set_family:xxx { \c_@@_math_tl } {#1} {#2} } \tl_const:Nn \c_@@_math_tl { CJKmath } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_set_mathfont:} % 当没有设置 CJK 数学字体时,使用 \cs{CJKfamilydefault} 作为数学字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_set_mathfont: { \xeCJK_family_if_exist:xTF { \c_@@_math_tl } { \tl_set:Nx \l_@@_tmpa_tl { \c_@@_math_tl } } { \xeCJK_family_if_exist:xTF { \CJKfamilydefault } { \tl_set:Nx \l_@@_tmpa_tl { \CJKfamilydefault } } { \use_none:nnnnn } } \prop_get:NVNT \g_@@_family_name_prop \l_@@_tmpa_tl \l_@@_tmpb_tl { \tl_const:Nx \c_@@_math_family_tl { \l_@@_tmpb_tl } \DeclareSymbolFont \c_@@_math_tl \c_@@_encoding_tl \c_@@_math_family_tl \mddefault \shapedefault \SetSymbolFont \c_@@_math_tl { bold } \c_@@_encoding_tl \c_@@_math_family_tl \bfdefault \shapedefault \int_const:Nn \c_xeCJK_math_fam_int { \use:c { sym \c_@@_math_tl } } \clist_concat:NNN \l_@@_tmpa_clist \c_@@_CJK_chars_clist \c_@@_FullLeft_chars_clist \clist_concat:NNN \l_@@_tmpa_clist \l_@@_tmpa_clist \c_@@_FullRight_chars_clist \clist_map_inline:Nn \l_@@_tmpa_clist { \@@_set_char_class_aux:Nnw \xeCJK_gset_mathcode:nnnn {##1} { \c_seven } { \c_xeCJK_math_fam_int } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_gset_mathcode:nnnn} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_gset_mathcode:nnnn #1#2#3#4 { \@@_check_num_range:nnNN {#1} {#2} \l_@@_tmpa_int \l_@@_tmpb_int \xeCJK_int_until_do:nn { \l_@@_tmpa_int > \l_@@_tmpb_int } { \tex_global:D \xeCJK_xetex_mathcode:w \l_@@_tmpa_int = #3 ~ #4 \l_@@_tmpa_int \int_incr:N \l_@@_tmpa_int } } % \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} 选项:在命令 \cs{verb} 里使用时, % 不破坏标点禁则,增加值 \texttt{env+}。} % % \begin{macro}{Verb} % 如果设置为 \texttt{env},则只在 \LaTeX 的抄录环境里使用 \cs{xeCJKVerbAddon},^^A % 而不包括 \cs{verb}。对当前使用环境的判断基于在标准 \LaTeX 的坏境定义里使用 % \cs{begingroup} 和 \cs{endgroup} 来分组。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { Verb .choice: , Verb / true .code:n = { \int_set_eq:NN \l_@@_verb_case_int \c_zero } , Verb / env .code:n = { \int_set_eq:NN \l_@@_verb_case_int \c_one } , Verb / env+ .code:n = { \int_set_eq:NN \l_@@_verb_case_int \c_two } , Verb / false .code:n = { \int_set_eq:NN \l_@@_verb_case_int \c_three } } \int_new:N \l_@@_verb_case_int \@@_after_preamble:n { \tl_put_right:Nn \verbatim@font { \if_case:w \l_@@_verb_case_int \cs_set_eq:NN \CJKglue \@@_zero_glue: \cs_set_eq:NN \CJKecglue \@@_zero_glue: \or: \int_compare:nNnTF \etex_currentgrouptype:D = \c_fourteen { \@@_set_verb_exspace: \@@_verb_addon: } { \cs_set_eq:NN \CJKglue \@@_zero_glue: \cs_set_eq:NN \CJKecglue \@@_zero_glue: } \or: \int_compare:nNnT \etex_currentgrouptype:D = \c_fourteen { \@@_set_verb_exspace: \@@_verb_addon: } \fi: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKVerbAddon} % \changes{v3.1.0}{2012/11/19}{新增 \cs{xeCJKVerbAddon} 用于抄录环境中的间距调整。} % \cs{xeCJKVerbAddon} 进行了比较大的调整,应该只在分组环境里使用。为了方便调整间距 % 以利于对齐,这里只把字符分成了两类,并且在 CJK 类与边界(空格)之间也插入 % \cs{CJKecglue}。当然,这样做之后,关于标点符号的禁则就没有了。 % \begin{macrocode} \NewDocumentCommand \xeCJKVerbAddon { } { \int_compare:nNnF \etex_currentgrouplevel:D = \c_zero { \@@_set_verb_exspace: \@@_verb_addon: } } \cs_new_protected_nopar:Npn \@@_verb_addon: { \bool_if:NF \l_@@_verb_addon_bool { \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 } \xeCJKsetup { xCJKecglue = false } \cs_set_protected_nopar:Npn \CJKglue { \skip_horizontal:N \g_@@_verb_exspace_skip } \cs_set_protected_nopar:Npn \CJKecglue { \skip_horizontal:n { 0.5 \g_@@_verb_exspace_skip } } \cs_set_eq:NN \xeCJK_check_for_glue: \CJKecglue \cs_set_eq:NN \xeCJK_ignore_spaces:w \CJKecglue \skip_set:Nn \tex_rightskip:D { \c_zero_dim plus 1 fil } } } \bool_new:N \l_@@_verb_addon_bool \cs_new_eq:NN \CJKfixedspacing \xeCJKVerbAddon % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_set_verb_exspace:} % \changes{v3.1.1}{2012/12/08}{调整间距的计算方法。} % 在抄录环境中,CJK 文字之间的间距为当前西文字体两个空格的宽度与当前字体大小之差, % 而与西文和空格的间距为 CJK 文字之间的间距的一半。这里的问题是, % \cs{g_@@_verb_exspace_skip} 有可能为负么?现在的处理是保证它非负。如果真的出现 % 负间距的情况,也可以像下面对后备可视空格符号一样,在 \cs{xeCJK_select_font:} 里 % 对 CJK 文字的字体大小做调整,并让间距为零。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_verb_exspace: { \tl_if_exist:cF { xeCJK/verb/\l_xeCJK_family_tl/\curr@fontshape/\f@size } { \group_begin: \xeCJK_select_font: \use:x { \group_end: \tl_gset:cx \exp_not:n { { xeCJK/verb/\l_xeCJK_family_tl/\curr@fontshape/\f@size } } { \exp_not:N \dim_max:nn { \c_zero_dim } { \c_two \tex_fontdimen:D \c_two \tex_font:D - \dim_use:N \etex_fontcharwd:D \tex_font:D "4E00 } } } } \skip_gset:Nn \g_@@_verb_exspace_skip { \use:c { xeCJK/verb/\l_xeCJK_family_tl/\curr@fontshape/\f@size } } } \skip_new:N \g_@@_verb_exspace_skip % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_visible_space_fallback:} % \changes{v3.1.0}{2012/11/19}{调整 \pkg{fontspec} 的后备可视空格符号,以便于使用 % 时对齐。} % \pkg{fontspec} 使用 |lmtt| 字体中的可视空格符号(|U+2423|)作为当前字体中相应符号 % 的后备。但是 |lmtt| 的字体大小未必与当前字体匹配。因此,我们在这里做一些调整,以 % 保证使用后备可视空格符号时,也能保证对齐。这里加入 \cs{scan_stop:} 的目的是强制 % 发生状态转移。这样当空格出现在 CJK 文字后面时,使字体回到西文,以便让 % \pkg{fontspec} 在当前西文字体而不是在 CJK 字体中检查有没有 |U+2423|。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_visible_space_fallback: { { \cs_if_exist_use:cF { xeCJK/space/\curr@fontshape/\f@size } { \xeCJK_set_visible_space_font: } \textvisiblespace } } \AtEndOfPackage { \tl_put_left:Nn \fontspec_visible_space: { \scan_stop: } \cs_gset_eq:NN \fontspec_visible_space_fallback: \xeCJK_visible_space_fallback: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJK_set_visible_space_font:} % 当前字体空格的宽度与后备字体 |lmtt| 不一样时,就对 \cs{textvisiblespace} 的字体尺寸 % 按相应的比例放缩。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_set_visible_space_font: { \tl_set:Nx \l_@@_current_coor_tl { xeCJK/space/\curr@fontshape/\f@size } \exp_after:wN \@@_set_visible_space_size:n \exp_after:wN { \dim_use:N \tex_fontdimen:D \c_two \tex_font:D } \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } \cs_new_protected_nopar:Npn \@@_set_visible_space_size:n #1 { \tl_set:Nx \f@encoding { \g_fontspec_encoding_tl } \tl_set:Nx \f@family { lmtt } \selectfont \dim_compare:nNnF {#1} = { \tex_fontdimen:D \c_two \tex_font:D } { \fontsize { \dim_eval:n { \f@size pt * \dim_ratio:nn {#1} { \tex_fontdimen:D \c_two \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}{CJKnumber,indentfirst} % 是否启用 \pkg{CJKnumb} 宏包和首行是否缩进。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { CJKnumber .bool_gset:N = \g_@@_number_bool , indentfirst .bool_gset:N = \g_@@_indent_bool , normalindentfirst .meta:n = { indentfirst = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{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~\l__keys_module_tl \ does~not~have~a~key~called~`#1'.\\\\ The~key~`#1'~is~being~ignored. } % \end{macrocode} % \end{macro} % % \subsection{\pkg{xeCJK} 初始化设置} % % \begin{macro}[internal]{\CJKsymbol, \CJKpunctsymbol} % \begin{macrocode} \cs_new_nopar:Npn \CJKsymbol #1 {#1} \cs_new_nopar:Npn \CJKpunctsymbol #1 {#1} % \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 , CJKnumber = false , xeCJKactive = true , LocalConfig = true , indentfirst = true , Verb = env , EmboldenFactor = 4 , SlantFactor = 0.167 , PunctStyle = quanjiao , NewLineCS = { \par \[ } , EnvCS = { \begin \end } , NoBreakCS = { \footnote \footnotemark \nobreak } , KaiMingPunct = { ^^^^3002 ^^^^ff0e ^^^^ff1f ^^^^ff01 } , LongPunct = { ^^^^2014 ^^^^2015 ^^^^2500 ^^^^2025 ^^^^2026 } , MiddlePunct = { ^^^^2014 ^^^^2015 ^^^^2027 ^^^^2500 ^^^^00b7 ^^^^30fb ^^^^ff65 } , AllowBreakBetweenPuncts = false } \defaultCJKfontfeatures { Script = CJK } % \end{macrocode} % % 执行宏包选项,并载入 \pkg{fontspec} 宏包。 % \begin{macrocode} \ProcessKeysOptions { xeCJK / options } \RequirePackage { fontspec } [ 2011/09/13 ] % \end{macrocode} % % \begin{macro}[internal,var]{\c_@@_encoding_tl} % 保存 \pkg{fontspec} 声明字体时使用的字体编码。 % \begin{macrocode} \tl_const:Nx \c_@@_encoding_tl { \g_fontspec_encoding_tl } % \end{macrocode} % \end{macro} % % 章节标题后面的首个段落的首行是否缩进。 % \changes{v3.1.0}{2012/11/21}{改用 \pkg{indentfirst} 宏包处理缩进的问题。} % \begin{macrocode} \bool_if:NT \g_@@_indent_bool { \RequirePackage { indentfirst } } % \end{macrocode} % % 对不能通过 \cs{xeCJKsetup} 设置的选项给出警告。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { LocalConfig .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } , CJKnumber .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } , indentfirst .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } } \@@_msg_new:nn { option-invalid } { The~`#1'~option~only~can~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{macro}[var]{\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_gset:Nx \l_@@_family_default_init_tl { \exp_not:N \@@_family_default_wrap:n { \tl_if_exist:NTF \CJKfamilydefault { \exp_not:V \CJKfamilydefault } { \exp_not:N \CJKrmdefault } } } \tl_gset_eq:NN \CJKfamilydefault \l_@@_family_default_init_tl % \end{macrocode} % \end{macro} % % \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}[internal]{\xeCJKsetemboldenfactor, \xeCJKsetslantfactor} % \begin{macrocode} \NewDocumentCommand \xeCJKsetemboldenfactor { m } { \xeCJKsetup { EmboldenFactor = {#1} } } \NewDocumentCommand \xeCJKsetslantfactor { m } { \xeCJKsetup { SlantFactor = {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\punctstyle, \xeCJKplainchr} % \begin{macrocode} \NewDocumentCommand \punctstyle { m } { \xeCJKsetup { PunctStyle = {#1} } } \NewDocumentCommand \xeCJKplainchr { } { \xeCJKsetup { PunctStyle = plain } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\CJKsetecglue} % \begin{macrocode} \NewDocumentCommand \CJKsetecglue { m } { \xeCJKsetup { CJKecglue = {#1} } } \cs_new_eq:NN \xeCJKsetecglue \CJKsetecglue % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\CJKspace,\CJKnospace} % \begin{macrocode} \NewDocumentCommand \CJKspace { } { \xeCJKsetup { CJKspace = true } } \NewDocumentCommand \CJKnospace { } { \xeCJKsetup { CJKspace = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJKallowbreakbetweenpuncts, \xeCJKnobreakbetweenpuncts} % \begin{macrocode} \NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } { \xeCJKsetup { AllowBreakBetweenPuncts = true } } \NewDocumentCommand \xeCJKnobreakbetweenpuncts { } { \xeCJKsetup { AllowBreakBetweenPuncts = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJKenablefallback, \xeCJKdisablefallback} % \begin{macrocode} \NewDocumentCommand \xeCJKenablefallback { } { \xeCJKsetup { AutoFallBack = true } } \NewDocumentCommand \xeCJKdisablefallback { } { \xeCJKsetup { AutoFallBack = false } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xeCJKsetcharclass} % \begin{macrocode} \NewDocumentCommand \xeCJKsetcharclass { m m m } { \xeCJK_set_char_class:nnn {#1} {#2} {#3} \xeCJKResetPunctClass } % \end{macrocode} % \end{macro} % % \subsection{兼容性修补} % % \begin{macro}[internal]{\nobreakspace} % \changes{v3.1.2}{2013/01/01} % {修正非 \cs{UTFencname} 编码下面 \pkg{xunicode} 重定义的 \cs{nobreakspace} 会失效的问题。} % 按照 \pkg{xunicode} 的设计,使用 \cs{DeclareUTFcharacter} 定义符号命令时,如果命令 % 已经存在,那么它会检查它是否是“健壮”的。如果是,则什么也不做;否则使用 % \cs{DeclareTextCommand} 来重定义它,实际意义与原来相同,原来的定义保存在名为 % |?-\cs| 的宏中。这里的主要问题是 \pkg{xunicode} 的健壮性检查对像 \cs{nobreakspace} % 这种原本由 \cs{DeclareRobustCommand} 定义的命令返回结果是“假”,因而重定义它。 % 如果编码发生变化,使用 \cs{nobreakspace} 时,\textsf{NFSS} 就会报错。 % 按照 \textsf{NFSS} 的机制,我们用 \cs{ProvideTextCommandDefault} 对未声明的编码给出 % 默认定义即可避免报错。其实 \pkg{xunicode} 重定义 \cs{nobreakspace} 的方式并不恰当。因为 % 在 \LaTeXe 中,\cs{nobreakspace} 原本并不是由 \cs{DeclareTextCommand} 或 % \cs{DeclareTextSymbol} 来定义,这样按照 \pkg{xunicode} 的实现方式,\cs{nobreakspace} % 永远都不会输出 |\char"00A0|。要想让 \cs{nobreakspace} 在 \cs{UTFencname} 编码下面输出 % |\char"00A0|,除非在 \pkg{xunicode} 载入\textbf{前}用 \cs{DeclareTextCommandDefault} 重新定义它: % \begin{verbatim} % \DeclareTextCommandDefault\nobreakspace{\leavevmode\nobreak\ } % \end{verbatim} % 这样我们也就不需要再做下面的处理。另外,如果作者使用名字 |?\cs| 来保存原来的定义 % 的话,也不需要下面的处理。因为下面实际上是定义了一个名为 |?\nobreakspace| 的宏作为 % 未声明编码的默认定义。但是作者使用了 |?-\cs|,不知道这是有意为之还是一个疏忽。 % \begin{macrocode} \cs_if_exist:cT { ? - \token_to_str:N \nobreakspace } { \exp_args:NNv \ProvideTextCommandDefault \nobreakspace { ? - \token_to_str:N \nobreakspace } } % \end{macrocode} % \end{macro} % % \changes{v3.1.1}{2012/12/13}{对于与 \pkg{xltxtra} 的冲突给出错误警告。} % \begin{macrocode} \@@_msg_new:nn { conflict-package } { The~`#1'~package~is~too~old. \\ Please~update~an~up~to~date~version~of~it\\ using~your~TeX~package~manager~or~from~CTAN. } \xeCJK_if_package_loaded:nTF { realscripts } { \@ifpackagelater { realscripts } { 2010/10/10 } { } { \@@_error:nx { conflict-package } { \xeCJK_if_package_loaded:nTF { xltxtra } { xltxtra } { realscripts } } } } { \cs_new_eq:NN \@@_dim_max:nn \dim_max:nn \cs_new_eq:NN \@@_dim_min:nn \dim_min:nn \@@_at_end_preamble:n { \xeCJK_if_package_loaded:nT { realscripts } { \@ifpackagelater { realscripts } { 2010/10/10 } { } { \cs_gset_eq:NN \dim_max:nn \@@_dim_max:nn \cs_gset_eq:NN \dim_min:nn \@@_dim_min:nn } } \cs_undefine:N \@@_dim_max:nn \cs_undefine:N \@@_dim_min:nn } } % \end{macrocode} % % \begin{macro}[internal]{\fontfamily} % \changes{v3.1.1}{2012/12/06}{修改主要 \texttt{CJK} 字体族的自动更新方式。} % \changes{v3.1.2}{2013/01/01}{不将参数完全展开。} % 修改 \cs{fontfamily},使主要 |CJK| 字体族能随西文主要字体更新。 % \begin{macrocode} \RenewDocumentCommand \fontfamily { m } { \tl_set:Nx \f@family {#1} \@@_update_family:n { \str_case:nnn {#1} { { \rmdefault } { \CJKfamily { \CJKrmdefault } } { \sfdefault } { \CJKfamily { \CJKsfdefault } } { \ttdefault } { \CJKfamily { \CJKttdefault } } { \familydefault } { \CJKfamily { \CJKfamilydefault } } } { } } } \cs_new_eq:NN \@@_update_family:n \use:n % \end{macrocode} % \end{macro} % % \newbox\xeCJKtmpbox % \setbox\xeCJKtmpbox\vbox\bgroup % \begin{macrocode} %<@@=> % \end{macrocode}\egroup % % \begin{macro}[internal]{\xeCJK@fix@penalty} % \changes{v3.1.0}{2012/11/13}{采用通过不修改原语 \cs{/} 的方式对修复倾斜校正。} % 对 \LaTeXe 内核中的 \cs{fix@penalty} 被用于诸如 \cs{textit} 之类的文档 % 字体转换命令的定义之中。这里对它进行补丁的目的是修复其中的倾斜校正,并使得这些 % 文档命令与紧随其后的汉字之间可以正确的插入 \cs{CJKecglue} 或者忽略其中的空格。 % 例如 \verb*|这是 \emph{强调} 文本|,第二个空格可以被忽略掉。如果使用 |xCJKecglue| % 选项,第一个空格也可以被省略。事实上,在 \cs{sw@slant} 的定义中,\cs{@@italiccorr} % 前面的 \cs{lastskip} 和 \cs{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}[internal]{\xeCJK@italiccorr} % 修复倾斜校正,并处理汉字后面的空格。 % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK@italiccorr { \int_compare:nNnTF \XeTeXinterchartokenstate > \c_zero { \xeCJK_if_last_node:nTF { default } { \tex_unkern:D \tex_unkern:D \@@italiccorr { \xeCJK_make_node:n { default } } } { \xeCJK_if_last_node:nTF { CJK } { \tex_unkern:D \tex_unkern:D \@@italiccorr { \xeCJK_make_node:n { CJK } } \use:n } { \xeCJK_if_last_node:nTF { CJK-space } { \tex_unkern:D \tex_unkern:D \@@italiccorr { \xeCJK_make_node:n { CJK-space } } \use:n } { \@@italiccorr \use_none:n } } % \end{macrocode} % \cs{xeCJK_ignore_spaces:w} 里面用到 |peek| 函数来判断后面是不是空格,而此时它 % 后面还有 $4$ 个 \cs{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} { \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 } } } { \@@italiccorr } } % \end{macrocode} % \end{macro} % % \setbox\xeCJKtmpbox\vbox\bgroup % \begin{macrocode} %<@@=xeCJK> % \end{macrocode}\egroup % % \begin{macro}[internal]{\@@_set_others_toks:n} % 简单处理与同样使用 \cs{XeTeXinterchartoks} 机制的宏包的兼容问题。 % \begin{macrocode} \@@_after_end_preamble:n { \int_compare:nNnF { \c_three + \seq_count:N \g_@@_new_class_seq } = \xe@alloc@intercharclass { \int_step_inline:nnnn \c_four \c_one \xe@alloc@intercharclass { \seq_if_in:NnF \g_@@_new_class_seq {#1} { \@@_set_others_toks:n {#1} } } } } \cs_new_protected_nopar: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:nnx {##1} { Others } { \xeCJK_get_inter_class_toks:nn { Default } { Others } } \xeCJK_pre_inter_class_toks:nnx { Others } {##1} { \xeCJK_get_inter_class_toks:nn { Others } { Default } } \xeCJK_if_blank_x:nT { \xeCJK_get_inter_class_toks:nn { Others } { Boundary } } { \xeCJK_copy_inter_class_toks:nnnn { Others } { Boundary } { Default } { Boundary } } \xeCJK_if_blank_x:nT { \xeCJK_get_inter_class_toks:nn { Boundary } { Others } } { \xeCJK_copy_inter_class_toks:nnnn { Boundary } { Others } { Boundary } { Default } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_group_begin:,\@@_group_end:} % 用于保护下面歧义宽度标点的分组。 % \begin{macrocode} \cs_new_eq:NN \@@_group_begin: \group_begin: \cs_new_eq:NN \@@_group_end: \group_end: % \end{macrocode} % \end{macro} % % 单独处理宽度有分歧的几个标点:包括省略号、破折号、间隔号、引号等中西文混用的 % 符号, 保证其命令形式输出的是西文字体。并对一些编码的符号宏包做特殊处理。 % \begin{macrocode} \@@_after_preamble:n { \tl_map_inline:nn { \textellipsis \textemdash \textperiodcentered \textcentereddot \textquoteleft \textquoteright \textquotedblleft \textquotedblright } { \cs_gset_nopar:Npx #1 { \@@_group_begin: \makexeCJKinactive \exp_not:o {#1} \@@_group_end: } } \tl_put_left:Nn \tipaencoding { \makexeCJKinactive } \cs_new_eq:NN \@@_aux_r:n \r \cs_set_nopar:Npn \r #1 { { \makexeCJKinactive \@@_aux_r:n {#1} } } \xeCJK_if_package_loaded:nT { pifont } { \RenewDocumentCommand \Pifont { m } { \makexeCJKinactive \usefont { U } {#1} { m } { n } } } } % \end{macrocode} % % 简单处理与 \pkg{hyperref} 宏包的兼容问题。 % \begin{macrocode} \@@_after_end_preamble:n { \xeCJK_if_package_loaded:nT { hyperref } { \pdfstringdefDisableCommands { \@@_gobble_CJKfamily: \xeCJK_cs_clear:N \makexeCJKinactive \xeCJK_cs_clear:N \@@_group_begin: \xeCJK_cs_clear:N \@@_group_end: } } } % \end{macrocode} % % \changes{v3.1.0}{2012/11/13}{取消 \cs{cprotect} 的外部宏限制。} % 当探测到 \pkg{cprotect} 宏包被引入时,则取消 \cs{cprotect} 宏的 \cs{outer} 定义。 % \begin{macrocode} \@@_after_end_preamble:n { \bool_if:nT { \xeCJK_if_package_loaded_p:n { cprotect } && \cs_if_exist_p:N \icprotect } { \exp_after:wN \tex_let:D \cs:w cprotect \cs_end: \icprotect } } % \end{macrocode} % % 禁止在 \pkg{xeCJK} 宏包后再载入 \pkg{CJK} 宏包,并使得 % \pkg{CJKnumb} 和 \pkg{CJKfntef} 宏包可以使用。 % \begin{macrocode} \tl_set:cn { ver@CJK.sty } { 9999/99/99 } \tl_set_eq:cc { ver@CJKulem.sty } { ver@CJK.sty } \tl_set_eq:cc { ver@CJKpunct.sty } { ver@CJK.sty } % \end{macrocode} % % \begin{macro}[internal]{\xeCJKcaption} % 可以使用 \pkg{CJK} 宏包中的 |.cpx| 文件。 % \begin{macrocode} \cs_if_exist:NF \CJK@ifundefined { \cs_set_eq:NN \CJK@ifundefined \cs_if_free:NTF } \NewDocumentCommand \xeCJKcaption { o m } { \IfNoValueF {#1} { \XeTeXdefaultencoding "#1" } \use:x { \char_set_catcode_letter:n { 64 } \file_input:n { #2.cpx } \char_set_catcode:nn { 64 } { \char_value_catcode:n { 64 } } } \XeTeXdefaultencoding "UTF-8" } % \end{macrocode} % \end{macro} % % 由于 \pkg{xeCJK} 禁止 \pkg{CJKulem} 的载入,因此当使用 \pkg{ctex} 宏包的 |fntef| % 选项时,就会出现 \cs{normalem} 没有定义的问题。此时改用 \pkg{xeCJKfntef} 以便 % 载入 \pkg{ulem}。 % \begin{macrocode} \cs_if_eq:NNTF \ifCTEX@fntef \tex_iftrue:D { \RequirePackage { xeCJKfntef } } { \@@_at_end_preamble:n { \xeCJK_if_package_loaded:nF { xeCJKfntef } { \xeCJK_if_package_loaded:nTF { CJKfntef } { \RequirePackage { xeCJKfntef } } { \xeCJK_if_package_loaded:nT { ulem } { \RequirePackage { xeCJKfntef } } } } } } % \end{macrocode} % % 为使用 \pkg{CJKnumb} 宏包而作一些处理。另外 \pkg{CJKnumb} 使用的是传统汉字“萬” % 和“億”,我们在这里把它们修正为简体字。 % \begin{macrocode} \bool_if:NT \g_@@_number_bool { \tl_set:Nn \CJK@UnicodeEnc { UTF8 } \cs_set_protected:Npn \CJKaddEncHook #1#2 { \cs_set:cpn { @@_enc_#1_hook: } {#2} } \cs_set_protected_nopar:Npn \Unicode #1#2 { \tex_char:D \etex_numexpr:D (#1) * \c_two_hundred_fifty_six + (#2) \scan_stop: } \RequirePackage { CJKnumb } \cs_if_exist_use:c { @@_enc_ \CJK@UnicodeEnc _hook: } \tl_set:Nn \CJK@tenthousand { \Unicode { 78 } { 7 } } \tl_set:Nn \CJK@hundredmillion { \Unicode { 78 } { 191 } } } % \end{macrocode} % % 最后引入本地配置文件。 % \begin{macrocode} \bool_if:NT \g_@@_config_bool { \tl_const:Nn \c_@@_config_ext_tl { cfg } \@onefilewithoptions { \g_@@_config_name_tl } [ ] [ ] { \c_@@_config_ext_tl } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJKfntef}} % % \changes{v3.1.1}{2012/12/08}{增加小宏包 \pkg{xeCJKfntef},用于处理下划线的问题。} % % \begin{macrocode} %<*fntef> % \end{macrocode} % % \pkg{xeCJKfntef} 不需要 \pkg{CJKulem} 宏包的支持,因此当使用 \pkg{CJKfntef} 时,% % 需要另行载入 \pkg{ulem}。 % \begin{macrocode} \PassOptionsToPackage { normalem } { ulem } \DeclareOption* { \PassOptionsToPackage { \CurrentOption } { ulem } } \ProcessOptions \scan_stop: % \end{macrocode} % % \begin{macrocode} \@ifpackageloaded { xeCJK } { } { \RequirePackage { xeCJK } } \RequirePackage { ulem } \RequirePackage { CJKfntef } % \end{macrocode} % % \begin{macrocode} \addto@hook \UL@hook { \xeCJK_hook_for_ulem: } % \end{macrocode} % % \begin{macro}[internal]{\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_nopar:Npn \xeCJK_hook_for_ulem: { \bool_if:NF \l_@@_ulem_hook_used_bool { \bool_set_true:N \l_@@_ulem_hook_used_bool \xeCJKsetup { CheckFullRight = false } \bool_if:NTF \l_@@_ulem_skip_punct_bool { \cs_set_eq:NN \@@_ulem_leader_type: \UL@leadtype } { \xeCJK_cs_clear:N \@@_ulem_skip_punct_begin: \xeCJK_cs_clear:N \@@_ulem_skip_punct_end: } \@@_ulem_initial: \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 \cs_set_protected_nopar:Npn \CJKglue { \@@_ulem_glue:n \l_@@_ccglue_skip } \cs_set_protected_nopar:Npn \CJKecglue { \@@_ulem_glue:n \l_@@_ecglue_skip } } } \bool_new:N \l_@@_ulem_hook_used_bool % \end{macrocode} % \end{macro} % % \setbox\xeCJKtmpbox\vbox\bgroup % \begin{macrocode} %<@@=> % \end{macrocode}\egroup % % \begin{macro}[internal]{\CJK@UL,\CJK@@UL} % 修改 \pkg{CJKfntef} 中的 \cs{CJK@UL} 和 \cs{CJK@@UL} 以适应下面的修改。 % \begin{macrocode} \cs_set_eq:NN \CJK@UL \CJK@@UL \tl_replace_once:Nnn \CJK@UL { \ULon } { \bool_set_true:N \l__xeCJK_ulem_skip_punct_bool \ULon } \tl_replace_once:Nnn \CJK@@UL { \ULon } { \bool_set_false:N \l__xeCJK_ulem_skip_punct_bool \ULon } \bool_new:N \l__xeCJK_ulem_skip_punct_bool % \end{macrocode} % \end{macro} % % \setbox\xeCJKtmpbox\vbox\bgroup % \begin{macrocode} %<@@=xeCJK> % \end{macrocode}\egroup % % \begin{macro}[internal]{\@@_ulem_skip_punct_begin:,\@@_ulem_skip_punct_end:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_skip_punct_begin: { \xeCJK_cs_clear:N \UL@leadtype } \cs_new_protected_nopar:Npn \@@_ulem_skip_punct_end: { \cs_set_eq:NN \UL@leadtype \@@_ulem_leader_type: } \xeCJK_cs_clear:N \@@_ulem_leader_type: % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_initial:} % 这里的设置是为了在下划线状态下,下划线可以自动跳过全角标点符号和正确的在它们 % 前/后断行,并且与行首行末对齐。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_initial: { \xeCJK_swap_cs:NN \@@_Default_and_FullLeft_glue:N \@@_ulem_Default_and_FullLeft_glue:N \xeCJK_swap_cs:NN \@@_Default_and_FullRight_glue:N \@@_ulem_Default_and_FullRight_glue:N \xeCJK_swap_cs:NN \@@_CJK_and_FullLeft_glue:N \@@_ulem_CJK_and_FullLeft_glue:N \xeCJK_swap_cs:NN \@@_CJK_and_FullRight_glue:N \@@_ulem_CJK_and_FullRight_glue:N \xeCJK_swap_cs:NN \@@_Boundary_and_FullLeft_glue:N \@@_ulem_Boundary_and_FullLeft_glue:N \xeCJK_swap_cs:NN \@@_punct_hskip:n \@@_ulem_punct_hskip:n \xeCJK_swap_cs:NN \xeCJK_FullLeft_and_Default: \@@_ulem_FullLeft_and_Default: \xeCJK_swap_cs:NN \xeCJK_FullLeft_and_CJK: \@@_ulem_FullLeft_and_CJK: \xeCJK_swap_cs:NN \xeCJK_FullRight_and_Default: \@@_ulem_FullRight_and_Default: \xeCJK_swap_cs:NN \xeCJK_FullRight_and_CJK: \@@_ulem_FullRight_and_CJK: \xeCJK_swap_cs:NN \xeCJK_CJK_and_CJK:N \@@_ulem_CJK_and_CJK:N \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} } } } } } % \end{macrocode} % \end{macro} % % \changes{v3.1.2}{2012/12/27}{解决在下划线状态下使用 \cs{makebox} 时的错误。} % % \begin{macro}[internal]{\xeCJK_if_ulem_patch:TF} % 在下划线状态下,\pkg{ulem} 宏包在数学模式或者盒子中使用 \cs{UL@hrest} 恢复 % \verb*|\ | 等的定义,此时不需要使用 \cs{UL@stop} 和 \cs{UL@start} 来断开下划线而 % 产生断点。 % \begin{macrocode} \cs_new_nopar: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} % % \begin{macro}[internal]{\@@_ulem_CJK_and_CJK:N} % \begin{macrocode} \cs_new_protected_nopar: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: \CJKsymbol } { \@@_ulem_CJK_and_CJK:N } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_class_group_begin:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_class_group_begin: { \xeCJK_class_group_begin: \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_select_font: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_between_CJK_blocks:nnN} % \begin{macrocode} \cs_new_protected_nopar: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} \CJKsymbol } { \skip_horizontal:N \l_@@_ccglue_skip \@@_switch_font:nn {#1} {#2} \CJKsymbol } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_Default_and_FullLeft_glue:N} % \begin{macrocode} \cs_new_protected_nopar: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}[internal]{\@@_ulem_Boundary_and_FullLeft_glue:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_Boundary_and_FullLeft_glue:N #1 { \xeCJK_if_ulem_patch:TF { \UL@stop \@@_ulem_skip_punct_begin: \int_compare:nNnF \etex_lastnodetype:D = \c_one { \@@_punct_glue:NN \c_@@_left_tl {#1} } \UL@start } { \@@_ulem_Boundary_and_FullLeft_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_CJK_and_FullLeft_glue:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_CJK_and_FullLeft_glue:N #1 { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \UL@stop \@@_ulem_skip_punct_begin: \@@_ulem_ccglue: \@@_punct_glue:NN \c_@@_left_tl {#1} \UL@start \@@_ulem_class_group_begin: } { \@@_ulem_CJK_and_FullLeft_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_Default_and_FullRight_glue:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_Default_and_FullRight_glue:N #1 { \xeCJK_if_ulem_patch:TF { \UL@stop \@@_ulem_skip_punct_begin: \@@_punct_if_long:NTF {#1} { \@@_ulem_ccglue: } { \@@_punct_if_middle:NT {#1} { \xeCJK_no_break: \@@_punct_glue:NN \c_@@_right_tl {#1} } \xeCJK_no_break: } \UL@start } { \@@_ulem_Default_and_FullRight_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_CJK_and_FullRight_glue:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_CJK_and_FullRight_glue:N #1 { \xeCJK_if_ulem_patch:TF { \xeCJK_class_group_end: \@@_ulem_Default_and_FullRight_glue:N {#1} \@@_ulem_class_group_begin: } { \@@_ulem_CJK_and_FullRight_glue:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_FullLeft_and_Default:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_FullLeft_and_Default: { \xeCJK_if_ulem_patch:TF { \@@_punct_if_middle:NTF \g_@@_last_punct_tl { \xeCJK_get_punct_bounds:NN \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}[internal]{\@@_ulem_FullLeft_and_CJK:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_FullLeft_and_CJK: { \xeCJK_if_ulem_patch:TF { \@@_ulem_FullLeft_and_Default: \@@_ulem_class_group_begin: } { \@@_ulem_FullLeft_and_CJK: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_FullRight_and_Default:} % \begin{macrocode} \cs_new_protected_nopar: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}[internal]{\@@_ulem_FullRight_and_CJK:} % \begin{macrocode} \cs_new_protected_nopar: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_ccglue: \@@_ulem_skip_punct_end: \UL@start \@@_ulem_class_group_begin: } { \@@_ulem_FullRight_and_CJK: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_punct_hskip:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_punct_hskip:n { \xeCJK_if_ulem_patch:TF { \@@_ulem_hskip:n } { \@@_ulem_punct_hskip:n } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_ulem_glue:n,\@@_ulem_ccglue:,\@@_ulem_hskip:n} % 在下划线状态下的分别代替 \cs{CJKglue} 等。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ulem_glue:n #1 { \xeCJK_if_ulem_patch:TF { \UL@stop \@@_ulem_hskip:n {#1} \UL@start } { \skip_horizontal:n {#1} } } \cs_new_protected_nopar:Npn \@@_ulem_ccglue: { \skip_set_eq:NN \UL@skip \l_@@_ccglue_skip \UL@leaders } \cs_new_protected_nopar:Npn \@@_ulem_hskip:n #1 { \int_compare:nNnTF \tex_lastkern:D = \c_three { \skip_horizontal:n {#1} } { \skip_set:Nn \UL@skip {#1} \UL@leaders } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\CJKunderdot} % 使用 \pkg{xeCJK} 时,\pkg{CJKfntef} 中的 \cs{CJKunderdot} 和 \cs{CJKunderanysymbol} % 在汉字之间不能断行。因此需要我们在这里修改它们。 % \begin{macrocode} \RenewDocumentCommand \CJKunderdot { m } { \bool_if:NT \l_@@_ulem_hook_used_bool { \UL@stop } \CJK@preUnderdot \@@_make_under_symbol:n { \CJK@underdotSkip } \cs_gset_eq:NN \@@_save_under_dot_CJKsymbol:N \CJKsymbol \cs_set_eq:NN \CJKsymbol \@@_under_CJKsymbol:N \bool_if:NT \l_@@_ulem_hook_used_bool { \UL@start } #1 \bool_if:NT \l_@@_ulem_hook_used_bool { \UL@stop } \cs_set_eq:NN \CJKsymbol \@@_save_under_dot_CJKsymbol:N \CJK@postUnderdot \bool_if:NT \l_@@_ulem_hook_used_bool { \UL@start } \tex_ignorespaces:D } \box_new:N \g_@@_under_symbol_box % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\CJKunderanysymbol} % \begin{macrocode} \RenewDocumentCommand \CJKunderanysymbol { m m m } { \group_begin: \hbox_set:Nn \CJK@underdotBox {#2} \@@_make_under_symbol:n {#1} \cs_gset_eq:NN \@@_save_under_dot_CJKsymbol:N \CJKsymbol \cs_set_eq:NN \CJKsymbol \@@_under_CJKsymbol:N #3 \group_end: \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_make_under_symbol:n} % \begin{macrocode} \cs_new_protected:Npn \@@_make_under_symbol:n #1 { \hbox_set:Nn \l_@@_tmp_box { ^^^^4e00 } \vbox_gset_to_ht:Nnn \g_@@_under_symbol_box \c_zero_dim { \skip_vertical:n {#1} \hbox_to_zero:n { \tex_kern:D - \box_wd:N \l_@@_tmp_box \tex_hss:D \box_use:N \CJK@underdotBox \tex_hss:D } \tex_vss:D } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_under_CJKsymbol:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_under_CJKsymbol:N #1 { \@@_save_under_dot_CJKsymbol:N {#1} \hbox_overlap_left:n { \box_use:N \g_@@_under_symbol_box } { \xeCJK_make_node:n { CJK } } \xeCJK_ignore_spaces:w } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{CJKfilltwosides} % 修改 |CJKfilltwosides| 环境,使其不必重定义 \cs{CJKsymbol}。 % \begin{macrocode} \RenewDocumentEnvironment { CJKfilltwosides } { m } { \dim_set:Nn \l_@@_fill_width_dim {#1} \cs_set_eq:NN \CJKglue \tex_hfil:D \cs_set_eq:NN \\ \@@_fill_newline: \mode_if_vertical:T { \tex_indent:D } \tex_vbox:D \c_group_begin_token \tex_hbox:D to \l_@@_fill_width_dim \c_group_begin_token \tex_ignorespaces:D } { \tex_unskip:D \c_group_end_token \c_group_end_token } \dim_new:N \l_@@_fill_width_dim % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_fill_newline:} % |CJKfilltwosides| 环境里的断行命令 |\\|。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_fill_newline: { \tex_unskip:D \c_group_end_token \tex_hbox:D to \l_@@_fill_width_dim \c_group_begin_token \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xeCJK.cfg}} % % \begin{macrocode} %<*config> % \end{macrocode} % % 预设的配置文件 \file{xeCJK.cfg} 为一个空文件。可以在里面增加设置,然后保存到 % 本地目录下面。 % \begin{macrocode} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \iffalse % % \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, ItalicFont=simkai.ttf]{simsun.ttc} \setCJKsansfont[AutoFakeSlant=false, BoldFont=simhei.ttf, ItalicFont=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} \catcode`\。=\active \def。{.} \def\foo{一} \long\def\showtext{一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十。 \[x^2+y^2\] 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十\foo $$x^2+y^2$$ 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十\foo \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{article} \usepackage{xeCJK} \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} \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} \begin{CJKfilltwosides}{40mm} 两端分散对齐\\ 分散对齐\\ \CJKunderdot{汉字可加点}\\ \CJKunderline{汉字可加下划线} \end{CJKfilltwosides} \CJKfntef{CJKunderline} \CJKfntef{CJKunderwave} \CJKfntef{CJKunderdblline} \CJKfntef{CJKsout} \CJKfntef{CJKxout} \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{xeCJK} \setCJKmainfont{SimSun} \xeCJKDeclarePunctStyle { mine } { fixed-punct-ratio = 0 , 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 } \begin{document} \setlength\parindent{2em} \newcommand\showexample[1]{% \texttt{------ #1 ------}\par\xeCJKsetup{PunctStyle=#1}\showtexts\par} \newcommand\showtexts{% 列位看官:你道此书从何而来?说起根由,虽近荒唐,细按则深有趣味。待在下将此来历注明,方使阅者了然不惑。 原来女娲氏炼石补天之时,于大荒山无稽崖炼成高经十二丈、方经二十四丈顽石三万六千五百零一块。娲皇氏只用了三万六千五百块,只单单剩了一块未用,便弃在此山青埂峰下。谁知此石自经煆炼之后,灵性已通,因见众石俱得补天,独自己无材不堪入选,遂自怨自叹,日夜悲号惭愧。 一日,正当嗟悼之际,俄见一僧一道远远而来,生得骨格不凡,丰神迥别,说说笑笑,来至峰下,坐于石边,高谈快论:先是说些云山雾海、神仙玄幻之事,后便说到红尘中荣华富贵。此石听了,不觉打动凡心,也想要到人间去享一享这荣华富贵,但自恨粗蠢,不得已,便口吐人言,向那僧道说道:“大师,弟子蠢物,不能见礼了!适闻二位谈那人世间荣耀繁华,心切慕之。弟子质虽粗蠢,性却稍通,况见二师仙形道体,定非凡品,必有补天济世之材,利物济人之德。如蒙发一点慈心,携带弟子得入红尘,在那富贵场中,温柔乡里受享几年,自当永佩洪恩,万劫不忘也!”二仙师听毕,齐憨笑道:“善哉,善哉!那红尘中有却有些乐事,但不能永远依恃;况又有‘美中不足,好事多磨’八个字紧相连属,瞬息间则又乐极悲生,人非物换,究竟是到头一梦,万境归空,倒不如不去的好。”这石凡心已炽,那里听得进这话去,乃复苦求再四。二仙知不可强制,乃叹道:“此亦静极思动,无中生有之数也!既如此,我们便携你去受享受享,只是到不得意时,切莫后悔!”石道:“自然,自然。”那僧又道:“若说你性灵,却又如此质蠢,并更无奇贵之处。如此也只好踮脚而已。也罢!我如今大施佛法,助你助,待劫终之日,复还本质,以了此案。你道好否?”石头听了,感谢不尽。那僧便念咒书符,大展幻术,将一块大石登时变成一块鲜明莹洁的美玉,且又缩成扇坠大小的可佩可拿。那僧托于掌上,笑道:“形体倒也是个宝物了!还只没有实在的好处,须得再镌上数字,使人一见便知是奇物方妙。然后好携你到那昌明隆盛之邦、诗礼簪缨之族、花柳繁华地、温柔富贵乡去安身乐业。”石头听了,喜不能禁,乃问:“不知赐了弟子那哪几件奇处?又不知携了弟子到何地方?望乞明示,使弟子不惑。”那僧笑道:“你且莫问,日后自然明白的。”说着,便袖了这石,同那道人飘然而去,竟不知投奔何方何舍。 \hfill ——曹雪芹《红楼梦》} \showexample{mine} \showexample{quanjiao} \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-IVS.tex}} % % \begin{macrocode} %<*ex-IVS> % \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} % % \fi % % \end{implementation} % % % \Finale % \endinput