% \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} % % \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} % % \changes{v2.0.2}{2015/05/16}{修复加载 \pkg{ctex} 宏包后章节标题后第一段 % 无段首缩进的问题} % 若 \pkg{ctex} 宏包与标准文档类及其衍生文档类联用,则将载入 \pkg{indentfirst} 宏包, % 实现章节标题后首个段落的段首缩进。 % \begin{macrocode} %<*!(article|book|report)> \clist_map_inline:nn { article , book , report } { \@ifclassloaded {#1} { \RequirePackage{ indentfirst } } { } } % % \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