From 9591c0c57b007ba49f15f0970009bc27efa23db4 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 14 May 2015 21:23:11 +0000 Subject: ctex (14may15) git-svn-id: svn://tug.org/texlive/trunk@37393 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/source/latex/ctex/ctex.dtx | 8645 ++++++++++++++++++++++++++ 1 file changed, 8645 insertions(+) create mode 100644 Master/texmf-dist/source/latex/ctex/ctex.dtx (limited to 'Master/texmf-dist/source/latex/ctex/ctex.dtx') diff --git a/Master/texmf-dist/source/latex/ctex/ctex.dtx b/Master/texmf-dist/source/latex/ctex/ctex.dtx new file mode 100644 index 00000000000..e81542a0afb --- /dev/null +++ b/Master/texmf-dist/source/latex/ctex/ctex.dtx @@ -0,0 +1,8645 @@ +% \iffalse meta-comment +% !TeX program = XeLaTeX +% !TeX encoding = UTF-8 +% +% Copyright (C) 2003--2015 +% CTEX.ORG and any individual authors listed elsewhere in this file. +% -------------------------------------------------------------------------- +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either +% version 1.3c of this license or (at your option) any later +% version. This version of this license is in +% http://www.latex-project.org/lppl/lppl-1-3c.txt +% and the latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of +% LaTeX version 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainers of this work are Leo Liu, Qing Lee and Liam Huang. +% +% -------------------------------------------------------------------------- +% +%<*internal> +\iffalse +% +%<*readme> +ctex is a collection of macro packages and document classes +for LaTeX Chinese typesetting. + +This package is licensed in LPPL. + +The authors and contributors of this package are: + + * Wu Lingyun + * Jiang Jiang + * Wang Yue + * Liu Haiyang + * Li Yanrui + * Chen Zhichu + * Li Qing + * Liam Huang + +If you are interested in the process of development you +may observe + + https://github.com/CTeX-org/ctex-kit + +Report feedback in the Issues section of ctex-kit project, +or in [ctex](http://bbs.ctex.org) forum. + +This package consists of the file ctex.dtx, and the derived files + + ctex.pdf, + ctex.ins, + ctex.sty, + ctexcap.sty, + ctexsize.sty, + ctexart.cls, + ctexbook.cls, + ctexrep.cls, + ctex-c5size.clo, + ctex-cs4size.clo, + ctex-article.def, + ctex-book.def, + ctex-report.def, + ctex-scheme-plain.def, + ctex-scheme-plain-article.def, + ctex-scheme-plain-book.def, + ctex-scheme-plain-report.def, + ctex-scheme-chinese.def, + ctex-scheme-chinese-article.def, + ctex-scheme-chinese-book.def, + ctex-scheme-chinese-report.def, + ctex-name-gbk.cfg, + ctex-name-utf8.cfg, + ctex.cfg, + ctexopts.cfg, + ctex-engine-pdftex.def, + ctex-engine-xetex.def, + ctex-engine-luatex.def, + c19rm.fd, + c19sf.fd, + c19tt.fd, + c70rm.fd, + c70sf.fd, + c70tt.fd, + ctex-fontset-windows.def, + ctex-fontset-windowsnew.def, + ctex-fontset-windowsold.def, + ctex-fontset-adobe.def, + ctex-fontset-fandol.def, + ctex-fontset-mac.def, + ctex-fontset-founder.def, + ctex-fontset-ubuntu.def, + ctexspa.def, + ctexpunct.spa, + ctexmakespa.tex, + ctexspamacro.tex, + zhadobefonts.tex, + zhfandolfonts.tex, + zhfounderfonts.tex, + zhubuntufonts.tex, + zhwindowsfonts.tex, and + README (this file). + +% +%<*internal> +\fi +\begingroup + \def\temp{LaTeX2e} +\expandafter\endgroup\ifx\temp\fmtname\else +\csname fi\endcsname +% +%<*install> + +\newread\inputcheck +\openin\inputcheck=ctex.ver +\ifeof\inputcheck + \def\ctexPutVersion{\string\GetIdInfo$Id$} +\else + \input ctex.ver +\fi +\closein\inputcheck + +\input l3docstrip.tex + +\def\checkOption<#1{% + \ifcase + \ifx*#10\else \ifx/#11\else + \ifx+#12\else \ifx-#13\else + \ifx<#14\else \ifx @#15\else + \ifx.#16\else + 7\fi\fi\fi\fi\fi\fi\fi\relax + \expandafter\starOption\or + \expandafter\slashOption\or + \expandafter\plusOption\or + \expandafter\minusOption\or + \expandafter\verbOption\or + \expandafter\moduleOption\or + \expandafter\expOption\or + \expandafter\doOption\fi + #1% +} +\def\expOption .#1>#2\endLine{% + \maybeMsg{<.#1 . >}% + \Evaluate{#1}% + \begingroup + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 + \xdef\expandedLineStuff{\scantokens{#2\noexpand}}% + \endgroup + \def\do##1##2##3{% + \if1\Expr{##2}\StreamPut##1{\expandedLineStuff}\fi + }% + \activefiles + } + + +\keepsilent +\askforoverwritefalse + +\preamble + + Copyright (C) 2003--2015 + CTEX.ORG and any individual authors listed in the documentation. +------------------------------------------------------------------------------ + + This work may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either + version 1.3c of this license or (at your option) any later + version. This version of this license is in + http://www.latex-project.org/lppl/lppl-1-3c.txt + and the latest version of this license is in + http://www.latex-project.org/lppl.txt + and version 1.3 or later is part of all distributions of + LaTeX version 2005/12/01 or later. + + This work has the LPPL maintenance status `maintained'. + + The Current Maintainers of this work are Leo Liu, Qing Lee and Liam Huang. + +------------------------------------------------------------------------------ + +\endpreamble + +\postamble + + This package consists of the file ctex.dtx, + and the derived files ctex.pdf, + ctex.ins, + ctex.sty, + ctexcap.sty, + ctexsize.sty, + ctexart.cls, + ctexbook.cls, + ctexrep.cls, + ctex-c5size.clo, + ctex-cs4size.clo, + ctex-article.def, + ctex-book.def, + ctex-report.def, + ctex-scheme-plain.def, + ctex-scheme-plain-article.def, + ctex-scheme-plain-book.def, + ctex-scheme-plain-report.def, + ctex-scheme-chinese.def, + ctex-scheme-chinese-article.def, + ctex-scheme-chinese-book.def, + ctex-scheme-chinese-report.def, + ctex-name-gbk.cfg, + ctex-name-utf8.cfg, + ctex.cfg, + ctexopts.cfg, + ctex-engine-pdftex.def, + ctex-engine-xetex.def, + ctex-engine-luatex.def, + c19rm.fd, + c19sf.fd, + c19tt.fd, + c70rm.fd, + c70sf.fd, + c70tt.fd, + ctex-fontset-windows.def, + ctex-fontset-windowsnew.def, + ctex-fontset-windowsold.def, + ctex-fontset-adobe.def, + ctex-fontset-fandol.def, + ctex-fontset-mac.def, + ctex-fontset-founder.def, + ctex-fontset-ubuntu.def, + ctexspa.def, + ctexpunct.spa, + ctexmakespa.tex, + ctexspamacro.tex, + zhadobefonts.tex, + zhfandolfonts.tex, + zhfounderfonts.tex, + zhubuntufonts.tex, + zhwindowsfonts.tex, and + README. +\endpostamble + +\declarepostamble\emptypostamble +\endpostamble + + +\generate + { + \usedir{tex/latex/ctex} + \file{ctex.sty} {\from{\jobname.dtx}{package,style}} + \file{ctexcap.sty} {\from{\jobname.dtx}{package,ctexcap}} + \file{ctexsize.sty} {\from{\jobname.dtx}{package,ctexsize}} + \file{ctexart.cls} {\from{\jobname.dtx}{class,article}} + \file{ctexbook.cls} {\from{\jobname.dtx}{class,book}} + \file{ctexrep.cls} {\from{\jobname.dtx}{class,report}} + \usepostamble\emptypostamble + \file{ctex-c5size.clo} {\from{\jobname.dtx}{c5size}} + \file{ctex-cs4size.clo} {\from{\jobname.dtx}{cs4size}} + \file{ctex-article.def} {\from{\jobname.dtx}{heading,article}} + \file{ctex-book.def} {\from{\jobname.dtx}{heading,book}} + \file{ctex-report.def} {\from{\jobname.dtx}{heading,report}} + \file{ctex-scheme-plain.def} {\from{\jobname.dtx}{scheme,generic,plain}} + \file{ctex-scheme-plain-article.def} {\from{\jobname.dtx}{scheme,article,plain}} + \file{ctex-scheme-plain-book.def} {\from{\jobname.dtx}{scheme,book,plain}} + \file{ctex-scheme-plain-report.def} {\from{\jobname.dtx}{scheme,report,plain}} + \file{ctex-scheme-chinese.def} {\from{\jobname.dtx}{scheme,generic,chinese}} + \file{ctex-scheme-chinese-article.def} {\from{\jobname.dtx}{scheme,article,chinese}} + \file{ctex-scheme-chinese-book.def} {\from{\jobname.dtx}{scheme,book,chinese}} + \file{ctex-scheme-chinese-report.def} {\from{\jobname.dtx}{scheme,report,chinese}} + \file{ctex-name-gbk.cfg} {\from{\jobname.dtx}{GBK}} + \file{ctex-name-utf8.cfg} {\from{\jobname.dtx}{UTF8}} + \file{ctex.cfg} {\from{\jobname.dtx}{config}} + \file{ctexopts.cfg} {\from{\jobname.dtx}{ctexopts}} + \file{ctex-engine-pdftex.def} {\from{\jobname.dtx}{pdftex}} + \file{ctex-engine-xetex.def} {\from{\jobname.dtx}{xetex}} + \file{ctex-engine-luatex.def} {\from{\jobname.dtx}{luatex}} + \file{c19rm.fd} {\from{\jobname.dtx}{rm,c19}} + \file{c19sf.fd} {\from{\jobname.dtx}{sf,c19}} + \file{c19tt.fd} {\from{\jobname.dtx}{tt,c19}} + \file{c70rm.fd} {\from{\jobname.dtx}{rm,c70}} + \file{c70sf.fd} {\from{\jobname.dtx}{sf,c70}} + \file{c70tt.fd} {\from{\jobname.dtx}{tt,c70}} + \file{ctex-fontset-windows.def} {\from{\jobname.dtx}{fontset,windows}} + \file{ctex-fontset-windowsnew.def} {\from{\jobname.dtx}{fontset,windowsnew}} + \file{ctex-fontset-windowsold.def} {\from{\jobname.dtx}{fontset,windowsold}} + \file{ctex-fontset-adobe.def} {\from{\jobname.dtx}{fontset,adobe}} + \file{ctex-fontset-fandol.def} {\from{\jobname.dtx}{fontset,fandol}} + \file{ctex-fontset-mac.def} {\from{\jobname.dtx}{fontset,mac}} + \file{ctex-fontset-founder.def} {\from{\jobname.dtx}{fontset,founder}} + \file{ctex-fontset-ubuntu.def} {\from{\jobname.dtx}{fontset,ubuntu}} + \file{ctexspa.def} + { + \from{\jobname.dtx} {ctexspa} + \from{ctexpunct.spa} {} + } + \file{ctexmakespa.tex} {\from{\jobname.dtx}{spa,make}} + \file{ctexspamacro.tex} {\from{\jobname.dtx}{spa,macro}} + \file{zhadobefonts.tex} {\from{\jobname.dtx}{zhmap,adobe}} + \file{zhfandolfonts.tex} {\from{\jobname.dtx}{zhmap,fandol}} + \file{zhfounderfonts.tex} {\from{\jobname.dtx}{zhmap,founder}} + \file{zhubuntufonts.tex} {\from{\jobname.dtx}{zhmap,ubuntu}} + \file{zhwindowsfonts.tex} {\from{\jobname.dtx}{zhmap,windows}} + \usedir{source/latex/ctex} + \file{\jobname.ins} {\from{\jobname.dtx}{install}} + \nopreamble\nopostamble + \usedir{doc/latex/ctex} + \file{README.txt} {\from{\jobname.dtx}{readme}} + } + +\catcode32=12\space + +\Msg{*************************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the following *} +\Msg{* file into proper directories searched by TeX: *} +\Msg{* *} +\Msg{* The recommended directory is TDS:tex/latex/ctex *} +\Msg{* *} +\Msg{* ctex.sty *} +\Msg{* ctexcap.sty *} +\Msg{* ctexsize.sty *} +\Msg{* ctexart.cls *} +\Msg{* ctexbook.cls *} +\Msg{* ctexrep.cls *} +\Msg{* ctex-c5size.clo *} +\Msg{* ctex-cs4size.clo *} +\Msg{* ctex-article.def *} +\Msg{* ctex-book.def *} +\Msg{* ctex-report.def *} +\Msg{* ctex-scheme-plain.def *} +\Msg{* ctex-scheme-plain-article.def *} +\Msg{* ctex-scheme-plain-book.def *} +\Msg{* ctex-scheme-plain-report.def *} +\Msg{* ctex-scheme-chinese.def *} +\Msg{* ctex-scheme-chinese-article.def *} +\Msg{* ctex-scheme-chinese-book.def *} +\Msg{* ctex-scheme-chinese-report.def *} +\Msg{* ctex-name-gbk.cfg *} +\Msg{* ctex-name-utf8.cfg *} +\Msg{* ctex.cfg *} +\Msg{* ctexopts.cfg *} +\Msg{* ctex-engine-pdftex.def *} +\Msg{* ctex-engine-xetex.def *} +\Msg{* ctex-engine-luatex.def *} +\Msg{* c19rm.fd *} +\Msg{* c19sf.fd *} +\Msg{* c19tt.fd *} +\Msg{* c70rm.fd *} +\Msg{* c70sf.fd *} +\Msg{* c70tt.fd *} +\Msg{* ctex-fontset-windows.def *} +\Msg{* ctex-fontset-windowsnew.def *} +\Msg{* ctex-fontset-windowsold.def *} +\Msg{* ctex-fontset-adobe.def *} +\Msg{* ctex-fontset-fandol.def *} +\Msg{* ctex-fontset-mac.def *} +\Msg{* ctex-fontset-founder.def *} +\Msg{* ctex-fontset-ubuntu.def *} +\Msg{* ctexspa.def *} +\Msg{* ctexmakespa.tex *} +\Msg{* ctexspamacro.tex *} +\Msg{* zhadobefonts.tex *} +\Msg{* zhfandolfonts.tex *} +\Msg{* zhfounderfonts.tex *} +\Msg{* zhubuntufonts.tex *} +\Msg{* zhwindowsfonts.tex *} +\Msg{* *} +\Msg{* To produce the documentation run the file ctex.dtx *} +\Msg{* through XeLaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{*************************************************************} + +\endbatchfile +% +%<*internal> +\fi +% +%<*!(readme|install|zhmap|spa)> +%<*!(c19|c70|ctexspa)> +%<*driver|package|class> +\NeedsTeXFormat{LaTeX2e} +\RequirePackage{expl3} +% +%<.!(readme|install|zhmap|spa|c19|c70|ctexspa)>\ctexPutVersion +%<*driver> +\InputIfFileExists{ctex.ver}{}{ + \def\ctexGetVersionInfo{\GetIdInfo$Id$}} +\ctexGetVersionInfo + {ctex source file} +\ProvidesExplFile{\ExplFileName.\ExplFileExtension} +% +% +% \end{macrocode} +% +% \subsection{用户设置接口} +% +% \changes{v2.0}{2014/03/18}{新增统一设置接口 \tn{ctexset}。} +% +% \begin{macro}{\ctexset} +% \begin{macrocode} +\NewDocumentCommand \ctexset { +m } + { \keys_set:nn { ctex } {#1} } +% \end{macrocode} +% \end{macro} +% +% \changes{v2.0}{2015/03/21}{\tn{CTEXsetup}, \tn{CTEXoptions} 是过时命令。} +% \begin{macro}{\CTEXsetup,\CTEXoptions} +% 过时命令。 +% \begin{macrocode} +\NewDocumentCommand \CTEXsetup { +o > { \TrimSpaces } m } + { + \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXsetup } + { \ctexset~ {~ #2~ =~ {~ #1~ }~ }~ is~ set. } + \IfNoValueF {#1} { \keys_set:nn { ctex / #2 } {#1} } + } +\NewDocumentCommand \CTEXoptions { +o } + { + \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXoptions } + { \ctexset~ {~ #1~ }~ is~ set. } + \IfNoValueF {#1} { \keys_set:nn { ctex } {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{特定引擎支持与设置} +% +% \subsubsection{\pkg{ctex-engine-pdftex.def}} +% +% \begin{macrocode} +%<*pdftex> +% \end{macrocode} +% +% 首先检查选项,决定是否载入 \pkg{zhmCJK} 宏包。 +% \begin{macrocode} +\if_bool:N \g_@@_zhmCJK_bool + \PassOptionsToPackage { encoding = \l_@@_encoding_tl } { zhmCJK } + \RequirePackage { zhmCJK } +% \end{macrocode} +% 不载入 \pkg{zhmCJK} 宏包时直接调用 \pkg{CJK} 及相关宏包。 +% \begin{macrocode} +\else: + \str_if_eq:onTF { \l_@@_encoding_tl } { GBK } + { \RequirePackage { CJK } } + { \RequirePackage { CJKutf8 } } + \RequirePackage { CJKpunct , CJKspace } +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_load_zhmap:nnnn} +% 载入 \pkg{zhmetrics} 的字体映射文件,同时设置 \tn{CJKrmdefault} 等。 +% \begin{macrocode} + \cs_new_protected_nopar:Npn \ctex_load_zhmap:nnnn #1#2#3#4 + { + \tl_set:Nn \CJKrmdefault {#1} + \tl_set:Nn \CJKsfdefault {#2} + \tl_set:Nn \CJKttdefault {#3} + \AtBeginDvi { \file_input:n {#4} } + \ctex_at_end_package:nn { atbegshi } + { \AtBeginShipoutFirst { \file_input:n {#4} } } + } + \@onlypreamble \ctex_load_zhmap:n +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} + \tl_if_exist:NF \CJKfamilydefault + { \tl_const:Nn \CJKfamilydefault { \CJKrmdefault } } + \tl_if_exist:NF \CJKrmdefault { \tl_new:N \CJKrmdefault } + \tl_if_exist:NF \CJKsfdefault { \tl_new:N \CJKsfdefault } + \tl_if_exist:NF \CJKttdefault { \tl_new:N \CJKttdefault } + \ctex_preto_cmd:NnTF \rmfamily { \CJKfamily { \CJKrmdefault } } { } + { \ctex_patch_failure:N \rmfamily } + \ctex_preto_cmd:NnTF \sffamily { \CJKfamily { \CJKsfdefault } } { } + { \ctex_patch_failure:N \sffamily } + \ctex_preto_cmd:NnTF \ttfamily { \CJKfamily { \CJKttdefault } } { } + { \ctex_patch_failure:N \ttfamily } + \ctex_preto_cmd:NnTF \normalfont { \CJKfamily { \CJKfamilydefault } } + { \cs_set_eq:NN \reset@font \normalfont } + { \ctex_patch_failure:N \normalfont } +% \end{macrocode} +% +% \pkg{zhmCJK} 判断结束。 +% \begin{macrocode} +\fi: +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_CJK_input:n,\CJK@input} +% \pkg{breqn} 包可能会在正文中将 |^| 的 \tn{catcode} 改为 $12$ 或 $13$,这将 +% 破坏 \pkg{CJK} 对汉字的首字节的定义(\tn{CJK@loadBinding} 和 +% \tn{CJK@loadEncoding})。因此需要确保载入 \file{.enc} 和 \file{.bdg} 文件时, +% |^| 的 \tn{catcode} 为 $7$。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_CJK_input:n #1 + { + \ctex_file_wrapper:nnn + { + \char_set_catcode_other:n { 60 } % < + \char_set_catcode_math_superscript:n { 94 } % ^ + \int_set_eq:NN \tex_endlinechar:D \c_minus_one + } + { \file_input:n {#1} } + { + \char_set_catcode:nn { 60 } { \char_value_catcode:n { 60 } } + \char_set_catcode:nn { 94 } { \char_value_catcode:n { 94 } } + \int_set:Nn \tex_endlinechar:D { \int_use:N \tex_endlinechar:D } + } + } +\cs_set_eq:NN \CJK@input \ctex_CJK_input:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_plane_to_utfxvibe:Nn,\CJK@surr} +% \changes{v2.0}{2014/04/08}{解决与 \tn{nouppercase} 的冲突。} +% \pkg{fancyhdr} 宏包的 \tn{nouppercase} 会将 \tn{uppercase} 定义为 \tn{relax},而 +% \tn{CJK@surr} 需要用它将 \tn{CJK@plane} 转化成大写字母,这就造成了冲突^^A +% \footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/146}}。 +% 我们在这里给出 \tn{CJK@surr} 的一个不依赖 \tn{uppercase} 的实现。 +% \begin{macrocode} +\if_cs_exist:N \CJK@surr + \cs_new_protected_nopar:Npn \ctex_plane_to_utfxvibe:Nn #1#2 + { + \tl_set:Nx \l_@@_tmp_tl {#2} + \int_set:Nn \l_@@_tmp_int + { \exp_args:No \int_from_hex:n { \l_@@_tmp_tl } } + \int_compare:nNnTF \l_@@_tmp_int < \c_two_hundred_fifty_six + { \tl_gset:Nx #1 { \int_to_Hex:n { \l_@@_tmp_int } } } + { + \int_sub:Nn \l_@@_tmp_int { \c_two_hundred_fifty_six } + \tl_gset:Nx #1 + { + \int_to_Hex:n + { \int_div_truncate:nn { \l_@@_tmp_int } { \c_four } + "D800 } + \int_to_Hex:n + { \int_mod:nn { \l_@@_tmp_int } { \c_four } + "DC } + } + } + } + \cs_set_eq:NN \CJK@surr \ctex_plane_to_utfxvibe:Nn +\fi: +% \end{macrocode} +% \end{macro} +% +% \pkg{CJKpunct} 宏包会在 \tn{AtBeginDocument} 的里设置标点格式为 \opt{quanjiao}。 +% \begin{macrocode} +\AtBeginDocument + { + \str_if_eq_x:nnF { \l_@@_punct_tl } { quanjiao } + { \punctstyle { \l_@@_punct_tl } } + } +% \end{macrocode} +% +% 启用中文字符功能。\texttt{GBK} 编码时,将汉字的首字节设置为活动字符,并对这些 +% 字符初始化;\texttt{UTF8} 编码时,上游宏包已经处理好。 +% \tn{CJK@makeActive} 应该先于 \file{ctex-name-gbk.cfg} 等文件的载入。 +% 注意 \tn{CJK@loadBinding} 需要调用补丁后的 \tn{CJK@input}。使用 +% \pkg{zhmCJK} 时,此功能已经被启用。 +% \begin{macrocode} +\reverse_if:N \if_bool:N \g_@@_zhmCJK_bool + \str_if_eq:onF { \l_@@_encoding_tl } { UTF8 } + { + \CJK@makeActive + \CJK@loadBinding { standard } + } +% \end{macrocode} +% +% 在导言区结束时调用 \tn{CJK@envStart} 启用完整的中文功能。 +% +% \tn{CJK@envStart} 的定义是 +% \begin{verbatim} +% \def\CJK@envStart#1#2#3{ +% \CJK@upperReset +% \ifCJK@lowercase@ +% \CJK@lowerReset +% \fi% +% \CJK@makeActive% +% \CJK@global\let\CJK@selectFamily \CJK@selFam +% \CJK@global\let\CJK@selectEnc \CJK@selEnc% +% \def\CJK@@@enc{#2} +% \ifx\CJK@@@enc \@empty +% \PackageInfo{CJK}{ +% no encoding parameter given,\MessageBreak +% waiting for \protect\CJKenc\space commands} +% \else +% \CJKenc{#2} +% \fi +% \CJKfontenc{#2}{#1} +% \CJKfamily{#3} +% \def\CJK@series{\f@series} +% \def\CJK@shape{\f@shape}% +% \csname CJKhook\endcsname} +% \end{verbatim} +% \tn{CJK@upperReset} 可能会有一定风险,因此我们直到导言区末尾才使用 +% \tn{CJK@envStart}。这样可以避免将 \env{CJK} 环境内置入 \env{document} 环境的 +% 最里层,最后也就不需要 \tn{clearpage}。\pkg{zhmCJK} 已经提供类似功能。 +% \begin{macrocode} + \exp_args:Nx \AtEndPreamble + { + \exp_not:N \CJK@envStart + { } { \l_@@_encoding_tl } { \exp_not:N \CJKfamilydefault } + \exp_not:N \CJKtilde + } +% \end{macrocode} +% +% \pkg{zhmCJK} 判断结束。 +% \begin{macrocode} +\fi: +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_auto_ignorespaces:} +% 关闭名字空间,保存 \tn{CJK@@ignorespaces} 的定义,方便使用。 +% \begin{macrocode} +%<@@=> +\cs_new_eq:NN \ctex_auto_ignorespaces: \CJK@@ignorespaces +% \end{macrocode} +% 恢复名字空间,要把它放在一个 \env{macrocode} 环境中,\cls{l3doc} 才能正确工作。 +% \begin{macrocode} +%<@@=ctex> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ignorespaces_case:N,\ctex_set_ignorespaces:} +% 设置忽略空格的的方式。根据 \opt{space} 选项的值重定义 \tn{CJK@ignorespaces}, +% 并保存起来供 \tn{CJKhook} 备用。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ignorespaces_case:N #1 + { + \cs_set_protected_nopar:Npn \ctex_set_ignorespaces: + { \cs_set_eq:NN \CJK@ignorespaces #1 } + \ctex_set_ignorespaces: + } +\cs_new_protected_nopar:Npn \ctex_set_ignorespaces: + { \cs_set_eq:NN \CJK@ignorespaces \ctex_auto_ignorespaces: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\CJKhook} +% \env{CJK} 和 \env{CJK*} 环境都会重新定义 \tn{CJK@ignorespaces}。我们在 \pkg{CJK} +% 宏包提供的 \tn{CJKhook} 里重新设置它,让这两个环境忽略空格的方式都受 \opt{space} +% 选项的控制。这对 \pkg{zhmCJK} 是必要的。 +% \begin{macrocode} +\ctex_add_hook:Nn \CJKhook { \ctex_set_ignorespaces: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_punct_set:n} +% 设置 CJK 族对应到实际的字体。|#1| 是 \opt{fontset} 的名字。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_punct_set:n #1 + { + \clist_map_inline:Nn \c_@@_punct_family_clist + { + \cs_if_free:cF { c_@@_ #1 ##1 _punct_spaces_tl } + { + \cs_set_eq:cc + { CJKpunct@ ##1 @spaces } + { c_@@_ #1 ##1 _punct_spaces_tl } + } + } + } +\clist_const:Nn \c_@@_punct_family_clist + { + zhsong , zhhei , zhfs , zhkai , zhli , zhyou , + zhsongb , zhheil , zhheib , zhyoub , zhyahei , zhyaheib + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_punct_map_family:nn} +% CJK 族 |#1| 使用族 |#2| 的边界信息。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_punct_map_family:nn #1#2 + { + \cs_if_free:cF { CJKpunct@ #2 @spaces } + { \cs_set_eq:cc { CJKpunct@ #1 @spaces } { CJKpunct@ #2 @spaces } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_punct_map_bfseries:nn} +% CJK 族 |#1| 的 \tn{bfseries} 使用族 |#2| 的边界信息。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_punct_map_bfseries:nn #1#2 + { + \clist_map_inline:nn {#1} + { + \ctex_punct_map_series:nnn { ##1 } { b } {#2} + \ctex_punct_map_series:nnn { ##1 } { bx } {#2} + } + } +\cs_new_protected_nopar:Npn \ctex_punct_map_series:nnn #1#2#3 + { + \CJKpunctmapfamily { C19 } {#1} {#2} { m } {#3} + \CJKpunctmapfamily { C19 } {#1} {#2} { it } {#3} + \CJKpunctmapfamily { C19 } {#1} {#2} { sl } {#3} + \CJKpunctmapfamily { C70 } {#1} {#2} { m } {#3} + \CJKpunctmapfamily { C70 } {#1} {#2} { it } {#3} + \CJKpunctmapfamily { C70 } {#1} {#2} { sl } {#3} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_punct_map_itshape:nn} +% CJK 族 |#1| 的 \tn{itshape} 使用族 |#2| 的边界信息。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_punct_map_itshape:nn #1#2 + { + \CJKpunctmapfamily { C19 } {#1} { m } { it } {#2} + \CJKpunctmapfamily { C19 } {#1} { b } { it } {#2} + \CJKpunctmapfamily { C19 } {#1} { bx } { it } {#2} + \CJKpunctmapfamily { C70 } {#1} { m } { it } {#2} + \CJKpunctmapfamily { C70 } {#1} { b } { it } {#2} + \CJKpunctmapfamily { C70 } {#1} { bx } { it } {#2} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_punct_space:nn,\ctexspadef} +% 定义标点的边界信息。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_punct_space:nn #1#2 + { \tl_const:cn { c_@@_ #1 _punct_spaces_tl } {#2} } +\cs_new_eq:NN \ctexspadef \ctex_punct_space:nn +% \end{macrocode} +% \end{macro} +% +% 载入边界信息文件。 +% \begin{macrocode} +\ctex_file_input:n { ctexspa.def } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-engine-xetex.def}} +% +% \begin{macrocode} +%<*xetex> +% \end{macrocode} +% +% \begin{macrocode} +\RequirePackage { xeCJK } +\exp_args:Nx \xeCJKsetup + { + LoadFandol = false , + AutoFakeBold = true , + PunctStyle = \l_@@_punct_tl + } +% \end{macrocode} +% +% 最新版本的 \pkg{fontspec} 默认对 \tn{rmfamily} 和 \tn{sffamily} 设置 +% |Ligatures=TeX|,对 \tn{ttfamily} 设置 |WordSpace={1,0,0}| 和 +% |PunctuationSpace=WordSpace|。 +% \begin{macrocode} +\@ifpackagelater { fontspec } { 2014/05/25 } { } + { \msg_error:nnn { ctex } { package-too-old } { fontspec } } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-engine-luatex.def}} +% +% \begin{macrocode} +%<*luatex> +% \end{macrocode} +% +% \changes{v2.0}{2014/03/08}{通过 \pkg{LuaTeX-ja} 宏包支持 \LuaLaTeX。} +% +% \pkg{LuaTeX-ja} 为了兼容 p\LaTeX 的使用习惯,对 \LaTeXe 的 \pkg{NFSS} 作了不少 +% 修改和扩充,这对于简体中文用户来说不是必要的。我们在这里禁用它。 +% \begin{macrocode} +\msg_new:nnn { ctex } { luatexja-loaded } + { + Package~`luatexja'~can~not~be~loaded~before~`ctex'.\\ + Loading~file~`#1'~will~abort! + } +\@ifpackageloaded { luatexja } + { \msg_critical:nnx { ctex } { luatexja-loaded } { \g_file_current_name_tl } } + { \tl_const:cn { ver@ltj-latex.\@pkgextension } { 9999/99/99 } } +% \end{macrocode} +% +% \begin{macrocode} +\RequirePackage { luatexja } +\@ifpackagelater { luatexja-core } { 2015/02/22 } { } + { \msg_error:nnn { ctex } { package-too-old } { luatexja } } +% \end{macrocode} +% +% \begin{macrocode} +\RequirePackage { fontspec } +\@ifpackagelater { fontspec } { 2014/05/25 } { } + { \msg_error:nnn { ctex } { package-too-old } { fontspec } } +% \end{macrocode} +% +% \paragraph{\pkg{LuaTeX-ja} 的默认设置} +% +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% 以下设置抄录自 \file{lltjdefs.sty}。 +% \begin{macrocode} +\ltjdefcharrange{1}{"80-"36F, "1E00-"1EFF} +\ltjdefcharrange{2}{"370-"4FF, "1F00-"1FFF} +\ltjdefcharrange{3}{% + "2000-"243F, "2500-"27BF, "2900-"29FF, "2B00-"2BFF} +\ltjdefcharrange{4}{% + "500-"10FF, "1200-"1DFF, "2440-"245F, "27C0-"28FF, "2A00-"2AFF, + "2C00-"2E7F, "4DC0-"4DFF, "A4D0-"A82F, "A840-"ABFF, "FB00-"FE0F, + "FE20-"FE2F, "FE70-"FEFF, "10000-"1FFFF, "E000-"F8FF} % non-Japanese +\ltjdefcharrange{5}{"D800-"DFFF, "E0000-"E00FF, "E01F0-"10FFFF} +\ltjdefcharrange{6}{% + "2460-"24FF, "2E80-"2EFF, "3000-"30FF, "3190-"319F, "31F0-"4DBF, + "4E00-"9FFF, "F900-"FAFF, "FE10-"FE6F, "20000-"2FFFF, "E0100-"E01EF} +\ltjdefcharrange{7}{ + "1100-"11FF, "2F00-"2FFF, "3100-"31EF, "A000-"A4CF, "A830-"A83F, + "AC00-"D7FF} +\ltjdefcharrange{8}{"A7, "A8, "B0, "B1, "B4, "B6, "D7, "F7} +\ltjsetparameter{jacharrange={-1, +2, +3, -4, -5, +6, +7, +8}} +\directlua{for x=128,255 do luatexja.math.is_math_letters[x] = true end} +% \end{macrocode} +% +% 以下设置抄录自 \file{ltj-latex.sty}。 +% \begin{macrocode} +\directlua{ + local s = kpse.find_file('ltj-kinsoku.lua', 'tex') + luatexja.stack.charprop_stack_table[0] = s and dofile(s) or {} +} +\ltjsetparameter{kanjiskip=\z@ plus .4pt minus .4pt, + xkanjiskip=.25\zw plus 1pt minus 1pt, + autospacing, autoxspacing, jacharrange={-1}, + yalbaselineshift=\z@, yjabaselineshift=\z@, + jcharwidowpenalty=500, differentjfm=paverage +} +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% \paragraph{\pkg{LuaTeX-ja} 的补丁} +% +% \begin{macrocode} +%<@@=ctex_ltj> +% \end{macrocode} +% +% 在 \LaTeX{} 下,\pkg{LuaTeX-ja} 对 \pkg{fontspec}、\pkg{xunicode}、\pkg{unicode-math} +% 和 \pkg{listings} 打了补丁。其中前三个是把 \tn{char} 换成 \tn{ltjalchar},确保 +% 字符是 ALchar 类。我们这里用 \pkg{xunicode-addon} 来处理 \pkg{xunicode}。 +% \begin{macrocode} +\RequirePackage { xunicode-addon } +\AtBeginUTFCommand + { + \group_begin: + \ctex_lua_now_x:n { tex.globaldefs = 0 } + \ltj@allalchar + } +\AtEndUTFCommand { \group_end: } +% \end{macrocode} +% 对 \pkg{fontspec} 沿用 \pkg{LuaTeX-ja} 的补丁。 +% \begin{macrocode} +\RequirePackage { lltjp-fontspec } +% \end{macrocode} +% \pkg{lltjp-unicode-math} 让数学符号命令成为普通的文字宏。为了避免它被展开,应该 +% 用 \tn{protected} 来定义。 +% \begin{macrocode} +\group_begin: +\char_set_catcode_other:n { \c_zero } +\cs_new_protected:Npn \@@_um_char:Nw #1 = #2 \q_nil + { + \group_begin: + \char_set_lccode:nn { \c_zero } {#2} + \tex_lowercase:D + { + \group_end: + \cs_gset_protected_nopar:Npn #1 + { + \mode_if_math:TF { ^^@ } + { { + \ctex_lua_now_x:n { tex.globaldefs = 0 } + \ltj@allalchar ^^@ + } } + } + } + \ltjsetmathletter {#2} + } +\group_end: +\ctex_at_end_package:nn { unicode-math } + { + \cs_if_free:NF \um_cs_set_eq_active_char:Nw + { \cs_set_eq:NN \um_cs_set_eq_active_char:Nw \@@_um_char:Nw } + } +% \end{macrocode} +% 对 \pkg{listings} 的补丁是让代码环境支持 JAchar 类。\pkg{LuaTeX-ja} 的补丁会将 +% 代码目录标题改为日文,我们不需要。 +% \begin{macrocode} +\ctex_at_end_package:nn { listings } + { + \use:x + { + \exp_not:N \RequirePackage { lltjp-listings } + \tl_set:Nn \exp_not:N \lstlistingname + { \exp_not:o { \lstlistingname } } + \tl_set:Nn \exp_not:N \lstlistlistingname + { \exp_not:o { \lstlistlistingname } } + } + } +% \end{macrocode} +% +% \paragraph{字体切换方式} +% +% \begin{macro}[internal]{\ctex_ltj_select_font:,\CJK@family} +% \tn{CJK@family} 保存的是当前 CJK 实际的字体族名,如果为空表示没有设置过字体。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_select_font: + { + \cs_if_exist_use:cF { \l_@@_current_font_tl } + { \tl_if_empty:NF \CJK@family { \@@_select_font_aux: } } + } +\tl_new:N \CJK@family +\tl_new:N \l_@@_current_font_tl +\tl_set:Nn \l_@@_current_font_tl + { \CJK@encoding / \CJK@family / \f@series / \f@shape / \f@size } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_select_font_aux:} +% 使用 \tn{pickup@font} 取得字体名称前,总需要先设置 \tn{font@name}。在这里将 +% \tn{f@family} 换成 CJK 字体族,并确保编码正确。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_select_font_aux: + { + \group_begin: + \tl_set_eq:NN \f@encoding \CJK@encoding + \tl_set_eq:NN \f@family \CJK@family + \@@_push_fontname:n { \use:c { \curr@fontshape / \f@size } } + \ctex_ltj_pickup_font: + \group_end: + \font@name + \@@_pop_fontname: +% \end{macrocode} +% 当字形未定义的时候,\textsf{NFSS} 就会启动替换机制(\tn{wrong@fontshape})。 +% 第一次启动后,\cs{l_@@_current_font_tl} 还是没有定义。为此,我们再次选择字体, +% 确保它有定义和指向正确的 \texttt{font.id}。这对 \opt{AlternateFont} 的设置 +% 特别重要。 +% \begin{macrocode} + \cs_if_exist:cF { \l_@@_current_font_tl } + { \@@_select_font_aux: } + } +\cs_new_protected_nopar:Npn \@@_push_fontname:n #1 + { + \cs_gset_eq:NN \@@_save_fontname:w \font@name + \cs_gset_nopar:Npx \font@name {#1} + } +\cs_new_protected_nopar:Npn \@@_pop_fontname: + { \cs_gset_eq:NN \font@name \@@_save_fontname:w } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_pickup_font:} +% 替换 \tn{define@newfont} 内部调用的 \tn{extract@font} 和 \tn{do@subst@correction}。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_pickup_font: + { + \exp_after:wN \cs_if_exist:NF \font@name + { + \group_begin: + \cs_set_eq:NN \extract@font \ctex_ltj_extract_font: + \cs_set_eq:NN \do@subst@correction \ctex_ltj_subst_font: + \define@newfont + \group_end: + } + } +\cs_new_eq:NN \pickup@jfont \ctex_ltj_pickup_font: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_extract_font:} +% \pkg{LuaTeX-ja} 的 \tn{globaljfont} 在 \pkg{luatexja-core} 中定义: +% \begin{verbatim} +% %%%%%%%% \jfont\CS={...:...;jfm=metric;...}, \globaljfont +% \protected\def\jfont{% +% \afterassignment\ltj@@jfont\directlua{luatexja.jfont.jfontdefX(false, 'yoko')}} +% \protected\def\globaljfont{% +% \afterassignment\ltj@@jfont\directlua{luatexja.jfont.jfontdefX(true, 'yoko')}} +% \def\ltj@@jfont{\directlua{luatexja.jfont.jfontdefY()}} +% \end{verbatim} +% \texttt{jfontdefX} 函数的作用是把 \tn{CS} 定义为其后的字体,\texttt{jfontdefY} +% 的作用是更新 \texttt{JFM} 和记录相关字体信息。最后的工作是: +% \begin{verbatim} +% tex.sprint(cat_lp, global_flag, '\\protected\\expandafter\\def\\csname ', +% cstemp , '\\endcsname{\\ltj@cur'.. +% (jfm_dir == 'yoko' and 'j' or 't') .. 'fnt', fn, '\\relax}') +% \end{verbatim} +% \tn{CS} 的作用就是把 \tn{ltj@curjfnt} 设置为刚才定义的字体的 \texttt{font.id}。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_extract_font: + { + \get@external@font + \ctex_ltj_if_alternate_shape_exist:nT { \curr@fontshape } + { + \tl_set:Nx \external@font + { \exp_after:wN \@@_patch_external_font:w \external@font } + } + \exp_after:wN \globaljfont \font@name \external@font \scan_stop: +% \end{macrocode} +% 这里 \tn{font@name} 不会直接改变当前字体,而 \tn{DeclareFontFamily} 和 +% \tn{DeclareFontShape} 的最后一个参数通常要使用 \tn{font} 来引用当前字体。 +% 为此,我们在分组内启用之前定义的字体,以便能得到正确的 \tn{font}。对字体参数的 +% 赋值总是全局的,不会受到分组的影响。 +% \begin{macrocode} + \font@name + \ctex_lua_now_x:n { font.current(tex.attribute['ltj@curjfnt']) } + \use:c { \f@encoding + \f@family } + \use:c { \curr@fontshape } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_subst_font:} +% \tn{do@subst@correction} 在设置通过 \texttt{sub} 或者 \texttt{ssub} 函数定义的 +% 字体时会用到。如果没有设置 \opt{SlantedFont},\pkg{fontspec} 会设置 +% \tn{itdefault} 作为 \tn{sldefault} 的替代字形,因而会用到这个函数。它的本来定义是: +% \begin{verbatim} +% \def\do@subst@correction{% +% \xdef\subst@correction{% +% \font@name +% \global\expandafter\font +% \csname \curr@fontshape/\f@size\endcsname +% \noexpand\fontname\font +% \relax}% +% \aftergroup\subst@correction +% } +% \end{verbatim} +% 我们在这里不需要定义新字体,而是设置对应字体的命令。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_subst_font: + { + \ctex_ltj_if_alternate_shape_exist:nF { \curr@fontshape } + { + \group_begin: + \tl_set_eq:NN \CJK@family \f@family + \cs_if_exist:cF { \l_@@_current_font_tl } + { + \cs_gset_protected_nopar:Npx \subst@correction + { + \cs_new_eq:NN + \exp_not:c { \l_@@_current_font_tl } + \font@name + } + \group_insert_after:N \group_insert_after:N + \group_insert_after:N \subst@correction + } + \group_end: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal,TF]{\ctex_ltj_if_alternate_shape_exist:n} +% 即 \pkg{LuaTeX-ja} 中的 \tn{ltj@@does@alt@set},判断是否存在替代字体。 +% \begin{macrocode} +\prg_new_conditional:Npnn \ctex_ltj_if_alternate_shape_exist:n #1 { T , F , TF } + { + \ctex_lua_now_x:n { luatexja.jfont.does_alt_set ('\luatexluaescapestring {#1}') } + \prg_return_true: \else: \prg_return_false: \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_patch_external_font:w} +% 若对字体的定义完全相同,则它们有相同的 \texttt{font.id}。因此如果字形是由 +% \textsf{NFSS} 的替换机制定义的,它们就有相同的 \texttt{font.id}。 +% |print_aftl_address| 函数的定义是 +% \begin{verbatim} +% function print_aftl_address() +% tex.sprint(cat_lp, ';ltjaltfont' .. tostring(aftl_base):sub(8)) +% end +% \end{verbatim} +% 主要目的是,如果当前字形有替代字体,则往字形的定义中加入一些标志,确保 +% \texttt{font.id} 唯一。 +% \begin{macrocode} +\cs_new_nopar:Npn \@@_patch_external_font:w #1 ~ at + { #1 \ctex_lua_now_x:n { luatexja.jfont.print_aftl_address() } ~ at } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_select_alternate_font:} +% 在 \tn{selectfont} 中更新替代字体。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_select_alternate_font: + { + \ctex_ltj_if_alternate_shape_exist:nT { \l_@@_current_shape_tl } + { + \ctex_lua_now_x:n + { + luatexja.jfont.output_alt_font_cmd + ('y', '\luatexluaescapestring { \l_@@_current_shape_tl }') + } + \ctex_lua_now_x:n { luatexja.jfont.pickup_alt_font_a ('\f@size') } + } + } +\tl_new:N \l_@@_current_shape_tl +\tl_set:Nn \l_@@_current_shape_tl + { \CJK@encoding / \CJK@family / \f@series / \f@shape } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ltj@pickup@altfont@auxy} +% 被用在函数 |output_alt_font_cmd| 中,作用是定义替代字体。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ltj@pickup@altfont@auxy #1 + { + \cs_if_exist:cF { #1/\f@size } + { + \group_begin: + \use:x { \exp_not:N \split@name #1 / \f@size } \@nil + \@@_push_fontname:n { \use:c { \curr@fontshape / \f@size } } + \ctex_ltj_pickup_font: + \group_end: + \@@_pop_fontname: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \begin{macro}[internal]{\ltj@pickup@altfont@copy} +% 被用在函数 |pickup_alt_font_a| 中。\tn{ltj@@getjfontnumber} 的作用是将字体命令 +% |#1| 对应的 \texttt{font.id} 保存到 \tn{ltj@tempcntc} 中。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ltj@pickup@altfont@copy #1#2 + { + \ltj@@getjfontnumber #1 + \ctex_lua_now_x:n + { + luatexja.jfont.pickup_alt_font_b + ( \the\ltj@tempcntc, '\luatexluaescapestring {#2}' ) + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% 以下内容抄录自 \file{lltjfont.sty},目的是让汉字可以在数学环境中直接使用。 +% \begin{macrocode} +\def\ltj@@IsFontJapanese#1{% + \directlua{luatexja.jfont.is_kenc(string.match( + '\luatexluaescapestring{#1}', '[^/]+'))}} +{\catcode`M=12% +\gdef\ltj@@mathJapaneseFonts#1M#2#3\relax{\ltj@@IsFontJapanese{#3}}} +\let\ltj@@al@getanddefine@fonts=\getanddefine@fonts +\def\ltj@@ja@getanddefine@fonts#1#2{% + \xdef\font@name{\csname \string#2/\tf@size\endcsname}% + \pickup@jfont\let\textfont@name\font@name + \xdef\font@name{\csname \string#2/\sf@size\endcsname}% + \pickup@jfont\let\scriptfont@name\font@name + \xdef\font@name{\csname \string#2/\ssf@size\endcsname}% + \pickup@jfont + \edef\math@fonts{\math@fonts\ltj@setpar@global% + \ltj@@set@stackfont#1,\textfont@name:{MJT}% + \ltj@@set@stackfont#1,\scriptfont@name:{MJS}% + \ltj@@set@stackfont#1,\font@name:{MJSS}% + }% +} +\def\getanddefine@fonts#1#2{% + \ltj@tempcnta=#1\ltj@@IsFontJapanese{\string#2}% + \ifin@\let\ltj@temp=\ltj@@ja@getanddefine@fonts% + \else \let\ltj@temp=\ltj@@al@getanddefine@fonts\fi + \ltj@temp{#1}{#2}% +} +\def\use@mathgroup#1#2{\relax\ifmmode + \math@bgroup + \expandafter\ifx\csname M@\f@encoding\endcsname#1\else + #1\fi\ltj@tempcnta=#2 \expandafter\ltj@@mathJapaneseFonts\string#1\relax% + \ifin@\jfam#2\relax\else\mathgroup#2\relax\fi + \expandafter\math@egroup\fi}% +% \end{macrocode} +% +% \begin{macrocode} +\let\@@italiccorr=\/ +% \end{macrocode} +% +% \begin{macrocode} +%<@@=ctex_ltj> +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_mono_jfm:n,\l_@@_jfm_tl} +% \pkg{LuaTeX-ja} 中与标点格式 \opt{plain} 对应的 \texttt{JFM} 是 \opt{mono}。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_mono_jfm:n #1 + { + \str_if_eq:nnTF {#1} { plain } + { \tl_set:Nn \l_@@_jfm_tl { mono } } + { \tl_set:Nn \l_@@_jfm_tl {#1} } + } +\tl_new:N \l_@@_jfm_tl +\cs_generate_variant:Nn \ctex_mono_jfm:n { o } +\ctex_mono_jfm:o { \l__ctex_punct_tl } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\CJK@encoding,\@@_change_encoding:} +% 在 \LaTeX 下,\pkg{LuaTeX-ja} 依赖字体编码来实现特殊设置。例如上述的 +% \tn{ltj@@IsFontJapanese} 就是通过判断编码来实现的,它在设置数学字体时会用到。所以 +% 不应该与西文共用 \texttt{EU2}。定义字体族 song 为 \tn{CJK@encoding} 的默认替换 +% 字体。下划线 |_| 不在 \tn{nfss@catcodes} 里,可以放心使用。 +% \begin{macrocode} +\tl_const:Nn \CJK@encoding { LTJY3 } +\DeclareFontEncoding { \CJK@encoding } { } { } +\DeclareFontSubstitution { LTJY3 } { song } { \mddefault } { \updefault } +\ctex_lua_now_x:n { luatexja.jfont.add_kyenc_list('\CJK@encoding') } +\cs_new_protected_nopar:Npn \@@_change_encoding: + { \tl_set_eq:NN \g_fontspec_encoding_tl \CJK@encoding } +\DeclareFontFamily { \CJK@encoding } { song } { } +\DeclareFontShape { \CJK@encoding } { song } { \mddefault } { \updefault } + { <-> psft:SimSun:cid=Adobe-GB1-5;jfm=\l_@@_jfm_tl } { } +\DeclareFontShape { \CJK@encoding } { song } { \bfdefault } { \updefault } + { <-> psft:SimHei:cid=Adobe-GB1-5;jfm=\l_@@_jfm_tl } { } +\tl_const:Nn \c_@@_math_tl { CJKmath } +\DeclareSymbolFont { \c_@@_math_tl } + { \CJK@encoding } { song } { \mddefault } { \updefault } +\SetSymbolFont { \c_@@_math_tl } { bold } + { \CJK@encoding } { song } { \bfdefault } { \updefault } +\int_const:Nn \c_@@_math_fam_int { \use:c { sym \c_@@_math_tl } } +\jfam \c_@@_math_fam_int +% \end{macrocode} +% \end{macro} +% +% \paragraph{字体族的定义与使用} +% +% 这是 \pkg{luatexja-fontspec} 中新增的一些字体选项。 +% \begin{macrocode} +\newfontfeature { CID } { cid = #1 } +\newfontfeature { JFM } { jfm = #1 } +\newfontfeature { JFM-var } { jfmvar = #1 } +% \end{macrocode} +% +% 在新版本的 \pkg{fontspec} 中,\cs{__fontspec_namewrap:n} 变成了私有函数。 +% \begin{macrocode} +\keys_define:nn { fontspec-preparse-external } + { + NoEmbed .code:n = + { \cs_set_eq:NN \__fontspec_namewrap:n \@@_noembed_wrap:n } + } +\cs_new:Npn \@@_noembed_wrap:n #1 { psft: #1 } +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_ltj_set_family:nnn} +% 将自定义的字体族名与 \pkg{fontspec} 实际设置的名字对应起来。 +% \begin{macrocode} +\cs_new_protected:Npn \ctex_ltj_set_family:nnn #1#2#3 + { + \group_begin: + \clist_clear:N \l_@@_char_range_clist + \seq_clear:N \l_@@_alternate_seq + \tl_set:Nn \l_@@_base_CJKfamily_tl {#1} + \keys_set_known:nnN { ctex_ltj / fontspec } {#2} \l_@@_tmp_tl + \clist_set:No \l_@@_font_options_clist { \l_@@_tmp_tl } + \ctex_ltj_set_alternate_family:nnF {#1} {#3} + { + \prop_gput:Nnn \g_@@_family_font_name_prop {#1} {#3} + \prop_gput:Nno \g_@@_family_font_options_prop + {#1} { \l_@@_font_options_clist } + \@@_update_family_uid:N \l_@@_font_options_clist + \@@_use_global_options:N \l_@@_font_options_clist + \@@_gset_family_cs:nn {#1} {#3} + } + \group_end: + } +\cs_new_protected:Npn \ctex_ltj_set_family:xxx #1#2#3 + { \use:x { \ctex_ltj_set_family:nnn {#1} {#2} {#3} } } +\tl_new:N \l_@@_base_CJKfamily_tl +\clist_new:N \l_@@_font_options_clist +\cs_new_protected_nopar:Npn \@@_use_global_options:N #1 + { + \clist_concat:NNN #1 \g_@@_default_features_clist #1 + \clist_put_left:Nx #1 { JFM = \l_@@_jfm_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}[internal] +% {\g_@@_family_name_prop,\g_@@_family_font_name_prop,\g_@@_family_font_options_prop} +% 分别保存 \pkg{fontspec} 设置的字体族名、字体名称和字体选项。 +% \begin{macrocode} +\prop_new:N \g_@@_family_name_prop +\prop_new:N \g_@@_family_font_name_prop +\prop_new:N \g_@@_family_font_options_prop +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[internal]{\@@_check_family:n} +% 删除重复的定义,清除替代字体的先前设置。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_check_family:n #1 + { + \prop_gpop:NnNT \g_@@_family_font_name_prop {#1} \l_@@_tmp_tl + { + \cs_undefine:c { \@@_family_csname:n {#1} } + \cs_undefine:c { \@@_alternate_cs:n {#1} } + \prop_gpop:NnNT \g_@@_family_name_prop {#1} \l_@@_base_family_tl + { + \use:c { \@@_alternate_cs:n { clear / #1 } } + \cs_undefine:c { \@@_alternate_cs:n { clear / #1 } } + \cs_undefine:c { \@@_alternate_cs:n { reset / #1 } } + \prop_gremove:Nn \g_@@_reset_alternate_prop {#1} + } + \msg_warning:nnxx { ctex } { redefine-family } {#1} { \l_@@_tmp_tl } + } + } +\tl_new:N \l_@@_tmp_tl +\msg_new:nnn { ctex } { redefine-family } + { Redefining~CJKfamily~`\@@_msg_family_map:n {#1}'~(#2). } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_gset_family_cs:nn} +% 在设置字体时,实际上并不是马上就定义。而是只保存相关参数,在通过 \tn{CJKfamily} +% 第一次使用时才定义。需要注意将编码改为 \tn{CJK@encoding}。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_gset_family_cs:nn #1#2 + { + \cs_gset_protected_nopar:cpx { \@@_family_csname:n {#1} } + { + \group_begin: + \@@_change_encoding: + \exp_not:n { \cs_set_eq:NN \CJKfamily \use_none:n } + \exp_not:n { \fontspec_set_family:Nnn \g_@@_fontspec_family_tl } + { \exp_not:o { \l_@@_font_options_clist } } {#2} + \prop_gput:Nno \exp_not:N \g_@@_family_name_prop {#1} + { \exp_not:N \g_@@_fontspec_family_tl } + \tl_gset_eq:NN \exp_not:N \g_@@_fontspec_family_tl + \exp_not:N \g_@@_fontspec_family_tl + \@@_set_alternate_family:n {#1} + \group_end: + } + } +\tl_new:N \l_@@_base_family_tl +\tl_new:N \g_@@_fontspec_family_tl +\cs_new_nopar:Npn \@@_family_csname:n #1 { ctex_ltj/family/#1 } +\cs_new_protected_nopar:Npn \@@_set_alternate_family:n #1 + { + \tl_set:Nn \l_@@_base_CJKfamily_tl {#1} + \tl_set_eq:NN \l_@@_base_family_tl \g_@@_fontspec_family_tl + \cs_if_exist_use:c { \@@_alternate_cs:n { reset / #1 } } + \cs_if_exist_use:c { \@@_alternate_cs:n {#1} } + } +\cs_new:Npn \@@_alternate_cs:n #1 { ctex_ltj/alternate_family/#1 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\CJKfamily} +% 切换字体。 +% \begin{macrocode} +\NewDocumentCommand \CJKfamily { m } + { \ctex_ltj_switch_family:x {#1} \tex_ignorespaces:D } +\cs_new_protected_nopar:Npn \ctex_ltj_switch_family:n #1 + { + \ctex_ltj_family_if_exist:xNTF {#1} \CJK@family + { + \tl_set:Nn \l_ctex_ltj_family_tl {#1} + \selectfont + } + { \@@_family_unknown_warning:n {#1} } + } +\tl_new:N \l_ctex_ltj_family_tl +\cs_generate_variant:Nn \ctex_ltj_switch_family:n { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal,TF]{\ctex_ltj_family_if_exist:n} +% 判断 CJK 字体族 |#1| 是否存在,若存在则把实际族名保存到 |#2| 中。 +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \ctex_ltj_family_if_exist:xN #1#2 { T , F , TF } + { + \prop_get:NxNTF \g_@@_family_name_prop {#1} #2 + { \prg_return_true: } + { + \cs_if_exist_use:cTF { \@@_family_csname:n {#1} } + { + \tl_set_eq:NN #2 \g_@@_fontspec_family_tl + \prg_return_true: + } + { \prg_return_false: } + } + } +\cs_generate_variant:Nn \prop_get:NnNTF { Nx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_family_unknown_warning:n} +% \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} + \msg_warning:nnn { ctex } { family-unknown } {#1} + } + } + } +\seq_new:N \g_@@_unknown_family_seq +\msg_new:nnn { ctex } { family-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:nnF {#1} + { + \CJKrmdefault { \token_to_str:N \setCJKmainfont } + \CJKsfdefault { \token_to_str:N \setCJKsansfont } + \CJKttdefault { \token_to_str:N \setCJKmonofont } + } + { \token_to_str:N \setCJKfamilyfont \{ #1 \} } + [...]\{...\} + } +\cs_new_nopar:Npn \@@_msg_family_map:n #1 + { + \str_case_x:nnF {#1} + { + \CJKrmdefault { \token_to_str:N \CJKrmdefault } + \CJKsfdefault { \token_to_str:N \CJKsfdefault } + \CJKttdefault { \token_to_str:N \CJKttdefault } + } + {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_fontspec:nn} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_fontspec:nn #1#2 + { + \prop_get:NnNTF \g_@@_fontspec_prop + { CJKfontspec/#1/#2/id } \l_ctex_ltj_family_tl + { \ctex_ltj_switch_family:x { \l_ctex_ltj_family_tl } } + { + \int_gincr:N \g_@@_family_int + \@@_fontspec:xnn + { CJKfontspec ( \int_use:N \g_@@_family_int ) } + {#1} {#2} + } + } +\cs_new_protected_nopar:Npn \ctex_ltj_fontspec:xx #1#2 + { \use:x { \ctex_ltj_fontspec:nn {#1} {#2} } } +\cs_new_protected_nopar:Npn \@@_fontspec:nnn #1#2#3 + { + \bool_if:NT \l_@@_add_alternate_bool + { + \cs_if_free:cF + { \@@_alternate_cs:n { reset / \l_ctex_ltj_family_tl } } + { + \cs_gset_eq:cc + { \@@_alternate_cs:n { reset / #1 } } + { \@@_alternate_cs:n { reset / \l_ctex_ltj_family_tl } } + \cs_gset_eq:cc + { \@@_alternate_cs:n { clear / #1 } } + { \@@_alternate_cs:n { clear / \l_ctex_ltj_family_tl } } + } + \bool_set_false:N \l_@@_add_alternate_bool + } + \prop_gput:Nnn \g_@@_fontspec_prop { CJKfontspec/#2/#3/id } {#1} + \ctex_ltj_set_family:nnn {#1} {#2} {#3} + \ctex_ltj_switch_family:n {#1} + } +\cs_generate_variant:Nn \@@_fontspec:nnn { x } +\prop_new:N \g_@@_fontspec_prop +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\ctex_ltj_add_font_features:n,\ctex_ltj_add_font_features:nn} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_add_font_features:n #1 + { \ctex_ltj_add_font_features:xn { \l_ctex_ltj_family_tl } {#1} } +\cs_new_protected_nopar:Npn \ctex_ltj_add_font_features:nn #1#2 + { + \prop_get:NnNTF \g_@@_family_font_name_prop + {#1} \l_@@_tmp_tl + { + \prop_get:NnN \g_@@_family_font_options_prop + {#1} \l_@@_font_options_clist + \clist_put_right:Nn \l_@@_font_options_clist {#2} + \bool_set_true:N \l_@@_add_alternate_bool + \ctex_ltj_fontspec:xx + { \exp_not:o { \l_@@_font_options_clist } } + { \exp_not:o { \l_@@_tmp_tl } } + } + { \msg_warning:nn { ctex } { addCJKfontfeature-ignored } } + } +\bool_new:N \l_@@_add_alternate_bool +\cs_generate_variant:Nn \ctex_ltj_add_font_features:n { x } +\cs_generate_variant:Nn \ctex_ltj_add_font_features:nn { x } +\msg_new:nnn { ctex } { addCJKfontfeature-ignored } + { + \token_to_str:N \addCJKfontfeature (s)~ignored.\\ + It~cannot~be~used~with~a~font~that~wasn't~selected~by~ctex. + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\setCJKfamilyfont,\newCJKfontfamily,\CJKfontspec,\addCJKfontfeatures} +% \begin{macrocode} +\NewDocumentCommand \setCJKfamilyfont { m O { } m } + { \ctex_ltj_set_family:xxx {#1} {#2} {#3} } +\NewDocumentCommand \newCJKfontfamily { o m O { } m } + { + \tl_set:Nx \l_@@_tmp_tl + { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } + \cs_new_protected_nopar:Npx #2 + { \ctex_ltj_switch_family:n { \l_@@_tmp_tl } } + \ctex_ltj_set_family:xxx { \l_@@_tmp_tl } {#3} {#4} + } +\NewDocumentCommand \CJKfontspec { O { } m } + { + \ctex_ltj_fontspec:xx {#1} {#2} + \tex_ignorespaces:D + } +\NewDocumentCommand \addCJKfontfeatures { m } + { + \ctex_ltj_add_font_features:x {#1} + \tex_ignorespaces:D + } +\cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\setCJKmainfont,\setCJKsansfont,\setCJKmonofont, +% \setCJKmathfont,\defaultCJKfontfeatures} +% \begin{macrocode} +\NewDocumentCommand \setCJKmainfont { O { } m } + { + \ctex_ltj_set_family:xxx { \CJKrmdefault } {#1} {#2} + \normalfont + } +\cs_new_eq:NN \setCJKromanfont \setCJKmainfont +\NewDocumentCommand \setCJKsansfont { O { } m } + { + \ctex_ltj_set_family:xxx { \CJKsfdefault } {#1} {#2} + \normalfont + } +\NewDocumentCommand \setCJKmonofont { O { } m } + { + \ctex_ltj_set_family:xxx { \CJKttdefault } {#1} {#2} + \normalfont + } +\NewDocumentCommand \setCJKmathfont { O { } m } + { \ctex_ltj_set_family:xxx { \c_@@_math_tl } {#1} {#2} } +\NewDocumentCommand \defaultCJKfontfeatures { m } + { \clist_gset:Nn \g_@@_default_features_clist {#1} } +\clist_new:N \g_@@_default_features_clist +\@onlypreamble \setCJKmainfont +\@onlypreamble \setCJKsansfont +\@onlypreamble \setCJKmonofont +\@onlypreamble \setCJKmathfont +\@onlypreamble \setCJKromanfont +\@onlypreamble \defaultCJKfontfeatures +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\tl_if_exist:NF \CJKfamilydefault + { \tl_const:Nn \CJKfamilydefault { \CJKrmdefault } } +\tl_if_exist:NF \CJKrmdefault { \tl_const:Nn \CJKrmdefault { rm } } +\tl_if_exist:NF \CJKsfdefault { \tl_const:Nn \CJKsfdefault { sf } } +\tl_if_exist:NF \CJKttdefault { \tl_const:Nn \CJKttdefault { tt } } +\ctex_preto_cmd:NnTF \rmfamily { \CJKfamily { \CJKrmdefault } } { } + { \ctex_patch_failure:N \rmfamily } +\ctex_preto_cmd:NnTF \sffamily { \CJKfamily { \CJKsfdefault } } { } + { \ctex_patch_failure:N \sffamily } +\ctex_preto_cmd:NnTF \ttfamily { \CJKfamily { \CJKttdefault } } { } + { \ctex_patch_failure:N \ttfamily } +\ctex_preto_cmd:NnTF \normalfont { \CJKfamily { \CJKfamilydefault } } + { \cs_set_eq:NN \reset@font \normalfont } + { \ctex_patch_failure:N \normalfont } +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_ltj_ensure_default_family:} +% 在导言区结束确认 \tn{CJKfamilydefault} 确实存在。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_ensure_default_family: + { + \prop_if_empty:NF \g_@@_family_font_name_prop + { + \ctex_ltj_family_if_exist:xNF { \CJKfamilydefault } \l_@@_tmpa_tl + { + \str_if_eq_x:nnTF { \CJKfamilydefault } { \CJKrmdefault } + { \use:n } + { + \ctex_ltj_family_if_exist:xNTF { \CJKrmdefault } \l_@@_tmpa_tl + { \tl_gset:Nn \CJKfamilydefault { \CJKrmdefault } \use_none:n } + { \use:n } + } + { + \prop_map_inline:Nn \g_@@_family_font_name_prop + { + \prop_map_break:n + { \tl_gset_rescan:Nnn \CJKfamilydefault { } { ##1 } } + } + } + } + \normalfont + \ctex_ltj_update_mathfont: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_update_mathfont:} +% 更新数学字体为实际的字体。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_update_mathfont: + { + \ctex_ltj_family_if_exist:xNTF { \c_@@_math_tl } \l_@@_tmp_tl + { \ctex_ltj_update_mathfont:n { \l_@@_tmp_tl } } + { + \ctex_ltj_family_if_exist:xNT { \CJKfamilydefault } \l_@@_tmp_tl + { \ctex_ltj_update_mathfont:n { \l_@@_tmp_tl } } + } + } +\cs_new_protected_nopar:Npn \ctex_ltj_update_mathfont:n #1 + { + \tl_const:Nx \c_@@_math_family_tl {#1} + \DeclareSymbolFont { \c_@@_math_tl } { \CJK@encoding } + { \c_@@_math_family_tl } { \mddefault } { \updefault } + \cs_if_free:cTF + { \CJK@encoding/\c_@@_math_family_tl/\bfdefault/\updefault } + { + \SetSymbolFont { \c_@@_math_tl } { bold } { \CJK@encoding } + { \c_@@_math_family_tl } { \mddefault } { \updefault } + } + { + \SetSymbolFont { \c_@@_math_tl } { bold } { \CJK@encoding } + { \c_@@_math_family_tl } { \bfdefault } { \updefault } + } + } +% \end{macrocode} +% \end{macro} +% +% \paragraph{替代字体的设置} +% +% \begin{macro}{AlternateFont,CharRange} +% 设置替代字体的选项。 +% \begin{macrocode} +\keys_define:nn { ctex_ltj / fontspec } + { + AlternateFont .code:n = \ctex_ltj_set_alternate_seq:n {#1} , + AlternateFont .value_required: , + CharRange .clist_set:N = \l_@@_char_range_clist , + CharRange .value_required: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_seq:n} +% 我们使用 \verb=||= 作为替代字体序列的分隔标志。它可能被设置为活动字符,为此 +% 需要先“消毒”,同时过滤掉空元素。 +% \begin{macrocode} +\group_begin: +\char_set_catcode_active:N \/ +\char_set_lccode:nn { `\/ } { `\| } +\tex_lowercase:D + { + \group_end: + \cs_new_protected:Npn \ctex_ltj_set_alternate_seq:n #1 + { + \clist_if_empty:NT \l_@@_char_range_clist + { + \tl_set:Nn \l_@@_tmp_tl {#1} + \tl_replace_all:Nnn \l_@@_tmp_tl { // } { || } + \seq_set_split:NnV \l_@@_tmp_seq { || } \l_@@_tmp_tl + \seq_set_filter:NNn \l_@@_tmp_seq \l_@@_tmp_seq + { ! \tl_if_blank_p:n { ##1 } } + \seq_concat:NNN \l_@@_alternate_seq + \l_@@_alternate_seq \l_@@_tmp_seq + } + } + } +\seq_new:N \l_@@_tmp_seq +\seq_new:N \l_@@_alternate_seq +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_family:nnF} +% 如果在字体的选项中设置了 \opt{CharRange},则只设置替代字体。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:nnF #1#2#3 + { + \clist_if_empty:NTF \l_@@_char_range_clist + { + \@@_check_family:n {#1} + \seq_if_empty:NF \l_@@_alternate_seq + { \ctex_ltj_save_alternate_seq:cn { \@@_alternate_cs:n {#1} } {#2} } + #3 + } + { \ctex_ltj_set_alternate_family:nn {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\ctex_ltj_save_alternate_seq:Nn,\ctex_ltj_save_alternate_seq:Nnnwn} +% 保存由 \opt{AlternateFont} 设置的替代字体序列。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_save_alternate_seq:Nn #1#2 + { + \seq_map_inline:Nn \l_@@_alternate_seq + { \ctex_ltj_save_alternate_seq:Nnnwnw #1 {#2} ##1 { } \q_stop } + } +\cs_generate_variant:Nn \ctex_ltj_save_alternate_seq:Nn { c } +\NewDocumentCommand \ctex_ltj_save_alternate_seq:Nnnwnw + { m m m +O{ } m u{ \q_stop } } + { + \clist_set:Nn \l_@@_char_range_clist {#3} + \clist_set:Nn \l_@@_alternate_options_clist {#4} + \@@_use_global_options:N \l_@@_alternate_options_clist + \tl_if_blank:nTF {#5} + { \tl_set:Nn \l_@@_tmp_tl {#2} } + { + \tl_set:Nn \l_@@_tmp_tl {#5} + \tl_replace_all:Nnn \l_@@_tmp_tl { * } {#2} + } + \use:x + { + \ctex_ltj_save_alternate_family:Nnnn \exp_not:N #1 + { \exp_not:o { \l_@@_char_range_clist } } + { \exp_not:o { \l_@@_alternate_options_clist } } + { \exp_not:o { \l_@@_tmp_tl } } + } + } +\clist_new:N \l_@@_alternate_options_clist +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_family:nn} +% 设置选项 \opt{CharRange} 范围内的替代字体。如果已经定义了主字体,我们也马上 +% 定义替代字体,否则只保存起来备用。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:nn #1#2 + { + \@@_update_family_uid:N \l_@@_font_options_clist + \@@_use_global_options:N \l_@@_font_options_clist + \ctex_ltj_set_alternate_family:coonn + { \@@_alternate_cs:n {#1} } + { \l_@@_char_range_clist } + { \l_@@_font_options_clist } {#2} {#1} + } +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:Nnnnn #1#2#3#4#5 + { + \prop_get:NnNT \g_@@_family_name_prop {#5} \l_@@_base_family_tl + { \ctex_ltj_set_alternate_family:nnn {#2} {#3} {#4} } + \ctex_ltj_save_alternate_family:Nnnn #1 {#2} {#3} {#4} + } +\cs_generate_variant:Nn \ctex_ltj_set_alternate_family:Nnnnn { coo } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_save_alternate_family:Nnnn} +% 保存替代字体序列的定义,以备定义主字体时使用。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_save_alternate_family:Nnnn #1#2#3#4 + { + \cs_if_exist:NF #1 { \cs_set_eq:NN #1 \prg_do_nothing: } + \cs_gset_protected_nopar:Npx #1 + { \exp_not:o { #1 \ctex_ltj_set_alternate_family:nnn {#2} {#3} {#4} } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_family:nnn} +% 实际定义替代字体族。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:nnn #1#2#3 + { + \group_begin: + \@@_change_encoding: + \cs_set_eq:NN \CJKfamily \use_none:n + \ctex_ltj_swap_cs:NN + \DeclareFontShape@ \ctex_ltj_declare_alternate_shape:nnnnnn + \tl_set:Nn \l_@@_char_range_clist {#1} + \fontspec_set_family:Nnn \l_@@_alternate_family_tl {#2} {#3} + \group_end: + } +\tl_new:N \l_@@_alternate_family_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_swap_cs:NN} +% 交换两个控制序列的意义。 +% \begin{macrocode} +\cs_new_protected:Npn \ctex_ltj_swap_cs:NN #1#2 + { + \cs_set_eq:NN \@@_tmp:w #1 + \cs_set_eq:NN #1 #2 + \cs_set_eq:NN #2 \@@_tmp:w + \cs_undefine:N \@@_tmp:w + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{LTJFONTUID,\@@_update_family_uid:N} +% \pkg{fontspec} 在一个字体族的选项和字体名称相同的时候,就不定义新字体。为了 +% 避免混淆替代字体的设置,我们新定义一个虚拟的选项 \opt{LTJFONTUID},确保 +% \pkg{fontspec} 对 CJK 字体族总是定义新字体。 +% \begin{macrocode} +\keys_define:nn { fontspec } { LTJFONTUID .code:n = } +\cs_new_protected_nopar:Npn \@@_update_family_uid:N #1 + { + \int_gincr:N \g_@@_family_int + \clist_put_right:Nx #1 { LTJFONTUID = \int_use:N \g_@@_family_int } + } +\int_new:N \g_@@_family_int +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_declare_alternate_shape:nnnnnn} +% 在定义替代字体的字形时,通过字符范围与主字体的对应字形关联起来。 +% \tn{DeclareFontShape@} 一个有六个参数,我们只需要使用它的第三个参数 \meta{series} +% 和第四个参数 \meta{shape}。 +% \begin{macrocode} +\cs_new_protected:Npn \ctex_ltj_declare_alternate_shape:nnnnnn #1#2#3#4#5#6 + { + \ctex_ltj_declare_alternate_shape:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} + \ctex_ltj_set_alternate_shape:Nnnnnnn \l_@@_char_range_clist + { \l_@@_base_family_tl } {#3} {#4} + { \l_fontspec_family_tl } {#3} {#4} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_shape:Nnnnnnn} +% 与 \pkg{LuaTeX-ja} 的 \tn{DeclareAlternateKanjiFont} 的功能类似,区别是固定编码 +% 为 \tn{CJK@encoding}。这个设置总是全局的。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:Nnnnnnn #1#2#3#4#5#6#7 + { + \clist_map_inline:Nn #1 + { + \prop_get:NnNTF \g_@@_char_range_prop { ##1 } \l_@@_char_range_tl + { + \ctex_ltj_set_alternate_shape:nnN { #2/#3/#4 } { #5/#6/#7 } + \l_@@_char_range_tl + } + { \ctex_ltj_set_alternate_shape:nnn { #2/#3/#4 } { #5/#6/#7 } { ##1 } } + } + \@@_save_alternate_shape:cnn + { \@@_alternate_cs:n { clear / \l_@@_base_CJKfamily_tl } } + { luatexja.jfont.clear_alt_font_latex } + { '\luatexluaescapestring { \CJK@encoding/#2/#3/#4 }' } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_shape:nnn} +% 我们使用 \texttt{->} 而不是像 \pkg{LuaTeX-ja} 一样使用 \texttt{-} 作为区间的 +% 分隔符。\pkg{LuaTeX-ja} 支持使用负数来引用由 \texttt{JFM} 设置的字符类。如果 +% 使用 \texttt{-} 作为分隔符,那么负数单独使用时,就需要把它放在两层花括号之内 +% (例如 |{{-1}}|),或者使用类似 |{-1}-{-1}| 的形式才不会解释错误。 +% \begin{macrocode} +\NewDocumentCommand \ctex_ltj_set_alternate_shape:nnn + { m m > { \SplitArgument { \c_one } { -> } } m } + { \ctex_ltj_set_alternate_shape:nnnn {#1} {#2} #3 } +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:nnnn #1#2#3#4 + { + \ctex_ltj_set_alternate_shape:n + { + \IfNoValueTF {#4} + { \int_eval:n {#3} , \int_eval:n {#3} , } + { + \int_eval:n { \tl_if_blank:nTF {#3} { "80 } {#3} } , + \int_eval:n { \tl_if_blank:nTF {#4} { "10FFFF } {#4} } , + } + '\luatexluaescapestring { \CJK@encoding/#2 }' , + '\luatexluaescapestring { \CJK@encoding/#1 }' + } + } +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:n #1 + { + \ctex_lua_now_x:n { luatexja.jfont.set_alt_font_latex ( #1 ) } + \@@_save_alternate_shape:cnn + { \@@_alternate_cs:n { reset / \l_@@_base_CJKfamily_tl } } + { luatexja.jfont.set_alt_font_latex } {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_set_alternate_shape:nnN} +% 若字符范围预先由 \texttt{declarecharrange} 声明,则可以直接使用。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:nnN #1#2#3 + { + \tl_map_inline:Nn #3 + { + \ctex_ltj_set_alternate_shape:n + { + ##1 , + '\luatexluaescapestring { \CJK@encoding/#2 }' , + '\luatexluaescapestring { \CJK@encoding/#1 }' + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_save_alternate_shape:Nnn} +% 将实际设置的替换字形保存起来用于清除或恢复。 +% 暂时令 \cs{l_@@_base_family_tl} 为 \cs{scan_stop:} 是让它不被展开,使得替换 +% 字体的设置可以在 \tn{addCJKfontfeature} 中直接使用。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_save_alternate_shape:Nnn #1#2#3 + { + \group_begin: + \cs_if_exist:NF #1 { \cs_set_eq:NN #1 \prg_do_nothing: } + \cs_set_eq:NN \l_@@_base_family_tl \scan_stop: + \cs_set_eq:NN \luatexluaescapestring \scan_stop: + \cs_gset_protected_nopar:Npx #1 + { \exp_not:o {#1} \exp_not:N \ctex_lua_now_x:n { #2 ( #3 ) } } + \group_end: + } +\cs_generate_variant:Nn \@@_save_alternate_shape:Nnn { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{clearalternatefont,resetalternatefont} +% 清除和重置操作总是全局的。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + clearalternatefont .code:n = + { \clist_map_function:xN {#1} \ctex_ltj_clear_alternate_font:n } , + resetalternatefont .code:n = + { \clist_map_function:xN {#1} \ctex_ltj_reset_alternate_font:n } , + clearalternatefont .default:n = \l_ctex_ltj_family_tl , + resetalternatefont .default:n = \l_ctex_ltj_family_tl + } +\cs_new_protected_nopar:Npn \ctex_ltj_clear_alternate_font:n #1 + { + \group_begin: + \ctex_ltj_family_if_exist:xNTF {#1} \l_@@_base_family_tl + { + \cs_if_exist_use:cT { \@@_alternate_cs:n { clear / #1 } } + { + \prop_gput:Nno \g_@@_reset_alternate_prop + {#1} { \l_@@_base_family_tl } + \tl_set_eq:NN \CJK@family \l_@@_base_family_tl + \selectfont + } + } + { \@@_family_unknown_warning:n {#1} } + \group_end: + } +\cs_new_protected_nopar:Npn \ctex_ltj_reset_alternate_font:n #1 + { + \group_begin: + \prop_gpop:NnNT \g_@@_reset_alternate_prop {#1} \CJK@family + { + \tl_set_eq:NN \l_@@_base_family_tl \CJK@family + \use:c { \@@_alternate_cs:n { reset / #1 } } + \selectfont + } + \group_end: + } +\prop_new:N \g_@@_reset_alternate_prop +\cs_generate_variant:Nn \clist_map_function:nN { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{declarecharrange} +% 预先声明字符范围。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + declarecharrange .code:n = \ctex_ltj_declare_char_range:x {#1} , + declarecharrange .value_required: + } +\cs_new_protected_nopar:Npn \ctex_ltj_declare_char_range:n #1 + { \clist_map_inline:nn {#1} { \@@_declare_char_range:nn ##1 } } +\cs_generate_variant:Nn \ctex_ltj_declare_char_range:n { x } +\cs_new_protected_nopar:Npn \@@_declare_char_range:nn #1#2 + { \use:x { \ctex_ltj_declare_char_range:nn { \tl_trim_spaces:n {#1} } } {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_declare_char_range:nn,\g_@@_char_range_prop} +% |#1| 是名字,|#2| 是范围。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_declare_char_range:nn #1#2 + { + \tl_clear:N \l_@@_char_range_tl + \clist_map_function:nN {#2} \ctex_ltj_save_char_range:n + \prop_gput:Nno \g_@@_char_range_prop {#1} { \l_@@_char_range_tl } + \ctex_ltj_def_char_range_key:n {#1} + \tl_clear:N \l_@@_char_range_tl + } +\tl_new:N \l_@@_char_range_tl +\prop_new:N \g_@@_char_range_prop +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_save_char_range:n} +% 预先解释字符区间的意义。 +% \begin{macrocode} +\NewDocumentCommand \ctex_ltj_save_char_range:n + { > { \SplitArgument { \c_one } { -> } } m } + { \ctex_ltj_save_char_range:nn #1 } +\cs_new_protected_nopar:Npn \ctex_ltj_save_char_range:nn #1#2 + { + \tl_put_right:Nx \l_@@_char_range_tl + { { + \IfNoValueTF {#2} + { \int_eval:n {#1} , \int_eval:n {#1} } + { + \int_eval:n { \tl_if_blank:nTF {#1} { "80 } {#1} } , + \int_eval:n { \tl_if_blank:nTF {#2} { "10FFFF } {#2} } + } + } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_def_char_range_key:n} +% 在字体设置选项中定义字符范围键。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_def_char_range_key:n #1 + { + \keys_if_exist:nnF { ctex_ltj / fontspec } {#1} + { + \keys_define:nn { ctex_ltj / fontspec } + { #1 .code:n = \ctex_ltj_char_range_key:nn {#1} { ##1 } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_ltj_char_range_key:nn} +% 如果字符范围键没有值,则只设置的这个字符范围内的替代字体。 +% \begin{macrocode} +\cs_new_protected:Npn \ctex_ltj_char_range_key:nn #1#2 + { + \tl_if_blank:nTF {#2} + { \tl_set:Nn \l_@@_char_range_clist {#1} } + { + \clist_if_empty:NT \l_@@_char_range_clist + { + \tl_set:Nn \l_@@_tmp_tl { {#1} } + \@@_char_range_parse_feature:w #2 \q_stop + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_char_range_parse_feature:w} +% 可以使用加方括号的方式,通过文件名来调用字体。这容易与字体选项混淆。例如,需要 +% 将 |[simsun.ttc]| 设置为 \opt{range} 的主字体,就需要使用 +% |range={{[simsun.ttc]}}| 或者 |[]{[simsun.ttc]}|。下面的目的是,支持直接使用 +% |[simsun.ttc]| 和 |[...][simsun.ttc]|。 +% \begin{macrocode} +\NewDocumentCommand \@@_char_range_parse_feature:w + { +o o u { \q_stop } } + { + \exp_args:NNf \tl_put_right:Nn \l_@@_tmp_tl + { + \IfNoValueTF {#1} { {#3} } + { + \IfNoValueTF {#2} + { \tl_if_blank:nTF {#3} { { [#1] } } { [ {#1} ] {#3} } } + { [ {#1} ] { [#2] } } + } + } + \seq_put_right:No \l_@@_alternate_seq { \l_@@_tmp_tl } + } +% \end{macrocode} +% \end{macro} +% +% \paragraph{其它设置} +% +% \begin{macro}[internal]{\ctex_ltj_update_xkanjiskip:,\l_@@_xkanjiskip_skip} +% \tn{ltjsetparameter} 对 \opt{xkanjiskip} 是即时赋值。\tn{zw} 与字体相关,因此 +% 需要每次 \tn{selectfont} 的时候更新一次 \opt{xkanjiskip}。如果用户设置过 +% \opt{xkanjiskip},就不更新。注意,同 \TeX{} 的 \tn{baselineskip} 一样,如果在 +% 一个段落内多次设置了 \opt{kanjiskip} 或 \opt{xkanjiskip},最后的设置会影响 +% 全段。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_ltj_update_xkanjiskip: + { + \skip_if_eq:nnT + { \ltjgetparameter { xkanjiskip } } { \l_@@_xkanjiskip_skip } + { + \skip_set:Nn \l_@@_xkanjiskip_skip { .25 \zw plus 1pt minus 1pt } + \ltjsetxkanjiskip \l_@@_xkanjiskip_skip + } + } +% \end{macrocode} +% 注意,此时还没有实际设置字体,所以 \tn{zw} 是 \opt{0pt}。 +% \begin{macrocode} +\skip_new:N \l_@@_xkanjiskip_skip +\skip_set:Nn \l_@@_xkanjiskip_skip { .25 \zw plus 1pt minus 1pt } +% \end{macrocode} +% \end{macro} +% +% 在抄录环境中禁用 \opt{autospacing} 和 \opt{autoxspacing}。然而,\pkg{LuaTeX-ja} +% 还是会使 JAchar 自动折行。没有看到有简单的禁用折行的办法,可能需要设置所有的 +% JAchar 的 \opt{prebreakpenalty} 或 \opt{postbreakpenalty} 为 \texttt{10000}: +% \begin{verbatim} +% \directlua +% { +% luatexja.isglobal = tex.globaldefs > 0 and "global" or "" +% for i = 0x80, 0x10FFFF do +% if luatexja.charrange.jcr_table_main[i] > 0 and +% luatexja.charrange.jcr_table_main[i] < 218 and +% luatexja.charrange.is_japanese_char_curlist(i) then +% luatexja.stack.set_stack_table(luatexja.stack_table_index.PRE + i, 10000) +% end +% end +% } +% \end{verbatim} +% \begin{macrocode} +\AtBeginDocument + { + \ctex_appto_cmd:NnTF \verbatim@font { \CTEX@verbatim@font@hook } + { } { \ctex_patch_failure:N \verbatim@font } + } +\cs_new_protected_nopar:Npn \CTEX@verbatim@font@hook + { \ltjsetparameter { autospacing = false , autoxspacing = false } } +% \end{macrocode} +% +% \begin{macrocode} +%<@@=ctex> +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{调整 \tn{CJKfamilydefault}} +% +% \begin{macro}[internal]{\ctex_update_default_family:} +% 在导言区结束,如果 \tn{CJKfamilydefault} 没有被更改,则在此时根据西文字体的情况 +% 更新 \tn{CJKfamilydefault}。\pkg{xeCJK} 已经有这个功能,不需要再调整。 +% \begin{macrocode} +%<*pdftex|luatex> +\cs_new_protected_nopar:Npn \ctex_update_default_family: + { + \tl_if_eq:NNT \CJKfamilydefault \l_@@_family_default_init_tl + { + \group_begin: + \cs_set_eq:NN \@@_family_default_wrap:n \exp_not:n + \tl_gset:Nx \CJKfamilydefault + { + \str_case:onF { \familydefault } + { + { \rmdefault } { \exp_not:N \CJKrmdefault } + { \sfdefault } { \exp_not:N \CJKsfdefault } + { \ttdefault } { \exp_not:N \CJKttdefault } + } + { \CJKfamilydefault } + } + \group_end: + } +% \end{macrocode} +% 使用 \LuaLaTeX{} 时,自动调整得到的 \tn{CJKfamilydefault} 可能没有定义,需要确认 +% 它的存在性。使用 \pkg{CJK} 宏包时,\texttt{C19rm} 等总是有定义的,不需要确认。 +% \begin{macrocode} +%<*luatex> + \ctex_ltj_ensure_default_family: +% + } +\AtEndPreamble { \ctex_update_default_family: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\l_@@_family_default_init_tl} +% 往 \tn{CJKfamilydefault} 中加入标志,用于判断它是否被更改。 +% \begin{macrocode} +\tl_new:N \l_@@_family_default_init_tl +\cs_new_eq:NN \@@_family_default_wrap:n \use:n +\tl_set:Nx \l_@@_family_default_init_tl + { + \exp_not:N \@@_family_default_wrap:n + { \exp_not:o { \CJKfamilydefault } } + } +\tl_gset_eq:NN \CJKfamilydefault \l_@@_family_default_init_tl +% +% \end{macrocode} +% \end{macro} +% +% \subsubsection{操作系统的判断} +% +% \changes{v2.0}{2014/04/16}{自动检测操作系统,载入对应的字体配置。} +% +% \begin{macro}[internal]{\ctex_detected_platform:} +% 在 \LuaTeX{} 下直接用调用 |os.name| 来判断。 +% \begin{macrocode} +%<*luatex> +\cs_new_protected_nopar:Npn \ctex_detected_platform: + { + \tl_gset:Nx \g_@@_fontset_tl + { + \ctex_lua_now_x:n + { + if ~ os.name == 'windows' then ~ + tex.sprint ( 'windows' ) + elseif ~ os.name == 'macosx' then ~ + tex.sprint ( 'mac' ) + else ~ + tex.sprint ( 'fandol' ) + end + } + } + } +% +% \end{macrocode} +% \pdfTeX{} 和 \XeTeX{} 下则依据 \file{/dev/null} 和 \file{nul:} 的存在性以及 +% 文件系统的大小写敏感性来判断。Mac~OS~X 的大小写敏感性在安装时是可选的。为了 +% 保险起见,这里的判断很繁琐,最多要进行 4 次文件操作! +% \begin{macrocode} +%<*xetex|pdftex> +\cs_new_protected_nopar:Npn \ctex_detected_platform: + { + \file_if_exist:nTF { /dev/null } + { + \file_if_exist:nTF { nul: } + { + \file_if_exist:nTF { \c_@@_engine_file_tl } + { \ctex_if_macosx:TF { mac } { windows } } + { \ctex_if_macosx:TF { mac } { fandol } } + } + { \ctex_if_macosx:TF { mac } { fandol } } + } + { \tl_gset:Nn \g_@@_fontset_tl { windows } } + } +\tex_uppercase:D \exp_after:wN + { + \exp_after:wN \tl_const:Nn \exp_after:wN \c_@@_engine_file_tl + \exp_after:wN { \g_file_current_name_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_if_macosx:TF} +% 以 \file{/mach_kernel} 为特征文件判断 Mac~OS~X。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_if_macosx:TF #1#2 + { + \file_if_exist:nTF { \c_@@_macosx_file_tl } + { \tl_gset:Nn \g_@@_fontset_tl {#1} } + { \tl_gset:Nn \g_@@_fontset_tl {#2} } + } +\tl_const:Nn \c_@@_macosx_file_tl { /mach_kernel } +% +% \end{macrocode} +% \end{macro} +% +% \subsubsection{\pkg{hyperref} 兼容性处理} +% +% 现在处理各个引擎下的 PDF 中文书签问题。根据编译引擎与文件编码的不 +% 同,\pkg{ctex} 向 \pkg{hyperref} 传递适当的参数,完成中文书签的正确设置。用 +% 户仍需要自己载入 \pkg{hyperref} 宏包。 +% +% \begin{macro}[internal]{\ctex_hypersetup:n} +% 如果已经载入 \pkg{hyperref} 宏包,则直接使用其定义设置选项;否则 +% \cs{ctex_hypersetup:n} 的效果与 \tn{PassOptionsToPackage} 一致,只传递宏包参 +% 数。如果用户不载入 \pkg{hyperref} 宏包,相关参数即被丢弃。 +% \begin{macrocode} +%<*class|style> +\@ifpackageloaded { hyperref } + { + \cs_new_protected_nopar:Npn \ctex_hypersetup:n #1 + { \hypersetup {#1} } + } + { + \cs_new_protected_nopar:Npn \ctex_hypersetup:n #1 + { \PassOptionsToPackage {#1} { hyperref } } + } +\ctex_hypersetup:n { colorlinks = true } +% +% \end{macrocode} +% \end{macro} +% +% 在 \pdfTeX{} 下使用 \texttt{GBK} 编码,\dvipdfmx{} 驱动可以直接用它的 +% \tn{special} 命令,其它模式用 \pkg{xCJK2uni} 宏包处理。使用 \texttt{UTF-8} 编 +% 码时,\pkg{CJKutf8} 已经处理了书签问题,但仍需要设置 \opt{pdfencoding} 为 +% \opt{unicode},目的是在书签的开头写入 BOM (|\376\377|),提示这是 +% \texttt{UTF-16BE} 字节流。 +% \begin{macrocode} +%<*pdftex> +\ctex_hypersetup:n { driverfallback = dvipdfmx } +\str_if_eq:onTF { \l_@@_encoding_tl } { GBK } + { + \ctex_hypersetup:n { CJKbookmarks = true } + \ctex_if_pdfmode:TF + { \ctex_at_end_package:nn { hyperref } { \RequirePackage { xCJK2uni } } } + { + \ctex_at_end_package:nn { hyperref } + { + \str_if_eq:onTF { \Hy@driver } { hdvipdfm } + { + \AtBeginShipoutFirst + { \special { pdf:tounicode~GBK-EUC-UCS2 } } + } + { \RequirePackage { xCJK2uni } } + } + } + } + { \ctex_hypersetup:n { pdfencoding = unicode } } +% +% \end{macrocode} +% 在 \XeTeX{} 下,\pkg{hyperref} 在处理带有非 ASCII 字符和 |\%| 的书签时有问题^^A +% \footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/39}}。 +% 事实上,\pkg{hyperref} 在驱动文件 \file{hxetex.def} 中设置了 +% \tn{Hy@unicodetrue},从而书签总是会被 \tn{HyPsd@ConvertToUnicode} 转化成 +% \texttt{UTF-16BE} 编码的形式(抄录自 \tn{pdfstringdef}的定义): +% \begin{verbatim} +% \ifHy@unicode +% \HyPsd@ConvertToUnicode#1% +% \ifx\HyPsd@pdfencoding\HyPsd@pdfencoding@auto +% \ltx@IfUndefined{StringEncodingConvertTest}{% +% }{% +% \EdefUnescapeString\HyPsd@temp#1% +% \ifxetex +% \let\HyPsd@UnescapedString\HyPsd@temp +% \StringEncodingConvertTest\HyPsd@temp\HyPsd@temp +% {utf16be}{ascii-print}{% +% \EdefEscapeString\HyPsd@temp\HyPsd@temp +% \global\let#1\HyPsd@temp +% \HyPsd@EscapeTeX#1% +% \Hy@unicodefalse +% }{% +% \HyPsd@ToBigChars#1% +% }% +% \end{verbatim} +% 通过宏包选项 \opt{pdfencoding=unicode} 设置 \tn{HyPsd@pdfencoding} 为 +% \opt{unicode},可以避免随后再将书签从 \texttt{UTF-16BE} 字节流转化回正常 +% 字符(其中使用的 \tn{HyPsd@ToBigChars} 没有考虑书签中含有 |\%| 的情况)。 +% Heiko Oberdiek 在 \file{README} 中说明了将书签转化回正常字符的意图:避免 +% XDVIPDFMX 的警告^^A +% \footnote{\url{http://project.ktug.org/dvipdfmx/mailman/dvipdfmx/2009-December/000153.html}}: +% \begin{verbatim} +% ** WARNING ** Failed to convert input string to UTF16... +% \end{verbatim} +% \XeTeX{} 的维护者 Khaled Hosny 已经注意到了这个问题^^A +% \footnote{\url{http://tug.org/pipermail/tex-live/2013-December/034613.html}}。 +% 需要注意的是,\file{hxetex.def} 重载了宏包选项 \opt{unicode},目的是不能设置 +% 它为 \opt{false},但也导致它不会改变 \tn{HyPsd@pdfencoding}。如果 +% \pkg{hyperref} 先于 \CTeX{} 被载入,那么 \opt{unicode} 选项是没有意义的。 +% 因此要通过意义相同但在 \XeTeX{} 下更保险的 \opt{pdfencoding} 选项来设置。 +% 为了与 \XeTeX 下的行为一致(使用 \tn{HyPsd@LoadUnicode} 载入 \file{puenc.def}), +% 在 \LuaTeX{} 下也启用这个选项。 +% \begin{macrocode} +%<*xetex|luatex> +\ctex_hypersetup:n { pdfencoding = unicode } +% +% \end{macrocode} +% +% \begin{macrocode} +%<*pdftex|xetex|luatex> +% \end{macrocode} +% +% \subsubsection{\pkg{CJKfntef}、\pkg{xeCJKfntef} 相关设置} +% +% \CTeX{} 套件对 \pdfTeX{} 与 \XeTeX{} 引擎,分别载入 \pkg{CJKfntef} 或 +% \pkg{xeCJKfntef} 宏包,并关闭宏包默认的彩色等多余格式。 +% +% \changes{v2.0}{2015/03/25}{默认关闭 \pkg{CJKfntef} 或 \pkg{xeCJKfntef} 的彩 +% 色设置。} +% \changes{v2.0}{2015/03/25}{\tn{CTEXunderdot}, \tn{CTEXunderline}, +% \tn{CTEXunderdblline}, \tn{CTEXunderwave}, \tn{CTEXsout}, \tn{CTEXxout} 是过 +% 时命令;\env{CTEXfilltwosides} 是过时环境。} +% +% 载入 \pkg{CJKfntef} 或 \pkg{xeCJKfntef} 并做适当格式设置。有关 |\CTEX| 开头 +% 的宏定义是过时命令,仅做兼容性保留。 +% +% \begin{macrocode} +%\RequirePackage { CJKfntef } \normalem +%\RequirePackage { xeCJKfntef } +%<*luatex> +\msg_new:nnn { ctex } { fntef-not-available } + { Functions~ of~ `CJKfntef'~ is~ not~ available~ in~ LuaLaTeX. } +\msg_warning:nn { ctex } { fntef-not-available } +% +\clist_map_inline:nn + { underdot , underline , underdblline , underwave , sout , xout } +%<*pdftex|xetex> + { +% \tl_clear:c { CJK#1color } +% \keys_set:nn { xeCJK / options } { #1 / format = { } } + \cs_new_protected_nopar:cpx { CTEX#1 } + { + \msg_warning:nnnn { ctex } { deprecated-command } { \exp_not:c { CTEX#1 } } + { You~ can~ use~ the~ command~ with~ prefix~ \exp_not:N \CJK~ instead. } + \exp_not:c { CJK#1 } + } + } +\cs_new_protected_nopar:Npn { \CTEXfilltwosides } + { + \msg_warning:nnnn { ctex } { deprecated-environment } { CTEXfilltwosides } + { You~ can~ use~ `CJKfilltwosides'~ environment~ instead. } + \CJKfilltwosides + } +\cs_new_protected_nopar:Npn { \endCTEXfilltwosides } { \endCJKfilltwosides } +% +%<*luatex> + { \cs_new_eq:cN { CTEX#1 } \use:n } +\cs_new_eq:NN \CTEXfilltwosides \use_none:n +\cs_new_eq:NN \endCTEXfilltwosides \prg_do_nothing: +% +%<*pdftex> +\clist_map_inline:nn + { + underdotbasesep , underdotsep , underlinebasesep , + underlinesep , underdbllinesep , underdbllinebasesep , + underwavebasesep , underwavesep , southeight , + underdotcolor , underwavecolor , underlinecolor , + underdbllinecolor , soutcolor , xoutcolor + } + { + \cs_new_eq:cc { CTEX#1 } { CJK#1 } + \cs_set_nopar:cpx { CJK#1 } { \exp_not:c { CTEX#1 } } + } +% +% \end{macrocode} +% +% \subsubsection{\tn{ccwd} 的更新} +% +% \begin{macro}[internal]{\ctex_update_ccwd:,\ccwd} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_ccwd: +%<*pdftex|xetex> + { + \hbox_set:Nn \l_@@_tmp_box { \CJKglue } + \dim_set:Nn \ccwd { \box_wd:N \l_@@_tmp_box + \f@size \p@ } + } +% +%<*luatex> + { \skip_set:Nn \ccwd { \ltjgetparameter { kanjiskip } + \zw } } +% +\dim_new:N \ccwd +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_update_ccglue:} +% 更新字间距。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_ccglue: +%<*pdftex> + { + \cs_set_protected_nopar:Npn \CJKglue + { \skip_horizontal:N \l_@@_ccglue_skip } + } +% +%<*xetex> + { \xeCJKsetup { CJKglue = { \skip_horizontal:N \l_@@_ccglue_skip } } } +% +%<*luatex> + { \ltjsetkanjiskip \l_@@_ccglue_skip } +% +\skip_new:N \l_@@_ccglue_skip +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal,pTF]{\ctex_if_ccglue_touched:} +% 检查用户是否修改过汉字间距。 +% \begin{macrocode} +\prg_new_conditional:Npnn \ctex_if_ccglue_touched: { TF } + { +%<*pdftex|xetex> + \if_meaning:w \CJKglue \@@_ccglue: + \prg_return_false: \else: \prg_return_true: \fi: +% +%<*luatex> + \skip_if_eq:nnTF { \l_@@_ccglue_skip } { \ltjgetparameter { kanjiskip } } + { \prg_return_false: } { \prg_return_true: } +% + } +% \end{macrocode} +% 注意下面的标记不能用 \verb"%",它会导致旧版本的 \pkg{l3docstrip} +% 不能替换 \texttt{@@}。 +% \begin{macrocode} +%<*pdftex|xetex> +\ctex_at_end:n { \cs_new_eq:NN \@@_ccglue: \CJKglue } +% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_update_em_unit:} +% 将当前汉字的宽度保存到 \tn{ccwd} 中备用。不采用 \texttt{1 em},因为这时的 +% \texttt{1 em} 实际上来自西文字体的信息,未必等于汉字的宽度,这似乎在传统的 +% \file{.tfm} 字体上表现更明显。在 \pdfTeX{} 和 \XeTeX{} 下,直接使用 |\f@size\p@| +% 作为汉字的宽度,这应该对大多数汉字字体都成立,但不适用于诸如“方正兰亭黑长”之类 +% 的特殊字体。在 \XeTeX{} 可以用 \tn{fontcharwd} 来改进。而在 \pdfTeX{} 下,若使用 +% \pkg{zhmetrics} 技术,所有的汉字共享同一个 \file{.tfm},\tn{fontcharwd} 也就没有 +% 意义。在 \LuaTeX{} 下,\pkg{LuaTeX-ja} 总是按照 JFM 中的设置输出汉字的宽度,可以 +% 直接用 \tn{zw} 作为汉字宽度。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_em_unit: +% { \dim_set:Nn \ccwd { \f@size \p@ } } +% { \dim_set:Nn \ccwd { \zw } } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{其它} +% +% \begin{macro}[internal]{\ctex_add_to_selectfont:n,\CTEX@selectfont@hook} +% \tn{EverySelectfont} 直到文档开始时才有效。为了 \tn{ccwd} 和 \pkg{LuaTeX-ja} 的 +% 字体设置在导言区也可用,我们还需要在这里手工修改 \tn{selectfont}。\pkg{everysel} +% 宏包会用 \tn{CheckCommand} 来检查 \tn{selectfont} 是否为标准定义。我们修改了 +% \tn{selectfont},所以会给出一个警告。为了消除这个警告,在它检查之前,还原本来 +% 定义。 +% \begin{macrocode} +\cs_new_protected:Npn \ctex_add_to_selectfont:n #1 + { + \cs_set_protected_nopar:Npx \CTEX@selectfont@hook + { \exp_not:o { \CTEX@selectfont@hook #1 } } + } +\cs_new_eq:NN \CTEX@selectfont@hook \prg_do_nothing: +\cs_new_eq:Nc \@@_save_selectfont: { selectfont ~ } +\use:n + { + \ExplSyntaxOff + \ctex_preto_cmd:NnTF \selectfont { \CTEX@selectfont@hook } + { + \tl_put_left:Nn \@EverySelectfont@Init + { \cs_set_eq:cN { selectfont ~ } \@@_save_selectfont: } + } + { \ctex_patch_failure:N \selectfont } + } +\ExplSyntaxOn +% \end{macrocode} +% \end{macro} +% +% \tn{CJK@plane} 有定义,说明处于 \pkg{CJK} 宏包的 \tn{CJKsymbol} 之内,不必使用钩子。 +% \begin{macrocode} +%<*pdftex> +\EverySelectfont { \cs_if_exist:NF \CJK@plane { \CTEX@selectfont@hook } } +% +%<*xetex|luatex> +\EverySelectfont { \CTEX@selectfont@hook } +% +% \end{macrocode} +% +% Attribute 寄存器 \tn{ltj@curjfnt} 的初始值是 $-1$,必须把它设置为一个有效的 +% \texttt{font.id},否则编译时会直接退出。 +% \begin{macrocode} +%<*luatex> +\ctex_add_to_selectfont:n + { + \ctex_ltj_select_font: + \ctex_ltj_select_alternate_font: + \ctex_ltj_update_xkanjiskip: + } +\tl_set:Nn \CJK@family { song } \selectfont +\tl_clear:N \CJK@family +% +% \end{macrocode} +% +% \begin{macro}{space} +% 在导言区或正文中设置忽略空格方式。 +% \pdfTeX{} 和 \XeTeX{} 下初始设置为 \opt{auto},\LuaTeX{} 下是无效选项。 +% \begin{macrocode} +\keys_define:nn { ctex } + { +%<*pdftex|xetex> + space .choice: , + space / true .code:n = +% { \ctex_ignorespaces_case:N \prg_do_nothing: } , +% { \xeCJKsetup { CJKspace = true } } , + space / auto .code:n = +% { \ctex_ignorespaces_case:N \ctex_auto_ignorespaces: } , +% { \xeCJKsetup { CJKspace = false } } , + space / false .code:n = +% { \ctex_ignorespaces_case:N \tex_ignorespaces:D } , +% { \xeCJKsetup { CJKspace = false } } , + space .default:n = { true } , + space .initial:n = { auto } +% +%<*luatex> + space .code:n = + { \msg_warning:nn { ctex } { invalid-option } } +% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{punct} +% 在导言区或正文中设置标点符号输出格式。\pkg{LuaTeX-ja} 设置的是字体的默认 \texttt{JFM}, +% 只会影响到之后设置的字体。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + punct .code:n = + { + \tl_set:Nx \l_@@_punct_tl { #1 } +% \punctstyle { \l_@@_punct_tl } +% \xeCJKsetup { PunctStyle = \l_@@_punct_tl } +% \ctex_mono_jfm:o { \l_@@_punct_tl } + } , + punct .default:n = { quanjiao } , + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +%<*class|style> +% \end{macrocode} +% +% \subsubsection{载入引擎定义文件} +% +% 最后载入各个编译引擎的定义文件。 +% \begin{macrocode} +\pdftex_if_engine:TF + { + \tl_set:Nx \l_@@_encoding_tl { \l_@@_encoding_tl } + \ctex_file_input:n { ctex-engine-pdftex.def } + } + { + \tl_set:Nn \l_@@_encoding_tl { UTF8 } + \xetex_if_engine:TF + { \ctex_file_input:n { ctex-engine-xetex.def } } + { \ctex_file_input:n { ctex-engine-luatex.def } } + } +% \end{macrocode} +% +% \subsection{字距与缩进} +% +% \begin{macro}{autoindent} +% \opt{autoindent} 也是可以用在正文中的选项,意义与宏包选项 |option/autoindent| 相同。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + autoindent .choice: , + autoindent .default:n = { true } , + autoindent / true .code:n = + { + \tl_set:Nn \l_@@_autoindent_tl { 2 \ccwd } + \ctex_select_size: + } , + autoindent / false .code:n = + { \tl_clear:N \l_@@_autoindent_tl } , + autoindent / unknown .code:n = + { + \ctex_set_default_ccwd:Nn \l_@@_autoindent_tl {#1} + \ctex_select_size: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\CTEXsetfont} +% 无论字体大小是否变化都更新相关信息。 +% \begin{macrocode} +\NewDocumentCommand \CTEXsetfont { } { \ctex_select_size: } +\cs_new_protected_nopar:Npn \ctex_select_size: + { \cs_if_free:NTF \size@update { \ctex_update_size: } { \selectfont } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_update_size:} +% 在字号变化时更新 \tn{ccwd}、\tn{parindent} 和汉字间距。字距为零则恢复正常设置。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_size: + { + \tl_if_eq:NNTF \l_@@_ziju_tl \c_@@_zero_tl + { + \ctex_update_stretch: + \ctex_update_parindent: + } + { \ctex_update_ziju: } + } +\tl_const:Nx \c_@@_zero_tl { \fp_use:N \c_zero_fp } +\tl_new:N \l_@@_ziju_tl +\tl_set_eq:NN \l_@@_ziju_tl \c_@@_zero_tl +% \end{macrocode} +% 在 \tn{selectfont} 中,若 \tn{size@update} 为 \tn{relax},说明字体大小没有变化, +% 我们也就不用更新相关参数。 +% \begin{macrocode} +\ctex_add_to_selectfont:n + { \cs_if_free:NF \size@update { \ctex_update_size: } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{linestretch} +% 若行宽不是汉字宽度的整数倍,自然要求伸展它们之间的差。这里设置的是在此基础上的 +% 额外伸展量。初始化为一个汉字的宽度。若设置为 \tn{maxdimen},则禁用此功能。 +% 参数的默认单位是汉字的宽度 \tn{ccwd}。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + linestretch .code:n = + { + \ctex_set_default_ccwd:Nn \l_@@_line_stretch_tl {#1} + \ctex_select_size: + } , + linestretch .value_required: + } +\tl_new:N \l_@@_line_stretch_tl +\tl_set:Nn \l_@@_line_stretch_tl { \ccwd } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_update_stretch:} +% 首先计算一行上汉字的字数,\tn{CJKglue} 相当于将 \tn{linewidth} 与汉字总宽度之差 +% 均匀地填充到汉字之间。\hologo{eTeX} 的除法是四舍五入,而我们这里应该用截断。由于 +% 没有可展性的要求,直接用原语 \cs{tex_divide:D} 要比 \cs{int_div_truncate:nn} +% 快一些。下面的算法还兼顾到了 \tn{linewidth} 不为汉字字宽的整数倍的情况。 +% 若用户禁用 \opt{linestretch} 并且修改过 \tn{CJKglue},则只更新 +% \tn{ccwd},否则设置伸展量为 $0.08$ 倍 \tn{baselineskip}。注意 \pkg{everysel} 的 +% 钩子位于 \tn{size@update} 之前,\tn{baselineskip} 还未更新,不能直接使用它。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_stretch: + { + \ctex_update_em_unit: + \dim_set:Nn \l_@@_tmp_dim { \l_@@_line_stretch_tl } + \dim_compare:nNnTF \l_@@_tmp_dim = \c_max_dim + { + \ctex_if_ccglue_touched:TF + { \ctex_update_ccwd: } + { + \dim_set:Nn \l_@@_tmp_dim + { \baselinestretch \etex_glueexpr:D \f@baselineskip \scan_stop: } + \skip_set:Nn \l_@@_ccglue_skip + { \c_zero_dim plus .08 \l_@@_tmp_dim } + \ctex_update_ccglue: + } + } + { + \int_set:Nn \l_@@_tmp_int + { \etex_dimexpr:D \linewidth - \ccwd - \l_@@_tmp_dim \scan_stop: } + \tex_divide:D \l_@@_tmp_int \ccwd + \int_compare:nNnTF \l_@@_tmp_int > \c_zero + { + \skip_set:Nn \l_@@_ccglue_skip + { + \c_zero_dim plus \dim_eval:n + { + ( \linewidth - \ccwd - \l_@@_tmp_int \ccwd ) / + \l_@@_tmp_int + } + } + } + { \skip_zero:N \l_@@_ccglue_skip } + \ctex_update_ccglue: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_update_parindent:} +% 更新段落首行缩进。此函数在字号变化时调用。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_parindent: + { + \tl_if_empty:NF \l_@@_autoindent_tl + { + \dim_compare:nNnF \parindent = \c_zero_dim + { \dim_set:Nn \parindent { \l_@@_autoindent_tl } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ziju} +% 若参数为 $0$,则恢复正常间距。 +% \begin{macrocode} +\NewDocumentCommand \ziju { m } + { \exp_args:Nx \ctex_ziju:n {#1} \tex_ignorespaces:D } +\cs_new_protected_nopar:Npn \ctex_ziju:n #1 + { + \tl_set:Nx \l_@@_ziju_tl { \fp_eval:n {#1} } + \ctex_select_size: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_update_ziju:} +% 更新字距。若字距不大于 $-1$,即 \tn{ccwd} 为非正值,则不计算伸缩值。 +% 否则,首先假定汉字的宽度为正常宽度加上字距,看一行上能正常放下多少个汉字。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_update_ziju: + { + \ctex_update_em_unit: + \dim_set:Nn \l_@@_ziju_dim { \l_@@_ziju_tl \ccwd } + \dim_add:Nn \ccwd { \l_@@_ziju_dim } + \dim_compare:nNnTF \ccwd > \c_zero_dim +% \end{macrocode} +% 伸展量保证行内的剩余空白能够被均匀地填充到汉字之间,收缩的最大限度是让当前行 +% 还能够再挤下一个汉字并且不会出现负间距。由 \TeX{} 决定伸展还是收缩。 +% \begin{macrocode} + { + \dim_set:Nn \l_@@_tmp_dim + { \linewidth - \ccwd + \l_@@_ziju_dim } + \int_set:Nn \l_@@_tmp_int { \l_@@_tmp_dim } + \tex_divide:D \l_@@_tmp_int \ccwd + \dim_sub:Nn \l_@@_tmp_dim { \l_@@_tmp_int \ccwd } +% \end{macrocode} +% 由于 \tn{parindent} 是一个固定值,并不参与伸缩,容易导致第一行出现坏盒子。 +% 我们在这里将字数减去 $2$,以此放大伸缩值。 +% \begin{macrocode} + \dim_compare:nNnF \parindent = \c_zero_dim + { + \int_compare:nNnF \l_@@_tmp_int < \c_three + { \int_sub:Nn \l_@@_tmp_int { \c_two } } + } + \skip_set:Nn \l_@@_ccglue_skip + { + \l_@@_ziju_dim + plus \dim_eval:n { \l_@@_tmp_dim / \l_@@_tmp_int } + minus \dim_min:nn { \dim_abs:n { \l_@@_ziju_dim } } + { ( \ccwd - \l_@@_tmp_dim ) / ( \l_@@_tmp_int + \c_one ) } + } + } + { \skip_set:Nn \l_@@_ccglue_skip { \l_@@_ziju_dim } } + \ctex_update_ccglue: +% \end{macrocode} +% 字距设置得比较大时,为了尽量保证段首缩进能够与下一行对齐,应该需要相应地加上 +% 或者减去伸缩值。但是这里并不清楚 \TeX{} 是伸展还是收缩,之前以“当前行是否还 +% 放得下一个汉字”为标准加上或减去伸缩值的做法也未必与实际结果一致,所以只好还 +% 是设置为 |2\ccwd|。 +% \begin{macrocode} + \ctex_update_parindent: + } +\dim_new:N \l_@@_ziju_dim +% \end{macrocode} +% \end{macro} +% +% \changes{v2.0}{2015/03/21}{\tn{CTEXindent}, \tn{CTEXnoindent} 是过时命令。} +% \begin{macro}{\CTEXindent,\CTEXnoindent} +% 过时命令。 +% \begin{macrocode} +\NewDocumentCommand \CTEXindent { } + { + \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXindent } + { \parindent is~ set~ to~ 2\ccwd. } + \ctex_update_ccwd: \dim_set:Nn \parindent { 2 \ccwd } + } +\NewDocumentCommand \CTEXnoindent { } + { + \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXnoindent } + { \parindent is~ set~ to~ 0pt. } + \dim_zero:N \parindent + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\bool_if:NT \l_@@_indent_bool + { \RequirePackage { indentfirst } } +% \end{macrocode} +% +% \subsection{中文数字与日期} +% +% \begin{macrocode} +\PassOptionsToPackage { encoding = \l_@@_encoding_tl } { zhnumber } +\RequirePackage { zhnumber } +% \end{macrocode} +% +% \begin{macro}{\chinese} +% \begin{macrocode} +\cs_new_eq:NN \chinese \zhnum +\cs_new_eq:NN \Chinese \chinese +\cs_new_eq:NN \CTEXcounter \use_none:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\CTEXnumber,\CTEXdigits} +% \begin{macrocode} +\NewDocumentCommand \CTEXnumber { m m } + { \protected@edef #1 { \zhnumber {#2} } } +\NewDocumentCommand \CTEXdigits { m m } + { \protected@edef #1 { \zhdigits {#2} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{today} +% \begin{macrocode} +\cs_set_eq:NN \CTEX@todayold \today +\keys_define:nn { ctex } + { + today .choice: , + today / old .code:n = + { \cs_set_eq:NN \today \CTEX@todayold } , + today / small .code:n = + { + \cs_set_eq:NN \today \zhtoday + \zhnumsetup { time = Arabic } + } , + today / big .code:n = + { + \cs_set_eq:NN \today \zhtoday + \zhnumsetup { time = Chinese } + } , + today / unknown .code:n = + { \msg_error:nnx { ctex } { today-undef } {#1} } + } +\msg_new:nnnn { ctex } { today-undef } + { Today~format~`#1'~is~undefined. } + { Available~today~formats~are~`old',~`small',~and~`big'. } +% \end{macrocode} +% \end{macro} +% +% \subsection{其它中文标题定义} +% +% \changes{v2.0}{2014/03/08}{将标题汉化功能加入 \pkg{ctex.sty}。} +% +% \begin{macrocode} +\keys_define:nn { ctex } + { + contentsname .tl_set:N = \contentsname , + listfigurename .tl_set:N = \listfigurename , + listtablename .tl_set:N = \listtablename , + figurename .tl_set:N = \figurename , + tablename .tl_set:N = \tablename , + abstractname .tl_set:N = \abstractname , + indexname .tl_set:N = \indexname , + appendixname .tl_set:N = \appendixname , +%
bibname .tl_set:N = \refname +% bibname .tl_set:N = \bibname + } +% \end{macrocode} +% +% \begin{macrocode} +%<*style> +\msg_new:nnn { ctex } { ctexbibname } + { + Neither~`\token_to_str:N \bibname'~nor~`\token_to_str:N \refname'~can~be~found.\\ + The~key~`bibname'~will~set~`\token_to_str:N \ctexbibname'~to~the~given~value. + } +\tl_if_exist:NTF \bibname + { \keys_define:nn { ctex } { bibname .tl_set:N = \bibname } } + { + \tl_if_exist:NTF \refname + { \keys_define:nn { ctex } { bibname .tl_set:N = \refname } } + { + \msg_warning:nn { ctex } { ctexbibname } + \keys_define:nn { ctex } { bibname .tl_set:N = \ctexbibname } + } + } +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{中文化的标题结构} +% +% 本节内容在 \CTeX{} 文档类或打开 \opt{heading} 选项下生效。 +% \begin{macrocode} +%<*class|heading> +% \end{macrocode} +% +% \subsubsection{定义标题格式选项} +% +% \begin{variable}[internal]{\c_@@_headings_seq} +% \begin{macrocode} +\seq_new:N \c_@@_headings_seq +\seq_gset_from_clist:Nn \c_@@_headings_seq + { +%
part , section , subsection , subsubsection , +% part , chapter , section , subsection , subsubsection , + paragraph , subparagraph + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[internal]{\@@_initial_heading:n} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_initial_heading:n #1 + { + \tl_new:c { CTEX@pre#1 } + \tl_new:c { CTEX@post#1 } + \tl_const:cx { CTEXthe#1 } + { + \exp_not:c { CTEX@pre#1 } + \exp_not:c { CTEX@the#1 } + \exp_not:c { CTEX@post#1 } + } + \tl_const:cx { CTEX@#1name } + { + \exp_not:c { CTEX@#1@nameformat } + \exp_not:c { CTEX@pre#1 } + \exp_not:N \tl_if_empty:NTF \exp_not:c { CTEX@#1@numberformat } + { \exp_not:c { CTEX@the#1 } } + { + \group_begin: + \exp_not:c { CTEX@#1@numberformat } + \exp_not:c { CTEX@the#1 } + \group_end: + } + \exp_not:c { CTEX@post#1 } + \exp_not:c { CTEX@#1@aftername } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_def_heading_keys:n} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_def_heading_keys:n #1 + { + \tl_put_right:Nx \l_@@_tmp_tl + { + #1 .meta:nn = { ctex / #1 } { ####1 } , + #1 / name .code:n = + { \ctex_assign_heading_name:nn {#1} { ####1 } } , + #1 / number .tl_set:N = \exp_not:c { CTEX@the#1 } , + #1 / format .tl_set:N = \exp_not:c { CTEX@#1@format } , + #1 / nameformat .tl_set:N = \exp_not:c { CTEX@#1@nameformat } , + #1 / numberformat .tl_set:N = \exp_not:c { CTEX@#1@numberformat } , + #1 / aftername .tl_set:N = \exp_not:c { CTEX@#1@aftername } , + #1 / titleformat .tl_set:N = \exp_not:c { CTEX@#1@titleformat } , + #1 / beforeskip .tl_set:N = \exp_not:c { CTEX@#1@beforeskip } , + #1 / afterskip .tl_set:N = \exp_not:c { CTEX@#1@afterskip} , + #1 / indent .tl_set:N = \exp_not:c { CTEX@#1@indent } , + #1 / format+ .code:n = + { \tl_put_right:Nn \exp_not:c { CTEX@#1@format } { ####1 } } , + #1 / nameformat+ .code:n = + { \tl_put_right:Nn \exp_not:c { CTEX@#1@nameformat } { ####1 } } , + #1 / numberformat+ .code:n = + { \tl_put_right:Nn \exp_not:c { CTEX@#1@numberformat } { ####1 } } , + #1 / aftername+ .code:n = + { \tl_put_right:Nn \exp_not:c { CTEX@#1@aftername } { ####1 } } , + #1 / titleformat+ .code:n = + { \tl_put_right:Nn \exp_not:c { CTEX@#1@titleformat } { ####1 } } , + #1 / beforeskip .initial:n = \c_zero_skip , + #1 / afterskip .initial:n = \c_zero_skip , + #1 / indent .initial:n = \c_zero_dim , + #1 / beforeskip .value_required: , + #1 / afterskip .value_required: , + #1 / indent .value_required: , + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_assign_heading_name:nn,\@@_assign_heading_name:nnn} +% \opt{name} 的值是一个至多两个元素的逗号分隔列表。由于 \LTXIII{} 的 +% \texttt{clist} 总是会自动忽略空元素,所以设置 |name={,章}| 后,第一个元素将会 +% 是“章”,必须用空的分组保护空元素:|name={{},章}|,这在使用中有些许不便。我们 +% 可以改用 \texttt{seq} 或者手写函数解析参数来加以改进。为实现的简单起见,这里用 +% 了 \pkg{xparse} 的 \tn{SplitArgument},它带有参数的长度检查。 +% \begin{macrocode} +\NewDocumentCommand \ctex_assign_heading_name:nn + { m > { \SplitArgument { \c_one } { , } } +m } + { \@@_assign_heading_name:nnn {#1} #2 } +\cs_new_protected:Npn \@@_assign_heading_name:nnn #1#2#3 + { + \tl_set:cn { CTEX@pre#1 } {#2} + \IfNoValueTF {#3} + { \tl_clear:c { CTEX@post#1 } } + { \tl_set:cn { CTEX@post#1 } {#3} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\tl_clear:N \l_@@_tmp_tl +\seq_map_inline:Nn \c_@@_headings_seq + { + \@@_initial_heading:n {#1} + \@@_def_heading_keys:n {#1} + } +\use:x { \keys_define:nn { ctex } { \exp_not:o { \l_@@_tmp_tl } } } +\tl_clear:N \l_@@_tmp_tl +% \end{macrocode} +% +% \changes{v2.0}{2014/03/21}{标题设置新增 \opt{pagestyle} 选项。} +% +% \begin{macro}{pagestyle} +% 只在 \cls{ctexbook} 和 \cls{ctexrep} 下有定义。 +% \begin{macrocode} +%<*book|report> +\keys_define:nn { ctex } + { + part / pagestyle .tl_set:N = \CTEX@part@pagestyle , + chapter / pagestyle .tl_set:N = \CTEX@chapter@pagestyle + } +% +% \end{macrocode} +% \end{macro} +% +% +% \subsubsection{标准标题命令的修改} +% +% \paragraph{part 的标题} +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \begin{macro}[internal]{\part} +% \begin{macrocode} +%<*article> +\renewcommand\part{% + \if@noskipsec \leavevmode \fi + \par +% \addvspace{4ex}% + \@tempskipa \CTEX@part@beforeskip \relax + \ifdim \@tempskipa <\z@ + \@tempskipa -\@tempskipa \@afterindentfalse + \else + \@afterindenttrue + \fi + \addvspace{\@tempskipa}% + \secdef\@part\@spart} +%
+% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@part} +% \begin{macrocode} +%<*article> +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >\m@ne + \refstepcounter{part}% +% \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% + \addcontentsline{toc}{part}{\CTEXthepart\hspace{1em}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + {\interlinepenalty \@M +% \normalfont \parindent \z@ \raggedright + \normalfont \parindent \CTEX@part@indent \CTEX@part@format + \ifnum \c@secnumdepth >\m@ne +% \Large\bfseries\partname\nobreakspace\thepart\par\nobreak + \CTEX@partname + \fi +% \huge\bfseries #2% + \CTEX@part@titleformat{#2}% + \markboth{}{}\par}% + \nobreak +% \vskip 3ex + \vskip \CTEX@part@afterskip + \@afterheading} +%
+% \end{macrocode} +% +% 标准文档类是在 \tn{part} 和 \tn{chapter} 定义的最开始设置 \tn{thispagestyle}, +% 我们这里的修改出现在它之后,可以覆盖之前的设置。 +% \begin{macrocode} +%<*book|report> +\def\@part[#1]#2{% + \thispagestyle{\CTEX@part@pagestyle}% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% +% \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% + \addcontentsline{toc}{part}{\CTEXthepart\hspace{1em}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + {\interlinepenalty \@M +% \normalfont \centering + \normalfont \CTEX@part@format + \ifnum \c@secnumdepth >-2\relax +% \huge\bfseries\partname\nobreakspace\thepart\par\vskip 20\p@ + \CTEX@partname + \fi +% \Huge\bfseries #2\par}% + \CTEX@part@titleformat{#2}\par}% + \@endpart} +% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@spart} +% \begin{macrocode} +%<*article> +\def\@spart#1{% + {\interlinepenalty \@M +% \normalfont \parindent \z@ \raggedright + \normalfont \parindent \CTEX@part@indent \CTEX@part@format +% \huge \bfseries #1\par}% + \CTEX@part@titleformat{#1}\par}% + \nobreak +% \vskip 3ex + \vskip \CTEX@part@afterskip + \@afterheading} +% +%<*book|report> +\def\@spart#1{% + {\interlinepenalty \@M +% \normalfont \centering + \normalfont \CTEX@part@format +% \Huge \bfseries #1\par}% + \CTEX@part@titleformat{#1}\par}% + \@endpart} +% +% \end{macrocode} +% \end{macro} +% +% \paragraph{chapter 的标题} +% +% \begin{macrocode} +%<*book|report> +% \end{macrocode} +% +% \begin{macro}[internal]{\@chapter} +% \begin{macrocode} +\def\@chapter[#1]#2{% + \ifnum \c@secnumdepth >\m@ne +% \if@mainmatter + \refstepcounter{chapter}% +% \typeout{\@chapapp\space\thechapter.}% + \typeout{\CTEXthechapter}% + \addcontentsline{toc}{chapter} +% {\protect\numberline{\thechapter}#1}% + {\protect\numberline{\CTEXthechapter\hspace{0.3em}}#1}% +% \else +% \addcontentsline{toc}{chapter}{#1}% +% \fi + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \chaptermark{#1}% + \addtocontents{lof}{\protect\addvspace{10\p@}}% + \addtocontents{lot}{\protect\addvspace{10\p@}}% + \if@twocolumn + \@topnewpage[\@makechapterhead{#2}]% + \else + \@makechapterhead{#2}% + \@afterheading + \fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@makechapterhead} +% \begin{macrocode} +\def\@makechapterhead#1{% + \thispagestyle{\CTEX@chapter@pagestyle}% +% \vspace*{50\p@}% + \@tempskipa \CTEX@chapter@beforeskip \relax + \ifdim \@tempskipa <\z@ + \@tempskipa -\@tempskipa \@afterindentfalse + \else + \@afterindenttrue + \fi + \vspace*{\@tempskipa}% +% {\normalfont \parindent \z@ \raggedright + {\normalfont \parindent \CTEX@chapter@indent \CTEX@chapter@format + \ifnum \c@secnumdepth >\m@ne +% \if@mainmatter +% \huge\bfseries\@chapapp\space\thechapter\par\nobreak\vskip 20\p@ + \CTEX@chaptername +% \fi + \fi + \interlinepenalty\@M +% \Huge \bfseries #1\par\nobreak + \CTEX@chapter@titleformat{#1}\par\nobreak +% \vskip 40\p@ + \vskip \CTEX@chapter@afterskip + }} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@makeschapterhead} +% \begin{macrocode} +\def\@makeschapterhead#1{% + \thispagestyle{\CTEX@chapter@pagestyle}% +% \vspace*{50\p@}% + \@tempskipa \CTEX@chapter@beforeskip \relax + \ifdim \@tempskipa <\z@ + \@tempskipa -\@tempskipa \@afterindentfalse + \else + \@afterindenttrue + \fi + \vspace*{\@tempskipa}% +% {\normalfont \parindent \z@ \raggedright + {\normalfont \parindent \CTEX@chapter@indent \CTEX@chapter@format + \interlinepenalty\@M +% \Huge \bfseries #1\par\nobreak + \CTEX@chapter@titleformat{#1}\par\nobreak +% \vskip 40\p@ + \vskip \CTEX@chapter@afterskip + }} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \paragraph{section 类的标题} +% +% \begin{macro}[internal]{\@seccntformat} +% \begin{macrocode} +\def\@seccntformat#1{% + \@ifundefined{CTEX@#1name}% + {\csname the#1\endcsname\quad}% + {\csname CTEX@#1name\endcsname}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@sect} +% \begin{macrocode} +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c@secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + \protected@edef\@svsec{\@seccntformat{#1}\relax}% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup + #6{% + \@hangfrom{\hskip #3\relax\@svsec}% +% \interlinepenalty \@M #8\@@par}% + \interlinepenalty \@M + \csname CTEX@#1@titleformat\endcsname{#8}\@@par}% + \endgroup + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else +% \protect\numberline{\csname the#1\endcsname}% + \protect\numberline{\@ifundefined{CTEXthe#1}% + {\csname the#1\endcsname}% + {\csname CTEXthe#1\endcsname}}% + \fi + #7}% + \else + \def\@svsechd{% + #6{\hskip #3\relax +% \@svsec #8}% + \@svsec \csname CTEX@#1@titleformat\endcsname{#8}}% + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else +% \protect\numberline{\csname the#1\endcsname}% + \protect\numberline{\@ifundefined{CTEXthe#1}% + {\csname the#1\endcsname}% + {\csname CTEXthe#1\endcsname}}% + \fi + #7}}% + \fi + \@xsect{#5}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@ssect} +% \tn{@ssect} 并没有参数给出当前标题的名字,扩展它的参数会与 \pkg{hyperref} 冲突。 +% 它的第二个参数是 BEFORESKIP(\tn{@startsection} 的第四个参数),在定义中并没有 +% 被用到,应该可以用它来传递名字。我们这里通过函数 \tn{CTEX@titleformat@n} 来传递, +% 它将在 |#4| 中被重定义为相应的 \opt{titleformat}。 +% \begin{macrocode} +\def\@ssect#1#2#3#4#5{% + \@tempskipa #3\relax + \ifdim \@tempskipa>\z@ + \begingroup + #4{% + \@hangfrom{\hskip #1}% +% \interlinepenalty \@M #5\@@par}% + \interlinepenalty \@M + \CTEX@titleformat@n{#5}\@@par}% + \endgroup + \else +% \def\@svsechd{#4{\hskip #1\relax #5}}% + \def\@svsechd{#4{\hskip #1\relax \CTEX@titleformat@n{#5}}}% + \fi + \@xsect{#3}} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<@@=ctex> +% \end{macrocode} +% +% \begin{macro}[internal]{\CTEX@set@titleformat@n, \CTEX@titleformat@n} +% 在 \tn{@startsection} 中设置 \tn{CTEX@titleformat@n} 为相应函数。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \CTEX@set@titleformat@n #1 + { \cs_set_eq:Nc \CTEX@titleformat@n { CTEX@#1@titleformat } } +\cs_new_eq:NN \CTEX@titleformat@n \use:n +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\int_zero:N \l_@@_tmp_int +\clist_map_inline:nn + { section , subsection , subsubsection , paragraph , subparagraph } + { + \int_incr:N \l_@@_tmp_int + \cs_gset_protected_nopar:cpx {#1} + { + \exp_not:N \@startsection {#1} + { \int_use:N \l_@@_tmp_int } + { \exp_not:c { CTEX@#1@indent } } + { \exp_not:c { CTEX@#1@beforeskip } } + { \exp_not:c { CTEX@#1@afterskip } } + { + \CTEX@set@titleformat@n {#1} + \exp_not:N \normalfont \exp_not:c { CTEX@#1@format } + } + } + } +% \end{macrocode} +% +% +% \paragraph{附录标题} +% +% \begin{macrocode} +\tl_new:N \CTEX@preappendix +\tl_new:N \CTEX@postappendix +\keys_define:nn { ctex } + { appendix .meta:nn = { ctex / appendix } {#1} } +\keys_define:nn { ctex / appendix } + { + name .code:n = { \ctex_assign_heading_name:nn { appendix } {#1} } , + number .tl_set:N = \CTEX@appendixnumber + } +% \end{macrocode} +% +% \begin{macro}[internal]{\appendix} +% \begin{macrocode} +\cs_new_eq:NN \CTEX@save@appendix \appendix +\cs_gset_protected_nopar:Npn \appendix + { + \CTEX@save@appendix +%<*article> + \gdef \CTEX@presection { \CTEX@preappendix } + \gdef \CTEX@thesection { \CTEX@appendixnumber } + \gdef \CTEX@postsection { \CTEX@postappendix } +% +%<*book|report> + \gdef \CTEX@prechapter { \CTEX@preappendix } + \gdef \CTEX@thechapter { \CTEX@appendixnumber } + \gdef \CTEX@postchapter { \CTEX@postappendix } +% + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{目录标签的宽度} +% +% \begin{macro}[internal]{\numberline} +% \begin{macrocode} +\cs_new_protected:Npn \CTEX@toc@width@n #1 + { + \hbox_set:Nn \l_@@_tmp_box {#1} + \dim_set:Nn \@tempdima + { + \dim_max:nn { \@tempdima } + { \box_wd:N \l_@@_tmp_box + \f@size \p@ / \c_two } + } + } +\group_begin: +\char_set_catcode_other:N \# +\use:n + { + \group_end: + \ExplSyntaxOff + \ctex_preto_cmd:NnTF \numberline { \CTEX@toc@width@n {#1} } { } + { \ctex_patch_failure:N \numberline } + \@ifpackageloaded { tocloft } + { } + { + \ctex_at_end_package:nn { tocloft } + { + \ctex_preto_cmd:NnTF \numberline { \CTEX@toc@width@n {#1} } { } + { \ctex_patch_failure:N \numberline } + } + } + \ExplSyntaxOn + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{页眉信息的修改} +% +% \begin{macro}[internal]{\ps@headings} +% \begin{macrocode} +%<*article> +\ctex_patch_cmd:Nnn \ps@headings { \thesection } { \CTEXthesection } +\if@twoside + \ctex_patch_cmd:Nnn \ps@headings { \thesubsection } { \CTEXthesubsection } +\fi: +% +%<*book|report> +\ctex_patch_cmd:Nnn \ps@headings + { \@chapapp\ \thechapter.~\ } { \CTEXthechapter \quad } +\if@twoside + \ctex_patch_cmd:Nnn \ps@headings { \thesection.~\ } { \CTEXthesection \quad } +\fi: +% +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[internal]{\ps@fancy} +% 这里对 \pkg{fancyhdr} 宏包打补丁。原来 \pkg{fancyhdr} 宏包中使用 +% \tn{thesection} 等宏表示页眉中的章节编号,这里改用 \pkg{ctex} 包所用的 +% \tn{CTEXthesection} 系列宏。 +% \begin{macrocode} +\ctex_at_end_package:nn { fancyhdr } + { +%<*article> + \ctex_patch_cmd:Nnn \ps@fancy + { \thesection \hskip 1em \relax } { \CTEXthesection \quad } + \ctex_patch_cmd:Nnn \ps@fancy + { \thesubsection \hskip 1em \relax } { \CTEXthesubsection \quad } +% +%<*book|report> + \ctex_patch_cmd:Nnn \ps@fancy +% { \@chapapp\ \thechapter.~\ } { \if@mainmatter \CTEXthechapter \quad \fi } +% { \@chapapp\ \thechapter.~\ } { \CTEXthechapter \quad } + \ctex_patch_cmd:Nnn \ps@fancy + { \thesection.~\ } { \CTEXthesection \quad } +% + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{标签引用数字的汉化} +% +% \begin{macro}[internal]{\refstepcounter} +% 对标题进行引用时,设置标签为通过 \opt{number} 选项设置的形式。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \CTEX@setcurrentlabel@n #1 + { + \protected@edef \@currentlabel + { + \cs_if_exist:cTF { CTEX@the#1 } + { \exp_args:cc { p@#1 } { CTEX@the#1 } } + { \exp_not:o { \@currentlabel } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_varioref_hook:} +% 关于标签引用的宏包可能会修改 \tn{refstepcounter}。其中 \pkg{cleveref} 和 +% \pkg{hyperref} 宏包都会保存之前的定义,并且它们都要求尽可能晚的被载入,所以 +% 对我们上述的修改影响不大。需要注意的是 \pkg{varioref} 宏包,如果它在 +% \CTeX{} 之后被载入,我们之前的修改将会被覆盖。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_varioref_hook: + { + \seq_map_inline:Nn \c_@@_headings_seq + { \ctex_fix_varioref_label:n { ##1 } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_fix_varioref_label:n} +% \pkg{varioref} 宏包的 \tn{labelformat} 实际上是定义一个以 |\the<#1>| 为参数的宏 +% |\p@<#1>|。\LaTeX{} 在定义计数器 |<#1>| 时,都会将 |\p@<#1>| 初始化为 \tn{@empty}。 +% 如果这个宏非空,说明用户自定义了标签格式,我们就不再修改。这里不能使用 +% \cs{exp_args:Nnc},因为 \texttt{c} 这种展开格式不会将参数放在花括号内。而 +% \tn{labelformat} 的定义是 +% \begin{verbatim} +% \def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1} +% \end{verbatim} +% 它的第二个参数必须放在花括号内,否则将会被作为宏的定界符号。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_fix_varioref_label:n #1 + { + \tl_if_empty:cT { p@#1 } + { \exp_args:Nno \labelformat {#1} { \cs:w CTEX@the#1 \cs_end: } } + } +% \end{macrocode} +% \end{macro} +% +% 如果 \pkg{varioref} 已经被载入,则使用它来设置。 +% \begin{macrocode} +\@ifpackageloaded { varioref } + { \ctex_varioref_hook: } + { + \cs_new_eq:NN \CTEX@save@refstepcounter \refstepcounter + \RenewDocumentCommand \refstepcounter { m } + { + \CTEX@save@refstepcounter {#1} + \CTEX@setcurrentlabel@n {#1} + } + \ctex_at_end_package:nn { varioref } { \ctex_varioref_hook: } + } +% \end{macrocode} +% +% \subsubsection{载入 \meta{scheme} 文件} +% +% \begin{macrocode} +\ctex_scheme_input:o { \l_@@_scheme_tl } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{标题格式的 \opt{scheme} 定义} +% +% 下面使用 \CTeX 文档类的设置方式,\opt{plain} 模拟标准文档类直接定义或以 +% \tn{@startsection} 设定的章节标题格式,\opt{chinese} 汉化的标题格式。 +% +% \begin{macrocode} +%<*scheme&(article|book|report)> +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex / part } + { +%<*plain> + name = \partname \space , + number = \thepart , +% +%<*article> + nameformat = \Large \bfseries , + afterskip = 3ex , +%<*plain> + format = \raggedright , + aftername = \par \nobreak , + titleformat = \huge \bfseries , + beforeskip = -4ex +% +%<*chinese> + number = \chinese { part } , + format = \centering , + aftername = \quad , + titleformat = \Large \bfseries , + beforeskip = 4ex +% +% +%<*book|report> + format = \centering , + nameformat = \huge \bfseries , + aftername = \par \vskip 20 \p@ , + pagestyle = plain , +%<*plain> + titleformat = \Huge \bfseries +% +%<*chinese> + titleformat = \huge \bfseries +% +% + } +% \end{macrocode} +% +% \begin{macrocode} +%<*book|report> +\keys_set:nn { ctex / chapter } + { + pagestyle = plain , + nameformat = \huge \bfseries , + afterskip = 40 \p@ , +%<*plain> + name = \chaptername \space , + number = \thechapter , + format = \raggedright , + aftername = \par \nobreak \vskip 20 \p@ , + titleformat = \Huge \bfseries , + beforeskip = -50 \p@ +% +%<*chinese> + number = \chinese { chapter } , + format = \centering , + aftername = \quad , + titleformat = \huge \bfseries , + beforeskip = 50 \p@ +% + } +% +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex / section } + { + number = \thesection , + aftername = \quad , + afterskip = 2.3ex \@plus .2ex , +%<*plain> + format = \Large \bfseries , + beforeskip = -3.5ex \@plus -1ex \@minus -.2ex +% +%<*chinese> + format = \Large \bfseries \centering , + beforeskip = 3.5ex \@plus 1ex \@minus .2ex +% + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex / subsection } + { + number = \thesubsection , + format = \large \bfseries , + aftername = \quad , + afterskip = 1.5ex \@plus .2ex , +%<*plain> + beforeskip = -3.25ex \@plus -1ex \@minus -.2ex +% +%<*chinese> + beforeskip = 3.25ex \@plus 1ex \@minus .2ex +% + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex / subsubsection } + { + number = \thesubsubsection , + format = \normalsize \bfseries , + aftername = \quad , + afterskip = 1.5ex \@plus .2ex , +%<*plain> + beforeskip = -3.25ex \@plus -1ex \@minus -.2ex +% +%<*chinese> + beforeskip = 3.25ex \@plus 1ex \@minus .2ex +% + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex / paragraph } + { + number = \theparagraph , + format = \normalsize \bfseries , + aftername = \quad + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex / subparagraph } + { + number = \thesubparagraph , + format = \normalsize \bfseries , + aftername = \quad + } +% \end{macrocode} +% +% 处理 \opt{sub3section} 与 \opt{sub4section} 的格式。 +% \begin{macrocode} +\int_compare:nNnTF \g_@@_section_depth_flag > \c_two + { + \keys_set:nn { ctex / paragraph } + { +%<*plain> + beforeskip = -3.25ex \@plus -1ex \@minus -.2ex , +% +%<*chinese> + beforeskip = 3.25ex \@plus 1ex \@minus .2ex , +% + afterskip = 1ex \@plus .2ex + } + } + { + \keys_set:nn { ctex / paragraph } + { + beforeskip = 3.25ex \@plus 1ex \@minus .2ex , + afterskip = -1em + } + } +\int_compare:nNnTF \g_@@_section_depth_flag > \c_three + { + \keys_set:nn { ctex / subparagraph } + { +%<*plain> + beforeskip = -3.25ex \@plus -1ex \@minus -.2ex , +% +%<*chinese> + beforeskip = 3.25ex \@plus 1ex \@minus .2ex , +% + afterskip = 1ex \@plus .2ex + } + } + { + \keys_set:nn { ctex / subparagraph } + { + beforeskip = 3.25ex \@plus 1ex \@minus .2ex , + afterskip = -1em + } + } +\int_compare:nNnTF \g_@@_section_depth_flag > \c_two + { \keys_set:nn { ctex / subparagraph } { indent = \c_zero_dim } } + { \keys_set:nn { ctex / subparagraph } { indent = \parindent } } +% \end{macrocode} +% +% 处理附录的格式。 +% \begin{macrocode} +\keys_set:nn { ctex / appendix } +%<*article> + { number = \@Alph \c@section } +% +%<*book|report> + { + name = \appendixname \space , + number = \@Alph \c@chapter + } +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{\pkg{ctex.sty} 的 \opt{heading} 选项} +% +% \begin{macrocode} +%<*style> +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnn { ctex } { not-standard-class } + { + None~of~the~standard~document~classes~was~loaded.\\ + Heading~`#1'~is~selected.\\ + ctex~may~not~work~as~expected. + } +\bool_if:NTF \l_@@_heading_bool + { + \clist_map_inline:nn { article , book , report } + { + \@ifclassloaded {#1} + { \clist_map_break:n { \tl_const:Nn \c_@@_class_tl {#1} } } { } + } + \tl_if_exist:NF \c_@@_class_tl + { + \cs_if_exist:NTF \chapter + { + \cs_if_exist:NF \if@mainmatter + { \cs_new_eq:NN \if@mainmatter \tex_iftrue:D } + \tl_const:Nn \c_@@_class_tl { book } + } + { \tl_const:Nn \c_@@_class_tl { article } } + \msg_warning:nnx { ctex } { not-standard-class } { \c_@@_class_tl } + } + \ctex_file_input:n { ctex- \c_@@_class_tl .def } + } + { \ctex_scheme_input:o { \l_@@_scheme_tl } } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{标题配置文件} +% +% \begin{macrocode} +%<*UTF8|GBK> +% \end{macrocode} +% +% \begin{macrocode} +\keys_set:nn { ctex } + { + contentsname = 目录 , + listfigurename = 插图 , + listtablename = 表格 , + figurename = 图 , + tablename = 表 , + abstractname = 摘要 , + indexname = 索引 , + bibname = 参考文献 , + appendixname = 附录 + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_if_exist:nnT { ctex / part } { name } + { + \keys_set:nn { ctex / part } { name = { 第 , 部分 } } + \keys_if_exist:nnT { ctex / chapter } { name } + { \keys_set:nn { ctex / chapter } { name = { 第 , 章 } } } + } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\opt{chinese} 方案的其他设置} +% +% \begin{macrocode} +%<*scheme&chinese> +% \end{macrocode} +% +% \opt{chinese} 在标准文档类下的页面格式总采用 \texttt{headings}。 +% \begin{macrocode} +%\pagestyle { headings } +% \end{macrocode} +% +% 汉化标题名字。 +% \begin{macrocode} +\str_if_eq:onTF { \l_@@_encoding_tl } { GBK } + { \ctex_file_input:n { ctex-name-gbk.cfg } } + { \ctex_file_input:n { ctex-name-utf8.cfg } } +% \end{macrocode} +% +% 日期格式。 +% \begin{macrocode} +\keys_set:nn { ctex } { today = small } +% \end{macrocode} +% +% 若用户未设置宏包选项 \opt{zihao},则设置 \tn{normalsize} 为五号字。 +% \begin{macrocode} +\int_compare:nNnF \g_@@_font_size_flag > \c_minus_one + { \cs_gset_eq:NN \g_@@_font_size_flag \c_zero } +% \end{macrocode} +% +% 若用户未设置宏包选项 \opt{linespread},则设置行距初始值为 $1.3\times 1.2=1.56$ +% 倍字体大小。 +% \begin{macrocode} +\fp_compare:nNnT { \l_@@_line_spread_fp } ? { \c_zero_fp } + { \keys_set:nn { ctex / option } { linespread = 1.3 } } +% \end{macrocode} +% +% 若用户未设置宏包选项 \opt{autoindent},则自动调整首行缩进。 +% \begin{macrocode} +\ctex_if_autoindent_touched:F + { \keys_set:nn { ctex } { autoindent = true } } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{中文字号} +% +% \begin{macrocode} +%<*class|style|ctexsize> +% \end{macrocode} +% +% \changes{v2.0}{2014/03/08}{将中文字号功能提取到可以独立使用的 \pkg{ctexsize}。} +% +% \begin{macro}{\zihao} +% \begin{macrocode} +\NewDocumentCommand \zihao { m } + { \exp_args:Nx \ctex_zihao:n {#1} \tex_ignorespaces:D } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_zihao:n} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_zihao:n #1 + { + \prop_get:NnNTF \c_@@_font_size_prop {#1} \l_@@_font_size_tl + { \exp_after:wN \fontsize \l_@@_font_size_tl \selectfont } + { \msg_error:nnn { ctex } { fontsize } {#1} } + } +\msg_new:nnnn { ctex } { fontsize } + { Undefined~Chinese~font~size~`#1'~in~command~\token_to_str:N \zihao.} + { + The~old~font~size~is~used~if~you~continue.\\ + The~available~font~sizes~are~listed~as~follow.\\ + \seq_use:Nnnn \c_@@_font_size_seq { ~and~ } { ,~ } { ,~and~ }. + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{定义中文字号} +% +% \changes{v2.0}{2014/03/08}{中文字号不再采用近似值。} +% +% \begin{variable}[internal]{\c_@@_font_size_prop} +% \begin{macro}[aux]{\@@_save_font_size:nn} +% 基础行距是字号的 $1.2$ 倍,采用 \hologo{eTeX} 的 scaling 运算得到的结果 +% 要比简单的 |1.2\dimexpr| 精确^^A +% \footnote{\url{http://thread.gmane.org/gmane.comp.tex.latex.latex3/3190}}。 +% \begin{macrocode} +\prop_new:N \c_@@_font_size_prop +\seq_new:N \c_@@_font_size_seq +\cs_new_protected_nopar:Npn \@@_save_font_size:nn #1#2 + { + \use:x + { + \prop_gput:Nnn \exp_not:N \c_@@_font_size_prop {#1} + { + { \dim_to_decimal:n {#2} } + { \dim_to_decimal:n { (#2) * \c_six / \c_five } } + } + } + \seq_gput_right:Nn \c_@@_font_size_seq {#1} + } +\clist_map_inline:nn + { + { 8 } { 5 bp } , + { 7 } { 5.5 bp } , + { -6 } { 6.5 bp } , + { 6 } { 7.5 bp } , + { -5 } { 9 bp } , + { 5 } { 10.5 bp } , + { -4 } { 12 bp } , + { 4 } { 14 bp } , + { -3 } { 15 bp } , + { 3 } { 16 bp } , + { -2 } { 18 bp } , + { 2 } { 22 bp } , + { -1 } { 24 bp } , + { 1 } { 26 bp } , + { -0 } { 36 bp } , + { 0 } { 42 bp } + } + { \@@_save_font_size:nn #1 } +% \end{macrocode} +% \end{macro} +% \end{variable} +% +% \begin{macro}[internal]{\ctex_declare_math_sizes:nnnn} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_declare_math_sizes:nnnn #1#2#3#4 + { + \@@_get_font_sizes:Nn \l_@@_font_size_tl { {#1} {#2} {#3} {#4} } + \exp_after:wN \DeclareMathSizes \l_@@_font_size_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_get_font_sizes:Nn} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_get_font_sizes:Nn #1#2 + { + \tl_clear:N #1 + \tl_map_inline:nn {#2} + { + \prop_get:NnNTF \c_@@_font_size_prop {##1} \l_@@_tmp_tl + { \tl_put_right:Nx #1 { { \tl_head:N \l_@@_tmp_tl } } } + { \tl_put_right:Nx #1 { { \dim_to_decimal:n { ##1 } } } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\clist_map_inline:nn + { + { 8 }{ 8 }{ 5pt }{ 5pt } , + { 7 }{ 7 }{ 5pt }{ 5pt } , + { -6 }{ -6 }{ 5pt }{ 5pt } , + { 6 }{ 6 }{ 5pt }{ 5pt } , + { -5 }{ -5 }{ 6pt }{ 5pt } , + { 5 }{ 5 }{ 7pt }{ 5pt } , + { -4 }{ -4 }{ 8pt }{ 6pt } , + { 4 }{ 4 }{ 5 }{ 6 } , + { -3 }{ -3 }{ -4 }{ -5 } , + { 3 }{ 3 }{ 4 }{ 5 } , + { -2 }{ -2 }{ -3 }{ -4 } , + { 2 }{ 2 }{ 3 }{ 4 } , + { -1 }{ -1 }{ -2 }{ -3 } , + { 1 }{ 1 }{ 2 }{ 3 } , + { -0 }{ -0 }{ -1 }{ -2 } , + { 0 }{ 0 }{ 1 }{ 2 } + } + { \ctex_declare_math_sizes:nnnn #1 } +% \end{macrocode} +% +% \subsubsection{修改默认字号大小} +% +% \begin{macro}[internal]{\ctex_set_font_size:Nnn} +% \begin{macrocode} +\cs_new_protected:Npn \ctex_set_font_size:Nnn #1#2#3 + { + \prop_get:NnNTF \c_@@_font_size_prop {#2} \l_@@_font_size_tl + { \exp_after:wN \@@_set_font_size:nnNn \l_@@_font_size_tl #1 {#3} } + { \msg_error:nnn { ctex } { fontsize } {#2} } + } +\cs_new_protected:Npn \@@_set_font_size:nnNn #1#2#3#4 + { \cs_set_protected_nopar:Npn #3 { \@setfontsize #3 {#1} {#2} #4 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\if_case:w \g_@@_font_size_flag + \ctex_file_input:n { ctex-c5size.clo } +\or: + \ctex_file_input:n { ctex-cs4size.clo } +\fi: +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*c5size> +\ctex_set_font_size:Nnn \normalsize { 5 } + { + \abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@ + \abovedisplayshortskip \z@ \@plus3\p@ + \belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@ + \belowdisplayskip \abovedisplayskip + \let\@listi\@listI + } +\ctex_set_font_size:Nnn \small { -5 } + { + \abovedisplayskip 8.5\p@ \@plus3\p@ \@minus4\p@ + \abovedisplayshortskip \z@ \@plus2\p@ + \belowdisplayshortskip 4\p@ \@plus2\p@ \@minus2\p@ + \def\@listi{\leftmargin\leftmargini + \topsep 4\p@ \@plus2\p@ \@minus2\p@ + \parsep 2\p@ \@plus\p@ \@minus\p@ + \itemsep \parsep} + \belowdisplayskip \abovedisplayskip + } +\ctex_set_font_size:Nnn \footnotesize { 6 } + { + \abovedisplayskip 6\p@ \@plus2\p@ \@minus4\p@ + \abovedisplayshortskip \z@ \@plus\p@ + \belowdisplayshortskip 3\p@ \@plus\p@ \@minus2\p@ + \def\@listi{\leftmargin\leftmargini + \topsep 3\p@ \@plus\p@ \@minus\p@ + \parsep 2\p@ \@plus\p@ \@minus\p@ + \itemsep \parsep} + \belowdisplayskip \abovedisplayskip + } +\ctex_set_font_size:Nnn \scriptsize { -6 } { } +\ctex_set_font_size:Nnn \tiny { 7 } { } +\ctex_set_font_size:Nnn \large { -4 } { } +\ctex_set_font_size:Nnn \Large { -3 } { } +\ctex_set_font_size:Nnn \LARGE { -2 } { } +\ctex_set_font_size:Nnn \huge { 2 } { } +\ctex_set_font_size:Nnn \Huge { 1 } { } +% +%<*cs4size> +\ctex_set_font_size:Nnn \normalsize { -4 } + { + \abovedisplayskip 12\p@ \@plus3\p@ \@minus7\p@ + \abovedisplayshortskip \z@ \@plus3\p@ + \belowdisplayshortskip 6.5\p@ \@plus3.5\p@ \@minus3\p@ + \belowdisplayskip \abovedisplayskip + \let\@listi\@listI + } +\ctex_set_font_size:Nnn \small { 5 } + { + \abovedisplayskip 11\p@ \@plus3\p@ \@minus6\p@ + \abovedisplayshortskip \z@ \@plus3\p@ + \belowdisplayshortskip 6.5\p@ \@plus3.5\p@ \@minus3\p@ + \def\@listi{\leftmargin\leftmargini + \topsep 9\p@ \@plus3\p@ \@minus5\p@ + \parsep 4.5\p@ \@plus2\p@ \@minus\p@ + \itemsep \parsep} + \belowdisplayskip \abovedisplayskip + } +\ctex_set_font_size:Nnn \footnotesize { -5 } + { + \abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@ + \abovedisplayshortskip \z@ \@plus3\p@ + \belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@ + \def\@listi{\leftmargin\leftmargini + \topsep 6\p@ \@plus2\p@ \@minus2\p@ + \parsep 3\p@ \@plus2\p@ \@minus\p@ + \itemsep \parsep} + \belowdisplayskip \abovedisplayskip + } +\ctex_set_font_size:Nnn \scriptsize { 6 } { } +\ctex_set_font_size:Nnn \tiny { -6 } { } +\ctex_set_font_size:Nnn \large { -3 } { } +\ctex_set_font_size:Nnn \Large { -2 } { } +\ctex_set_font_size:Nnn \LARGE { 2 } { } +\ctex_set_font_size:Nnn \huge { -1 } { } +\ctex_set_font_size:Nnn \Huge { 1 } { } +% +% \end{macrocode} +% +% \begin{macrocode} +%\normalsize +% \end{macrocode} +% +% \begin{macrocode} +%<*class|style> +% \end{macrocode} +% +% \subsection{更新行距} +% +% \cs{l_@@_line_spread_fp} 被设置了才有必要更新行距和 \tn{footnotesep}。 +% \begin{macrocode} +\fp_compare:nNnF { \l_@@_line_spread_fp } ? { \c_zero_fp } + { + \linespread { \fp_use:N \l_@@_line_spread_fp } +% \end{macrocode} +% +% \changes{v2.0}{2014/04/23}{调整 \tn{footnotesep} 的大小,以适合行距的变化。} +% +% \begin{variable}[internal]{\footnotesep} +% 我们调整了行距,可能导致脚注的间距与行距不协调,需要调整 \tn{footnotesep}。标准 +% 文档类对 \tn{footnotesep} 的设置是,字体大小为 \tn{footnotesize} 时 \tn{strutbox} +% 的高度(默认值是 |.7\baselineskip|)。我们沿用这个设置方法,只需要更新具体的大小。 +% \begin{macrocode} + \group_begin: \footnotesize \exp_args:NNNo \group_end: + \dim_set:Nn \footnotesep { \dim_use:N \box_ht:N \strutbox } + } +% \end{macrocode} +% \end{variable} +% +% 激活默认字体大小,更新行距、\tn{parindent} 和 \tn{CJKglue}。 +% \begin{macrocode} +\normalsize +% \end{macrocode} +% +% \subsection{其它功能} +% +% \begin{macro}{\CTeX} +% \file{ctex-faq.sty} 中的定义是 +% \begin{verbatim} +% \DeclareRobustCommand\CTeX{$\mathbb{C}$\kern-.05em\TeX} +% \end{verbatim} +% 然而 \tn{mathbb} 未必有定义,这里就不采用它了,只定义最简单的形式。 +% 同 \pkg{hologo} 宏包的设置类似,\CTeX{} 可以用在 \tn{csname} 和 PDF 书签中。 +% \begin{macrocode} +\NewDocumentCommand \CTeX { } + { \ifincsname CTeX \else: C \TeX \fi: } +\AtBeginDocument + { + \cs_if_exist_use:NT \pdfstringdefDisableCommands + { { \tl_set:Nn \CTeX { CTeX } } } + } +% \end{macrocode} +% \end{macro} +% +% \changes{v2.0}{2014/03/28}{\opt{captiondelimiter} 是过时选项。} +% \begin{macro}[internal]{captiondelimiter} +% 过时选项。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + captiondelimiter .code:n = + { + \msg_warning:nnn { ctex } { deprecated-option } + { You~can~load~the~package~`caption'~to~get~its~functionality. } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{列表环境的缩进} +% +% \begin{macro}[internal]{\verse,\quotation} +% 只在使用文档类的时候修改诗歌和引用环境的缩进。 +% \begin{macrocode} +%<*scheme&!generic&chinese> +\ctex_patch_cmd:Nnn \verse { -1.5em } { -2 \ccwd } +\ctex_patch_cmd:Nnn \verse { 1.5em } { 2 \ccwd } +\ctex_patch_cmd:Nnn \quotation { 1.5em } { 2 \ccwd } +% +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<*class|style> +% \end{macrocode} +% +% \subsubsection{其他兼容性修改} +% +% \begin{macro}[internal]{\end} +% \changes{v2.0}{2014/03/09} +% {解决 \pkg{etoolbox} 与 \pkg{breqn} 关于 \tn{end} 的冲突。} +% \pkg{breqn} 宏包对 \tn{end} 作了如下处理,然而这个处理并不保险。 +% \begin{verbatim} +% \def\@tempa#1\endcsname#2\@nil{\def\latex@end##1{#2}} +% \expandafter\@tempa\end{#1}\@nil +% \def\end#1{\csname end#1\endcsname \latex@end{#1}}% +% \end{verbatim} +% \pkg{etoolbox} 在 \tn{end} 定义中的 \tn{csname} 前加入 +% 钩子 |\csuse{@end@#1@hook}|。如果 \pkg{etoolbox} 先于 \pkg{breqn} 被载入(这 +% 在使用 \cls{ctexart} 等文档类时几乎是必然的),|\csuse{@end@#1@hook}| 将会被 +% 忽略,即 \tn{AtEndEnvironment} 失效。如果交换两个宏包的载入顺序,则 +% \pkg{etoolbox} 会给出警告:\tn{AfterEndEnvironment} 失效,我们不打算处理这种 +% 情况。 +% \begin{macrocode} +\group_begin: +\char_set_catcode_other:N \# +\use:n + { + \group_end: + \ExplSyntaxOff + \ctex_at_end_package:nn { breqn } + { + \ctex_patch_cmd:NnnTF \end { \csname end#1 \endcsname } + { + \csuse { @end@#1@hook } + \csname end#1 \endcsname + } { } + { + \ctex_preto_cmd:NnTF \end { \csuse { @end@#1@hook } } + { } { \ctex_patch_failure:N \end } + } + } + \ExplSyntaxOn + } +% \end{macrocode} +% \end{macro} +% +% \subsection{载入中文字体} +% +% \begin{macro}[internal]{\ctex_fontset_error:n} +% 字库不可用时给出紧急错误信息,停止读取定义文件。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_fontset_error:n #1 + { \msg_critical:nnn { ctex } { fontset-unavailable } {#1} } +\msg_new:nnn { ctex } { fontset-unavailable } + { CTeX~fontset~`#1'~is~unavailable~in~current~mode. } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\ctex_load_fontset:} +% 如果用户没有指定字体,则探测操作系统,载入相应的字体配置。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_load_fontset: + { + \tl_if_empty:NTF \g_@@_fontset_tl + { + \ctex_detected_platform: + \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } + } + { + \file_if_exist:nTF { ctex-fontset- \g_@@_fontset_tl .def } + { \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } } + { + \use:x + { + \ctex_detected_platform: + \msg_error:nnxx { ctex } { fontset-not-found } + { \g_@@_fontset_tl } { \exp_not:N \g_@@_fontset_tl } + } + \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } + } + } + } +\@onlypreamble \ctex_load_fontset: +\msg_new:nnnn { ctex } { fontset-not-found } + { + CTeX~fontset~`#1'~could~not~be~found.\\ + Fontset~`#2'~will~be~used~instead. + } + { You~may~run~`mktexlsr'~firstly. } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{fontset} +% 在导言区通过 \tn{ctexset} 载入中文字库的选项。 +% \begin{macrocode} +\keys_define:nn { ctex } + { + fontset .code:n = + { + \ctex_if_preamble:TF + { + \str_if_eq_x:nnTF {#1} { none } + { \msg_warning:nnn { ctex } { invalid-value } {#1} } + { + \str_if_eq:onTF { \g_@@_fontset_tl } { none } + { + \tl_gset:Nx \g_@@_fontset_tl {#1} + \ctex_load_fontset: + } + { + \msg_error:nnxx { ctex } { fontset-loaded } + { \g_@@_fontset_tl } {#1} + } + } + } + { \msg_error:nn { ctex } { fontset-only-preamble } } + } + } +\msg_new:nnnn { ctex } { fontset-loaded } + { + CTeX~fontset~`#1'~has~been~loaded. + \str_if_eq:nnF {#1} {#2} { \\ Fontset~`#2'~will~be~ignored. } + } + { Only~one~fontset~can~be~loaded~in~the~preamble. } +\msg_new:nnn { ctex } { fontset-only-preamble } + { + The~ `fontset'~ option~ can~ be~ used~ only~ in~ preamble. + } +% \end{macrocode} +% \end{macro} +% +% 载入中文字库。 +% \begin{macrocode} +\str_if_eq:onF { \g_@@_fontset_tl } { none } + { \ctex_load_fontset: } +% \end{macrocode} +% +% \subsection{宏包配置文件} +% +% \subsubsection{\pkg{ctex.cfg}} +% +% \begin{macrocode} +\ctex_at_end:n { \ctex_file_input:n { ctex.cfg } } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*config> +%% +% +% \end{macrocode} +% +% \subsubsection{\pkg{ctexopts.cfg}} +% +% 这里仅为配置文件示例:使用 Windows Vista 或以后版本的字体设置。 +% \begin{macrocode} +%<*ctexopts> +%% +%% \keys_set:nn { ctex / option } { fontset = windowsnew } +% +% \end{macrocode} +% +% \subsection{字体定义文件} +% +% \subsubsection{传统定义方式} +% +% \begin{macrocode} +%<*c19|c70> +%% +%% Chinese characters +%% +%%% character set: GBK (extension of GB 2312) +%%% character set: Unicode +%% font encoding: Unicode +%% +% +% \end{macrocode} +% +% \begin{macrocode} +%\DeclareFontFamily{C19}{rm}{\hyphenchar\font\m@ne} +%\DeclareFontFamily{C70}{rm}{\hyphenchar\font\m@ne} +%\DeclareFontFamily{C19}{sf}{\hyphenchar\font\m@ne} +%\DeclareFontFamily{C70}{sf}{\hyphenchar\font\m@ne} +%\DeclareFontFamily{C19}{tt}{\hyphenchar\font\m@ne} +%\DeclareFontFamily{C70}{tt}{\hyphenchar\font\m@ne} +% \end{macrocode} +% +% \begin{macrocode} +%<*rm> +%<*c19> +\DeclareFontShape{C19}{rm}{m}{n}{<-> CJK * gbksong}{\CJKnormal} +\DeclareFontShape{C19}{rm}{b}{n}{<-> CJK * gbkhei}{\CJKnormal} +\DeclareFontShape{C19}{rm}{bx}{n}{<-> CJK * gbkhei}{\CJKnormal} +\DeclareFontShape{C19}{rm}{m}{sl}{<-> CJK * gbksongsl}{\CJKnormal} +\DeclareFontShape{C19}{rm}{b}{sl}{<-> CJK * gbkheisl}{\CJKnormal} +\DeclareFontShape{C19}{rm}{bx}{sl}{<-> CJK * gbkheisl}{\CJKnormal} +\DeclareFontShape{C19}{rm}{m}{it}{<-> CJK * gbkkai}{\CJKnormal} +\DeclareFontShape{C19}{rm}{b}{it}{<-> CJKb * gbkkai}{\CJKbold} +\DeclareFontShape{C19}{rm}{bx}{it}{<-> CJKb * gbkkai}{\CJKbold} +% +%<*c70> +\DeclareFontShape{C70}{rm}{m}{n}{<-> CJK * unisong}{\CJKnormal} +\DeclareFontShape{C70}{rm}{b}{n}{<-> CJK * unihei}{\CJKnormal} +\DeclareFontShape{C70}{rm}{bx}{n}{<-> CJK * unihei}{\CJKnormal} +\DeclareFontShape{C70}{rm}{m}{sl}{<-> CJK * unisongsl}{\CJKnormal} +\DeclareFontShape{C70}{rm}{b}{sl}{<-> CJK * uniheisl}{\CJKnormal} +\DeclareFontShape{C70}{rm}{bx}{sl}{<-> CJK * uniheisl}{\CJKnormal} +\DeclareFontShape{C70}{rm}{m}{it}{<-> CJK * unikai}{\CJKnormal} +\DeclareFontShape{C70}{rm}{b}{it}{<-> CJKb * unikai}{\CJKbold} +\DeclareFontShape{C70}{rm}{bx}{it}{<-> CJKb * unikai}{\CJKbold} +% +% +% \end{macrocode} +% +% \begin{macrocode} +%<*sf> +%<*c19> +\DeclareFontShape{C19}{sf}{m}{n}{<-> CJK * gbkyou}{\CJKnormal} +\DeclareFontShape{C19}{sf}{b}{n}{<-> CJKb * gbkyou}{\CJKbold} +\DeclareFontShape{C19}{sf}{bx}{n}{<-> CJKb * gbkyou}{\CJKbold} +\DeclareFontShape{C19}{sf}{m}{sl}{<-> CJK * gbkyousl}{\CJKnormal} +\DeclareFontShape{C19}{sf}{b}{sl}{<-> CJKb * gbkyousl}{\CJKbold} +\DeclareFontShape{C19}{sf}{bx}{sl}{<-> CJKb * gbkyousl}{\CJKbold} +\DeclareFontShape{C19}{sf}{m}{it}{<-> CJK * gbkyou}{\CJKnormal} +\DeclareFontShape{C19}{sf}{b}{it}{<-> CJKb * gbkyou}{\CJKbold} +\DeclareFontShape{C19}{sf}{bx}{it}{<-> CJKb * gbkyou}{\CJKbold} +% +%<*c70> +\DeclareFontShape{C70}{sf}{m}{n}{<-> CJK * uniyou}{\CJKnormal} +\DeclareFontShape{C70}{sf}{b}{n}{<-> CJKb * uniyou}{\CJKbold} +\DeclareFontShape{C70}{sf}{bx}{n}{<-> CJKb * uniyou}{\CJKbold} +\DeclareFontShape{C70}{sf}{m}{sl}{<-> CJK * uniyousl}{\CJKnormal} +\DeclareFontShape{C70}{sf}{b}{sl}{<-> CJKb * uniyousl}{\CJKbold} +\DeclareFontShape{C70}{sf}{bx}{sl}{<-> CJKb * uniyousl}{\CJKbold} +\DeclareFontShape{C70}{sf}{m}{it}{<-> CJK * uniyou}{\CJKnormal} +\DeclareFontShape{C70}{sf}{b}{it}{<-> CJKb * uniyou}{\CJKbold} +\DeclareFontShape{C70}{sf}{bx}{it}{<-> CJKb * uniyou}{\CJKbold} +% +% +% \end{macrocode} +% +% \begin{macrocode} +%<*tt> +%<*c19> +\DeclareFontShape{C19}{tt}{m}{n}{<-> CJK * gbkfs}{\CJKnormal} +\DeclareFontShape{C19}{tt}{b}{n}{<-> CJKb * gbkfs}{\CJKbold} +\DeclareFontShape{C19}{tt}{bx}{n}{<-> CJKb * gbkfs}{\CJKbold} +\DeclareFontShape{C19}{tt}{m}{sl}{<-> CJK * gbkfssl}{\CJKnormal} +\DeclareFontShape{C19}{tt}{b}{sl}{<-> CJKb * gbkfssl}{\CJKbold} +\DeclareFontShape{C19}{tt}{bx}{sl}{<-> CJKb * gbkfssl}{\CJKbold} +\DeclareFontShape{C19}{tt}{m}{it}{<-> CJK * gbkfs}{\CJKnormal} +\DeclareFontShape{C19}{tt}{b}{it}{<-> CJKb * gbkfs}{\CJKbold} +\DeclareFontShape{C19}{tt}{bx}{it}{<-> CJKb * gbkfs}{\CJKbold} +% +%<*c70> +\DeclareFontShape{C70}{tt}{m}{n}{<-> CJK * unifs}{\CJKnormal} +\DeclareFontShape{C70}{tt}{b}{n}{<-> CJKb * unifs}{\CJKbold} +\DeclareFontShape{C70}{tt}{bx}{n}{<-> CJKb * unifs}{\CJKbold} +\DeclareFontShape{C70}{tt}{m}{sl}{<-> CJK * unifssl}{\CJKnormal} +\DeclareFontShape{C70}{tt}{b}{sl}{<-> CJKb * unifssl}{\CJKbold} +\DeclareFontShape{C70}{tt}{bx}{sl}{<-> CJKb * unifssl}{\CJKbold} +\DeclareFontShape{C70}{tt}{m}{it}{<-> CJK * unifs}{\CJKnormal} +\DeclareFontShape{C70}{tt}{b}{it}{<-> CJKb * unifs}{\CJKbold} +\DeclareFontShape{C70}{tt}{bx}{it}{<-> CJKb * unifs}{\CJKbold} +% +% +% \end{macrocode} +% +% \begin{macrocode} +%<*fontset> +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-fontset-windows.def}, +% \pkg{ctex-fontset-windowsnew.def}, \pkg{ctex-fontset-windowsold.def}} +% +% \pkg{ctex} 包利用 \path{C:\boot.ini} 文件的存在性来判断是否使用 Windows XP +% 及以前的版本,分别载入新旧字体设置。 +% \begin{macrocode} +%<*windows> +\file_if_exist:nTF { C:/boot.ini } + { \ctex_file_input:n { ctex-fontset-windowsold.def } } + { \ctex_file_input:n { ctex-fontset-windowsnew.def } } +% +% \end{macrocode} +% +% 旧的 Windows 字体设置使用黑体作为无衬线体,楷体和仿宋是 GB2312 编码;新的 +% Windows 字体设置使用微软雅黑作为无衬线体,楷体和仿宋是大字库。 +% \begin{macrocode} +%<*windowsnew,windowsold> +\pdftex_if_engine:TF + { + \ctex_zhmap_case:nnn + { + \ctex_punct_set:n { windows } + \setCJKmainfont + [ BoldFont = simhei.ttf , ItalicFont = simkai.ttf ] { simsun.ttc } +%<*windowsold> + \setCJKsansfont { simhei.ttf } + \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } +% +% \end{macrocode} +% Windows 8 以后,微软雅黑由原来的 \file{.ttf} 后缀改为 \file{.ttc} 后缀,需要 +% 加以区分。 +% \begin{macrocode} +%<*windowsnew> + \file_if_exist:nTF { C:/Windows/Fonts/msyh.ttc } + { + \setCJKsansfont [ BoldFont = msyhbd.ttc ] { msyh.ttc } + \setCJKfamilyfont { zhyahei } + [ BoldFont = msyhbd.ttc ] { msyh.ttc } + } + { + \setCJKsansfont [ BoldFont = msyhbd.ttf ] { msyh.ttf } + \setCJKfamilyfont { zhyahei } + [ BoldFont = msyhbd.ttf ] { msyh.ttf } + } + \ctex_punct_map_family:nn { \CJKsfdefault } { zhyahei } + \ctex_punct_map_bfseries:nn { \CJKsfdefault , zhyahei } { zhyaheib } +% + \setCJKmonofont { simfang.ttf } + \setCJKfamilyfont { zhkai } { simkai.ttf } + \setCJKfamilyfont { zhfs } { simfang.ttf } + \setCJKfamilyfont { zhsong } { simsun.ttc } + \setCJKfamilyfont { zhhei } { simhei.ttf } + \setCJKfamilyfont { zhli } { simli.ttf } + \setCJKfamilyfont { zhyou } { simyou.ttf } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + } + { + \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhwindowsfonts } + \ctex_punct_set:n { windows } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + } + { + \tl_set:Nn \CJKrmdefault { rm } + \tl_set:Nn \CJKsfdefault { sf } + \tl_set:Nn \CJKttdefault { tt } + } + } + { +%<*windowsold> + \setCJKmainfont + [ BoldFont = SimHei , ItalicFont = KaiTi_GB2312 ] { SimSun } + \setCJKsansfont { SimHei } + \setCJKmonofont { FangSong_GB2312 } + \setCJKfamilyfont { zhkai } { KaiTi_GB2312 } + \setCJKfamilyfont { zhfs } { FangSong_GB2312 } +% +%<*windowsnew> + \setCJKmainfont + [ BoldFont = SimHei , ItalicFont = KaiTi ] { SimSun } + \setCJKsansfont + [ BoldFont = { *~Bold } ] { Microsoft~YaHei } + \setCJKmonofont { FangSong } + \setCJKfamilyfont { zhkai } { KaiTi } + \setCJKfamilyfont { zhfs } { FangSong } +% + \setCJKfamilyfont { zhsong } { SimSun } + \setCJKfamilyfont { zhhei } { SimHei } + \setCJKfamilyfont { zhli } { LiSu } + \setCJKfamilyfont { zhyou } { YouYuan } +%<*windowsnew> + \setCJKfamilyfont { zhyahei } + [ BoldFont = { *~Bold } ] { Microsoft~YaHei } +% + } +% +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-fontset-adobe.def}} +% +% \begin{macrocode} +%<*adobe> +% \end{macrocode} +% +% \tn{pdfmapline} 不支持 OpenType 字体,因而 \opt{adobe} 字体集在 pdf 模式下 +% 就没有定义。\opt{fandol} 的情况类似。 +% \begin{macrocode} +\pdftex_if_engine:TF + { + \ctex_if_pdfmode:TF + { \ctex_fontset_error:n { adobe } } + { + \ctex_zhmap_case:nnn + { + \setCJKmainfont + [ + cmap = UniGB-UTF16-H , + BoldFont = AdobeHeitiStd-Regular.otf , + ItalicFont = AdobeKaitiStd-Regular.otf + ] { AdobeSongStd-Light.otf } + \setCJKsansfont [ cmap = UniGB-UTF16-H ] { AdobeHeitiStd-Regular.otf } + \setCJKmonofont [ cmap = UniGB-UTF16-H ] { AdobeFangsongStd-Regular.otf } + \setCJKfamilyfont { zhsong } + [ cmap = UniGB-UTF16-H ] { AdobeSongStd-Light.otf } + \setCJKfamilyfont { zhhei } + [ cmap = UniGB-UTF16-H ] { AdobeHeitiStd-Regular.otf } + \setCJKfamilyfont { zhkai } + [ cmap = UniGB-UTF16-H ] { AdobeKaitiStd-Regular.otf } + \setCJKfamilyfont { zhfs } + [ cmap = UniGB-UTF16-H ] { AdobeFangsongStd-Regular.otf } + \ctex_punct_set:n { adobe } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } + \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + } + { + \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhadobefonts } + \ctex_punct_set:n { adobe } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + } + { \ctex_fontset_error:n { adobe } } + } + } + { + \setCJKmainfont + [ + BoldFont = AdobeHeitiStd-Regular , + ItalicFont = AdobeKaitiStd-Regular + ] { AdobeSongStd-Light } + \setCJKsansfont { AdobeHeitiStd-Regular} + \setCJKmonofont { AdobeFangsongStd-Regular} + \setCJKfamilyfont { zhsong } { AdobeSongStd-Light } + \setCJKfamilyfont { zhhei } { AdobeHeitiStd-Regular } + \setCJKfamilyfont { zhfs } { AdobeFangsongStd-Regular } + \setCJKfamilyfont { zhkai } { AdobeKaitiStd-Regular } + } +% \end{macrocode} +% +% \begin{macrocode} +% +%<*fandol> +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-fontset-fandol.def}} +% +% \begin{macrocode} +\pdftex_if_engine:TF + { + \ctex_if_pdfmode:TF + { \ctex_fontset_error:n { fandol } } + { + \ctex_zhmap_case:nnn + { + \setCJKmainfont + [ + cmap = UniGB-UTF16-H , + BoldFont = FandolSong-Bold.otf , + ItalicFont = FandolKai-Regular.otf + ] { FandolSong-Regular.otf } + \setCJKsansfont + [ + cmap = UniGB-UTF16-H , + BoldFont = FandolHei-Bold.otf + ] { FandolHei-Regular.otf } + \setCJKmonofont [ cmap = UniGB-UTF16-H ] { FandolFang-Regular.otf } + \setCJKfamilyfont { zhsong } + [ + cmap = UniGB-UTF16-H , + BoldFont = FandolSong-Bold.otf + ] { FandolSong-Regular.otf } + \setCJKfamilyfont { zhhei } + [ + cmap = UniGB-UTF16-H , + BoldFont = FandolHei-Bold.otf + ] { FandolHei-Regular.otf } + \setCJKfamilyfont { zhfs } + [ cmap = UniGB-UTF16-H ] { FandolFang-Regular.otf } + \setCJKfamilyfont { zhkai } + [ cmap = UniGB-UTF16-H ] { FandolKai-Regular.otf } + \ctex_punct_set:n { fandol } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } + \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + \ctex_punct_map_bfseries:nn { \CJKrmdefault , zhsong } { zhsongb } + \ctex_punct_map_bfseries:nn { \CJKsfdefault , zhhei } { zhheib } + } + { + \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhfandolfonts } + \ctex_punct_set:n { fandol } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + } + { \ctex_fontset_error:n { fandol } } + } + } + { + \setCJKmainfont + [ Extension = .otf , BoldFont = FandolSong-Bold , ItalicFont = FandolKai-Regular ] + { FandolSong-Regular } + \setCJKsansfont [ Extension = .otf , BoldFont = FandolHei-Bold ] { FandolHei-Regular } + \setCJKmonofont [ Extension = .otf ] { FandolFang-Regular } + \setCJKfamilyfont { zhsong } + [ Extension = .otf , BoldFont = FandolSong-Bold ] { FandolSong-Regular } + \setCJKfamilyfont { zhhei } + [ Extension = .otf , BoldFont = FandolHei-Bold ] { FandolHei-Regular } + \setCJKfamilyfont { zhfs } [ Extension = .otf ] { FandolFang-Regular } + \setCJKfamilyfont { zhkai } [ Extension = .otf ] { FandolKai-Regular } + } +% \end{macrocode} +% +% \begin{macrocode} +% +%<*mac> +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-fontset-mac.def}} +% +% OS X Mavericks (10.9) 预装的主要简体中文字体如下^^A +% \footnote{\url{http://support.apple.com/kb/HT5944}}: +% \begin{verbatim} +% /Library/Fonts/Baoli.ttc: 报隶-简,Baoli SC:style=Regular +% /Library/Fonts/Hannotate.ttc: 手札体-简,Hannotate SC:style=Bold +% /Library/Fonts/Hannotate.ttc: 手札体-简,Hannotate SC:style=Regular +% /Library/Fonts/Hanzipen.ttc: 翩翩体-简,HanziPen SC:style=Bold +% /Library/Fonts/Hanzipen.ttc: 翩翩体-简,HanziPen SC:style=Regular +% /Library/Fonts/Hei.ttf: Hei +% /Library/Fonts/Hiragino Sans GB W3.otf: 冬青黑体简体中文 W3,Hiragino Sans GB W3 +% /Library/Fonts/Hiragino Sans GB W6.otf: 冬青黑体简体中文 W6,Hiragino Sans GB W6 +% /Library/Fonts/Kai.ttf: Kai +% /Library/Fonts/Kaiti.ttc: STKaiti +% /Library/Fonts/Kaiti.ttc: 楷体-简,Kaiti SC:style=Black +% /Library/Fonts/Kaiti.ttc: 楷体-简,Kaiti SC:style=Bold +% /Library/Fonts/Kaiti.ttc: 楷体-简,Kaiti SC:style=Regular +% /Library/Fonts/Lantinghei.ttc: 兰亭黑-简,Lantinghei SC:style=Demibold +% /Library/Fonts/Lantinghei.ttc: 兰亭黑-简,Lantinghei SC:style=Heavy +% /Library/Fonts/Lantinghei.ttc: 兰亭黑-简,Lantinghei SC:style=Extralight +% /Library/Fonts/Libian.ttc: 隶变-简,Libian SC +% /Library/Fonts/Songti.ttc: STSong +% /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Black +% /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Bold +% /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Light +% /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Regular +% /Library/Fonts/WawaSC-Regular.otf: 娃娃体-简,Wawati SC +% /Library/Fonts/WeibeiSC-Bold.otf: 魏碑-简,Weibei SC +% /Library/Fonts/Xingkai.ttc: 行楷-简,Xingkai SC:style=Bold +% /Library/Fonts/Xingkai.ttc: 行楷-简,Xingkai SC:style=Light +% /Library/Fonts/Yuanti.ttc: 圆体-简,Yuanti SC:style=Bold +% /Library/Fonts/Yuanti.ttc: 圆体-简,Yuanti SC:style=Light +% /Library/Fonts/Yuanti.ttc: 圆体-简,Yuanti SC:style=Regular +% /Library/Fonts/YuppySC-Regular.otf: 雅痞-简,Yuppy SC +% /Library/Fonts/华文仿宋.ttf: STFangsong +% /Library/Fonts/华文细黑.ttf: STHeiti:style=Light +% /Library/Fonts/华文黑体.ttf: STHeiti:style=Regular +% /System/Library/Fonts/STHeiti Light.ttc: 黑体-简,Heiti SC:style=Light +% /System/Library/Fonts/STHeiti Medium.ttc: 黑体-简,Heiti SC:style=Medium +% \end{verbatim} +% 在 \dvipdfmx{} 下,可以通过下述方式使用华文宋体和华文楷体: +% \begin{verbatim} +% \special{pdf:mapline unisong@Unicode@ unicode :4:Songti.ttc} +% \special{pdf:mapline unikai@Unicode@ unicode :4:Kaiti.ttc} +% \end{verbatim} +% 而 \tn{pdfmapline} 似乎不支持带索引的 \texttt{ttc} 字体,\file{Songti.ttc} 默认 +% 使用的是 Songti SC Black,\file{Kaiti.ttc} 默认使用的是 Kaiti SC Black。 +% 华文黑体不能通过这种方式使用: +% \begin{verbatim} +% \special{pdf:mapline unihei@Unicode@ unicode \detokenize{华文黑体}.ttf} +% \end{verbatim} +% \dvipdfmx{} 不能生成 PDF,报下述错误: +% \begin{verbatim} +% ** WARNING ** UCS-4 TrueType cmap table... +% ** ERROR ** Unable to read OpenType/TrueType Unicode cmap table. +% \end{verbatim} +% 如果将 CMap 改为 UniGB-UTF16-H,错误信息是 +% \begin{verbatim} +% ** WARNING ** No usable TrueType cmap table found for font "华文黑体.ttf". +% ** WARNING ** CID character collection for this font is set to "Adobe-GB1" +% ** ERROR ** Cannot continue without this... +% \end{verbatim} +% 在 \pdfTeX{} 下生成的 PDF 只有方框^^A +% \footnote{\url{http://www.newsmth.net/bbscon.php?bid=460&id=312640}}。 +% 华文细黑和华文仿宋的情况类似。 +% \begin{macrocode} +\pdftex_if_engine:TF + { \ctex_fontset_error:n { mac } } + { + \setCJKmainfont [ BoldFont = STHeiti , ItalicFont = STKaiti ] { STSong } + \setCJKsansfont [ BoldFont = STHeiti ] { STXihei } + \setCJKmonofont { STFangsong } + \setCJKfamilyfont { zhsong } { STSong } + \setCJKfamilyfont { zhhei } { STHeiti } + \setCJKfamilyfont { zhfs } { STFangsong } + \setCJKfamilyfont { zhkai } { STKaiti } + } +% \end{macrocode} +% +% \begin{macrocode} +% +%<*founder> +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-fontset-founder.def}} +% +% \begin{macrocode} +\pdftex_if_engine:TF + { + \ctex_zhmap_case:nnn + { + \setCJKmainfont + [ BoldFont = FZXBSK.TTF , ItalicFont = FZKTK.TTF ] { FZSSK.TTF } + \setCJKsansfont [ BoldFont = FZHTK.TTF ] { FZXH1K.TTF } + \setCJKmonofont { FZFSK.TTF } + \setCJKfamilyfont { zhsong } [ BoldFont = FZXBSK.TTF ] { FZSSK.TTF } + \setCJKfamilyfont { zhhei } { FZHTK.TTF } + \setCJKfamilyfont { zhkai } { FZKTK.TTF } + \setCJKfamilyfont { zhfs } { FZFSK.TTF } + \setCJKfamilyfont { zhli } { FZLSK.TTF } + \setCJKfamilyfont { zhyou } [ BoldFont = FZY3K.TTF ] { FZY1K.TTF } + \ctex_punct_set:n { founder } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_family:nn { \CJKsfdefault } { zhheil } + \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + \ctex_punct_map_bfseries:nn { \CJKrmdefault , zhsong } { zhsongb } + \ctex_punct_map_bfseries:nn { \CJKsfdefault } { zhhei } + \ctex_punct_map_bfseries:nn { zhyou } { zhyoub } + } + { + \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhfounderfonts } + \ctex_punct_set:n { founder } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + } + { \ctex_fontset_error:n { founder } } + } + { + \setCJKmainfont + [ BoldFont = FZXiaoBiaoSong-B05 , ItalicFont = FZKai-Z03 ] { FZShuSong-Z01 } +% \end{macrocode} +% +% 在 WPS For Linux 附带的 5.00 版和家庭版 5.20 版的“方正细黑一\_GBK”的字体名称 +% 是 |FZXiHeiI-Z08|。但在网上发现不少文档和资料都是 \verb*|FZXiHei I-Z08|,而在 +% 官方资料《2013 方正字库字体样张》中对应的英文名字是 \verb*|FZXiHei I|。可以用 +% Postscript 名字 |FZXH1K--GBK1-0| 来统一。经测试时发现(WPS 中的字体),\XeTeX{} +% 找该字体时会出现明显的延迟,而用字体文件名 |FZXH1K.TTF| 又可能会出现大小写问题, +% 遂采用汉字名称。由于 \pkg{luaotfload} 不支持汉字名称,故使用 Postscript 名字, +% 速度不受影响。 +% \begin{macrocode} + \setCJKsansfont [ BoldFont = FZHei-B01 ] + { \xetex_if_engine:TF { 方正细黑一_GBK } { FZXH1K--GBK1-0 } } + \setCJKmonofont { FZFangSong-Z02 } + \setCJKfamilyfont { zhsong } [ BoldFont = FZXiaoBiaoSong-B05 ] { FZShuSong-Z01 } + \setCJKfamilyfont { zhhei } { FZHei-B01 } + \setCJKfamilyfont { zhkai } { FZKai-Z03 } + \setCJKfamilyfont { zhfs } { FZFangSong-Z02 } + \setCJKfamilyfont { zhli } { FZLiShu-S01 } + \setCJKfamilyfont { zhyou } [ BoldFont = FZZhunYuan-M02 ] { FZXiYuan-M01 } + } +% \end{macrocode} +% +% \begin{macrocode} +% +%<*ubuntu> +% \end{macrocode} +% +% \subsubsection{\pkg{ctex-fontset-ubuntu.def}} +% +% 以下根据 Ubuntu 12.04 的中文字体情况设置。CMap 不清楚应该是什么,指定为 +% UniGB-UTF16-H 还是有警告: +% \begin{verbatim} +% ** WARNING ** UCS-4 TrueType cmap table... +% \end{verbatim} +% 需要注意的是 \file{uming.ttc} 和 \file{ukai.ttc} 看起来像有四种字形的样子,但 +% 其实只有“令”和“骨”这区区两个字有新字形,其余都取旧字形^^A +% \footnote{\url{http://www.freedesktop.org/wiki/Software/CJKUnifonts/Download/}}。 +% \begin{macrocode} +\pdftex_if_engine:TF + { + \ctex_zhmap_case:nnn + { + \setCJKmainfont + [ BoldFont = wqy-zenhei.ttc , ItalicFont = ukai.ttc ] { uming.ttc } + \setCJKsansfont { wqy-zenhei.ttc } + \setCJKmonofont { uming.ttc } + \setCJKfamilyfont { zhsong } { uming.ttc } + \setCJKfamilyfont { zhhei } { wqy-zenhei.ttc } + \setCJKfamilyfont { zhkai } { ukai.ttc } + \ctex_punct_set:n { ubuntu } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } + \ctex_punct_map_family:nn { \CJKttdefault } { zhsong } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + } + { + \ctex_load_zhmap:nnnn { rm } { zhhei } { zhsong } { zhubuntufonts } + \ctex_punct_set:n { ubuntu } + \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } + \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } + \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } + } + { \ctex_fontset_error:n { ubuntu } } + } + { + \setCJKmainfont [ ItalicFont = AR~PL~UKai~CN ] { AR~PL~UMing~CN } + \setCJKsansfont { WenQuanYi~Zen~Hei } + \setCJKmonofont { AR~PL~UMing~CN } + \setCJKfamilyfont { zhsong } { AR~PL~UMing~CN } + \setCJKfamilyfont { zhhei } { WenQuanYi~Zen~Hei } + \setCJKfamilyfont { zhkai } { AR~PL~UKai~CN } + } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{中文字体命令} +% +% \begin{macrocode} +%<*!windows> +% \end{macrocode} +% +% \begin{macrocode} +\NewDocumentCommand \songti { } { \CJKfamily { zhsong } } +\NewDocumentCommand \heiti { } { \CJKfamily { zhhei } } +%\NewDocumentCommand \fangsong { } { \CJKfamily { zhfs } } +\NewDocumentCommand \kaishu { } { \CJKfamily { zhkai } } +%<*windowsnew|windowsold|founder> +\NewDocumentCommand \lishu { } { \CJKfamily { zhli } } +\NewDocumentCommand \youyuan { } { \CJKfamily { zhyou } } +% +%\NewDocumentCommand \yahei { } { \CJKfamily { zhyahei } } +% \end{macrocode} +% +% \begin{macrocode} +% +% +%<*zhmap> +% \end{macrocode} +% +% \subsubsection{\pkg{zhmetrics} 的字体映射} +% +% 确认 \tn{catcode},没有重复载入检查。 +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode 35=6 % # + \catcode123=1 % { + \catcode125=2 % } + \toks0{\endlinechar=\the\endlinechar\relax}% + \toks2{\endlinechar=13 }% + \def\x#1 #2 {% + \toks0\expandafter{\the\toks0 \catcode#1=\the\catcode#1\relax}% + \toks2\expandafter{\the\toks2 \catcode#1=#2 }}% + \x 13 5 % carriage return + \x 32 10 % space + \x 35 6 % # + \x 40 12 % ( + \x 41 12 % ) + \x 45 12 % - + \x 46 12 % . + \x 47 12 % / + \x 58 12 % : + \x 60 12 % < + \x 61 12 % = + \x 64 11 % @ + \x 91 12 % [ + \x 93 12 % ] + \x 123 1 % { + \x 125 2 % } + \edef\x#1{\endgroup% + \edef\noexpand#1{% + \the\toks0 % + \let\noexpand\noexpand\noexpand#1% + \noexpand\noexpand\noexpand\undefined% + \noexpand\noexpand\noexpand\endinput}% + \the\toks2}% +\expandafter\x\csname ctex@zhmap@endinput\endcsname +% \end{macrocode} +% +% \begin{macrocode} +\input ifpdf.sty\relax +% \end{macrocode} +% +% 提供非 \LaTeX{} 格式下的 \tn{ProvidesFile}。 +% \begin{macrocode} +\begingroup +\expandafter\ifx\csname ProvidesFile\endcsname\relax + \long\def\x#1\ProvidesFile#2[#3]{% + #1% + \immediate\write-1{File: #2 #3}% + \expandafter\xdef\csname ver@#2\endcsname{#3}} + \expandafter\x% +\fi +\endgroup +% \end{macrocode} +% +% \paragraph{\pkg{zhwindowsfonts.tex}} +% +% \begin{macrocode} +%<*windows> +\ProvidesFile{zhwindowsfonts.tex}% + [2014/06/03 v2.0 Windows font map loader for pdfTeX and DVIPDFMx (CTEX)] + +\ifpdf + \pdfmapline{=gbk@UGBK@ +% \end{macrocode} +% +% \paragraph{\pkg{zhadobefonts.tex}} +% +% \begin{macrocode} +%<*adobe> +\ProvidesFile{zhadobefonts.tex}% + [2014/06/03 v2.0 Adobe font map loader for DVIPDFMx (CTEX)] + +\ifpdf +%% pdfTeX does not support OTF fonts + +\else + \special{pdf:mapline gbk@UGBK@ UniGB-UTF16-H AdobeSongStd-Light.otf} + \special{pdf:mapline gbksong@UGBK@ UniGB-UTF16-H AdobeSongStd-Light.otf} + \special{pdf:mapline gbkkai@UGBK@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf} + \special{pdf:mapline gbkhei@UGBK@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf} + \special{pdf:mapline gbkfs@UGBK@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf} + + \special{pdf:mapline cyberb@Unicode@ UniGB-UTF16-H AdobeSongStd-Light.otf} + \special{pdf:mapline unisong@Unicode@ UniGB-UTF16-H AdobeSongStd-Light.otf} + \special{pdf:mapline unikai@Unicode@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf} + \special{pdf:mapline unihei@Unicode@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf} + \special{pdf:mapline unifs@Unicode@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf} + + \special{pdf:mapline gbksongsl@UGBK@ UniGB-UTF16-H AdobeSongStd-Light.otf -s .167} + \special{pdf:mapline gbkkaisl@UGBK@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf -s .167} + \special{pdf:mapline gbkheisl@UGBK@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf -s .167} + \special{pdf:mapline gbkfssl@UGBK@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf -s .167} + + \special{pdf:mapline unisongsl@Unicode@ UniGB-UTF16-H AdobeSongStd-Light.otf -s .167} + \special{pdf:mapline unikaisl@Unicode@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf -s .167} + \special{pdf:mapline uniheisl@Unicode@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf -s .167} + \special{pdf:mapline unifssl@Unicode@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf -s .167} + +% +% \end{macrocode} +% +% \paragraph{\pkg{zhfandolfonts.tex}} +% +% \begin{macrocode} +%<*fandol> +\ProvidesFile{zhfandolfonts.tex}% + [2014/06/03 v2.0 Fandol font map loader for DVIPDFMx (CTEX)] + +\ifpdf +%% pdfTeX does not support OTF fonts + +\else + \special{pdf:mapline gbk@UGBK@ UniGB-UTF16-H FandolSong-Regular.otf} + \special{pdf:mapline gbksong@UGBK@ UniGB-UTF16-H FandolSong-Regular.otf} + \special{pdf:mapline gbkkai@UGBK@ UniGB-UTF16-H FandolKai-Regular.otf} + \special{pdf:mapline gbkhei@UGBK@ UniGB-UTF16-H FandolHei-Regular.otf} + \special{pdf:mapline gbkfs@UGBK@ UniGB-UTF16-H FandolFang-Regular.otf} + + \special{pdf:mapline cyberb@Unicode@ UniGB-UTF16-H FandolSong-Regular.otf} + \special{pdf:mapline unisong@Unicode@ UniGB-UTF16-H FandolSong-Regular.otf} + \special{pdf:mapline unikai@Unicode@ UniGB-UTF16-H FandolKai-Regular.otf} + \special{pdf:mapline unihei@Unicode@ UniGB-UTF16-H FandolHei-Regular.otf} + \special{pdf:mapline unifs@Unicode@ UniGB-UTF16-H FandolFang-Regular.otf} + + \special{pdf:mapline gbksongsl@UGBK@ UniGB-UTF16-H FandolSong-Regular.otf -s .167} + \special{pdf:mapline gbkkaisl@UGBK@ UniGB-UTF16-H FandolKai-Regular.otf -s .167} + \special{pdf:mapline gbkheisl@UGBK@ UniGB-UTF16-H FandolHei-Regular.otf -s .167} + \special{pdf:mapline gbkfssl@UGBK@ UniGB-UTF16-H FandolFang-Regular.otf -s .167} + + \special{pdf:mapline unisongsl@Unicode@ UniGB-UTF16-H FandolSong-Regular.otf -s .167} + \special{pdf:mapline unikaisl@Unicode@ UniGB-UTF16-H FandolKai-Regular.otf -s .167} + \special{pdf:mapline uniheisl@Unicode@ UniGB-UTF16-H FandolHei-Regular.otf -s .167} + \special{pdf:mapline unifssl@Unicode@ UniGB-UTF16-H FandolFang-Regular.otf -s .167} + +% +% \end{macrocode} +% +% \paragraph{\pkg{zhfounderfonts.tex}} +% +% \begin{macrocode} +%<*founder> +\ProvidesFile{zhfounderfonts.tex}% + [2014/06/03 v2.0 Founder font map loader for pdfTeX and DVIPDFMx (CTEX)] + +\ifpdf + \pdfmapline{=gbk@UGBK@ +% \end{macrocode} +% +% \paragraph{\pkg{zhubuntufonts.tex}} +% +% \begin{macrocode} +%<*ubuntu> +\ProvidesFile{zhubuntufonts.tex}% + [2014/06/03 v2.0 Ubuntu font map loader for pdfTeX and DVIPDFMx (CTEX)] + +\ifpdf + \pdfmapline{=gbk@UGBK@ +% \end{macrocode} +% +% \begin{macrocode} +\fi + +\ctex@zhmap@endinput +% +% \end{macrocode} +% +% \subsubsection{制作 \texttt{spa} 文件} +% +% 我们通过 \XeTeX{} 的 \tn{XeTeXglyphbounds} 取得字体中标点符号的边界信息,为 +% \pkg{CJKpunct} 宏包制作 \file{spa}。 +% +% \begin{macrocode} +%<*spa> +%<*macro> +\input expl3-generic % +\ExplSyntaxOn +\xetex_if_engine:F + { + \msg_new:nn { ctex } { xetex } + { XeTeX~is~required~to~compile~this~document! } + \msg_fatal:nn { ctex } { xetex } + } +% \end{macrocode} +% +% \pkg{CJKpunct} 定义的标点符号是: +% \begin{verbatim} +% ‘“「『〔([{〈《〖【 +% —…、。,.:;!?%〕)]}〉》〗】’”」』 +% \end{verbatim} +% 注意顺序不能改变。 +% \begin{macrocode} +\seq_new:N \c_@@_punct_seq +\seq_gset_from_clist:Nn \c_@@_punct_seq + { + "2018 , "201C , "300C , "300E , "3014 , "FF08 , "FF3B , "FF5B , + "3008 , "300A , "3016 , "3010 , + "2014 , "2026 , "3001 , "3002 , "FF0C , "FF0E , "FF1A , "FF1B , + "FF01 , "FF1F , "FF05 , "3015 , "FF09 , "FF3D , "FF5D , "3009 , + "300B , "3017 , "3011 , "2019 , "201D , "300D , "300F + } +% \end{macrocode} +% +% \begin{macro}[internal]{\ctex_make_spa:nn} +% |#1| 是 \file{spa} 文件名,|#2| 是由 CJK 族名与字体构成的逗号列表。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \ctex_make_spa:nn #1#2 + { + \iow_open:Nn \g_@@_spa_iow {#1} + \clist_map_inline:nn {#2} + { \@@_write_family:nn ##1 } + \iow_close:N \g_@@_spa_iow + } +\iow_new:N \g_@@_spa_iow +\cs_new_eq:NN \MAKESPA \ctex_make_spa:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_write_family:nn #1#2 + { + \group_begin: + \tex_font:D \l_@@_punct_font = "#2" ~ at ~ 100 pt \scan_stop: + \l_@@_punct_font + \clist_clear:N \l_@@_punct_bounds_clist + \seq_map_inline:Nn \c_@@_punct_seq + { \exp_args:No \@@_save_bounds:n { \int_use:N \XeTeXcharglyph ##1 } } + \iow_now:Nx \g_@@_spa_iow + { + \token_to_str:N \ctexspadef {#1} +% \end{macrocode} +% 最后这三个逗号对 \pkg{CJKpunct} 来说是必要的。 +% \begin{macrocode} + { \l_@@_punct_bounds_clist , , , } + } + \group_end: + } +\cs_new_protected_nopar:Npn \@@_save_bounds:n #1 + { + \clist_put_right:Nx \l_@@_punct_bounds_clist + { + \@@_calc_bounds:nn { \c_one } {#1} , + \@@_calc_bounds:nn { \c_three } {#1} + } + } +\clist_new:N \l_@@_punct_bounds_clist +% \end{macrocode} +% +% \pkg{CJKpunct} 要求的格式是边界空白宽度与 1\,em 的比值的一百倍。 +% \begin{macrocode} +\cs_new_nopar:Npn \@@_calc_bounds:nn #1#2 + { + \fp_eval:n + { + round + ( + \dim_to_decimal_in_unit:nn + { 100 \XeTeXglyphbounds #1 ~ #2 } + { 1 em } + ) + } + } +\ExplSyntaxOff +% +% \end{macrocode} +% +% 下面是 \CTeX{} 定义的一些字体。 +% \begin{macrocode} +%<*make> +\input ctexspamacro % + +\MAKESPA {ctexpunct.spa} + { + {adobezhsong} {AdobeSongStd-Light} , + {adobezhhei} {AdobeHeitiStd-Regular} , + {adobezhkai} {AdobeKaitiStd-Regular} , + {adobezhfs} {AdobeFangsongStd-Regular} , + {fandolzhsong} {FandolSong} , + {fandolzhsongb} {FandolSong-Bold} , + {fandolzhhei} {FandolHei} , + {fandolzhheib} {FandolHei-Bold} , + {fandolzhkai} {FandolKai} , + {fandolzhfs} {FandolFang} , + {founderzhsong} {FZShuSong-Z01} , + {founderzhsongb} {FZXiaoBiaoSong-B05} , + {founderzhhei} {FZHei-B01} , + {founderzhheil} {FZXiHeiI-Z08} , + {founderzhkai} {FZKai-Z03} , + {founderzhfs} {FZFangSong-Z02} , + {founderzhli} {FZLiShu-S01} , + {founderzhyou} {FZXiYuan-M01} , + {founderzhyoub} {FZZhunYuan-M02} , + {ubuntuzhsong} {AR PL UMing CN} , + {ubuntuzhhei} {WenQuanYi Zen Hei} , + {ubuntuzhkai} {AR PL UKai CN} , + {windowszhsong} {SimSun} , + {windowszhhei} {SimHei} , + {windowszhkai} {KaiTi} , + {windowszhfs} {FangSong} , + {windowszhli} {LiSu} , + {windowszhyou} {YouYuan} , + {windowszhyahei} {Microsoft YaHei} , + {windowszhyaheib} {Microsoft YaHei Bold} + } + +\primitive\end +% +% +% \end{macrocode} +% +% \end{implementation} +% +% \Finale +% +\endinput -- cgit v1.2.3