% \iffalse meta-comment % !TeX program = XeLaTeX % !TeX encoding = UTF-8 % % Copyright (C) 2003--2016 % CTEX.ORG and any individual authors listed elsewhere in this file. % -------------------------------------------------------------------------- % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3c of this license or (at your option) any later % version. This version of this license is in % http://www.latex-project.org/lppl/lppl-1-3c.txt % and the latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of % LaTeX version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainers of this work are Leo Liu, Qing Lee and Liam Huang. % % -------------------------------------------------------------------------- % %<*internal> \iffalse % %<*readme> ctex is a collection of macro packages and document classes for LaTeX Chinese typesetting. This package is licensed in LPPL. The authors and contributors of this package are: * Wu Lingyun * Jiang Jiang * Wang Yue * Liu Haiyang * Li Yanrui * Chen Zhichu * Li Qing * Liam Huang If you are interested in the process of development you may observe https://github.com/CTeX-org/ctex-kit Report feedback in the Issues section of ctex-kit project, or in [ctex](http://bbs.ctex.org) forum. This package consists of the file ctex.dtx, and the derived files ctex.pdf, ctex.ins, ctex.sty, ctexsize.sty, ctexheading.sty, ctexart.cls, ctexbook.cls, ctexrep.cls, ctexcap.sty, ctexhook.sty, ctexpatch.sty, ctex-c5size.clo, ctex-cs4size.clo, ctex-article.def, ctex-book.def, ctex-report.def, ctex-scheme-plain.def, ctex-scheme-plain-article.def, ctex-scheme-plain-book.def, ctex-scheme-plain-report.def, ctex-scheme-chinese.def, ctex-scheme-chinese-article.def, ctex-scheme-chinese-book.def, ctex-scheme-chinese-report.def, ctex-name-gbk.cfg, ctex-name-utf8.cfg, ctex.cfg, ctexopts.cfg, ctex-engine-pdftex.def, ctex-engine-xetex.def, ctex-engine-luatex.def, c19rm.fd, c19sf.fd, c19tt.fd, c70rm.fd, c70sf.fd, c70tt.fd, ctex-fontset-windows.def, ctex-fontset-windowsnew.def, ctex-fontset-windowsold.def, ctex-fontset-adobe.def, ctex-fontset-fandol.def, ctex-fontset-mac.def, ctex-fontset-founder.def, ctex-fontset-ubuntu.def, ctexspa.def, ctexpunct.spa, ctexmakespa.tex, ctexspamacro.tex, zhadobefonts.tex, zhfandolfonts.tex, zhfounderfonts.tex, zhubuntufonts.tex, zhwindowsfonts.tex, and README (this file). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> \newread\inputcheck \openin\inputcheck=ctex.ver \ifeof\inputcheck \def\ctexPutVersion{\string\GetIdInfo$Id$} \else \input ctex.ver \fi \closein\inputcheck \input l3docstrip.tex \def\checkOption<#1{% \ifcase \ifx*#10\else \ifx/#11\else \ifx+#12\else \ifx-#13\else \ifx<#14\else \ifx @#15\else \ifx.#16\else 7\fi\fi\fi\fi\fi\fi\fi\relax \expandafter\starOption\or \expandafter\slashOption\or \expandafter\plusOption\or \expandafter\minusOption\or \expandafter\verbOption\or \expandafter\moduleOption\or \expandafter\expOption\or \expandafter\doOption\fi #1% } \def\expOption .#1>#2\endLine{% \maybeMsg{<.#1 . >}% \Evaluate{#1}% \begingroup \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \xdef\expandedLineStuff{\scantokens{#2\noexpand}}% \endgroup \def\do##1##2##3{% \if1\Expr{##2}\StreamPut##1{\expandedLineStuff}\fi }% \activefiles } \keepsilent \askforoverwritefalse \preamble Copyright (C) 2003--2015 CTEX.ORG and any individual authors listed in the documentation. ------------------------------------------------------------------------------ This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status `maintained'. The Current Maintainers of this work are Leo Liu, Qing Lee and Liam Huang. ------------------------------------------------------------------------------ \endpreamble \postamble This package consists of the file ctex.dtx, and the derived files ctex.pdf, ctex.ins, ctex.sty, ctexsize.sty, ctexheading.sty, ctexart.cls, ctexbook.cls, ctexrep.cls, ctexcap.sty, ctexhook.sty, ctexpatch.sty, ctex-c5size.clo, ctex-cs4size.clo, ctex-article.def, ctex-book.def, ctex-report.def, ctex-scheme-plain.def, ctex-scheme-plain-article.def, ctex-scheme-plain-book.def, ctex-scheme-plain-report.def, ctex-scheme-chinese.def, ctex-scheme-chinese-article.def, ctex-scheme-chinese-book.def, ctex-scheme-chinese-report.def, ctex-name-gbk.cfg, ctex-name-utf8.cfg, ctex.cfg, ctexopts.cfg, ctex-engine-pdftex.def, ctex-engine-xetex.def, ctex-engine-luatex.def, c19rm.fd, c19sf.fd, c19tt.fd, c70rm.fd, c70sf.fd, c70tt.fd, ctex-fontset-windows.def, ctex-fontset-windowsnew.def, ctex-fontset-windowsold.def, ctex-fontset-adobe.def, ctex-fontset-fandol.def, ctex-fontset-mac.def, ctex-fontset-founder.def, ctex-fontset-ubuntu.def, ctexspa.def, ctexpunct.spa, ctexmakespa.tex, ctexspamacro.tex, zhadobefonts.tex, zhfandolfonts.tex, zhfounderfonts.tex, zhubuntufonts.tex, zhwindowsfonts.tex, and README. \endpostamble \declarepostamble\emptypostamble \endpostamble \generate { \usedir{tex/latex/ctex} \file{ctex.sty} {\from{\jobname.dtx}{style,ctex}} \file{ctexsize.sty} {\from{\jobname.dtx}{style,ctexsize}} \file{ctexheading.sty} {\from{\jobname.dtx}{style,ctexheading}} \file{ctexart.cls} {\from{\jobname.dtx}{class,article}} \file{ctexbook.cls} {\from{\jobname.dtx}{class,book}} \file{ctexrep.cls} {\from{\jobname.dtx}{class,report}} \usepostamble\emptypostamble \file{ctexcap.sty} {\from{\jobname.dtx}{ctexcap}} \file{ctexhook.sty} {\from{\jobname.dtx}{ctexhook}} \file{ctexpatch.sty} {\from{\jobname.dtx}{ctexpatch}} \file{ctex-c5size.clo} {\from{\jobname.dtx}{c5size}} \file{ctex-cs4size.clo} {\from{\jobname.dtx}{cs4size}} \file{ctex-article.def} {\from{\jobname.dtx}{heading,article}} \file{ctex-book.def} {\from{\jobname.dtx}{heading,book}} \file{ctex-report.def} {\from{\jobname.dtx}{heading,report}} \file{ctex-scheme-plain.def} {\from{\jobname.dtx}{scheme,generic,plain}} \file{ctex-scheme-plain-article.def} {\from{\jobname.dtx}{scheme,article,plain}} \file{ctex-scheme-plain-book.def} {\from{\jobname.dtx}{scheme,book,plain}} \file{ctex-scheme-plain-report.def} {\from{\jobname.dtx}{scheme,report,plain}} \file{ctex-scheme-chinese.def} {\from{\jobname.dtx}{scheme,generic,chinese}} \file{ctex-scheme-chinese-article.def} {\from{\jobname.dtx}{scheme,article,chinese}} \file{ctex-scheme-chinese-book.def} {\from{\jobname.dtx}{scheme,book,chinese}} \file{ctex-scheme-chinese-report.def} {\from{\jobname.dtx}{scheme,report,chinese}} \file{ctex-name-gbk.cfg} {\from{\jobname.dtx}{GBK}} \file{ctex-name-utf8.cfg} {\from{\jobname.dtx}{UTF8}} \file{ctex.cfg} {\from{\jobname.dtx}{config}} \file{ctexopts.cfg} {\from{\jobname.dtx}{ctexopts}} \file{ctex-engine-pdftex.def} {\from{\jobname.dtx}{pdftex}} \file{ctex-engine-xetex.def} {\from{\jobname.dtx}{xetex}} \file{ctex-engine-luatex.def} {\from{\jobname.dtx}{luatex}} \file{c19rm.fd} {\from{\jobname.dtx}{rm,c19}} \file{c19sf.fd} {\from{\jobname.dtx}{sf,c19}} \file{c19tt.fd} {\from{\jobname.dtx}{tt,c19}} \file{c70rm.fd} {\from{\jobname.dtx}{rm,c70}} \file{c70sf.fd} {\from{\jobname.dtx}{sf,c70}} \file{c70tt.fd} {\from{\jobname.dtx}{tt,c70}} \file{ctex-fontset-windows.def} {\from{\jobname.dtx}{fontset,windows}} \file{ctex-fontset-windowsnew.def} {\from{\jobname.dtx}{fontset,windowsnew}} \file{ctex-fontset-windowsold.def} {\from{\jobname.dtx}{fontset,windowsold}} \file{ctex-fontset-adobe.def} {\from{\jobname.dtx}{fontset,adobe}} \file{ctex-fontset-fandol.def} {\from{\jobname.dtx}{fontset,fandol}} \file{ctex-fontset-mac.def} {\from{\jobname.dtx}{fontset,mac}} \file{ctex-fontset-founder.def} {\from{\jobname.dtx}{fontset,founder}} \file{ctex-fontset-ubuntu.def} {\from{\jobname.dtx}{fontset,ubuntu}} \file{ctexspa.def} { \from{\jobname.dtx} {ctexspa} \from{ctexpunct.spa} {} } \file{ctexmakespa.tex} {\from{\jobname.dtx}{spa,make}} \file{ctexspamacro.tex} {\from{\jobname.dtx}{spa,macro}} \file{zhadobefonts.tex} {\from{\jobname.dtx}{zhmap,adobe}} \file{zhfandolfonts.tex} {\from{\jobname.dtx}{zhmap,fandol}} \file{zhfounderfonts.tex} {\from{\jobname.dtx}{zhmap,founder}} \file{zhubuntufonts.tex} {\from{\jobname.dtx}{zhmap,ubuntu}} \file{zhwindowsfonts.tex} {\from{\jobname.dtx}{zhmap,windows}} \usedir{source/latex/ctex} \file{\jobname.ins} {\from{\jobname.dtx}{install}} \nopreamble\nopostamble \usedir{doc/latex/ctex} \file{README.txt} {\from{\jobname.dtx}{readme}} } \catcode32=12\space \Msg{*************************************************************} \Msg{* *} \Msg{* To finish the installation you have to move the following *} \Msg{* file into proper directories searched by TeX: *} \Msg{* *} \Msg{* The recommended directory is TDS:tex/latex/ctex *} \Msg{* *} \Msg{* ctex.sty *} \Msg{* ctexsize.sty *} \Msg{* ctexheading.sty *} \Msg{* ctexart.cls *} \Msg{* ctexbook.cls *} \Msg{* ctexrep.cls *} \Msg{* ctexcap.sty *} \Msg{* ctexhook.sty *} \Msg{* ctexpatch.sty *} \Msg{* ctex-c5size.clo *} \Msg{* ctex-cs4size.clo *} \Msg{* ctex-article.def *} \Msg{* ctex-book.def *} \Msg{* ctex-report.def *} \Msg{* ctex-scheme-plain.def *} \Msg{* ctex-scheme-plain-article.def *} \Msg{* ctex-scheme-plain-book.def *} \Msg{* ctex-scheme-plain-report.def *} \Msg{* ctex-scheme-chinese.def *} \Msg{* ctex-scheme-chinese-article.def *} \Msg{* ctex-scheme-chinese-book.def *} \Msg{* ctex-scheme-chinese-report.def *} \Msg{* ctex-name-gbk.cfg *} \Msg{* ctex-name-utf8.cfg *} \Msg{* ctex.cfg *} \Msg{* ctexopts.cfg *} \Msg{* ctex-engine-pdftex.def *} \Msg{* ctex-engine-xetex.def *} \Msg{* ctex-engine-luatex.def *} \Msg{* c19rm.fd *} \Msg{* c19sf.fd *} \Msg{* c19tt.fd *} \Msg{* c70rm.fd *} \Msg{* c70sf.fd *} \Msg{* c70tt.fd *} \Msg{* ctex-fontset-windows.def *} \Msg{* ctex-fontset-windowsnew.def *} \Msg{* ctex-fontset-windowsold.def *} \Msg{* ctex-fontset-adobe.def *} \Msg{* ctex-fontset-fandol.def *} \Msg{* ctex-fontset-mac.def *} \Msg{* ctex-fontset-founder.def *} \Msg{* ctex-fontset-ubuntu.def *} \Msg{* ctexspa.def *} \Msg{* ctexmakespa.tex *} \Msg{* ctexspamacro.tex *} \Msg{* zhadobefonts.tex *} \Msg{* zhfandolfonts.tex *} \Msg{* zhfounderfonts.tex *} \Msg{* zhubuntufonts.tex *} \Msg{* zhwindowsfonts.tex *} \Msg{* *} \Msg{* To produce the documentation run the file ctex.dtx *} \Msg{* through XeLaTeX. *} \Msg{* *} \Msg{* Happy TeXing! *} \Msg{* *} \Msg{*************************************************************} \endbatchfile % %<*internal> \fi % %<*!(readme|install|zhmap|spa)> %<*!(c19|c70|ctexspa)> %<*driver|class|style|ctexcap|ctexhook|ctexpatch> \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} % %<.!(readme|install|zhmap|spa|c19|c70|ctexspa)>\ctexPutVersion %<*driver> \InputIfFileExists{ctex.ver}{}{ \def\ctexGetVersionInfo{\GetIdInfo$Id$}} \ctexGetVersionInfo {ctex source file} \ProvidesExplFile{\ExplFileName.\ExplFileExtension} % % {Chinese adapter in LaTeX (CTEX)} %\ProvidesExplPackage{\ExplFileName} % {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 in LaTeX (CTEX)} %\ProvidesExplPackage{ctexcap} % {Document and package hooks (CTEX)} %\ProvidesExplPackage{ctexhook} % {Patching commands (CTEX)} %\ProvidesExplPackage{ctexpatch} % {c5size option (CTEX)} %\ProvidesExplFile{ctex-c5size.clo} % {cs4size option (CTEX)} %\ProvidesExplFile{ctex-cs4size.clo} % {Heading modification for article (CTEX)} %\ProvidesExplFile{ctex-article.def} % {Heading modification for book (CTEX)} %\ProvidesExplFile{ctex-book.def} % {Heading modification for report (CTEX)} %\ProvidesExplFile{ctex-report.def} % {Plain scheme for generic (CTEX)} %\ProvidesExplFile{ctex-scheme-plain.def} % {Plain scheme for article (CTEX)} %\ProvidesExplFile{ctex-scheme-plain-article.def} % {Plain scheme for book (CTEX)} %\ProvidesExplFile{ctex-scheme-plain-book.def} % {Plain scheme for report (CTEX)} %\ProvidesExplFile{ctex-scheme-plain-report.def} % {Chinese scheme for generic (CTEX)} %\ProvidesExplFile{ctex-scheme-chinese.def} % {Chinese scheme for article (CTEX)} %\ProvidesExplFile{ctex-scheme-chinese-article.def} % {Chinese scheme for book (CTEX)} %\ProvidesExplFile{ctex-scheme-chinese-book.def} % {Chinese scheme for report (CTEX)} %\ProvidesExplFile{ctex-scheme-chinese-report.def} % {Caption with encoding GBK (CTEX)} %\ProvidesExplFile{ctex-name-gbk.cfg} % {Caption with encoding UTF8 (CTEX)} %\ProvidesExplFile{ctex-name-utf8.cfg} % {Configuration file (CTEX)} %\ProvidesExplFile{\ExplFileName.cfg} % {Option configuration file (CTEX)} %\ProvidesExplFile{ctexopts.cfg} % {(pdf)LaTeX adapter (CTEX)} %\ProvidesExplFile{ctex-engine-pdftex.def} % {XeLaTeX adapter (CTEX)} %\ProvidesExplFile{ctex-engine-xetex.def} % {LuaLaTeX adapter (CTEX)} %\ProvidesExplFile{ctex-engine-luatex.def} % {Windows fonts definition (CTEX)} %\ProvidesExplFile{ctex-fontset-windows.def} % {Windows fonts definition for Vista or later version (CTEX)} %\ProvidesExplFile{ctex-fontset-windowsnew.def} % {Windows fonts definition for XP or earlier version (CTEX)} %\ProvidesExplFile{ctex-fontset-windowsold.def} % {Adobe fonts definition (CTEX)} %\ProvidesExplFile{ctex-fontset-adobe.def} % {Fandol fonts definition (CTEX)} %\ProvidesExplFile{ctex-fontset-fandol.def} % {Mac OS X fonts definition (CTEX)} %\ProvidesExplFile{ctex-fontset-mac.def} % {Founder fonts definition (CTEX)} %\ProvidesExplFile{ctex-fontset-founder.def} % {Ubuntu fonts definition (CTEX)} %\ProvidesExplFile{ctex-fontset-ubuntu.def} {\ExplFileDate}{2.3}{\ExplFileDescription} % %\ProvidesFile{c19rm.fd}% %\ProvidesFile{c19sf.fd}% %\ProvidesFile{c19tt.fd}% %\ProvidesFile{c70rm.fd}% %\ProvidesFile{c70sf.fd}% %\ProvidesFile{c70tt.fd}% %\ProvidesFile{ctexspa.def}% % [2016/02/02 v2.3 Chinese font definition (CTEX)] % [2016/02/02 v2.3 Space info for CJKpunct (CTEX)] % %<*driver> \ExplSyntaxOff \let\ctexrevnum\ExplFileVersion \expandafter\let\csname ver@thumbpdf.sty\endcsname\fmtversion \documentclass[a4paper,full,numbered]{l3doc} \usepackage[UTF8, punct = kaiming, heading, linespread = 1.2, sub3section]{ctex} \ctexset{ abstractname = 简介, indexname = 代码索引, section = { format = \Large\bfseries\raggedright, name = {第,节}, }, } \usepackage[toc]{multitoc} \usepackage{geometry} \usepackage{tabularx} \usepackage{siunitx} \usepackage{unicode-math} \geometry{includemp,hmargin={0mm,15mm},vmargin={25mm,15mm},footskip=7mm} \hypersetup{pdfstartview=FitH,bookmarksdepth=subparagraph} \setcounter{secnumdepth}{4} \setcounter{tocdepth}{2} \newcommand*\email{\nolinkurl} \setmainfont{TeX Gyre Pagella} \setsansfont[ BoldFont = * Semibold, BoldItalicFont = * Semibold Italic]{Source Sans Pro} \setmonofont[ UprightFont=* Light, BoldFont=* Bold, SlantedFont=* Light Oblique]{CMU Typewriter Text} \setmathfont{texgyrepagella-math.otf} \usepackage{xcolor} \usepackage{caption} \captionsetup{strut=off, labelsep=quad, labelfont+=bf} \makeatletter %% <--- http://tex.stackexchange.com/a/40896 \patchcmd{\@addtocurcol}% {\vskip \intextsep}% {\edef\save@first@penalty{\the\lastpenalty}\unpenalty \ifnum \lastpenalty = \@M % hopefully the OR penalty \unpenalty \else \penalty \save@first@penalty \relax % put it back \fi \ifnum\outputpenalty <-\@Mii \addvspace\intextsep \vskip\parskip \else \addvspace\intextsep \fi}% {\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}} \patchcmd{\@addtocurcol}% {\vskip\intextsep \ifnum\outputpenalty <-\@Mii \vskip -\parskip\fi}% {\ifnum\outputpenalty <-\@Mii \aftergroup\vskip\aftergroup\intextsep \aftergroup\nointerlineskip \else \vskip\intextsep \fi}% {\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}} \patchcmd{\@getpen}{\@M}{\@Mi} {\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}} %% ---> %% 不对代码实现的 \section 以下标题编目录。 \AtBeginEnvironment{implementation}{% \ifnum\value{tocdepth}>\@ne \addtocontents{toc}{\protect\value{tocdepth}=1\relax}% \fi} \ifxetex \let\ctexdocverbaddon\xeCJKVerbAddon \def\ctexdisableecglue{\xeCJKsetup{CJKecglue}} \appto\meta@font@select{\ifinner\ctexdisableecglue\fi} \else \let\ctexdocverbaddon\relax \def\ctexdisableecglue{\ltjsetparameter{autoxspacing=false}} \appto\meta@font@select{\ctexdisableecglue} \fi \setlist{noitemsep,topsep=\smallskipamount} \setlist[1]{labelindent=\parindent} \setlist[enumerate]{leftmargin=*} \setlist[itemize]{leftmargin=*} \newlist{optdesc}{description}{3} %% 设置间距为 \marginparsep,与 l3doc 一致 \setlist[optdesc]{% font=\mdseries\small\ttfamily,align=right,listparindent=\parindent, labelsep=\marginparsep,labelindent=-\marginparsep,leftmargin=*} \fvset{ fontsize=\small,baselinestretch=1,numbersep=5pt, formatcom=\ctexdocverbaddon, listparameters=\setlength\topsep{\MacrocodeTopsep}} \DefineVerbatimEnvironment{frameverb}{Verbatim}{% gobble=4, frame=single,framesep=8pt, listparameters= \setlength\topsep{\medskipamount}% \appto\FV@EndList{\nointerlineskip}} \DefineVerbatimEnvironment{ctexexam}{Verbatim}{% gobble=4, frame=single,framesep=10pt, label=\rule{0pt}{12pt}\textnormal{\bfseries 例 \arabic{ctexexam}}, listparameters= \setlength\topsep{\bigskipamount}% \refstepcounter{ctexexam}\ctexexamlabelref \appto\FV@EndList{\nointerlineskip}} \define@key{FV}{labelref}{\def\ctexexamlabelref{\label{#1}}} \let\ctexexamlabelref\empty \newcounter{ctexexam} \BeforeBeginEnvironment{function}{\par\nointerlineskip} \AtEndEnvironment{function}{% \par\xdef\ctexfixprevdepth{\prevdepth=\the\prevdepth\space}% \ctexfixdescrcoffinyoffset} %% l3doc 会在 function 环境的 syntax 和 descr 盒子中间加上 \medskipamount 的距离。 %% 但是若 syntax 盒子为空(未使用 syntax 环境),就会显得不好看。 %% 此时我们通过将 \medskipamount 设置为零来修正。 \def\ctexfixdescrcoffinyoffset{% \aftergroup\aftergroup\aftergroup\ctexzeromedskipamount} \def\ctexzeromedskipamount{\setlength\medskipamount{\z@skip}} \AfterEndEnvironment{syntax}{\let\ctexfixdescrcoffinyoffset\relax} \AfterEndEnvironment{function}{\ctexfixprevdepth} \AtBeginEnvironment{syntax}{\linespread{1}\ctexdisableecglue} \preto\MacroFont{\linespread{1}} \appto\MacroFont{\hyphenchar\font\m@ne\ctexdocverbaddon} \preto\AltMacroFont{\linespread{1}} \appto\AltMacroFont{\hyphenchar\font\m@ne\ctexdocverbaddon} \def\Module#1{\mbox{% \color{purple}\footnotesize\normalfont\sffamily\textlangle#1\textrangle}} \newcommand*\exptarget{\Hy@raisedlink{\hypertarget{expstar}{}}} \newcommand*\rexptarget{\Hy@raisedlink{\hypertarget{rexpstar}{}}} \newcommand*\expstar{\hyperlink{expstar}{$\star$}} \newcommand*\rexpstar{\hyperlink{rexpstar}{\ding{73}}} \ExplSyntaxOn %% l3doc 会设置列表环境中 \listparindent=\z@,我们在这里恢复它。 \cs_set_eq:NN \list \__codedoc_oldlist:nn \cs_new_nopar:Npn \zihaopt #1 { \exp_last_unbraced:Nf \tl_head:w { \prop_item:Nn \c__ctex_font_size_prop {#1} } { } \q_stop } %% 用 \vtop 让函数名字和语法盒子首行对齐 \patchcmd \__codedoc_syntax:w { { minipage } { \l__codedoc_syntax_dim } } { { minipage } [t] { \l__codedoc_syntax_dim } } { \iow_term:n { *** ~ SUCCESS ~ *** } } { \iow_term:n { *** ~ FAIL ~ *** } } %% 左侧边注的函数列表采用单倍行距 \cs_set_protected_nopar:Npx \__codedoc_typeset_names: { \exp_not:N \linespread { 1 } \exp_not:o { \__codedoc_typeset_names: } } \patchcmd \__codedoc_macro_typeset_one:n { \vbox_unpack_clear:N } { \linespread { 1 } \selectfont \vbox_unpack_clear:N } { \iow_term:n { *** ~ SUCCESS ~ *** } } { \iow_term:n { *** ~ FAIL ~ *** } } %% 不重复使用 \HD@target,避免索引出现重复页码 \cs_set_protected:Npn \__codedoc_special_index_aux:nnnnn #1#2#3#4#5 { \__codedoc_special_index_set:Nn \l__codedoc_index_escaped_macro_tl {#2} \str_if_eq:onTF { \@currenvir } { macrocode } { \codeline@wrindex } { \HD@target \index } { \tl_if_empty:nF { #3 #4 } { #3 \actualchar #4 \levelchar } #1 \actualchar { \token_to_str:N \verbatim@font \c_space_tl \l__codedoc_index_escaped_macro_tl } \encapchar hdclindex{\the\c@HD@hypercount}{#5} } } \DeclareDocumentCommand \cs { O{} m } { \__codedoc_cmd_aux:no {#1} { \c__codedoc_backslash_tl #2 } } \DeclareDocumentCommand \tn { O{} m } { \__codedoc_cmd_aux:no { index = TeX , replace = false , #1 } { \c__codedoc_backslash_tl #2 } } \DeclareDocumentCommand \meta { +m } { \__codedoc_meta_aux:n {#1} } \DeclareExpandableDocumentCommand \bookmarkcstn { O{} m } { \textbackslash \tl_to_str:n {#2} } \cs_new:Npn \bookmarkmeta #1 { < \tl_to_str:n {#1} > } \cs_generate_variant:Nn \__codedoc_cmd_aux:nn { no } \AtBeginEnvironment { syntax } { \char_set_active_eq:NN \| \orbar \char_set_active_eq:NN \( \defaultvalaux } %% 不对目录中出现的 \cs 和 \tn 等编索引 \DeclareDocumentCommand \StopSpecialIndexModule { } { \cs_set_eq:NN \__codedoc_special_index_module:nnnn \use_none:nnnn } \tl_map_inline:nn { \actualchar \encapchar \levelchar } { \exp_args:Nx \DoNotIndex { \bslash \tl_to_str:N #1 } } \ExplSyntaxOff \AtBeginDocument{\addtocontents{toc}{\StopSpecialIndexModule}} \pdfstringdefDisableCommands{% \let\cs\bookmarkcstn \let\tn\bookmarkcstn \let\meta\bookmarkmeta \let\opt\@firstofone} \preto\@thehead{\cslet{MakeUppercase\space}{\@iden}} \def\orbar{\textup{\textbar}} \def\defaultval#1{\textbf{\textup{#1}}} \def\defaultvalaux#1){\defaultval{#1}} \def\TF{true\orbar false} \def\TTF{\defaultval{true}\orbar false} \def\TFF{true\orbar\defaultval{false}} \protected\def\opt{\texttt} \def\pdfTeX{\hologo{pdfTeX}} \def\XeTeX{\hologo{XeTeX}} \def\XeLaTeX{\hologo{XeLaTeX}} \def\LuaLaTeX{\hologo{LuaLaTeX}} \def\pdfLaTeX{\hologo{pdfLaTeX}} \def\LaTeX{\hologo{LaTeX}} \def\LaTeXe{\hologo{LaTeX2e}} \def\LaTeXiii{\hologo{LaTeX3}} \def\dvipdfmx{DVIPDFM\textit{x}} \def\ctexkitrev#1{% \href{https://github.com/CTeX-org/ctex-kit/commit/#1}{\texttt{ctex-kit} rev. #1}} \patchcmd\theCodelineNo{\sffamily\tiny}{\normalfont\sffamily\tiny}{}{} \appto\GlossaryParms{% \def\@idxitem{\par\hangindent 2em }% \def\subitem{\@idxitem\hspace*{1em}}% \def\subsubitem{\@idxitem\hspace*{2em}}} \patchcmd\l@section{2.5em}{1.5em}{}{} \patchcmd\l@subsection{2.5em}{1.5em}{}{} \patchcmd\changes@{\space}{\lbrack}{}{} \patchcmd\@wrglossary{hdpindex}{% \ifnum\c@HD@hypercount=\z@ hdpindex% \else hdclindex{\the\c@HD@hypercount}\fi}{}{} \newenvironment{defaultcapconfig}{% \MakePercentComment \input{ctex-name-utf8.cfg}% \ExplSyntaxOff \MakePercentIgnore}{} \makeatother \EnableCrossrefs \CodelineIndex \RecordChanges \def\glossaryname{版本历史} \GlossaryPrologue{\section{\glossaryname}} \IndexPrologue{% \section{\indexname} \textit{意大利体的数字表示描述对应索引项的页码; 带下划线的数字表示定义对应索引项的代码行号; 罗马字体的数字表示使用对应索引项的代码行号。}} \usepackage{makecell} \newcommand{\bashcmd}{\texttt} \newcommand{\TeXLive}{\TeX\ Live} \newcommand{\MiKTeX}{\hologo{MiKTeX}} \usepackage{threeparttable} \begin{document} \DocInput{\jobname.dtx} \newgeometry{hmargin=15mm,vmargin={25mm,15mm},footskip=7mm} \ctexset{section/numbering=false} \PrintChanges \PrintIndex \end{document} % % % \fi % % \changes{v2.0}{2014/03/06}{应用 \LaTeXiii{} 重新整理代码。} % \changes{v2.0}{2014/03/12}{删除 \file{c19gbsn.fd} 和 \file{c19gkai.fd}。} % \changes{v2.1}{2015/05/18}{将章节标题设置功能提取到可以独立使用的宏包 % \pkg{ctexheading} 中。} % \changes{v2.2}{2015/06/24}{不再依赖 \pkg{etoolbox} 宏包。} % % % \CheckSum{5056} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \GetFileInfo{\jobname.dtx}% % % \title{\bfseries \CTeX{} 宏集手册} % \author{\href{http://www.ctex.org}{ctex.org}} % \date{\filedate\qquad\fileversion\thanks{\ctexkitrev{\ctexrevnum}.}} % \maketitle % % \begin{abstract} % \CTeX{} 宏集是面向中文排版的通用 \LaTeX{} 排版框架,为中文 \LaTeX{} 文档 % 提供了汉字输出支持、标点压缩、字体字号命令、标题文字汉化、中文版式调整、数字 % 日期转换等支持功能,可适应论文、报告、书籍、幻灯片等不同类型的中文文档。 % % \CTeX{} 宏集支持 \LaTeX{}、\pdfLaTeX{}、\XeLaTeX{} 和 \LuaLaTeX{} 等多种不同 % 的编译方式,并为它们提供了统一的界面。主要功能由宏包 \pkg{ctex} 和中文文档类 % \cls{ctexart}、\cls{ctexrep}、\cls{ctexbook} 实现。 % \end{abstract} % % \tableofcontents % % \clearpage % \setlength{\parskip}{0.8ex} % % \begin{documentation} % % \section{介绍} % % \subsection*{历史} % % \CTeX{} 宏集的源头有两个:一是王磊编写的 \cls{cjkbook} 文档类,二是吴凌云编写的 % \file{GB.cap}。 % 这些工作没有经过认真、系统的设计,也没有用户文档,不利于维护和改进。 % % 2003 年,吴凌云使用 \pkg{doc} 和 \pkg{DocStrip} 重构了整个工程,并增加了许多新的功能, % 称为 \pkg{ctex} 宏包。2007 年,oseen 和王越在 \pkg{ctex} 宏包的基础上, % 增加了对 UTF-8 编码的支持,开发出了 \pkg{ctexutf8} 宏包。 % % 2009 年 5 月,我们在 Google Code 建立了 ctex-kit 项目^^A % \footnote{\nolinkurl{http://code.google.com/p/ctex-kit/}}, % 对 \pkg{ctex} 宏包及相关脚本进行了整合,并加入了对 \XeTeX{} 引擎的支持。 % 在开发新版本时,考虑到合作开发和调试的方便,我们放弃了 \pkg{doc} 和 \pkg{DocStrip}, % 采取了直接编写宏包代码的方式。 % % 2014 年 3 月,为了适应 \LaTeX{} 的最新发展,特别是 \LaTeXiii{} 的逐渐成熟,李清用 % \LaTeXiii{} 重构了整个宏包的代码,并重新使用 \pkg{doc} 和 \pkg{DocStrip} 工具进行代码 % 的管理,升级版本号为 2.0,并改称 \CTeX{} 宏集。 % % 2015 年 3 月,由于 Google Code 即将停止服务,ctex-kit 项目迁移至 % \href{https://github.com/CTeX-org/ctex-kit}{GitHub}^^A % \footnote{\url{https://github.com/CTeX-org/ctex-kit}}。 % % 最初,Knuth 在设计开发 \TeX{} 的时候没有考虑到多国语言支持,特别是对多字节的中日韩 % 语言的支持。这使得 \TeX{} 以至后来的 \LaTeX{} 对中文的支持一直不是很好。即使在 % \pkg{CJK} 宏包解决了中文字符处理的问题以后,中文用户使用 \LaTeX{} 仍然要面对许 % 多困难。 % 这些困难里,以章节标题的中文化为最。由于中文和西文语言习惯的差异,用户很难使用标准 % 文档类中的代码结构来表达中文标题。于是,用户不得不对标准文档类做较大的修改。 % 除此之外,日期格式、首行缩进、中文字号和字距等细节问题,也需要精细的调校。 % 我们设计 \CTeX{} 宏集的目的之一就是解决这些 \LaTeX{} 文档的汉化难题。 % % 另一方面,随着 \TeX{} 引擎和 \LaTeX{} 宏包的不断发展,\LaTeX{} 的中文支持方式从早期的 % 专用系统(如 \pkg{CCT})发展为适用于不同引擎的多种方式^^A % \footnote{比如:\pdfTeX{} 引擎下的 \pkg{CJK}、\pkg{zhmCJK}宏包, % \XeTeX{} 引擎下的 \pkg{xeCJK} 宏包和 \LuaTeX{} 引擎下的 \pkg{LuaTeX-ja} 宏 % 包}。这些方式的适用情况和使用方式有不少细节上的差异,同时操作系统的不同、语言环境的不同等 % 客观情况又进一步带来了更多的细节差异。我们设计 \CTeX{} 宏集的另一个主要目的就是 % 尽可能消除这些差异带来的影响,使用户能够以一个统一的接口来使用不同的中文支持方式, % 使得同一份文档能够在不同环境下交换使用。 % % \CTeX{} 宏集的许多实现细节离不开热心朋友们在 \url{bbs.ctex.org} 论坛上的讨论, % 在此对参与讨论的朋友们表示感谢。 % % \subsection*{关于宏集名字的说明} % % \CTeX{} 之名是英文单词 China(中国)或 Chinese(中文)的首字母“C”与 “\TeX{}” % 结合而成的。在纯文本环境下,该名字应写作“CTeX”。 % % \CTeX{} 宏集是由 \href{http://bbs.ctex.org}{\CTeX{} 社区} 发起并维护的 % \LaTeX{} \emph{宏包和文档类的集合}。 % 社区另有发布名为 \href{http://www.ctex.org/CTeX}{\CTeX{} 套装} % 的 \TeX{} 发行版,与本文档所述的 \CTeX{} 宏集并非是同一事物。 % % \pkg{ctex} 则是本宏集中的 \pkg{ctex.sty} 的名字。这一完全小写的名称,在过去 % 也被用来指代整个 \CTeX{} 宏集,不过现在则特指 \pkg{ctex.sty} 这一宏包。 % 在不引起歧义的情况下,它也可以沿用过去的习惯,代指整个宏集。 % % \section{简明教程} % % \subsection{\CTeX{} 宏集的组成} % % 为了适应用户不同的需求,我们将 \CTeX{} 宏集的主要功能分散在三个中文文档类和 % 四个宏包当中,具体的组成见表~\ref{tab:ctex}。 % % \begin{table}[htbp] % \centering % \caption{\CTeX{} 宏集的组成}\label{tab:ctex} % \begin{tabularx}{\linewidth}{llX} % \toprule % 类别 & 文件 & 说明 \\ % \midrule % 文档类 & \file{ctexart.cls} & 标准文档类 \cls{article} 的汉化版本,一般适用于 % 短篇幅的文章 \\ % & \file{ctexrep.cls} & 标准文档类 \cls{report} 的汉化版本,一般适用于 % 中篇幅的报告 \\ % & \file{ctexbook.cls} & 标准文档类 \cls{book} 的汉化版本,一般适用于 % 长篇幅的书籍 \\ % \midrule % 宏包 & \file{ctex.sty} & 提供全部功能,但\emph{默认不开启章节标题设置功能}, % 需要使用 \opt{heading} 选项来开启 \\ % & \file{ctexcap.sty} & \emph{过时宏包,仅作兼容使用},相当于开启章节标题 % 设置功能的 \file{ctex.sty} \\ % & \file{ctexsize.sty} & 定义和调整中文字号,在 \pkg{ctex} 宏包 % 或 \CTeX{} 中文文档类之外单独调用 \\ % & \file{ctexheading.sty} & 提供章节标题设置功能的(见 \ref{sec:secstyle} % 节),在 \pkg{ctex} 宏包或 \CTeX{} 中文 % 文档类之外单独调用 \\ % \bottomrule % \end{tabularx} % \end{table} % % \subsection{\CTeX{} 宏集的安装和更新} % \label{subsec:easy-ins} % % \CTeX{} 宏集依赖的宏包和宏集已被最常见的 \TeX{} 发行版 \TeXLive{} 和 \MiKTeX{} % 所收录。如果本地安装 \TeXLive{} 或 \MiKTeX{} 不是完全版本,就可能需要通过这 % 两个发行版提供的\emph{宏包管理器}来安装宏包。 % % \TeXLive{} 的宏包管理器是 tlmgr。用户可以在系统命令行中^^A % \footnote{Windows 系统的命令行是 CMD 命令提示符,你可以使用 Win + R 组合键^^A % 打开“运行”对话框,然后输入 cmd 确认打开命令提示符窗口。}^^A % 执行 % \begin{frameverb} % tlmgr gui % \end{frameverb} % 启动管理器的图形界面(Windows 用户也可以通过开始菜单的 % TeX Live 2015 \ding{212} TeX Live Manager 打开)。 % 连接上远程仓库之后,搜索 ctex 安装即可。 % tlmgr 的图形界面使用 Perl 编写,容易造成系统假死。遇到这种问题的用户, % 也可以直接在系统命令行执行 % \begin{frameverb} % tlmgr install ctex % \end{frameverb} % 来安装 \CTeX{} 宏集\footnote{*nix 用户可能需要超级用户权限才能正确安装宏集。}。 % % \MiKTeX{} 的宏包管理器是 mpm (\MiKTeX{} Package Manager)。用户可以在开始菜单 % 找到 MiKTeX \ding{212} Maintenance (Admin) \ding{212} Package Manager (Admin), % 打开管理器,连接上远程仓库之后,搜索 ctex 安装即可。 % % 若希望了解 \CTeX{} 宏集具体的依赖情况和手工安装宏集的方法, % 请参阅第 \ref{sec:dep-ins}~节。 % % 当宏包发布新版本,并被发行版在远程仓库安装之后,在本地就可以通过宏包管理器来 % 取得新版本。 % % 对于 \TeXLive{},可以在 tlmgr 的图形界面点击“更新全部已安装的”按钮或者在 % 命令行执行 % \begin{frameverb} % tlmgr update --all % \end{frameverb} % 来完整更新已安装的宏包。 % % 对于 \MiKTeX{},在开始菜单找到 % MiKTeX \ding{212} Maintenance (Admin) \ding{212} Update (Admin), % 按照界面说明更新即可。 % % \subsection{使用 \CTeX{} 文档类} % % \emph{如果用户需要在标准文档类的基础上添加中文支持和中文版式支持,我们建议用户使用 \CTeX{} % 宏集提供的三个中文文档类。} % % \CTeX{} 宏集提供了三个中文文档类:\cls{ctexart}、\cls{ctexrep} 和 \cls{ctexbook}, % 分别对应 \LaTeX{} 的标准文档类 \cls{article}、\cls{report} 和 \cls{book}。使用它们 % 的时候,需要将涉及到的所有源文件使用 UTF-8 编码保存^^A % \footnote{使用 (pdf)\LaTeX{} 时也能够使用 GBK 编码,但不推荐。 % (见 \ref{subs:encoding}~节)}。 % % \begin{ctexexam} % \documentclass[UTF8]{ctexart} % \begin{document} % 中文文档类测试。你需要将所有源文件保存为 UTF-8 编码。 % % 你可以使用 XeLaTeX 或 LuaLaTeX 编译,也可以使用 (pdf)LaTeX 编译。 % 推荐使用 XeLaTeX 或 LuaLaTeX 编译。 % \end{document} % \end{ctexexam} % % \subsection{使用 \pkg{ctex} 宏包} % % \emph{用户在使用非标准文档类时,如果需要添加中文支持或中文版式支持,则可以使用 \pkg{ctex} % 宏包。} % % 以下是使用 \cls{beamer} 文档类编写中文演示文稿的一个示例。 % \begin{ctexexam} % \documentclass{beamer} % \usepackage[UTF8]{ctex} % \begin{document} % \begin{frame}{中文演示文档} % \begin{itemize} % \item 你需要将所有源文件保存为 UTF-8 编码 % \item 你可以使用 XeLaTeX 或 LuaLaTeX 编译 % \item 也可以使用 (pdf)LaTeX 编译 % \item 推荐使用 XeLaTeX 或 LuaLaTeX 编译 % \end{itemize} % \end{frame} % \end{document} % \end{ctexexam} % % 有些文档类是建立在 \LaTeX{} 标准文档类之上开发的。这时,给 \pkg{ctex} 宏包 % 加上 \opt{heading} 选项,可以将章节标题设置为中文风格。 % \begin{ctexexam} % \documentclass{ltxdoc} % \usepackage[UTF8, heading = true]{ctex} % \begin{document} % \section{简介} % 章节标题中文化的 \LaTeX{} 手册。 % \end{document} % \end{ctexexam} % % \section{宏包选项与 \tn{ctexset} 命令} % \label{sec:options} % % \CTeX{} 宏集已经尽可能就中文的行文和版式习惯做了调整和配置,通常而言,这些配置 % 已经够用。因此,除非必要,我们不建议普通用户修改这些默认配置。如果你认为 \CTeX{} 宏集 % 的默认配置还可以完善,可以在项目主页上 % \href{https://github.com/CTeX-org/ctex-kit/issues}{提交 issue}, % 向我们反映,我们会酌情在后续版本中予以改进。 % % 不过,\CTeX{} 宏集也提供了一系列选项。用户可以使用这些选项来控制 \CTeX{} 宏集的行为。 % 具体来说,这些选项里,有的以传统的方式提供, % 也有的以 \meta{key}|=|\meta{value} 的形式提供。对于以键值对形式提供的选项, % 在下面的说明中使用\textbf{粗体}来表示 \CTeX{} 的默认设置。 % % 另一方面,这些选项可以分为以下三类: % \begin{itemize} % \item 名字后带有 \rexptarget\rexpstar{} 号的选项,只能作为宏包/文档类选项,需要 % 在引入宏包/文档类的时候指定; % \item 名字后带有 \exptarget\expstar{} 号的选项,只能通过 \CTeX{} 宏集提供的 % 用户接口 \tn{ctexset} 来设定; % \item 名字后不带有特殊符号的选项,既可以作为宏包/文档类选项,也可以通过 % \tn{ctexset} 来设定。 % \end{itemize} % 后续文档将在使用说明中对某些特殊的选项加以说明。 % % \begin{function}[added=2014-03-18]{\ctexset} % \begin{syntax} % \tn{ctexset} \Arg{键值列表} % \end{syntax} % 是 \CTeX{} 宏集的通用控制命令,用来在宏包载入后控制宏包的各项功能。 % \tn{ctexset} 的参数是一个键值列表,以通用的接口完成各项设置。 % \end{function} % % \tn{ctexset} 的参数是一组由逗号分隔的选项列表,列表中的选项通常是一个 % \meta{key}|=|\meta{value} 格式的定义。例如设置摘要与参考文献标题名称 % (\ref{subs:capname}~节)就可以使用: % \begin{ctexexam}[labelref=exam:capname] % \ctexset{ % abstractname = {本文概要}, % bibname = {文\quad 献} % } % \end{ctexexam} % % \tn{ctexset} 采用 \LaTeXiii{} 风格的键值设置,支持不同类型的选项与层次化的选 % 项设置,相关示例见 \ref{sec:secstyle}~节。 % % \section{编译方式、编码与中文字库} % \label{sec:chinese} % % \subsection{编译方式} % \label{subs:compile} % % \CTeX{} 宏集会根据用户使用的编译方式\footnote{\LaTeX、\pdfLaTeX、\XeLaTeX 以及 % \LuaLaTeX。},在底层选择不同的中文支持方式(见表 \ref{tab:chinese-support})。 % % \begin{table}[htbp] % \centering % \caption{\CTeX{} 宏集的中文支持方式} % \begin{tabular}{ccc} % \toprule % (pdf)\LaTeX & \XeLaTeX & \LuaLaTeX \\ % \midrule % \pkg{CJK} & \pkg{xeCJK} & \pkg{LuaTeX-ja} \\ % \bottomrule % \end{tabular} % \label{tab:chinese-support} % \end{table} % % 不同的编译方式和中文支持方式会在一定程度上影响 \CTeX{} 宏集的行为,比如宏包对编码的处理。 % 在用户使用 \XeLaTeX{} 及 \LuaLaTeX{} 编译时,\CTeX{} 宏集使用(且仅能 % 使用)UTF-8 编码;而因为历史原因,在用户使用 \LaTeX{} 及 \pdfLaTeX{} 编译 % 时,宏包默认使用 GBK 编码。用户需要\emph{保证编译方式、 % 源文件编码、宏包编码选项三者一致}。 % 关于宏包编码选项,可以参考 \ref{subs:encoding}~节。 % % 除去文档编码之外,选择不同的编译方式还可能影响 \CTeX{} 宏集对字体选择、空格处理、 % 标点处理的处理。具体的影响将在本文档后续内容中进行阐述。 % % \subsection{中文编码} % \label{subs:encoding} % % \begin{function}[rEXP]{GBK, UTF8} % 指明编写文档时使用的编码格式。\CTeX{} 宏集无法检测用户编写文档时使用的编码格式,因此 % 需要用户自行指定编码。\emph{我们建议用户总是使用 UTF-8 编码,并显式指定 \opt{UTF8} % 选项,并使用 \XeLaTeX{} 或 \LuaLaTeX{} 编译。} % % 使用 \XeLaTeX{} 或 \LuaLaTeX{} 编译时,\CTeX{} 宏集强制使用 UTF-8 编码, % 此时 \opt{GBK} 选项无效。 % 使用 (pdf)\LaTeX{} 编译时,\CTeX{} 宏集默认启用 \opt{GBK} 选项;不过,用户也可以 % 显式声明 \opt{UTF8} 选项,使 \CTeX{} 宏集工作在 UTF-8 编码下。 % \end{function} % % \subsection{中文字库} % \label{subs:options-CJK-font} % % 以往,为 \LaTeX{} 文档配置中文支持是一件相当繁琐的事情。默认情况下, % \CTeX{} 宏集能自动检测用户使用的编译方式(参见 \ref{subs:compile}~节)和 % 操作系统\footnote{\CTeX{} 宏集现在能够识别 Mac~OS~X 系统以及 Windows 系统。}, % 选择合适的底层支持和字库,从而简化配置过程。自动配置的情况参见 % 表~\ref{tab:default-font-select}。 % % \begin{table}[htbp] % \centering % \begin{threeparttable} % \caption{\CTeX{} 宏集自动配置字体策略} % \label{tab:default-font-select} % \begin{tabular}{*{5}{c}} % \toprule % & Mac OS X & Windows New\tnote{1} & Windows Old\tnote{2} & % 其他 \\ % \midrule % \XeLaTeX{} & \makecell{\pkg{xeCJK}\\华文字库} & % \makecell{\pkg{xeCJK}\\中易字库 + 微软雅黑} & \makecell{\pkg{xeCJK}\\中易字库} & % \makecell{\pkg{xeCJK}\\Fandol 字库\tnote{3}} \\ % \cmidrule(lr){1-5} % \LuaLaTeX{}\tnote{4} & \makecell{\pkg{LuaTeX-ja}\\华文字库} & % \makecell{\pkg{LuaTeX-ja}\\中易字库 + 微软雅黑} & % \makecell{\pkg{LuaTeX-ja}\\中易字库} & % \makecell{\pkg{LuaTeX-ja}\\Fandol 字库} \\ % \cmidrule(lr){1-5} % \pdfLaTeX{} & 不可用 & % \makecell{\pkg{CJK} + \pkg{zhmetrics}\\中易字库 + 微软雅黑} & % \makecell{\pkg{CJK} + \pkg{zhmetrics}\\中易字库} & 不可用 \\ % \cmidrule(lr){1-5} % \makecell{\LaTeX{} + \\\dvipdfmx{}} & 不可用 & % \makecell{\pkg{CJK} + \pkg{zhmetrics}\\中易字库 + 微软雅黑} & % \makecell{\pkg{CJK} + \pkg{zhmetrics}\\中易字库} & % \makecell{\pkg{CJK} + \pkg{zhmetrics}\\Fandol 字库} \\ % \bottomrule % \end{tabular} % \smallskip % \begin{tablenotes}\footnotesize % \item [1] Windows Vista 及以后的 Windows 操作系统。 % \item [2] Windows XP 及以前的 Windows 操作系统。 % \item [3] 由马起园、苏杰、黄晨成等人开发的开源中文字体, % 参见:\url{https://github.com/clerkma/fandol-fonts}。 % \item [4] \LuaLaTeX{} 编译时使用 \pkg{LuaTeX-ja} 宏包。对此, % 第 \ref{sec:lualatex-chinese}~节有特别说明。 % \end{tablenotes} % \end{threeparttable} % \end{table} % % 通常,由 \CTeX{} 宏集进行的自动配置已经足够使用,无需用户手工干预;但 % 是 \CTeX{} 仍然提供了一系列选项,供在 \CTeX{} 的自动选择机制因为 % 意外情况失效,或者在用户有特殊需求的情况下使用。\emph{除非必要,用户不 % 应使用这些选项。} % % \begin{function}[rEXP,updated=2014-03-08]{zhmap} % \begin{syntax} % zhmap = <\TTF|zhmCJK> % \end{syntax} % 指定字体映射机制。本选项只在使用 \pdfLaTeX/\LaTeX{} 编译时有意义。 % \end{function} % \begin{optdesc} % \item[true] 使用 \pkg{zhmetrics} 宏包,将 CJK 字库通过 \tn{special} % 命令映射到 \file{.ttf} 文件。 % % \item[false] 使用传统的 CJK 字库(Type 1)^^A % \footnote{如果需要使用自定义的字体映射文件,或者希望使用 Type1 字库,请禁用本选项。}。 % % \item[zhmCJK] 载入 \pkg{zhmCJK} 宏包^^A % \footnote{\pkg{zhmCJK} 宏包基于 \pkg{zhmetrics} 和 \pkg{CJK} 宏包,提供与 % \pkg{xeCJK} 宏包类似的用户接口。}^^A % ,由 \pkg{zhmCJK} 宏包提供从 CJK 字库到 \file{.ttf} 的映射。 % \end{optdesc} % % \begin{function}[added=2014-03-08]{fontset} % \begin{syntax} % fontset =^^A % % \end{syntax} % 指定 \CTeX{} 宏集加载的字库。 % % 如果没有指定 \opt{fontset} 的值,\CTeX{} 宏集将自动检测用户使用的操作系统,配置 % 相应的字体(参见表~\ref{tab:default-font-select})。 % \end{function} % % \CTeX{} 预定义了以下六种中文字库。 % % \begin{optdesc} % \item[adobe] 使用 Adobe 公司的四款中文字体,\emph{不支持 \pdfLaTeX}。 % \item[fandol] 使用 Fandol 中文字体,\emph{不支持 \pdfLaTeX}。 % \item[founder] 使用方正公司的中文字体。 % \item[mac] 使用 Mac OS X 系统下的华文字体,\emph{不支持 (pdf)\LaTeX}。 % \item[ubuntu] 使用 Ubuntu 系统下的文泉驿和文鼎字体。 % \item[windows] 使用简体中文 Windows 系统下的中文字体,自动判断 Windows 系 % 统版本,采用 |windowsnew| 或 |windowsold| 的设置。 % \item[windowsnew] 使用简体中文 Windows Vista 或之后系统下的中易字体和微软 % 雅黑字体。 % \item[windowsold] 使用简体中文 Windows XP 或之前系统下的中易字体。 % \end{optdesc} % % 注意:使用 (pdf)\LaTeX{} 编译的时候,若设置 \opt{zhmap = false}(比如需要 % 使用 \LaTeX{} + Dvips 编译),则需要按照传统方式^^A % \footnote{可以使用 \pkg{zhmetrics} 宏包提供的脚本 % \href{https://github.com/CTeX-org/ctex-kit/blob/master/zhmetrics/CTeXFonts.lua} % {\file{CTeXFonts.lua}}。}^^A % 在本地安装好 CJK 字体。 % % 如果不想使用 \CTeX{} 预定义的中文字库,可以设置 \opt{fontset} 为下述值之一。 % % \begin{optdesc} % \item[none] 不配置中文字体,需要用户自己配置。 % \item[\meta{name}] 这里 \meta{name} 为自定义的名字。 % \CTeX{} 宏集将载入名为 |ctex-fontset-|\meta{name}|.def| 的文件作为字体配置 % 文件。因此,请先保证文件的存在。可以在当前工作目录或者本地 \texttt{TDS} 目录 % 树下合适位置建立一个名为 |ctex-fontset-|\meta{name}|.def| 的文件,在这个文件 % 里面自定义中文字体。然后通过使用 |fontset=|\meta{name} 选项来调用它。字体配置 % 文件的具体写法可以参考 \CTeX{} 宏集 \texttt{fontset} 目录下的字体配置文件。 % \end{optdesc} % % 注意:\emph{如果希望使用 \tn{ctexset} 在导言区指定字库,则需要先在宏包/文档类选项中指定 % \opt{fontset = none}}。例如: % \begin{ctexexam} % \documentclass[fontset = none]{ctexart} % \ctexset{fontset = founder} % \begin{document} % 在文档类选项中声明 \verb|fontset = none|,随后在导言区用 \verb|\ctexset| % 指定字体。 % \end{document} % \end{ctexexam} % % \CTeX{} 宏集预定义的中文字库还定义了一些字体命令。 % % \begin{optdesc} % \item[\tn{songti}] 宋体,CJK 等价命令 |\CJKfamily{zhsong}|。 % \item[\tn{heiti}] 黑体,CJK 等价命令 |\CJKfamily{zhhei}|。 % \item[\tn{fangsong}] 仿宋,CJK 等价命令 |\CJKfamily{zhfs}|。 % \item[\tn{kaishu}] 楷书,CJK 等价命令 |\CJKfamily{zhkai}|。 % \end{optdesc} % 其中 \tn{fangsong} 在 \opt{ubuntu} 字库中没有定义。在 % \opt{windows} 和 \opt{founder} 字库中,还有 \tn{lishu} 和 \tn{youyuan}。 % \begin{optdesc} % \item[\tn{lishu}] 隶书,CJK 等价命令 |\CJKfamily{zhli}|。 % \item[\tn{youyuan}] 圆体,CJK 等价命令 |\CJKfamily{zhyou}|。 % \end{optdesc} % 在 \opt{windowsnew} 字库中,还有 \tn{yahei}。 % \begin{optdesc} % \item[\tn{yahei}] 微软雅黑,CJK 等价命令 |\CJKfamily{zhyahei}|。 % \end{optdesc} % % \section{排版格式设定} % \label{sec:format-settings} % \subsection{文档默认字号} % \label{subs:options-class} % % \begin{function}[rEXP,added=2015-05-06]{zihao} % \begin{syntax} % zihao = <-4|5|false> % \end{syntax} % 将文章默认字号(\tn{normalsize})设置为小四号字或五号字, % 具体情况见表 \ref{tab:fontsize}。\opt{false} 禁用本功能。 % 本选项可以用于三个 \CTeX{} 文档类和 \pkg{ctex} 宏包, % 也可以用于 \pkg{ctexsize} 宏包。 % % \opt{scheme = chinese} 时,默认值为 |5|,即设置 \tn{normalsize} 为五号字。 % \end{function} % % \begin{table}[htbp] % \centering % \setlength\tabcolsep{1em} % \caption{标准字体命令与字号的对应}\label{tab:fontsize} % \begin{tabular}{l*2{c>{\ttfamily}r}*3{>{\ttfamily}c}} % \toprule % & \multicolumn2c{|zihao = 5|} & \multicolumn2c{|zihao = -4|} & % \multicolumn1c{|10pt|} & \multicolumn1c{|11pt|} & \multicolumn1c{|12pt|} \\ % \cmidrule(lr){2-3} \cmidrule(lr){4-5} % \cmidrule(lr){6-6} \cmidrule(lr){7-7} \cmidrule(lr){8-8} % 字体命令 & 字号 & \si{bp} & 字号 & \si{bp} % & \si{pt} & \si{pt} & \si{pt} \\ % \midrule % |\tiny| & 七号 & 5.5 & 小六 & 6.5 & ~5 & ~6 & ~6 \\ % |\scriptsize| & 小六 & 6.5 & 六号 & 7.5 & ~7 & ~8 & ~8 \\ % |\footnotesize| & 六号 & 7.5 & 小五 & 9~~ & ~8 & ~9 & 10 \\ % |\small| & 小五 & 9~~ & 五号 & 10.5 & ~9 & 10 & 11 \\ % |\normalsize| & 五号 & 10.5 & 小四 & 12~~ & 10 & 11 & 12 \\ % |\large| & 小四 & 12~~ & 小三 & 15~~ & 12 & 12 & 14 \\ % |\Large| & 小三 & 15~~ & 小二 & 18~~ & 14 & 14 & 17 \\ % |\LARGE| & 小二 & 18~~ & 二号 & 22~~ & 17 & 17 & 20 \\ % |\huge| & 二号 & 22~~ & 小一 & 24~~ & 20 & 20 & 25 \\ % |\Huge| & 一号 & 26~~ & 一号 & 26~~ & 25 & 25 & 25 \\ % \bottomrule % \end{tabular} %\end{table} % % \begin{function}[rEXP]{10pt, 11pt, 12pt} % \CTeX{} 文档类是在 \LaTeX{} 标准文档类之上开发的。因此,除了可以使用 \CTeX{} % 宏包定义的字号选项之外,还可以使用标准文档类的同类选项(\opt{10pt}、\opt{11pt} % 和 \opt{12pt})。在使用这些来自标准文档类的选项的时候,\CTeX{} 文档类的字号 % 选项会被抑制。亦即,在 \opt{zihao} 选项之后设置 \opt{10pt} 选项, % \opt{zihao} 选项将不再起作用。 % \end{function} % % 标准文档类的其他选项在 \CTeX{} 文档类中依旧有效。例如,设置纸张大小和方向的 % \opt{a4paper} 和 \opt{landscape},设置单双面的 \opt{oneside} 和 % \opt{twoside} 等。\CTeX{} 会将这些选项传给标准文档类^^A % \footnote{事实上,\LaTeX{} 在文档类中的选项是全局设定的,除了对使用的文档类有 % 影响外,也可能会影响到随后使用的宏包。如果这些宏包中有某些选项出现在文档类的 % 选项列表中,那么该选项将会被自动激活。}。 % % \subsection{章节标题风格} % \label{subs:options-heading} % % \begin{function}[rEXP,added=2014-03-08]{heading} % \begin{syntax} % heading = <\TFF> % \end{syntax} % 本选项只能在调用 \pkg{ctex.sty} 时作为宏包选项使用。 % % \CTeX{} 宏集提供了一套用于修改文档章节标题格式的接口。该选项用于选择是否 % 启用该功能。详细的设置方法请参见 % \ref{sec:secstyle}~节和 \ref{subs:pagestyle}~节。 % \end{function} % % \CTeX{} 宏集提供的三个文档类总是启用该功能。如果在 \pkg{ctex.sty} 下启用该选项, % 将会检查当前是否使用 \LaTeX{} 标准文档类。 % 若然,则该选项将会使得 \pkg{ctex.sty} 宏包的行为和 \CTeX{} 宏集提供的 % 三个中文文档类\emph{完全}一致;若不然,则会根据 \tn{chapter} % 是否有定义来使用 \cls{ctexbook} 或者 \cls{ctexart} 的标题设置。 % % \begin{function}[rEXP]{sub3section, sub4section} % 修改 \tn{paragraph} 和 \tn{subparagraph} 的格式。 % % 默认情况下,\tn{paragraph} 和 \tn{subparagraph} 会将标题与随后的正文 % 排版在同一个段落。启用 \opt{sub3section} 会将 \tn{paragraph} 的格式修改为 % 类似 \tn{section} 的格式,并将 \tn{subparagraph} 的格式修改为原本 \tn{paragraph} % 的格式。启用 \opt{sub4section} 会将 \tn{paragraph} 和 \tn{subparagraph} 的格式 % 都修改为类似 \tn{section} 的格式。 % % 启用该选项通常需要将计数器 |secnumdepth| 的值为设置为 4 或 5。 % % 具体格式可参考 \ref{sec:secstyle}~节中的 \opt{afterskip} 等选项。 % % 注意,上述两个选项只有在 \opt{heading} 选项启用的时候才有意义。亦即,只有在使用 % 三个 \CTeX{} 文档类或启用了 \opt{heading} 的 \pkg{ctex.sty} 的时候才有意义。 % \end{function} % % \subsection{排版方案选项} % \label{subs:options-type-style} % % \begin{function}[rEXP,added=2015-04-15]{scheme} % \begin{syntax} % scheme = <(chinese)|plain> % \end{syntax} % 选择文章的排版方案,预设有 \opt{chinese} 和 \opt{plain} 两种方案。% % \end{function} % \begin{optdesc}[itemsep=\medskipamount] % \item[chinese] 调整默认字号为五号字,并调整行距为 |1.3|; % 汉化文档中的标题名字(如“图”、“表”、“目录”和“参考文献”, % 见 \ref{subs:capname}~节); % 在 \opt{heading = true} 的情况下^^A % \footnote{使用 \CTeX{} 文档类,或者使用 \pkg{ctex} 宏包且开启该选项时。}^^A % (\ref{subs:options-heading}~节),还会将章节标题的风格修改为 % 中文样式(见 \ref{sec:secstyle}~节)。 % % 当关闭 \opt{heading} 选项的 \pkg{ctex} 宏包与标准文档类或其衍生文档类 % 联用时,会载入 \pkg{indentfirst} 宏包,以实现章节标题后的段首缩进。 % \item[plain] 不调整默认字号和行距,不会汉化文档中的标题名字,也不会将章节 % 标题风格修改为中文样式,同时不会调整 \tn{pagestyle},并禁用 \opt{autoindent} % 选项。事实上,此时的 \CTeX{} 宏集只提供了中文支持功能,而不对文章版式进行任何修改。 % \end{optdesc} % % \begin{function}[updated=2014-04-11]{punct} % \begin{syntax} % punct = <(quanjiao)|banjiao|kaiming|CCT|plain> % \end{syntax} % 设置标点处理格式。预定义好的格式有: % \end{function} % \begin{optdesc} % \item[quanjiao] 全角式:所有标点占一个汉字宽度,相邻两个标点占 1.5 汉字宽度; % \item[banjiao] 半角式:所有标点占半个汉字宽度; % \item[kaiming] 开明式:句末点号^^A % \footnote{标点符号分为标号与点号。点号分为两类,一共七种:句末点号有^^A % 句号、问号和叹号;句内点号有逗号、顿号、冒号和分号。}用占一个汉字宽度,标^^A % 号和句内点号占半个汉字宽度; % \item[CCT] CCT 式:所有标点符号的宽度略小于一个汉字宽度; % \item[plain] 原样(不调整标点间距)。 % \end{optdesc} % % \begin{function}[updated=2014-03-08]{space} % \begin{syntax} % space = <\TF|(auto)> % \end{syntax} % 是否在生成的 PDF 中保留汉字后面的空格。 % \end{function} % % \begin{optdesc} % \item[true] 总是保留汉字后的空格。此时,用户需要自行在行尾加上~|%|~处理换行产生 % 的空格\footnote{\LaTeX{} 将单个换行视作一个空格。}。 % \item[false] 总是忽略掉汉字后面的空格,不论汉字后是什么(使用 (pdf)\LaTeX{} % 编译时);等同于 \opt{auto} 的效果(使用 \XeLaTeX{} 编译时)。不建议使用该选项。 % \item[auto] 根据空格后面的情况决定是否保留:如果空格后面是汉字,则忽略该 % 空格,否则保留。 % \end{optdesc} % % 例如,使用 % \begin{ctexexam} % \ctexset{space=true} % 汉字 分词 % 技术 English % \end{ctexexam} % 将得到“{\ctexset{space=true}汉字 分词 技术 English}”;使用 % \begin{ctexexam} % \ctexset{space=auto} % 汉字 分词 % 技术 English % \end{ctexexam} % 则会得到“{\ctexset{space=auto}汉字 分词 技术 English}”。 % % \emph{使用 \textup{\LuaLaTeX} 编译的时候,该选项无效:汉字间的空格以及汉字与西文字符 % 之间的空格总是有效,不会被忽略,但可以自动忽略掉由换行产生的空格。} % % \begin{function}[rEXP,added=2014-04-23]{linespread} % \begin{syntax} % linespread = <数值> % \end{syntax} % 接受一个浮点数值,设置行距倍数。本选项的初始值与 \opt{scheme} 有关。 % \end{function} % \begin{optdesc} % \item[scheme = chinese] 初始值为 $1.3$,即 $1.3$ 倍行距。此时,相邻两行的基线 % (\tn{baselineskip})距离为 $1.3\times 1.2=1.56$ 倍字体高度。 % % \item[scheme = plain] \CTeX{} 宏集默认不调整行距倍数,文档中的行距由所选文档类和 % 其他宏包或用户设置决定。 % \end{optdesc} % % \begin{function}[added=2014-03-13]{autoindent} % \begin{syntax} % autoindent = <\TTF|数值|带单位的数值> % \end{syntax} % 在字体大小发生变化时,是否自动调整段首缩进(\tn{parindent})的大小。 % \end{function} % \begin{optdesc} % \item[\meta{数值或带单位的数值}] 用于设置段首缩进的长度。如果不带单位,则默认 % 单位是单个汉字字宽 \tn{ccwd};如果带单位,则使用该单位。 % % \item[true] 等价于设置 \opt{autoindent = 2}。 % % \item[false] 禁用自动调整功能,可以设置固定长度的段首缩进。如设置每段缩进 40 点: % \begin{ctexexam} % \ctexset{autoindent=false} % \setlength\parindent{40pt} % \end{ctexexam} % \end{optdesc} % % \begin{function}[EXP,added=2014-03-26]{linestretch} % \begin{syntax} % linestretch = <数值或长度> % \end{syntax} % \opt{linestretch} 是一个比较特殊的选项,它用来设置汉字之间弹性间距的弹性程 % 度。如果有单位,则可以在选项中直接写;如果是数字,单位则是汉字宽度 % \tn{ccwd} 的倍数。 % \end{function} % % 如果行宽不是汉字宽度的整数倍,为了让段落左右两端对齐,自然就要求伸展汉字之 % 间的间距,而 \opt{linestretch} 选项就是设置每行总的允许伸行量。初始值是允 % 许每行伸行一个汉字的宽度 \tn{ccwd},并且此宽度能根据字号变化动态调整。 % % 过小的 \opt{linestretch} 可能导致段落文字右侧可能参差不齐;较大的 % \opt{linestretch} 选项则可以帮助拥有较长不可断行内容的复杂段落方便地断行, % 而不会产生大量编译警告;但很大的 \opt{linestretch} 则会掩盖段落不良断行产 % 生的坏盒子警告。 % % 如果将 \opt{linestretch} 选项的值设置为 \tn{maxdimen},则可以禁止按字号自 % 动修改每行的允许伸长量。此时汉字间的弹性间距则固定为 \tn{baselineskip} 的 % $0.08$ 倍。 % % \section{文档汉化} % \label{sec:chinese-localization} % \subsection{日期汉化} % % \CTeX 宏包对显示当前日期的 \tn{today} 命令进行了汉化,使之以中文的方式显示今 % 天的日期。如编译本文档的日期就是“\today”。 % % \begin{function}[EXP]{today} % \begin{syntax} % today = <(small)|big|old> % \end{syntax} % 该选项用来控制 \tn{today} 命令的输出格式: % \begin{optdesc} % \item[small] \ctexset{today=small} % 效果为“\today”。使用阿拉伯数字和汉字的日期格式。 % \item[big] \ctexset{today=big} % 效果为“\today”。使用全汉字的日期格式。 % \item[old] \ctexset{today=old} % 效果为“\today”。使用文档原来的(英文)日期格式。 % \end{optdesc} % \end{function} % % 设置日期格式使用 \tn{ctexset} 命令完成,例如设置全汉字的日期格式: % \begin{ctexexam} % \ctexset{today=big} % \end{ctexexam} % % \CTeX 宏包的中文日期功能实际上是调用 \pkg{zhnumber} 宏包完成的。如果需要更 % 多有关日期、时间的命令和更复杂的设置,可以查阅 \pkg{zhnumber} 宏包的文档。 % % \subsection{文档标题汉化} % \label{subs:capname} % % 这里主要介绍由宏包 \opt{scheme} 选项(\ref{subs:options-type-style}~节)控制 % 的文档标题汉化功能。 % % 设置文档标题名的示例可见例~\ref{exam:capname}。下面的选项(如 % \opt{contentsname})主要用来重新定义与选项同名的宏(如 \tn{contentsname})的 % 定义。 % % \begin{defaultcapconfig} % % \begin{function}[EXP]{contentsname} % \begin{syntax} % contentsname = <名字> % \end{syntax} % 设置目录标题名 \tn{contentsname}。中文默认为“\contentsname”。 % \end{function} % % \begin{function}[EXP]{listfigurename} % \begin{syntax} % listfigurename = <名字> % \end{syntax} % 设置插图目录标题名 \tn{listfigurename}。中文默认为“\listfigurename”。 % \end{function} % % \begin{function}[EXP]{listtablename} % \begin{syntax} % listtablename = <名字> % \end{syntax} % 设置表格目录标题名 \tn{listtablename}。中文默认为“\listtablename”。 % \end{function} % % \begin{function}[EXP]{figurename} % \begin{syntax} % figurename = <名字> % \end{syntax} % 设置图片环境标题名 \tn{figurename}。中文默认为“\figurename”。 % \end{function} % % \begin{function}[EXP]{tablename} % \begin{syntax} % tablename = <名字> % \end{syntax} % 设置表格环境标题名 \tn{tablename}。中文默认为“\tablename”。 % \end{function} % % \begin{function}[EXP]{abstractname} % \begin{syntax} % abstractname = <名字> % \end{syntax} % 设置摘要 \env{abstract} 环境标题名 \tn{abstractname}。中文默认 % 为“\abstractname”。注意 \cls{book} 类没有摘要,该选项无效。 % \end{function} % % \begin{function}[EXP]{indexname} % \begin{syntax} % indexname = <名字> % \end{syntax} % 设置索引标题名 \tn{indexname}。中文默认为“\indexname”。 % \end{function} % % \begin{function}[EXP]{appendixname} % \begin{syntax} % appendixname = <名字> % \end{syntax} % 设置附录标题名 \tn{appendixname}。中文默认为“\appendixname”。 % \end{function} % % \begin{function}[EXP]{bibname} % \begin{syntax} % bibname = <名字> % \end{syntax} % 设置参考文献标题名 \tn{refname}(对 \cls{article})或 \tn{bibname}(对 % \cls{report} 和 \cls{book})。中文默认为“\refname”。 % \end{function} % % \end{defaultcapconfig} % % \subsection{页面格式设置与汉化} % \label{subs:pagestyle} % % 当使用了 \CTeX 的文档类或是用 \pkg{ctex} 宏包加载了 \opt{heading} 选项时,会 % 设置整个文档的页面格式(page style)为 |headings|,即相当于设置了 % \begin{frameverb} % \pagestyle{headings} % \end{frameverb} % 在页眉中显示当前章节的编号与标题。 % % 同时,\CTeX 宏包也会对默认的 |headings| 页面格式进行修改,使之调用 % \tn{CTEXthechapter}、\tn{CTEXthesection} 等宏来正确显示中文的章节编号。 % % \CTeX 宏包的默认页面格式设置是经过汉化的 |headings|,其基本效果如本文档所 % 示,只在页眉一侧显示章节编号和标题,另一侧显示页码。 % % 更复杂的页面格式可以通过调用 \pkg{fancyhdr}、\pkg{titleps} 等宏包来设 % 置。\CTeX 宏包同时也为这些自定义页面格式 % 的包提供了以下宏供使用: % \begin{itemize} % \item \tn{CTEXthechapter}、\tn{CTEXthesection} 等章节编号(见 % \ref{sec:secstyle} 节)。它们用来代替英文文档类中的 % \tn{thechapter}、\tn{thesection} 等宏。 % % \item \tn{leftmark}、\tn{rightmark},它们是在使用章节标题命令后,自动设置的 % 宏。它们实际是在与章节标题命令对应的标记命令 % \tn{chaptermark}、\tn{sectionmark} 中调用 \tn{markright} 或 \tn{markboth} 生 % 成的。 % \end{itemize} % 有关 \LaTeX 页面标记的涵义与使用细节,已经超出了本文档讨论的范围。可以参考 % \cite[Chapter~23]{knuthtex1986}、\cite[\S4.3, \S4.4]{mittelbach2004} 等书籍。 % % 这里举一个例子,说明通过重定义 \tn{sectionmark},在 \cls{ctexart} 文档类中的 % 标准 |headings| 页面格式下控制页眉的方式: % \begin{ctexexam} % \documentclass{ctexart} % \pagestyle{headings} % \ctexset{section={ % name={第,节}, % number=\arabic{section}, % } % } % \renewcommand\sectionmark[1]{% % \markright{\CTEXthesection——#1}} % % \begin{document} % % \section{天地玄黄} % \newpage % % \section{宇宙洪荒} % % \end{document} % \end{ctexexam} % 在上例中,我们设置了页眉的形式是用破折号分开的节编号与节标题,即“第 1 节 % ——天地玄黄”、“第 2 节——宇宙洪荒”。 % % \CTeX 宏包已经对 \pkg{fancyhdr} 宏包进行了补丁,载入 \pkg{fancyhdr} 后,其 % |fancy| 页面格式将使用 \tn{CTEXthechapter} 等宏显示中文章节编号。 % % 关于 \pkg{fancyhdr} 的具体用法可以参见其宏包手册。通常也只要像在标准的英文文 % 档类中使用 \pkg{fancyhdr} 一样定义页眉页脚格式即可,并不需要额外的定义。 % % 下面我则给出一个与前例类似而稍复杂的例子,展示如何在文档中设置页眉内容与页眉 % 的格式。 % \begin{ctexexam} % \documentclass{ctexart} % \ctexset{section={ % name={第,节}, % number=\arabic{section}, % } % } % \usepackage{fancyhdr} % \fancyhf{} % \lhead{\textnormal{\kaishu\rightmark}} % \rhead{--\ \thepage\ --} % \pagestyle{fancy} % % \sectionmark 的重定义需要在 \pagestyle 之后生效 % \renewcommand\sectionmark[1]{% % \markright{\CTEXthesection——#1}} % % \begin{document} % % \section{天地玄黄} % \newpage % % \section{宇宙洪荒} % % \end{document} % \end{ctexexam} % 本例的页眉效果大致如下(有页眉线): % \begin{trivlist}\item % \textnormal{\kaishu 第 1 节——天地玄黄}\hfill -- 1 --\par % \smallskip\hrule % \end{trivlist} % % \section{章节标题格式设置} % \label{sec:secstyle} % % \CTeX 宏包对 \LaTeX 的标准文档类(\cls{article}、\cls{report} 和 % \cls{book})进行了扩充。当以 \opt{heading} 选项调用 \CTeX 宏包时 % (\ref{subs:options-heading}~节),则会启用章 % 节标题的格式设置功能。本节就来介绍有关章节标题的格式选项,所有选项使用 % \tn{ctexset} 命令设置。 % % 第 \ref{subs:pagestyle} 节和本节介绍的功能已经被提取到 \pkg{ctexheading} % 宏包之中,可以在 \pkg{ctex} 宏包和 \cls{ctexart} 等文档类之外独立使用。 % 各选项的默认值与 \opt{scheme = plain} 时的情形相同。 % % \changes{v2.0}{2015/03/21}{\tn{CTEXsetup}, \tn{CTEXoptions} 是过时命令。} % 章节标题的格式选项是分层设置的。顶层的选项是章节标题名称,次一级的选项是章节 % 标题的格式。章节标题名包括 |part|, |chapter|, |section|, |subsection|, % |subsubsection|, |paragraph|, |subparagraph|;而可用的格式包括 \opt{numbering}, % \opt{name}, \opt{number}, \opt{format}, \opt{nameformat}, \opt{numberformat}, % \opt{aftername}, \opt{titleformat}, \opt{aftertitle}, \opt{runin}, % \opt{afterindent}, \opt{beforeskip}, \opt{afterskip}, \opt{indent}, % \opt{pagestyle} 等。但注意,对 \cls{article} 及其衍生的 % \cls{ctexart} 等文档类,没有 |chapter| 级别的标题。 % % 多级选项之间用斜线分开,例如,\opt{part/name} 选项设置 \tn{part} 标题的在数 % 字前后的名称,而 \opt{section/number} 选项设置 \tn{section} 标题的数字类型。 % % 使用 \tn{ctexset} 设置多级选项时,可以在同一个上级选项下设置多个下级选项。 % % 例如,同时设置 |part| 一级标题的 \opt{pagestyle} 选项,|chapter| 一级标题的 % \opt{format} 与 \opt{pagestyle} 选项和 |section| 一级标题的 \opt{name} 与 % \opt{number} 选项: % \begin{ctexexam} % \ctexset { % part/pagestyle = empty, % chapter = { % format = \raggedright, % pagestyle = empty, % }, % section = { % name = {第,节}, % number = \chinese{section}, % } % } % \end{ctexexam} % % \begin{function}[EXP,added=2015-06-21]{part/numbering, chapter/numbering, % section/numbering, subsection/numbering, subsubsection/numbering, % paragraph/numbering, subparagraph/numbering} % \begin{syntax} % numbering = \TTF % \end{syntax} % 控制是否对章节标题编号。对各级标题的默认值均为 \opt{true}。 % % 我们知道,\LaTeX{} 带星号的章节标题命令(如 \tn{section*})不会对标题编号, % 但也不会将该没编号的标题编入目录中。本选项控制的是不带星号的标题命令是否编号。 % 设置本选项为 \opt{false},除了不对标题编号以外,功能与正常标题一致, % 比如可以编目录,正确的 \pkg{hyperref} 目录超链接位置和页眉标记。 % % 注意,章节标题的编号深度受 \LaTeX{} 计数器 |secnumdepth| 的控制。 % \opt{numbering} 选项在 |secnumdepth| 的控制下起作用。 % \end{function} % % 如果没有特别说明,以下将用 “|...|” 代表各级章节标题名。 % % \begin{function}[EXP,updated=2014-03-08]{.../name} % \begin{syntax} % name = \{<前名字>,<后名字>\} % name = \Arg{前名字} % \end{syntax} % 设置章节的名字。名字可以分为前后两部分,即章节编号前后的词语,两个词之间用 % 一个半角逗号分开;也可以只有一部分,表示只有章节编号之前的名字。例如: % \begin{ctexexam} % \ctexset{ % chapter/name = {第,章}, % section/name = {\S}, % } % \end{ctexexam} % 会使得 \tn{chapter} 标题使用形如“第一章”的名字,而 \tn{section} 标题则使 % 用形如“\S1”的名字。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{name} 选项的默认设置} % \begin{tabular}{llll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} & 注 \\ % \midrule % part & |{第,部分}| & |{\partname\space}| & 原 \tn{partname} 为 Part \\ % chapter & |{第,章}| & |{\chaptername\space}| % & 原 \tn{chaptername} 为 Chapter \\ % section & 同右 & |{}| & \\ % subsection & 同右 & |{}| & \\ % subsubsection & 同右 & |{}| & \\ % paragraph & 同右 & |{}| & \\ % subparagraph & 同右 & |{}| & \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP]{.../number} % \begin{syntax} % number = \Arg{数字输出命令} % \end{syntax} % 设置章节编号的数字输出格式。\meta{数字输出命令} 通常是对应章节编号计数器的 % 输出命令,如 \tn{thesection} 或 |\chinese{chapter}| 之类。 % \begin{ctexexam} % \ctexset{ % section/number = \Roman{section} % } % \end{ctexexam} % % \opt{number} 选项的定义同时将控制对章节计数器的交叉引用。在引用计数器时, % 记录在 \LaTeX{} 辅助文件中的是 \opt{number} 选项的定义。 % % 但是,\opt{number} 选项不会影响计数器本身的输出。即设置 |section/number| % 不会影响 \tn{thesection} 的定义。(但该选项会影响 \tn{CTEXthesection} 的定 % 义,见后。) % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{number} 选项的默认设置} % \setlength\leftskip{0pt plus 1 fil minus \marginparwidth} % \begin{tabular}{llll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} % & 原 |\the|\meta{标题} 等价定义 \\ % \midrule % part & |\chinese{part}| & |\thepart| & |\Roman{part}| \\ % chapter & |\chinese{chapter}| & |\thechapter| & |\arabic{chapter}| \\ % section & 同右 & |\thesection| & |\arabic{section}| \\ % subsection & 同右 & |\thesubsection| & |\thesection.\arabic{subsection}| \\ % subsubsection & 同右 & |\thesubsubsection| % & |\thesubsection.\arabic{subsubsection}| \\ % paragraph & 同右 & |\theparagraph| % & |\thesubsubsection.\arabic{paragraph}| \\ % subparagraph & 同右 & |\thesubparagraph| % & |\theparagraph.\arabic{subparagraph}| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}{\CTEXthepart, \CTEXthechapter, \CTEXthesection, % \CTEXthesubsection, \CTEXthesubsubsection, \CTEXtheparagraph, % \CTEXthesubparagraph} % 以 |\CTEXthe| 开头的这组宏给出结合了 \opt{name} 与 \opt{number} 选项的章节 % 编号输出格式。例如在 \opt{scheme = chinese} 时,默认章编号输出格式就是 % \tn{CTEXthechapter},形如“第一章”。 % % 这组宏在 \CTeX 文档类中将代替 \tn{thechapter} 等宏的作用,在章节中引用本章 % 节的完整编号。例如用于帮助定义自定义的目录格式、页眉格式等。 % \end{function} % % \begin{function}[EXP,updated=2015-06-30]{.../format, .../format+} % \begin{syntax} % format = \Arg{格式命令} % format+= \Arg{格式命令} % \end{syntax} % \opt{format} 选项用于控制章节标题的全局格式,作用域为章节名字和随后的标题 % 内容。可以用于控制章节标题的对齐方式、整体字体字号等格式。 % % 带加号的 \opt{format+} 选项则用于在已有格式之后追加新的格式命令。 % % 例如,设置章格式为无衬线字体左对齐,为节格式增加无衬线字体设置: % \end{function} % \begin{ctexexam} % \ctexset{ % chapter/format = \sffamily\raggedright, % section/format+ = \sffamily % } % \end{ctexexam} % % \begin{table}[htbp] % \small\centering % \caption{\opt{format} 选项的默认设置} % \begin{tabular}{lll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} \\ % \midrule % part (article) & |\Large\bfseries\centering| & |\raggedright| \\ % part & |\huge\bfseries\centering| & |\centering| \\ % chapter & |\huge\bfseries\centering| & |\raggedright| \\ % section & |\Large\bfseries\centering| & |\Large\bfseries| \\ % subsection & 同右 & |\large\bfseries| \\ % subsubsection & 同右 & |\normalsize\bfseries| \\ % paragraph & 同右 & |\normalsize\bfseries| \\ % subparagraph & 同右 & |\normalsize\bfseries| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,updated=2015-06-30]{.../nameformat, .../nameformat+} % \begin{syntax} % nameformat = \Arg{格式命令} % nameformat+= \Arg{格式命令} % \end{syntax} % \opt{nameformat} 用于控制章节名字的格式,作用域为章节名字,包括编号。它一 % 般用于章节名(包括编号)与章节标题的字体、字号等设置不一致的情形。参见 % \opt{titleformat} 选项。 % % \opt{nameformat+} 用于在已有的章节名字格式后附加内容。 % % \opt{nameformat} 选项的最后一个格式命令可以是一个有一个参数的命令。 % 这个命令的参数用于接受章节名字和编号,实现特殊效果(见例~\ref{exam:miscopt})。 % % \opt{nameformat} 选项的默认值,在 \opt{scheme} 选项的不同取值下相同。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{nameformat} 选项的默认设置} % \begin{tabular}{lll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} \\ % \midrule % part (article) & |{}| & |\Large\bfseries| \\ % part & |{}| & |\huge\bfseries| \\ % chapter & |{}| & |\huge\bfseries| \\ % section & 同右 & |{}| \\ % subsection & 同右 & |{}| \\ % subsubsection & 同右 & |{}| \\ % paragraph & 同右 & |{}| \\ % subparagraph & 同右 & |{}| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,updated=2015-06-19]{.../numberformat, .../numberformat+} % \begin{syntax} % numberformat = \Arg{格式命令} % numberformat+= \Arg{格式命令} % \end{syntax} % \opt{numberformat} 选项用于控制章节编号的格式,作用域仅为编号数字本身。对 % 各级标题默认均为空,当你需要编号的格式和前后的章节名字不一样时可以使用。 % % \opt{numberformat+} 选项用于在原有编号格式后面附加格式命令。 % % \opt{numberformat} 选项的最后一个格式命令可以是一个有一个参数的命令。 % 这个命令的参数用于接受编号数字。 % \end{function} % % 例如,我们可以使用 \opt{numberformat} 特别强调章标题中的数字: % \begin{ctexexam} % \ctexset{ % chapter/number = \arabic{chapter}, % chapter/numberformat = \color{blue}\zihao{0}\itshape, % } % \end{ctexexam} % 上面的代码在 \opt{scheme = chinese} 时可以做出类似这样的章标题效果: % \begin{center} % \huge\bfseries 第 \textit{\color{blue}\zihao{0}4} 章 % \end{center} % % \begin{function}[EXP,updated=2014-03-08]{.../aftername, .../aftername+} % \begin{syntax} % aftername = \Arg{代码} % aftername+= \Arg{代码} % \end{syntax} % \opt{aftername} 选项的参数 \meta{代码} 将被插入到章节编号与其后的标题内容之 % 间,用于控制格式变换。常用于控制章节编号与标题内容之间的距离,或者控制标题 % 是否另起一行。 % % \opt{aftername+} 选项用于在原有代码后面附加代码。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{aftername} 选项的默认设置} % \begin{tabular}{lll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} \\ % \midrule % part (article) & |\quad| & |\par\nobreak| \\ % part & 同右 & |\par\vskip 20pt| \\ % chapter & |\quad| & |\par\nobreak\vskip 20pt| \\ % section & 同右 & |\quad| \\ % subsection & 同右 & |\quad| \\ % subsubsection & 同右 & |\quad| \\ % paragraph & 同右 & |\quad| \\ % subparagraph & 同右 & |\quad| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,updated=2015-06-30]{.../titleformat, .../titleformat+} % \begin{syntax} % titleformat = \Arg{格式命令} % titleformat+= \Arg{格式命令} % \end{syntax} % \opt{titleformat} 选项用于控制标题内容的格式,作用域为章节标题内容。 % % \opt{titleformat+} 选项用于在原有标题格式后面附加格式命令。 % % 需要注意的是,\opt{titleformat} 选项的最后一个格式命令可以是一个有一个 % 参数的命令。这个命令的参数接受标题内容,用于实现特殊效果。 % 例如,实现多行标题的居中悬挂对齐: % \end{function} % \begin{ctexexam} % \usepackage{varwidth} %% 提供 varwidth 环境 % \ctexset{ % chapter/name = {第,回}, % chapter/titleformat = \chaptertitleformat % } % \newcommand\chaptertitleformat[1]{%% 以标题内容为参数 % \begin{varwidth}[t]{.7\linewidth}#1\end{varwidth}} % ...... % \chapter{情中情因情感妹妹\\错里错以错劝哥哥} % \end{ctexexam} % 上面的代码可以做出类似这样的章标题效果: % \begin{center}\Large\bfseries % 第三十四回\quad % \begin{tabular}[t]{l} % 情中情因情感妹妹\\ % 错里错以错劝哥哥 % \end{tabular} % \end{center} % % \begin{table}[htbp] % \small\centering % \caption{\opt{titleformat} 选项的默认设置} % \begin{tabular}{lll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} \\ % \midrule % part (article) & |{}| & |\huge\bfseries| \\ % part & |{}| & |\Huge\bfseries| \\ % chapter & |{}| & |\Huge\bfseries| \\ % section & 同右 & |{}| \\ % subsection & 同右 & |{}| \\ % subsubsection & 同右 & |{}| \\ % paragraph & 同右 & |{}| \\ % subparagraph & 同右 & |{}| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,added=2015-06-19]{.../aftertitle, .../aftertitle+} % \begin{syntax} % aftertitle = \Arg{代码} % aftertitle+= \Arg{代码} % \end{syntax} % \opt{aftertitle} 选项的参数 \meta{代码} 将被插入到章节标题内容之后。 % % \opt{aftertitle+} 选项用于在原有代码后面附加代码。 % % \opt{aftertitle} 选项的默认值,在 \opt{scheme} 选项的不同取值下相同。 % % \opt{sub3section} 或 \opt{sub4section} 宏包选项(见 % \ref{subs:options-heading}~节)会影响 \opt{aftertitle} 选项的默认值。 % \end{function} % % \begin{table}[htbp] % \begin{minipage}[t]{.5\linewidth} % \small\centering % \caption{\opt{aftertitle} 选项的默认设置} % \begin{tabular}{ll} % \toprule % 标题名 & 默认值 \\ % \midrule % part & |\par| \\ % chapter & |\par| \\ % section & |\@@par| \\ % subsection & |\@@par| \\ % subsubsection & |\@@par| \\ % paragraph & |{}| \\ % \qquad(sub3section) & |\@@par| \\ % \qquad(sub4section) & 同上 \\ % subparagraph & |{}| \\ % \qquad(sub4section) & |\@@par| \\ % \bottomrule % \end{tabular} % \end{minipage}% % \begin{minipage}[t]{.5\linewidth} % \small\centering % \caption{\opt{runin} 选项的默认设置} % \begin{tabular}{ll} % \toprule % 标题名 & 默认值 \\ % \midrule % part & 无效 \\ % chapter & 无效 \\ % section & |false| \\ % subsection & |false| \\ % subsubsection & |false| \\ % paragraph & |true| \\ % \qquad(sub3section) & |false| \\ % \qquad(sub4section) & 同上 \\ % subparagraph & |true| \\ % \qquad(sub4section) & |false| \\ % \bottomrule % \end{tabular} % \end{minipage} % \end{table} % % \begin{function}[EXP,added=2015-06-27]{section/runin, subsection/runin, % subsubsection/runin, paragraph/runin, subparagraph/runin} % \begin{syntax} % runin = \TF % \end{syntax} % \opt{runin} 选项只对 \tn{section} 级以下标题有意义。 % 用于确定标题与随后的正文是否排在同一段之上。 % % \opt{runin} 选项的默认值,在 \opt{scheme} 选项的不同取值下相同。 % % 默认情况下,\tn{paragraph}、\tn{subparagraph} 两级标题是与后面正文排在同一 % 段的,\opt{runin} 选项为 \opt{true};但使用 \opt{sub3section} 或 % \opt{sub4section} 宏包选项(见 \ref{subs:options-heading}~节)后, % 将对这两级标题设 \opt{runin} 选项为 \opt{false},这两级标题会改为排在不同段。 % \end{function} % % \begin{function}[EXP,added=2015-06-27]{.../afterindent} % \begin{syntax} % afterindent = \TF % \end{syntax} % \opt{afterindent} 选项用于设置章节标题后首段的缩进。 % % \cls{book} 和 \cls{report} 类的 \tn{part} 标题被单独排在一页之上, % \opt{afterindent} 选项没有意义。 % % 对于 \tn{section} 级以下标题,若设置了 \opt{runin} 选项为 \opt{true}, % 即标题与随后正文排在同一段,\opt{afterindent} 选项也就没有了意义。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{afterindent} 选项的默认设置} % \begin{tabular}{lll} % \toprule % 标题名 & \opt{scheme = chinese} & \opt{scheme = plain} \\ % \midrule % part (article) & |true| & |false| \\ % part & 无效 & 无效 \\ % chapter & |true| & |false| \\ % section & |true| & |false| \\ % subsection & |true| & |false| \\ % subsubsection & |true| & |false| \\ % paragraph & |true| & |false| \\ % subparagraph & |true| & |false| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,updated=2015-06-27]{.../beforeskip} % \begin{syntax} % beforeskip = \Arg{弹性间距} % \end{syntax} % \opt{beforeskip} 选项用于设置章节标题前的垂直间距。 % % \opt{beforeskip} 选项的默认值,在 \opt{scheme} 选项的不同取值下相同。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{beforeskip} 选项的默认设置} % \begin{tabular}{ll} % \toprule % 标题名 & 默认值 \\ % \midrule % part (article) & |4ex| \\ % part & |0pt plus 1fil| \\ % chapter & |50pt| \\ % section & |3.5ex plus 1ex minus .2ex| \\ % subsection & |3.25ex plus 1ex minus .2ex| \\ % subsubsection & |3.25ex plus 1ex minus .2ex| \\ % paragraph & |3.25ex plus 1ex minus .2ex| \\ % subparagraph & |3.25ex plus 1ex minus .2ex| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,updated=2015-06-27]{.../afterskip} % \begin{syntax} % afterskip = \Arg{弹性间距} % \end{syntax} % \opt{afterskip} 选项控制章节标题与后面下方之间的距离。 % % 对于 \tn{section} 级以下标题,\opt{runin} 选项会影响 \opt{afterskip} 选项的意义: % 若 \opt{runin} 为 \opt{true},标题与随后正文排在同一段,\meta{弹性间距} 给出水平间距。 % 否则,正文另起一段,\meta{弹性间距} 给出的是垂直间距。 % % \opt{afterskip} 选项的默认值,在 \opt{scheme} 选项的不同取值下相同。 % % \opt{sub3section} 或 \opt{sub4section} 宏包选项(见 % \ref{subs:options-heading}~节)会影响 \opt{aftertitle} 选项的默认值。 % \end{function} % % \begin{table}[htbp] % \begin{minipage}[t]{.5\linewidth} % \small\centering % \caption{\opt{afterskip} 选项的默认设置} % \begin{tabular}{ll} % \toprule % 标题名 & 默认值 \\ % \midrule % part (article) & |3ex| \\ % part & |0pt plus 1fil| \\ % chapter & |40pt| \\ % section & |2.3ex plus .2ex| \\ % subsection & |1.5ex plus .2ex| \\ % subsubsection & |1.5ex plus .2ex| \\ % paragraph & |1em| \\ % \qquad(sub3section) & |1ex plus .2ex| \\ % \qquad(sub4section) & 同上 \\ % subparagraph & |1em| \\ % \qquad(sub4section) & |1ex plus .2ex| \\ % \bottomrule % \end{tabular} % \end{minipage}% % \begin{minipage}[t]{.5\linewidth} % \small\centering % \caption{\opt{indent} 选项的默认设置} % \begin{tabular}{ll} % \toprule % 标题名 & 默认值 \\ % \midrule % part (article) & |0pt| \\ % part & 无效 \\ % chapter & |0pt| \\ % section & |0pt| \\ % subsection & |0pt| \\ % subsubsection & |0pt| \\ % paragraph & |0pt| \\ % subparagraph & |\parindent| \\ % \qquad(sub3section) & |0pt| \\ % \qquad(sub4section) & 同上 \\ % \bottomrule % \end{tabular} % \end{minipage} % \end{table} % % \begin{function}[EXP,updated=2015-06-27]{.../indent} % \begin{syntax} % indent = \Arg{缩进间距} % \end{syntax} % \opt{indent} 选项用于设置章节标题本身的首行缩进。 % % \opt{indent} 选项的默认值,在 \opt{scheme} 选项的不同取值下相同。 % % 例如,设置 \tn{section} 标题缩进 \SI{20}{pt}: % \end{function} % \begin{ctexexam} % \ctexset{section={ % format=\Large\bfseries, % indent=20pt, % } % } % \section{首行缩进的标题} % \noindent 无缩进的正文。 % \end{ctexexam} % % \begin{function}[EXP,added=2014-03-21]{part/pagestyle, chapter/pagestyle} % \begin{syntax} % pagestyle = \Arg{页面格式} % \end{syntax} % 设置 \cls{book}/\cls{ctexbook} 或 \cls{report}/\cls{ctexrep} 文档类 % 中,\tn{part} 与 \tn{chapter} 标题所在页的页面格式(page style)。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{pagestyle} 选项的默认设置} % \begin{tabular}{ll} % \toprule % 标题名 & 默认值 \\ % \midrule % part (article) & 无效 \\ % part & |plain| \\ % chapter & |plain| \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP,added=2015-06-21]{appendix/numbering} % \begin{syntax} % numbering = \TTF % \end{syntax} % 控制是否对附录章(对 \cls{book} 与 \cls{report})或附录节(对 \cls{article}) % 进行编号。 % % 用法与普通章节 \opt{numbering} 选项类似。 % \end{function} % % \begin{function}[updated=2014-03-08]{appendix/name} % \begin{syntax} % name = \{<前名字>,<后名字>\} % name = \Arg{前名字} % \end{syntax} % 设置附录章(对 \cls{book} 与 \cls{report})或附录节(对 \cls{article})的 % 名字。 % % 用法与普通章节 \opt{name} 选项类似。 % % 注意该选项与 \opt{appendixname} 选项(\ref{subs:capname}~节)在意义上有 % 些重叠,但意义不同。\opt{appendixname} 选项只用来重定义 % \tn{appendixname},而不管 \tn{appendixname} 如何使用;该选项则决定在章节标 % 题中输出的名字,可以调用 \tn{appendixname} 设置。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{appendix/name} 选项的默认设置} % \begin{tabular}{llllll} % \toprule % 文档类 & 影响命令 & \opt{scheme = chinese} & 实际定义 % & \opt{scheme = plain} & 实际定义 \\ % \midrule % article & \tn{section} & |{}| & & |{}| & \\ % book, report & \tn{chapter} & |\appendixname\space| & \verb*|附录 | % & |\appendixname\space| & \verb*|Appendix | \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[EXP]{appendix/number} % \begin{syntax} % number = \Arg{数字输出命令} % \end{syntax} % 设置附录章(对 \cls{book} 与 \cls{report})或附录节(对 \cls{article})编 % 号的数字输出格式。 % % 用法与普通章节的 \opt{number} 选项类似。 % % 该选项也同时控制附录章节计数器的交叉引用。 % % 与普通章节的 \opt{number} 选项类似,同样需要注意,该选项不会影响计数器本身 % 的输出,即不影响 \tn{thesection} 或 \tn{thechapter} 的定义。 % \end{function} % % \begin{table}[htbp] % \small\centering % \caption{\opt{appendix/number} 选项的默认设置} % \begin{tabular}{llllll} % \toprule % 文档类 & 影响命令 & 默认值 \\ % \midrule % article & \tn{section} & |\Alph{section}| \\ % book, report & \tn{chapter} & |\Alph{chapter}| \\ % \bottomrule % \end{tabular} % \end{table} % % 我们最后举一个稍微复杂的例子,来看看上述选项的综合应用。 % % \begin{ctexexam}[labelref=exam:miscopt] % \ctexset { % chapter = { % format = \Huge\bfseries, % nameformat = \hrule height 1bp \relax\bigskip\hfill\chapternamebox, % number = \arabic{chapter}, % aftername = \par\medskip, % aftertitle = \bigskip\hrule height 2bp \relax % } % } % \newcommand\chapternamebox[1]{% % \parbox{\ccwd}{\linespread{1}\selectfont\centering #1}} % ...... % \chapter{熟悉 \LaTeX} % \end{ctexexam} % 本例的设置效果大致如下: % \begin{center} % \begin{minipage}{.75\linewidth}\Large\bfseries % \hrule height .5bp \relax % \medskip % \hfill\parbox{\ccwd}{\linespread{1}\selectfont\centering 第 1 章} % \par\smallskip % \noindent 熟悉 \LaTeX % \medskip\hrule height 1bp \relax % \end{minipage} % \end{center} % % \section{实用命令} % \label{sec:useful-commands} % \subsection{字号与间距} % % \begin{function}[updated=2014-03-08]{\zihao} % \begin{syntax} % \tn{zihao} \Arg{字号} % \end{syntax} % 用于调整字号大小。其中 \meta{字号} 的有效值共有 16 个,如表 \ref{tab:zihao} % 所示。使用 \tn{zihao} 命令调整字体大小时,西文字号大小会始终和中文字号保持一致。 % \end{function} % % \begin{table}[!htbp] % \centering % \def\ZH#1{\zihaopt{#1} & \zihao{#1}} % \tabcolsep=1em % \caption{中文字号}\label{tab:zihao} % \begin{tabular}{>{\ttfamily}S[mode=text,detect-family,table-format=-1] % S[table-format=2.1]S[table-format=2.5]l} % \toprule % {\meta{字号}} & {大小(bp)} & {大小(pt)} & 意义 \\ % \midrule % 0 & 42 & \ZH{0} 初号 \\ % {−0} & 36 & \ZH{-0} 小初号 \\ % 1 & 26 & \ZH{1} 一号 \\ % -1 & 24 & \ZH{-1} 小一号 \\ % 2 & 22 & \ZH{2} 二号 \\ % -2 & 18 & \ZH{-2} 小二号 \\ % 3 & 16 & \ZH{3} 三号 \\ % -3 & 15 & \ZH{-3} 小三号 \\ % 4 & 14 & \ZH{4} 四号 \\ % -4 & 12 & \ZH{-4} 小四号 \\ % 5 & 10.5 & \ZH{5} 五号 \\ % -5 & 9 & \ZH{-5} 小五号 \\ % 6 & 7.5 & \ZH{6} 六号 \\ % -6 & 6.5 & \ZH{-6} 小六号 \\ % 7 & 5.5 & \ZH{7} 七号 \\ % 8 & 5 & \ZH{8} 八号 \\ % \bottomrule % \end{tabular} % \end{table} % % \begin{function}[updated=2014-03-28]{\ziju} % \begin{syntax} % \tn{ziju} \Arg{中文字符宽度的倍数} % \end{syntax} % 用于调整相邻汉字之间的间距,即(在正常中文行文中)前一个汉字的右边缘与后一个汉字 % 的左边缘之间的距离。其中参数可以是任意浮点数值;而中文字符宽度指的是实际汉字的 % 宽度,不包含当前字距。 % % 这个命令会影响 \tn{ccwd} 的值,但不会影响英文字距。 % \end{function} % % \begin{function}[updated=2014-03-27]{\ccwd} % 当前汉字的字宽保存在长度寄存器 \tn{ccwd} 之中。汉字字宽是相邻两个汉字中心 % 之间的距离,包含字距在内。因此修改字距会间接修改字宽。 % \end{function} % % \subsection{中文数字转换} % % \CTeX{} 宏集的中文数字转换功能实际上是调用 \pkg{zhnumber} 宏包来完成。下面只 % 介绍一些基本的用法,更高级的用法可以查阅 \pkg{zhnumber} 宏包的文档。 % % \begin{function}[updated=2014-03-08]{\chinese} % \begin{syntax} % \tn{chinese} \Arg{counter} % \end{syntax} % \tn{chinese} 命令与 \tn{roman} 等命令的用法类似,作用在一个 \LaTeX{} % 计数器上,将计数器的值以中文数字的形式输出。 % \end{function} % % \begin{function}[added=2014-03-08]{\zhnumber} % \begin{syntax} % \tn{zhnumber} \Arg{number} % \end{syntax} % 以中文格式输出数字。这里的数字可以是整数、小数和分数。 % \end{function} % % \begin{function}[added=2014-03-08]{\zhdigits} % \begin{syntax} % \tn{zhdigits} \Arg{number} % \end{syntax} % 将阿拉伯数字转换为中文数字串。 % \end{function} % % \begin{function}{\CTEXnumber} % \begin{syntax} % \tn{CTEXnumber} "\" \Arg{number} % \end{syntax} % |\| 必须是一个 \TeX{} 宏,不需预先定义。\tn{CTEXnumber} 通过 % \tn{zhnumber} 将 \meta{number} 转为中文数字,最后将结果存储在 |\| % 里。对 |\| 的定义是局部的,将它展开一次就可以得到转换结果。 % \end{function} % % 一般来说,并不需要使用 \tn{CTEXnumber},直接使用 \tn{zhnumber} 即可。但是,如果 % 在文档中需要多次使用同一个数字 \meta{number} 的中文形式,就可以先用 % \tn{CTEXnumber} 将结果保存起来备用,而不是每次使用时都用 \tn{zhnumber} 现场 % 转换一次。 % % \begin{function}{\CTEXdigits} % \begin{syntax} % \tn{CTEXdigits} "\" \Arg{number} % \end{syntax} % \tn{CTEXdigits} 与 \tn{CTEXnumber} 类似,但其转换的结果是中文数字串,而不是 % 中文数字。 % \end{function} % % \subsection{杂项} % % \begin{function}{\CTeX} % 用于显示 \CTeX 标志。 % \end{function} % % \section{\LuaLaTeX{} 下的中文支持方式} % \label{sec:lualatex-chinese} % % 在 \LuaLaTeX{} 下,\CTeX{} 宏集依赖 \pkg{LuaTeX-ja} 宏包来完成中文支持。 % 该宏包是日本 \TeX{} 社区的北川弘典、前田一贵、八登崇之等人开发的,设计目的主要 % 是在 \LuaTeX{} 引擎下实现日本 p\TeX{} 引擎的(大部分)功能。它为了兼容 p\LaTeX % 的使用习惯,对 \LaTeXe 的 \pkg{NFSS} 作了不少修改和扩充。这对于简体中文用户来说 % 不是必要的,因而 \CTeX{} 禁用了它在 \LaTeX{} 格式下的大部分设置,只保留了必要的 % 部分。同时修改了它的字体设置方式,使得相关命令与 \pkg{xeCJK} 宏包大致相同。 % % 20150420 版以后的 \pkg{LuaTeX-ja} 宏包开始支持竖排,但 \CTeX{} 暂不支持竖排。 % % \subsection{\LuaLaTeX{} 下替代字体的设置} % % \begin{function}[added=2014-04-14]{AlternateFont} % \begin{syntax} % \tn{setCJKfamilyfont} \Arg{family} % \ [ % \ AlternateFont = % \ \{ % \ \Arg{character range_1} \oarg{alternate font features_1} \Arg{alternate font name_1} || % \ \Arg{character range_2} \oarg{alternate font features_2} \Arg{alternate font name_2} || % \ ...... % \ \} , % \ % \ ] \Arg{base font name} % \end{syntax} % 在设置字体族 \meta{family} 的时候,同时设置该字体族在字符范围 % \meta{character range_n} 内,对应字形的替代字体。 % \end{function} % % \begin{function}[added=2014-04-14]{CharRange} % \begin{syntax} % \tn{setCJKfamilyfont} \Arg{family} % \ [ % \ CharRange = \Arg{character range} , % \ % \ ] \Arg{alternate font name} % \end{syntax} % 只设置字体族 \meta{family} 在字符范围 \meta{character range} 内,对应字形的 % 替代字体。 % \end{function} % % 一个 \tn{setCJKfamilyfont} 里只能使用一次 \opt{CharRange} 或者 % \opt{AlternateFont},但可以将它们分开重叠使用。例如下面的方式是有效的。 % % \begin{ctexexam} % \setCJKmainfont[AlternateFont={...}{...}, ...]{...} % \setCJKmainfont[CharRange={"4E00->"67FF,-2}, ...]{...} % \setCJKmainfont[CharRange={"6800->"9FFF}, ...]{...} % \end{ctexexam} % % \begin{function}[EXP,added=2014-04-14]{declarecharrange} % \begin{syntax} % \tn{ctexset} % \ \{ % \ declarecharrange = % \ \{ % \ \Arg{name_1} \Arg{character range_1} , % \ \Arg{name_2} \Arg{character range_2} , % \ ... % \ \} % \ \} % \end{syntax} % 预先声明字符范围。声明字符范围 \meta{name} 之后,它的名字 \meta{name} 可以 % 用在 \opt{AlternateFont} 和 \opt{CharRange} 选项的 \meta{character range} % 之中,表示对应的字符范围。 % \end{function} % % 在声明字符范围 \meta{name} 的同时,还为 \tn{setCJKmainfont} 等字体设置命令定义 % 了选项 \meta{name},用于设置对应字符的替代字体: % \begin{quote}\linespread{1}\small\ttfamily % \meta{name} = \oarg{alternate font features} \Arg{alternate font name} % \end{quote} % \meta{name} 选项可以与 \opt{AlternateFont} 共同使用,但不能与 \opt{CharRange} % 一起使用。如果没有给 \meta{name} 设置值,则等价于设置 \opt{CharRange=\meta{name}}, % 即只设置 \meta{name} 对应的字符范围的替代字体。 % % \begin{function}[EXP,added=2014-04-15]{clearalternatefont,resetalternatefont} % \begin{syntax} % \tn{ctexset} % \ \{ % \ clearalternatefont = \Arg{family_1, family_2, ...} , % \ resetalternatefont = \Arg{family_1, family_2, ...} , % \ clearalternatefont , % \ resetalternatefont % \ \} % \end{syntax} % 清除与重置 CJK 字体族 \meta{family} 的替换字体设置。如果没有给定值,则作用于 % 当前 CJK 字体族。清除与重置操作总是全局的。 % \end{function} % % \section{\CTeX{} 宏集的配置文件} % % \CTeX{} 宏集提供了不同的配置文件,可以通过修改配置文件来改变 \CTeX{} 宏集的 % 默认行为。 % % 在多数情况下,并不需要修改配置文件,\CTeX{} 宏集的默认设置已经能满足大多数用 % 户的需要。不恰当地修改 \CTeX{} 宏集的默认行为也可能导致同一文件在别处无法正 % 常编译或排版效果完全不同,因此修改应该慎重。 % % 但在一些情况下,直接修改配置文件仍是必要的,例如: % \begin{itemize} % \item 系统没有安装默认设置的字体文件,无法编译。 % \item 需要经常编译来自其他系统的中文 \TeX{} 文件,但对方的操作系统或默认设置 % 与本机不同。 % \end{itemize} % % 与 \CTeX{} 宏集的源代码一样,配置文件采用 \LaTeXiii{} 的语法编写。 % % \CTeX{} 宏集的配置文件随宏包其他文件一起安装在 \TeX{} 系统 TDS 目录树中,文 % 件后缀是 \file{.cfg}。为了避免本地配置文件内容因 \CTeX{} 宏集的更新而丢失, % 不要直接修改系统 TDS 目录树中的配置文件,而应该将系统自带的配置文件复制到本 % 地的或用户私有的 TDS 目录树中修改,并运行 \bashcmd{texhash} 命令刷新文件名数据库。 % % 例如对于 \TeX{} Live,系统自带的配置文件就在 \TeX{} Live 安装目录下的 % \path{texmf-dist/tex/latex/ctex/config/} 子目录下,可以修改它的副本,保存在 % 本地 TDS 树的 \path{texmf-local/tex/latex/ctex/} 目录下,或者用户 TDS 树的 % \path{~/.texlive2015/texmf-var/tex/latex/ctex/} 目录下,作为本地/用户专有的 % 配置文件。复制配置文件后需要运行 |texhash| 命令使本地配置文件生效。 % % \MiKTeX{} 的配置文件也保存在类似的目录结构中,\MiKTeX{} 管理的 % 几个 TDS 根目录可以在 \MiKTeX{} Options 设置项中查看到,这里不再赘述。 % % 除了修改本地 \TeX{} 系统中的配置文件,对于特定文档,也可以将修改过的配置文件 % 保存在文档的工作目录下。此时配置文件就只对工作目录下的所有文档生效。 % % \subsection{修改宏包默认选项} % % 配置文件 \file{ctexopts.cfg} 可以用来修改宏包的默认选项。随系统安装的配置文 % 件除了文件信息声明外没有实际的内容,但在注释中给出了一个简单的示例,只要取消 % 注释就可以生效。 % % \begin{ctexexam} % % 系统自带 ctexopts.cfg 注释中的示例语句,固定默认字体集为 windowsnew。 % % 该设置可以用在安装了 Windows 字体的非 Windows 系统中。 % \keys_set:nn { ctex / option } { fontset = windowsnew } % \end{ctexexam} % 如上例所示,宏包选项通常使用 \LaTeXiii{} 的 \cs{keys_set:nn} 命令完成键值设置, % 第一个参数是固定的子模块 |ctex/option|,第二个参数中是用户定义的新的默认宏包 % 选项。 % % \file{ctexopts.cfg} 中的设置将在 \CTeX{} 宏集的开始处,定义过宏包选项之后, % \tn{ProcessKeysOptions} 命令之前生效。最好只使用此配置文件修改宏包默认选项。 % % \subsection{宏包载入后的配置} % % 配置文件 \file{ctex.cfg} 将在宏包的末尾被载入生效。可以用它完成任意的设置, % 或是覆盖已有的定义。随系统安装的配置文件除版本信息外没有实际内容,注意配置文 % 件中也使用 \LaTeXiii{} 语法。 % % \begin{ctexexam} % % 简单的 ctex.cfg 内容示例。 % % 修改默认的页面格式设置。 % \pagestyle{plain} % \end{ctexexam} % % \begin{ctexexam} % % 略复杂的 ctex.cfg 内容示例:禁止段末孤字成行。 % % 在使用 XeTeX 编译时,打开 xeCJK 的 CheckSingle 选项。 % \sys_if_engine_xetex:T % { % \xeCJKsetup { CheckSingle } % } % % 在使用 LuaTeX 编译时,设置 LuaTeX-ja 的 jcharwidowpenalty 参数。 % \sys_if_engine_luatex:T % { % \ltjsetparameter { jcharwidowpenalty = 10000 } % } % \end{ctexexam} % % \subsection{配置标题中文翻译} % % 由于 \CTeX{} 宏集需要同时支持 GBK 和 UTF-8 两种编码,因此对标题的中文翻译写 % 在两个配置文件当中:\file{ctex-name-gbk.cfg} 和 \file{ctex-name-utf8.cfg}。 % 两个文件的设置相同,只是编码不同。 % % 为了同一文档在不同电脑上编译效果的一致性,通常不建议修改默认的中文翻译。 % % \subsection{自定义字体集} % % \ref{subs:options-CJK-font}~节介绍的用于 |fontset| 选项的自定义字库文件, % 类似于 \CTeX{} 宏集的配置文件,也应该与其他本地配置文件一起保存在本地 % \texttt{TDS} 目录树下,并可以配合 \file{ctexopts.cfg} 等配置文件使用。 % % \section{对旧版本的兼容性} % % \subsection{\CTeX\ 0.8a 及以前的版本} % % 在 ctex-kit 项目成立之前,\CTeX 宏包的最后一个版本是 \CTeX\ % 0.8a(2007/05/06)。 % % 第 2 版未考虑对这些很早版本的兼容性。 % % \subsection{\CTeX\ 0.9--\CTeX\ 1.0d} % % 在 2009 年在 ctex-kit 项目成立后,新增了 \XeTeX{} 引擎的支持,并增加了不少控 % 制字体的命令和选项。 % % 这里主要介绍新版本 \CTeX 宏包相对 1.02d 版本(2014/06/09)的兼容性。 % % 第 2 版的 \CTeX 宏包已尽力保证对 1.0x 版本的兼容性,原有为 1.0x 编写的代码, % 在第 2 版的 \CTeX 宏包下保证仍能编译,并且在大多数情况下保持编译效果不变。 % % \CTeX 宏包在 0.8a 以前的版本支持以 \pkg{CCT} 作为底层中文支持方式,从 0.9 版 % 之后即不再推荐使用,只保留向后兼容。在 \CTeX 宏包第 2 版中则完全不再支持 % \pkg{CCT}。 % % 下面这些是在旧版本 \CTeX 宏包中存在,而在新版本中已不建议使用的选项和命令, % 在未来版本中可能会删去它们的支持。 % % 在多数情况下它们的功能仍将保留,但也有部分选项命令功能已失效。 % % \begin{function}{cs4size, c5size} % 分别相当于 |zihao=-4| 和 |zihao=5|,过时选项。 % \end{function} % % \begin{function}{CCT, CCTfont} % 相关选项已删除。 % \end{function} % % \begin{function}{indent, noindent} % \opt{indent} 和 \opt{noindent} 什么也不做,过时选项。 % % 在中文版式下,\pkg{ctex} 宏包的相关功能在与标准文档类及其衍生文档类联用时 % 默认打开。\CTeX{} 文档类的相关功能由章节标题的 \opt{afterindent} 选项的值 % 来确定。 % \end{function} % % \begin{function}{zhmap, nozhmap} % \opt{zhmap} 宏包选项增加了参数,扩充了功能,除了支持真假值参数外,还支持选择 % \pkg{zhmCJK} 作为底层中文处理宏包。(\ref{subs:options-CJK-font}~节) % % \opt{nozhmap} 选项相当于 |zhmap=false|。过时选项。 % \end{function} % % \begin{function}{winfonts, adobefonts, nofonts} % 宏包选项 \opt{winfonts} 相当于 |fontset=windows|,\opt{adobefonts} 相当于 % |fontset=adobe|,\opt{nofonts} 相当于 |fontset=none|。这几个选项是过时选项, % 对于新文档,应使用 \opt{fontset} 选项设置不同字体集。 % % 另外,第 2 版 \CTeX 宏包的默认字体不再是 Windows 系统字体,而是根据检测到的 % 操作系统选择使用 Windows、Mac 的系统字体还是 Fandol 字体 % (\ref{subs:options-CJK-font}~节)。 % \end{function} % % \begin{function}{punct, nopunct} % 旧版本中宏包 \opt{punct} 选项没有参数,现在可以用参数设定标点风格 % (\ref{subs:options-type-style}~节)。原有无参形式的 \opt{punct} 选项相当 % 于 |punct=quanjiao|。 % % 旧版宏包中 \opt{nopunct} 选项的效果大致相当于 |punct=plain|。过时选项,不推荐使用。 % \end{function} % % \begin{function}{cap, nocap} % 原有的 \opt{cap} 和 \opt{nocap} 选项由新的 \opt{scheme} 选项代替。 % (\ref{subs:options-type-style}~节) % % \opt{cap} 选项相当于 |scheme = chinese|,\opt{nocap} 选项相当 % 于 |scheme = plain|。它们均已过时,仅因兼容性而保留。 % \end{function} % % \begin{function}{space, nospace} % 新版本宏包 \opt{space} 选项增加真假值参数。 % (\ref{subs:options-type-style}~节) % % \opt{nospace} 选项相当于 |space=false|,成为过时选项。 % \end{function} % % \begin{function}{fancyhdr} % 新版本宏包中总是自动处理对 \pkg{fancyhdr} 宏包的兼容性,而由用户自己使用 % \tn{usepackage} 载入 \pkg{fancyhdr} 宏包。 % % \opt{fancyhdr} 选项过时,因兼容性保留,功能是载入 \pkg{fancyhdr} 宏包。 % \end{function} % % \begin{function}{hyperref} % 新版本宏包中总是自动处理对 \pkg{hyperref} 宏包的兼容性,而由用户自己使用 % \tn{usepackage} 载入 \pkg{hyperref} 宏包。 % % \opt{hyperref} 选项过时,因兼容性保留,功能是在导言区末尾载入 \pkg{hyperref} % 宏包。 % \end{function} % % \begin{function}{fntef} % 旧版本的 \opt{fntef} 选项用于统一 \pkg{CCTfntef} 与 \pkg{CJKfntef} 的界面, % 新版本 \CTeX{} 宏集不再支持 \pkg{CCT},而是直接载入 \pkg{CJKfntef} 或 % \pkg{xeCJKfntef} 宏包并禁用其彩色设置。该选项是过时选项。 % \end{function} % % \begin{function}{\CTEXunderdot, \CTEXunderline, \CTEXunderdblline, % \CTEXunderwave, \CTEXsout, \CTEXxout, \CTEXfilltwosides} % 在调用 \opt{fntef} 宏包选项的同时,旧版本 \CTeX{} 宏包由于需要支持 \pkg{CCT} % 系统,会将以 |\CJK| 开头的 \tn{CJKunderline} 等宏换名为以 |\CTEX| 开头的 % \tn{CTEXunderline} 等宏。此功能在新版本的 \CTeX{} 宏集中已失去意义。 % % 此外,在 \pdfTeX{} 引擎下,用于设置格式的 \tn{CJKunderdotbasesep} 等宏也被换 % 名为 \tn{CTEXunderdotbasesep} 等宏。 % % 在新版本中,上述由 \opt{fntef} 衍生的相关宏都成为过时命令。 % \end{function} % % \begin{function}{\CTEXsetfont} % 更新当前的中文字体信息,包括当前字距(\tn{ccwd})和段首缩进(\tn{parindent})。 % 一般来说,用户无需使用这个命令。 % \end{function} % % \begin{function}{\CTEXindent} % 更新 \tn{ccwd} 宽度后设置 |\parindent=2\ccwd|。过时命令。 % \end{function} % % \begin{function}{\CTEXnoindent} % 设置 |\parindent=0pt|。过时命令。 % \end{function} % % \begin{function}{\CTEXsetup} % \begin{syntax} % \tn{CTEXsetup}\oarg{选项}\Arg{标题} % \end{syntax} % 相当于设置了 % \texttt{\tn{ctexset}\{ \meta{标题} = \Arg{选项} \}}。 % 过时命令。 % \end{function} % % \begin{function}{\CTEXoptions} % \begin{syntax} % \tn{CTEXoptions}\oarg{选项} % \end{syntax} % 相当于设置了 % \texttt{\tn{ctexset}\Arg{选项}}。 % 过时命令。 % \end{function} % % \begin{function}{\Chinese} % \begin{syntax} % \tn{Chinese}\Arg{counter} % \end{syntax} % 新版宏集中 \tn{chinese} 统一了旧版本中 \tn{chinese} 和 \tn{Chinese} 的功能。因此, % 该命令已过时。 % \end{function} % % \begin{function}{captiondelimiter} % 原为 \tn{CTEXoptions} 命令的选项,用于控制 \tn{caption} 编号后面的标点。此选 % 项已过时,并在新版本的 \CTeX 宏包中失效。 % % 可以使用 \pkg{caption} 宏包的 \opt{labelsep} 选项来完成同样的功能。 % \begin{ctexexam} % % 代替 \CTEXoptions[captiondelimiter={:}] % \usepackage{caption} % \captionsetup{labelsep=colon} % \end{ctexexam} % \end{function} % % \subsection{\CTeX\ 1.02c 以后的 SVN 开发版} % % \CTeX 宏包在 1.02c 版本(2011/03/11)之后在 Google code 上的 SVN 开发版本, % 内部版本号一直升到 1.11 版,但从未正式发布。SVN 开发版在 1.02c 版本的基础上 % 新增的功能在第 2 版中大多继承了过来,但新增的命令与选项都不再保持兼容。 % % \CTeX 宏包第 2 版不保证对未发布的 SVN 开发版兼容。 % % \subsection{\CTeX\ 2.2 之前的版本} % % \begin{function}{part/beforeskip, chapter/beforeskip, section/beforeskip, % subsection/beforeskip, subsubsection/beforeskip, paragraph/beforeskip, % subparagraph/beforeskip} % 在 \CTeX\ 2.2 之前的版本中,\opt{beforeskip} 选项的符号还用于确定章节标题后 % 首段的缩进。当 \opt{beforeskip} 是负值时,章节标题后的第一段按英文文档的排版 % 习惯,没有首行缩进,否则保留首行缩进。 % % 这一特性在 2.2 版和后续版本中不再保留,相应的功能通过新的 \opt{afterindent} % 选项来设置。如果原先设置 \opt{beforeskip} 为负值,在新版本中需要改为正值, % 并设置相应的 \opt{afterindent} 选项为 \opt{false}。 % \end{function} % % \begin{function}{section/afterskip, subsection/afterskip, % subsubsection/afterskip, paragraph/afterskip, subparagraph/afterskip} % 在 \CTeX\ 2.2 之前的版本中,对于 \tn{section} 级以下标题,\opt{afterskip} % 选项的符号用于确定标题与随后正文是否排在同一段。 % 如果是正值,则正文另起一段,否则标题与随后正文排在同一段, % \opt{afterskip} 的绝对值给出水平间距。 % % 这一特性在 2.2 版和后续版本中不再保留,相应的功能通过新的 \opt{runin} % 选项来设置。如果原先设置 \opt{afterskip} 为负值,在新版本中需要改为正值, % 并设置相应的 \opt{runin} 选项为 \opt{true}。 % \end{function} % % \section{宏集依赖情况与手工安装方法} % \label{sec:dep-ins} % % 本节介绍 \CTeX{} 宏集的依赖情况,并介绍手工编译安装的具体方法。 % 通常用户只需参照第 \ref{subsec:easy-ins}~节介绍的方法,使用发行版自带的宏包管理器安装 % 本宏集。 % % \CTeX{} 宏集有两个源文件:\file{ctex.dtx}、\file{ctexpunct.spa}。 % 使用不同的编译方式时,\CTeX{} 依赖的宏包略有不同。在手工安装 \CTeX{} 宏集之前,请确保 % 你的 \TeX{} 发行版中已经正确安装了这些宏包。\CTeX{} 依赖宏包的详情叙述如下: % % \begin{itemize} % \item \pkg{expl3}、\pkg{xparse} 和 \pkg{l3keys2e} 宏包。它们属于 \pkg{l3kernel} % 和 \pkg{l3packages} 宏集,它们还依赖 % \begin{itemize} % \item \pkg{etex} 宏包。 % \end{itemize} % \item \pkg{indentfirst} 宏包,属于 \pkg{tools} 宏集。 % \item \pkg{everysel} 宏包,属于 \pkg{ms} 宏集。 % \item \pkg{zhnumber} 宏包。 % \item[\ding{229}] 以上是各种编译方式都必需的依赖项。 % \item \pkg{CJK} 宏集,它的下划线功能依赖 \pkg{ulem} 宏包。 % \item \pkg{CJKpunct} 宏包。 % \item \pkg{xCJK2uni} 宏包。 % \item \pkg{zhmetrics} 宏包。 % \item \pkg{zhmCJK} 宏包。 % \item[\ding{229}] 以上是使用 \pdfLaTeX{} 或 \LaTeX{} + \dvipdfmx{} 的编译方式所需要 % 的依赖项,其中 \pkg{zhmCJK} 是可选的。 % \item \pkg{xeCJK} 宏包,它还依赖 % \begin{itemize} % \item \pkg{fontspec} 宏包,它还依赖 % \begin{itemize} % \item \pkg{euenc} 宏包。 % \item \pkg{xunicode} 宏包,它还依赖 \pkg{tipa} 宏包。 % \end{itemize} % \end{itemize} % \item[\ding{229}] 以上是使用 \XeLaTeX{} 编译时的依赖项。 % \item \pkg{LuaTeX-ja} 宏集,它还依赖 % \begin{itemize} % \item \pkg{oberdiek} 宏集。 % \item \pkg{xkeyval} 宏包。 % \item \pkg{lualibs} 宏包。 % \item \pkg{luaotfload} 宏包,它还依赖 \pkg{luatexbase} 宏包。 % \end{itemize} % \item[\ding{229}] 以上是使用 \LuaLaTeX{} 编译时的依赖项。 % \end{itemize} % % 出于一些原因,\pkg{zhmCJK} 尚未被收入 \TeXLive{} 和 \MiKTeX。因此,若 % 你希望使用 \pkg{zhmCJK} 作为 \CTeX{} 宏集的底层中文支持方式,那么你需要自行安装该宏包。 % \pkg{zhmCJK} 的安装较为复杂。我们建议你 % \begin{enumerate} % \item 从 CTAN 下载 \pkg{zhmCJK} 宏包的 % \href{http://mirrors.ctan.org/install/language/chinese/zhmcjk.tds.zip} % {TDS 安装包}, % \item 按目录结构将文件复制到 \TeX{} 发行版的本地 TDS 根目录, % \item 最后执行 \bashcmd{texhash} 刷新 \TeX{} 发行版的 ls-R 数据库以完成安装。 % \end{enumerate} % 其他细节,可参照其 % \href{http://mirrors.ctan.org/language/chinese/zhmcjk/zhmCJK.pdf}{宏包手册} % 中第 3 节的指导。 % % \emph{\CTeX{} 宏集已被 \TeXLive{} 和 \MiKTeX{} 收录,若无特别理由, % 我们强烈建议用户使用宏包管理器安装本宏集。} % % 若要手工安装,请遵循如下步骤: % \begin{enumerate} % \item 从 CTAN 下载 \CTeX{} 宏集的 % \href{http://mirrors.ctan.org/install/language/chinese/ctex.tds.zip} % {TDS 安装包}, % \item 按目录结构将文件复制到 \TeX{} 发行版的本地 TDS 根目录, % \item 最后执行 \bashcmd{texhash} 刷新 \TeX{} 发行版的 ls-R 数据库以完成安装。 % \end{enumerate} % % \section{开发人员} % % \begin{itemize} % \item 吴凌云 (\email{aloft@ctex.org}) % \item 江疆 (\email{gzjjgod@gmail.com}) % \item 王越 (\email{yuleopen@gmail.com}) % \item 刘海洋 (\email{LeoLiu.PKU@gmail.com}) % \item 李延瑞 (\email{LiYanrui.m2@gmail.com}) % \item 陈之初 (\email{zhichu.chen@gmail.com}) % \item 李清 (\email{sobenlee@gmail.com}) % \item 黄晨成 (\email{liamhuang0205@gmail.com}) % \end{itemize} % % 目前比较活跃的开发维护人员是刘海洋、李清和黄晨成。 % % % \begin{thebibliography}{9} % \bibitem{knuthtex1986} % \textsc{Donald~Ervin Knuth}. % \newblock \textit{The {{\TeX{}book}}}, \textit{Computers \& Typesetting}, % volume~A. % \newblock Addison-Wesley, 1986 % % \bibitem{mittelbach2004} % \textsc{Frank Mittelbach} and \textsc{Michel Goossens}. % \newblock \textit{The {{\LaTeX}} Companion}. % \newblock Tools and Techniques for Computer Typesetting. Boston: % Addison-Wesley, second edition, 2004 % % \end{thebibliography} % % \end{documentation} % % % \StopEventually{} % % %\begin{implementation} % \clearpage % \section{代码实现} % % \begin{macrocode} %<@@=ctex> % \end{macrocode} % % 宏包载入检查。 % \begin{macrocode} %<*class|ctex> \tl_const:Nx \c_@@_version_tl { \cs_if_exist_use:cF { ver@ \@currname . \@currext } { 9999/99/99 } } %<*class> \cs_new_eq:cN { ver@ctex. \@pkgextension } \c_@@_version_tl \cs_new_eq:cN { ver@ctexcap. \@pkgextension } \c_@@_version_tl \cs_new_eq:cN { ver@ctexsize. \@pkgextension } \c_@@_version_tl \cs_new_eq:cN { ver@ctexheading. \@pkgextension } \c_@@_version_tl % %<*ctex> \msg_new:nnnn { ctex } { subpackage-loaded } { Package~`#1'~can~not~be~loaded~with~`ctex'. } { `#1'~is~actually~a~part~of~`ctex'.\\ It~is~not~necessary~to~load~it~separately. } \@ifpackageloaded { ctexsize } { \msg_error:nnn { ctex } { subpackage-loaded } { ctexsize } } { \cs_new_eq:cN { ver@ctexsize. \@pkgextension } \c_@@_version_tl } \@ifpackageloaded { ctexheading } { \msg_error:nnn { ctex } { subpackage-loaded } { ctexheading } } { \cs_new_eq:cN { ver@ctexheading. \@pkgextension } \c_@@_version_tl } % % % \end{macrocode} % % \begin{macrocode} %<*class|style> \RequirePackage { xparse , l3keys2e } % % \end{macrocode} % % \begin{macrocode} %<*class|ctex> % \end{macrocode} % % \changes{v2.3}{2015/12/20}{与 \LaTeXiii{} (2015/12/20) 同步。} % % 检查 \pkg{expl3} 和 \pkg{l3keys2e} 的版本。 % \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 } { 2015/12/20 } { } { \msg_error:nnn { ctex } { l3-too-old } { expl3 } } %<*class> \@ifpackagelater { l3keys2e } { 2015/12/20 } { } { \msg_error:nnn { ctex } { l3-too-old } { l3keys2e } } % % \end{macrocode} % % \begin{variable}[int]{\c_@@_engine_file_str} % 引擎检查,暂不支持 \pTeX{} 系。 % \begin{macrocode} \msg_new:nnnn { ctex } { engine-not-supported } { Engine~`#1'~is~not~yet~supported,~ctex~will~abort! } { You~can~switch~to~xelatex,~lualatex~or~pdflatex.} \file_if_exist:nTF { ctex-engine- \c_sys_engine_str .def } { \str_const:Nx \c_@@_engine_file_str { ctex-engine- \c_sys_engine_str .def } } { \msg_critical:nnx { ctex } { engine-not-supported } { \c_sys_engine_str } } % \end{macrocode} % \end{variable} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<*class|ctex|ctexheading> % \end{macrocode} % % \begin{macrocode} \RequirePackage { ctexhook , ctexpatch } %\RequirePackage { fix-cm , everysel } % \end{macrocode} % % \subsection{内部函数与变量} % % \begin{variable}[int]{\l_@@_tmp_tl,\l_@@_tmp_int,\l_@@_tmp_dim,\l_@@_tmp_box} % \begin{macrocode} \tl_new:N \l_@@_tmp_tl \int_new:N \l_@@_tmp_int %\dim_new:N \l_@@_tmp_dim \box_new:N \l_@@_tmp_box % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\ctex_file_wrapper:nnn} % 设置文件操作的 \tn{catcode} 环境,参数 |#1| 是设置,|#2| 是文件操作,|#3| 是恢复。 % 默认关闭 \LaTeXiii{} 语法环境,并设置 |@| 的 \tn{catcode} 为 $11$。 % \begin{macrocode} \cs_new_protected:Npn \ctex_file_wrapper:nnn #1#2#3 { \use:x { \ExplSyntaxOff \char_set_catcode_letter:n { 64 } #1 \exp_not:n {#2} \bool_if:NTF \l__kernel_expl_bool { \ExplSyntaxOn } { \ExplSyntaxOff } \char_set_catcode:nn { 64 } { \char_value_catcode:n { 64 } } #3 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_file_input:n} % 输入文件。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_file_input:n #1 { \ctex_file_wrapper:nnn { } { \file_input:n {#1} } { } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_scheme_input:n} % 输入 \opt{scheme} 文件。先查找当前文档类下的 \meta{scheme},找不到再查找一般的文件。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_scheme_input:n #1 { \ctex_file_wrapper:nnn { } { \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 } } } { } } \cs_generate_variant:Nn \ctex_scheme_input:n { o } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\g_@@_section_depth_flag} % 若大于 |3|,则 \tn{paragraph} 和 \tn{subparagraph} 标题单独占一行;若为 |3|,则 % \tn{paragraph} 单独占一行。 % \begin{macrocode} \cs_new_eq:NN \g_@@_section_depth_flag \c_two % \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} % % \begin{macro}[int]{\ctex_set_default_ccwd:Nn} % 若参数 |#2| 带长度单位,则设置它为 |tl| 变量 |#1| 的值,否则以 \tn{ccwd} 为单位。 % \begin{macrocode} \cs_new:Npn \ctex_set_default_ccwd:Nn #1#2 { \dim_compare:nNnTF { \ctex_default_pt:n {#2} } = { \ctex_default_pt:n { #2 ~ mm } } { \tl_set:Nn #1 {#2} } { \tl_set:Nn #1 { #2 \ccwd } } } % \end{macrocode} % \end{macro} % % \changes{v2.3}{2015/09/17}{代码实现避免使用 \tn{lowercase} 技巧(Joseph Wright)。} % % \begin{macro}[int]{\ctex_default_pt:n} % 最新版本的 \pkg{expl3} 已经不允许 \cs{dim_to_decimal:n} 的参数带额外的单位。 % 然而我们需要这个特性实现可展的 \tn{@defaultunits}。 % \begin{macrocode} \cs_new:Npn \ctex_default_pt:n #1 { \exp_after:wN \@@_default_pt:w \dim_use:N \etex_dimexpr:D #1 pt \scan_stop: \q_stop } \use:x { \cs_new:Npn \exp_not:N \@@_default_pt:w ##1 \tl_to_str:n { pt } ##2 \exp_not:N \q_stop { ##1 \tl_to_str:n { pt } } } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\l_@@_encoding_tl} % (pdf)\LaTeX{} 初始化编码为 GBK,其它则是 UTF8。 % \begin{macrocode} \tl_new:N \l_@@_encoding_tl \tl_set:Nx \l_@@_encoding_tl { \sys_if_engine_pdftex:TF { GBK } { UTF8 } } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\g_@@_zhmCJK_bool} % 是否使用 \pkg{zhmCJK} 宏包。 % \begin{macrocode} \bool_new:N \g_@@_zhmCJK_bool % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\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_nopar:Npn \ctex_at_end:n { \AtEndOfClass } %\cs_new_protected_nopar:Npn \ctex_at_end:n { \AtEndOfPackage } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\g_@@_std_options_clist} % 保存传递给标准文档类的选项。 % \begin{macrocode} %<*class> \clist_new:N \g_@@_std_options_clist % % \end{macrocode} % \end{variable} % % 对无效选项给出警告。 % \begin{macrocode} \msg_new:nnn { ctex } { invalid-option } { Option~`\l_keys_key_tl'~is~invalid~in~current~mode. } \msg_new:nnn { ctex } { invalid-value } { Value~`#1'~is~invalid~for~the~key~`\l_keys_key_tl'. } % \end{macrocode} % % 对过时选项或命令给出警告。 % \begin{macrocode} \msg_new:nnn { ctex } { deprecated-option } { Option~ `\l_keys_key_tl'~ is~ deprecated.\\ #1 } \msg_new:nnn { ctex } { deprecated-command } { Command~ #1 is~ deprecated.\\ #2 } \msg_new:nnn { ctex } { deprecated-environment } { Environment~ `#1'~ is~ deprecated.\\ #2 } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{variable}[int]{\g_@@_font_size_flag} % |0| 表示修改默认字体大小为五号,|1| 为小四号,其它值则不作修改。 % \begin{macrocode} %<*class|ctex|ctexsize> \cs_new_eq:NN \g_@@_font_size_flag \c_minus_one % % \end{macrocode} % \end{variable} % % \subsection{宏包选项} % % \changes{v2.3}{2015/09/25} % {\texttt{.value_required:} 和 \texttt{.value_forbidden:} 已过时。} % % \begin{macrocode} %<*class|style> \keys_define:nn { ctex / option } { % % \end{macrocode} % % \changes{v2.0}{2015/05/06}{新增 \opt{zihao} 选项。} % \changes{v2.0}{2015/05/06}{\opt{c5size}, \opt{cs4size} 是过时选项。} % % \begin{macro}{zihao} % \begin{macrocode} %<*class|ctex|ctexsize> zihao .choice: , zihao .default:n = { 5 } , zihao / 5 .code:n = { \cs_gset_eq:NN \g_@@_font_size_flag \c_zero } , zihao / -4 .code:n = { \cs_gset_eq:NN \g_@@_font_size_flag \c_one } , zihao / false .code:n = { \cs_gset_eq:NN \g_@@_font_size_flag \c_two } , % } % %<*class|ctex> c5size .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `zihao=5'~ is~ set. } \keys_set:nn { ctex / option } { zihao = 5 } } , cs4size .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `zihao=-4'~ is~ set. } \keys_set:nn { ctex / option } { 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 = { \msg_warning:nnn { ctex } { deprecated-option } { The~ functionality~ has~ been~ removed.\\ It's~ better~ to~ set~ the~ heading~ styles~ via~ `afterindent'~ options.~ } } , indent .value_forbidden:n = true , noindent .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { The~ functionality~ has~ been~ removed.\\ It's~ better~ to~ set~ the~ heading~ styles~ via~ `afterindent'~ options. } } , noindent .value_forbidden:n = true , % \end{macrocode} % \end{macro} % % \begin{macro}{GBK,UTF8} % \begin{macrocode} GBK .code:n = { \tl_set:Nn \l_@@_encoding_tl { GBK } } , UTF8 .code:n = { \tl_set:Nn \l_@@_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、 % Mac~OS~X 和其它。 % \begin{macrocode} fontset .tl_gset:N = \g_@@_fontset_tl , nofonts .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `fontset=none'~ is~ set.~ It~ is~ better~ to~ use~ fontset~ option. } \keys_set:nn { ctex / option } { fontset = none } } , adobefonts .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `fontset=adobe'~ is~ set.~ It~ is~ better~ to~ use~ fontset~ option. } \keys_set:nn { ctex / option } { fontset = adobe } } , winfonts .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `fontset=windows'~ is~ set.~ It~ is~ better~ to~ use~ fontset~ option. } \keys_set:nn { ctex / option } { 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 = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `zhmap=false'~ is~ set. } \keys_set:nn { ctex / option } { 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 = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `punct=plain'~ is~ set. } \keys_set:nn { ctex / option } { 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 } { \exp_args:Nx \ctex_at_end:n { \keys_set:nn { ctex } { space = \l_keys_choice_tl } } } , space .default:n = { true } , nospace .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `space=false'~ is~ set. } \keys_set:nn { ctex / option } { 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} sub3section .code:n = { \cs_gset_eq:NN \g_@@_section_depth_flag \c_three } , sub4section .code:n = { \cs_gset_eq:NN \g_@@_section_depth_flag \c_four } , 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} % % \begin{macrocode} % %<*class|ctex> % \end{macrocode} % % \begin{macrocode} cap .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `scheme = chinese' ~ is~ set. } \keys_set:nn { ctex / option } { scheme = chinese } } , nocap .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { Option~ `scheme = plain' ~ is~ set. } \keys_set:nn { ctex / option } { 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,fancyhdr,hyperref} % \changes{v2.1}{2015/06/03}{补充定义 \tn{hypersetup}。} % 这些都是过时的宏包兼容选项,原选项功能总是打开的。 % \begin{macrocode} fntef .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { `(xe)CJKfntef'~ package~ is~ always~ loaded. } } , fancyhdr .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { `fancyhdr'~ package~ is~ loaded. } \RequirePackage { fancyhdr } } , hyperref .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { `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: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> { \cs_gset_eq:NN \g_@@_font_size_flag \c_two } , % %<*class> { \cs_gset_eq:NN \g_@@_font_size_flag \c_two \clist_gput_right:Nn \g_@@_std_options_clist {#1} } , % #1 .value_forbidden:n = true , } } \use:x { \keys_define:nn { ctex / option } { \exp_not:o { \l_@@_tmp_tl } } } \tl_clear:N \l_@@_tmp_tl % \end{macrocode} % \end{macro} % % 将未知选项传给标准文档类。 % \begin{macrocode} %<*class> \keys_define:nn { ctex / option } { 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> \ProcessKeysOptions { ctex / option } % % \end{macrocode} % % \begin{macrocode} %<*class> % \end{macrocode} % % 五号字使用标准文档类的 |10pt| 字体大小设置,小四号字则使用 |12pt|。 % \begin{macrocode} \if_case:w \g_@@_font_size_flag \clist_gput_right:Nn \g_@@_std_options_clist { 10pt } \or: \clist_gput_right:Nn \g_@@_std_options_clist { 12pt } \fi: % \end{macrocode} % % 使用 \tn{PassOptionsToClass} 是为了预防可能存在的选项冲突。 % \begin{macrocode} %<*article> \tl_const:Nn \c_@@_class_tl { article } \PassOptionsToClass { \g_@@_std_options_clist } { article } \LoadClass { article } % %<*book> \tl_const:Nn \c_@@_class_tl { book } \PassOptionsToClass { \g_@@_std_options_clist } { book } \LoadClass { book } % %<*report> \tl_const:Nn \c_@@_class_tl { report } \PassOptionsToClass { \g_@@_std_options_clist } { report } \LoadClass { report } % % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{用户设置接口} % % \changes{v2.0}{2014/03/18}{新增统一设置接口 \tn{ctexset}。} % % \begin{macro}{\ctexset} % \begin{macrocode} %<*class|ctex|ctexheading> \NewDocumentCommand \ctexset { } { \keys_set:nn { ctex } } % % \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 } { \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXsetup } { \ctexset~ {~ #2~ =~ {~ #1~ }~ }~ is~ set. } \IfNoValueF {#1} { \keys_set:nn { ctex / #2 } {#1} } } \NewDocumentCommand \CTEXoptions { +o } { \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXoptions } { \ctexset~ {~ #1~ }~ is~ set. } \IfNoValueF {#1} { \keys_set:nn { ctex } {#1} } } % % \end{macrocode} % \end{macro} % % \subsection{特定引擎支持与设置} % % \subsubsection{\pkg{ctex-engine-pdftex.def}} % % \begin{macrocode} %<*pdftex> % \end{macrocode} % % \changes{v2.1}{2015/05/18}{给 \pdfLaTeX{} 下的非 UTF8 编码 CJK 字体族加上 CMap。} % % \begin{variable}[int]{\c_@@_cmap_encoding_seq} % 需要加上 CMap 的 CJK 字体编码。 % \begin{macrocode} \seq_new:N \c_@@_cmap_encoding_seq \seq_set_from_clist:Nn \c_@@_cmap_encoding_seq { C19 , C10 , C00 , C09 , C40 , C60 } % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\ctex_family_cmap:nn} % 在 \tn{DeclareFontFamily} 的 \meta{loading-settings} 中给 CJK 字体族加上 CMap。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_family_cmap:nn #1#2 { \cs_if_free:cF { #1 + #2 } { \seq_if_in:NnT \c_@@_cmap_encoding_seq {#1} { \tl_gput_right:cn { #1 + #2 } { \ctex_add_cmap:n {#1} } } } } \cs_generate_variant:Nn \ctex_family_cmap:nn { x } \cs_new_eq:NN \CTEX@Family@CMap \ctex_family_cmap:xn % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_add_cmap:n} % 给 |#1| 编码的 CJK 字体加上 CMap。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_add_cmap:n #1 { \cs_if_free:NF \CJK@plane { \ctex_add_cmap:cn { @@_add_cmap_ #1 \CJK@plane : } {#1} } } \cs_new_protected_nopar:Npn \ctex_add_cmap:Nn #1#2 { \cs_if_exist:NF #1 { \@@_save_cmap:Nn #1 {#2} } #1 } \cs_generate_variant:Nn \ctex_add_cmap:Nn { c } \cs_new_protected_nopar:Npn \@@_save_cmap:Nn #1#2 { \tl_set:Nx \l_@@_tmp_tl { \str_lower_case:n {#2} \CJK@plane } \tex_immediate:D \pdfobj stream ~ file { \l_@@_tmp_tl .cmap } \cs_new_protected_nopar:Npx #1 { \exp_not:N \pdffontattr \exp_not:N \font { /ToUnicode ~ \int_use:N \pdflastobj \c_space_tl 0 ~ R } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\DeclareFontFamily} % 只在 \pdfLaTeX{} 下加 CMap。如 \pkg{cmap} 宏包被引入,则不重复设置。 % \begin{macrocode} \group_begin: \char_set_catcode_other:N \# \sys_if_output_pdf:TF { \group_end: \ctex_appto_cmd:NnnTF \DeclareFontFamily { \ExplSyntaxOff } { \CTEX@Family@CMap {#1} {#2} } { \ctex_at_end_package:nn { cmap } { \cs_gset_eq:NN \CTEX@Family@CMap \use_none:nn } } { \ctex_patch_failure:N \DeclareFontFamily } } { \group_end: } % \end{macrocode} % \end{macro} % % 首先检查选项,决定是否载入 \pkg{zhmCJK} 宏包。 % \begin{macrocode} \if_bool:N \g_@@_zhmCJK_bool \PassOptionsToPackage { encoding = \l_@@_encoding_tl } { zhmCJK } \RequirePackage { zhmCJK } % \end{macrocode} % 不载入 \pkg{zhmCJK} 宏包时直接调用 \pkg{CJK} 及相关宏包。 % \begin{macrocode} \else: \str_if_eq:onTF { \l_@@_encoding_tl } { GBK } { \RequirePackage { CJK } } { \RequirePackage { CJKutf8 } } \RequirePackage { CJKpunct , CJKspace } % \end{macrocode} % % \begin{macro}[int]{\ctex_load_zhmap:nnnn} % 载入 \pkg{zhmetrics} 的字体映射文件,同时设置 \tn{CJKrmdefault} 等。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_load_zhmap:nnnn #1#2#3#4 { \tl_set:Nn \CJKrmdefault {#1} \tl_set:Nn \CJKsfdefault {#2} \tl_set:Nn \CJKttdefault {#3} \AtBeginDvi { \file_input:n {#4} } \ctex_at_end_package:nn { atbegshi } { \AtBeginShipoutFirst { \file_input:n {#4} } } } \@onlypreamble \ctex_load_zhmap:n % \end{macrocode} % \end{macro} % % \begin{macrocode} \tl_if_exist:NF \CJKfamilydefault { \tl_const:Nn \CJKfamilydefault { \CJKrmdefault } } \tl_if_exist:NF \CJKrmdefault { \tl_new:N \CJKrmdefault } \tl_if_exist:NF \CJKsfdefault { \tl_new:N \CJKsfdefault } \tl_if_exist:NF \CJKttdefault { \tl_new:N \CJKttdefault } \ctex_preto_cmd:NnnTF \rmfamily { \ExplSyntaxOff } { \CJKfamily { \CJKrmdefault } } { } { \ctex_patch_failure:N \rmfamily } \ctex_preto_cmd:NnnTF \sffamily { \ExplSyntaxOff } { \CJKfamily { \CJKsfdefault } } { } { \ctex_patch_failure:N \sffamily } \ctex_preto_cmd:NnnTF \ttfamily { \ExplSyntaxOff } { \CJKfamily { \CJKttdefault } } { } { \ctex_patch_failure:N \ttfamily } \ctex_preto_cmd:NnnTF \normalfont { \ExplSyntaxOff } { \CJKfamily { \CJKfamilydefault } } { \cs_set_eq:NN \reset@font \normalfont } { \ctex_patch_failure:N \normalfont } % \end{macrocode} % % \pkg{zhmCJK} 判断结束。 % \begin{macrocode} \fi: % \end{macrocode} % % \begin{macro}[int]{\ctex_CJK_input:n,\CJK@input} % \pkg{breqn} 包可能会在正文中将 |^| 的 \tn{catcode} 改为 $12$ 或 $13$,这将 % 破坏 \pkg{CJK} 对汉字的首字节的定义(\tn{CJK@loadBinding} 和 % \tn{CJK@loadEncoding})。因此需要确保载入 \file{.enc} 和 \file{.bdg} 文件时, % |^| 的 \tn{catcode} 为 $7$。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_CJK_input:n #1 { \ctex_file_wrapper:nnn { \char_set_catcode_other:n { 60 } % < \char_set_catcode_math_superscript:n { 94 } % ^ \int_set_eq:NN \tex_endlinechar:D \c_minus_one } { \file_input:n {#1} } { \char_set_catcode:nn { 60 } { \char_value_catcode:n { 60 } } \char_set_catcode:nn { 94 } { \char_value_catcode:n { 94 } } \int_set:Nn \tex_endlinechar:D { \int_use:N \tex_endlinechar:D } } } \cs_set_eq:NN \CJK@input \ctex_CJK_input:n % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_plane_to_utfxvibe:Nn,\CJK@surr} % \changes{v2.0}{2014/04/08}{解决与 \tn{nouppercase} 的冲突。} % \pkg{fancyhdr} 宏包的 \tn{nouppercase} 会将 \tn{uppercase} 定义为 \tn{relax},而 % \tn{CJK@surr} 需要用它将 \tn{CJK@plane} 转化成大写字母,这就造成了冲突^^A % \footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/146}}。 % 我们在这里给出 \tn{CJK@surr} 的一个不依赖 \tn{uppercase} 的实现。 % \begin{macrocode} \if_cs_exist:N \CJK@surr \cs_new_protected_nopar:Npn \ctex_plane_to_utfxvibe:Nn #1#2 { \tl_set:Nx \l_@@_tmp_tl {#2} \int_set:Nn \l_@@_tmp_int { \exp_args:No \int_from_hex:n { \l_@@_tmp_tl } } \int_compare:nNnTF \l_@@_tmp_int < \c_two_hundred_fifty_six { \tl_gset:Nx #1 { \int_to_Hex:n { \l_@@_tmp_int } } } { \int_sub:Nn \l_@@_tmp_int { \c_two_hundred_fifty_six } \tl_gset:Nx #1 { \int_to_Hex:n { \int_div_truncate:nn { \l_@@_tmp_int } { \c_four } + "D800 } \int_to_Hex:n { \int_mod:nn { \l_@@_tmp_int } { \c_four } + "DC } } } } \cs_set_eq:NN \CJK@surr \ctex_plane_to_utfxvibe:Nn \fi: % \end{macrocode} % \end{macro} % % \pkg{CJKpunct} 宏包会在 \tn{AtBeginDocument} 的里设置标点格式为 \opt{quanjiao}。 % \begin{macrocode} \AtBeginDocument { \str_if_eq_x:nnF { \l_@@_punct_tl } { quanjiao } { \punctstyle { \l_@@_punct_tl } } } % \end{macrocode} % % 启用中文字符功能。\texttt{GBK} 编码时,将汉字的首字节设置为活动字符,并对这些 % 字符初始化;\texttt{UTF8} 编码时,上游宏包已经处理好。 % \tn{CJK@makeActive} 应该先于 \file{ctex-name-gbk.cfg} 等文件的载入。 % 注意 \tn{CJK@loadBinding} 需要调用补丁后的 \tn{CJK@input}。使用 % \pkg{zhmCJK} 时,此功能已经被启用。 % \begin{macrocode} \reverse_if:N \if_bool:N \g_@@_zhmCJK_bool \str_if_eq:onF { \l_@@_encoding_tl } { UTF8 } { \CJK@makeActive \CJK@loadBinding { standard } } % \end{macrocode} % % 在导言区结束时调用 \tn{CJK@envStart} 启用完整的中文功能。 % % \tn{CJK@envStart} 的定义是 % \begin{verbatim} % \def\CJK@envStart#1#2#3{ % \CJK@upperReset % \ifCJK@lowercase@ % \CJK@lowerReset % \fi% % \CJK@makeActive% % \CJK@global\let\CJK@selectFamily \CJK@selFam % \CJK@global\let\CJK@selectEnc \CJK@selEnc% % \def\CJK@@@enc{#2} % \ifx\CJK@@@enc \@empty % \PackageInfo{CJK}{ % no encoding parameter given,\MessageBreak % waiting for \protect\CJKenc\space commands} % \else % \CJKenc{#2} % \fi % \CJKfontenc{#2}{#1} % \CJKfamily{#3} % \def\CJK@series{\f@series} % \def\CJK@shape{\f@shape}% % \csname CJKhook\endcsname} % \end{verbatim} % \tn{CJK@upperReset} 可能会有一定风险,因此我们直到导言区末尾才使用 % \tn{CJK@envStart}。这样可以避免将 \env{CJK} 环境内置入 \env{document} 环境的 % 最里层,最后也就不需要 \tn{clearpage}。\pkg{zhmCJK} 已经提供类似功能。 % \begin{macrocode} \exp_args:Nx \ctex_at_end_preamble:n { \exp_not:N \CJK@envStart { } { \l_@@_encoding_tl } { \exp_not:N \CJKfamilydefault } \exp_not:N \CJKtilde } % \end{macrocode} % % \pkg{zhmCJK} 判断结束。 % \begin{macrocode} \fi: % \end{macrocode} % % \begin{macro}[int]{\ctex_auto_ignorespaces:} % 关闭名字空间,保存 \tn{CJK@@ignorespaces} 的定义,方便使用。 % \begin{macrocode} %<@@=> \cs_new_eq:NN \ctex_auto_ignorespaces: \CJK@@ignorespaces % \end{macrocode} % 恢复名字空间,要把它放在一个 \env{macrocode} 环境中,\cls{l3doc} 才能正确工作。 % \begin{macrocode} %<@@=ctex> % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ignorespaces_case:N,\ctex_set_ignorespaces:} % 设置忽略空格的的方式。根据 \opt{space} 选项的值重定义 \tn{CJK@ignorespaces}, % 并保存起来供 \tn{CJKhook} 备用。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ignorespaces_case:N #1 { \cs_set_protected_nopar:Npn \ctex_set_ignorespaces: { \cs_set_eq:NN \CJK@ignorespaces #1 } \ctex_set_ignorespaces: } \cs_new_protected_nopar:Npn \ctex_set_ignorespaces: { \cs_set_eq:NN \CJK@ignorespaces \ctex_auto_ignorespaces: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKhook} % \env{CJK} 和 \env{CJK*} 环境都会重新定义 \tn{CJK@ignorespaces}。我们在 \pkg{CJK} % 宏包提供的 \tn{CJKhook} 里重新设置它,让这两个环境忽略空格的方式都受 \opt{space} % 选项的控制。这对 \pkg{zhmCJK} 是必要的。 % \begin{macrocode} \ctex_gadd_hook:Nn \CJKhook { \ctex_set_ignorespaces: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_punct_set:n} % 设置 CJK 族对应到实际的字体。|#1| 是 \opt{fontset} 的名字。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_punct_set:n #1 { \clist_map_inline:Nn \c_@@_punct_family_clist { \cs_if_free:cF { c_@@_ #1 ##1 _punct_spaces_tl } { \cs_set_eq:cc { CJKpunct@ ##1 @spaces } { c_@@_ #1 ##1 _punct_spaces_tl } } } } \clist_const:Nn \c_@@_punct_family_clist { zhsong , zhhei , zhfs , zhkai , zhli , zhyou , zhsongb , zhheil , zhheib , zhyoub , zhyahei , zhyaheib } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_punct_map_family:nn} % CJK 族 |#1| 使用族 |#2| 的边界信息。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_punct_map_family:nn #1#2 { \cs_if_free:cF { CJKpunct@ #2 @spaces } { \cs_set_eq:cc { CJKpunct@ #1 @spaces } { CJKpunct@ #2 @spaces } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_punct_map_bfseries:nn} % CJK 族 |#1| 的 \tn{bfseries} 使用族 |#2| 的边界信息。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_punct_map_bfseries:nn #1#2 { \clist_map_inline:nn {#1} { \ctex_punct_map_series:nnn { ##1 } { b } {#2} \ctex_punct_map_series:nnn { ##1 } { bx } {#2} } } \cs_new_protected_nopar:Npn \ctex_punct_map_series:nnn #1#2#3 { \CJKpunctmapfamily { C19 } {#1} {#2} { m } {#3} \CJKpunctmapfamily { C19 } {#1} {#2} { it } {#3} \CJKpunctmapfamily { C19 } {#1} {#2} { sl } {#3} \CJKpunctmapfamily { C70 } {#1} {#2} { m } {#3} \CJKpunctmapfamily { C70 } {#1} {#2} { it } {#3} \CJKpunctmapfamily { C70 } {#1} {#2} { sl } {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_punct_map_itshape:nn} % CJK 族 |#1| 的 \tn{itshape} 使用族 |#2| 的边界信息。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_punct_map_itshape:nn #1#2 { \CJKpunctmapfamily { C19 } {#1} { m } { it } {#2} \CJKpunctmapfamily { C19 } {#1} { b } { it } {#2} \CJKpunctmapfamily { C19 } {#1} { bx } { it } {#2} \CJKpunctmapfamily { C70 } {#1} { m } { it } {#2} \CJKpunctmapfamily { C70 } {#1} { b } { it } {#2} \CJKpunctmapfamily { C70 } {#1} { bx } { it } {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_punct_space:nn,\ctexspadef} % 定义标点的边界信息。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_punct_space:nn #1#2 { \tl_const:cn { c_@@_ #1 _punct_spaces_tl } {#2} } \cs_new_eq:NN \ctexspadef \ctex_punct_space:nn % \end{macrocode} % \end{macro} % % 载入边界信息文件。 % \begin{macrocode} \ctex_file_input:n { ctexspa.def } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{\pkg{ctex-engine-xetex.def}} % % \begin{macrocode} %<*xetex> % \end{macrocode} % % \begin{macrocode} \RequirePackage { xeCJK } \exp_args:Nx \xeCJKsetup { LoadFandol = false , AutoFakeBold = true , PunctStyle = \l_@@_punct_tl } % \end{macrocode} % % 最新版本的 \pkg{fontspec} 默认对 \tn{rmfamily} 和 \tn{sffamily} 设置 % |Ligatures=TeX|,对 \tn{ttfamily} 设置 |WordSpace={1,0,0}| 和 % |PunctuationSpace=WordSpace|。 % \begin{macrocode} \@ifpackagelater { fontspec } { 2014/05/25 } { } { \msg_error:nnn { ctex } { package-too-old } { fontspec } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{\pkg{ctex-engine-luatex.def}} % % \begin{macrocode} %<*luatex> % \end{macrocode} % % \changes{v2.0}{2014/03/08}{通过 \pkg{LuaTeX-ja} 宏包支持 \LuaLaTeX。} % \changes{v2.3}{2015/09/25}{更新 \pkg{LuaTeX-ja} 支持(20150922.0)。} % % \pkg{LuaTeX-ja} 为了兼容 p\LaTeX 的使用习惯,对 \LaTeXe 的 \pkg{NFSS} 作了不少 % 修改和扩充,这对于简体中文用户来说不是必要的。我们在这里禁用它。 % \begin{macrocode} \msg_new:nnn { ctex } { luatexja-loaded } { Package~`luatexja'~can~not~be~loaded~before~`ctex'.\\ Loading~file~`#1'~will~abort! } \@ifpackageloaded { luatexja } { \msg_critical:nnx { ctex } { luatexja-loaded } { \g_file_current_name_tl } } { \tl_const:cn { ver@ltj-latex.\@pkgextension } { 9999/99/99 } } % \end{macrocode} % % \begin{macrocode} \RequirePackage { luatexja } \@ifpackagelater { luatexja } { 2015/09/21 } { } { \msg_error:nnn { ctex } { package-too-old } { luatexja } } % \end{macrocode} % % \begin{macrocode} \RequirePackage { fontspec } \@ifpackagelater { fontspec } { 2014/05/25 } { } { \msg_error:nnn { ctex } { package-too-old } { fontspec } } % \end{macrocode} % % \paragraph{\pkg{LuaTeX-ja} 的默认设置} % % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % 以下设置抄录自 \file{lltjdefs.sty}。 % \begin{macrocode} \ltjdefcharrange{1}{"80-"36F, "1E00-"1EFF} \ltjdefcharrange{2}{"370-"4FF, "1F00-"1FFF} \ltjdefcharrange{3}{% "2000-"243F, "2500-"27BF, "2900-"29FF, "2B00-"2BFF} \ltjdefcharrange{4}{% "500-"10FF, "1200-"1DFF, "2440-"245F, "27C0-"28FF, "2A00-"2AFF, "2C00-"2E7F, "4DC0-"4DFF, "A4D0-"A82F, "A840-"ABFF, "FB00-"FE0F, "FE20-"FE2F, "FE70-"FEFF, "10000-"1FFFF, "E000-"F8FF} % non-Japanese \ltjdefcharrange{5}{"D800-"DFFF, "E0000-"E00FF, "E01F0-"10FFFF} \ltjdefcharrange{6}{% "2460-"24FF, "2E80-"2EFF, "3000-"30FF, "3190-"319F, "31F0-"4DBF, "4E00-"9FFF, "F900-"FAFF, "FE10-"FE6F, "20000-"2FFFF, "E0100-"E01EF} \ltjdefcharrange{7}{ "1100-"11FF, "2F00-"2FFF, "3100-"31EF, "A000-"A4CF, "A830-"A83F, "AC00-"D7FF} \ltjdefcharrange{8}{"A7, "A8, "B0, "B1, "B4, "B6, "D7, "F7} \ltjsetparameter{jacharrange={-1, +2, +3, -4, -5, +6, +7, -8}} \directlua{for x=128,255 do luatexja.math.is_math_letters[x] = true end} % \end{macrocode} % % 以下设置抄录自 \file{ltj-latex.sty}。 % \begin{macrocode} \directlua{ local s = kpse.find_file('ltj-kinsoku.lua', 'tex') luatexja.stack.charprop_stack_table[0] = s and dofile(s) or {} } \ltjsetparameter{kanjiskip=\z@ plus .4pt minus .4pt, xkanjiskip=.25\zw plus 1pt minus 1pt, autospacing, autoxspacing, jacharrange={-1}, yalbaselineshift=\z@, yjabaselineshift=\z@, jcharwidowpenalty=500, differentjfm=paverage } % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOn % \end{macrocode} % % \paragraph{\pkg{LuaTeX-ja} 的补丁} % % \begin{macrocode} %<@@=ctex_ltj> % \end{macrocode} % % \changes{v2.3}{2015/09/26}{更新 \pkg{unicode-math} 宏包补丁。} % % 在 \LaTeX{} 下,\pkg{LuaTeX-ja} 对 \pkg{fontspec}、\pkg{xunicode}、\pkg{unicode-math} % 和 \pkg{listings} 打了补丁。其中前三个是把 \tn{char} 换成 \tn{ltjalchar},确保 % 字符是 ALchar 类。我们这里用 \pkg{xunicode-addon} 来处理 \pkg{xunicode}。 % \begin{macrocode} \RequirePackage { xunicode-addon } \AtBeginUTFCommand { \group_begin: \lua_now_x:n { tex.globaldefs = 0 } \ltj@allalchar } \AtEndUTFCommand { \group_end: } % \end{macrocode} % 对 \pkg{fontspec} 沿用 \pkg{LuaTeX-ja} 的补丁。 % \begin{macrocode} \RequirePackage { lltjp-fontspec } % \end{macrocode} % \pkg{lltjp-unicode-math} 让数学符号命令成为普通的文字宏。为了避免它被展开,应该 % 用 \tn{protected} 来定义。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_um_define_math_chars: { \group_begin: \cs_set_protected:Npn \__um_sym:nnn ##1##2##3 { \tl_if_in:nnT { \mathord \mathalpha \mathbin \mathrel \mathpunct \mathop \mathfence } { ##3 } { \@@_um_char:Nn ##2 { ##1 } } } \__um_input_math_symbol_table: \group_end: } \cs_new_protected:Npn \@@_um_char:Nn #1#2 { \@@_um_char_aux:Nx #1 { \char_generate:nn {#2} { 12 } } \ltjsetmathletter {#2} } \cs_new_protected:Npn \@@_um_char_aux:Nn #1#2 { \cs_gset_protected_nopar:Npn #1 { \mode_if_math:TF {#2} { { \lua_now_x:n { tex.globaldefs = 0 } \ltj@allalchar #2 } } } } \cs_generate_variant:Nn \@@_um_char_aux:Nn { Nx } \ctex_at_end_package:nn { unicode-math } { \cs_set_eq:NN \__um_define_math_chars: \@@_um_define_math_chars: \@ifpackagelater { unicode-math } { 2015/06/28 } { \cs_set_eq:NN \use@mathgroup \ctex_ltj_use_math_group:Nn \cs_set_protected_nopar:Npn \ctex_ltj_math_group_hook: { \__um_switchto_literal: } } { } } % \end{macrocode} % 对 \pkg{listings} 的补丁是让代码环境支持 JAchar 类。\pkg{LuaTeX-ja} 的补丁会将 % 代码目录标题改为日文,我们不需要。 % \begin{macrocode} \ctex_at_end_package:nn { listings } { \use:x { \exp_not:N \RequirePackage { lltjp-listings } \tl_set:Nn \exp_not:N \lstlistingname { \exp_not:o { \lstlistingname } } \tl_set:Nn \exp_not:N \lstlistlistingname { \exp_not:o { \lstlistlistingname } } } } % \end{macrocode} % % \paragraph{字体切换方式} % % \begin{macro}[int]{\ctex_ltj_select_font:,\CJK@family} % \tn{CJK@family} 保存的是当前 CJK 实际的字体族名,如果为空表示没有设置过字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_select_font: { \cs_if_exist_use:cF { \l_@@_current_font_tl } { \tl_if_empty:NF \CJK@family { \@@_select_font_aux: } } } \tl_new:N \CJK@family \tl_new:N \l_@@_current_font_tl \tl_set:Nn \l_@@_current_font_tl { \CJK@encoding / \CJK@family / \f@series / \f@shape / \f@size } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_select_font_aux:} % 使用 \tn{pickup@font} 取得字体名称前,总需要先设置 \tn{font@name}。在这里将 % \tn{f@family} 换成 CJK 字体族,并确保编码正确。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_select_font_aux: { \group_begin: \tl_set_eq:NN \f@encoding \CJK@encoding \tl_set_eq:NN \f@family \CJK@family \@@_push_fontname:n { \use:c { \curr@fontshape / \f@size } } \ctex_ltj_pickup_font: \group_end: \font@name \@@_pop_fontname: % \end{macrocode} % 当字形未定义的时候,\textsf{NFSS} 就会启动替换机制(\tn{wrong@fontshape})。 % 第一次启动后,\cs{l_@@_current_font_tl} 还是没有定义。为此,我们再次选择字体, % 确保它有定义和指向正确的 \texttt{font.id}。这对 \opt{AlternateFont} 的设置 % 特别重要。 % \begin{macrocode} \cs_if_exist:cF { \l_@@_current_font_tl } { \@@_select_font_aux: } } \cs_new_protected_nopar:Npn \@@_push_fontname:n #1 { \cs_gset_eq:NN \@@_save_fontname:w \font@name \cs_gset_nopar:Npx \font@name {#1} } \cs_new_protected_nopar:Npn \@@_pop_fontname: { \cs_gset_eq:NN \font@name \@@_save_fontname:w } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_pickup_font:} % 替换 \tn{define@newfont} 内部调用的 \tn{extract@font} 和 \tn{do@subst@correction}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_pickup_font: { \exp_after:wN \cs_if_exist:NF \font@name { \group_begin: \cs_set_eq:NN \extract@font \ctex_ltj_extract_font: \cs_set_eq:NN \do@subst@correction \ctex_ltj_subst_font: \define@newfont \group_end: } } \cs_new_eq:NN \pickup@jfont \ctex_ltj_pickup_font: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_extract_font:} % \pkg{LuaTeX-ja} 的 \tn{globaljfont} 在 \pkg{luatexja-core} 中定义: % \begin{verbatim} % %%%%%%%% \jfont\CS={...:...;jfm=metric;...}, \globaljfont % \protected\def\jfont#1{% % \afterassignment\ltj@@jfont % \directlua{luatexja.jfont.jfontdefX(false, 'yoko','\luatexluaescapestring{\noexpand#1}')}} % \protected\def\globaljfont#1{% % \afterassignment\ltj@@jfont % \directlua{luatexja.jfont.jfontdefX(true, 'yoko','\luatexluaescapestring{\noexpand#1}')}} % \def\ltj@@jfont{\directlua{luatexja.jfont.jfontdefY()}} % \end{verbatim} % \texttt{jfontdefX} 函数的作用是把 \tn{CS} 定义为其后的字体,\texttt{jfontdefY} % 的作用是更新 \texttt{JFM} 和记录相关字体信息。最后的工作是: % \begin{verbatim} % tex.sprint(cat_lp, global_flag, '\\protected\\expandafter\\def\\csname ', % (cstemp==' ') and '\\space' or cstemp, '\\endcsname{\\ltj@cur'.. % (jfm_dir == 'yoko' and 'j' or 't') .. 'fnt', fn, '\\relax}') % \end{verbatim} % \tn{CS} 的作用就是把 \tn{ltj@curjfnt} 设置为刚才定义的字体的 \texttt{font.id}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_extract_font: { \get@external@font \ctex_ltj_if_alternate_shape_exist:nT { \curr@fontshape } { \tl_set:Nx \external@font { \exp_after:wN \@@_patch_external_font:w \external@font } } \exp_after:wN \globaljfont \font@name \external@font \scan_stop: % \end{macrocode} % 这里 \tn{font@name} 不会直接改变当前字体,而 \tn{DeclareFontFamily} 和 % \tn{DeclareFontShape} 的最后一个参数通常要使用 \tn{font} 来引用当前字体。 % 为此,我们在分组内启用之前定义的字体,以便能得到正确的 \tn{font}。对字体参数的 % 赋值总是全局的,不会受到分组的影响。 % \begin{macrocode} \font@name \lua_now_x:n { font.current(tex.getattribute('ltj@curjfnt')) } \use:c { \f@encoding + \f@family } \use:c { \curr@fontshape } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_subst_font:} % \tn{do@subst@correction} 在设置通过 \texttt{sub} 或者 \texttt{ssub} 函数定义的 % 字体时会用到。如果没有设置 \opt{SlantedFont},\pkg{fontspec} 会设置 % \tn{itdefault} 作为 \tn{sldefault} 的替代字形,因而会用到这个函数。它的本来定义是: % \begin{verbatim} % \def\do@subst@correction{% % \xdef\subst@correction{% % \font@name % \global\expandafter\font % \csname \curr@fontshape/\f@size\endcsname % \noexpand\fontname\font % \relax}% % \aftergroup\subst@correction % } % \end{verbatim} % 我们在这里不需要定义新字体,而是设置对应字体的命令。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_subst_font: { \ctex_ltj_if_alternate_shape_exist:nF { \curr@fontshape } { \group_begin: \tl_set_eq:NN \CJK@family \f@family \cs_if_exist:cF { \l_@@_current_font_tl } { \cs_gset_protected_nopar:Npx \subst@correction { \cs_new_eq:NN \exp_not:c { \l_@@_current_font_tl } \font@name } \group_insert_after:N \group_insert_after:N \group_insert_after:N \subst@correction } \group_end: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int,TF]{\ctex_ltj_if_alternate_shape_exist:n} % 即 \pkg{LuaTeX-ja} 中的 \tn{ltj@@does@alt@set},判断是否存在替代字体。 % \begin{macrocode} \prg_new_conditional:Npnn \ctex_ltj_if_alternate_shape_exist:n #1 { T , F , TF } { \lua_now_x:n { luatexja.jfont.does_alt_set ('\lua_escape_x:n {#1}') } \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_patch_external_font:w} % 若对字体的定义完全相同,则它们有相同的 \texttt{font.id}。因此如果字形是由 % \textsf{NFSS} 的替换机制定义的,它们就有相同的 \texttt{font.id}。 % |print_aftl_address| 函数的定义是 % \begin{verbatim} % function print_aftl_address() % tex.sprint(cat_lp, ';ltjaltfont' .. tostring(aftl_base):sub(8)) % end % \end{verbatim} % 主要目的是,如果当前字形有替代字体,则往字形的定义中加入一些标志,确保 % \texttt{font.id} 唯一。 % \begin{macrocode} \cs_new_nopar:Npn \@@_patch_external_font:w #1 ~ at { #1 \lua_now_x:n { luatexja.jfont.print_aftl_address() } ~ at } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_select_alternate_font:} % 在 \tn{selectfont} 中更新替代字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_select_alternate_font: { \ctex_ltj_if_alternate_shape_exist:nT { \l_@@_current_shape_tl } { \lua_now_x:n { luatexja.jfont.output_alt_font_cmd ('y', '\lua_escape_x:n { \l_@@_current_shape_tl }') } \lua_now_x:n { luatexja.jfont.pickup_alt_font_a ('\f@size') } } } \tl_new:N \l_@@_current_shape_tl \tl_set:Nn \l_@@_current_shape_tl { \CJK@encoding / \CJK@family / \f@series / \f@shape } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ltj@pickup@altfont@auxy} % 被用在函数 |output_alt_font_cmd| 中,作用是定义替代字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ltj@pickup@altfont@auxy #1 { \cs_if_exist:cF { #1/\f@size } { \group_begin: \use:x { \exp_not:N \split@name #1 / \f@size } \@nil \@@_push_fontname:n { \use:c { \curr@fontshape / \f@size } } \ctex_ltj_pickup_font: \group_end: \@@_pop_fontname: } } % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \begin{macro}[int]{\ltj@pickup@altfont@copy} % 被用在函数 |pickup_alt_font_a| 中。\tn{ltj@@getjfontnumber} 的作用是将字体命令 % |#1| 对应的 \texttt{font.id} 保存到 \tn{ltj@tempcntc} 中。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ltj@pickup@altfont@copy #1#2 { \ltj@@getjfontnumber #1 \lua_now_x:n { luatexja.jfont.pickup_alt_font_b ( \int_use:N \ltj@tempcntc, '\lua_escape_x:n {#2}' ) } } % \end{macrocode} % \end{macro} % % \paragraph{数学字体族} % % \begin{macrocode} %<@@=ctex_ltj> % \end{macrocode} % % 以下内容来自 \file{lltjfont.sty},目的是让汉字可以在数学环境中直接使用。 % % \begin{macro}[int]{\ctex_ltj_if_jfont:nTF} % 参数 |#1| 是一个 \LaTeXe{} 编码名称或者字体命令。\LaTeXe{} 字体命令的一般形式是: % \begin{quote}\ttfamily\small % \textbackslash\meta{encoding}/\meta{family}/\meta{series}/\meta{shape} % \end{quote} % 通过截取名字中的 \meta{encoding} 来判断是否是 jfont。 % 最后会设置 \tn{ifin@} 为对应的 \tn{iftrue} 或者 \tn{iffalse}。 % \begin{macrocode} \cs_new:Npn \ctex_ltj_if_jfont:nTF #1 { \lua_now_x:n { luatexja.jfont.is_kenc( string.match('\lua_escape_x:n {#1}', '[^/]+') ) } \ifin@ \exp_after:wN \use_i:nn \else: \exp_after:wN \use_ii:nn \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_if_jfont_math:NTF} % |#1| 是一个形式为 |\M@|\meta{encoding} 的命令,它由 \tn{DeclareFontEncoding} 的 % 第三个参数来定义。 % \begin{macrocode} \cs_new:Npn \ctex_ltj_if_jfont_math:NTF #1 { \exp_after:wN \@@_if_jfont_math:w \token_to_str:N #1 \q_stop } \group_begin: \char_set_catcode_other:N M \cs_new:Npn \@@_if_jfont_math:w #1 M #2#3 \q_stop { \ctex_ltj_if_jfont:nTF {#3} } \group_end: % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \begin{macro}[int]{\getanddefine@fonts,\ctex_ltj_get_and_define_fonts:nN} % 在使用的场合,\tn{escapechar} 已经被设置成 $-1$,使用 \cs{token_to_str:N} 就 % 可以得到名字,不必使用 \cs{cs_to_str:N}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_get_and_define_fonts:nN #1#2 { \ctex_ltj_if_jfont:nTF { \token_to_str:N #2 } { \ctex_ltj_get_and_define_fonts_ja:nN } { \ctex_ltj_get_and_define_fonts_al:nN } {#1} #2 } \cs_new_eq:NN \ctex_ltj_get_and_define_fonts_al:nN \getanddefine@fonts \cs_set_eq:NN \getanddefine@fonts \ctex_ltj_get_and_define_fonts:nN \cs_new_protected_nopar:Npn \ctex_ltj_get_and_define_fonts_ja:nN #1#2 { \tl_gset:Nx \font@name { \use:c { \token_to_str:N #2 / \tf@size } } \ctex_ltj_pickup_font: \tl_set_eq:NN \textfont@name \font@name \tl_gset:Nx \font@name { \use:c { \token_to_str:N #2 / \sf@size } } \ctex_ltj_pickup_font: \tl_set_eq:NN \scriptfont@name \font@name \tl_gset:Nx \font@name { \use:c { \token_to_str:N #2 / \ssf@size } } \ctex_ltj_pickup_font: \tl_put_right:Nx \math@fonts { \ltj@setpar@global \ltj@@set@stackfont #1 , \textfont@name \c_colon_str { MJT } \ltj@@set@stackfont #1 , \scriptfont@name \c_colon_str { MJS } \ltj@@set@stackfont #1 , \font@name \c_colon_str { MJSS } } } % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=ctex_ltj> % \end{macrocode} % % \begin{macro}[int]{\use@mathgroup,\ctex_ltj_use_math_group:Nn} % 在使用 \pkg{unicode-math} 宏包时,\cs{ctex_ltj_math_group_hook:} 将被重定义。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_use_math_group:Nn #1#2 { \mode_if_math:T { \math@bgroup \cs_if_eq:cNF { M@ \f@encoding } #1 {#1} \ctex_ltj_math_group_hook: \ctex_ltj_if_jfont_math:NTF #1 { \jfam } { \mathgroup } #2 \scan_stop: \math@egroup } } \cs_new_eq:NN \ctex_ltj_math_group_hook: \prg_do_nothing: \cs_set_eq:NN \use@mathgroup \ctex_ltj_use_math_group:Nn % \end{macrocode} % \end{macro} % % \paragraph{字体族的定义与使用} % % \begin{macro}[int]{\ctex_mono_jfm:n,\l_@@_jfm_tl} % \pkg{LuaTeX-ja} 中与标点格式 \opt{plain} 对应的 \texttt{JFM} 是 \opt{mono}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_mono_jfm:n #1 { \str_if_eq:nnTF {#1} { plain } { \tl_set:Nn \l_@@_jfm_tl { mono } } { \tl_set:Nn \l_@@_jfm_tl {#1} } } \tl_new:N \l_@@_jfm_tl \cs_generate_variant:Nn \ctex_mono_jfm:n { o } \ctex_mono_jfm:o { \l__ctex_punct_tl } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJK@encoding,\@@_change_encoding:} % 在 \LaTeX 下,\pkg{LuaTeX-ja} 依赖字体编码来实现特殊设置。例如上述的 % \cs{ctex_ltj_if_jfont:nTF} 就是通过判断编码来实现的,它在设置数学字体时会用到。所以 % 不应该与西文共用 \texttt{EU2}。定义字体族 song 为 \tn{CJK@encoding} 的默认替换 % 字体。下划线 |_| 不在 \tn{nfss@catcodes} 里,可以放心使用。 % \begin{macrocode} \tl_const:Nn \CJK@encoding { LTJY3 } \DeclareFontEncoding { \CJK@encoding } { } { } \use:x { \exp_not:N \DeclareFontSubstitution { \CJK@encoding } { song } { \mddefault } { \updefault } } \lua_now_x:n { luatexja.jfont.add_kyenc_list('\CJK@encoding') } \cs_new_protected_nopar:Npn \@@_change_encoding: { \tl_set_eq:NN \g_fontspec_encoding_tl \CJK@encoding } \DeclareFontFamily { \CJK@encoding } { song } { } \DeclareFontShape { \CJK@encoding } { song } { \mddefault } { \updefault } { <-> psft:SimSun:cid=Adobe-GB1-5;jfm=\l_@@_jfm_tl } { } \DeclareFontShape { \CJK@encoding } { song } { \bfdefault } { \updefault } { <-> psft:SimHei:cid=Adobe-GB1-5;jfm=\l_@@_jfm_tl } { } \tl_const:Nn \c_@@_math_tl { CJKmath } \DeclareSymbolFont { \c_@@_math_tl } { \CJK@encoding } { song } { \mddefault } { \updefault } \SetSymbolFont { \c_@@_math_tl } { bold } { \CJK@encoding } { song } { \bfdefault } { \updefault } \int_const:Nn \c_@@_math_fam_int { \use:c { sym \c_@@_math_tl } } \jfam \c_@@_math_fam_int % \end{macrocode} % \end{macro} % % 这是 \pkg{luatexja-fontspec} 中新增的一些字体选项。 % \begin{macrocode} \newfontfeature { CID } { cid = #1 } \newfontfeature { JFM } { jfm = #1 } \newfontfeature { JFM-var } { jfmvar = #1 } % \end{macrocode} % % 在新版本的 \pkg{fontspec} 中,\cs{__fontspec_namewrap:n} 变成了私有函数。 % \begin{macrocode} \keys_define:nn { fontspec-preparse-external } { NoEmbed .code:n = { \cs_set_eq:NN \__fontspec_namewrap:n \@@_noembed_wrap:n } } \cs_new:Npn \@@_noembed_wrap:n #1 { psft: #1 } % \end{macrocode} % % \begin{macro}[int]{\ctex_ltj_set_family:nnn} % 将自定义的字体族名与 \pkg{fontspec} 实际设置的名字对应起来。 % \begin{macrocode} \cs_new_protected:Npn \ctex_ltj_set_family:nnn #1#2#3 { \group_begin: \clist_clear:N \l_@@_char_range_clist \seq_clear:N \l_@@_alternate_seq \tl_set:Nn \l_@@_base_CJKfamily_tl {#1} \keys_set_known:nnN { ctex_ltj / fontspec } {#2} \l_@@_tmp_tl \clist_set:No \l_@@_font_options_clist { \l_@@_tmp_tl } \ctex_ltj_set_alternate_family:nnF {#1} {#3} { \prop_gput:Nnn \g_@@_family_font_name_prop {#1} {#3} \prop_gput:Nno \g_@@_family_font_options_prop {#1} { \l_@@_font_options_clist } \@@_update_family_uid:N \l_@@_font_options_clist \@@_use_global_options:N \l_@@_font_options_clist \@@_gset_family_cs:nn {#1} {#3} } \group_end: } \cs_new_protected:Npn \ctex_ltj_set_family:xxx #1#2#3 { \use:x { \ctex_ltj_set_family:nnn {#1} {#2} {#3} } } \tl_new:N \l_@@_base_CJKfamily_tl \clist_new:N \l_@@_font_options_clist \cs_new_protected_nopar:Npn \@@_use_global_options:N #1 { \clist_concat:NNN #1 \g_@@_default_features_clist #1 \clist_put_left:Nx #1 { JFM = \l_@@_jfm_tl } } % \end{macrocode} % \end{macro} % % \begin{variable}[int] % {\g_@@_family_name_prop,\g_@@_family_font_name_prop,\g_@@_family_font_options_prop} % 分别保存 \pkg{fontspec} 设置的字体族名、字体名称和字体选项。 % \begin{macrocode} \prop_new:N \g_@@_family_name_prop \prop_new:N \g_@@_family_font_name_prop \prop_new:N \g_@@_family_font_options_prop % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\@@_check_family:n} % 删除重复的定义,清除替代字体的先前设置。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_check_family:n #1 { \prop_gpop:NnNT \g_@@_family_font_name_prop {#1} \l_@@_tmp_tl { \cs_undefine:c { \@@_family_csname:n {#1} } \cs_undefine:c { \@@_alternate_cs:n {#1} } \prop_gpop:NnNT \g_@@_family_name_prop {#1} \l_@@_base_family_tl { \use:c { \@@_alternate_cs:n { clear / #1 } } \cs_undefine:c { \@@_alternate_cs:n { clear / #1 } } \cs_undefine:c { \@@_alternate_cs:n { reset / #1 } } \prop_gremove:Nn \g_@@_reset_alternate_prop {#1} } \msg_warning:nnxx { ctex } { redefine-family } {#1} { \l_@@_tmp_tl } } } \tl_new:N \l_@@_tmp_tl \msg_new:nnn { ctex } { redefine-family } { Redefining~CJKfamily~`\@@_msg_family_map:n {#1}'~(#2). } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_gset_family_cs:nn} % 在设置字体时,实际上并不是马上就定义。而是只保存相关参数,在通过 \tn{CJKfamily} % 第一次使用时才定义。需要注意将编码改为 \tn{CJK@encoding}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_gset_family_cs:nn #1#2 { \cs_gset_protected_nopar:cpx { \@@_family_csname:n {#1} } { \group_begin: \@@_change_encoding: \exp_not:n { \cs_set_eq:NN \CJKfamily \use_none:n } \exp_not:n { \fontspec_set_family:Nnn \g_@@_fontspec_family_tl } { \exp_not:o { \l_@@_font_options_clist } } {#2} \prop_gput:Nno \exp_not:N \g_@@_family_name_prop {#1} { \exp_not:N \g_@@_fontspec_family_tl } \tl_gset_eq:NN \exp_not:N \g_@@_fontspec_family_tl \exp_not:N \g_@@_fontspec_family_tl \@@_set_alternate_family:n {#1} \group_end: } } \tl_new:N \l_@@_base_family_tl \tl_new:N \g_@@_fontspec_family_tl \cs_new_nopar:Npn \@@_family_csname:n #1 { ctex_ltj/family/#1 } \cs_new_protected_nopar:Npn \@@_set_alternate_family:n #1 { \tl_set:Nn \l_@@_base_CJKfamily_tl {#1} \tl_set_eq:NN \l_@@_base_family_tl \g_@@_fontspec_family_tl \cs_if_exist_use:c { \@@_alternate_cs:n { reset / #1 } } \cs_if_exist_use:c { \@@_alternate_cs:n {#1} } } \cs_new:Npn \@@_alternate_cs:n #1 { ctex_ltj/alternate_family/#1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKfamily} % 切换字体。 % \begin{macrocode} \NewDocumentCommand \CJKfamily { m } { \ctex_ltj_switch_family:x {#1} \tex_ignorespaces:D } \cs_new_protected_nopar:Npn \ctex_ltj_switch_family:n #1 { \ctex_ltj_family_if_exist:xNTF {#1} \CJK@family { \tl_set:Nn \l_ctex_ltj_family_tl {#1} \selectfont } { \@@_family_unknown_warning:n {#1} } } \tl_new:N \l_ctex_ltj_family_tl \cs_generate_variant:Nn \ctex_ltj_switch_family:n { x } % \end{macrocode} % \end{macro} % % \begin{macro}[int,TF]{\ctex_ltj_family_if_exist:n} % 判断 CJK 字体族 |#1| 是否存在,若存在则把实际族名保存到 |#2| 中。 % \begin{macrocode} \prg_new_protected_conditional:Npnn \ctex_ltj_family_if_exist:xN #1#2 { T , F , TF } { \prop_get:NxNTF \g_@@_family_name_prop {#1} #2 { \prg_return_true: } { \cs_if_exist_use:cTF { \@@_family_csname:n {#1} } { \tl_set_eq:NN #2 \g_@@_fontspec_family_tl \prg_return_true: } { \prg_return_false: } } } \cs_generate_variant:Nn \prop_get:NnNTF { Nx } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_family_unknown_warning:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_family_unknown_warning:n #1 { \prop_if_empty:NF \g_@@_family_font_name_prop { \seq_if_in:NnF \g_@@_unknown_family_seq {#1} { \seq_gput_right:Nn \g_@@_unknown_family_seq {#1} \msg_warning:nnn { ctex } { family-unknown } {#1} } } } \seq_new:N \g_@@_unknown_family_seq \msg_new:nnn { ctex } { family-unknown } { Unknown~CJK~family~`\@@_msg_family_map:n {#1}'~is~being~ignored.\\ Try~to~use~`\@@_msg_def_family_map:n {#1}'~to~define~it. } \cs_new_nopar:Npn \@@_msg_def_family_map:n #1 { \str_case_x:nnF {#1} { \CJKrmdefault { \token_to_str:N \setCJKmainfont } \CJKsfdefault { \token_to_str:N \setCJKsansfont } \CJKttdefault { \token_to_str:N \setCJKmonofont } } { \token_to_str:N \setCJKfamilyfont \{ #1 \} } [...]\{...\} } \cs_new_nopar:Npn \@@_msg_family_map:n #1 { \str_case_x:nnF {#1} { \CJKrmdefault { \token_to_str:N \CJKrmdefault } \CJKsfdefault { \token_to_str:N \CJKsfdefault } \CJKttdefault { \token_to_str:N \CJKttdefault } } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_fontspec:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_fontspec:nn #1#2 { \prop_get:NnNTF \g_@@_fontspec_prop { CJKfontspec/#1/#2/id } \l_ctex_ltj_family_tl { \ctex_ltj_switch_family:x { \l_ctex_ltj_family_tl } } { \int_gincr:N \g_@@_family_int \@@_fontspec:xnn { CJKfontspec ( \int_use:N \g_@@_family_int ) } {#1} {#2} } } \cs_new_protected_nopar:Npn \ctex_ltj_fontspec:xx #1#2 { \use:x { \ctex_ltj_fontspec:nn {#1} {#2} } } \cs_new_protected_nopar:Npn \@@_fontspec:nnn #1#2#3 { \bool_if:NT \l_@@_add_alternate_bool { \cs_if_free:cF { \@@_alternate_cs:n { reset / \l_ctex_ltj_family_tl } } { \cs_gset_eq:cc { \@@_alternate_cs:n { reset / #1 } } { \@@_alternate_cs:n { reset / \l_ctex_ltj_family_tl } } \cs_gset_eq:cc { \@@_alternate_cs:n { clear / #1 } } { \@@_alternate_cs:n { clear / \l_ctex_ltj_family_tl } } } \bool_set_false:N \l_@@_add_alternate_bool } \prop_gput:Nnn \g_@@_fontspec_prop { CJKfontspec/#2/#3/id } {#1} \ctex_ltj_set_family:nnn {#1} {#2} {#3} \ctex_ltj_switch_family:n {#1} } \cs_generate_variant:Nn \@@_fontspec:nnn { x } \prop_new:N \g_@@_fontspec_prop % \end{macrocode} % \end{macro} % % \begin{macro}[int] % {\ctex_ltj_add_font_features:n,\ctex_ltj_add_font_features:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_add_font_features:n #1 { \ctex_ltj_add_font_features:xn { \l_ctex_ltj_family_tl } {#1} } \cs_new_protected_nopar:Npn \ctex_ltj_add_font_features:nn #1#2 { \prop_get:NnNTF \g_@@_family_font_name_prop {#1} \l_@@_tmp_tl { \prop_get:NnN \g_@@_family_font_options_prop {#1} \l_@@_font_options_clist \clist_put_right:Nn \l_@@_font_options_clist {#2} \bool_set_true:N \l_@@_add_alternate_bool \ctex_ltj_fontspec:xx { \exp_not:o { \l_@@_font_options_clist } } { \exp_not:o { \l_@@_tmp_tl } } } { \msg_warning:nn { ctex } { addCJKfontfeature-ignored } } } \bool_new:N \l_@@_add_alternate_bool \cs_generate_variant:Nn \ctex_ltj_add_font_features:n { x } \cs_generate_variant:Nn \ctex_ltj_add_font_features:nn { x } \msg_new:nnn { ctex } { addCJKfontfeature-ignored } { \token_to_str:N \addCJKfontfeature (s)~ignored.\\ It~cannot~be~used~with~a~font~that~wasn't~selected~by~ctex. } % \end{macrocode} % \end{macro} % % \begin{macro}[int] % {\setCJKfamilyfont,\newCJKfontfamily,\CJKfontspec,\addCJKfontfeatures} % \begin{macrocode} \NewDocumentCommand \setCJKfamilyfont { m O { } m } { \ctex_ltj_set_family:xxx {#1} {#2} {#3} } \NewDocumentCommand \newCJKfontfamily { o m O { } m } { \tl_set:Nx \l_@@_tmp_tl { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } \cs_new_protected_nopar:Npx #2 { \ctex_ltj_switch_family:n { \l_@@_tmp_tl } } \ctex_ltj_set_family:xxx { \l_@@_tmp_tl } {#3} {#4} } \NewDocumentCommand \CJKfontspec { O { } m } { \ctex_ltj_fontspec:xx {#1} {#2} \tex_ignorespaces:D } \NewDocumentCommand \addCJKfontfeatures { m } { \ctex_ltj_add_font_features:x {#1} \tex_ignorespaces:D } \cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures % \end{macrocode} % \end{macro} % % \begin{macro}[int] % {\setCJKmainfont,\setCJKsansfont,\setCJKmonofont, % \setCJKmathfont,\defaultCJKfontfeatures} % \begin{macrocode} \NewDocumentCommand \setCJKmainfont { O { } m } { \ctex_ltj_set_family:xxx { \CJKrmdefault } {#1} {#2} \normalfont } \cs_new_eq:NN \setCJKromanfont \setCJKmainfont \NewDocumentCommand \setCJKsansfont { O { } m } { \ctex_ltj_set_family:xxx { \CJKsfdefault } {#1} {#2} \normalfont } \NewDocumentCommand \setCJKmonofont { O { } m } { \ctex_ltj_set_family:xxx { \CJKttdefault } {#1} {#2} \normalfont } \NewDocumentCommand \setCJKmathfont { O { } m } { \ctex_ltj_set_family:xxx { \c_@@_math_tl } {#1} {#2} } \NewDocumentCommand \defaultCJKfontfeatures { m } { \clist_gset:Nn \g_@@_default_features_clist {#1} } \clist_new:N \g_@@_default_features_clist \@onlypreamble \setCJKmainfont \@onlypreamble \setCJKsansfont \@onlypreamble \setCJKmonofont \@onlypreamble \setCJKmathfont \@onlypreamble \setCJKromanfont \@onlypreamble \defaultCJKfontfeatures % \end{macrocode} % \end{macro} % % \begin{macrocode} \tl_if_exist:NF \CJKfamilydefault { \tl_const:Nn \CJKfamilydefault { \CJKrmdefault } } \tl_if_exist:NF \CJKrmdefault { \tl_const:Nn \CJKrmdefault { rm } } \tl_if_exist:NF \CJKsfdefault { \tl_const:Nn \CJKsfdefault { sf } } \tl_if_exist:NF \CJKttdefault { \tl_const:Nn \CJKttdefault { tt } } \ctex_preto_cmd:NnnTF \rmfamily { \ExplSyntaxOff } { \CJKfamily { \CJKrmdefault } } { } { \ctex_patch_failure:N \rmfamily } \ctex_preto_cmd:NnnTF \sffamily { \ExplSyntaxOff } { \CJKfamily { \CJKsfdefault } } { } { \ctex_patch_failure:N \sffamily } \ctex_preto_cmd:NnnTF \ttfamily { \ExplSyntaxOff } { \CJKfamily { \CJKttdefault } } { } { \ctex_patch_failure:N \ttfamily } \ctex_preto_cmd:NnnTF \normalfont { \ExplSyntaxOff } { \CJKfamily { \CJKfamilydefault } } { \cs_set_eq:NN \reset@font \normalfont } { \ctex_patch_failure:N \normalfont } % \end{macrocode} % % \begin{macro}[int]{\ctex_ltj_ensure_default_family:} % 在导言区结束确认 \tn{CJKfamilydefault} 确实存在。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_ensure_default_family: { \prop_if_empty:NF \g_@@_family_font_name_prop { \ctex_ltj_family_if_exist:xNF { \CJKfamilydefault } \l_@@_tmpa_tl { \str_if_eq_x:nnTF { \CJKfamilydefault } { \CJKrmdefault } { \use:n } { \ctex_ltj_family_if_exist:xNTF { \CJKrmdefault } \l_@@_tmpa_tl { \tl_gset:Nn \CJKfamilydefault { \CJKrmdefault } \use_none:n } { \use:n } } { \prop_map_inline:Nn \g_@@_family_font_name_prop { \prop_map_break:n { \tl_gset_rescan:Nnn \CJKfamilydefault { } { ##1 } } } } } \normalfont \ctex_ltj_update_mathfont: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_update_mathfont:} % 更新数学字体为实际的字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_update_mathfont: { \ctex_ltj_family_if_exist:xNTF { \c_@@_math_tl } \l_@@_tmp_tl { \ctex_ltj_update_mathfont:n { \l_@@_tmp_tl } } { \ctex_ltj_family_if_exist:xNT { \CJKfamilydefault } \l_@@_tmp_tl { \ctex_ltj_update_mathfont:n { \l_@@_tmp_tl } } } } \cs_new_protected_nopar:Npn \ctex_ltj_update_mathfont:n #1 { \tl_const:Nx \c_@@_math_family_tl {#1} \DeclareSymbolFont { \c_@@_math_tl } { \CJK@encoding } { \c_@@_math_family_tl } { \mddefault } { \updefault } \cs_if_free:cTF { \CJK@encoding/\c_@@_math_family_tl/\bfdefault/\updefault } { \SetSymbolFont { \c_@@_math_tl } { bold } { \CJK@encoding } { \c_@@_math_family_tl } { \mddefault } { \updefault } } { \SetSymbolFont { \c_@@_math_tl } { bold } { \CJK@encoding } { \c_@@_math_family_tl } { \bfdefault } { \updefault } } } % \end{macrocode} % \end{macro} % % \paragraph{替代字体的设置} % % \begin{macro}{AlternateFont,CharRange} % 设置替代字体的选项。 % \begin{macrocode} \keys_define:nn { ctex_ltj / fontspec } { AlternateFont .code:n = \ctex_ltj_set_alternate_seq:n {#1} , AlternateFont .value_required:n = true , CharRange .clist_set:N = \l_@@_char_range_clist , CharRange .value_required:n = true } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_seq:n} % 我们使用 \verb=||= 作为替代字体序列的分隔标志。它可能被设置为活动字符,为此 % 需要先“消毒”,同时过滤掉空元素。 % \begin{macrocode} \group_begin: \char_set_catcode_other:N \| \cs_set:Npn \@@_tmp:w #1 { \cs_new_protected:Npn \ctex_ltj_set_alternate_seq:n ##1 { \clist_if_empty:NT \l_@@_char_range_clist { \tl_set:Nn \l_@@_tmp_tl { ##1 } \tl_replace_all:Nnn \l_@@_tmp_tl {#1} { || } \seq_set_split:NnV \l_@@_tmp_seq { || } \l_@@_tmp_tl \seq_set_filter:NNn \l_@@_tmp_seq \l_@@_tmp_seq { ! \tl_if_blank_p:n { ####1 } } \seq_concat:NNN \l_@@_alternate_seq \l_@@_alternate_seq \l_@@_tmp_seq } } } \char_set_catcode_active:N \| \@@_tmp:w { || } \group_end: \seq_new:N \l_@@_tmp_seq \seq_new:N \l_@@_alternate_seq % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_family:nnF} % 如果在字体的选项中设置了 \opt{CharRange},则只设置替代字体。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:nnF #1#2#3 { \clist_if_empty:NTF \l_@@_char_range_clist { \@@_check_family:n {#1} \seq_if_empty:NF \l_@@_alternate_seq { \ctex_ltj_save_alternate_seq:cn { \@@_alternate_cs:n {#1} } {#2} } #3 } { \ctex_ltj_set_alternate_family:nn {#1} {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int] % {\ctex_ltj_save_alternate_seq:Nn,\ctex_ltj_save_alternate_seq:Nnnwn} % 保存由 \opt{AlternateFont} 设置的替代字体序列。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_save_alternate_seq:Nn #1#2 { \seq_map_inline:Nn \l_@@_alternate_seq { \ctex_ltj_save_alternate_seq:Nnnwnw #1 {#2} ##1 { } \q_stop } } \cs_generate_variant:Nn \ctex_ltj_save_alternate_seq:Nn { c } \NewDocumentCommand \ctex_ltj_save_alternate_seq:Nnnwnw { m m m +O{ } m u{ \q_stop } } { \clist_set:Nn \l_@@_char_range_clist {#3} \clist_set:Nn \l_@@_alternate_options_clist {#4} \@@_use_global_options:N \l_@@_alternate_options_clist \tl_if_blank:nTF {#5} { \tl_set:Nn \l_@@_tmp_tl {#2} } { \tl_set:Nn \l_@@_tmp_tl {#5} \tl_replace_all:Nnn \l_@@_tmp_tl { * } {#2} } \use:x { \ctex_ltj_save_alternate_family:Nnnn \exp_not:N #1 { \exp_not:o { \l_@@_char_range_clist } } { \exp_not:o { \l_@@_alternate_options_clist } } { \exp_not:o { \l_@@_tmp_tl } } } } \clist_new:N \l_@@_alternate_options_clist % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_family:nn} % 设置选项 \opt{CharRange} 范围内的替代字体。如果已经定义了主字体,我们也马上 % 定义替代字体,否则只保存起来备用。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:nn #1#2 { \@@_update_family_uid:N \l_@@_font_options_clist \@@_use_global_options:N \l_@@_font_options_clist \ctex_ltj_set_alternate_family:coonn { \@@_alternate_cs:n {#1} } { \l_@@_char_range_clist } { \l_@@_font_options_clist } {#2} {#1} } \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:Nnnnn #1#2#3#4#5 { \prop_get:NnNT \g_@@_family_name_prop {#5} \l_@@_base_family_tl { \ctex_ltj_set_alternate_family:nnn {#2} {#3} {#4} } \ctex_ltj_save_alternate_family:Nnnn #1 {#2} {#3} {#4} } \cs_generate_variant:Nn \ctex_ltj_set_alternate_family:Nnnnn { coo } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_save_alternate_family:Nnnn} % 保存替代字体序列的定义,以备定义主字体时使用。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_save_alternate_family:Nnnn #1#2#3#4 { \cs_if_exist:NF #1 { \cs_set_eq:NN #1 \prg_do_nothing: } \cs_gset_protected_nopar:Npx #1 { \exp_not:o { #1 \ctex_ltj_set_alternate_family:nnn {#2} {#3} {#4} } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_family:nnn} % 实际定义替代字体族。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_family:nnn #1#2#3 { \group_begin: \@@_change_encoding: \cs_set_eq:NN \CJKfamily \use_none:n \ctex_ltj_swap_cs:NN \DeclareFontShape@ \ctex_ltj_declare_alternate_shape:nnnnnn \tl_set:Nn \l_@@_char_range_clist {#1} \fontspec_set_family:Nnn \l_@@_alternate_family_tl {#2} {#3} \group_end: } \tl_new:N \l_@@_alternate_family_tl % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_swap_cs:NN} % 交换两个控制序列的意义。 % \begin{macrocode} \cs_new_protected:Npn \ctex_ltj_swap_cs:NN #1#2 { \cs_set_eq:NN \@@_tmp:w #1 \cs_set_eq:NN #1 #2 \cs_set_eq:NN #2 \@@_tmp:w \cs_undefine:N \@@_tmp:w } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{LTJFONTUID,\@@_update_family_uid:N} % \pkg{fontspec} 在一个字体族的选项和字体名称相同的时候,就不定义新字体。为了 % 避免混淆替代字体的设置,我们新定义一个虚拟的选项 \opt{LTJFONTUID},确保 % \pkg{fontspec} 对 CJK 字体族总是定义新字体。 % \begin{macrocode} \keys_define:nn { fontspec } { LTJFONTUID .code:n = } \cs_new_protected_nopar:Npn \@@_update_family_uid:N #1 { \int_gincr:N \g_@@_family_int \clist_put_right:Nx #1 { LTJFONTUID = \int_use:N \g_@@_family_int } } \int_new:N \g_@@_family_int % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_declare_alternate_shape:nnnnnn} % 在定义替代字体的字形时,通过字符范围与主字体的对应字形关联起来。 % \tn{DeclareFontShape@} 一个有六个参数,我们只需要使用它的第三个参数 \meta{series} % 和第四个参数 \meta{shape}。 % \begin{macrocode} \cs_new_protected:Npn \ctex_ltj_declare_alternate_shape:nnnnnn #1#2#3#4#5#6 { \ctex_ltj_declare_alternate_shape:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} \ctex_ltj_set_alternate_shape:Nnnnnnn \l_@@_char_range_clist { \l_@@_base_family_tl } {#3} {#4} { \l_fontspec_family_tl } {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_shape:Nnnnnnn} % 与 \pkg{LuaTeX-ja} 的 \tn{DeclareAlternateKanjiFont} 的功能类似,区别是固定编码 % 为 \tn{CJK@encoding}。这个设置总是全局的。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:Nnnnnnn #1#2#3#4#5#6#7 { \clist_map_inline:Nn #1 { \prop_get:NnNTF \g_@@_char_range_prop { ##1 } \l_@@_char_range_tl { \ctex_ltj_set_alternate_shape:nnN { #2/#3/#4 } { #5/#6/#7 } \l_@@_char_range_tl } { \ctex_ltj_set_alternate_shape:nnn { #2/#3/#4 } { #5/#6/#7 } { ##1 } } } \@@_save_alternate_shape:cnn { \@@_alternate_cs:n { clear / \l_@@_base_CJKfamily_tl } } { luatexja.jfont.clear_alt_font_latex } { '\lua_escape_x:n { \CJK@encoding/#2/#3/#4 }' } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_shape:nnn} % 我们使用 \texttt{->} 而不是像 \pkg{LuaTeX-ja} 一样使用 \texttt{-} 作为区间的 % 分隔符。\pkg{LuaTeX-ja} 支持使用负数来引用由 \texttt{JFM} 设置的字符类。如果 % 使用 \texttt{-} 作为分隔符,那么负数单独使用时,就需要把它放在两层花括号之内 % (例如 |{{-1}}|),或者使用类似 |{-1}-{-1}| 的形式才不会解释错误。 % \begin{macrocode} \NewDocumentCommand \ctex_ltj_set_alternate_shape:nnn { m m > { \SplitArgument { \c_one } { -> } } m } { \ctex_ltj_set_alternate_shape:nnnn {#1} {#2} #3 } \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:nnnn #1#2#3#4 { \ctex_ltj_set_alternate_shape:n { \IfNoValueTF {#4} { \int_eval:n {#3} , \int_eval:n {#3} , } { \int_eval:n { \tl_if_blank:nTF {#3} { "80 } {#3} } , \int_eval:n { \tl_if_blank:nTF {#4} { "10FFFF } {#4} } , } '\lua_escape_x:n { \CJK@encoding/#2 }' , '\lua_escape_x:n { \CJK@encoding/#1 }' } } \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:n #1 { \lua_now_x:n { luatexja.jfont.set_alt_font_latex ( #1 ) } \@@_save_alternate_shape:cnn { \@@_alternate_cs:n { reset / \l_@@_base_CJKfamily_tl } } { luatexja.jfont.set_alt_font_latex } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_set_alternate_shape:nnN} % 若字符范围预先由 \texttt{declarecharrange} 声明,则可以直接使用。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_set_alternate_shape:nnN #1#2#3 { \tl_map_inline:Nn #3 { \ctex_ltj_set_alternate_shape:n { ##1 , '\lua_escape_x:n { \CJK@encoding/#2 }' , '\lua_escape_x:n { \CJK@encoding/#1 }' } } } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_save_alternate_shape:Nnn} % 将实际设置的替换字形保存起来用于清除或恢复。 % 暂时令 \cs{l_@@_base_family_tl} 为 \cs{scan_stop:} 是让它不被展开,使得替换 % 字体的设置可以在 \tn{addCJKfontfeature} 中直接使用。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_save_alternate_shape:Nnn #1#2#3 { \group_begin: \cs_if_exist:NF #1 { \cs_set_eq:NN #1 \prg_do_nothing: } \cs_set_eq:NN \l_@@_base_family_tl \scan_stop: \cs_set_eq:NN \lua_escape_x:n \scan_stop: \cs_gset_protected_nopar:Npx #1 { \exp_not:o {#1} \exp_not:N \lua_now_x:n { #2 ( #3 ) } } \group_end: } \cs_generate_variant:Nn \@@_save_alternate_shape:Nnn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{clearalternatefont,resetalternatefont} % 清除和重置操作总是全局的。 % \begin{macrocode} \keys_define:nn { ctex } { clearalternatefont .code:n = { \clist_map_function:xN {#1} \ctex_ltj_clear_alternate_font:n } , resetalternatefont .code:n = { \clist_map_function:xN {#1} \ctex_ltj_reset_alternate_font:n } , clearalternatefont .default:n = \l_ctex_ltj_family_tl , resetalternatefont .default:n = \l_ctex_ltj_family_tl } \cs_new_protected_nopar:Npn \ctex_ltj_clear_alternate_font:n #1 { \group_begin: \ctex_ltj_family_if_exist:xNTF {#1} \l_@@_base_family_tl { \cs_if_exist_use:cT { \@@_alternate_cs:n { clear / #1 } } { \prop_gput:Nno \g_@@_reset_alternate_prop {#1} { \l_@@_base_family_tl } \tl_set_eq:NN \CJK@family \l_@@_base_family_tl \selectfont } } { \@@_family_unknown_warning:n {#1} } \group_end: } \cs_new_protected_nopar:Npn \ctex_ltj_reset_alternate_font:n #1 { \group_begin: \prop_gpop:NnNT \g_@@_reset_alternate_prop {#1} \CJK@family { \tl_set_eq:NN \l_@@_base_family_tl \CJK@family \use:c { \@@_alternate_cs:n { reset / #1 } } \selectfont } \group_end: } \prop_new:N \g_@@_reset_alternate_prop \cs_generate_variant:Nn \clist_map_function:nN { x } % \end{macrocode} % \end{macro} % % \begin{macro}{declarecharrange} % 预先声明字符范围。 % \begin{macrocode} \keys_define:nn { ctex } { declarecharrange .code:n = \ctex_ltj_declare_char_range:x {#1} , declarecharrange .value_required:n = true } \cs_new_protected_nopar:Npn \ctex_ltj_declare_char_range:n #1 { \clist_map_inline:nn {#1} { \@@_declare_char_range:nn ##1 } } \cs_generate_variant:Nn \ctex_ltj_declare_char_range:n { x } \cs_new_protected_nopar:Npn \@@_declare_char_range:nn #1#2 { \use:x { \ctex_ltj_declare_char_range:nn { \tl_trim_spaces:n {#1} } } {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_declare_char_range:nn,\g_@@_char_range_prop} % |#1| 是名字,|#2| 是范围。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_declare_char_range:nn #1#2 { \tl_clear:N \l_@@_char_range_tl \clist_map_function:nN {#2} \ctex_ltj_save_char_range:n \prop_gput:Nno \g_@@_char_range_prop {#1} { \l_@@_char_range_tl } \ctex_ltj_def_char_range_key:n {#1} \tl_clear:N \l_@@_char_range_tl } \tl_new:N \l_@@_char_range_tl \prop_new:N \g_@@_char_range_prop % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_save_char_range:n} % 预先解释字符区间的意义。 % \begin{macrocode} \NewDocumentCommand \ctex_ltj_save_char_range:n { > { \SplitArgument { \c_one } { -> } } m } { \ctex_ltj_save_char_range:nn #1 } \cs_new_protected_nopar:Npn \ctex_ltj_save_char_range:nn #1#2 { \tl_put_right:Nx \l_@@_char_range_tl { { \IfNoValueTF {#2} { \int_eval:n {#1} , \int_eval:n {#1} } { \int_eval:n { \tl_if_blank:nTF {#1} { "80 } {#1} } , \int_eval:n { \tl_if_blank:nTF {#2} { "10FFFF } {#2} } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_def_char_range_key:n} % 在字体设置选项中定义字符范围键。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_def_char_range_key:n #1 { \keys_if_exist:nnF { ctex_ltj / fontspec } {#1} { \keys_define:nn { ctex_ltj / fontspec } { #1 .code:n = \ctex_ltj_char_range_key:nn {#1} { ##1 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_ltj_char_range_key:nn} % 如果字符范围键没有值,则只设置的这个字符范围内的替代字体。 % \begin{macrocode} \cs_new_protected:Npn \ctex_ltj_char_range_key:nn #1#2 { \tl_if_blank:nTF {#2} { \tl_set:Nn \l_@@_char_range_clist {#1} } { \clist_if_empty:NT \l_@@_char_range_clist { \tl_set:Nn \l_@@_tmp_tl { {#1} } \@@_char_range_parse_feature:w #2 \q_stop } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_char_range_parse_feature:w} % 可以使用加方括号的方式,通过文件名来调用字体。这容易与字体选项混淆。例如,需要 % 将 |[simsun.ttc]| 设置为 \opt{range} 的主字体,就需要使用 % |range={{[simsun.ttc]}}| 或者 |[]{[simsun.ttc]}|。下面的目的是,支持直接使用 % |[simsun.ttc]| 和 |[...][simsun.ttc]|。 % \begin{macrocode} \NewDocumentCommand \@@_char_range_parse_feature:w { +o o u { \q_stop } } { \exp_args:NNf \tl_put_right:Nn \l_@@_tmp_tl { \IfNoValueTF {#1} { {#3} } { \IfNoValueTF {#2} { \tl_if_blank:nTF {#3} { { [#1] } } { [ {#1} ] {#3} } } { [ {#1} ] { [#2] } } } } \seq_put_right:No \l_@@_alternate_seq { \l_@@_tmp_tl } } % \end{macrocode} % \end{macro} % % \paragraph{其它设置} % % \begin{macro}[int]{\ctex_ltj_update_xkanjiskip:,\l_@@_xkanjiskip_skip} % \tn{ltjsetparameter} 对 \opt{xkanjiskip} 是即时赋值。\tn{zw} 与字体相关,因此 % 需要每次 \tn{selectfont} 的时候更新一次 \opt{xkanjiskip}。如果用户设置过 % \opt{xkanjiskip},就不更新。注意,同 \TeX{} 的 \tn{baselineskip} 一样,如果在 % 一个段落内多次设置了 \opt{kanjiskip} 或 \opt{xkanjiskip},最后的设置会影响 % 全段。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_ltj_update_xkanjiskip: { \skip_if_eq:nnT { \ltjgetparameter { xkanjiskip } } { \l_@@_xkanjiskip_skip } { \skip_set:Nn \l_@@_xkanjiskip_skip { .25 \zw plus 1pt minus 1pt } \ltjsetxkanjiskip \l_@@_xkanjiskip_skip } } % \end{macrocode} % 注意,此时还没有实际设置字体,所以 \tn{zw} 是 \opt{0pt}。 % \begin{macrocode} \skip_new:N \l_@@_xkanjiskip_skip \skip_set:Nn \l_@@_xkanjiskip_skip { .25 \zw plus 1pt minus 1pt } % \end{macrocode} % \end{macro} % % 在抄录环境中禁用 \opt{autospacing} 和 \opt{autoxspacing}。然而,\pkg{LuaTeX-ja} % 还是会使 JAchar 自动折行。没有看到有简单的禁用折行的办法,可能需要设置所有的 % JAchar 的 \opt{prebreakpenalty} 或 \opt{postbreakpenalty} 为 \texttt{10000}: % \begin{verbatim} % \directlua % { % luatexja.isglobal = tex.globaldefs > 0 and "global" or "" % for i = 0x80, 0x10FFFF do % if luatexja.charrange.jcr_table_main[i] > 0 and % luatexja.charrange.jcr_table_main[i] < 218 and % luatexja.charrange.is_japanese_char_curlist(i) then % luatexja.stack.set_stack_table(luatexja.stack_table_index.PRE + i, 10000) % end % end % } % \end{verbatim} % \begin{macrocode} \AtBeginDocument { \ctex_appto_cmd:NnnTF \verbatim@font { \char_set_catcode_letter:n { 64 } } { \CTEX@verbatim@font@hook } { } { \ctex_patch_failure:N \verbatim@font } } \cs_new_protected_nopar:Npn \CTEX@verbatim@font@hook { \ltjsetparameter { autospacing = false , autoxspacing = false } } % \end{macrocode} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \begin{macro}[int]{\@@italiccorr} % \LaTeX{} 的倾斜校正也要重新定义。 % \begin{macrocode} \cs_set_eq:NN \@@italiccorr \/ % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=ctex> % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{调整 \tn{CJKfamilydefault}} % % \begin{macro}[int]{\ctex_update_default_family:} % 在导言区结束,如果 \tn{CJKfamilydefault} 没有被更改,则在此时根据西文字体的情况 % 更新 \tn{CJKfamilydefault}。\pkg{xeCJK} 已经有这个功能,不需要再调整。 % \begin{macrocode} %<*pdftex|luatex> \cs_new_protected_nopar:Npn \ctex_update_default_family: { \tl_if_eq:NNT \CJKfamilydefault \l_@@_family_default_init_tl { \group_begin: \cs_set_eq:NN \@@_family_default_wrap:n \exp_not:n \tl_gset:Nx \CJKfamilydefault { \str_case:onF { \familydefault } { { \rmdefault } { \exp_not:N \CJKrmdefault } { \sfdefault } { \exp_not:N \CJKsfdefault } { \ttdefault } { \exp_not:N \CJKttdefault } } { \CJKfamilydefault } } \group_end: } % \end{macrocode} % 使用 \LuaLaTeX{} 时,自动调整得到的 \tn{CJKfamilydefault} 可能没有定义,需要确认 % 它的存在性。使用 \pkg{CJK} 宏包时,\texttt{C19rm} 等总是有定义的,不需要确认。 % \begin{macrocode} %<*luatex> \ctex_ltj_ensure_default_family: % } \ctex_at_end_preamble:n { \ctex_update_default_family: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\l_@@_family_default_init_tl} % 往 \tn{CJKfamilydefault} 中加入标志,用于判断它是否被更改。 % \begin{macrocode} \tl_new:N \l_@@_family_default_init_tl \cs_new_eq:NN \@@_family_default_wrap:n \use:n \tl_set:Nx \l_@@_family_default_init_tl { \exp_not:N \@@_family_default_wrap:n { \exp_not:o { \CJKfamilydefault } } } \tl_gset_eq:NN \CJKfamilydefault \l_@@_family_default_init_tl % % \end{macrocode} % \end{macro} % % \subsubsection{操作系统的判断} % % \changes{v2.0}{2014/04/16}{自动检测操作系统,载入对应的字体配置。} % % \begin{macro}[int]{\ctex_detected_platform:} % 在 \LuaTeX{} 下直接用调用 |os.name| 来判断。 % \begin{macrocode} %<*luatex> \cs_new_protected_nopar:Npn \ctex_detected_platform: { \tl_gset:Nx \g_@@_fontset_tl { \lua_now_x:n { if ~ os.name == 'windows' then ~ tex.sprint ( 'windows' ) elseif ~ os.name == 'macosx' then ~ tex.sprint ( 'mac' ) else ~ tex.sprint ( 'fandol' ) end } } } % % \end{macrocode} % \pdfTeX{} 和 \XeTeX{} 下则依据 \file{/dev/null} 和 \file{nul:} 的存在性以及 % 文件系统的大小写敏感性来判断。Mac~OS~X 的大小写敏感性在安装时是可选的。为了 % 保险起见,这里的判断很繁琐,最多要进行 4 次文件操作! % \begin{macrocode} %<*xetex|pdftex> \cs_new_protected_nopar:Npn \ctex_detected_platform: { \file_if_exist:nTF { /dev/null } { \file_if_exist:nTF { nul: } { \file_if_exist:nTF { \c_@@_upper_case_file_str } { \ctex_if_macosx:TF { mac } { windows } } { \ctex_if_macosx:TF { mac } { fandol } } } { \ctex_if_macosx:TF { mac } { fandol } } } { \tl_gset:Nn \g_@@_fontset_tl { windows } } } \str_const:Nx \c_@@_upper_case_file_str { \exp_args:No \str_upper_case:n { \g_file_current_name_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_if_macosx:TF} % \changes{v2.1}{2015/06/17}{改用 \file{/Library/Fonts/Songti.ttc} 为特征文件。} % 以 \file{/Library/Fonts/Songti.ttc} 为特征文件判断 Mac~OS~X。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_if_macosx:TF #1#2 { \file_if_exist:nTF { \c_@@_macosx_file_str } { \tl_gset:Nn \g_@@_fontset_tl {#1} } { \tl_gset:Nn \g_@@_fontset_tl {#2} } } \str_const:Nn \c_@@_macosx_file_str { /Library/Fonts/Songti.ttc } % % \end{macrocode} % \end{macro} % % \subsubsection{\pkg{hyperref} 兼容性处理} % % \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_nopar:Npn \ctex_hypersetup:n #1 { \hypersetup {#1} } } { \cs_new_protected_nopar:Npn \ctex_hypersetup:n #1 { \PassOptionsToPackage {#1} { hyperref } } } % % \end{macrocode} % \end{macro} % % 在 \pdfTeX{} 下使用 \texttt{GBK} 编码,\dvipdfmx{} 驱动可以直接用它的 % \tn{special} 命令,其它模式用 \pkg{xCJK2uni} 宏包处理。使用 \texttt{UTF-8} 编 % 码时,\pkg{CJKutf8} 已经处理了书签问题,但仍需要设置 \opt{pdfencoding} 为 % \opt{unicode},目的是在书签的开头写入 BOM (|\376\377|),提示这是 % \texttt{UTF-16BE} 字节流。 % \begin{macrocode} %<*pdftex> \ctex_hypersetup:n { driverfallback = dvipdfmx } \str_if_eq:onTF { \l_@@_encoding_tl } { GBK } { \ctex_hypersetup:n { CJKbookmarks = true } \sys_if_output_pdf:TF { \ctex_at_end_package:nn { hyperref } { \RequirePackage { xCJK2uni } } } { \ctex_at_end_package:nn { hyperref } { \str_if_eq:onTF { \Hy@driver } { hdvipdfm } { \AtBeginShipoutFirst { \special { pdf:tounicode~GBK-EUC-UCS2 } } } { \RequirePackage { xCJK2uni } } } } } { \ctex_hypersetup:n { pdfencoding = unicode } } % % \end{macrocode} % 在 \XeTeX{} 下,\pkg{hyperref} 在处理带有非 ASCII 字符和 |\%| 的书签时有问题^^A % \footnote{\url{https://github.com/CTeX-org/ctex-kit/issues/39}}。 % 事实上,\pkg{hyperref} 在驱动文件 \file{hxetex.def} 中设置了 % \tn{Hy@unicodetrue},从而书签总是会被 \tn{HyPsd@ConvertToUnicode} 转化成 % \texttt{UTF-16BE} 编码的形式(抄录自 \tn{pdfstringdef}的定义): % \begin{verbatim} % \ifHy@unicode % \HyPsd@ConvertToUnicode#1% % \ifx\HyPsd@pdfencoding\HyPsd@pdfencoding@auto % \ltx@IfUndefined{StringEncodingConvertTest}{% % }{% % \EdefUnescapeString\HyPsd@temp#1% % \ifxetex % \let\HyPsd@UnescapedString\HyPsd@temp % \StringEncodingConvertTest\HyPsd@temp\HyPsd@temp % {utf16be}{ascii-print}{% % \EdefEscapeString\HyPsd@temp\HyPsd@temp % \global\let#1\HyPsd@temp % \HyPsd@EscapeTeX#1% % \Hy@unicodefalse % }{% % \HyPsd@ToBigChars#1% % }% % \end{verbatim} % 通过宏包选项 \opt{pdfencoding=unicode} 设置 \tn{HyPsd@pdfencoding} 为 % \opt{unicode},可以避免随后再将书签从 \texttt{UTF-16BE} 字节流转化回正常 % 字符(其中使用的 \tn{HyPsd@ToBigChars} 没有考虑书签中含有 |\%| 的情况)。 % Heiko Oberdiek 在 \file{README} 中说明了将书签转化回正常字符的意图:避免 % XDVIPDFMX 的警告^^A % \footnote{\url{http://project.ktug.org/dvipdfmx/mailman/dvipdfmx/2009-December/000153.html}}: % \begin{verbatim} % ** WARNING ** Failed to convert input string to UTF16... % \end{verbatim} % \XeTeX{} 的维护者 Khaled Hosny 已经注意到了这个问题^^A % \footnote{\url{http://tug.org/pipermail/tex-live/2013-December/034613.html}}。 % 需要注意的是,\file{hxetex.def} 重载了宏包选项 \opt{unicode},目的是不能设置 % 它为 \opt{false},但也导致它不会改变 \tn{HyPsd@pdfencoding}。如果 % \pkg{hyperref} 先于 \CTeX{} 被载入,那么 \opt{unicode} 选项是没有意义的。 % 因此要通过意义相同但在 \XeTeX{} 下更保险的 \opt{pdfencoding} 选项来设置。 % 为了与 \XeTeX 下的行为一致(使用 \tn{HyPsd@LoadUnicode} 载入 \file{puenc.def}), % 在 \LuaTeX{} 下也启用这个选项。 % \begin{macrocode} %<*xetex|luatex> \ctex_hypersetup:n { pdfencoding = unicode } % % \end{macrocode} % % \begin{macrocode} %<*pdftex|xetex|luatex> % \end{macrocode} % % \subsubsection{\pkg{CJKfntef}、\pkg{xeCJKfntef} 相关设置} % % \CTeX{} 宏集对 \pdfTeX{} 与 \XeTeX{} 引擎,分别载入 \pkg{CJKfntef} 或 % \pkg{xeCJKfntef} 宏包,并关闭宏包默认的彩色等多余格式。 % % \changes{v2.0}{2015/03/25}{默认关闭 \pkg{CJKfntef} 或 \pkg{xeCJKfntef} 的彩 % 色设置。} % \changes{v2.0}{2015/03/25}{\tn{CTEXunderdot}, \tn{CTEXunderline}, % \tn{CTEXunderdblline}, \tn{CTEXunderwave}, \tn{CTEXsout}, \tn{CTEXxout} 是过 % 时命令;\env{CTEXfilltwosides} 是过时环境。} % % 载入 \pkg{CJKfntef} 或 \pkg{xeCJKfntef} 并做适当格式设置。有关 |\CTEX| 开头 % 的宏定义是过时命令,仅做兼容性保留。 % % \begin{macrocode} %<*pdftex> \RequirePackage { CJKfntef } \normalem \cs_new_protected_nopar:Npn \@@_clear_fntef_color:n #1 { \tl_clear:c { CJK#1color } } % %<*xetex> \RequirePackage { xeCJKfntef } \@ifpackagelater { xeCJKfntef } { 2014/11/04 } { \cs_new_protected_nopar:Npn \@@_clear_fntef_color:n #1 { \xeCJKsetup { #1 / format = { } } } } { \cs_new_protected_nopar:Npn \@@_clear_fntef_color:n #1 { \tl_clear:c { CJK#1color } } } % %<*luatex> \msg_new:nnn { ctex } { fntef-not-available } { Functions~ of~ `CJKfntef'~ is~ not~ available~ in~ LuaLaTeX. } \msg_warning:nn { ctex } { fntef-not-available } % \clist_map_inline:nn { underdot , underline , underdblline , underwave , sout , xout } %<*pdftex|xetex> { \@@_clear_fntef_color:n {#1} \cs_new_protected_nopar:cpx { CTEX#1 } { \msg_warning:nnnn { ctex } { deprecated-command } { \exp_not:c { CTEX#1 } } { You~ can~ use~ the~ command~ with~ prefix~ \exp_not:N \CJK~ instead. } \exp_not:c { CJK#1 } } } \cs_new_protected_nopar:Npn { \CTEXfilltwosides } { \msg_warning:nnnn { ctex } { deprecated-environment } { CTEXfilltwosides } { You~ can~ use~ `CJKfilltwosides'~ environment~ instead. } \CJKfilltwosides } \cs_new_protected_nopar:Npn { \endCTEXfilltwosides } { \endCJKfilltwosides } % %<*luatex> { \cs_new_eq:cN { CTEX#1 } \use:n } \cs_new_eq:NN \CTEXfilltwosides \use_none:n \cs_new_eq:NN \endCTEXfilltwosides \prg_do_nothing: % %<*pdftex> \clist_map_inline:nn { underdotbasesep , underdotsep , underlinebasesep , underlinesep , underdbllinesep , underdbllinebasesep , underwavebasesep , underwavesep , southeight , underdotcolor , underwavecolor , underlinecolor , underdbllinecolor , soutcolor , xoutcolor } { \cs_new_eq:cc { CTEX#1 } { CJK#1 } \cs_set_nopar:cpx { CJK#1 } { \exp_not:c { CTEX#1 } } } % % \end{macrocode} % % \subsubsection{\tn{ccwd} 的更新} % % \begin{macro}[int]{\ctex_update_ccwd:,\ccwd} % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_update_ccwd: %<*pdftex|xetex> { \hbox_set:Nn \l_@@_tmp_box { \CJKglue } \dim_set:Nn \ccwd { \box_wd:N \l_@@_tmp_box + \f@size \p@ } } % %<*luatex> { \skip_set:Nn \ccwd { \ltjgetparameter { kanjiskip } + \zw } } % \dim_new:N \ccwd % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_ccglue:} % 更新字间距。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_update_ccglue: %<*pdftex> { \cs_set_protected_nopar:Npn \CJKglue { \skip_horizontal:N \l_@@_ccglue_skip } } % %<*xetex> { \xeCJKsetup { CJKglue = { \skip_horizontal:N \l_@@_ccglue_skip } } } % %<*luatex> { \ltjsetkanjiskip \l_@@_ccglue_skip } % \skip_new:N \l_@@_ccglue_skip % \end{macrocode} % \end{macro} % % \begin{macro}[int,pTF]{\ctex_if_ccglue_touched:} % 检查用户是否修改过汉字间距。 % \begin{macrocode} \prg_new_conditional:Npnn \ctex_if_ccglue_touched: { TF } { %<*pdftex|xetex> \if_meaning:w \CJKglue \@@_ccglue: \prg_return_false: \else: \prg_return_true: \fi: % %<*luatex> \skip_if_eq:nnTF { \l_@@_ccglue_skip } { \ltjgetparameter { kanjiskip } } { \prg_return_false: } { \prg_return_true: } % } % \end{macrocode} % 注意下面的标记不能用 \verb"%",它会导致旧版本的 \pkg{l3docstrip} % 不能替换 \texttt{@@}。 % \begin{macrocode} %<*pdftex|xetex> \ctex_at_end:n { \cs_new_eq:NN \@@_ccglue: \CJKglue } % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_em_unit:} % 将当前汉字的宽度保存到 \tn{ccwd} 中备用。不采用 \texttt{1 em},因为这时的 % \texttt{1 em} 实际上来自西文字体的信息,未必等于汉字的宽度,这似乎在传统的 % \file{.tfm} 字体上表现更明显。在 \pdfTeX{} 和 \XeTeX{} 下,直接使用 |\f@size\p@| % 作为汉字的宽度,这应该对大多数汉字字体都成立,但不适用于诸如“方正兰亭黑长”之类 % 的特殊字体。在 \XeTeX{} 可以用 \tn{fontcharwd} 来改进。而在 \pdfTeX{} 下,若使用 % \pkg{zhmetrics} 技术,所有的汉字共享同一个 \file{.tfm},\tn{fontcharwd} 也就没有 % 意义。在 \LuaTeX{} 下,\pkg{LuaTeX-ja} 总是按照 JFM 中的设置输出汉字的宽度,可以 % 直接用 \tn{zw} 作为汉字宽度。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_update_em_unit: % { \dim_set:Nn \ccwd { \f@size \p@ } } % { \dim_set:Nn \ccwd { \zw } } % \end{macrocode} % \end{macro} % % \subsubsection{其它} % % \begin{macro}[int]{\ctex_add_to_selectfont:n,\CTEX@selectfont@hook} % \tn{EverySelectfont} 直到文档开始时才有效。为了 \tn{ccwd} 和 \pkg{LuaTeX-ja} 的 % 字体设置在导言区也可用,我们还需要在这里手工修改 \tn{selectfont}。\pkg{everysel} % 宏包会用 \tn{CheckCommand} 来检查 \tn{selectfont} 是否为标准定义。我们修改了 % \tn{selectfont},所以会给出一个警告。为了消除这个警告,在它检查之前,还原本来 % 定义。 % \begin{macrocode} \cs_new_protected:Npn \ctex_add_to_selectfont:n #1 { \cs_set_protected_nopar:Npx \CTEX@selectfont@hook { \exp_not:o { \CTEX@selectfont@hook #1 } } } \cs_new_eq:NN \CTEX@selectfont@hook \prg_do_nothing: \cs_new_eq:Nc \@@_save_selectfont: { selectfont ~ } \ctex_preto_cmd:NnnTF \selectfont { \ExplSyntaxOff } { \CTEX@selectfont@hook } { \tl_put_left:Nn \@EverySelectfont@Init { \cs_set_eq:cN { selectfont ~ } \@@_save_selectfont: } } { \ctex_patch_failure:N \selectfont } % \end{macrocode} % \end{macro} % % \tn{CJK@plane} 有定义,说明处于 \pkg{CJK} 宏包的 \tn{CJKsymbol} 之内,不必使用钩子。 % \begin{macrocode} %<*pdftex> \EverySelectfont { \cs_if_exist:NF \CJK@plane { \CTEX@selectfont@hook } } % %<*xetex|luatex> \EverySelectfont { \CTEX@selectfont@hook } % % \end{macrocode} % % Attribute 寄存器 \tn{ltj@curjfnt} 的初始值是 $-1$,必须把它设置为一个有效的 % \texttt{font.id},否则编译时会直接退出。 % \begin{macrocode} %<*luatex> \ctex_add_to_selectfont:n { \ctex_ltj_select_font: \ctex_ltj_select_alternate_font: \ctex_ltj_update_xkanjiskip: } \tl_set:Nn \CJK@family { song } \selectfont \tl_clear:N \CJK@family % % \end{macrocode} % % \begin{macro}{space} % 在导言区或正文中设置忽略空格方式。 % \pdfTeX{} 和 \XeTeX{} 下初始设置为 \opt{auto},\LuaTeX{} 下是无效选项。 % \begin{macrocode} \keys_define:nn { ctex } { %<*pdftex|xetex> space .choice: , space / true .code:n = % { \ctex_ignorespaces_case:N \prg_do_nothing: } , % { \xeCJKsetup { CJKspace = true } } , space / auto .code:n = % { \ctex_ignorespaces_case:N \ctex_auto_ignorespaces: } , % { \xeCJKsetup { CJKspace = false } } , space / false .code:n = % { \ctex_ignorespaces_case:N \tex_ignorespaces:D } , % { \xeCJKsetup { CJKspace = false } } , space .default:n = { true } , space .initial:n = { auto } % %<*luatex> space .code:n = { \msg_warning:nn { ctex } { invalid-option } } % } % \end{macrocode} % \end{macro} % % \begin{macro}{punct} % 在导言区或正文中设置标点符号输出格式。\pkg{LuaTeX-ja} 设置的是字体的默认 \texttt{JFM}, % 只会影响到之后设置的字体。 % \begin{macrocode} \keys_define:nn { ctex } { punct .code:n = { \tl_set:Nx \l_@@_punct_tl { #1 } % \punctstyle { \l_@@_punct_tl } % \xeCJKsetup { PunctStyle = \l_@@_punct_tl } % \ctex_mono_jfm:o { \l_@@_punct_tl } } , punct .default:n = { quanjiao } , } % \end{macrocode} % \end{macro} % % \XeLaTeX{} 和 \LuaLaTeX{} 总是使用 \texttt{UTF8} 编码。 % \begin{macrocode} %<*xetex|luatex> \tl_set:Nn \l_@@_encoding_tl { UTF8 } % % \end{macrocode} % % \begin{macrocode} % %<*class|ctex> % \end{macrocode} % % \subsubsection{载入引擎定义文件} % % 最后载入各个编译引擎的定义文件。 % \begin{macrocode} \ctex_file_input:n { \c_@@_engine_file_str } % \end{macrocode} % % \subsection{字距与缩进} % % \begin{macro}{autoindent} % \opt{autoindent} 也是可以用在正文中的选项,意义与宏包选项 |option/autoindent| 相同。 % \begin{macrocode} \keys_define:nn { ctex } { autoindent .choice: , autoindent .default:n = { true } , autoindent / true .code:n = { \tl_set:Nn \l_@@_autoindent_tl { 2 \ccwd } \ctex_select_size: } , autoindent / false .code:n = { \tl_clear:N \l_@@_autoindent_tl } , autoindent / unknown .code:n = { \ctex_set_default_ccwd:Nn \l_@@_autoindent_tl {#1} \ctex_select_size: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\CTEXsetfont} % 无论字体大小是否变化都更新相关信息。 % \begin{macrocode} \NewDocumentCommand \CTEXsetfont { } { \ctex_select_size: } \cs_new_protected_nopar:Npn \ctex_select_size: { \cs_if_free:NTF \size@update { \ctex_update_size: } { \selectfont } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_size:} % 在字号变化时更新 \tn{ccwd}、\tn{parindent} 和汉字间距。字距为零则恢复正常设置。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_update_size: { \tl_if_eq:NNTF \l_@@_ziju_tl \c_@@_zero_tl { \ctex_update_stretch: \ctex_update_parindent: } { \ctex_update_ziju: } } \tl_const:Nx \c_@@_zero_tl { \fp_use:N \c_zero_fp } \tl_new:N \l_@@_ziju_tl \tl_set_eq:NN \l_@@_ziju_tl \c_@@_zero_tl % \end{macrocode} % 在 \tn{selectfont} 中,若 \tn{size@update} 为 \tn{relax},说明字体大小没有变化, % 我们也就不用更新相关参数。 % \begin{macrocode} \ctex_add_to_selectfont:n { \cs_if_free:NF \size@update { \ctex_update_size: } } % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/26}{新增 \opt{linestretch} 选项。} % % \begin{macro}{linestretch} % 若行宽不是汉字宽度的整数倍,自然要求伸展它们之间的差。这里设置的是在此基础上的 % 额外伸展量。初始化为一个汉字的宽度。若设置为 \tn{maxdimen},则禁用此功能。 % 参数的默认单位是汉字的宽度 \tn{ccwd}。 % \begin{macrocode} \keys_define:nn { ctex } { linestretch .code:n = { \ctex_set_default_ccwd:Nn \l_@@_line_stretch_tl {#1} \ctex_select_size: } , linestretch .value_required: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_nopar:Npn \ctex_update_stretch: { \ctex_update_em_unit: \dim_set:Nn \l_@@_tmp_dim { \l_@@_line_stretch_tl } \dim_compare:nNnTF \l_@@_tmp_dim = \c_max_dim { \ctex_if_ccglue_touched:TF { \ctex_update_ccwd: } { \dim_set:Nn \l_@@_tmp_dim { \baselinestretch \etex_glueexpr:D \f@baselineskip \scan_stop: } \skip_set:Nn \l_@@_ccglue_skip { \c_zero_dim plus .08 \l_@@_tmp_dim } \ctex_update_ccglue: } } { \int_set:Nn \l_@@_tmp_int { \etex_dimexpr:D \linewidth - \ccwd - \l_@@_tmp_dim \scan_stop: } \tex_divide:D \l_@@_tmp_int \ccwd \int_compare:nNnTF \l_@@_tmp_int > \c_zero { \skip_set:Nn \l_@@_ccglue_skip { \c_zero_dim plus \dim_eval:n { ( \linewidth - \ccwd - \l_@@_tmp_int \ccwd ) / \l_@@_tmp_int } } } { \skip_zero:N \l_@@_ccglue_skip } \ctex_update_ccglue: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_parindent:} % 更新段落首行缩进。此函数在字号变化时调用。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_update_parindent: { \tl_if_empty:NF \l_@@_autoindent_tl { \dim_compare:nNnF \parindent = \c_zero_dim { \dim_set:Nn \parindent { \l_@@_autoindent_tl } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\ziju} % 若参数为 $0$,则恢复正常间距。 % \begin{macrocode} \NewDocumentCommand \ziju { m } { \exp_args:Nx \ctex_ziju:n {#1} \tex_ignorespaces:D } \cs_new_protected_nopar:Npn \ctex_ziju:n #1 { \tl_set:Nx \l_@@_ziju_tl { \fp_eval:n {#1} } \ctex_select_size: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_update_ziju:} % 更新字距。若字距不大于 $-1$,即 \tn{ccwd} 为非正值,则不计算伸缩值。 % 否则,首先假定汉字的宽度为正常宽度加上字距,看一行上能正常放下多少个汉字。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_update_ziju: { \ctex_update_em_unit: \dim_set:Nn \l_@@_ziju_dim { \l_@@_ziju_tl \ccwd } \dim_add:Nn \ccwd { \l_@@_ziju_dim } \dim_compare:nNnTF \ccwd > \c_zero_dim % \end{macrocode} % 伸展量保证行内的剩余空白能够被均匀地填充到汉字之间,收缩的最大限度是让当前行 % 还能够再挤下一个汉字并且不会出现负间距。由 \TeX{} 决定伸展还是收缩。 % \begin{macrocode} { \dim_set:Nn \l_@@_tmp_dim { \linewidth - \ccwd + \l_@@_ziju_dim } \int_set:Nn \l_@@_tmp_int { \l_@@_tmp_dim } \tex_divide:D \l_@@_tmp_int \ccwd \dim_sub:Nn \l_@@_tmp_dim { \l_@@_tmp_int \ccwd } % \end{macrocode} % 由于 \tn{parindent} 是一个固定值,并不参与伸缩,容易导致第一行出现坏盒子。 % 我们在这里将字数减去 $2$,以此放大伸缩值。 % \begin{macrocode} \dim_compare:nNnF \parindent = \c_zero_dim { \int_compare:nNnF \l_@@_tmp_int < \c_three { \int_sub:Nn \l_@@_tmp_int { \c_two } } } \skip_set:Nn \l_@@_ccglue_skip { \l_@@_ziju_dim plus \dim_eval:n { \l_@@_tmp_dim / \l_@@_tmp_int } minus \dim_min:nn { \dim_abs:n { \l_@@_ziju_dim } } { ( \ccwd - \l_@@_tmp_dim ) / ( \l_@@_tmp_int + \c_one ) } } } { \skip_set:Nn \l_@@_ccglue_skip { \l_@@_ziju_dim } } \ctex_update_ccglue: % \end{macrocode} % 字距设置得比较大时,为了尽量保证段首缩进能够与下一行对齐,应该需要相应地加上 % 或者减去伸缩值。但是这里并不清楚 \TeX{} 是伸展还是收缩,之前以“当前行是否还 % 放得下一个汉字”为标准加上或减去伸缩值的做法也未必与实际结果一致,所以只好还 % 是设置为 |2\ccwd|。 % \begin{macrocode} \ctex_update_parindent: } \dim_new:N \l_@@_ziju_dim % \end{macrocode} % \end{macro} % % \changes{v2.0}{2015/03/21}{\tn{CTEXindent}, \tn{CTEXnoindent} 是过时命令。} % \begin{macro}{\CTEXindent,\CTEXnoindent} % 过时命令。 % \begin{macrocode} \NewDocumentCommand \CTEXindent { } { \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXindent } { \parindent is~ set~ to~ 2\ccwd. } \ctex_update_ccwd: \dim_set:Nn \parindent { 2 \ccwd } } \NewDocumentCommand \CTEXnoindent { } { \msg_warning:nnnn { ctex } { deprecated-command } { \CTEXnoindent } { \parindent is~ set~ to~ 0pt. } \dim_zero:N \parindent } % \end{macrocode} % \end{macro} % % \subsection{中文数字与日期} % % \begin{macrocode} \PassOptionsToPackage { encoding = \l_@@_encoding_tl } { zhnumber } \RequirePackage { zhnumber } % \end{macrocode} % % \begin{macro}{\chinese} % \begin{macrocode} \cs_new_eq:NN \chinese \zhnum \cs_new_eq:NN \Chinese \chinese \cs_new_eq:NN \CTEXcounter \use_none:n % \end{macrocode} % \end{macro} % % \changes{v2.2}{2015/06/29}{给 \pkg{enumitem} 宏包注册 \tn{chinese} 和 % \tn{zhnum}。} % % 给 \pkg{enumitem} 宏包注册 \tn{chinese} 和 \tn{zhnum}。 % \begin{macrocode} \ctex_at_end_package:nn { enumitem } { \cs_if_free:NF \AddEnumerateCounter { \AddEnumerateCounter * { \zhnum } { \zhnum_int:n } { 1 } \AddEnumerateCounter * { \chinese } { \zhnum_int:n } { 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 \keys_define:nn { ctex } { today .choice: , today / old .code:n = { \cs_set_eq:NN \today \CTEX@todayold } , today / small .code:n = { \cs_set_eq:NN \today \zhtoday \zhnumsetup { time = Arabic } } , today / big .code:n = { \cs_set_eq:NN \today \zhtoday \zhnumsetup { time = Chinese } } , today / unknown .code:n = { \msg_error:nnx { ctex } { today-undef } {#1} } } \msg_new:nnnn { ctex } { today-undef } { Today~format~`#1'~is~undefined. } { Available~today~formats~are~`old',~`small',~and~`big'. } % \end{macrocode} % \end{macro} % % \subsection{其它中文标题定义} % % \changes{v2.0}{2014/03/08}{将标题汉化功能加入 \pkg{ctex.sty}。} % % \begin{macrocode} \keys_define:nn { ctex } { contentsname .tl_set:N = \contentsname , listfigurename .tl_set:N = \listfigurename , listtablename .tl_set:N = \listtablename , figurename .tl_set:N = \figurename , tablename .tl_set:N = \tablename , abstractname .tl_set:N = \abstractname , indexname .tl_set:N = \indexname , appendixname .tl_set:N = \appendixname , %
bibname .tl_set:N = \refname % bibname .tl_set:N = \bibname } % \end{macrocode} % % \begin{macrocode} %<*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 \bibname { \keys_define:nn { ctex } { bibname .tl_set:N = \bibname } } { \tl_if_exist:NTF \refname { \keys_define:nn { ctex } { bibname .tl_set:N = \refname } } { \msg_warning:nn { ctex } { ctexbibname } \keys_define:nn { ctex } { bibname .tl_set:N = \ctexbibname } } } % % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{中文化的标题结构} % % 本节内容在 \CTeX{} 文档类或打开 \opt{heading} 选项下生效。 % \begin{macrocode} %<*class|heading> % \end{macrocode} % % \subsubsection{定义标题格式选项} % % \begin{variable}[int]{\c_@@_section_headings_seq} % 保存 \tn{section} 级以下标题名字。 % \begin{macrocode} \seq_new:N \c_@@_section_headings_seq \seq_gset_from_clist:Nn \c_@@_section_headings_seq { section , subsection , subsubsection , paragraph , subparagraph } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\c_@@_headings_seq} % \begin{macrocode} \seq_new:N \c_@@_headings_seq \seq_gset_eq:NN \c_@@_headings_seq \c_@@_section_headings_seq %\seq_gput_left:Nn \c_@@_headings_seq { chapter } \seq_gput_left:Nn \c_@@_headings_seq { part } % \end{macrocode} % \end{variable} % % \changes{v2.1}{2015/06/19}{\opt{nameformat} 可以接受章节名字为参数。} % \changes{v2.3}{2016/01/05}{修复 \opt{nameformat} 作用域问题。} % % \begin{macro}[int]{\@@_initial_heading:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_initial_heading:n #1 { \tl_new:c { CTEX@pre#1 } \tl_new:c { CTEX@post#1 } \tl_const:cx { CTEXthe#1 } { \exp_not:c { CTEX@pre#1 } \exp_not:c { CTEX@the#1 } \exp_not:c { CTEX@post#1 } } \tl_const:cx { CTEX@#1name } { \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}。} % % \begin{macro}[int]{\@@_def_heading_keys:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_def_heading_keys:n #1 { \tl_put_right:Nx \l_@@_tmp_tl { #1 .meta:nn = { ctex / #1 } { ####1 } , #1 / name .code:n = { \ctex_assign_heading_name:nn {#1} { ####1 } } , #1 / number .tl_set:N = \exp_not:c { CTEX@the#1 } , #1 / format .tl_set:N = \exp_not:c { CTEX@#1@format } , #1 / nameformat .tl_set:N = \exp_not:c { CTEX@#1@nameformat } , #1 / numberformat .tl_set:N = \exp_not:c { CTEX@#1@numberformat } , #1 / aftername .tl_set:N = \exp_not:c { CTEX@#1@aftername } , #1 / titleformat .tl_set:N = \exp_not:c { CTEX@#1@titleformat } , #1 / aftertitle .tl_set:N = \exp_not:c { CTEX@#1@aftertitle } , #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 / afterindent .bool_set:N = \exp_not:c { CTEX@#1@afterindent } , #1 / runin .bool_set:N = \exp_not:c { CTEX@#1@runin } , #1 / format+ .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@format } { ####1 } } , #1 / nameformat+ .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@nameformat } { ####1 } } , #1 / numberformat+ .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@numberformat } { ####1 } } , #1 / aftername+ .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@aftername } { ####1 } } , #1 / titleformat+ .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@titleformat } { ####1 } } , #1 / aftertitle+ .code:n = { \tl_put_right:Nn \exp_not:c { CTEX@#1@aftertitle } { ####1 } } , #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 , } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_assign_heading_name:nn,\@@_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 { \c_one } { , } } +m } { \@@_assign_heading_name:nnn {#1} #2 } \cs_new_protected:Npn \@@_assign_heading_name:nnn #1#2#3 { \tl_set:cn { CTEX@pre#1 } {#2} \IfNoValueTF {#3} { \tl_clear:c { CTEX@post#1 } } { \tl_set:cn { CTEX@post#1 } {#3} } } % \end{macrocode} % \end{macro} % % \changes{v2.0}{2014/03/21}{标题设置新增 \opt{pagestyle} 选项。} % % \begin{macro}{part/pagestyle,chapter/pagestyle} % 只在 \cls{ctexbook} 和 \cls{ctexrep} 下有定义。 % \begin{macrocode} %<*book|report> \tl_set:Nn \l_@@_tmp_tl { part / pagestyle .tl_set:N = \CTEX@part@pagestyle , chapter / pagestyle .tl_set:N = \CTEX@chapter@pagestyle , } % % \end{macrocode} % \end{macro} % % 定义标题键值选项。 % \begin{macrocode} \seq_map_inline:Nn \c_@@_headings_seq { \@@_initial_heading:n {#1} \@@_def_heading_keys:n {#1} } \use:x { \keys_define:nn { ctex } { \exp_not:o { \l_@@_tmp_tl } } } \tl_clear:N \l_@@_tmp_tl % \end{macrocode} % % % \subsubsection{标准标题命令的修改} % % \begin{macro}[int]{\CTEX@makeheadinganchor} % 用于 |numbering=false| 时,设置超链接跳转描点。 % \begin{macrocode} \cs_new_protected_nopar:Npn \CTEX@makeheadinganchor { } \ctex_at_end_package:nn { hyperref } { \cs_gset_protected_nopar:Npn \CTEX@makeheadinganchor { \phantomsection } } % \end{macrocode} % \end{macro} % % \changes{v2.2}{2015/06/27}{\opt{beforeskip}、\opt{afterskip} 和 \opt{indent} % 选项支持表达式。} % % \paragraph{part 的标题} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \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 % \addvspace{4ex}% \addvspace{\glueexpr\CTEX@part@beforeskip\relax}% \ifodd \CTEX@part@afterindent \@afterindenttrue \else \@afterindentfalse \fi \secdef\@part\@spart} %
%<*book|report> \renewcommand\part{% \if@openright \cleardoublepage \else \clearpage \fi % \thispagestyle{plain}% \thispagestyle{\CTEX@part@pagestyle}% \if@twocolumn \onecolumn \@tempswatrue \else \@tempswafalse \fi % \null\vfil \null\vskip \glueexpr \CTEX@part@beforeskip \relax \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 \refstepcounter{part}% % \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% \addcontentsline{toc}{part}{\CTEXthepart\hspace{1em}#1}% \else \CTEX@makeheadinganchor \addcontentsline{toc}{part}{#1}% \fi \else \addcontentsline{toc}{part}{#1}% \fi {\interlinepenalty \@M % \normalfont \parindent \z@ \raggedright \normalfont \parindent \dimexpr \CTEX@part@indent \relax \CTEX@part@format \ifnum \c@secnumdepth >\m@ne \ifodd \CTEX@part@numbering % \Large\bfseries\partname\nobreakspace\thepart\par\nobreak \CTEX@partname \CTEX@part@aftername \fi \fi % \huge\bfseries #2% \CTEX@part@titleformat{#2}% \markboth{}{}% \CTEX@part@aftertitle}% \nobreak % \vskip 3ex \vskip \glueexpr \CTEX@part@afterskip \relax \@afterheading} % %<*book|report> \def\@part[#1]#2{% \ifnum \c@secnumdepth >-2\relax \ifodd \CTEX@part@numbering \refstepcounter{part}% % \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% \addcontentsline{toc}{part}{\CTEXthepart\hspace{1em}#1}% \else \CTEX@makeheadinganchor \addcontentsline{toc}{part}{#1}% \fi \else \addcontentsline{toc}{part}{#1}% \fi \markboth{}{}% {\interlinepenalty \@M % \normalfont \centering \normalfont \CTEX@part@format \ifnum \c@secnumdepth >-2\relax \ifodd \CTEX@part@numbering % \huge\bfseries\partname\nobreakspace\thepart\par\vskip 20\p@ \CTEX@partname \CTEX@part@aftername \fi \fi % \Huge\bfseries #2\par}% \CTEX@part@titleformat{#2}% \CTEX@part@aftertitle}% \@endpart} % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@spart} % \begin{macrocode} %<*article> \def\@spart#1{% {\interlinepenalty \@M % \normalfont \parindent \z@ \raggedright \normalfont \parindent \dimexpr \CTEX@part@indent \relax \CTEX@part@format % \huge \bfseries #1\par}% \CTEX@part@titleformat{#1}% \CTEX@part@aftertitle}% \nobreak % \vskip 3ex \vskip \glueexpr \CTEX@part@afterskip \relax \@afterheading} % %<*book|report> \def\@spart#1{% {\interlinepenalty \@M % \normalfont \centering \normalfont \CTEX@part@format % \Huge \bfseries #1\par}% \CTEX@part@titleformat{#1}% \CTEX@part@aftertitle}% \@endpart} % % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@endpart} % \begin{macrocode} %<*book|report> \def\@endpart{% % \vfil \vskip \glueexpr \CTEX@part@afterskip \relax \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}% \thispagestyle{\CTEX@chapter@pagestyle}% \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 % \if@mainmatter \ifodd \CTEX@chapter@numbering \refstepcounter{chapter}% % \typeout{\@chapapp\space\thechapter.}% \typeout{\CTEXthechapter}% \addcontentsline{toc}{chapter} % {\protect\numberline{\thechapter}#1}% {\protect\numberline{\CTEXthechapter\hspace{0.3em}}#1}% \else \CTEX@makeheadinganchor \addcontentsline{toc}{chapter}{#1}% \fi % \else % \addcontentsline{toc}{chapter}{#1}% % \fi \else \addcontentsline{toc}{chapter}{#1}% \fi \chaptermark{#1}% \addtocontents{lof}{\protect\addvspace{10\p@}}% \addtocontents{lot}{\protect\addvspace{10\p@}}% \if@twocolumn \@topnewpage[\@makechapterhead{#2}]% \else \@makechapterhead{#2}% \@afterheading \fi} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@makechapterhead} % \begin{macrocode} \def\@makechapterhead#1{% % \vspace*{50\p@}% \vspace*{\glueexpr\CTEX@chapter@beforeskip\relax}% % {\normalfont \parindent \z@ \raggedright {\normalfont \parindent \dimexpr \CTEX@chapter@indent \relax \CTEX@chapter@format \ifnum \c@secnumdepth >\m@ne % \if@mainmatter \ifodd \CTEX@chapter@numbering % \huge\bfseries\@chapapp\space\thechapter\par\nobreak\vskip 20\p@ \CTEX@chaptername \CTEX@chapter@aftername \fi % \fi \fi \interlinepenalty\@M % \Huge \bfseries #1\par\nobreak \CTEX@chapter@titleformat{#1}% \CTEX@chapter@aftertitle \nobreak % \vskip 40\p@ \vskip \glueexpr \CTEX@chapter@afterskip \relax }} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@makeschapterhead} % \begin{macrocode} \def\@makeschapterhead#1{% % \vspace*{50\p@}% \vspace*{\glueexpr\CTEX@chapter@beforeskip\relax}% % {\normalfont \parindent \z@ \raggedright {\normalfont \parindent \dimexpr \CTEX@chapter@indent \relax \CTEX@chapter@format \interlinepenalty\@M % \Huge \bfseries #1\par\nobreak \CTEX@chapter@titleformat{#1} \CTEX@chapter@aftertitle \nobreak % \vskip 40\p@ \vskip \glueexpr \CTEX@chapter@afterskip \relax }} % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \paragraph{section 类的标题} % % \begin{macro}[int]{\@startsection} % \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 \addpenalty\@secpenalty\addvspace{\glueexpr #4\relax}% \fi \@ifstar {\@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 \let\@svsec\@empty \else \ifodd \csname CTEX@#1@numbering\endcsname \refstepcounter{#1}% \protected@edef\@svsec{\@seccntformat{#1}\relax}% \else \CTEX@makeheadinganchor \let\@svsec\@empty \fi \fi % \@tempskipa #5\relax % \ifdim \@tempskipa>\z@ \unless \ifodd \CTEX@runin \begingroup #6{% \@hangfrom{\hskip\glueexpr #3\relax\@svsec}% % \interlinepenalty \@M #8\@@par}% \interlinepenalty \@M \csname CTEX@#1@titleformat\endcsname{#8}% \csname CTEX@#1@aftertitle\endcsname}% \endgroup \csname #1mark\endcsname{#7}% \addcontentsline{toc}{#1}{% \ifnum #2>\c@secnumdepth \else \ifodd \csname CTEX@#1@numbering\endcsname % \protect\numberline{\csname the#1\endcsname}% \protect\numberline{\csname CTEXthe#1\endcsname}% \fi \fi #7}% \else \def\@svsechd{% #6{\hskip\glueexpr #3\relax % \@svsec #8}% \@svsec \csname CTEX@#1@titleformat\endcsname{#8}% \csname CTEX@#1@aftertitle\endcsname}% \csname #1mark\endcsname{#7}% \addcontentsline{toc}{#1}{% \ifnum #2>\c@secnumdepth \else \ifodd \csname CTEX@#1@numbering\endcsname % \protect\numberline{\csname the#1\endcsname}% \protect\numberline{\csname CTEXthe#1\endcsname}% \fi \fi #7}}% \fi \@xsect{#5}} % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@ssect} % \begin{macrocode} \def\@ssect#1#2#3#4#5{% % \@tempskipa #3\relax % \ifdim \@tempskipa>\z@ \unless \ifodd \CTEX@runin \begingroup #4{% \@hangfrom{\hskip\glueexpr #1\relax}% % \interlinepenalty \@M #5\@@par}% \interlinepenalty \@M \CTEX@titleformat@n{#5}% \CTEX@aftertitle}% \endgroup \else % \def\@svsechd{#4{\hskip\glueexpr #1\relax #5}}% \def\@svsechd{#4{\hskip\glueexpr #1\relax \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 \vskip\glueexpr #1\relax \@afterheading \else \@nobreakfalse \global\@noskipsectrue \everypar{% \if@noskipsec \global\@noskipsecfalse {\setbox\z@\lastbox}% \clubpenalty\@M \begingroup \@svsechd \endgroup \unskip % \@tempskipa #1\relax % \hskip -\@tempskipa \hskip\glueexpr #1\relax \else \clubpenalty \@clubpenalty \everypar{}% \fi}% \fi \ignorespaces} % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=ctex> % \end{macrocode} % % \begin{macro}[int]{\CTEX@update@sectionformat@n} % 在 \tn{@startsection} 中设置 \tn{CTEX@titleformat@n} 等为相应函数。 % \begin{macrocode} \cs_new_protected_nopar: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@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@runin \c_false_bool % \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_nopar:cpx {#1} { \exp_not:N \@startsection {#1} { \int_use:N \l_@@_tmp_int } { \exp_not:c { CTEX@#1@indent } } { \exp_not:c { CTEX@#1@beforeskip } } { \exp_not:c { CTEX@#1@afterskip } } { \exp_not:N \normalfont \exp_not:c { CTEX@#1@format } } } } % \end{macrocode} % % \paragraph{附录标题} % % \begin{macro}[int]{appendix/name,appendix/number,appendix/numbering} % \begin{macrocode} \keys_define:nn { ctex } { 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_nopar: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{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_nopar: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_nopar:Npn \@@_titlesec_hook:n #1 { \@@_titlesec_format:n {#1} \exp_args:Nc \@@_titlesec_spacing:Nn { ttls@#1 } {#1} } \cs_new_protected_nopar:Npn \@@_titlesec_format:n #1 { \cs_if_free:cF { ttlf@#1 } { \exp_args:Nc \@@_titlesec_format:Nn { ttlf@#1 } {#1} } } \cs_new_protected_nopar:Npn \@@_titlesec_format:Nn #1#2 { \tl_set:Nx #1 { \bool_if:cTF { CTEX@#2@runin } { \exp_not:N \ttlh@runin } { \exp_not:N \ttlh@hang } \tl_tail:N #1 } } \cs_new_protected_nopar: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_nopar:Npn \@@_titlesec_spacing:Nn #1#2 { \tl_set:Nx #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} % % \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_nopar: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}[aux]{\CTEX@titlepslabel@set,\CTEX@titlepslabel@clear} % 这两个函数要在随后被 \tn{xdef} 展开来获得 |\CTEXtheXXX| 的内容,不应该用 % \tn{protected} 来定义。 % \begin{macrocode} \cs_new_nopar:Npn \CTEX@titlepslabel@set #1 { \cs_if_free:cF { CTEXthe#1 } { \protect \@namedef { CTEXthe#1 } { \@nameuse { CTEXthe#1 } } } } \cs_new_nopar: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} 不包含章节间的层次信息,功能上不及修改内部命令完整。 % % % \subsubsection{目录标签的宽度} % % \begin{macro}[int]{\numberline} % \begin{macrocode} \cs_new_protected:Npn \CTEX@toc@width@n #1 { \hbox_set:Nn \l_@@_tmp_box {#1} \dim_set:Nn \@tempdima { \dim_max:nn { \@tempdima } { \box_wd:N \l_@@_tmp_box + \f@size \p@ / \c_two } } } \group_begin: \char_set_catcode_other:N \# \use:n { \group_end: \ctex_preto_cmd:NnnTF \numberline { \ExplSyntaxOff } { \CTEX@toc@width@n {#1} } { } { \ctex_patch_failure:N \numberline } \@ifpackageloaded { tocloft } { } { \ctex_at_end_package:nn { tocloft } { \ctex_preto_cmd:NnnTF \numberline { \char_set_catcode_letter:n { 64 } } { \CTEX@toc@width@n {#1} } { } { \ctex_patch_failure:N \numberline } } } } % \end{macrocode} % \end{macro} % % \subsubsection{页眉信息的修改} % % \begin{macro}[int]{\ps@headings} % \begin{macrocode} %<*article> \ctex_patch_cmd:Nnn \ps@headings { \thesection \quad } { \ifodd \CTEX@section@numbering \CTEXthesection \quad \fi } \if@twoside \ctex_patch_cmd:Nnn \ps@headings { \thesubsection \quad } { \ifodd \CTEX@subsection@numbering \CTEXthesubsection \quad \fi } \fi: % %<*book|report> \ctex_patch_cmd:Nnn \ps@headings { \@chapapp\ \thechapter.~\ } { \ifodd \CTEX@chapter@numbering \CTEXthechapter \quad \fi } \if@twoside \ctex_patch_cmd:Nnn \ps@headings { \thesection.~\ } { \ifodd \CTEX@section@numbering \CTEXthesection \quad \fi } \fi: % % \end{macrocode} % \end{macro} % % % \begin{macro}[int]{\ps@fancy} % 这里对 \pkg{fancyhdr} 宏包打补丁。原来 \pkg{fancyhdr} 宏包中使用 % \tn{thesection} 等宏表示页眉中的章节编号,这里改用 \pkg{ctex} 包所用的 % \tn{CTEXthesection} 系列宏。 % \begin{macrocode} \ctex_at_end_package:nn { fancyhdr } { %<*article> \ctex_patch_cmd:Nnn \ps@fancy { \thesection \hskip 1em \relax } { \ifodd \CTEX@section@numbering \CTEXthesection \quad \fi } \ctex_patch_cmd:Nnn \ps@fancy { \thesubsection \hskip 1em \relax } { \ifodd \CTEX@subsection@numbering \CTEXthesubsection \quad \fi } % %<*book|report> \ctex_patch_cmd:Nnn \ps@fancy { \@chapapp\ \thechapter.~\ } % { \if@mainmatter \ifodd \CTEX@chapter@numbering \CTEXthechapter \quad \fi \fi } % { \ifodd \CTEX@chapter@numbering \CTEXthechapter \quad \fi } \ctex_patch_cmd:Nnn \ps@fancy { \thesection.~\ } { \ifodd \CTEX@section@numbering \CTEXthesection \quad \fi } % } % \end{macrocode} % \end{macro} % % \subsubsection{标签引用数字的汉化} % % \begin{macro}[int]{\refstepcounter} % 对标题进行引用时,设置标签为通过 \opt{number} 选项设置的形式。 % \begin{macrocode} \cs_new_protected_nopar:Npn \CTEX@setcurrentlabel@n #1 { \protected@edef \@currentlabel { \cs_if_exist:cTF { CTEX@the#1 } { \exp_args:cc { p@#1 } { CTEX@the#1 } } { \exp_not:o { \@currentlabel } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_varioref_hook:} % 关于标签引用的宏包可能会修改 \tn{refstepcounter}。其中 \pkg{cleveref} 和 % \pkg{hyperref} 宏包都会保存之前的定义,并且它们都要求尽可能晚的被载入,所以 % 对我们上述的修改影响不大。需要注意的是 \pkg{varioref} 宏包,如果它在 % \CTeX{} 之后被载入,我们之前的修改将会被覆盖。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_varioref_hook: { \seq_map_inline:Nn \c_@@_headings_seq { \ctex_fix_varioref_label:n { ##1 } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_fix_varioref_label:n} % \pkg{varioref} 宏包的 \tn{labelformat} 实际上是定义一个以 |\the<#1>| 为参数的宏 % |\p@<#1>|。\LaTeX{} 在定义计数器 |<#1>| 时,都会将 |\p@<#1>| 初始化为 \tn{@empty}。 % 如果这个宏非空,说明用户自定义了标签格式,我们就不再修改。这里不能使用 % \cs{exp_args:Nnc},因为 \texttt{c} 这种展开格式不会将参数放在花括号内。而 % \tn{labelformat} 的定义是 % \begin{verbatim} % \def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1} % \end{verbatim} % 它的第二个参数必须放在花括号内,否则将会被作为宏的定界符号。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_fix_varioref_label:n #1 { \tl_if_empty:cT { p@#1 } { \exp_args:Nno \labelformat {#1} { \cs:w CTEX@the#1 \cs_end: } } } % \end{macrocode} % \end{macro} % % 如果 \pkg{varioref} 已经被载入,则使用它来设置。 % \begin{macrocode} \@ifpackageloaded { varioref } { \ctex_varioref_hook: } { \cs_new_eq:NN \CTEX@save@refstepcounter \refstepcounter \RenewDocumentCommand \refstepcounter { m } { \CTEX@save@refstepcounter {#1} \CTEX@setcurrentlabel@n {#1} } \ctex_at_end_package:nn { varioref } { \ctex_varioref_hook: } } % \end{macrocode} % % \subsubsection{载入 \meta{scheme} 文件} % % \begin{macrocode} \ctex_scheme_input:o { \l_@@_scheme_tl } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{标题格式的 \opt{scheme} 定义} % % 下面使用 \CTeX 文档类的设置方式,\opt{plain} 模拟标准文档类直接定义或以 % \tn{@startsection} 设定的章节标题格式,\opt{chinese} 汉化的标题格式。 % % \begin{macrocode} %<*scheme&(article|book|report)> % \end{macrocode} % % \changes{v2.1}{2015/05/30}{修复 \cls{ctexbook} 和 \cls{ctexrep} 类的中文 % \opt{part/number} 选项初值为空的错误。} % \changes{v2.2}{2015/06/30}{将中文版式下的 \texttt{part} 和 \texttt{chapter} % 标题的 \opt{nameformat} 和 \opt{titleformat} 选项的初值合并到 \opt{format} 中。} % % \begin{macrocode} \keys_set:nn { ctex / part } { aftertitle = \par , %<*plain> name = \partname \space , number = \thepart , % %<*chinese> number = \chinese { part } , % %<*article> beforeskip = 4ex , afterskip = 3ex , %<*plain> format = \raggedright , nameformat = \Large \bfseries , aftername = \par \nobreak , titleformat = \huge \bfseries , afterindent = false % %<*chinese> format = \Large \bfseries \centering , aftername = \quad , afterindent = true % % %<*book|report> aftername = \par \vskip 20 \p@ , beforeskip = 0pt \@plus 1fil , afterskip = 0pt \@plus 1fil , pagestyle = plain , %<*plain> format = \centering , nameformat = \huge \bfseries , titleformat = \Huge \bfseries % %<*chinese> format = \huge \bfseries \centering % % } % \end{macrocode} % % \begin{macrocode} %<*book|report> \keys_set:nn { ctex / chapter } { pagestyle = plain , aftertitle = \par , beforeskip = 50 \p@ , afterskip = 40 \p@ , %<*plain> name = \chaptername \space , number = \thechapter , format = \raggedright , nameformat = \huge \bfseries , aftername = \par \nobreak \vskip 20 \p@ , titleformat = \Huge \bfseries , afterindent = false % %<*chinese> number = \chinese { chapter } , format = \huge \bfseries \centering , aftername = \quad , afterindent = true % } % % \end{macrocode} % % \begin{macrocode} %<@@=> % \end{macrocode} % % \begin{macrocode} \keys_set:nn { ctex / section } { number = \thesection , aftername = \quad , aftertitle = \@@par , beforeskip = 3.5ex \@plus 1ex \@minus .2ex , afterskip = 2.3ex \@plus .2ex , runin = false , %<*plain> format = \Large \bfseries , afterindent = false % %<*chinese> format = \Large \bfseries \centering , afterindent = true % } % \end{macrocode} % % \begin{macrocode} \keys_set:nn { ctex / subsection } { number = \thesubsection , format = \large \bfseries , aftername = \quad , aftertitle = \@@par , beforeskip = 3.25ex \@plus 1ex \@minus .2ex , afterskip = 1.5ex \@plus .2ex , runin = false , %<*plain> afterindent = false % %<*chinese> afterindent = true % } % \end{macrocode} % % \begin{macrocode} \keys_set:nn { ctex / subsubsection } { number = \thesubsubsection , format = \normalsize \bfseries , aftername = \quad , aftertitle = \@@par , beforeskip = 3.25ex \@plus 1ex \@minus .2ex , afterskip = 1.5ex \@plus .2ex , runin = false , %<*plain> afterindent = false % %<*chinese> afterindent = true % } % \end{macrocode} % % \begin{macrocode} \keys_set:nn { ctex / paragraph } { number = \theparagraph , format = \normalsize \bfseries , aftername = \quad , beforeskip = 3.25ex \@plus 1ex \@minus .2ex , %<*plain> afterindent = false % %<*chinese> afterindent = true % } % \end{macrocode} % % \begin{macrocode} \keys_set:nn { ctex / subparagraph } { number = \thesubparagraph , format = \normalsize \bfseries , aftername = \quad , beforeskip = 3.25ex \@plus 1ex \@minus .2ex , %<*plain> afterindent = false % %<*chinese> afterindent = true % } % \end{macrocode} % % 处理 \opt{sub3section} 与 \opt{sub4section} 的格式。 % \begin{macrocode} \int_compare:nNnTF \g__ctex_section_depth_flag > \c_two { \keys_set:nn { ctex / paragraph } { aftertitle = \@@par , afterskip = 1ex \@plus .2ex , runin = false } } { \keys_set:nn { ctex / paragraph } { afterskip = 1em , runin = true } } \int_compare:nNnTF \g__ctex_section_depth_flag > \c_three { \keys_set:nn { ctex / subparagraph } { aftertitle = \@@par , afterskip = 1ex \@plus .2ex , runin = false } } { \keys_set:nn { ctex / subparagraph } { afterskip = 1em , runin = true } } \int_compare:nNnTF \g__ctex_section_depth_flag > \c_two { \keys_set:nn { ctex / subparagraph } { indent = \c_zero_dim } } { \keys_set:nn { ctex / subparagraph } { indent = \parindent } } % \end{macrocode} % % \begin{macrocode} %<@@=ctex> % \end{macrocode} % % 处理附录的格式。 % \begin{macrocode} \keys_set:nn { ctex / appendix } %<*article> { number = \@Alph \c@section } % %<*book|report> { name = \appendixname \space , number = \@Alph \c@chapter } % % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{\pkg{ctex.sty} 的 \opt{heading} 选项} % % \begin{macrocode} %<*ctex|ctexheading> % \end{macrocode} % % \begin{variable}[int]{\c_@@_std_class_tl} % 用于记录被引入的标准文档类。 % \begin{macrocode} \clist_map_inline:nn { article , book , report } { \@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:nnx { ctex } { not-standard-class } { \c_@@_class_tl } } \ctex_file_input:n { ctex- \c_@@_class_tl .def } } % { \ctex_scheme_input:o { \l_@@_scheme_tl } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{标题配置文件} % % \begin{macrocode} %<*UTF8|GBK> % \end{macrocode} % % \begin{macrocode} \keys_set:nn { ctex } { contentsname = 目录 , listfigurename = 插图 , listtablename = 表格 , figurename = 图 , tablename = 表 , abstractname = 摘要 , indexname = 索引 , bibname = 参考文献 , appendixname = 附录 } % \end{macrocode} % % \begin{macrocode} \keys_if_exist:nnT { ctex / part } { name } { \keys_set:nn { ctex / part } { name = { 第 , 部分 } } \keys_if_exist:nnT { ctex / chapter } { name } { \keys_set:nn { ctex / chapter } { name = { 第 , 章 } } } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\opt{chinese} 方案的其他设置} % % \begin{macrocode} %<*scheme&chinese> % \end{macrocode} % % \opt{chinese} 在标准文档类下的页面格式总采用 \texttt{headings}。 % \begin{macrocode} %\pagestyle { headings } % \end{macrocode} % % 汉化标题名字。 % \begin{macrocode} \str_if_eq:onTF { \l_@@_encoding_tl } { GBK } { \ctex_file_input:n { ctex-name-gbk.cfg } } { \ctex_file_input:n { ctex-name-utf8.cfg } } % \end{macrocode} % % 日期格式。 % \begin{macrocode} \keys_set:nn { ctex } { today = small } % \end{macrocode} % % 若用户未设置宏包选项 \opt{zihao},则设置 \tn{normalsize} 为五号字。 % \begin{macrocode} \int_compare:nNnF \g_@@_font_size_flag > \c_minus_one { \cs_gset_eq:NN \g_@@_font_size_flag \c_zero } % \end{macrocode} % % 若用户未设置宏包选项 \opt{linespread},则设置行距初始值为 $1.3\times 1.2=1.56$ % 倍字体大小。 % \begin{macrocode} \fp_compare:nNnT { \l_@@_line_spread_fp } ? { \c_zero_fp } { \keys_set:nn { ctex / option } { linespread = 1.3 } } % \end{macrocode} % % 若用户未设置宏包选项 \opt{autoindent},则自动调整首行缩进。 % \begin{macrocode} \ctex_if_autoindent_touched:F { \keys_set:nn { ctex } { autoindent = true } } % \end{macrocode} % % \changes{v2.0.2}{2015/05/16}{修复加载 \pkg{ctex} 宏包后章节标题后第一段 % 无段首缩进的问题。} % 若 \pkg{ctex} 宏包与标准文档类及其衍生文档类联用,则将载入 \pkg{indentfirst} 宏包, % 实现章节标题后首个段落的段首缩进。 % \begin{macrocode} %<*generic> \tl_if_exist:NT \c_@@_std_class_tl { \RequirePackage { indentfirst } } % % \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:Nx \ctex_zihao:n {#1} \tex_ignorespaces:D } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_zihao:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_zihao:n #1 { \prop_get:NnNTF \c_@@_font_size_prop {#1} \l_@@_font_size_tl { \exp_after:wN \fontsize \l_@@_font_size_tl \selectfont } { \msg_error:nnn { ctex } { fontsize } {#1} } } \msg_new:nnnn { ctex } { fontsize } { Undefined~Chinese~font~size~`#1'~in~command~\token_to_str:N \zihao.} { The~old~font~size~is~used~if~you~continue.\\ The~available~font~sizes~are~listed~as~follow.\\ \seq_use:Nnnn \c_@@_font_size_seq { ~and~ } { ,~ } { ,~and~ }. } % \end{macrocode} % \end{macro} % % \subsubsection{定义中文字号} % % \changes{v2.0}{2014/03/08}{中文字号不再采用近似值。} % % \begin{variable}[int]{\c_@@_font_size_prop} % \begin{macro}[aux]{\@@_save_font_size:nn} % 基础行距是字号的 $1.2$ 倍,采用 \hologo{eTeX} 的 scaling 运算得到的结果 % 要比简单的 |1.2\dimexpr| 精确^^A % \footnote{\url{http://thread.gmane.org/gmane.comp.tex.latex.latex3/3190}}。 % \begin{macrocode} \prop_new:N \c_@@_font_size_prop \seq_new:N \c_@@_font_size_seq \cs_new_protected_nopar:Npn \@@_save_font_size:nn #1#2 { \use:x { \prop_gput:Nnn \exp_not:N \c_@@_font_size_prop {#1} { { \dim_to_decimal:n {#2} } { \dim_to_decimal:n { (#2) * \c_six / \c_five } } } } \seq_gput_right:Nn \c_@@_font_size_seq {#1} } \clist_map_inline:nn { { 8 } { 5 bp } , { 7 } { 5.5 bp } , { -6 } { 6.5 bp } , { 6 } { 7.5 bp } , { -5 } { 9 bp } , { 5 } { 10.5 bp } , { -4 } { 12 bp } , { 4 } { 14 bp } , { -3 } { 15 bp } , { 3 } { 16 bp } , { -2 } { 18 bp } , { 2 } { 22 bp } , { -1 } { 24 bp } , { 1 } { 26 bp } , { -0 } { 36 bp } , { 0 } { 42 bp } } { \@@_save_font_size:nn #1 } % \end{macrocode} % \end{macro} % \end{variable} % % \begin{macro}[int]{\ctex_declare_math_sizes:nnnn} % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_declare_math_sizes:nnnn #1#2#3#4 { \@@_get_font_sizes:Nn \l_@@_font_size_tl { {#1} {#2} {#3} {#4} } \exp_after:wN \DeclareMathSizes \l_@@_font_size_tl } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_get_font_sizes:Nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_get_font_sizes:Nn #1#2 { \tl_clear:N #1 \tl_map_inline:nn {#2} { \prop_get:NnNTF \c_@@_font_size_prop {##1} \l_@@_tmp_tl { \tl_put_right:Nx #1 { { \tl_head:N \l_@@_tmp_tl } } } { \tl_put_right:Nx #1 { { \dim_to_decimal:n { ##1 } } } } } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \clist_map_inline:nn { { 8 }{ 8 }{ 5pt }{ 5pt } , { 7 }{ 7 }{ 5pt }{ 5pt } , { -6 }{ -6 }{ 5pt }{ 5pt } , { 6 }{ 6 }{ 5pt }{ 5pt } , { -5 }{ -5 }{ 6pt }{ 5pt } , { 5 }{ 5 }{ 7pt }{ 5pt } , { -4 }{ -4 }{ 8pt }{ 6pt } , { 4 }{ 4 }{ 5 }{ 6 } , { -3 }{ -3 }{ -4 }{ -5 } , { 3 }{ 3 }{ 4 }{ 5 } , { -2 }{ -2 }{ -3 }{ -4 } , { 2 }{ 2 }{ 3 }{ 4 } , { -1 }{ -1 }{ -2 }{ -3 } , { 1 }{ 1 }{ 2 }{ 3 } , { -0 }{ -0 }{ -1 }{ -2 } , { 0 }{ 0 }{ 1 }{ 2 } } { \ctex_declare_math_sizes:nnnn #1 } % \end{macrocode} % % \subsubsection{修改默认字号大小} % % \begin{macro}[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_nopar:Npn #3 { \@setfontsize #3 {#1} {#2} #4 } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \if_case:w \g_@@_font_size_flag \ctex_file_input:n { ctex-c5size.clo } \or: \ctex_file_input:n { ctex-cs4size.clo } \fi: % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<*c5size> \ctex_set_font_size:Nnn \normalsize { 5 } { \abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@ \abovedisplayshortskip \z@ \@plus3\p@ \belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@ \belowdisplayskip \abovedisplayskip \let\@listi\@listI } \ctex_set_font_size:Nnn \small { -5 } { \abovedisplayskip 8.5\p@ \@plus3\p@ \@minus4\p@ \abovedisplayshortskip \z@ \@plus2\p@ \belowdisplayshortskip 4\p@ \@plus2\p@ \@minus2\p@ \def\@listi{\leftmargin\leftmargini \topsep 4\p@ \@plus2\p@ \@minus2\p@ \parsep 2\p@ \@plus\p@ \@minus\p@ \itemsep \parsep} \belowdisplayskip \abovedisplayskip } \ctex_set_font_size:Nnn \footnotesize { 6 } { \abovedisplayskip 6\p@ \@plus2\p@ \@minus4\p@ \abovedisplayshortskip \z@ \@plus\p@ \belowdisplayshortskip 3\p@ \@plus\p@ \@minus2\p@ \def\@listi{\leftmargin\leftmargini \topsep 3\p@ \@plus\p@ \@minus\p@ \parsep 2\p@ \@plus\p@ \@minus\p@ \itemsep \parsep} \belowdisplayskip \abovedisplayskip } \ctex_set_font_size:Nnn \scriptsize { -6 } { } \ctex_set_font_size:Nnn \tiny { 7 } { } \ctex_set_font_size:Nnn \large { -4 } { } \ctex_set_font_size:Nnn \Large { -3 } { } \ctex_set_font_size:Nnn \LARGE { -2 } { } \ctex_set_font_size:Nnn \huge { 2 } { } \ctex_set_font_size:Nnn \Huge { 1 } { } % %<*cs4size> \ctex_set_font_size:Nnn \normalsize { -4 } { \abovedisplayskip 12\p@ \@plus3\p@ \@minus7\p@ \abovedisplayshortskip \z@ \@plus3\p@ \belowdisplayshortskip 6.5\p@ \@plus3.5\p@ \@minus3\p@ \belowdisplayskip \abovedisplayskip \let\@listi\@listI } \ctex_set_font_size:Nnn \small { 5 } { \abovedisplayskip 11\p@ \@plus3\p@ \@minus6\p@ \abovedisplayshortskip \z@ \@plus3\p@ \belowdisplayshortskip 6.5\p@ \@plus3.5\p@ \@minus3\p@ \def\@listi{\leftmargin\leftmargini \topsep 9\p@ \@plus3\p@ \@minus5\p@ \parsep 4.5\p@ \@plus2\p@ \@minus\p@ \itemsep \parsep} \belowdisplayskip \abovedisplayskip } \ctex_set_font_size:Nnn \footnotesize { -5 } { \abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@ \abovedisplayshortskip \z@ \@plus3\p@ \belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@ \def\@listi{\leftmargin\leftmargini \topsep 6\p@ \@plus2\p@ \@minus2\p@ \parsep 3\p@ \@plus2\p@ \@minus\p@ \itemsep \parsep} \belowdisplayskip \abovedisplayskip } \ctex_set_font_size:Nnn \scriptsize { 6 } { } \ctex_set_font_size:Nnn \tiny { -6 } { } \ctex_set_font_size:Nnn \large { -3 } { } \ctex_set_font_size:Nnn \Large { -2 } { } \ctex_set_font_size:Nnn \LARGE { 2 } { } \ctex_set_font_size:Nnn \huge { -1 } { } \ctex_set_font_size:Nnn \Huge { 1 } { } % % \end{macrocode} % % \begin{macrocode} %\normalsize % \end{macrocode} % % \begin{macrocode} %<*class|ctex> % \end{macrocode} % % \subsection{更新行距} % % \cs{l_@@_line_spread_fp} 被设置了才有必要更新行距和 \tn{footnotesep}。 % \begin{macrocode} \fp_compare:nNnF { \l_@@_line_spread_fp } ? { \c_zero_fp } { \exp_args:Nx \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} % \file{ctex-faq.sty} 中的定义是 % \begin{verbatim} % \DeclareRobustCommand\CTeX{$\mathbb{C}$\kern-.05em\TeX} % \end{verbatim} % 然而 \tn{mathbb} 未必有定义,这里就不采用它了,只定义最简单的形式。 % 同 \pkg{hologo} 宏包的设置类似,\CTeX{} 可以用在 \tn{csname} 和 PDF 书签中。 % \begin{macrocode} \NewDocumentCommand \CTeX { } { \ifincsname CTeX \else: C \TeX \fi: } \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} \keys_define:nn { ctex } { captiondelimiter .code:n = { \msg_warning:nnn { ctex } { deprecated-option } { You~can~load~the~package~`caption'~to~get~its~functionality. } } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{列表环境的缩进} % % \begin{macro}[int]{\verse,\quotation} % 只在使用文档类的时候修改诗歌和引用环境的缩进。 % \begin{macrocode} %<*scheme&!generic&chinese> \ctex_patch_cmd:Nnn \verse { -1.5em } { -2 \ccwd } \ctex_patch_cmd:Nnn \verse { 1.5em } { 2 \ccwd } \ctex_patch_cmd:Nnn \quotation { 1.5em } { 2 \ccwd } % % \end{macrocode} % \end{macro} % % \begin{macrocode} %<*class|ctex> % \end{macrocode} % % \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_nopar:Npn \ctex_fontset_error:n #1 { \msg_critical:nnn { ctex } { fontset-unavailable } {#1} } \msg_new:nnn { ctex } { fontset-unavailable } { CTeX~fontset~`#1'~is~unavailable~in~current~mode. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_load_fontset:} % 如果用户没有指定字体,则探测操作系统,载入相应的字体配置。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_load_fontset: { \tl_if_empty:NTF \g_@@_fontset_tl { \ctex_detected_platform: \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } } { \file_if_exist:nTF { ctex-fontset- \g_@@_fontset_tl .def } { \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } } { \use:x { \ctex_detected_platform: \msg_error:nnxx { ctex } { fontset-not-found } { \g_@@_fontset_tl } { \exp_not:N \g_@@_fontset_tl } } \ctex_file_input:n { ctex-fontset- \g_@@_fontset_tl .def } } } } \@onlypreamble \ctex_load_fontset: \msg_new:nnnn { ctex } { fontset-not-found } { CTeX~fontset~`#1'~could~not~be~found.\\ Fontset~`#2'~will~be~used~instead. } { You~may~run~`mktexlsr'~firstly. } % \end{macrocode} % \end{macro} % % \begin{macro}{fontset} % 在导言区通过 \tn{ctexset} 载入中文字库的选项。 % \begin{macrocode} \keys_define:nn { ctex } { fontset .code:n = { \ctex_if_preamble:TF { \str_if_eq_x:nnTF {#1} { none } { \msg_warning:nnn { ctex } { invalid-value } {#1} } { \str_if_eq:onTF { \g_@@_fontset_tl } { none } { \tl_gset:Nx \g_@@_fontset_tl {#1} \ctex_load_fontset: } { \msg_error:nnxx { ctex } { fontset-loaded } { \g_@@_fontset_tl } {#1} } } } { \msg_error:nn { ctex } { fontset-only-preamble } } } } \msg_new:nnnn { ctex } { fontset-loaded } { CTeX~fontset~`#1'~has~been~loaded. \str_if_eq:nnF {#1} {#2} { \\ Fontset~`#2'~will~be~ignored. } } { Only~one~fontset~can~be~loaded~in~the~preamble. } \msg_new:nnn { ctex } { fontset-only-preamble } { The~ `fontset'~ option~ can~ be~ used~ only~ in~ preamble. } % \end{macrocode} % \end{macro} % % 载入中文字库。 % \begin{macrocode} \str_if_eq:onF { \g_@@_fontset_tl } { none } { \ctex_load_fontset: } % \end{macrocode} % % \subsection{宏包配置文件} % % \subsubsection{\pkg{ctex.cfg}} % % \begin{macrocode} \ctex_at_end:n { \ctex_file_input:n { ctex.cfg } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<*config> %% % % \end{macrocode} % % \subsubsection{\pkg{ctexopts.cfg}} % % 这里仅为配置文件示例:使用 Windows Vista 或以后版本的字体设置。 % \begin{macrocode} %<*ctexopts> %% %% \keys_set:nn { ctex / option } { fontset = windowsnew } % % \end{macrocode} % % \subsection{字体定义文件} % % \subsubsection{传统定义方式} % % \begin{macrocode} %<*c19|c70> %% %% Chinese characters %% %%% character set: GBK (extension of GB 2312) %%% character set: Unicode %% font encoding: Unicode %% % % \end{macrocode} % % \begin{macrocode} %\DeclareFontFamily{C19}{rm}{\hyphenchar\font\m@ne} %\DeclareFontFamily{C70}{rm}{\hyphenchar\font\m@ne} %\DeclareFontFamily{C19}{sf}{\hyphenchar\font\m@ne} %\DeclareFontFamily{C70}{sf}{\hyphenchar\font\m@ne} %\DeclareFontFamily{C19}{tt}{\hyphenchar\font\m@ne} %\DeclareFontFamily{C70}{tt}{\hyphenchar\font\m@ne} % \end{macrocode} % % \begin{macrocode} %<*rm> %<*c19> \DeclareFontShape{C19}{rm}{m}{n}{<-> CJK * gbksong}{\CJKnormal} \DeclareFontShape{C19}{rm}{b}{n}{<-> CJK * gbkhei}{\CJKnormal} \DeclareFontShape{C19}{rm}{bx}{n}{<-> CJK * gbkhei}{\CJKnormal} \DeclareFontShape{C19}{rm}{m}{sl}{<-> CJK * gbksongsl}{\CJKnormal} \DeclareFontShape{C19}{rm}{b}{sl}{<-> CJK * gbkheisl}{\CJKnormal} \DeclareFontShape{C19}{rm}{bx}{sl}{<-> CJK * gbkheisl}{\CJKnormal} \DeclareFontShape{C19}{rm}{m}{it}{<-> CJK * gbkkai}{\CJKnormal} \DeclareFontShape{C19}{rm}{b}{it}{<-> CJKb * gbkkai}{\CJKbold} \DeclareFontShape{C19}{rm}{bx}{it}{<-> CJKb * gbkkai}{\CJKbold} % %<*c70> \DeclareFontShape{C70}{rm}{m}{n}{<-> CJK * unisong}{\CJKnormal} \DeclareFontShape{C70}{rm}{b}{n}{<-> CJK * unihei}{\CJKnormal} \DeclareFontShape{C70}{rm}{bx}{n}{<-> CJK * unihei}{\CJKnormal} \DeclareFontShape{C70}{rm}{m}{sl}{<-> CJK * unisongsl}{\CJKnormal} \DeclareFontShape{C70}{rm}{b}{sl}{<-> CJK * uniheisl}{\CJKnormal} \DeclareFontShape{C70}{rm}{bx}{sl}{<-> CJK * uniheisl}{\CJKnormal} \DeclareFontShape{C70}{rm}{m}{it}{<-> CJK * unikai}{\CJKnormal} \DeclareFontShape{C70}{rm}{b}{it}{<-> CJKb * unikai}{\CJKbold} \DeclareFontShape{C70}{rm}{bx}{it}{<-> CJKb * unikai}{\CJKbold} % % % \end{macrocode} % % \begin{macrocode} %<*sf> %<*c19> \DeclareFontShape{C19}{sf}{m}{n}{<-> CJK * gbkyou}{\CJKnormal} \DeclareFontShape{C19}{sf}{b}{n}{<-> CJKb * gbkyou}{\CJKbold} \DeclareFontShape{C19}{sf}{bx}{n}{<-> CJKb * gbkyou}{\CJKbold} \DeclareFontShape{C19}{sf}{m}{sl}{<-> CJK * gbkyousl}{\CJKnormal} \DeclareFontShape{C19}{sf}{b}{sl}{<-> CJKb * gbkyousl}{\CJKbold} \DeclareFontShape{C19}{sf}{bx}{sl}{<-> CJKb * gbkyousl}{\CJKbold} \DeclareFontShape{C19}{sf}{m}{it}{<-> CJK * gbkyou}{\CJKnormal} \DeclareFontShape{C19}{sf}{b}{it}{<-> CJKb * gbkyou}{\CJKbold} \DeclareFontShape{C19}{sf}{bx}{it}{<-> CJKb * gbkyou}{\CJKbold} % %<*c70> \DeclareFontShape{C70}{sf}{m}{n}{<-> CJK * uniyou}{\CJKnormal} \DeclareFontShape{C70}{sf}{b}{n}{<-> CJKb * uniyou}{\CJKbold} \DeclareFontShape{C70}{sf}{bx}{n}{<-> CJKb * uniyou}{\CJKbold} \DeclareFontShape{C70}{sf}{m}{sl}{<-> CJK * uniyousl}{\CJKnormal} \DeclareFontShape{C70}{sf}{b}{sl}{<-> CJKb * uniyousl}{\CJKbold} \DeclareFontShape{C70}{sf}{bx}{sl}{<-> CJKb * uniyousl}{\CJKbold} \DeclareFontShape{C70}{sf}{m}{it}{<-> CJK * uniyou}{\CJKnormal} \DeclareFontShape{C70}{sf}{b}{it}{<-> CJKb * uniyou}{\CJKbold} \DeclareFontShape{C70}{sf}{bx}{it}{<-> CJKb * uniyou}{\CJKbold} % % % \end{macrocode} % % \begin{macrocode} %<*tt> %<*c19> \DeclareFontShape{C19}{tt}{m}{n}{<-> CJK * gbkfs}{\CJKnormal} \DeclareFontShape{C19}{tt}{b}{n}{<-> CJKb * gbkfs}{\CJKbold} \DeclareFontShape{C19}{tt}{bx}{n}{<-> CJKb * gbkfs}{\CJKbold} \DeclareFontShape{C19}{tt}{m}{sl}{<-> CJK * gbkfssl}{\CJKnormal} \DeclareFontShape{C19}{tt}{b}{sl}{<-> CJKb * gbkfssl}{\CJKbold} \DeclareFontShape{C19}{tt}{bx}{sl}{<-> CJKb * gbkfssl}{\CJKbold} \DeclareFontShape{C19}{tt}{m}{it}{<-> CJK * gbkfs}{\CJKnormal} \DeclareFontShape{C19}{tt}{b}{it}{<-> CJKb * gbkfs}{\CJKbold} \DeclareFontShape{C19}{tt}{bx}{it}{<-> CJKb * gbkfs}{\CJKbold} % %<*c70> \DeclareFontShape{C70}{tt}{m}{n}{<-> CJK * unifs}{\CJKnormal} \DeclareFontShape{C70}{tt}{b}{n}{<-> CJKb * unifs}{\CJKbold} \DeclareFontShape{C70}{tt}{bx}{n}{<-> CJKb * unifs}{\CJKbold} \DeclareFontShape{C70}{tt}{m}{sl}{<-> CJK * unifssl}{\CJKnormal} \DeclareFontShape{C70}{tt}{b}{sl}{<-> CJKb * unifssl}{\CJKbold} \DeclareFontShape{C70}{tt}{bx}{sl}{<-> CJKb * unifssl}{\CJKbold} \DeclareFontShape{C70}{tt}{m}{it}{<-> CJK * unifs}{\CJKnormal} \DeclareFontShape{C70}{tt}{b}{it}{<-> CJKb * unifs}{\CJKbold} \DeclareFontShape{C70}{tt}{bx}{it}{<-> CJKb * unifs}{\CJKbold} % % % \end{macrocode} % % \begin{macrocode} %<*fontset> % \end{macrocode} % % \subsubsection{\pkg{ctex-fontset-windows.def}, % \pkg{ctex-fontset-windowsnew.def}, \pkg{ctex-fontset-windowsold.def}} % % \pkg{ctex} 包利用 \path{C:\boot.ini} 文件的存在性来判断是否使用 Windows XP % 及以前的版本,分别载入新旧字体设置。 % \begin{macrocode} %<*windows> \file_if_exist:nTF { C:/boot.ini } { \ctex_file_input:n { ctex-fontset-windowsold.def } } { \ctex_file_input:n { ctex-fontset-windowsnew.def } } % % \end{macrocode} % % 旧的 Windows 字体设置使用黑体作为无衬线体,楷体和仿宋是 GB2312 编码;新的 % Windows 字体设置使用微软雅黑作为无衬线体,楷体和仿宋是大字库。 % \begin{macrocode} %<*windowsnew|windowsold> \sys_if_engine_pdftex:TF { \ctex_zhmap_case:nnn { \ctex_punct_set:n { windows } \setCJKmainfont [ BoldFont = simhei.ttf , ItalicFont = simkai.ttf ] { simsun.ttc } %<*windowsold> \setCJKsansfont { simhei.ttf } \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } % % \end{macrocode} % Windows 8 以后,微软雅黑由原来的 \file{.ttf} 后缀改为 \file{.ttc} 后缀,需要 % 加以区分。 % \begin{macrocode} %<*windowsnew> \file_if_exist:nTF { C:/Windows/Fonts/msyh.ttc } { \setCJKsansfont [ BoldFont = msyhbd.ttc ] { msyh.ttc } \setCJKfamilyfont { zhyahei } [ BoldFont = msyhbd.ttc ] { msyh.ttc } } { \setCJKsansfont [ BoldFont = msyhbd.ttf ] { msyh.ttf } \setCJKfamilyfont { zhyahei } [ BoldFont = msyhbd.ttf ] { msyh.ttf } } \ctex_punct_map_family:nn { \CJKsfdefault } { zhyahei } \ctex_punct_map_bfseries:nn { \CJKsfdefault , zhyahei } { zhyaheib } % \setCJKmonofont { simfang.ttf } \setCJKfamilyfont { zhkai } { simkai.ttf } \setCJKfamilyfont { zhfs } { simfang.ttf } \setCJKfamilyfont { zhsong } { simsun.ttc } \setCJKfamilyfont { zhhei } { simhei.ttf } \setCJKfamilyfont { zhli } { simli.ttf } \setCJKfamilyfont { zhyou } { simyou.ttf } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } } { \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhwindowsfonts } \ctex_punct_set:n { windows } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } } { \tl_set:Nn \CJKrmdefault { rm } \tl_set:Nn \CJKsfdefault { sf } \tl_set:Nn \CJKttdefault { tt } } } { %<*windowsold> \setCJKmainfont [ BoldFont = SimHei , ItalicFont = KaiTi_GB2312 ] { SimSun } \setCJKsansfont { SimHei } \setCJKmonofont { FangSong_GB2312 } \setCJKfamilyfont { zhkai } { KaiTi_GB2312 } \setCJKfamilyfont { zhfs } { FangSong_GB2312 } % %<*windowsnew> \setCJKmainfont [ BoldFont = SimHei , ItalicFont = KaiTi ] { SimSun } \setCJKsansfont [ BoldFont = { *~Bold } ] { Microsoft~YaHei } \setCJKmonofont { FangSong } \setCJKfamilyfont { zhkai } { KaiTi } \setCJKfamilyfont { zhfs } { FangSong } % \setCJKfamilyfont { zhsong } { SimSun } \setCJKfamilyfont { zhhei } { SimHei } \setCJKfamilyfont { zhli } { LiSu } \setCJKfamilyfont { zhyou } { YouYuan } %<*windowsnew> \setCJKfamilyfont { zhyahei } [ BoldFont = { *~Bold } ] { Microsoft~YaHei } % } % % \end{macrocode} % % \subsubsection{\pkg{ctex-fontset-adobe.def}} % % \begin{macrocode} %<*adobe> % \end{macrocode} % % \tn{pdfmapline} 不支持 OpenType 字体,因而 \opt{adobe} 字体集在 pdf 模式下 % 就没有定义。\opt{fandol} 的情况类似。 % \begin{macrocode} \sys_if_engine_pdftex:TF { \sys_if_output_pdf:TF { \ctex_fontset_error:n { adobe } } { \ctex_zhmap_case:nnn { \setCJKmainfont [ cmap = UniGB-UTF16-H , BoldFont = AdobeHeitiStd-Regular.otf , ItalicFont = AdobeKaitiStd-Regular.otf ] { AdobeSongStd-Light.otf } \setCJKsansfont [ cmap = UniGB-UTF16-H ] { AdobeHeitiStd-Regular.otf } \setCJKmonofont [ cmap = UniGB-UTF16-H ] { AdobeFangsongStd-Regular.otf } \setCJKfamilyfont { zhsong } [ cmap = UniGB-UTF16-H ] { AdobeSongStd-Light.otf } \setCJKfamilyfont { zhhei } [ cmap = UniGB-UTF16-H ] { AdobeHeitiStd-Regular.otf } \setCJKfamilyfont { zhkai } [ cmap = UniGB-UTF16-H ] { AdobeKaitiStd-Regular.otf } \setCJKfamilyfont { zhfs } [ cmap = UniGB-UTF16-H ] { AdobeFangsongStd-Regular.otf } \ctex_punct_set:n { adobe } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } } { \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhadobefonts } \ctex_punct_set:n { adobe } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } } { \ctex_fontset_error:n { adobe } } } } { \setCJKmainfont [ BoldFont = AdobeHeitiStd-Regular , ItalicFont = AdobeKaitiStd-Regular ] { AdobeSongStd-Light } \setCJKsansfont { AdobeHeitiStd-Regular} \setCJKmonofont { AdobeFangsongStd-Regular} \setCJKfamilyfont { zhsong } { AdobeSongStd-Light } \setCJKfamilyfont { zhhei } { AdobeHeitiStd-Regular } \setCJKfamilyfont { zhfs } { AdobeFangsongStd-Regular } \setCJKfamilyfont { zhkai } { AdobeKaitiStd-Regular } } % \end{macrocode} % % \begin{macrocode} % %<*fandol> % \end{macrocode} % % \subsubsection{\pkg{ctex-fontset-fandol.def}} % % \begin{macrocode} \sys_if_engine_pdftex:TF { \sys_if_output_pdf:TF { \ctex_fontset_error:n { fandol } } { \ctex_zhmap_case:nnn { \setCJKmainfont [ cmap = UniGB-UTF16-H , BoldFont = FandolSong-Bold.otf , ItalicFont = FandolKai-Regular.otf ] { FandolSong-Regular.otf } \setCJKsansfont [ cmap = UniGB-UTF16-H , BoldFont = FandolHei-Bold.otf ] { FandolHei-Regular.otf } \setCJKmonofont [ cmap = UniGB-UTF16-H ] { FandolFang-Regular.otf } \setCJKfamilyfont { zhsong } [ cmap = UniGB-UTF16-H , BoldFont = FandolSong-Bold.otf ] { FandolSong-Regular.otf } \setCJKfamilyfont { zhhei } [ cmap = UniGB-UTF16-H , BoldFont = FandolHei-Bold.otf ] { FandolHei-Regular.otf } \setCJKfamilyfont { zhfs } [ cmap = UniGB-UTF16-H ] { FandolFang-Regular.otf } \setCJKfamilyfont { zhkai } [ cmap = UniGB-UTF16-H ] { FandolKai-Regular.otf } \ctex_punct_set:n { fandol } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } \ctex_punct_map_bfseries:nn { \CJKrmdefault , zhsong } { zhsongb } \ctex_punct_map_bfseries:nn { \CJKsfdefault , zhhei } { zhheib } } { \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhfandolfonts } \ctex_punct_set:n { fandol } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } } { \ctex_fontset_error:n { fandol } } } } { \setCJKmainfont [ Extension = .otf , BoldFont = FandolSong-Bold , ItalicFont = FandolKai-Regular ] { FandolSong-Regular } \setCJKsansfont [ Extension = .otf , BoldFont = FandolHei-Bold ] { FandolHei-Regular } \setCJKmonofont [ Extension = .otf ] { FandolFang-Regular } \setCJKfamilyfont { zhsong } [ Extension = .otf , BoldFont = FandolSong-Bold ] { FandolSong-Regular } \setCJKfamilyfont { zhhei } [ Extension = .otf , BoldFont = FandolHei-Bold ] { FandolHei-Regular } \setCJKfamilyfont { zhfs } [ Extension = .otf ] { FandolFang-Regular } \setCJKfamilyfont { zhkai } [ Extension = .otf ] { FandolKai-Regular } } % \end{macrocode} % % \begin{macrocode} % %<*mac> % \end{macrocode} % % \subsubsection{\pkg{ctex-fontset-mac.def}} % % OS X Mavericks (10.9) 预装的主要简体中文字体如下^^A % \footnote{\url{http://support.apple.com/kb/HT5944}}: % \begin{verbatim} % /Library/Fonts/Baoli.ttc: 报隶-简,Baoli SC:style=Regular % /Library/Fonts/Hannotate.ttc: 手札体-简,Hannotate SC:style=Bold % /Library/Fonts/Hannotate.ttc: 手札体-简,Hannotate SC:style=Regular % /Library/Fonts/Hanzipen.ttc: 翩翩体-简,HanziPen SC:style=Bold % /Library/Fonts/Hanzipen.ttc: 翩翩体-简,HanziPen SC:style=Regular % /Library/Fonts/Hei.ttf: Hei % /Library/Fonts/Hiragino Sans GB W3.otf: 冬青黑体简体中文 W3,Hiragino Sans GB W3 % /Library/Fonts/Hiragino Sans GB W6.otf: 冬青黑体简体中文 W6,Hiragino Sans GB W6 % /Library/Fonts/Kai.ttf: Kai % /Library/Fonts/Kaiti.ttc: STKaiti % /Library/Fonts/Kaiti.ttc: 楷体-简,Kaiti SC:style=Black % /Library/Fonts/Kaiti.ttc: 楷体-简,Kaiti SC:style=Bold % /Library/Fonts/Kaiti.ttc: 楷体-简,Kaiti SC:style=Regular % /Library/Fonts/Lantinghei.ttc: 兰亭黑-简,Lantinghei SC:style=Demibold % /Library/Fonts/Lantinghei.ttc: 兰亭黑-简,Lantinghei SC:style=Heavy % /Library/Fonts/Lantinghei.ttc: 兰亭黑-简,Lantinghei SC:style=Extralight % /Library/Fonts/Libian.ttc: 隶变-简,Libian SC % /Library/Fonts/Songti.ttc: STSong % /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Black % /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Bold % /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Light % /Library/Fonts/Songti.ttc: 宋体-简,Songti SC:style=Regular % /Library/Fonts/WawaSC-Regular.otf: 娃娃体-简,Wawati SC % /Library/Fonts/WeibeiSC-Bold.otf: 魏碑-简,Weibei SC % /Library/Fonts/Xingkai.ttc: 行楷-简,Xingkai SC:style=Bold % /Library/Fonts/Xingkai.ttc: 行楷-简,Xingkai SC:style=Light % /Library/Fonts/Yuanti.ttc: 圆体-简,Yuanti SC:style=Bold % /Library/Fonts/Yuanti.ttc: 圆体-简,Yuanti SC:style=Light % /Library/Fonts/Yuanti.ttc: 圆体-简,Yuanti SC:style=Regular % /Library/Fonts/YuppySC-Regular.otf: 雅痞-简,Yuppy SC % /Library/Fonts/华文仿宋.ttf: STFangsong % /Library/Fonts/华文细黑.ttf: STHeiti:style=Light % /Library/Fonts/华文黑体.ttf: STHeiti:style=Regular % /System/Library/Fonts/STHeiti Light.ttc: 黑体-简,Heiti SC:style=Light % /System/Library/Fonts/STHeiti Medium.ttc: 黑体-简,Heiti SC:style=Medium % \end{verbatim} % 在 \dvipdfmx{} 下,可以通过下述方式使用华文宋体和华文楷体: % \begin{verbatim} % \special{pdf:mapline unisong@Unicode@ unicode :4:Songti.ttc} % \special{pdf:mapline unikai@Unicode@ unicode :4:Kaiti.ttc} % \end{verbatim} % 而 \tn{pdfmapline} 似乎不支持带索引的 \texttt{ttc} 字体,\file{Songti.ttc} 默认 % 使用的是 Songti SC Black,\file{Kaiti.ttc} 默认使用的是 Kaiti SC Black。 % 华文黑体不能通过这种方式使用: % \begin{verbatim} % \special{pdf:mapline unihei@Unicode@ unicode \detokenize{华文黑体}.ttf} % \end{verbatim} % \dvipdfmx{} 不能生成 PDF,报下述错误: % \begin{verbatim} % ** WARNING ** UCS-4 TrueType cmap table... % ** ERROR ** Unable to read OpenType/TrueType Unicode cmap table. % \end{verbatim} % 如果将 CMap 改为 UniGB-UTF16-H,错误信息是 % \begin{verbatim} % ** WARNING ** No usable TrueType cmap table found for font "华文黑体.ttf". % ** WARNING ** CID character collection for this font is set to "Adobe-GB1" % ** ERROR ** Cannot continue without this... % \end{verbatim} % 在 \pdfTeX{} 下生成的 PDF 只有方框^^A % \footnote{\url{http://www.newsmth.net/bbscon.php?bid=460&id=312640}}。 % 华文细黑和华文仿宋的情况类似。 % \begin{macrocode} \sys_if_engine_pdftex:TF { \ctex_fontset_error:n { mac } } { \setCJKmainfont [ BoldFont = STHeiti , ItalicFont = STKaiti ] { STSong } \setCJKsansfont [ BoldFont = STHeiti ] { STXihei } \setCJKmonofont { STFangsong } \setCJKfamilyfont { zhsong } { STSong } \setCJKfamilyfont { zhhei } { STHeiti } \setCJKfamilyfont { zhfs } { STFangsong } \setCJKfamilyfont { zhkai } { STKaiti } } % \end{macrocode} % % \begin{macrocode} % %<*founder> % \end{macrocode} % % \subsubsection{\pkg{ctex-fontset-founder.def}} % % \begin{macrocode} \sys_if_engine_pdftex:TF { \ctex_zhmap_case:nnn { \setCJKmainfont [ BoldFont = FZXBSK.TTF , ItalicFont = FZKTK.TTF ] { FZSSK.TTF } \setCJKsansfont [ BoldFont = FZHTK.TTF ] { FZXH1K.TTF } \setCJKmonofont { FZFSK.TTF } \setCJKfamilyfont { zhsong } [ BoldFont = FZXBSK.TTF ] { FZSSK.TTF } \setCJKfamilyfont { zhhei } { FZHTK.TTF } \setCJKfamilyfont { zhkai } { FZKTK.TTF } \setCJKfamilyfont { zhfs } { FZFSK.TTF } \setCJKfamilyfont { zhli } { FZLSK.TTF } \setCJKfamilyfont { zhyou } [ BoldFont = FZY3K.TTF ] { FZY1K.TTF } \ctex_punct_set:n { founder } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_family:nn { \CJKsfdefault } { zhheil } \ctex_punct_map_family:nn { \CJKttdefault } { zhfs } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } \ctex_punct_map_bfseries:nn { \CJKrmdefault , zhsong } { zhsongb } \ctex_punct_map_bfseries:nn { \CJKsfdefault } { zhhei } \ctex_punct_map_bfseries:nn { zhyou } { zhyoub } } { \ctex_load_zhmap:nnnn { rm } { zhhei } { zhfs } { zhfounderfonts } \ctex_punct_set:n { founder } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } } { \ctex_fontset_error:n { founder } } } { \setCJKmainfont [ BoldFont = FZXiaoBiaoSong-B05 , ItalicFont = FZKai-Z03 ] { FZShuSong-Z01 } % \end{macrocode} % % 在 WPS For Linux 附带的 5.00 版和家庭版 5.20 版的“方正细黑一\_GBK”的字体名称 % 是 |FZXiHeiI-Z08|。但在网上发现不少文档和资料都是 \verb*|FZXiHei I-Z08|,而在 % 官方资料《2013 方正字库字体样张》中对应的英文名字是 \verb*|FZXiHei I|。可以用 % Postscript 名字 |FZXH1K--GBK1-0| 来统一。经测试时发现(WPS 中的字体),\XeTeX{} % 找该字体时会出现明显的延迟,而用字体文件名 |FZXH1K.TTF| 又可能会出现大小写问题, % 遂采用汉字名称。由于 \pkg{luaotfload} 不支持汉字名称,故使用 Postscript 名字, % 速度不受影响。 % \begin{macrocode} \setCJKsansfont [ BoldFont = FZHei-B01 ] { \sys_if_engine_xetex:TF { 方正细黑一_GBK } { FZXH1K--GBK1-0 } } \setCJKmonofont { FZFangSong-Z02 } \setCJKfamilyfont { zhsong } [ BoldFont = FZXiaoBiaoSong-B05 ] { FZShuSong-Z01 } \setCJKfamilyfont { zhhei } { FZHei-B01 } \setCJKfamilyfont { zhkai } { FZKai-Z03 } \setCJKfamilyfont { zhfs } { FZFangSong-Z02 } \setCJKfamilyfont { zhli } { FZLiShu-S01 } \setCJKfamilyfont { zhyou } [ BoldFont = FZZhunYuan-M02 ] { FZXiYuan-M01 } } % \end{macrocode} % % \begin{macrocode} % %<*ubuntu> % \end{macrocode} % % \subsubsection{\pkg{ctex-fontset-ubuntu.def}} % % 以下根据 Ubuntu 12.04 的中文字体情况设置。CMap 不清楚应该是什么,指定为 % UniGB-UTF16-H 还是有警告: % \begin{verbatim} % ** WARNING ** UCS-4 TrueType cmap table... % \end{verbatim} % 需要注意的是 \file{uming.ttc} 和 \file{ukai.ttc} 看起来像有四种字形的样子,但 % 其实只有“令”和“骨”这区区两个字有新字形,其余都取旧字形^^A % \footnote{\url{http://www.freedesktop.org/wiki/Software/CJKUnifonts/Download/}}。 % \begin{macrocode} \sys_if_engine_pdftex:TF { \ctex_zhmap_case:nnn { \setCJKmainfont [ BoldFont = wqy-zenhei.ttc , ItalicFont = ukai.ttc ] { uming.ttc } \setCJKsansfont { wqy-zenhei.ttc } \setCJKmonofont { uming.ttc } \setCJKfamilyfont { zhsong } { uming.ttc } \setCJKfamilyfont { zhhei } { wqy-zenhei.ttc } \setCJKfamilyfont { zhkai } { ukai.ttc } \ctex_punct_set:n { ubuntu } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_family:nn { \CJKsfdefault } { zhhei } \ctex_punct_map_family:nn { \CJKttdefault } { zhsong } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } } { \ctex_load_zhmap:nnnn { rm } { zhhei } { zhsong } { zhubuntufonts } \ctex_punct_set:n { ubuntu } \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong } \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei } \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai } } { \ctex_fontset_error:n { ubuntu } } } { \setCJKmainfont [ BoldFont = WenQuanYi~Zen~Hei , ItalicFont = AR~PL~UKai~CN ] { AR~PL~UMing~CN } \setCJKsansfont { WenQuanYi~Zen~Hei } \setCJKmonofont { AR~PL~UMing~CN } \setCJKfamilyfont { zhsong } { AR~PL~UMing~CN } \setCJKfamilyfont { zhhei } { WenQuanYi~Zen~Hei } \setCJKfamilyfont { zhkai } { AR~PL~UKai~CN } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsubsection{中文字体命令} % % \begin{macrocode} %<*!windows> % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \songti { } { \CJKfamily { zhsong } } \NewDocumentCommand \heiti { } { \CJKfamily { zhhei } } %\NewDocumentCommand \fangsong { } { \CJKfamily { zhfs } } \NewDocumentCommand \kaishu { } { \CJKfamily { zhkai } } %<*windowsnew|windowsold|founder> \NewDocumentCommand \lishu { } { \CJKfamily { zhli } } \NewDocumentCommand \youyuan { } { \CJKfamily { zhyou } } % %\NewDocumentCommand \yahei { } { \CJKfamily { zhyahei } } % \end{macrocode} % % \begin{macrocode} % % %<*zhmap> % \end{macrocode} % % \subsubsection{\pkg{zhmetrics} 的字体映射} % % 确认 \tn{catcode},没有重复载入检查。 % \begin{macrocode} \begingroup\catcode61\catcode48\catcode32=10\relax% \catcode 35=6 % # \catcode123=1 % { \catcode125=2 % } \toks0{\endlinechar=\the\endlinechar\relax}% \toks2{\endlinechar=13 }% \def\x#1 #2 {% \toks0\expandafter{\the\toks0 \catcode#1=\the\catcode#1\relax}% \toks2\expandafter{\the\toks2 \catcode#1=#2 }}% \x 13 5 % carriage return \x 32 10 % space \x 35 6 % # \x 40 12 % ( \x 41 12 % ) \x 45 12 % - \x 46 12 % . \x 47 12 % / \x 58 12 % : \x 60 12 % < \x 61 12 % = \x 64 11 % @ \x 91 12 % [ \x 93 12 % ] \x 123 1 % { \x 125 2 % } \edef\x#1{\endgroup% \edef\noexpand#1{% \the\toks0 % \let\noexpand\noexpand\noexpand#1% \noexpand\noexpand\noexpand\undefined% \noexpand\noexpand\noexpand\endinput}% \the\toks2}% \expandafter\x\csname ctex@zhmap@endinput\endcsname % \end{macrocode} % % \begin{macrocode} \begingroup\expandafter\endgroup \expandafter\let\csname ifzhmappdf\expandafter\endcsname\csname \expandafter\ifx\csname ifctexpdf\endcsname\relax \expandafter\ifx\csname pdfoutput\endcsname\relax iffalse\else\ifnum\pdfoutput < 1 iffalse\else iftrue\fi\fi \else ifctexpdf\fi \endcsname % \end{macrocode} % % 提供非 \LaTeX{} 格式下的 \tn{ProvidesFile}。 % \begin{macrocode} \begingroup \expandafter\ifx\csname ProvidesFile\endcsname\relax \long\def\x#1\ProvidesFile#2[#3]{% #1% \immediate\write-1{File: #2 #3}% \expandafter\xdef\csname ver@#2\endcsname{#3}} \expandafter\x% \fi \endgroup % \end{macrocode} % % \paragraph{\pkg{zhwindowsfonts.tex}} % % \begin{macrocode} %<*windows> \ProvidesFile{zhwindowsfonts.tex}% [2016/02/02 v2.3 Windows font map loader for pdfTeX and DVIPDFMx (CTEX)] \ifzhmappdf \pdfmapline{=gbk@UGBK@ % \end{macrocode} % % \paragraph{\pkg{zhadobefonts.tex}} % % \begin{macrocode} %<*adobe> \ProvidesFile{zhadobefonts.tex}% [2016/02/02 v2.3 Adobe font map loader for DVIPDFMx (CTEX)] \ifzhmappdf %% pdfTeX does not support OTF fonts \else \special{pdf:mapline gbk@UGBK@ UniGB-UTF16-H AdobeSongStd-Light.otf} \special{pdf:mapline gbksong@UGBK@ UniGB-UTF16-H AdobeSongStd-Light.otf} \special{pdf:mapline gbkkai@UGBK@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf} \special{pdf:mapline gbkhei@UGBK@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf} \special{pdf:mapline gbkfs@UGBK@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf} \special{pdf:mapline cyberb@Unicode@ UniGB-UTF16-H AdobeSongStd-Light.otf} \special{pdf:mapline unisong@Unicode@ UniGB-UTF16-H AdobeSongStd-Light.otf} \special{pdf:mapline unikai@Unicode@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf} \special{pdf:mapline unihei@Unicode@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf} \special{pdf:mapline unifs@Unicode@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf} \special{pdf:mapline gbksongsl@UGBK@ UniGB-UTF16-H AdobeSongStd-Light.otf -s .167} \special{pdf:mapline gbkkaisl@UGBK@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf -s .167} \special{pdf:mapline gbkheisl@UGBK@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf -s .167} \special{pdf:mapline gbkfssl@UGBK@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf -s .167} \special{pdf:mapline unisongsl@Unicode@ UniGB-UTF16-H AdobeSongStd-Light.otf -s .167} \special{pdf:mapline unikaisl@Unicode@ UniGB-UTF16-H AdobeKaitiStd-Regular.otf -s .167} \special{pdf:mapline uniheisl@Unicode@ UniGB-UTF16-H AdobeHeitiStd-Regular.otf -s .167} \special{pdf:mapline unifssl@Unicode@ UniGB-UTF16-H AdobeFangsongStd-Regular.otf -s .167} % % \end{macrocode} % % \paragraph{\pkg{zhfandolfonts.tex}} % % \begin{macrocode} %<*fandol> \ProvidesFile{zhfandolfonts.tex}% [2016/02/02 v2.3 Fandol font map loader for DVIPDFMx (CTEX)] \ifzhmappdf %% pdfTeX does not support OTF fonts \else \special{pdf:mapline gbk@UGBK@ UniGB-UTF16-H FandolSong-Regular.otf} \special{pdf:mapline gbksong@UGBK@ UniGB-UTF16-H FandolSong-Regular.otf} \special{pdf:mapline gbkkai@UGBK@ UniGB-UTF16-H FandolKai-Regular.otf} \special{pdf:mapline gbkhei@UGBK@ UniGB-UTF16-H FandolHei-Regular.otf} \special{pdf:mapline gbkfs@UGBK@ UniGB-UTF16-H FandolFang-Regular.otf} \special{pdf:mapline cyberb@Unicode@ UniGB-UTF16-H FandolSong-Regular.otf} \special{pdf:mapline unisong@Unicode@ UniGB-UTF16-H FandolSong-Regular.otf} \special{pdf:mapline unikai@Unicode@ UniGB-UTF16-H FandolKai-Regular.otf} \special{pdf:mapline unihei@Unicode@ UniGB-UTF16-H FandolHei-Regular.otf} \special{pdf:mapline unifs@Unicode@ UniGB-UTF16-H FandolFang-Regular.otf} \special{pdf:mapline gbksongsl@UGBK@ UniGB-UTF16-H FandolSong-Regular.otf -s .167} \special{pdf:mapline gbkkaisl@UGBK@ UniGB-UTF16-H FandolKai-Regular.otf -s .167} \special{pdf:mapline gbkheisl@UGBK@ UniGB-UTF16-H FandolHei-Regular.otf -s .167} \special{pdf:mapline gbkfssl@UGBK@ UniGB-UTF16-H FandolFang-Regular.otf -s .167} \special{pdf:mapline unisongsl@Unicode@ UniGB-UTF16-H FandolSong-Regular.otf -s .167} \special{pdf:mapline unikaisl@Unicode@ UniGB-UTF16-H FandolKai-Regular.otf -s .167} \special{pdf:mapline uniheisl@Unicode@ UniGB-UTF16-H FandolHei-Regular.otf -s .167} \special{pdf:mapline unifssl@Unicode@ UniGB-UTF16-H FandolFang-Regular.otf -s .167} % % \end{macrocode} % % \paragraph{\pkg{zhfounderfonts.tex}} % % \begin{macrocode} %<*founder> \ProvidesFile{zhfounderfonts.tex}% [2016/02/02 v2.3 Founder font map loader for pdfTeX and DVIPDFMx (CTEX)] \ifzhmappdf \pdfmapline{=gbk@UGBK@ % \end{macrocode} % % \paragraph{\pkg{zhubuntufonts.tex}} % % \begin{macrocode} %<*ubuntu> \ProvidesFile{zhubuntufonts.tex}% [2016/02/02 v2.3 Ubuntu font map loader for pdfTeX and DVIPDFMx (CTEX)] \ifzhmappdf \pdfmapline{=gbk@UGBK@ % \end{macrocode} % % \begin{macrocode} \fi \ctex@zhmap@endinput % % \end{macrocode} % % \subsubsection{制作 \texttt{spa} 文件} % % 我们通过 \XeTeX{} 的 \tn{XeTeXglyphbounds} 取得字体中标点符号的边界信息,为 % \pkg{CJKpunct} 宏包制作 \file{spa}。 % % \begin{macrocode} %<*spa> %<*macro> \input expl3-generic % \ExplSyntaxOn \sys_if_engine_xetex:F { \msg_new:nn { ctex } { xetex } { XeTeX~is~required~to~compile~this~document! } \msg_fatal:nn { ctex } { xetex } } % \end{macrocode} % % \pkg{CJKpunct} 定义的标点符号是: % \begin{verbatim} % ‘“「『〔([{〈《〖【 % —…、。,.:;!?%〕)]}〉》〗】’”」』 % \end{verbatim} % 注意顺序不能改变。 % \begin{macrocode} \seq_new:N \c_@@_punct_seq \seq_gset_from_clist:Nn \c_@@_punct_seq { "2018 , "201C , "300C , "300E , "3014 , "FF08 , "FF3B , "FF5B , "3008 , "300A , "3016 , "3010 , "2014 , "2026 , "3001 , "3002 , "FF0C , "FF0E , "FF1A , "FF1B , "FF01 , "FF1F , "FF05 , "3015 , "FF09 , "FF3D , "FF5D , "3009 , "300B , "3017 , "3011 , "2019 , "201D , "300D , "300F } % \end{macrocode} % % \begin{macro}[int]{\ctex_make_spa:nn} % |#1| 是 \file{spa} 文件名,|#2| 是由 CJK 族名与字体构成的逗号列表。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_make_spa:nn #1#2 { \iow_open:Nn \g_@@_spa_iow {#1} \clist_map_inline:nn {#2} { \@@_write_family:nn ##1 } \iow_close:N \g_@@_spa_iow } \iow_new:N \g_@@_spa_iow \cs_new_eq:NN \MAKESPA \ctex_make_spa:nn % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_new_protected:Npn \@@_write_family:nn #1#2 { \group_begin: \tex_font:D \l_@@_punct_font = "#2" ~ at ~ 100 pt \scan_stop: \l_@@_punct_font \clist_clear:N \l_@@_punct_bounds_clist \seq_map_inline:Nn \c_@@_punct_seq { \exp_args:No \@@_save_bounds:n { \int_use:N \xetex_charglyph:D ##1 } } \iow_now:Nx \g_@@_spa_iow { \token_to_str:N \ctexspadef {#1} % \end{macrocode} % 最后这三个逗号对 \pkg{CJKpunct} 来说是必要的。 % \begin{macrocode} { \l_@@_punct_bounds_clist , , , } } \group_end: } \cs_new_protected_nopar:Npn \@@_save_bounds:n #1 { \clist_put_right:Nx \l_@@_punct_bounds_clist { \@@_calc_bounds:nn { \c_one } {#1} , \@@_calc_bounds:nn { \c_three } {#1} } } \clist_new:N \l_@@_punct_bounds_clist % \end{macrocode} % % \pkg{CJKpunct} 要求的格式是边界空白宽度与 1\,em 的比值的一百倍。 % \begin{macrocode} \cs_new_nopar:Npn \@@_calc_bounds:nn #1#2 { \fp_eval:n { round ( \dim_to_decimal_in_unit:nn { 100 \xetex_glyphbounds:D #1 ~ #2 } { 1 em } ) } } \ExplSyntaxOff % % \end{macrocode} % % 下面是 \CTeX{} 定义的一些字体。 % \begin{macrocode} %<*make> \input ctexspamacro % \MAKESPA {ctexpunct.spa} { {adobezhsong} {AdobeSongStd-Light} , {adobezhhei} {AdobeHeitiStd-Regular} , {adobezhkai} {AdobeKaitiStd-Regular} , {adobezhfs} {AdobeFangsongStd-Regular} , {fandolzhsong} {FandolSong} , {fandolzhsongb} {FandolSong-Bold} , {fandolzhhei} {FandolHei} , {fandolzhheib} {FandolHei-Bold} , {fandolzhkai} {FandolKai} , {fandolzhfs} {FandolFang} , {founderzhsong} {FZShuSong-Z01} , {founderzhsongb} {FZXiaoBiaoSong-B05} , {founderzhhei} {FZHei-B01} , {founderzhheil} {FZXiHeiI-Z08} , {founderzhkai} {FZKai-Z03} , {founderzhfs} {FZFangSong-Z02} , {founderzhli} {FZLiShu-S01} , {founderzhyou} {FZXiYuan-M01} , {founderzhyoub} {FZZhunYuan-M02} , {ubuntuzhsong} {AR PL UMing CN} , {ubuntuzhhei} {WenQuanYi Zen Hei} , {ubuntuzhkai} {AR PL UKai CN} , {windowszhsong} {SimSun} , {windowszhhei} {SimHei} , {windowszhkai} {KaiTi} , {windowszhfs} {FangSong} , {windowszhli} {LiSu} , {windowszhyou} {YouYuan} , {windowszhyahei} {Microsoft YaHei} , {windowszhyaheib} {Microsoft YaHei Bold} } \primitive\end % % % \end{macrocode} % % % \subsection{\pkg{ctexcap} 宏包} % % \begin{macrocode} %<*ctexcap> % \end{macrocode} % % \pkg{ctexcap} 是过时宏包。 % \begin{macrocode} \clist_new:N \l_@@_ctexcap_options_clist \clist_set:Nx \l_@@_ctexcap_options_clist { \exp_not:v { opt@ \@currname . \@currext } , heading } \msg_new:nnn { ctexcap } { deprecated } { Package~`ctexcap'~is~deprecated.\\ Please~use~package~`ctex'~with~option~`#1'~instead: \\\\ \iow_indent:n { \token_to_str:N \usepackage [#1] \{ ctex \} } \\ } \msg_warning:nnx { ctexcap } { deprecated } { \clist_use:Nn \l_@@_ctexcap_options_clist { , ~ } } % \end{macrocode} % % \pkg{ctexcap} 是默认打开 \opt{heading} 选项的 \pkg{ctex}。 % \begin{macrocode} \PassOptionsToPackage { heading = true } { ctexcap } \RequirePackageWithOptions { ctex } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % % \subsection{\pkg{ctexhook} 宏包} % % \changes{v2.2}{2015/06/26}{将文档开头和宏包末尾钩子提取到 \pkg{ctexhook} 宏包中。} % % \begin{macrocode} %<*ctexhook> % \end{macrocode} % % \begin{macro}[int]{\ctex_at_end_preamble:n,\ctex_after_end_preamble:n} % 实现 \pkg{etoolbox} 宏包的 \tn{AtEndPreamble} 和 \tn{AfterEndPreamble}。 % \begin{macrocode} \cs_new_protected:Npn \ctex_at_end_preamble:n #1 { \tl_gput_right:Nn \g_@@_end_preamble_hook_tl {#1} } \cs_new_protected:Npn \ctex_after_end_preamble:n #1 { \tl_gput_right:Nn \g_@@_after_end_preamble_hook_tl {#1} } \cs_new_protected_nopar:Npn \CTEX@document@left@hook { \group_end: \g_@@_end_preamble_hook_tl \group_begin: } \cs_new_protected_nopar:Npn \CTEX@document@right@hook { \scan_stop: \g_@@_after_end_preamble_hook_tl \tex_ignorespaces:D } \cs_set_nopar:Npx \document { \CTEX@document@left@hook \exp_not:o { \document } \CTEX@document@right@hook } \tl_new:N \g_@@_end_preamble_hook_tl \tl_new:N \g_@@_after_end_preamble_hook_tl % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_at_end_package:nn} % 与 \pkg{filehook} 的 \tn{AtEndOfPackageFile*} 类似,如果原来没有在载入宏包则 % 在宏包末尾执行语句,否则立即执行。 % \begin{macrocode} \cs_new_protected:Npn \ctex_at_end_package:nn #1#2 { \@ifpackageloaded {#1} {#2} { \ctex_gadd_hook:cn { g_@@_at_end_ #1 _hook_tl } {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_gadd_hook:Nn, \ctex_gadd_hook:cn} % 给钩子附加内容。 % \begin{macrocode} \cs_new_protected:Npn \ctex_gadd_hook:Nn #1#2 { \tl_if_exist:NF #1 { \tl_new:N #1 } \tl_gput_right:Nn #1 {#2} } \cs_generate_variant:Nn \ctex_gadd_hook:Nn { c } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_package_end_hook:n, \ctex_package_end_hook:o} % 宏包末尾钩子,只执行一次,用后清除。 % \begin{macrocode} \cs_new_protected_nopar:Npn \ctex_package_end_hook:n #1 { \cs_if_exist_use:cT { g_@@_at_end_ #1 _hook_tl } { \cs_undefine:c { g_@@_at_end_ #1 _hook_tl } } } \cs_generate_variant:Nn \ctex_package_end_hook:n { o } % \end{macrocode} % \end{macro} % % 对 \tn{@popfilename} 做补丁来实现 \cs{ctex_at_end_package:nn} 的功能。 % \begin{macrocode} \tl_put_left:Nn \@popfilename { \cs_if_eq:NNT \@currext \@pkgextension { \ctex_package_end_hook:o { \@currname } } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % % \subsection{\pkg{ctexpatch} 宏包} % % \changes{v2.2}{2015/06/23}{新增子宏包 \pkg{ctexpatch} 实现给宏打补丁功能。} % % \begin{macrocode} %<*ctexpatch> % \end{macrocode} % % \begin{macrocode} \cs_if_exist:NF \str_new:N { \RequirePackage { l3str } } % \end{macrocode} % % \begin{macro}[int]{\ctex_patch_cmd_once:NnnnTF} % 只进行第一次匹配进行替换。参数 |#2| 是宏重建时的 \tn{catcode} 设置。 % \begin{macrocode} \cs_new_protected:Npn \ctex_patch_cmd_once:NnnnTF #1#2 { \ctex_patch_boot:NNnnTF \@@_patch_cmd:Nnnnnw #1 { once } {#2} { \use_i:nn } { \use_ii:nn } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_patch_cmd_all:NnnnTF} % 替换所有匹配到的文本。 % \begin{macrocode} \cs_new_protected:Npn \ctex_patch_cmd_all:NnnnTF #1#2 { \ctex_patch_boot:NNnnTF \@@_patch_cmd:Nnnnnw #1 { all } {#2} { \use_i:nn } { \use_ii:nn } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_patch_cmd:Nnn} % 快捷方式,在补丁的时候关闭 \LaTeXiii{} 语法和设置 |@| 为字母类,补丁失败时给出警告。 % \begin{macrocode} \cs_new_protected:Npn \ctex_patch_cmd:Nnn #1 { \ctex_patch_boot:NNnnTF \@@_patch_cmd:Nnnnnw #1 { once } { \ExplSyntaxOff \char_set_catcode_letter:n { 64 } } { } { \ctex_patch_failure:N #1 } } \cs_new_protected:Npn \ctex_patch_failure:N #1 { \msg_warning:nnx { ctex } { patch-failure } { \token_to_str:N #1 } } \msg_new:nnn { ctex } { patch-failure } { Oops!~Command~`#1'~is~NOT~patchable.\\ } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_preto_cmd:NnnTF} % 在宏的原本定义前面增加钩子。 % \begin{macrocode} \cs_new_protected:Npn \ctex_preto_cmd:NnnTF #1#2 { \ctex_patch_boot:NNnnTF \@@_hookto_cmd:Nnnnw #1 { left } {#2} { \use_i:nn } { \use_ii:nn } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_appto_cmd:NnnTF} % 在宏的原本定义后面追加钩子。 % \begin{macrocode} \cs_new_protected:Npn \ctex_appto_cmd:NnnTF #1#2 { \ctex_patch_boot:NNnnTF \@@_hookto_cmd:Nnnnw #1 { right } {#2} { \use_i:nn } { \use_ii:nn } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_patch_boot:NNnnTF} % 参数记号 |#| 作为宏的参数被读入时,总是会双写,会影响随后的字符串替换。需要先 % 将它转换为普通符号。 % \begin{macrocode} \cs_new_protected:Npn \ctex_patch_boot:NNnnTF #1#2#3#4#5#6 { \tl_set:Nn \@@_patch_true:w {#5} \tl_set:Nn \@@_patch_false:w {#6} \group_begin: \char_set_catcode_other:n { 35 } \ctex_parse_name:NN #1 #2 {#3} {#4} } \tl_new:N \@@_patch_true:w \tl_new:N \@@_patch_false:w % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\ctex_parse_name:NN} % 用 \tn{DeclareRobustCommand} 定义的宏或者由 \tn{newcommand} 或 \tn{newrobustcmd} % 定义的带一个可选参数的宏第一次展开的结果都不是其实际定义,实际定义被保存在另外的 % 宏中。由这些命令定义的宏的第一次展开结果可以有下面的形式(细节可查阅 \pkg{xpatch} % 的文档): % \begin{verbatim}[numbers=left,gobble=4] % \protect␣\xaa␣␣ % \DeclareRobustCommand\xaa[1]{...} % \protect␣\xab␣␣ % \DeclareRobustCommand\xab[1][]{...} % \@protected@testopt␣\xac␣\\xac␣{} % \newcommand\xac[1][]{...} % \@testopt␣\\xad␣{} % \newrobustcmd\xad[1][]{...} % \x@protect␣\1\protect␣\1␣␣ % \DeclareRobustCommand\1[1]{...} % \x@protect␣\2\protect␣\2␣␣ % \DeclareRobustCommand\2[1][]{...} % \@protected@testopt␣\3\\3␣{} % \newcommand\3[1][]{...} % \@testopt␣\\4␣{} % \newrobustcmd\4[1][]{...} % \end{verbatim} % \pkg{ctexpatch} 的主要原理是先对宏的 \tn{meaning} 作字符串替换,然后再用 % \tn{scantokens} 来重建它。我们希望对宏的实际定义打补丁,为此需要先得到 % 对应的名字。\pkg{letltxmacro}、\pkg{show2e} 和 \pkg{xpatch} 宏包中都有 % 类似的工作。 % \begin{macrocode} \cs_new_protected:Npn \ctex_parse_name:NN #1#2 { \ctex_parse_name:NNx #1#2 { \cs_to_str:N #2 } } \group_begin: \cs_set_protected:Npn \@@_tmp:w #1#2#3 { \cs_new_protected:Npn \ctex_parse_name:NNn ##1##2##3 { \bool_if:nTF { \cs_if_exist_p:c { ##3 ~ } || \cs_if_exist_p:c { #1##3 } } { \group_begin: \use:x { \group_end: \@@_parse_name:nNNNnN { \token_get_replacement_spec:N ##2 } \exp_not:N ##2 \exp_not:c { ##3 ~ } \exp_not:c { #1##3 } } {##3} ##1 } { ##1##2 } } \cs_new_protected:Npn \@@_parse_name:nNNNnN ##1##2##3##4##5##6 { \exp_args:Nc ##6 { \str_case:nnTF {##1} { { \protect ##3 } { } { \x@protect ##2 \protect ##3 } { } } { \str_if_eq_x:nnTF { \exp_not:n { #1@protected@ ##3 #1##3 } } { \exp_last_unbraced:Nf \@@_parse_name:w \token_get_replacement_spec:N ##3 #2 ~ #1 \q_stop } { #1##5 ~ } { ##5 ~ } } { \str_case:onTF { \@@_parse_name:w ##1 #2 ~ #1 \q_stop } { { #1@protected@ ##2 ##4 } { } { #1@ ##4 } { } } { #1##5 } {##5} } } } \cs_new:Npn \@@_parse_name:w ##1 #2 ~ ##2 #1 ##3 \q_stop { ##1##2 } } \use:x { \@@_tmp:w { \c_backslash_str } { \c_left_brace_str } { \tl_to_str:n { testopt } } } \group_end: \cs_generate_variant:Nn \ctex_parse_name:NNn { NNx } % \end{macrocode} % \end{macro} % % \begin{variable}[int]{\l_@@_prefix_str,\l_@@_parameter_str,\l_@@_replacement_str} % 分别保存宏的 \tn{meaning} 中的前缀、参数文本和替换文本。 % \begin{macrocode} \str_new:N \l_@@_prefix_str \str_new:N \l_@@_parameter_str \str_new:N \l_@@_replacement_str % \end{macrocode} % \end{variable} % % \begin{macro}[int]{\ctex_get_macro_meaning:NTF} % \begin{macro}[aux]{\@@_get_macro_meaning:w} % 解构待补丁宏的 \tn{meaning}。若命令不是宏,则走向 |false| 分支。 % \begin{macrocode} \group_begin: \cs_set_protected:Npn \@@_tmp:w #1 { \prg_new_protected_conditional:Npnn \ctex_get_macro_meaning:N ##1 { TF } { \exp_after:wN \@@_get_macro_meaning:w \token_to_meaning:N ##1 \q_mark #1 -> \q_no_value \q_mark \q_stop } \cs_new_protected:Npn \@@_get_macro_meaning:w ##1 #1 ##2 -> ##3 \q_mark ##4 \q_stop { \tl_set:Nn \l_@@_replacement_tl {##3} \quark_if_no_value:NTF \l_@@_replacement_tl { \prg_return_false: } { \str_set:Nn \l_@@_prefix_str {##1} \str_set:Nn \l_@@_parameter_str {##2} \str_set:Nn \l_@@_replacement_str {##3} \prg_return_true: } } } \exp_args:No \@@_tmp:w { \tl_to_str:n { macro: } } \group_end: % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\ctex_if_rescanable:NnTF} % 检查宏是否可以重建。 % \begin{macrocode} \cs_new_protected:Npn \ctex_if_rescanable:NnTF #1#2#3#4 { \ctex_get_macro_meaning:NTF #1 { \@@_patch_rebuild:Nn \@@_rebuild_cmd:w {#2} \cs_if_eq:NNTF #1 \@@_rebuild_cmd:w {#3} {#4} } {#4} } \cs_new_eq:NN \@@_rebuild_cmd:w \prg_do_nothing: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_patch_rebuild:Nn} % 使用 \cs{tl_rescan:nn} 来重新记号化 \tn{meaning} 字符串。 % \begin{macrocode} \cs_new_protected:Npn \@@_patch_rebuild:Nn #1#2 { \@@_patch_rescan:NNn \l_@@_prefix_tl \l_@@_prefix_str {#2} \@@_patch_rescan:NNn \l_@@_parameter_tl \l_@@_parameter_str {#2} \@@_patch_rescan:NNn \l_@@_replacement_tl \l_@@_replacement_str {#2} \use:x { \exp_not:o { \l_@@_prefix_tl } \tex_def:D \exp_not:N #1 \exp_not:o { \l_@@_parameter_tl } { \exp_not:o { \l_@@_replacement_tl } } } } \cs_new_protected:Npn \@@_patch_rescan:NNn #1#2#3 { \str_if_empty:NTF #2 { \tl_clear:N #1 } { \tl_set_rescan:Nnx #1 {#3} {#2} } } \tl_new:N \l_@@_prefix_tl \tl_new:N \l_@@_parameter_tl \tl_new:N \l_@@_replacement_tl % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_patch_cmd:Nnnnnw} % 对宏的替换文本进行字符串替换,然后重建。 % \begin{macrocode} \cs_new_protected:Npn \@@_patch_cmd:Nnnnnw #1#2#3#4#5 { \group_end: \ctex_if_rescanable:NnTF #1 {#3} { \use:x { \@@_patch_replace:nnnTF {#2} { \tl_to_str:n {#4} } { \tl_to_str:n {#5} } } { \@@_patch_rebuild:Nn #1 {#3} \@@_patch_true:w } { \@@_patch_false:w } } { \@@_patch_false:w } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_patch_replace:nnnTF} % 替换前先检查原文本是否存在。 % \begin{macrocode} \cs_new_protected:Npn \@@_patch_replace:nnnTF #1#2#3#4 { \tl_if_in:NnTF \l_@@_replacement_str {#2} { \use:c { tl_replace_ #1 :Nnn } \l_@@_replacement_str {#2} {#3} #4 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_hookto_cmd:Nnnnw} % 在宏的前/后附加钩子。 % \begin{macrocode} \cs_new_protected:Npn \@@_hookto_cmd:Nnnnw #1#2#3#4 { \group_end: \ctex_get_macro_meaning:NTF #1 { \str_if_empty:NTF \l_@@_parameter_str { \@@_hookto_cmd_parameterless:Nnnw #1 {#2} {#4} } { \@@_hookto_cmd_parameter:Nnnnw #1 {#2} {#3} {#4} } } { \@@_patch_false:w } } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_hookto_cmd_parameterless:Nnnw} % 如果宏没有参数,可以直接进行附加操作。注意保持宏的前缀。 % \begin{macrocode} \cs_new_protected:Npn \@@_hookto_cmd_parameterless:Nnnw #1#2#3 { \str_if_empty:NF \l_@@_prefix_str { \tl_rescan:nx { } { \l_@@_prefix_str } } \tex_edef:D #1 { \use:c { @@_ #2 _hook_aux:nn } { \exp_not:o {#1} } { \exp_not:n {#3} } } \@@_patch_true:w } \cs_generate_variant:Nn \tl_rescan:nn { nx } \cs_new:Npn \@@_left_hook_aux:nn #1#2 { #2#1 } \cs_new_eq:NN \@@_right_hook_aux:nn \use:nn % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_hookto_cmd_parameter:Nnnnw} % 如果宏有参数,需要在字符串中进行附加,然后再重建。 % \begin{macrocode} \cs_new_protected:Npn \@@_hookto_cmd_parameter:Nnnnw #1#2#3#4 { \@@_patch_rebuild:Nn \@@_rebuild_cmd:w {#3} \cs_if_eq:NNTF #1 \@@_rebuild_cmd:w { \use:c { str_put_ #2 :Nn } \l_@@_replacement_str {#4} \@@_patch_rebuild:Nn #1 {#3} \@@_patch_true:w } { \@@_patch_false:w } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput