% \iffalse meta-comment % % File: ctex-kernel.dtx % ----------------------------------------------------------------------- % Copyright (C) 2003--2026 % 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 (LPPL), either version 1.3c of * % this license or (at your option) any later version. * % The latest version of this license is in * % * % http://www.latex-project.org/lppl.txt * % * % and version 1.3c or later is part of all distributions of LaTeX * % version 2008 or later. * % * % This work has the LPPL maintenance status `maintained'. * % ----------------------------------------------------------------------- % This work consists of the files ctex.dtx, * % ctex-kernel.dtx, * % ctex-engine.dtx, * % ctex-scheme.dtx, * % ctex-auxpkg.dtx, * % ctex-fontset.dtx, * % ctexpunct.spa, * % ctxdoc.cls, * % ctxdocstrip.tex, * % ctex-zhconv.lua, * % ctex-zhconv-index.lua, * % ctex-zhconv-make.lua, * % the derived files ctex.ins, * % ctex.sty, * % ctexsize.sty, * % ctexheading.sty, * % ctexart.cls, * % ctexbook.cls, * % ctexrep.cls, * % ctexbeamer.cls, * % ctexcap.sty, * % ctexhook.sty, * % ctexpatch.sty, * % ctex-c5size.clo, * % ctex-cs4size.clo, * % ctex-heading-article.def, * % ctex-heading-book.def, * % ctex-heading-report.def, * % ctex-heading-beamer.def, * % ctexbackend.cfg, * % ctex-engine-pdftex.def, * % ctex-engine-xetex.def, * % ctex-engine-luatex.def, * % ctex-engine-aptex.def, * % ctex-engine-uptex.def, * % ctex-name-utf8.cfg, * % ctex-name-gbk.cfg, * % ctex.cfg, * % ctexopts.cfg, * % ctex-scheme-plain.def, * % ctex-scheme-plain-article.def, * % ctex-scheme-plain-book.def, * % ctex-scheme-plain-report.def, * % ctex-scheme-plain-beamer.def, * % ctex-scheme-chinese.def, * % ctex-scheme-chinese-article.def, * % ctex-scheme-chinese-book.def, * % ctex-scheme-chinese-report.def, * % ctex-scheme-chinese-beamer.def, * % ctex-fontset-adobe.def, * % ctex-fontset-fandol.def, * % ctex-fontset-founder.def, * % ctex-fontset-hanyi.def, * % ctex-fontset-mac.def, * % ctex-fontset-macnew.def, * % ctex-fontset-macold.def, * % ctex-fontset-ubuntu.def, * % ctex-fontset-windows.def, * % c19rm.fd, * % c19sf.fd, * % c19tt.fd, * % c70rm.fd, * % c70sf.fd, * % c70tt.fd, * % jy2zhrm.fd, * % jy2zhsf.fd, * % jy2zhtt.fd, * % jt2zhrm.fd, * % jt2zhsf.fd, * % jt2zhtt.fd, * % ctexspa.def, * % translator-theorem-dictionary-ChineseUTF8.dict, * % translator-theorem-dictionary-ChineseGBK.dict, * % ctex-spa-make.tex, * % ctex-spa-macro.tex, * % ctex-zhmap-adobe.tex, * % ctex-zhmap-fandol.tex, * % ctex-zhmap-founder.tex, * % ctex-zhmap-hanyi.tex, * % ctex-zhmap-mac.tex, * % ctex-zhmap-ubuntu.tex, * % ctex-zhmap-windows.tex, * % the documentation files ctex.pdf, * % and README.md. * % ----------------------------------------------------------------------- % * % Any modification of this file should ensure that the copyright and * % license information is placed in the derived files. * % * % ----------------------------------------------------------------------- % %<*!driver> %\NeedsTeXFormat{LaTeX2e}[2026/06/01] %\input{ctexbackend.cfg} %\RequirePackage{expl3} %<+!driver>\GetIdInfo $Id: ctex-kernel.dtx 2.6.2 2026-07-06 20:43:36 +0800 dbfd7c43 Mingyu Hsia $ % {Chinese adapter in LaTeX (CTEX)} %\ProvidesExplPackage{ctex} % {Chinese font size definition (CTEX)} %\ProvidesExplPackage{ctexsize} % {Heading style modification (CTEX)} %\ProvidesExplPackage{ctexheading} % {Chinese adapter for class article (CTEX)} %\ProvidesExplClass{ctexart} % {Chinese adapter for class book (CTEX)} %\ProvidesExplClass{ctexbook} % {Chinese adapter for class report (CTEX)} %\ProvidesExplClass{ctexrep} % {Chinese adapter for class beamer (CTEX)} %\ProvidesExplClass{ctexbeamer} % {c5size option (CTEX)} %\ProvidesExplFile{ctex-c5size.clo} % {cs4size option (CTEX)} %\ProvidesExplFile{ctex-cs4size.clo} % {Heading modification for article (CTEX)} %\ProvidesExplFile{ctex-heading-article.def} % {Heading modification for book (CTEX)} %\ProvidesExplFile{ctex-heading-book.def} % {Heading modification for report (CTEX)} %\ProvidesExplFile{ctex-heading-report.def} % {Heading modification for beamer (CTEX)} %\ProvidesExplFile{ctex-heading-beamer.def} % {\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} % % % \fi % % \begin{implementation} % % \paragraph*{\fbox{\file{\jobname-kernel.dtx}}} % % \begin{macrocode} %<@@=ctex> % \end{macrocode} % % \changes{v2.6.2}{2026/07/02}{订正 \file{ctex-heading-*.def} 中 % \cs{ProvidesExplFile} 使用与实际文件名不匹配的 \file{ctex-*.def}。} % \changes{v2.5.9}{2022/05/27}{设置消息模块的名字和类型。} % \changes{v2.5.10}{2022/06/10}{更新一些内部函数。} % \changes{v2.5.10}{2022/07/08}{不直接依赖 \pkg{xparse} 和 \pkg{l3keys2e}。} % % \begin{macrocode} %<*class|style> \cs_if_exist:NF \NewDocumentCommand { \RequirePackage { xparse } } %\prop_gput:Nnn \g_msg_module_type_prop { ctex } { Class } %
\prop_gput:Nnn \g_msg_module_name_prop { ctex } { ctexart } %\prop_gput:Nnn \g_msg_module_name_prop { ctex } { ctexbook } %\prop_gput:Nnn \g_msg_module_name_prop { ctex } { ctexrep } %\prop_gput:Nnn \g_msg_module_name_prop { ctex } { ctexbeamer } %\prop_gput:Nnn \g_msg_module_name_prop { ctex } { ctexsize } %\prop_gput:Nnn \g_msg_module_name_prop { ctex } { ctexheading } % % \end{macrocode} % % \begin{macrocode} %<*class|ctex> % \end{macrocode} % % \changes{v2.3}{2015/12/20}{与 \LaTeXiii{} (2015/12/20) 同步。} % \changes{v2.4.10}{2017/07/19}{常数 \cs{c_minus_one} 已过时。} % \changes{v2.4.10}{2017/07/22}{使用 \texttt{lazy} 函数对 Boolean 表达式 % 进行最小化运算(\LaTeXiii{} 2017/07/19)。} % \changes{v2.6.0}{2024/04/20}{提升 \LaTeXiii{} 版本至 2022/10/09。} % \changes{v2.6.0}{2026/05/03}{提升 \LaTeXiii{} 最低版本要求至 2025/10/09。} % % 检查 \pkg{expl3} 的版本。 % \begin{macrocode} \msg_new:nnnn { ctex } { l3-too-old } { Support~package~`#1'~too~old. } { Please~update~an~up-to-date~version~of~the~bundles\\\\ `l3kernel'~and~`l3packages'\\\\ using~your~TeX~package~manager~or~from~CTAN. } \@ifpackagelater { expl3 } { 2025/10/09 } { } { \msg_error:nnn { ctex } { l3-too-old } { expl3 } } % \end{macrocode} % % \begin{variable}{\c_@@_engine_str,\c_@@_engine_file_str} % 引擎检查。目前 \LaTeXiii{} 将 \ApTeX{} 识别为 \upTeX。 % \begin{macrocode} \str_const:Ne \c_@@_engine_str { \cs_if_exist:NTF \ngostype { aptex } { \c_sys_engine_str } } \msg_new:nnnn { ctex } { engine-not-supported } { Engine~`#1'~is~not~yet~supported,~ctex~will~abort! } { You~can~switch~to~xelatex,~lualatex,~pdflatex,~uplatex,~or~aplatex. } \file_if_exist:nTF { ctex-engine- \c_@@_engine_str .def } { \str_const:Ne \c_@@_engine_file_str { ctex-engine- \c_@@_engine_str .def } } { \msg_critical:nne { ctex } { engine-not-supported } { \c_@@_engine_str } } % \end{macrocode} % \end{variable} % % \begin{macrocode} % % \end{macrocode} % % \changes{v2.5}{2020/04/19} % {处理 \cs{ctex_file_input:n} 在 \pkg{ctexsize} 中未定义的错误。} % \changes{v2.5}{2020/04/21}{在 \pkg{ctexsize} 也载入 \pkg{fix-cm}。} % % \begin{macrocode} %<*class|ctex|ctexheading|ctexsize> % \end{macrocode} % % \pkg{ctexsize} 也要载入 \pkg{fix-cm} 包解决传统 cm 字体字号缺失的问题。 % \begin{macrocode} %\RequirePackage { ctexhook , ctexpatch } %\RequirePackage { fix-cm } % \end{macrocode} % % 宏包载入检查。 % \begin{macrocode} %<*class|ctex> %<*class> \ctex_disable_package:n { ctex } \ctex_disable_package:n { ctexcap } % \ctex_disable_package:n { ctexsize } \ctex_disable_package:n { ctexheading } % % \end{macrocode} % % \changes{v2.5.7}{2021/06/04}{兼容 \LaTeX \ 2021/06/01 的字体钩子。} % % \begin{variable}{\c_@@_everysel_loaded_bool} % \LaTeX \ 2021-06-01 以后的版本内建了 \pkg{everysel} 包的功能。 % \begin{macrocode} %<*!ctexsize> %<*!ctexheading> \ctex_if_format_at_least:nTF { 2021/06/01 } { \bool_const:Nn \c_@@_everysel_loaded_bool { \c_false_bool } } { \RequirePackage { everysel } \bool_const:Nn \c_@@_everysel_loaded_bool { \c_true_bool } } % % \end{macrocode} % \end{variable} % % \subsection{内部函数与变量} % % \begin{variable}{\l_@@_tmp_tl,\l_@@_tmp_int,\l_@@_tmp_box,\l_@@_tmp_dim} % 临时变量。 % \begin{macrocode} \tl_clear_new:N \l_@@_tmp_tl \int_new:N \l_@@_tmp_int \box_new:N \l_@@_tmp_box %\dim_new:N \l_@@_tmp_dim % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\ctex_define_option:n, % \ctex_define:n,\ctex_set:n,\ctex_set:nn} % 在宏包内部使用的键值选项定义、设置命令。 % \begin{macrocode} % \cs_new_protected:Npn \ctex_define_option:n { \keys_define:nn { ctex / option } } %<*!ctexsize> \cs_new_protected:Npn \ctex_define:n { \keys_define:nn { ctex } } \cs_new_protected:Npn \ctex_set:n { \keys_set:nn { ctex } } \cs_new_protected:Npn \ctex_set:nn #1 { \keys_set:nn { ctex / #1 } } % \end{macrocode} % \end{macro} % % \changes{v2.5.3}{2020/06/06}{正确关闭和恢复 \LaTeXiii 语法环境。} % \changes{v2.5.4}{2020/08/02}{应用 \pkg{l3cctab}。} % \changes{v2.5.5}{2020/10/17}{放弃应用 \pkg{l3cctab}。} % % \begin{macro}[int]{\ctex_scheme_input:n} % 输入 \opt{scheme} 文件。先查找当前文档类下的 \meta{scheme},找不到再查找一般的文件。 % \begin{macrocode} \cs_new_protected:Npn \ctex_scheme_input:n #1 { \ctex_push_file: \tl_if_exist:NTF \c_@@_class_tl { \file_if_exist_input:nF { ctex-scheme- #1 - \c_@@_class_tl .def } { \file_input:n { ctex-scheme- #1 .def } } } { \file_input:n { ctex-scheme- #1 .def } } \ctex_pop_file: } \cs_generate_variant:Nn \ctex_scheme_input:n { o } % \end{macrocode} % \end{macro} % % \begin{variable}{\g_@@_section_depth_int} % 若大于 |3|,则 \tn{paragraph} 和 \tn{subparagraph} 标题单独占一行;若为 |3|,则 % \tn{paragraph} 单独占一行。 % \begin{macrocode} %<*!beamer> \int_new:N \g_@@_section_depth_int \int_gset:Nn \g_@@_section_depth_int { 2 } % % \end{macrocode} % \end{variable} % % \begin{macrocode} % % %<*class|ctex> % \end{macrocode} % % 对旧版本的宏包给出错误信息。 % \begin{macrocode} \msg_new:nnnn { ctex } { package-too-old } { Support~package~`#1'~too~old. } { Please~update~an~up-to-date~version~of~the~package~`#1'\\ using~your~TeX~package~manager~or~from~CTAN. } % \end{macrocode} % % \changes{v2.1}{2015/05/25}{不依赖 \pkg{ifpdf} 宏包。} % % \begin{macro}[int]{\ifctexpdf} % 在 \pkg{zhmetrics} 映射文件中使用。 % \begin{macrocode} \sys_if_output_pdf:TF { \cs_new_eq:NN \ifctexpdf \if_true: } { \cs_new_eq:NN \ifctexpdf \if_false: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_if_preamble:TF} % 测试是否在 \LaTeXe{} 的导言区。在宏包内部初始为真,文档最开始位置再设置为假。 % 注意,钩子 \cs{ctex_after_end_preamble:n} 在 \tn{AtBeginDocument} 之后执行, % 可以与 \tn{@onlypreamble} 的行为一致。 % \begin{macrocode} \cs_new_eq:NN \ctex_if_preamble:TF \use_i:nn \ctex_after_end_preamble:n { \cs_set_eq:NN \ctex_if_preamble:TF \use_ii:nn } % \end{macrocode} % \end{macro} % % \changes{v2.3}{2015/09/17}{代码实现避免使用 \tn{lowercase} 技巧(Joseph Wright)。} % % \changes{v2.4.16}{2019/05/11}{允许设置 \texttt{autoindent} 为 $0$。} % % \begin{macro}[int]{\ctex_set_default_ccwd:Nn} % 若参数 |#2| 带长度单位,则设置它为 |tl| 变量 |#1| 的值,否则以 \tn{ccwd} 为单位。 % \begin{macrocode} \cs_new_protected:Npn \ctex_set_default_ccwd:Nn #1#2 { \tl_set:Ne #1 { \@@_default_ccwd_aux:n {#2} } } \cs_new:Npn \@@_default_ccwd_aux:n #1 { \exp_not:n {#1} \exp_after:wN \@@_default_ccwd_aux:w \dim_use:N \tex_dimexpr:D #1 pt \scan_stop: \q_stop } \exp_last_unbraced:NNNNo \cs_new:Npn \@@_default_ccwd_aux:w #1 { \tl_to_str:n { pt } } #2 \q_stop { \tl_if_empty:nT {#2} { \ccwd } } % \end{macrocode} % \end{macro} % % \begin{variable}{\g_@@_encoding_tl} % 所有引擎下默认编码均设为 UTF-8,初始值为空,\tn{ProcessKeysOptions} 再判断。 % \begin{macrocode} \tl_new:N \g_@@_encoding_tl % \end{macrocode} % \end{variable} % % \begin{variable}{\g_@@_zhmCJK_bool} % 是否使用 \pkg{zhmCJK} 宏包。 % \begin{macrocode} \bool_new:N \g_@@_zhmCJK_bool % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_autoindent_tl} % 保存 \opt{autoindent} 选项的值,空值表示不自动调整首行缩进。 % \begin{macrocode} \tl_new:N \l_@@_autoindent_tl % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\ctex_if_autoindent_touched:F} % 检查 \opt{autoindent} 选项是否被用户设置。 % \begin{macrocode} \cs_new_eq:NN \ctex_if_autoindent_touched:F \use:n % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_zhmap_case:nnn} % 参数 |#1| 是 \pkg{zhmCJK} 的内容,|#2| 是 \pkg{zhmetrics}。 % \begin{macrocode} \cs_new_eq:NN \ctex_zhmap_case:nnn \use_ii:nnn % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_at_end:n} % 区分 \tn{AtEndOfClass} 和 \tn{AtEndOfPackage},虽然它们的意思都是一样的。 % \begin{macrocode} %\cs_new_protected:Npn \ctex_at_end:n { \AtEndOfClass } %\cs_new_protected:Npn \ctex_at_end:n { \AtEndOfPackage } % \end{macrocode} % \end{macro} % % \begin{variable}{\ctex_load_std_class:n,\g_@@_std_options_clist} % 保存传递给标准文档类的选项。 % 使用 \tn{PassOptionsToClass} 是为了预防可能存在的选项冲突,选项列表展开后再传递。 % \begin{macrocode} %<*class> \cs_new_protected:Npn \ctex_load_std_class:n #1 { \tl_const:Nn \c_@@_class_tl {#1} \exp_args:No \PassOptionsToClass { \g_@@_std_options_clist } {#1} \LoadClass {#1} } \clist_new:N \g_@@_std_options_clist % % \end{macrocode} % \end{variable} % % 对无效选项给出警告。 % \changes{v2.6.0}{2026/05/02}{使用 \cs{l_keys_key_str} 和 % \cs{l_keys_choice_str} 替代已废弃的 \texttt{\_tl} 版本(\#806)。} % \begin{macrocode} \msg_new:nnn { ctex } { invalid-option } { Option~`\l_keys_key_str'~is~invalid~in~current~mode. } \msg_new:nnn { ctex } { invalid-value } { Value~`#1'~is~invalid~for~the~key~`\l_keys_key_str'. } \msg_new:nnn { ctex } { CJKecglue-unsupported } { `experiment/CJKecglue'~is~not~supported~by~the~current~engine. } % \end{macrocode} % % \begin{macro}[int]{\ctex_deprecated_option:nn, % \ctex_set_deprecated_option:n,\ctex_deprecated_command:Nn} % 对过时选项或命令给出警告。 % \begin{macrocode} \cs_new_protected:Npn \ctex_deprecated_option:n { \msg_warning:nnn { ctex } { deprecated-option } } \cs_new_protected:Npn \ctex_set_deprecated_option:n #1 { \ctex_deprecated_option:n { Option~`#1'~is~set. } \ctex_set:nn { option } {#1} } \cs_new_protected:Npn \ctex_deprecated_command:Nn #1#2 { \msg_warning:nnee { ctex } { deprecated-command } { \token_to_str:N #1 } { \exp_not:n {#2} } } \msg_new:nnn { ctex } { deprecated-option } { Option~`\l_keys_key_str'~is~deprecated.\\ #1 } \msg_new:nnn { ctex } { deprecated-command } { Command~`#1'~is~deprecated.\\ #2 } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \begin{variable}{\g_@@_font_size_int} % |0| 表示修改默认字体大小为五号,|1| 为小四号,大于 1 则不作修改。初始值 |-1| % 表示 \opt{zihao} 选项未初始化,会在将来根据文档类决定初值。 % \begin{macrocode} %<*class|ctex|ctexsize> \int_new:N \g_@@_font_size_int \int_gset:Nn \g_@@_font_size_int { -1 } % % \end{macrocode} % \end{variable} % % \subsection{宏包选项} % % \changes{v2.3}{2015/09/25} % {\texttt{.value_required:} 和 \texttt{.value_forbidden:} 已过时。} % % \begin{macrocode} %<*class|style> \ctex_define_option:n { % % \end{macrocode} % % \changes{v2.6.0}{2026/05/04}{新增实验性 % \opt{experiment/font-size-system} 选项(\#543)。} % \changes{v2.6.0}{2026/05/04}{将 \opt{experiment/font-size-system} % 的 \opt{traditional} 选项更名为 \opt{letterpress}(\#813)。} % \changes{v2.6.0}{2026/06/23}{文档:在标准字体命令、中文字号表附近提示 % \opt{experiment/font-size-system} 的影响;说明 % \opt{letterpress} 只是金属活字排印字号体系之一(\#871)。} % % \begin{macro}{experiment/font-size-system} % 选择字号系统。预设有 |word| 和 |letterpress| 两种字号系统,用户也可以自定义。 % \begin{macrocode} %<*class|ctex|ctexsize> experiment / font-size-system .tl_gset:N = \g_@@_font_size_system_tl , experiment / font-size-system .initial:n = { word } , experiment / font-size-system .value_required:n = true , % % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/05/06}{新增 \opt{zihao} 选项。} % \changes{v2.0}{2015/05/06}{\opt{c5size}, \opt{cs4size} 是过时选项。} % % \begin{macro}{zihao} % \changes{v2.4.1}{2016/05/13}{不允许无参 \opt{zihao} 选项。} % \begin{macrocode} %<*class|ctex|ctexsize> zihao .choice: , zihao .value_required:n = true , zihao / 5 .code:n = { \int_gset:Nn \g_@@_font_size_int { 0 } } , zihao / -4 .code:n = { \int_gset:Nn \g_@@_font_size_int { 1 } } , zihao / false .code:n = { \int_gset:Nn \g_@@_font_size_int { 2 } } , % } % %<*class|ctex> c5size .code:n = { \ctex_set_deprecated_option:n { zihao = 5 } } , cs4size .code:n = { \ctex_set_deprecated_option:n { zihao = -4 } } , c5size .value_forbidden:n = true , cs4size .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/04/23}{新增 \opt{linespread} 选项。} % % \begin{macro}{linespread} % 行距初始值为标志 \texttt{nan},用于检查用户是否设置了 \opt{linespread} 选项。 % \begin{macrocode} linespread .fp_set:N = \l_@@_line_spread_fp , linespread .initial:n = { \c_nan_fp } , linespread .value_required:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/13}{新增 \opt{autoindent} 选项。} % % \begin{macro}{autoindent} % 自动调整段落的首行缩进功能。 % \begin{macrocode} autoindent .choice: , autoindent .default:n = { true } , autoindent / true .code:n = { \tl_set:Nn \l_@@_autoindent_tl { 2 \ccwd } \cs_set_eq:NN \ctex_if_autoindent_touched:F \use_none:n } , autoindent / false .code:n = { \tl_clear:N \l_@@_autoindent_tl \cs_set_eq:NN \ctex_if_autoindent_touched:F \use_none:n } , autoindent / unknown .code:n = { \ctex_set_default_ccwd:Nn \l_@@_autoindent_tl {#1} \cs_set_eq:NN \ctex_if_autoindent_touched:F \use_none:n } , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/03/21}{\opt{indent}, \opt{noindent} 是过时选项。} % \begin{macro}{indent} % 仅为兼容性保留,已过时。 % \begin{macrocode} indent .code:n = { \ctex_deprecated_option:n { The~functionality~has~been~removed.\\ It's~better~to~set~the~heading~styles~via~`afterindent'~option. } } , indent .value_forbidden:n = true , noindent .code:n = { \ctex_deprecated_option:n { The~functionality~has~been~removed.\\ It's~better~to~set~the~heading~styles~via~`afterindent'~option. } } , noindent .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.5}{2019/11/10}{所有引擎下默认编码均设为 UTF-8。} % % \begin{macro}{GBK,UTF8} % 文档编码,默认为 UTF-8。 % \begin{macrocode} GBK .code:n = { \sys_if_engine_pdftex:TF { \tl_gset:Nn \g_@@_encoding_tl { GBK } } { \msg_warning:nn { ctex } { invalid-option } \tl_gset:Nn \g_@@_encoding_tl { UTF8 } } } , UTF8 .code:n = { \tl_gset:Nn \g_@@_encoding_tl { UTF8 } } , GBK .value_forbidden:n = true , UTF8 .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/08}{新增 \opt{fontset} 选项。} % \changes{v2.0}{2015/03/21}{\opt{nofonts}, \opt{adobefonts}, \opt{winfonts} % 是过时选项。} % % \begin{macro}{fontset} % 初始值为空。若用户未指定,则根据操作系统载入对应字体配置,可以区分 Windows、 % macOS 和其他。 % \begin{macrocode} fontset .tl_gset:N = \g_@@_fontset_tl , nofonts .code:n = { \ctex_set_deprecated_option:n { fontset = none } } , adobefonts .code:n = { \ctex_set_deprecated_option:n { fontset = adobe } } , winfonts .code:n = { \ctex_set_deprecated_option:n { fontset = windows } } , nofonts .value_forbidden:n = true , winfonts .value_forbidden:n = true , adobefonts .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/08}{新增 \opt{zhmCJK} 支持选项。} % \changes{v2.0}{2015/03/22}{\opt{nozhmap} 是过时选项。} % % \begin{macro}{zhmap} % \begin{macrocode} zhmap .choice: , zhmap .default:n = { true } , zhmap / zhmCJK .code:n = { \bool_gset_true:N \g_@@_zhmCJK_bool \cs_gset_eq:NN \ctex_zhmap_case:nnn \use_i:nnn } , zhmap / true .code:n = { \bool_gset_false:N \g_@@_zhmCJK_bool \cs_gset_eq:NN \ctex_zhmap_case:nnn \use_ii:nnn } , zhmap / false .code:n = { \bool_gset_false:N \g_@@_zhmCJK_bool \cs_gset_eq:NN \ctex_zhmap_case:nnn \use_iii:nnn } , nozhmap .code:n = { \ctex_set_deprecated_option:n { zhmap = false } } , nozhmap .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/04/11}{\opt{punct} 选项可以设置标点格式。} % \changes{v2.0}{2015/03/21}{\opt{nopunct} 是过时选项。} % % \begin{macro}{punct} % 设置标点符号输出格式。 % \begin{macrocode} punct .tl_set:N = \l_@@_punct_tl , punct .default:n = { quanjiao } , punct .initial:n = { quanjiao } , nopunct .code:n = \ctex_set_deprecated_option:n { punct = plain } , nopunct .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/03/22}{\opt{nospace} 是过时选项。} % \begin{macro}{space} % \begin{macrocode} space .choices:nn = { true , auto , false } { \ctex_at_end:n { \ctex_set:n { space = #1 } } } , space .default:n = { true } , nospace .code:n = { \ctex_deprecated_option:nn { space = false } } , nospace .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/08}{\pkg{ctex} 宏包新增 \opt{heading} 选项。} % % \begin{macro}{heading} % \begin{macrocode} heading .bool_set:N = \l_@@_heading_bool , % \end{macrocode} % \end{macro} % % \begin{macrocode} % %<*class|ctex|ctexheading> % \end{macrocode} % % \begin{macro}{sub3section,sub4section} % \begin{macrocode} %<*!beamer> sub3section .code:n = { \int_gset:Nn \g_@@_section_depth_int { 3 } } , sub4section .code:n = { \int_gset:Nn \g_@@_section_depth_int { 4 } } , sub3section .value_forbidden:n = true , sub4section .value_forbidden:n = true , % % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/04/15}{新增 \opt{scheme} 选项,并将 \opt{cap} 和 \opt{nocap} % 列为过时选项。} % % \begin{macro}{scheme} % \begin{macrocode} scheme .tl_set:N = \l_@@_scheme_tl , %<*ctexheading> scheme .default:n = { plain } , scheme .initial:n = { plain } } % %<*!ctexheading> scheme .default:n = { chinese } , scheme .initial:n = { chinese } , % % \end{macrocode} % \end{macro} % % \begin{macrocode} % %<*class|ctex> % \end{macrocode} % % \begin{macro}{cap,nocap} % \opt{cap} 和 \opt{nocap} 是过时选项。 % \begin{macrocode} cap .code:n = { \ctex_set_deprecated_option:n { scheme = chinese } } , nocap .code:n = { \ctex_set_deprecated_option:n { scheme = plain } } , cap .value_forbidden:n = true , nocap .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/04/20}{\opt{hyperref} 成为过时选项,原选项功能总是打开。} % \changes{v2.0}{2015/04/20}{\opt{fancyhdr} 成为过时选项,原选项功能总是打开。} % \changes{v2.0}{2015/04/20}{\opt{fntef} 成为过时选项,原选项功能总是打开。} % % 以下三项都是过时的兼容选项,它们会载入有关宏包。 % % \begin{macro}{fntef} % \changes{v2.5}{2019/11/10}{仅在该选项启用时会载入 \pkg{CJKfntef} 或 % \pkg{xeCJKfntef} 宏包。} % \begin{macrocode} fntef .code:n = { \sys_if_engine_xetex:TF { \ctex_deprecated_option:n { `xeCJKfntef'~package~is~loaded. } \ctex_at_end:n { \RequirePackage { xeCJKfntef } } } { \sys_if_engine_pdftex:TF { \ctex_deprecated_option:n { `CJKfntef'~package~is~loaded. } \ctex_at_end:n { \RequirePackage { CJKfntef } } } { \ctex_deprecated_option:n { Furthermore,~option~`fntef'~is~invalid~in~current~mode. } } } } , % \end{macrocode} % \end{macro} % % \begin{macro}{fancyhdr} % \begin{macrocode} fancyhdr .code:n = { \ctex_deprecated_option:n { `fancyhdr'~package~is~loaded. } \ctex_at_end:n { \RequirePackage { fancyhdr } } } , % \end{macrocode} % \end{macro} % % \begin{macro}{hyperref} % \changes{v2.1}{2015/06/03}{补充定义 \tn{hypersetup}。} % \begin{macrocode} hyperref .code:n = { \ctex_deprecated_option:n { `hyperref'~package~will~be~loaded. } \ctex_at_end:n { \cs_if_exist:NF \hypersetup { \cs_new_eq:NN \hypersetup \ctex_hypersetup:n } } \ctex_at_end_preamble:n { \RequirePackage { hyperref } } } , } % \end{macrocode} % \end{macro} % % \begin{macrocode} % %<*class|ctex|ctexsize> % \end{macrocode} % % \changes{v2.0}{2015/05/06}{兼容 \pkg{extsizes} 宏包、\cls{beamer}、\pkg{memoir} % 等提供的更多字号选项。} % \changes{v2.0.1}{2015/05/15}{修复 \opt{10pt}、\opt{11pt} 等选项无效的问题。} % \begin{macro}{10pt,11pt,12pt} % 使 \pkg{ctex} 和 \pkg{ctexsize} 可以接受文档类的全局选项,不修改默认字体大小。 % 在文档类下还将参数传给标准文档类。 % \begin{macrocode} \tl_clear_new:N \l_@@_tmp_tl \clist_map_inline:nn { 10pt , 11pt , 12pt , 8pt , 9pt , 14pt , 17pt , 20pt , 25pt , 30pt , 36pt , 48pt , 60pt } { \tl_put_right:Nn \l_@@_tmp_tl { #1 .code:n = %<*!class> { \int_gset:Nn \g_@@_font_size_int { 2 } } , % %<*class> { \int_gset:Nn \g_@@_font_size_int { 2 } \clist_gput_right:Nn \g_@@_std_options_clist {#1} } , % #1 .value_forbidden:n = true , } } \exp_args:No \ctex_define_option:n { \l_@@_tmp_tl } \tl_clear:N \l_@@_tmp_tl % \end{macrocode} % \end{macro} % % 将未知选项传给标准文档类。 % \begin{macrocode} %<*class> \ctex_define_option:n { unknown .code:n = { \clist_gput_right:No \g_@@_std_options_clist { \CurrentOption } } } % % \end{macrocode} % % 载入选项配置文件。 % \begin{macrocode} %\ctex_file_input:n { ctexopts.cfg } % % \end{macrocode} % % 处理宏包选项。 % \begin{macrocode} %<*class|style> \cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions [ ctex / option ] } { \RequirePackage { l3keys2e } \ProcessKeysOptions { ctex / option } } % % \end{macrocode} % % \pdfLaTeX{} 下,如果没有显式指定编码为 |UTF8|,则给出警告信息。 % \begin{macrocode} %<*class|ctex> \msg_new:nnn { ctex } { pdftex-utf8 } { UTF8~will~be~used~as~the~default~encoding. } \tl_if_empty:NT \g_@@_encoding_tl { \sys_if_engine_pdftex:T { \msg_warning:nn { ctex } { pdftex-utf8 } } \tl_gset:Nn \g_@@_encoding_tl { UTF8 } } % % \end{macrocode} % % \begin{macrocode} %<*class> % \end{macrocode} % % 五号字使用标准文档类的 |10pt| 字体大小设置,小四号字则使用 |12pt|。 % \begin{macrocode} \int_case:nn { \g_@@_font_size_int } { { 0 } { \clist_gput_right:Nn \g_@@_std_options_clist { 10pt } } { 1 } { \clist_gput_right:Nn \g_@@_std_options_clist { 12pt } } } % \end{macrocode} % % 载入标准文档类。 % \begin{macrocode} %<*article> \ctex_load_std_class:n { article } %
%<*book> \ctex_load_std_class:n { book } % %<*report> \ctex_load_std_class:n { report } % %<*beamer> \ctex_load_std_class:n { beamer } % % \end{macrocode} % % \begin{macrocode} %
% \end{macrocode} % % \changes{v2.1}{2015/06/16}{不再设置 \pkg{hyperref} 宏包的 \opt{colorlinks} 选项。} % % 现在处理各个引擎下的 PDF 中文书签问题。根据编译引擎与文件编码的不 % 同,\pkg{ctex} 向 \pkg{hyperref} 传递适当的参数,完成中文书签的正确设置。用 % 户仍需要自己载入 \pkg{hyperref} 宏包。 % % \begin{macro}[int]{\ctex_hypersetup:n} % 如果已经载入 \pkg{hyperref} 宏包,则直接使用其定义设置选项;否则 % \cs{ctex_hypersetup:n} 的效果与 \tn{PassOptionsToPackage} 一致,只传递宏包参 % 数。如果用户不载入 \pkg{hyperref} 宏包,相关参数即被丢弃。 % \begin{macrocode} %<*class|ctex> \@ifpackageloaded { hyperref } { \cs_new_protected:Npn \ctex_hypersetup:n #1 { \hypersetup {#1} } } { \cs_new_protected:Npn \ctex_hypersetup:n #1 { \PassOptionsToPackage {#1} { hyperref } } } % \end{macrocode} % \end{macro} % % \subsubsection{载入引擎定义文件} % % 最后载入 \ref{subsubsec:hyperref}~中的各个编译引擎的定义文件。 % \begin{macrocode} \ctex_file_input:n { \c_@@_engine_file_str } % % \end{macrocode} % % \subsection{用户设置接口} % % \changes{v2.0}{2014/03/18}{新增统一设置接口 \tn{ctexset}。} % \changes{v2.4.12}{2018/01/14} % {修正 \tn{ctexset} 在 \pkg{ctexheading} 包中无定义的错误(曾祥东)。 } % % \begin{macro}{\ctexset} % \begin{macrocode} %<*class|ctex|ctexheading> \NewDocumentCommand \ctexset { } { \ctex_set:n } % % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/03/21}{\tn{CTEXsetup}, \tn{CTEXoptions} 是过时命令。} % \begin{macro}{\CTEXsetup,\CTEXoptions} % 过时命令。 % \begin{macrocode} %<*class|ctex> \NewDocumentCommand \CTEXsetup { +O { } > { \TrimSpaces } m } { \tl_if_blank:nTF {#1} { \ctex_deprecated_command:Nn \CTEXsetup { } } { \ctex_deprecated_command:Nn \CTEXsetup { \ctexset {~#2~=~{~#1~}~}~is~set. } \ctex_set:nn {#2} {#1} } } \NewDocumentCommand \CTEXoptions { +O { } } { \tl_if_blank:nTF {#1} { \ctex_deprecated_command:Nn \CTEXoptions { } } { \ctex_deprecated_command:Nn \CTEXoptions { \ctexset {~#1~}~is~set. } \ctex_set:n {#1} } } % \end{macrocode} % \end{macro} % % \subsection{字距与缩进} % % \begin{macro}{autoindent} % \opt{autoindent} 也是可以用在正文中的选项,意义与宏包选项 |option/autoindent| 相同。 % \begin{macrocode} \ctex_define:n { 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:Npn \ctex_select_size: { \cs_if_free:NTF \size@update { \ctex_update_size: } { \selectfont } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_size:} % 在字号变化时更新 \tn{ccwd}、\tn{parindent} 和汉字间距。字距为零则恢复正常设置。 % \begin{macrocode} \cs_new_protected: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:Ne \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} % % \changes{v2.0}{2014/03/26}{新增 \opt{linestretch} 选项。} % % \begin{macro}{linestretch} % 若行宽不是汉字宽度的整数倍,自然要求伸展它们之间的差。这里设置的是在此基础上的 % 额外伸展量。初始化为一个汉字的宽度。若设置为 \tn{maxdimen},则禁用此功能。 % 参数的默认单位是汉字的宽度 \tn{ccwd}。 % \begin{macrocode} \ctex_define:n { linestretch .code:n = { \ctex_set_default_ccwd:Nn \l_@@_line_stretch_tl {#1} \ctex_select_size: } , linestretch .value_required:n = true } \tl_new:N \l_@@_line_stretch_tl \tl_set:Nn \l_@@_line_stretch_tl { \ccwd } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\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: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 { \@@_update_stretch_auxi: } { \@@_update_stretch_auxii: } } \cs_new_protected:Npn \@@_update_stretch_auxi: { \ctex_if_ccglue_touched:TF { \ctex_update_ccwd: } { \dim_set:Nn \l_@@_tmp_dim { \baselinestretch \tex_glueexpr:D \f@baselineskip \scan_stop: } \skip_set:Nn \l_@@_ccglue_skip { \c_zero_dim plus .08 \l_@@_tmp_dim } \ctex_update_ccglue: } } \cs_new_protected:Npn \@@_update_stretch_auxii: { \@@_update_stretch_auxiii: } \cs_new_protected:Npn \@@_update_stretch_auxiii: { \int_set:Nn \l_@@_tmp_int { \tex_dimexpr:D \linewidth - \ccwd - \l_@@_tmp_dim \scan_stop: } \tex_divide:D \l_@@_tmp_int \ccwd \int_compare:nNnTF \l_@@_tmp_int > \c_zero_int { \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}[int]{\ctex_update_parindent:} % 更新段落首行缩进。此函数在字号变化时调用。 % \begin{macrocode} \cs_new_protected: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:Ne \ctex_ziju:n {#1} \tex_ignorespaces:D } \cs_new_protected:Npn \ctex_ziju:n #1 { \tl_set:Ne \l_@@_ziju_tl { \fp_eval:n {#1} } \ctex_select_size: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_ziju:} % 更新字距。若字距不大于 $-1$,即 \tn{ccwd} 为非正值,则不计算伸缩值。 % 否则,首先假定汉字的宽度为正常宽度加上字距,看一行上能正常放下多少个汉字。 % \begin{macrocode} \cs_new_protected: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 < 3 { \int_sub:Nn \l_@@_tmp_int { 2 } } } \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 + 1 ) } } } { \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 { } { \ctex_deprecated_command:Nn \CTEXindent { \parindent is~set~to~2\ccwd. } \ctex_update_ccwd: \dim_set:Nn \parindent { 2 \ccwd } } \NewDocumentCommand \CTEXnoindent { } { \ctex_deprecated_command:Nn \CTEXnoindent { \parindent is~set~to~0pt. } \dim_zero:N \parindent } % \end{macrocode} % \end{macro} % % \subsection{中文数字与日期} % % 需要注意的是,\pkg{ltkeys} 设置的选项列表是 % |\@raw@opt@|\meta{\textbackslash @currname}|.|\meta{\textbackslash @currext}, % 该列表不会将 \tn{PassOptionsToPackage} 传递的选项完全展开。 % \begin{macrocode} \exp_args:Ne \PassOptionsToPackage { encoding = \g_@@_encoding_tl } { zhnumber } \RequirePackage { zhnumber } % \end{macrocode} % % \begin{macro}{\chinese} % \changes{v2.4.1}{2016/05/01}{支持 \tn{pagenumbering}。} % \begin{macrocode} \cs_new:Npn \chinese { \zhnum_counter:n } \cs_new_eq:NN \@chinese \@zhnum \cs_new_eq:NN \Chinese \chinese \cs_new_eq:NN \CTEXcounter \use_none:n % \end{macrocode} % \end{macro} % % \changes{v2.2}{2015/06/29}{给 \pkg{enumitem} 宏包注册 \tn{chinese} 和 % \tn{zhnum}。} % % 给 \pkg{enumitem} 宏包注册 \tn{chinese}、\tn{zhnum} 和 \tn{zhdig}。 % \begin{macrocode} \ctex_at_end_package:nn { enumitem } { \cs_if_free:NF \AddEnumerateCounter { \AddEnumerateCounter * { \zhnum } { \@zhnum } { 1 } \AddEnumerateCounter * { \zhdig } { \@zhdig } { 1 } \AddEnumerateCounter * { \chinese } { \@chinese } { 1 } } } % \end{macrocode} % % \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 \ctex_define:n { 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:nne { 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}{将标题汉化功能加入 \file{ctex.sty}。} % \changes{v2.4.3}{2016/08/18}{确保 \tn{proofname} 非空。} % % \begin{macro}[int]{\proofname} % \tn{proofname} 未在标准文档类中定义,需要确保它非空。 % \begin{macrocode} \tl_if_exist:NF \proofname { \tl_new:N \proofname \tl_set:Nn \proofname { Proof } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \ctex_define:n { 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 , proofname .tl_set:N = \proofname , %
bibname .tl_set:N = \refname % bibname .tl_set:N = \bibname %<*beamer> algorithmname .tl_set:N = \algorithmname , bibname .tl_set:N = \bibname , refname .tl_set:N = \refname , continuation .tl_set:N = \insertcontinuationtext % } % \end{macrocode} % % \begin{macrocode} %<*ctex> \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 \insertcontinuationtext { \ctex_define:n { algorithmname .tl_set:N = \algorithmname , bibname .tl_set:N = \bibname , refname .tl_set:N = \refname , continuation .tl_set:N = \insertcontinuationtext } } { \tl_if_exist:NTF \bibname { \ctex_define:n { bibname .tl_set:N = \bibname } } { \tl_if_exist:NTF \refname { \ctex_define:n { bibname .tl_set:N = \refname } } { \msg_warning:nn { ctex } { ctexbibname } \ctex_define:n { bibname .tl_set:N = \ctexbibname } } } } % % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{中文化的标题结构} % % 本节内容在 \CTeX{} 文档类或打开 \opt{heading} 选项下生效。 % \begin{macrocode} %<*class|heading> % \end{macrocode} % % \subsubsection{定义标题格式选项} % % \begin{variable}{\c_@@_section_headings_seq} % 保存 \tn{section} 级以下标题名字。 % \begin{macrocode} %<*article|book|report> \seq_const_from_clist:Nn \c_@@_section_headings_seq { section , subsection , subsubsection , paragraph , subparagraph } % % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_headings_seq} % 保存各级标题名字。 % \begin{macrocode} %\seq_const_from_clist:Nn \c_@@_headings_seq %<*article|book|report> { part , % chapter , section , subsection , subsubsection , paragraph , subparagraph } % % { part , section , subsection } % \end{macrocode} % \end{variable} % % \changes{v2.1}{2015/06/19}{\opt{nameformat} 可以接受章节名字为参数。} % \changes{v2.3}{2016/01/05}{修复 \opt{nameformat} 作用域问题。} % % \begin{macro}{\@@_initial_heading:n} % \begin{macrocode} \cs_new_protected:Npn \@@_initial_heading:n #1 { \tl_new:c { CTEX@pre#1 } \tl_new:c { CTEX@post#1 } \tl_const:ce { CTEXthe#1 } { \exp_not:c { CTEX@pre#1 } \exp_not:c { CTEX@the#1 } \exp_not:c { CTEX@post#1 } } \tl_const:ce { CTEX@#1name } { \group_begin: \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 } } \group_end: } } % \end{macrocode} % \end{macro} % % \changes{v2.1}{2015/05/22}{\opt{format+}, \opt{nameformat+} 等带加号的选项, % 加号与前面的文字之间可以有可选的空格。} % \changes{v2.1}{2015/06/19}{新的标题格式选项 \opt{aftertitle}。} % \changes{v2.2}{2015/06/21}{新的标题格式选项 \opt{numbering}。} % \changes{v2.2}{2015/06/27}{\opt{beforeskip} 和 \opt{afterskip} 选项的符号 % 不再有特殊意义。} % \changes{v2.2}{2015/06/27}{新的标题格式选项 \opt{afterindent}。} % \changes{v2.2}{2015/06/27}{新的标题格式选项 \opt{runin}。} % \changes{v2.4.3}{2016/06/03}{新的标题格式选项 \opt{fixskip}。} % \changes{v2.4.4}{2016/09/19}{新的标题格式选项 \opt{break}。} % \changes{v2.4.5}{2016/10/22}{新的标题格式选项 \opt{hang}。} % \changes{v2.4.5}{2016/10/25}{新的标题格式选项 \opt{tocline}。} % \changes{v2.4.11}{2017/11/21}{因上游 \pkg{l3keys} 变化,重新定义 % \opt{format\textvisiblespace+} 等带空格加号的选项。} % % \begin{macro}{\@@_def_heading_keys:n} % \begin{macrocode} \cs_new_protected:Npn \@@_def_heading_keys:n #1 { \exp_args:NNe \tl_put_right:Nn \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 / 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 / numbering .bool_set:N = \exp_not:c { CTEX@#1@numbering } , #1 / numbering .initial:n = true , #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:n = true , #1 / afterskip .value_required:n = true , #1 / indent .value_required:n = true , %<*article|book|report> #1 / afterindent .bool_set:N = \exp_not:c { CTEX@#1@afterindent } , #1 / fixskip .bool_set:N = \exp_not:c { CTEX@#1@fixskip } , #1 / hang .bool_set:N = \exp_not:c { CTEX@#1@hang } , #1 / hang .initial:n = true , #1 / runin .bool_set:N = \exp_not:c { CTEX@#1@runin } , #1 / tocline .cs_set:Np = \exp_not:c { CTEX@#1@tocline } ##1##2 , \@@_plus_key_aux:nn {#1} { break } , % \@@_plus_key_aux:nn {#1} { format } , \@@_plus_key_aux:nn {#1} { nameformat } , \@@_plus_key_aux:nn {#1} { numberformat } , \@@_plus_key_aux:nn {#1} { titleformat } , \@@_plus_key_aux:nn {#1} { aftername } , \@@_plus_key_aux:nn {#1} { aftertitle } , } } \cs_new:Npn \@@_plus_key_aux:nn #1#2 { #1 / #2 .tl_set:N = \exp_not:c { CTEX@#1@#2 } , #1 / #2 + .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@#2 } { ##1 } } , #1 / #2 ~ + .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@#2 } { ##1 } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_assign_heading_name:nn} % \begin{macro}{\@@_assign_heading_name:nnn} % \opt{name} 的值是一个至多两个元素的逗号分隔列表。由于 \LaTeXiii{} 的 % \texttt{clist} 总是会自动忽略空元素,所以设置 |name={,章}| 后,第一个元素将会 % 是“章”,必须用空的分组保护空元素:|name={{},章}|,这在使用中有些许不便。我们 % 可以改用 \texttt{seq} 或者手写函数解析参数来加以改进。为实现的简单起见,这里用 % 了 \pkg{xparse} 的 \tn{SplitArgument},它带有参数的长度检查。 % \begin{macrocode} \NewDocumentCommand \ctex_assign_heading_name:nn { m > { \SplitArgument { 1 } { , } } +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} \tl_if_novalue:nTF {#3} { \tl_clear:c { CTEX@post#1 } } { \tl_set:cn { CTEX@post#1 } {#3} } } % \end{macrocode} % \end{macro} % \end{macro} % % \changes{v2.0}{2014/03/21}{标题设置新增 \opt{pagestyle} 选项。} % \changes{v2.4.1}{2016/05/10}{新的标题格式选项 \opt{part/fixbeforeskip} 和 % \opt{chapter/fixbeforeskip}。} % \changes{v2.4.3}{2016/06/03}{删除选项 \opt{part/fixbeforeskip} 和 % \opt{chapter/fixbeforeskip}。} % \changes{v2.4.5}{2016/10/01}{新的标题格式选项 \opt{chapter/lofskip} 和 % \opt{chapter/lotskip}。} % % \begin{macro}{part/pagestyle,chapter/pagestyle,chapter/lofskip,chapter/lotskip} % 只在 \cls{ctexbook} 和 \cls{ctexrep} 下有定义。 % \begin{macrocode} \group_begin: %<*book|report> \tl_set:Nn \l_@@_tmp_tl { part / pagestyle .tl_set:N = \CTEX@part@pagestyle , chapter / pagestyle .tl_set:N = \CTEX@chapter@pagestyle , chapter / lofskip .tl_set:N = \CTEX@chapter@lofskip , chapter / lotskip .tl_set:N = \CTEX@chapter@lotskip , chapter / lofskip .initial:n = \c_zero_skip , chapter / lotskip .initial:n = \c_zero_skip , chapter / lofskip .value_required:n = true , chapter / lotskip .value_required:n = true , } % %<*article|beamer> \tl_clear:N \l_@@_tmp_tl % % \end{macrocode} % \end{macro} % % 定义标题键值选项。 % \begin{macrocode} \seq_map_inline:Nn \c_@@_headings_seq { \@@_initial_heading:n {#1} \@@_def_heading_keys:n {#1} } \exp_args:NNo \group_end: \ctex_define:n { \l_@@_tmp_tl } % \end{macrocode} % % \changes{v2.5}{2020/04/23}{重构标题选项 \opt{indent} 和 \opt{hang}。} % % \begin{macro}[int]{\CTEX@heading@format@initial} % 标题格式的一些初始设置,包括恢复默认字体,并禁用自动调整首行缩进,禁止在标题中分页。 % 同时用 \tn{noindent} 抑制首行缩进并进入水平模式。 % 统一在各级标题的 \opt{format} 选项之前使用。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@heading@format@initial { \normalfont \tl_clear:N \l_@@_autoindent_tl \int_set:Nn \tex_interlinepenalty:D { 10 000 } \tex_noindent:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_indent_box:n} % 设置 \tn{parindent},并插入用于产生缩进的盒子,如果缩进为 |0|,就不插入。 % \begin{macrocode} \cs_new_protected:Npn \ctex_indent_box:n #1 { \dim_set:Nn \tex_parindent:D {#1} \@@_insert_indent: } \cs_new_protected:Npn \@@_insert_indent: { \dim_compare:nNnF \tex_parindent:D = \c_zero_dim { \tex_indent:D } } \cs_new_eq:NN \CTEX@indentbox \ctex_indent_box:n % \end{macrocode} % \end{macro} % % \subsubsection{标准标题命令的修改} % % \begin{macrocode} %<*article|book|report> % \end{macrocode} % % \begin{macro}[int]{\CTEX@fixtopskip} % 修正 \cls{book} 和 \cls{report} 类的 \tn{part} 和 \tn{chapter} 标题之前的多余空行。 % \begin{macrocode} %<*book|report> \cs_new_protected:Npn \CTEX@fixtopskip { \CTEX@fixheadingskip \dim_compare:nNnF \tex_pagegoal:D < \c_max_dim { \skip_sub:Nn \l_@@_heading_skip { \tex_topskip:D } } } % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEX@fixheadingskip} % 抑制行间粘连,修正标题前后的多余间距。事实上,减掉 \tn{parskip},有一定的风险。 % 如果接下来的内容不会进入水平模式(例如在 \opt{format} 选项中使用 \tn{hrule} 或者 \tn{hbox}), % \TeX{} 就不会加上 \tn{parskip}。这时候就需要用户把 \tn{parskip} 加到 \opt{beforeskip} % 或者 \opt{afterskip} 作为修正。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@fixheadingskip { \par \dim_set:Nn \tex_prevdepth:D { -1000pt } \skip_sub:Nn \l_@@_heading_skip { \tex_parskip:D } } \skip_new:N \l_@@_heading_skip \cs_new_protected:Npn \CTEX@setheadingskip { \skip_set:Nn \l_@@_heading_skip } \cs_new_eq:NN \CTEX@headingskip \l_@@_heading_skip % \end{macrocode} % \end{macro} % % \changes{v2.5.10}{2022/06/23}{展开传递 \opt{pagestyle} 的值。} % % \begin{macro}[int]{\CTEX@setthispagestyle} % 将 \verb"\CTEX@(part|chapter)@pagestyle" 展开后再传给 \tn{thispagestyle}。 % \begin{macrocode} %<*book|report> \cs_new_protected:Npn \CTEX@setthispagestyle #1 { \exp_args:Ne \thispagestyle { \use:c { CTEX@#1@pagestyle } } } % % \end{macrocode} % \end{macro} % % \changes{v2.4.4}{2016/09/18}{提供 \tn{partmark}。} % \begin{macro}[int]{\partmark} % 提供 \tn{partmark}。 % \begin{macrocode} \ProvideDocumentCommand \partmark { m } { \markboth { } { } } % \end{macrocode} % \end{macro} % % \changes{v2.4.4}{2016/09/19}{提供 \tn{CTEXifname}。} % \changes{v2.4.6}{2016/10/31}{\tn{CTEXifname} 初始为假。} % \begin{macro}{\CTEXifname} % \begin{macro}[int]{\CTEX@ifnametrue,\CTEX@ifnamefalse} % 用于判断当前标题是否有编号。 % \begin{macrocode} \cs_new_eq:NN \CTEXifname \use_ii:nn \cs_new_protected:Npn \CTEX@ifnametrue { \cs_set_eq:NN \CTEXifname \use_i:nn } \cs_new_protected:Npn \CTEX@ifnamefalse { \cs_set_eq:NN \CTEXifname \use_ii:nn } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\CTEX@addloflotskip} % 往插图和表格目录中加入额外间距。如果间距为零,则不加入。 % \begin{macrocode} %<*book|report> \cs_new_protected:Npn \CTEX@addloflotskip #1 { \skip_set:Nn \l_@@_heading_skip { \use:c { CTEX@#1@lofskip } } \skip_if_eq:nnF { \l_@@_heading_skip } { \c_zero_skip } { \addtocontents { lof } { \protect \addvspace { \skip_use:N \l_@@_heading_skip } } } \skip_set:Nn \l_@@_heading_skip { \use:c { CTEX@#1@lotskip } } \skip_if_eq:nnF { \l_@@_heading_skip } { \c_zero_skip } { \addtocontents { lot } { \protect \addvspace { \skip_use:N \l_@@_heading_skip } } } } % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEX@addtocline} % \begin{macrocode} \cs_new_protected:Npn \CTEX@addtocline #1#2 { \addcontentsline { toc } {#1} { \use:c { CTEX@#1@tocline } {#1} {#2} } } % \end{macrocode} % \end{macro} % % \changes{v2.2}{2015/06/27}{\opt{beforeskip}、\opt{afterskip} 和 \opt{indent} % 选项支持表达式。} % \changes{v2.4.15}{2019/03/31}{修正 \opt{part/indent} 和 \opt{chapter/indent} 的实现方法。} % \changes{v2.4.15}{2019/03/31}{定义 \opt{part/hang} 和 \opt{chapter/hang}。} % \changes{v2.4.16}{2019/05/11}{修正 \opt{part/indent} 和 \opt{chapter/indent} % 的实现方法,在其标题内部禁用 \opt{autoindent}。} % % \changes{v2.5}{2020/04/22}{标题选项 \opt{format} 也可以接受参数。} % % \paragraph{part 的标题} % % \changes{v2.2}{2015/06/27}{非 \cls{ctexart} 类的 \opt{part/beforeskip} 和 % \opt{part/afterskip} 选项有意义。} % % \begin{macro}[int]{\part} % \begin{macrocode} %<*article> \renewcommand\part{% \if@noskipsec \leavevmode \fi \par \CTEX@part@break % \addvspace{4ex}% \CTEX@setheadingskip \CTEX@part@beforeskip \ifodd \CTEX@part@fixskip \CTEX@fixheadingskip \fi \addvspace \CTEX@headingskip \ifodd \CTEX@part@afterindent \@afterindenttrue \else \@afterindentfalse \fi \secdef\@part\@spart} %
%<*book|report> \renewcommand\part{% % \if@openright % \cleardoublepage % \else % \clearpage % \fi \CTEX@part@break % \thispagestyle{plain}% \CTEX@setthispagestyle{part}% \if@twocolumn \onecolumn \@tempswatrue \else \@tempswafalse \fi % \null\vfil \CTEX@setheadingskip \CTEX@part@beforeskip \ifodd \CTEX@part@fixskip \CTEX@fixtopskip \fi \vspace*{\CTEX@headingskip}% \secdef\@part\@spart} % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@part} % \begin{macrocode} %<*article> \def\@part[#1]#2{% \ifnum \c@secnumdepth >\m@ne \ifodd \CTEX@part@numbering \CTEX@ifnametrue \refstepcounter{part}% % \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% \else \CTEX@ifnamefalse \CTEX@makeanchor{part*}% % \addcontentsline{toc}{part}{#1}% \fi \else \CTEX@ifnamefalse \CTEX@makeanchor{part*}% % \addcontentsline{toc}{part}{#1}% \fi \CTEX@gettitle{#1}% \CTEX@addtocline{part}{#1}% \partmark{#1}% \begingroup % \parindent \z@ \raggedright \interlinepenalty \@M \normalfont \CTEX@heading@format@initial \CTEX@part@format{% % \ifnum \c@secnumdepth >\m@ne % \Large\bfseries\partname\nobreakspace\thepart\par\nobreak % \fi \CTEX@headinghang{part}% {\CTEXifname{\CTEX@partname\CTEX@part@aftername}{}}% % \huge\bfseries #2% \CTEX@part@titleformat{#2}% % \markboth{}{}\par \CTEX@part@aftertitle}\par \endgroup \nobreak % \vskip 3ex \CTEX@setheadingskip \CTEX@part@afterskip \ifodd \CTEX@part@fixskip \CTEX@fixheadingskip \fi \vskip \CTEX@headingskip \@afterheading} % %<*book|report> \def\@part[#1]#2{% \ifnum \c@secnumdepth >-2\relax \ifodd \CTEX@part@numbering \CTEX@ifnametrue \refstepcounter{part}% % \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% \else \CTEX@ifnamefalse \CTEX@makeanchor{part*}% % \addcontentsline{toc}{part}{#1}% \fi \else \CTEX@ifnamefalse \CTEX@makeanchor{part*}% % \addcontentsline{toc}{part}{#1}% \fi \CTEX@gettitle{#1}% \CTEX@addtocline{part}{#1}% % \markboth{}{}% \partmark{#1}% \begingroup % \centering \interlinepenalty \@M \normalfont \CTEX@heading@format@initial \CTEX@part@format{% % \ifnum \c@secnumdepth >-2\relax % \huge\bfseries\partname\nobreakspace\thepart\par\vskip 20\p@ % \fi \CTEX@headinghang{part}% {\CTEXifname{\CTEX@partname\CTEX@part@aftername}{}}% % \Huge\bfseries #2\par \CTEX@part@titleformat{#2}% \CTEX@part@aftertitle}\par \endgroup \@endpart} % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@spart} % \begin{macrocode} %<*article> \def\@spart#1{% \CTEX@ifnamefalse \CTEX@makeanchor@spart{part*}% \CTEX@gettitle{#1}% \begingroup % \parindent \z@ \raggedright \interlinepenalty \@M \normalfont \CTEX@heading@format@initial \CTEX@part@format{% \CTEX@headinghang{part}{}% % \huge \bfseries #1\par \CTEX@part@titleformat{#1}% \CTEX@part@aftertitle}\par \endgroup \nobreak % \vskip 3ex \CTEX@setheadingskip \CTEX@part@afterskip \ifodd \CTEX@part@fixskip \CTEX@fixheadingskip \fi \vskip \CTEX@headingskip \@afterheading} % %<*book|report> \def\@spart#1{% \CTEX@ifnamefalse \CTEX@makeanchor@spart{part*}% \CTEX@gettitle{#1}% \begingroup % \centering \interlinepenalty \@M \normalfont \CTEX@heading@format@initial \CTEX@part@format{% \CTEX@headinghang{part}{}% % \Huge \bfseries #1\par% \CTEX@part@titleformat{#1}% \CTEX@part@aftertitle}\par \endgroup \@endpart} % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@endpart} % \begin{macrocode} %<*book|report> \def\@endpart{% % \vfil \CTEX@setheadingskip \CTEX@part@afterskip \ifodd \CTEX@part@fixskip \CTEX@fixheadingskip \fi \vskip \CTEX@headingskip \newpage \if@twoside \if@openright \null \thispagestyle{empty}% \newpage \fi \fi \if@tempswa \twocolumn \fi} % % \end{macrocode} % \end{macro} % % \paragraph{chapter 的标题} % % \begin{macrocode} %<*book|report> % \end{macrocode} % % \begin{macro}[int]{\chapter} % \begin{macrocode} \renewcommand\chapter{% % \if@openright\cleardoublepage\else\clearpage\fi % \thispagestyle{plain}% \CTEX@chapter@break \CTEX@setthispagestyle{chapter}% \global\@topnum\z@ % \@afterindentfalse \ifodd \CTEX@chapter@afterindent \@afterindenttrue \else \@afterindentfalse \fi \secdef\@chapter\@schapter} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@chapter} % \begin{macrocode} \def\@chapter[#1]#2{% \ifnum \c@secnumdepth >\m@ne %<*book> \if@mainmatter % \ifodd \CTEX@chapter@numbering \CTEX@ifnametrue \refstepcounter{chapter}% % \typeout{\@chapapp\space\thechapter.}% \typeout{\CTEXthechapter}% % \addcontentsline{toc}{chapter} % {\protect\numberline{\thechapter}#1}% \else \CTEX@ifnamefalse \CTEX@makeanchor{\Hy@chapapp*}% % \addcontentsline{toc}{chapter}{#1}% \fi %<*book> \else \CTEX@ifnamefalse \CTEX@makeanchor@chapter{\Hy@chapapp*}% % \addcontentsline{toc}{chapter}{#1}% \fi % \else \CTEX@ifnamefalse \CTEX@makeanchor@chapter{\Hy@chapapp*}% % \addcontentsline{toc}{chapter}{#1}% \fi \CTEX@gettitle{#1}% \CTEX@addtocline{chapter}{#1}% \chaptermark{#1}% % \addtocontents{lof}{\protect\addvspace{10\p@}}% % \addtocontents{lot}{\protect\addvspace{10\p@}}% \CTEX@addloflotskip{chapter}% \if@twocolumn \@topnewpage[\@makechapterhead{#2}]% \else \@makechapterhead{#2}% \@afterheading \fi} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@schapter} % \begin{macrocode} \def\@schapter#1{% \CTEX@ifnamefalse \CTEX@makeanchor@schapter{\Hy@chapapp*}% \CTEX@gettitle{#1}% \if@twocolumn \@topnewpage[\@makeschapterhead{#1}]% \else \@makeschapterhead{#1}% \@afterheading \fi} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@makechapterhead} % \begin{macrocode} \def\@makechapterhead#1{% % \vspace*{50\p@}% \CTEX@setheadingskip \CTEX@chapter@beforeskip \ifodd \CTEX@chapter@fixskip \CTEX@fixtopskip \fi \vspace*{\CTEX@headingskip}% \begingroup % \parindent \z@ \raggedright \normalfont \CTEX@heading@format@initial \CTEX@chapter@format{% % \ifnum \c@secnumdepth >\m@ne % \if@mainmatter % \huge\bfseries\@chapapp\space\thechapter\par\nobreak\vskip 20\p@ % \fi % \fi \CTEX@headinghang{chapter}% {\CTEXifname{\CTEX@chaptername\CTEX@chapter@aftername}{}}% % \Huge \bfseries #1\par\nobreak \CTEX@chapter@titleformat{#1}% \CTEX@chapter@aftertitle}\par \endgroup \nobreak % \vskip 40\p@ \CTEX@setheadingskip \CTEX@chapter@afterskip \ifodd \CTEX@chapter@fixskip \CTEX@fixheadingskip \fi \vskip \CTEX@headingskip} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@makeschapterhead} % \begin{macrocode} \def\@makeschapterhead#1{% % \vspace*{50\p@}% \CTEX@setheadingskip \CTEX@chapter@beforeskip \ifodd \CTEX@chapter@fixskip \CTEX@fixtopskip \fi \vspace*{\CTEX@headingskip}% \begingroup % \parindent \z@ \raggedright \normalfont \interlinepenalty\@M \CTEX@heading@format@initial \CTEX@chapter@format{% \CTEX@headinghang{chapter}{}% % \Huge \bfseries #1\par\nobreak \CTEX@chapter@titleformat{#1}% \CTEX@chapter@aftertitle}\par \endgroup \nobreak % \vskip 40\p@ \CTEX@setheadingskip \CTEX@chapter@afterskip \ifodd \CTEX@chapter@fixskip \CTEX@fixheadingskip \fi \vskip \CTEX@headingskip} % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \paragraph{section 类的标题} % % \begin{macro}[int]{\@startsection} % \LaTeX 的标准参数是: % \begin{quote}\small % \Arg{name}\Arg{level}\Arg{indent}\Arg{beforeskip}\Arg{afterskip}^^A % \Arg{style}|*|\oarg{altheading}\Arg{heading} % \end{quote} % \begin{macrocode} \def\@startsection#1#2#3#4#5#6{% \if@noskipsec \leavevmode \fi \par % \@tempskipa #4\relax % \@afterindenttrue % \ifdim \@tempskipa <\z@ % \@tempskipa -\@tempskipa \@afterindentfalse % \fi \CTEX@update@sectionformat@n{#1}% \ifodd \CTEX@afterindent \@afterindenttrue \else \@afterindentfalse \fi \if@nobreak \everypar{}% \else % \addpenalty\@secpenalty\addvspace\@tempskipa \csname CTEX@#1@break\endcsname \CTEX@setheadingskip{#4}% \ifodd \CTEX@fixskip \CTEX@fixheadingskip \fi \addvspace \CTEX@headingskip \fi \@ifstar {\CTEX@makeanchor@ssect{#1*}\@ssect{#3}{#4}{#5}{#6}}% {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@seccntformat} % \begin{macrocode} \def\@seccntformat#1{% % \csname the#1\endcsname\quad}% \csname CTEX@#1name\endcsname \csname CTEX@#1@aftername\endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@sect} % \begin{macrocode} \def\@sect#1#2#3#4#5#6[#7]#8{% \ifnum #2>\c@secnumdepth \CTEX@ifnamefalse \CTEX@makeanchor@sect{#1*}% \let\@svsec\@empty \else \ifodd \csname CTEX@#1@numbering\endcsname \CTEX@ifnametrue \refstepcounter{#1}% \protected@edef\@svsec{\@seccntformat{#1}\relax}% \else \CTEX@ifnamefalse \CTEX@makeanchor{#1*}% \let\@svsec\@empty \fi \fi \CTEX@gettitle{#7}% % \@tempskipa #5\relax % \ifdim \@tempskipa>\z@ \unless \ifodd \CTEX@runin \begingroup \CTEX@heading@format@initial #6{% % \@hangfrom{\hskip #3\relax\@svsec}% % \interlinepenalty \@M #8\@@@@par \CTEX@sectionhang{#3}{\@svsec}% \csname CTEX@#1@titleformat\endcsname{#8}% \csname CTEX@#1@aftertitle\endcsname}\par \endgroup \csname #1mark\endcsname{#7}% % \addcontentsline{toc}{#1}{% % \ifnum #2>\c@secnumdepth \else % \protect\numberline{\csname the#1\endcsname}% % \fi % #7}% \CTEX@addtocline{#1}{#7}% \else \def\@svsechd{% #6{% % \hskip #3\relax \@svsec #8 {\CTEX@indentbox{#3}}\@svsec \csname CTEX@#1@titleformat\endcsname{#8}% \csname CTEX@#1@aftertitle\endcsname}% \csname #1mark\endcsname{#7}% % \addcontentsline{toc}{#1}{% % \ifnum #2>\c@secnumdepth \else % \protect\numberline{\csname the#1\endcsname}% % \fi % #7}% \CTEX@addtocline{#1}{#7}}% \fi \@xsect{#5}} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@ssect} % \begin{macrocode} \def\@ssect#1#2#3#4#5{% \CTEX@ifnamefalse \CTEX@gettitle{#5}% % \@tempskipa #3\relax % \ifdim \@tempskipa>\z@ \unless \ifodd \CTEX@runin \begingroup \CTEX@heading@format@initial #4{% % \@hangfrom{\hskip #1}% % \interlinepenalty \@M #5\@@par \CTEX@sectionhang{#1}{}% \CTEX@titleformat@n{#5}% \CTEX@aftertitle}\par \endgroup \else % \def\@svsechd{#4{\hskip #1\relax #5}}% \def\@svsechd{#4{{\CTEX@indentbox{#1}}% \CTEX@titleformat@n{#5}\CTEX@aftertitle}}% \fi \@xsect{#3}} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@xsect} % \begin{macrocode} \def\@xsect#1{% % \@tempskipa #1\relax % \ifdim \@tempskipa>\z@ \unless \ifodd \CTEX@runin \par \nobreak % \vskip \@tempskipa \CTEX@setheadingskip{#1}% \ifodd \CTEX@fixskip \CTEX@fixheadingskip \fi \vskip \CTEX@headingskip \@afterheading \else \@nobreakfalse \global\@noskipsectrue \everypar{% \if@noskipsec \global\@noskipsecfalse {\setbox\z@\lastbox}% \clubpenalty\@M \begingroup \@svsechd \endgroup \unskip % \@tempskipa #1\relax % \hskip -\@tempskipa \CTEX@heading@glue{#1}% \else \clubpenalty \@clubpenalty \everypar{}% \fi}% \fi \ignorespaces} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEX@headinghang,\CTEX@sectionhang} % 分别用于用于实现 \tn{part}/\tn{chapter} 和 \tn{section} 类标题的 % \opt{indent} 和 \opt{hang} 选项。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@headinghang #1 { \ctex_heading_hang:cnn { CTEX@#1@hang } { \use:c { CTEX@#1@indent } } } \cs_new_protected:Npn \CTEX@sectionhang { \ctex_heading_hang:Nnn \CTEX@hang } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_heading_hang:Nnn,\ctex_hang_from:n} % \opt{hang} 选项控制是否采用悬挂缩进,同时设置 \tn{parindent}。 % \begin{macrocode} \cs_new_protected:Npn \ctex_heading_hang:Nnn #1#2#3 { \dim_set:Nn \tex_parindent:D {#2} \bool_if:NTF #1 { \ctex_hang_from:n } { \use:n } { \@@_insert_indent: #3 } } \cs_new_protected:Npn \ctex_hang_from:n #1 { \tex_noindent:D \hbox_set:Nn \l_@@_tmp_box {#1} \tex_hangindent:D = \box_wd:N \l_@@_tmp_box \box_use_drop:N \l_@@_tmp_box } \cs_generate_variant:Nn \ctex_heading_hang:Nnn { c } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_heading_glue:n,\CTEX@heading@glue} % 如果缩进 |#1| 长度为零,就不插入水平间距。 % \begin{macrocode} \cs_new_protected:Npn \ctex_heading_glue:n #1 { \group_begin: \skip_set:Nn \l_@@_heading_skip {#1} \dim_compare:nNnF \l_@@_heading_skip = \c_zero_dim { \skip_horizontal:N \l_@@_heading_skip } \group_end: } \cs_new_eq:NN \CTEX@heading@glue \ctex_heading_glue:n % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEX@update@sectionformat@n} % 在 \tn{@startsection} 中设置 \tn{CTEX@titleformat@n} 等为相应函数。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@update@sectionformat@n #1 { \cs_set_eq:Nc \CTEX@titleformat@n { CTEX@#1@titleformat } \cs_set_eq:Nc \CTEX@aftertitle { CTEX@#1@aftertitle } \cs_set_eq:Nc \CTEX@afterindent { CTEX@#1@afterindent } \cs_set_eq:Nc \CTEX@fixskip { CTEX@#1@fixskip } \cs_set_eq:Nc \CTEX@hang { CTEX@#1@hang } \cs_set_eq:Nc \CTEX@runin { CTEX@#1@runin } } \cs_new_eq:NN \CTEX@titleformat@n \use:n \cs_new_eq:NN \CTEX@aftertitle \prg_do_nothing: \cs_new_eq:NN \CTEX@afterindent \c_true_bool \cs_new_eq:NN \CTEX@fixskip \c_false_bool \cs_new_eq:NN \CTEX@hang \c_true_bool \cs_new_eq:NN \CTEX@runin \c_false_bool % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEX@part@tocline, \CTEX@chapter@tocline} % \begin{macrocode} \cs_new:Npn \CTEX@part@tocline #1#2 { \CTEXifname { \CTEXthepart \hspace { 1em } } { } #2 } %<*book|report> \cs_new:Npn \CTEX@chapter@tocline #1#2 { \CTEXifname { \protect \numberline { \CTEXthechapter \hspace { .3em } } } { } #2 } % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEXnumberline} % \begin{macrocode} \cs_new:Npn \CTEXnumberline #1 { \CTEXifname { \protect \numberline { \use:c { CTEXthe #1 } } } { } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \int_zero:N \l_@@_tmp_int \seq_map_inline:Nn \c_@@_section_headings_seq { \int_incr:N \l_@@_tmp_int \cs_gset_protected: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 } } { \exp_not:N \normalfont \exp_not:c { CTEX@#1@format } } } \cs_new:cpn { CTEX@#1@tocline } ##1##2 { \CTEXnumberline { ##1 } ##2 } } % \end{macrocode} % % \paragraph{附录标题} % % \begin{macro}[int]{appendix/name,appendix/number,appendix/numbering} % \begin{macrocode} \ctex_define:n { appendix .meta:nn = { ctex / appendix } {#1} , appendix / name .code:n = { \ctex_assign_heading_name:nn { appendix } {#1} } , appendix / number .tl_set:N = \CTEX@appendix@number , appendix / numbering .bool_set:N = \CTEX@appendix@numbering , appendix / numbering .initial:n = true } \tl_new:N \CTEX@preappendix \tl_new:N \CTEX@postappendix % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\appendix} % \begin{macrocode} \cs_new_eq:NN \CTEX@save@appendix \appendix \cs_gset_protected:Npn \appendix { \CTEX@save@appendix %<*article> \gdef \CTEX@presection { \CTEX@preappendix } \gdef \CTEX@thesection { \CTEX@appendix@number } \gdef \CTEX@postsection { \CTEX@postappendix } \gdef \CTEX@section@numbering { \CTEX@appendix@numbering } % %<*book|report> \gdef \CTEX@prechapter { \CTEX@preappendix } \gdef \CTEX@thechapter { \CTEX@appendix@number } \gdef \CTEX@postchapter { \CTEX@postappendix } \gdef \CTEX@chapter@numbering { \CTEX@appendix@numbering } % } % \end{macrocode} % \end{macro} % % \paragraph{设置 \pkg{hyperref} 宏包的标题锚点} % % \changes{v2.4.4}{2016/09/12}{改进 \pkg{hyperref} 宏包的标题锚点设置。} % % \begin{macro}[int]{\CTEX@makeanchor} % 设置超链接跳转锚点,在 \pkg{hyperref} 载入后才有意义。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@makeanchor #1 { } % \end{macrocode} % \end{macro} % % \begin{variable}{\c_@@_headings_cs_seq} % 保存内部标题命令的 \CTeX{} 定义,用于随后比较。 % \begin{macrocode} \seq_const_from_clist:Nn \c_@@_headings_cs_seq %
{ part , spart , sect , ssect } % { part , spart , chapter , schapter , sect , ssect } \seq_map_inline:Nn \c_@@_headings_cs_seq { \cs_new_eq:cc { CTEX@ #1 } { @ #1 } \cs_new_eq:cN { CTEX@makeanchor@ #1 } \CTEX@makeanchor } % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\CTEX@hyperheadinghook} % \pkg{hyperref} 会重定义内部标题命令,目的在于为没有编号的标题设置锚点(这一功能受他的 % \opt{implicit} 选项的控制)。我们在上面对标题命令的修改已经包含这一功能,如果这些标题命令在 % \pkg{hyperref} 载入之前没有被修改过,则恢复 \CTeX{} 的定义。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@hyperheadinghook { \group_begin: \legacy_if:nTF { Hy@implicit } { \cs_set_eq:NN \H@old@chapter \Hy@org@chapter \seq_map_inline:Nn \c_@@_headings_cs_seq { \cs_if_eq:ccT { H@old@ ##1 } { CTEX@ ##1 } { \cs_gset_eq:cc { @ ##1 } { CTEX@ ##1 } \cs_gset_eq:cN { CTEX@makeanchor@ ##1 } \CTEX@makeanchor } } } { \seq_map_inline:Nn \c_@@_headings_cs_seq { \cs_gset_eq:cN { CTEX@makeanchor@ ##1 } \CTEX@makeanchor } } \group_end: } % \end{macrocode} % \end{macro} % % \begin{macrocode} \ctex_at_end_package:nn { hyperref } { \cs_gset_protected:Npn \CTEX@makeanchor #1 { \Hy@MakeCurrentHrefAuto {#1} \Hy@raisedlink { \hyper@anchorstart { \@currentHref } \hyper@anchorend } } \CTEX@hyperheadinghook } % \end{macrocode} % % \paragraph{兼容 \pkg{nameref} 宏包} % % \changes{v2.4.16}{2019/05/29}{更好地兼容 \pkg{nameref} 宏包。} % % \begin{macro}[int]{\CTEX@gettitle} % 在 \pkg{nameref} 载入后才有意义,与上述 \pkg{hyperref} 的处理类似。 % \begin{macrocode} \cs_new_protected:Npn \CTEX@gettitle #1 { } \ctex_at_end_package:nn { nameref } { \cs_gset_protected:Npn \CTEX@gettitle { \NR@gettitle } \seq_map_inline:Nn \c_@@_headings_cs_seq { \cs_if_eq:ccT { NR@ #1 } { CTEX@ #1 } { \cs_gset_eq:cc { @ #1 } { CTEX@ #1 } } } } % \end{macrocode} % \end{macro} % % \paragraph{兼容 \pkg{titlesec} 宏包} % % 我们修改了 \tn{@startsection} 的定义,它的第四个(\meta{beforeskip})和 % 第五个(\meta{afterskip})参数的符号不再有特殊意义,改由相应的选项 % \opt{afterindent} 和 \opt{runin} 来控制。 % % 引入 \pkg{titlesec} 宏包,并且未设置它的 \opt{loadonly} 选项时,\pkg{titlesec} % 会展开 section 类标题获取它们的参数,进行初始设置。我们需要进行一些调整。 % % \begin{macro}[int]{\ctex_titlesec_hook:} % \tn{titleformat} 的设置保存在名为 |\ttlf@|\meta{section} 的宏中备用,它的内容是 % \begin{quote}\small % |\ttlh@|\meta{shape}\Arg{format}\Arg{label}\Arg{sep}\Arg{before}\Arg{after} % \end{quote} % 我们这里的 \meta{shape} 为 |hang| 或者 |runin|。\tn{titlespacing} 的设置保存在 % |\ttls@|\meta{section} 之中,它的内容是 % \begin{quote}\small % \Arg{left}\Arg{right}\Arg{before}\Arg{after}\Arg{afterindent} % \end{quote} % 其中 \meta{afterindent} 为 |1| 或 |0|,分别对应是否保留段首缩进。 % 我们需要根据 \CTeX{} 的 \opt{runin} 和 \opt{afterindent} 选项调整 % |\ttlh@|\meta{shape} 和 \meta{afterindent}。注意,由 \tn{ttl@extract} 得的 % \meta{before} 和 \meta{after} 的值总是非负的,而 \CTeX{} 的 \opt{beforeskip} % 和 \opt{afterskip} 是可以取负值的,但我们不打算调整它们了。 % 如果使用了 \pkg{titlesec} 的 \opt{indentafter} 等选项,也不需要调整 % |\ttls@|\meta{section}。 % \begin{macrocode} \cs_new_protected:Npn \ctex_titlesec_hook: { \@ifpackagewith { titlesec } { explicit } { \cs_set_eq:NN \@@_titlesec_format:Nn \@@_titlesec_format_explicit:Nn } { } \clist_map_inline:nn { indentafter , noindentafter , indentfirst , nonindentfirst } { \@ifpackagewith { titlesec } { ##1 } { \clist_map_break:n { \cs_set_eq:NN \@@_titlesec_hook:n \@@_titlesec_format:n } } { } } \seq_map_function:NN \c_@@_section_headings_seq \@@_titlesec_hook:n } \cs_new_protected:Npn \@@_titlesec_hook:n #1 { \@@_titlesec_format:n {#1} \exp_args:Nc \@@_titlesec_spacing:Nn { ttls@#1 } {#1} } \cs_new_protected:Npn \@@_titlesec_format:n #1 { \cs_if_free:cF { ttlf@#1 } { \exp_args:Nc \@@_titlesec_format:Nn { ttlf@#1 } {#1} } } \cs_new_protected:Npn \@@_titlesec_format:Nn #1#2 { \tl_set:Ne #1 { \bool_if:cTF { CTEX@#2@runin } { \exp_not:N \ttlh@runin } { \exp_not:N \ttlh@hang } \tl_tail:N #1 } } \cs_new_protected:Npn \@@_titlesec_format_explicit:Nn #1#2 { \cs_set_nopar:Npx #1 ##1 { \bool_if:cTF { CTEX@#2@runin } { \exp_not:N \ttlh@runin } { \exp_not:N \ttlh@hang } \exp_args:No \tl_tail:n { #1 { } } } } \cs_new_protected:Npn \@@_titlesec_spacing:Nn #1#2 { \tl_set:Ne #1 { \exp_after:wN \@@_titlesec_spacing:nnnnnn #1 {#2} } } \cs_new:Npn \@@_titlesec_spacing:nnnnnn #1#2#3#4#5#6 { \exp_not:n { {#1} {#2} {#3} {#4} } { \bool_if:cTF { CTEX@#6@afterindent } { \@ne } { \z@ } } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \@ifpackageloaded { titlesec } { } { \ctex_at_end_package:nn { titlesec } { \@ifpackagewith { titlesec } { loadonly } { } { \ctex_titlesec_hook: } } } % \end{macrocode} % % \changes{v2.4.4}{2016/09/13}{使用 \pkg{titlesec} 时,章节目录也使用 \CTeX{} 的编号。} % 让编译时终端显示 \tn{CTEXthechapter},目录使用 |\CTEXtheXXX| 编号。 % \begin{macrocode} \ctex_at_end_package:nn { titlesec } { %<*book|report> \tl_set:Nn \ttl@chapterout { \typeout { \CTEXthechapter } } % \cs_if_free:NF \ttl@tocpart { \cs_set_protected:Npn \ttl@tocpart { \tl_set:Nn \ttl@a { \CTEXthepart \hspace { 1em } } } } \seq_map_inline:Nn \c_@@_headings_seq { \cs_if_exist:cF { ttl@toc #1 } { \cs_new_protected:cpx { ttl@toc #1 } { \tl_set:Nn \exp_not:N \ttl@a { \exp_not:N \protect \exp_not:N \numberline { \exp_not:c { CTEXthe #1 } } } } } } } % \end{macrocode} % % \changes{v2.5.8}{2021/12/04}{兼容 \pkg{titlesec} 包和 \tn{CTEXifname}。} % 在 \pkg{titlesec} 包定义的标题中更新 \tn{CTEXifname}。 % \begin{macrocode} \ctex_at_end_package:nn { titlesec } { \ctex_patch_cmd:Nnn \ttl@labelling { \let \ifttl@toclabel \ifttl@label } { \let \ifttl@toclabel \ifttl@label \CTEX@updatettlifname } \cs_new_protected:Npn \CTEX@updatettlifname { \legacy_if:nTF { ttl@label } { \CTEX@ifnametrue } { \CTEX@ifnamefalse } } } % \end{macrocode} % % \paragraph{兼容 \pkg{titleps} 宏包} % % \changes{v2.3}{2015/12/25}{兼容 \pkg{titleps} 宏包。} % % 按照 \pkg{titleps} 宏包的实现机制,|\CTEXtheXXX| 等宏直到页眉排版时才会被展开, % 这可能会造成问题\footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/217}}。 % % \begin{macro}[int]{\ctex_titleps_hook:} % 我们修改 \pkg{titleps} 包的内部命令 \tn{ttl@settopmark} 和 \tn{ttl@setsubmark}, % 将 |\CTEXtheXXX| 等加入更新队列中。 % \begin{macrocode} \group_begin: \char_set_catcode_other:N \# \cs_new_protected:Npn \ctex_titleps_hook: { \ctex_patch_cmd:Nnn \ttl@settopmark { \protect \@namedef { the#1 } { \@nameuse { the#1 } } } { \protect \@namedef { the#1 } { \@nameuse { the#1 } } \CTEX@titlepslabel@set {#1} } \ctex_patch_cmd:Nnn \ttl@setsubmark { \protect \@namedef { the#1 } { } } { \protect \@namedef { the#1 } { } \CTEX@titlepslabel@clear {#1} } \ctex_patch_cmd:Nnn \ttl@setsubmark { \protect \@namedef { the#2 } { \@nameuse { the#2 } } } { \protect \@namedef { the#2 } { \@nameuse { the#2 } } \CTEX@titlepslabel@set {#2} } } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CTEX@titlepslabel@set,\CTEX@titlepslabel@clear} % 这两个函数要在随后被 \tn{xdef} 展开来获得 |\CTEXtheXXX| 的内容,不应该用 % \tn{protected} 来定义。 % \begin{macrocode} \cs_new:Npn \CTEX@titlepslabel@set #1 { \cs_if_free:cF { CTEXthe#1 } { \protect \@namedef { CTEXthe#1 } { \@nameuse { CTEXthe#1 } } } } \cs_new:Npn \CTEX@titlepslabel@clear #1 { \cs_if_free:cF { CTEXthe#1 } { \protect \@namedef { CTEXthe#1 } { } } } % \end{macrocode} % \end{macro} % % \pkg{titleps} 宏包的功能可以由 \pkg{titlesec} 的选项 \opt{pagestyles} 引入。 % \begin{macrocode} \ctex_at_end_package:nn { titlesec } { \cs_if_free:NF \ttl@settopmark { \ctex_titleps_hook: } } \ctex_at_end_package:nn { titleps } { \ctex_titleps_hook: } % \end{macrocode} % % 除此之外,也可以使用 \pkg{titleps} 提供的命令 \tn{newtitlemark} 来完成: % \begin{verbatim} % \newtitlemark { \CTEXthechapter } % \newtitlemark { \CTEXthesection } % \end{verbatim} % 但 \tn{newtitlemark} 不包含章节间的层次信息,功能上不及修改内部命令完整。 % % \changes{v2.4.6}{2016/10/31}{重新初始化 \tn{ifthechapter} 等。} % \begin{macro}[int]{\ttl@setifthe} % 使 |\iftheXXX| 等命令在页眉设置中可用。 % \begin{macrocode} \ctex_at_end_package:nn { titleps } { \cs_set_protected:Npn \ttl@setifthe #1 { \exp_args:Nco \cs_set:Npn { ifthe #1 } { \CTEXifname { \protect \@firstoftwo } { \protect \@secondoftwo } } } \seq_map_function:NN \c_@@_headings_seq \ttl@setifthe } % \end{macrocode} % \end{macro} % % \subsubsection{目录标签的宽度} % % \begin{macro}{\CTEX@toc@width@n} % \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@ / 2 } } } % \end{macrocode} % \end{macro} % % \changes{v2.5}{2020/01/11}{兼容 \pkg{titletoc} 宏包。} % % \begin{macro}{\numberline,\@@_patch_toc_width:n} % 为 \tn{numberline} 命令打补丁,并兼容 \pkg{tocloft} 和 \pkg{titletoc} 宏包。 % % 这里需要替换 |#| 本身,因此需要先切换为 other 类。表示参数的 |#| 用 % \cs{c_parameter_token} 代替。 % \begin{macrocode} \group_begin: \char_set_catcode_other:N \# \use:n { \group_end: \ctex_preto_cmd:NnnTF \numberline { \ExplSyntaxOff } { \CTEX@toc@width@n {#1} } { } { \ctex_patch_failure:N \numberline } \cs_new_protected:Npn \@@_patch_toc_width:n \c_parameter_token 1 { \@ifpackageloaded { \c_parameter_token 1 } { } { \ctex_at_end_package:nn { \c_parameter_token 1 } { \ctex_preto_cmd:NnnTF \numberline { \char_set_catcode_letter:n { 64 } } { \CTEX@toc@width@n {#1} } { } { \ctex_patch_failure:N \numberline } } } } } \@@_patch_toc_width:n { tocloft } \@@_patch_toc_width:n { titletoc } % \end{macrocode} % \end{macro} % % \subsubsection{页眉信息的修改} % % \begin{macro}[int]{\ps@headings} % \changes{v2.4.5}{2016/10/01}{修复补丁失败。} % \changes{v2.4.7}{2016/12/23}{修复 \cls{ctexrep} 类的 \tn{chaptermark} 汉化错误。} % \changes{v2.4.11}{2017/09/13}{补充页眉空格。} % \begin{macrocode} %<*article> \legacy_if:nTF { @twoside } { \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \z@ \thesection \quad \fi } { \CTEXifname { \CTEXthesection \quad } { } } \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \@ne \thesubsection \quad \fi } { \CTEXifname { \CTEXthesubsection \quad } { } } } % \end{macrocode} % 不知为何,标准文档类此处对 \texttt{secnumdepth} 的判断为 $0$,与 \tn{section} 的层次 $1$ 不符。 % \begin{macrocode} { \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \m@ne \thesection \quad \fi } { \CTEXifname { \CTEXthesection \quad } { } } } %
%<*book|report> \ctex_patch_cmd:Nnn \ps@headings { % \ifnum \c@secnumdepth > \m@ne \if@mainmatter % \ifnum \c@secnumdepth > \m@ne \@chapapp \ \thechapter . ~ \ % % \fi % \fi \fi } { \CTEXifname { \CTEXthechapter \quad } { } } \legacy_if:nT { @twoside } { \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \z@ \thesection . ~ \ \fi } { \CTEXifname { \CTEXthesection \quad } { } } } % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\f@nch@initialise} % 这里对 \pkg{fancyhdr} 宏包打补丁。原来 \pkg{fancyhdr} 宏包中使用 % \tn{thesection} 等宏表示页眉中的章节编号,这里改用 \pkg{ctex} 包所用的 % \tn{CTEXthesection} 系列宏。 % \changes{v2.5.6}{2021/01/11}{更新 \pkg{fancyhdr} 宏包的补丁。} % \begin{macrocode} \ctex_at_end_package:nn { fancyhdr } { \ctex_patch_cmd:Nnn \f@nch@initialise { \ifnum \c@secnumdepth > \z@ \thesection \hskip 1em \relax \fi } { \CTEXifname { \CTEXthesection \quad } { } } \ctex_patch_cmd:Nnn \f@nch@initialise { \ifnum \c@secnumdepth > \@ne \thesubsection \hskip 1em \relax \fi } { \CTEXifname { \CTEXthesubsection \quad } { } } \ctex_patch_cmd:Nnn \f@nch@initialise { \ifnum \c@secnumdepth > \m@ne \@chapapp\ \thechapter . ~ \ \fi } { \CTEXifname { \CTEXthechapter \quad } { } } \ctex_patch_cmd:Nnn \f@nch@initialise { \ifnum \c@secnumdepth > \z@ \thesection . ~ \ \fi } { \CTEXifname { \CTEXthesection \quad } { } } \f@nch@initialise % \end{macrocode} % \pkg{fancyhdr} 的 \opt{headings} 选项会重定义 \tn{ps@headings}, % 这里也要打补丁。 % \begin{macrocode} \@ifpackagewith { fancyhdr } { headings } { %<*article> \legacy_if:nTF { @twoside } { \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \z@ \thesection \quad \fi } { \CTEXifname { \CTEXthesection \quad } { } } \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \@ne \thesubsection \quad \fi } { \CTEXifname { \CTEXthesubsection \quad } { } } } { \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \z@ \thesection \quad \fi } { \CTEXifname { \CTEXthesection \quad } { } } } % %<*book|report> \ctex_patch_cmd:Nnn \ps@headings { % \ifnum \c@secnumdepth > \m@ne \if@mainmatter % \ifnum \c@secnumdepth > \m@ne \@chapapp \ \thechapter . ~ \ % % \fi % \fi \fi } { \CTEXifname { \CTEXthechapter \quad } { } } \legacy_if:nT { @twoside } { \ctex_patch_cmd:Nnn \ps@headings { \ifnum \c@secnumdepth > \z@ \thesection . ~ \ \fi } { \CTEXifname { \CTEXthesection \quad } { } } } % } { } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{\cls{beamer} 标题页模板的修改} % % \begin{macrocode} %<*beamer> % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % \changes{v2.4.15}{2019/01/29}{局部指定 \opt{autoindent} 为 \opt{false},并交换 % \tn{CTEX@XXX@indent} 与 \tn{CTEX@XXX@format} 的顺序。} % % 对应 \tn{partpage}。 % \begin{macrocode} \defbeamertemplate*{part page}{CTEX}[1][]{% \begingroup % \centering % {\usebeamerfont{part name}% % \usebeamercolor[fg]{part name}\partname~\insertromanpartnumber} % \vskip1em\par \par \addvspace{\glueexpr\CTEX@part@beforeskip\relax}% \CTEX@heading@format@initial \CTEX@part@format{% \CTEX@indentbox{\CTEX@part@indent}% \ifodd \CTEX@part@numbering \CTEX@partname \CTEX@part@aftername \fi \begin{beamercolorbox}[sep=16pt,center,#1]{part title} % \usebeamerfont{part title}\insertpart\par \CTEX@part@titleformat \insertpart \CTEX@part@aftertitle \end{beamercolorbox}}% \par \addvspace{\glueexpr\CTEX@part@afterskip\relax}% \endgroup} % \end{macrocode} % % 对应 \tn{sectionpage}。 % \begin{macrocode} \defbeamertemplate*{section page}{CTEX}[1][]{% \begingroup % \centering % {\usebeamerfont{section name}% % \usebeamercolor[fg]{section name}\sectionname~\insertsectionnumber} % \vskip1em\par \par \addvspace{\glueexpr\CTEX@section@beforeskip\relax}% \CTEX@heading@format@initial \CTEX@section@format{% \CTEX@indentbox{\CTEX@section@indent}% \ifodd \CTEX@section@numbering \CTEX@sectionname \CTEX@section@aftername \fi \begin{beamercolorbox}[sep=12pt,center,#1]{part title} % \usebeamerfont{section title}\insertsection\par \CTEX@section@titleformat \insertsection \CTEX@section@aftertitle \end{beamercolorbox}}% \par \addvspace{\glueexpr\CTEX@section@afterskip\relax}% \endgroup} % \end{macrocode} % % 对应 \tn{subsectionpage}。 % \begin{macrocode} \defbeamertemplate*{subsection page}{CTEX}[1][]{% \begingroup % \centering % {\usebeamerfont{subsection name}% % \usebeamercolor[fg]{subsection name}\subsectionname~\insertsubsectionnumber} % \vskip1em\par \par \addvspace{\glueexpr\CTEX@subsection@beforeskip\relax}% \CTEX@heading@format@initial \CTEX@subsection@format{% \CTEX@indentbox{\CTEX@subsection@indent}% \ifodd \CTEX@subsection@numbering \CTEX@subsectionname \CTEX@subsection@aftername \fi \begin{beamercolorbox}[sep=8pt,center,#1]{part title} % \usebeamerfont{subsection title}\insertsubsection\par \CTEX@subsection@titleformat \insertsubsection \CTEX@subsection@aftertitle \end{beamercolorbox}}% \par \addvspace{\glueexpr\CTEX@subsection@afterskip\relax}% \endgroup} % \end{macrocode} % % 将 \cls{beamer} 的默认模板重定向为 \texttt{CTEX} 模板。 % \begin{macrocode} \defbeamertemplatealias{part page}{default}{CTEX} \defbeamertemplatealias{section page}{default}{CTEX} \defbeamertemplatealias{subsection page}{default}{CTEX} % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOn % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{标题编号和目录的层次设置} % % \changes{v2.5.2}{2020/05/06}{新增标题选项 \opt{secnumdepth} 和 \opt{tocdepth}。} % % \begin{macro}{secnumdepth, tocdepth} % \opt{secnumdepth} 在 \cls{beamer} 下无意义。 % \begin{macrocode} \ctex_define:n { %<*!beamer> secnumdepth .code:n = \ctex_heading_depth:ne { secnumdepth } {#1} , secnumdepth .value_required:n = true , % tocdepth .code:n = \ctex_heading_depth:ne { tocdepth } {#1} , tocdepth .value_required:n = true } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_heading_depth:nn} % 注意此处 \tn{setcounter} 的赋值是全局的。 % \begin{macrocode} \cs_new_protected:Npn \ctex_heading_depth:nn #1#2 { \prop_get:NnNTF \c_@@_heading_level_prop {#2} \l_@@_tmp_tl { \setcounter {#1} { \l_@@_tmp_tl } } { \setcounter {#1} { \int_eval:n {#2} } } } \cs_generate_variant:Nn \ctex_heading_depth:nn { ne } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\c_@@_heading_level_prop} % 章节层次与名称的对应表。 % \begin{macrocode} \prop_const_from_keyval:Nn \c_@@_heading_level_prop { %<*article|beamer> part = 0 , % %<*book|report> part = -1 , chapter = 0 , % section = 1 , subsection = 2 , subsubsection = 3 , paragraph = 4 , subparagraph = 5 } % \end{macrocode} % \end{variable} % % \subsubsection{标签引用数字的汉化} % % \begin{macro}[int]{\refstepcounter} % 对标题进行引用时,设置标签为通过 \opt{number} 选项设置的形式。 % \begin{macrocode} \cs_new_protected: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}[int]{\ctex_varioref_hook:} % 关于标签引用的宏包可能会修改 \tn{refstepcounter}。其中 \pkg{cleveref} 和 % \pkg{hyperref} 宏包都会保存之前的定义,并且它们都要求尽可能晚的被载入,所以 % 对我们上述的修改影响不大。需要注意的是 \pkg{varioref} 宏包,如果它在 % \CTeX{} 之后被载入,我们之前的修改将会被覆盖。 % 较新版 \LaTeX \ 内核已经包含 \tn{labelformat},可以直接使用。 % \begin{macrocode} \cs_new_protected:Npn \ctex_varioref_hook: { \seq_map_inline:Nn \c_@@_headings_seq { \ctex_fix_varioref_label:n { ##1 } } \ctex_at_end_package:nn { cleveref } { \ctex_cleveref_hook: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\ctex_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:Npn \ctex_fix_varioref_label:n #1 { \tl_if_empty:cT { p@#1 } { \exp_args:Nne \labelformat {#1} { \exp_not:c { CTEX@the#1 } } } } % \end{macrocode} % \end{macro} % % \changes{v2.5.3}{2020/06/04}{兼容 \pkg{cleveref}。} % \changes{v2.5.4}{2020/06/17}{同时兼容 \pkg{cleveref} 和 \pkg{hyperref}。} % \changes{v2.5.7}{2021/06/04}{同时兼容 \pkg{cleveref} 和 \cls{beamer}。} % % \begin{macro}{patch/cleveref} % \pkg{cleveref} 宏包长期未维护,与较新的 \LaTeX{} 内核和 \pkg{hyperref} % 存在兼容问题。\CTeX{} 提供了对 \pkg{cleveref} 的补丁,但用户也可以选择 % 关闭它。 % % 当同时使用 \pkg{hyperref} 和 \pkg{cleveref} 时,|\appendix| 之后的交叉引用 % 类型可能不正确(例如,\texttt{appendix} 退化为 \texttt{chapter})。 % 这是上游 \LaTeX{} 内核 \texttt{firstaid} 对 \pkg{cleveref} 补丁不完整所致, % 与 \CTeX{} 无关。可以使用以下方法规避: % \begin{verbatim} % \AddToHook{cmd/appendix/before}{% % \crefalias{chapter}{appendix}% % \crefalias{section}{subappendix}% % \crefalias{subsection}{subsubappendix}% % \crefalias{subsubsection}{subsubsubappendix}% % } % \end{verbatim} % \begin{macrocode} \ctex_define:n { patch / cleveref .bool_set:N = \l_@@_patch_cleveref_bool , patch / cleveref .initial:n = true } % \end{macrocode} % \end{macro} % % \begin{macro}{\ctex_cleveref_hook:,\@@_cleveref_hook_aux:N} % 需要将\pkg{cleveref} 包对应命令中 |\p@|\meta{counter} 的参数及时展开,以兼容 \tn{labelformat}。 % \begin{macrocode} \cs_new_protected:Npn \ctex_cleveref_hook: { \bool_if:NT \l_@@_patch_cleveref_bool { \@ifpackageloaded { hyperref } { \@ifpackagewith { hyperref } { implicit = false } { } { \@@_cleveref_hook_aux:N \H@refstepcounter } } { \@@_cleveref_hook_aux:N \refstepcounter@noarg \@@_cleveref_hook_aux:N \refstepcounter@optarg } \@@_cleveref_hook_aux:N \appendix } } \cs_new_protected:Npn \@@_cleveref_hook_aux:N #1 { \ctex_patch_cmd_all:NnnnTF #1 { \ExplSyntaxOff \char_set_catcode_letter:n { 64 } } { \endcsname \csname the } { \expandafter \endcsname \csname the } { } { \ctex_patch_failure:N #1 } } % \end{macrocode} % \end{macro} % % \changes{v2.5}{2020/04/19}{应用新内核中的 \tn{labelformat}。} % % 如果 \pkg{varioref} 已经被载入,则使用它来设置。 % \begin{macrocode} \cs_if_exist:NTF \labelformat { \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{\texttt{ctex.sty} 的 \opt{heading} 选项} % % \begin{macrocode} %<*ctex|ctexheading> % \end{macrocode} % % \begin{variable}{\c_@@_std_class_tl} % 用于记录被引入的标准文档类。 % \begin{macrocode} \clist_map_inline:nn { article , book , report , beamer } { \@ifclassloaded {#1} { \clist_map_break:n { \tl_const:Nn \c_@@_std_class_tl {#1} } } { } } % \end{macrocode} % \end{variable} % % 若标准文档类被引入,则载入对应的标题定义文件。否则视 \tn{chapter} 是否有定义来 % 引入 \cls{book} 或者 \cls{article}。 % \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 %\use:n { \tl_if_exist:NTF \c_@@_std_class_tl { \cs_new_eq:NN \c_@@_class_tl \c_@@_std_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:nne { ctex } { not-standard-class } { \c_@@_class_tl } } \ctex_file_input:n { ctex-heading- \c_@@_class_tl .def } } % { \ctex_scheme_input:o { \l_@@_scheme_tl } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{中文字号} % % \begin{macrocode} %<*class|ctex|ctexsize> % \end{macrocode} % % \changes{v2.0}{2014/03/08}{将中文字号功能提取到可以独立使用的 \pkg{ctexsize}。} % % \begin{macro}{\zihao} % \begin{macrocode} \NewDocumentCommand \zihao { m } { \exp_args:Ne \ctex_zihao:n {#1} \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_zihao:n} % \begin{macrocode} \cs_new_protected: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}{\c_@@_font_size_prop} % \begin{macro}{\@@_save_font_size:nn} % \begin{macro}[int]{\ctex_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 \l_@@_font_size_temp_prop \seq_new:N \l_@@_font_size_temp_seq \cs_new_protected:Npn \@@_save_font_size:nn #1#2 { \prop_put:Nne \l_@@_font_size_temp_prop {#1} { { \dim_to_decimal:n {#2} } { \dim_to_decimal:n { (#2) * 6 / 5 } } } \seq_put_right:Nn \l_@@_font_size_temp_seq {#1} } \cs_new_eq:NN \ctex_save_font_size:nn \@@_save_font_size:nn \group_begin: \prop_clear:N \l_@@_font_size_temp_prop \seq_clear:N \l_@@_font_size_temp_seq \str_case:onF { \g_@@_font_size_system_tl } { { word } { \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 } } { letterpress } { \clist_map_inline:nn { { 8 } { 4 bp } , { 7 } { 5.25 bp } , { -6 } { 7.5 bp } , { 6 } { 8 bp } , { -5 } { 9 bp } , { 5 } { 10.5 bp } , { -4 } { 12 bp } , { 4 } { 14 bp } , { -3 } { 15 bp } , { 3 } { 16 bp } , { -2 } { 18 bp } , { 2 } { 21 bp } , { -1 } { 24 bp } , { 1 } { 28 bp } , { -0 } { 36 bp } , { 0 } { 42 bp } } { \@@_save_font_size:nn #1 } } } { \file_if_exist:nTF { ctex-fontsize- \g_@@_font_size_system_tl .def } { \ctex_file_input:n { ctex-fontsize- \g_@@_font_size_system_tl .def } } { \msg_error:nne { ctex } { fontsize-system-not-found } { \g_@@_font_size_system_tl } \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 } } } \exp_args:NNe \prop_const_from_keyval:Nn \c_@@_font_size_prop { \prop_to_keyval:N \l_@@_font_size_temp_prop } \exp_args:NNe \seq_const_from_clist:Nn \c_@@_font_size_seq { \seq_use:Nn \l_@@_font_size_temp_seq { , } } \group_end: \msg_new:nnnn { ctex } { fontsize-system-not-found } { CTeX~font~size~system~`#1'~could~not~be~found. \\ The~`word'~system~will~be~used~instead. } { You~may~need~to~create~`ctex-fontsize-#1.def'. } % \end{macrocode} % \end{macro} % \end{macro} % \end{variable} % % \begin{macro}[int]{\ctex_declare_math_sizes:nnnn} % \begin{macrocode} \cs_new_protected: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}{\@@_get_font_sizes:Nn} % \begin{macrocode} \cs_new_protected: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:Ne #1 { { \tl_head:N \l_@@_tmp_tl } } } { \tl_put_right:Ne #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}[int]{\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:Npn #3 { \@setfontsize #3 {#1} {#2} #4 } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \int_case:nn { \g_@@_font_size_int } { { 0 } { \file_input:n { ctex-c5size.clo } } { 1 } { \file_input:n { ctex-cs4size.clo } } } % \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|ctex> % \end{macrocode} % % \subsection{更新行距} % % \cs{l_@@_line_spread_fp} 被设置了才有必要更新行距和 \tn{footnotesep}。 % \begin{macrocode} \fp_if_nan:nF { \l_@@_line_spread_fp } { \exp_args:Ne \linespread { \fp_use:N \l_@@_line_spread_fp } % \end{macrocode} % % \changes{v2.0}{2014/04/23}{调整 \tn{footnotesep} 的大小,以适合行距的变化。} % % \begin{variable}[int]{\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} % \changes{v2.4.12}{2017/12/05}{不依赖 \tn{ifincsname}。} % \file{ctex-faq.sty} 中的定义是 % \begin{verbatim} % \DeclareRobustCommand\CTeX{$\mathbb{C}$\kern-.05em\TeX} % \end{verbatim} % 然而 \tn{mathbb} 未必有定义,这里就不采用它了,只定义最简单的形式。 % \CTeX{} 可以直接用在 PDF 书签中。 % \begin{macrocode} \NewDocumentCommand \CTeX { } { C \TeX } \ctex_at_end_package:nn { hyperref } { \pdfstringdefDisableCommands { \tl_set:Nn \CTeX { CTeX } } } % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/28}{\opt{captiondelimiter} 是过时选项。} % \begin{macro}{captiondelimiter} % 过时选项。 % \begin{macrocode} \ctex_define:n { captiondelimiter .code:n = { \ctex_deprecated_option:n { You~can~load~the~package~`caption'~to~get~its~functionality. } } } % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/09} % {解决 \pkg{etoolbox} 与 \pkg{breqn} 关于 \tn{end} 的冲突。} % \changes{v2.2}{2015/06/23}{删去 \pkg{etoolbox} 与 \pkg{breqn} 的兼容补丁。} % % \subsection{载入中文字库} % % \begin{macro}[int]{\ctex_fontset_error:n} % 字库不可用时给出紧急错误信息,停止读取定义文件。 % \begin{macrocode} \cs_new_protected: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}[int]{\ctex_fontset_case:nnn} % $3$ 个参数依次为 \pdfTeX、\upTeX\ 和 \XeTeX/\LuaTeX。 % \begin{macrocode} \cs_new:Npx \ctex_fontset_case:nnn #1#2#3 { \sys_if_engine_pdftex:TF {#1} { \sys_if_engine_uptex:TF {#2} {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_fontset_case:nnnn} % $4$ 个参数依次为 \pdfTeX(生成 PDF)、\pdfTeX(生成 DVI)、\upTeX 和 % \XeTeX/\LuaTeX。 % \begin{macrocode} \cs_new:Npx \ctex_fontset_case:nnnn #1#2#3#4 { \sys_if_engine_pdftex:TF { \sys_if_output_pdf:TF {#1} {#2} } { \sys_if_engine_uptex:TF {#3} {#4} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_detect_platform:} % 根据操作系统判断默认字体配置。 % \begin{macrocode} \cs_new_protected:Npn \ctex_detect_platform: { \sys_if_platform_windows:TF { \tl_gset:Nn \g_@@_fontset_tl { windows } } { \ctex_if_platform_macos:TF { \tl_gset:Nn \g_@@_fontset_tl { mac } } { \tl_gset:Nn \g_@@_fontset_tl { fandol } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_if_platform_macos:TF} % \changes{v2.1}{2015/06/17}{改用 \file{/Library/Fonts/Songti.ttc} 为特征文件。} % \changes{v2.5}{2019/10/25}{改用 \file{/System/Library/Fonts/Menlo.ttc} % 为特征文件。} % 以特定字体判断 macOS 系统。 % \begin{macrocode} \cs_new_protected:Npn \ctex_if_platform_macos:TF { \file_if_exist:nTF { /System/Library/Fonts/Menlo.ttc } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_load_fontset:} % 如果用户没有指定字体,则探测操作系统,载入相应的字体配置。 % \begin{macrocode} \cs_new_protected:Npn \ctex_load_fontset: { \tl_if_empty:NTF \g_@@_fontset_tl { \ctex_detect_platform: } { \bool_lazy_or:nnTF { \str_if_eq_p:on { \g_@@_fontset_tl } { windowsnew } } { \str_if_eq_p:on { \g_@@_fontset_tl } { windowsold } } { \msg_warning:nnee { ctex } { deprecated-fontset } { \g_@@_fontset_tl } { windows } \tl_gset:Nn \g_@@_fontset_tl { windows } } { \file_if_exist:nF { ctex-fontset- \g_@@_fontset_tl .def } { \use:e { \ctex_detect_platform: \msg_error:nnee { ctex } { fontset-not-found } { \g_@@_fontset_tl } { \exp_not:N \g_@@_fontset_tl } } } } } \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } } \msg_new:nnn { ctex } { deprecated-fontset } { CTeX~fontset~`#1'~is~deprecated.\\ Fontset~`#2'~will~be~used~instead. } \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. } \@onlypreamble \ctex_load_fontset: % \end{macrocode} % \end{macro} % % \begin{macro}{fontset} % 在导言区通过 \tn{ctexset} 载入中文字库的选项。 % \begin{macrocode} \ctex_define:n { fontset .code:n = { \ctex_if_preamble:TF { \str_if_eq:eeTF {#1} { none } { \msg_warning:nnn { ctex } { invalid-value } {#1} } { \str_if_eq:onTF { \g_@@_fontset_tl } { none } { \tl_gset:Ne \g_@@_fontset_tl {#1} \ctex_load_fontset: } { \msg_error:nnee { 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{\texttt{ctex.cfg}} % % \begin{macrocode} \ctex_at_end:n { \ctex_file_input:n { ctex.cfg } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \end{implementation}